blob: 5a57b86d248b09f89183b2b78bed1675f77f9589 [file] [log] [blame]
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001package net.onrc.onos.core.drivermanager;
2
3import java.io.IOException;
4import java.util.ArrayList;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07005import java.util.Collection;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07006import java.util.Collections;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07007import java.util.HashSet;
Srikanth Vavilapallibd9b3e22014-10-02 08:57:46 -07008import java.util.Iterator;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07009import java.util.List;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -070010import java.util.Set;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070011import java.util.concurrent.ConcurrentHashMap;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -070012import java.util.concurrent.ConcurrentMap;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070013import java.util.concurrent.atomic.AtomicBoolean;
14
15import net.floodlightcontroller.core.IFloodlightProviderService.Role;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -070016import net.floodlightcontroller.core.IOF13Switch;
17import net.floodlightcontroller.core.IOFSwitch;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070018import net.floodlightcontroller.core.SwitchDriverSubHandshakeAlreadyStarted;
19import net.floodlightcontroller.core.SwitchDriverSubHandshakeCompleted;
20import net.floodlightcontroller.core.SwitchDriverSubHandshakeNotStarted;
21import net.floodlightcontroller.core.internal.OFSwitchImplBase;
Saurav Dase972b3a2014-09-26 15:41:06 -070022import net.floodlightcontroller.util.MACAddress;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -070023import net.onrc.onos.core.configmanager.INetworkConfigService;
24import net.onrc.onos.core.configmanager.INetworkConfigService.NetworkConfigState;
25import net.onrc.onos.core.configmanager.INetworkConfigService.SwitchConfigStatus;
26import net.onrc.onos.core.configmanager.NetworkConfig.LinkConfig;
Srikanth Vavilapalli68144302014-10-08 15:55:24 -070027import net.onrc.onos.core.configmanager.NetworkConfig.SwitchConfig;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -070028import net.onrc.onos.core.configmanager.NetworkConfigManager;
29import net.onrc.onos.core.configmanager.PktLinkConfig;
30import net.onrc.onos.core.configmanager.SegmentRouterConfig;
31import net.onrc.onos.core.matchaction.MatchAction;
32import net.onrc.onos.core.matchaction.MatchActionOperationEntry;
Saurav Dasbc594a42014-09-25 20:13:50 -070033import net.onrc.onos.core.matchaction.MatchActionOperations;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -070034import net.onrc.onos.core.matchaction.MatchActionOperations.Operator;
35import net.onrc.onos.core.matchaction.action.Action;
36import net.onrc.onos.core.matchaction.action.CopyTtlInAction;
37import net.onrc.onos.core.matchaction.action.CopyTtlOutAction;
38import net.onrc.onos.core.matchaction.action.DecMplsTtlAction;
39import net.onrc.onos.core.matchaction.action.DecNwTtlAction;
40import net.onrc.onos.core.matchaction.action.GroupAction;
41import net.onrc.onos.core.matchaction.action.ModifyDstMacAction;
42import net.onrc.onos.core.matchaction.action.ModifySrcMacAction;
43import net.onrc.onos.core.matchaction.action.OutputAction;
44import net.onrc.onos.core.matchaction.action.PopMplsAction;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -070045import net.onrc.onos.core.matchaction.match.Ipv4Match;
46import net.onrc.onos.core.matchaction.match.Match;
47import net.onrc.onos.core.matchaction.match.MplsMatch;
48import net.onrc.onos.core.matchaction.match.PacketMatch;
49import net.onrc.onos.core.util.Dpid;
50import net.onrc.onos.core.util.IPv4Net;
51import net.onrc.onos.core.util.PortNumber;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070052
53import org.projectfloodlight.openflow.protocol.OFAsyncGetReply;
54import org.projectfloodlight.openflow.protocol.OFBarrierRequest;
55import org.projectfloodlight.openflow.protocol.OFBucket;
56import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
57import org.projectfloodlight.openflow.protocol.OFErrorMsg;
58import org.projectfloodlight.openflow.protocol.OFFactory;
Saurav Dase972b3a2014-09-26 15:41:06 -070059import org.projectfloodlight.openflow.protocol.OFFlowMod;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070060import org.projectfloodlight.openflow.protocol.OFGroupDescStatsReply;
61import org.projectfloodlight.openflow.protocol.OFGroupFeaturesStatsReply;
62import org.projectfloodlight.openflow.protocol.OFGroupType;
63import org.projectfloodlight.openflow.protocol.OFMatchV3;
64import org.projectfloodlight.openflow.protocol.OFMessage;
65import org.projectfloodlight.openflow.protocol.OFOxmList;
66import org.projectfloodlight.openflow.protocol.OFPortDesc;
67import org.projectfloodlight.openflow.protocol.OFStatsReply;
68import org.projectfloodlight.openflow.protocol.action.OFAction;
69import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
Saurav Dase972b3a2014-09-26 15:41:06 -070070import org.projectfloodlight.openflow.protocol.match.Match.Builder;
71import org.projectfloodlight.openflow.protocol.match.MatchField;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070072import org.projectfloodlight.openflow.protocol.oxm.OFOxmEthDst;
73import org.projectfloodlight.openflow.protocol.oxm.OFOxmEthSrc;
74import org.projectfloodlight.openflow.protocol.oxm.OFOxmEthType;
75import org.projectfloodlight.openflow.protocol.oxm.OFOxmInPort;
76import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv4DstMasked;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070077import org.projectfloodlight.openflow.protocol.oxm.OFOxmMplsLabel;
78import org.projectfloodlight.openflow.protocol.oxm.OFOxmVlanVid;
79import org.projectfloodlight.openflow.types.EthType;
80import org.projectfloodlight.openflow.types.IPv4Address;
Saurav Dase972b3a2014-09-26 15:41:06 -070081import org.projectfloodlight.openflow.types.IpProtocol;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070082import org.projectfloodlight.openflow.types.MacAddress;
83import org.projectfloodlight.openflow.types.OFBufferId;
84import org.projectfloodlight.openflow.types.OFGroup;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070085import org.projectfloodlight.openflow.types.OFPort;
86import org.projectfloodlight.openflow.types.OFVlanVidMatch;
87import org.projectfloodlight.openflow.types.TableId;
Saurav Dase972b3a2014-09-26 15:41:06 -070088import org.projectfloodlight.openflow.types.TransportPort;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070089import org.projectfloodlight.openflow.types.U32;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070090import org.projectfloodlight.openflow.util.HexString;
91
92/**
93 * OFDescriptionStatistics Vendor (Manufacturer Desc.): Stanford University,
94 * Ericsson Research and CPqD Research. Make (Hardware Desc.) : OpenFlow 1.3
95 * Reference Userspace Switch Model (Datapath Desc.) : None Software : Serial :
96 * None
97 */
Saurav Dasfc5e3eb2014-09-25 19:05:21 -070098public class OFSwitchImplCPqD13 extends OFSwitchImplBase implements IOF13Switch {
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070099 private AtomicBoolean driverHandshakeComplete;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700100 private AtomicBoolean haltStateMachine;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700101 private OFFactory factory;
102 private static final int OFPCML_NO_BUFFER = 0xffff;
103 // Configuration of asynch messages to controller. We need different
104 // asynch messages depending on role-equal or role-master.
105 // We don't want to get anything if we are slave.
106 private static final long SET_FLOW_REMOVED_MASK_MASTER = 0xf;
107 private static final long SET_PACKET_IN_MASK_MASTER = 0x7;
108 private static final long SET_PORT_STATUS_MASK_MASTER = 0x7;
109 private static final long SET_FLOW_REMOVED_MASK_EQUAL = 0x0;
110 private static final long SET_PACKET_IN_MASK_EQUAL = 0x0;
111 private static final long SET_PORT_STATUS_MASK_EQUAL = 0x7;
112 private static final long SET_ALL_SLAVE = 0x0;
113
114 private static final long TEST_FLOW_REMOVED_MASK = 0xf;
115 private static final long TEST_PACKET_IN_MASK = 0x7;
116 private static final long TEST_PORT_STATUS_MASK = 0x7;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700117
118 private static final int TABLE_VLAN = 0;
119 private static final int TABLE_TMAC = 1;
Sangho Shin01bca862014-09-12 11:18:59 -0700120 private static final int TABLE_IPv4_UNICAST = 2;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700121 private static final int TABLE_MPLS = 3;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700122 private static final int TABLE_ACL = 5;
123
124 private static final short MAX_PRIORITY = (short) 0xffff;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700125 private static final short PRIORITY_MULTIPLIER = (short) 2046;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700126 private static final short MIN_PRIORITY = 0x0;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700127
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700128 private long barrierXidToWaitFor = -1;
129 private DriverState driverState;
Jonathan Hartcb34f382014-08-12 21:11:03 -0700130 private final boolean usePipeline13;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700131 private SegmentRouterConfig srConfig;
132 private ConcurrentMap<Dpid, Set<PortNumber>> neighbors;
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700133 private List<Integer> edgeLabels;
134 private boolean isEdgeRouter;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700135 private ConcurrentMap<NeighborSet, EcmpInfo> ecmpGroups;
Srikanth Vavilapallib95e6e02014-10-02 13:56:39 -0700136 private ConcurrentMap<PortNumber, ArrayList<NeighborSet>> portNeighborSetMap;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700137
138
Jonathan Hartcb34f382014-08-12 21:11:03 -0700139
140 public OFSwitchImplCPqD13(OFDescStatsReply desc, boolean usePipeline13) {
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700141 super();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700142 haltStateMachine = new AtomicBoolean(false);
143 driverState = DriverState.INIT;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700144 driverHandshakeComplete = new AtomicBoolean(false);
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700145 setSwitchDescription(desc);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700146 neighbors = new ConcurrentHashMap<Dpid, Set<PortNumber>>();
147 ecmpGroups = new ConcurrentHashMap<NeighborSet, EcmpInfo>();
Srikanth Vavilapallib95e6e02014-10-02 13:56:39 -0700148 portNeighborSetMap =
149 new ConcurrentHashMap<PortNumber, ArrayList<NeighborSet>>();
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700150 edgeLabels = new ArrayList<Integer>();
151 isEdgeRouter = false;
Jonathan Hartcb34f382014-08-12 21:11:03 -0700152 this.usePipeline13 = usePipeline13;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700153 }
154
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700155 // *****************************
156 // OFSwitchImplBase
157 // *****************************
158
159
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700160 /* (non-Javadoc)
161 * @see java.lang.Object#toString()
162 */
163 @Override
164 public String toString() {
165 return "OFSwitchImplCPqD13 [" + ((channel != null)
166 ? channel.getRemoteAddress() : "?")
167 + " DPID[" + ((stringId != null) ? stringId : "?") + "]]";
168 }
169
170 @Override
171 public void startDriverHandshake() throws IOException {
172 log.debug("Starting driver handshake for sw {}", getStringId());
173 if (startDriverHandshakeCalled) {
174 throw new SwitchDriverSubHandshakeAlreadyStarted();
175 }
176 startDriverHandshakeCalled = true;
Jonathan Harta213bce2014-08-11 15:44:07 -0700177 factory = getFactory();
Jonathan Hartcb34f382014-08-12 21:11:03 -0700178 if (!usePipeline13) {
179 // Send packet-in to controller if a packet misses the first table
180 populateTableMissEntry(0, true, false, false, 0);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700181 driverHandshakeComplete.set(true);
Sangho Shin01bca862014-09-12 11:18:59 -0700182 } else {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700183 nextDriverState();
Sangho Shin01bca862014-09-12 11:18:59 -0700184 }
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700185 }
186
187 @Override
188 public boolean isDriverHandshakeComplete() {
Sangho Shin01bca862014-09-12 11:18:59 -0700189 if (!startDriverHandshakeCalled)
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700190 throw new SwitchDriverSubHandshakeNotStarted();
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700191 return driverHandshakeComplete.get();
192 }
193
194 @Override
195 public void processDriverHandshakeMessage(OFMessage m) {
Sangho Shin01bca862014-09-12 11:18:59 -0700196 if (!startDriverHandshakeCalled)
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700197 throw new SwitchDriverSubHandshakeNotStarted();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700198 if (isDriverHandshakeComplete())
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700199 throw new SwitchDriverSubHandshakeCompleted(m);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700200 try {
201 processOFMessage(this, m);
202 } catch (IOException e) {
203 log.error("Error generated when processing OFMessage", e.getCause());
204 }
205 }
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700206
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700207 @Override
208 public String getSwitchDriverState() {
209 return driverState.toString();
210 }
211
Srikanth Vavilapallibd9b3e22014-10-02 08:57:46 -0700212 public void removePortFromGroups(PortNumber port) {
213 ArrayList<NeighborSet> portNSSet = portNeighborSetMap.get(port);
Sangho Shin5be3e532014-10-03 17:20:58 -0700214 if (portNSSet == null)
Srikanth Vavilapalli7d873fd2014-10-04 07:50:57 -0700215 /* No Groups are created with this port yet */
Sangho Shin5be3e532014-10-03 17:20:58 -0700216 return;
Srikanth Vavilapallibd9b3e22014-10-02 08:57:46 -0700217 for (NeighborSet ns : portNSSet) {
218 /* Delete the first matched bucket */
Srikanth Vavilapalli7d873fd2014-10-04 07:50:57 -0700219 EcmpInfo portEcmpInfo = ecmpGroups.get(ns);
220 Iterator<BucketInfo> it = portEcmpInfo.buckets.iterator();
Srikanth Vavilapallibd9b3e22014-10-02 08:57:46 -0700221 while (it.hasNext()) {
222 BucketInfo bucket = it.next();
223 if (bucket.outport.equals(port)) {
224 it.remove();
225 /* Assuming port appears under only one bucket for
Srikanth Vavilapalli7d873fd2014-10-04 07:50:57 -0700226 * a neighbor set and hence invoking Group modify command
Srikanth Vavilapallibd9b3e22014-10-02 08:57:46 -0700227 */
Srikanth Vavilapalli7d873fd2014-10-04 07:50:57 -0700228 modifyEcmpGroup(portEcmpInfo);
Srikanth Vavilapallibd9b3e22014-10-02 08:57:46 -0700229 break;
230 }
231 }
232 }
233 /* Delete entry from portNeighborSetMap */
234 portNeighborSetMap.remove(port);
Srikanth Vavilapalli7d873fd2014-10-04 07:50:57 -0700235 return;
Srikanth Vavilapallibd9b3e22014-10-02 08:57:46 -0700236 }
237
238 public void addPortToGroups(PortNumber port) {
239 ArrayList<NeighborSet> portNSSet = portNeighborSetMap.get(port);
240 if (portNSSet != null) {
241 /* Port is already part of ECMP groups */
242 return;
243 }
Srikanth Vavilapalli7d873fd2014-10-04 07:50:57 -0700244 /* TODO:
245 * 1) Find the neighbors reached from this port
246 * 2) Compute the Neighbor sets
247 * 3) For the Neighbor set entries that are already there
248 * in the database,
249 * a) Update the ecmpGroups hashmap
250 * b) perform Group Modify on updated groups
251 * 4) For the new Neighbor set entries, add an entry in the database
252 * a) Add entry to the ecmpGroups hashmap
253 * b) perform Group Add on those groups
254 * 5) Update the portNeighborSetMap hashmap
255 * */
Srikanth Vavilapallibd9b3e22014-10-02 08:57:46 -0700256 return;
257 }
258
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700259 // *****************************
260 // Driver handshake state-machine
261 // *****************************
262
263 enum DriverState {
264 INIT,
265 SET_TABLE_MISS_ENTRIES,
266 SET_TABLE_VLAN_TMAC,
267 SET_GROUPS,
268 VERIFY_GROUPS,
269 SET_ADJACENCY_LABELS,
270 EXIT
271 }
272
273 protected void nextDriverState() throws IOException {
274 DriverState currentState = driverState;
Saurav Das80d17392014-10-01 10:24:56 -0700275 if (haltStateMachine.get()) {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700276 return;
Saurav Das80d17392014-10-01 10:24:56 -0700277 }
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700278 switch (currentState) {
279 case INIT:
280 driverState = DriverState.SET_TABLE_MISS_ENTRIES;
281 setTableMissEntries();
Saurav Dasd84178f2014-09-29 17:48:54 -0700282 sendHandshakeBarrier();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700283 break;
284 case SET_TABLE_MISS_ENTRIES:
285 driverState = DriverState.SET_TABLE_VLAN_TMAC;
286 getNetworkConfig();
287 populateTableVlan();
288 populateTableTMac();
Saurav Dasd84178f2014-09-29 17:48:54 -0700289 sendHandshakeBarrier();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700290 break;
291 case SET_TABLE_VLAN_TMAC:
292 driverState = DriverState.SET_GROUPS;
293 createGroups();
Saurav Dasd84178f2014-09-29 17:48:54 -0700294 sendHandshakeBarrier();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700295 break;
296 case SET_GROUPS:
297 driverState = DriverState.VERIFY_GROUPS;
298 verifyGroups();
299 break;
300 case VERIFY_GROUPS:
301 driverState = DriverState.SET_ADJACENCY_LABELS;
302 assignAdjacencyLabels();
303 break;
304 case SET_ADJACENCY_LABELS:
305 driverState = DriverState.EXIT;
306 driverHandshakeComplete.set(true);
307 break;
308 case EXIT:
309 default:
310 driverState = DriverState.EXIT;
311 log.error("Driver handshake has exited for sw: {}", getStringId());
312 }
313 }
314
315 void processOFMessage(IOFSwitch sw, OFMessage m) throws IOException {
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700316 switch (m.getType()) {
317 case BARRIER_REPLY:
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700318 processBarrierReply(m);
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700319 break;
320
321 case ERROR:
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700322 processErrorMessage(m);
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700323 break;
324
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700325 case GET_ASYNC_REPLY:
326 OFAsyncGetReply asrep = (OFAsyncGetReply) m;
327 decodeAsyncGetReply(asrep);
328 break;
329
330 case PACKET_IN:
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700331 // not ready to handle packet-ins
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700332 break;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700333
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700334 case QUEUE_GET_CONFIG_REPLY:
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700335 // not doing queue config yet
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700336 break;
337
338 case STATS_REPLY:
339 processStatsReply((OFStatsReply) m);
340 break;
341
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700342 case ROLE_REPLY: // channelHandler should handle this
343 case PORT_STATUS: // channelHandler should handle this
344 case FEATURES_REPLY: // don't care
345 case FLOW_REMOVED: // don't care
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700346 default:
347 log.debug("Received message {} during switch-driver subhandshake "
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700348 + "from switch {} ... Ignoring message", m, sw.getStringId());
349 }
350 }
351
352 private void processStatsReply(OFStatsReply sr) {
353 switch (sr.getStatsType()) {
354 case AGGREGATE:
355 break;
356 case DESC:
357 break;
358 case EXPERIMENTER:
359 break;
360 case FLOW:
361 break;
362 case GROUP_DESC:
363 processGroupDesc((OFGroupDescStatsReply) sr);
364 break;
365 case GROUP_FEATURES:
366 processGroupFeatures((OFGroupFeaturesStatsReply) sr);
367 break;
368 case METER_CONFIG:
369 break;
370 case METER_FEATURES:
371 break;
372 case PORT_DESC:
373 break;
374 case TABLE_FEATURES:
375 break;
376 default:
377 break;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700378
379 }
380 }
381
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700382 private void processErrorMessage(OFMessage m) {
383 log.error("Switch {} Error {} in DriverState", getStringId(),
384 (OFErrorMsg) m, driverState);
385 }
386
387 private void processBarrierReply(OFMessage m) throws IOException {
388 if (m.getXid() == barrierXidToWaitFor) {
389 // Driver state-machine progresses to the next state.
390 // If Barrier messages is not received, then eventually
391 // the ChannelHandler state machine will timeout, and the switch
392 // will be disconnected.
393 nextDriverState();
394 } else {
395 log.error("Received incorrect barrier-message xid {} (expected: {}) in "
396 + "switch-driver state {} for switch {}", m, barrierXidToWaitFor,
397 driverState, getStringId());
398 }
399 }
400
401 private void processGroupDesc(OFGroupDescStatsReply gdsr) {
402 log.info("Sw: {} Group Desc {}", getStringId(), gdsr);
403 try {
404 nextDriverState();
405 } catch (IOException e) {
406 // TODO Auto-generated catch block
407 e.printStackTrace();
408 }
409 }
410
411 // *****************************
412 // Utility methods
413 // *****************************
414
415 void setTableMissEntries() throws IOException {
416 // set all table-miss-entries
417 populateTableMissEntry(TABLE_VLAN, true, false, false, -1);
418 populateTableMissEntry(TABLE_TMAC, true, false, false, -1);
419 populateTableMissEntry(TABLE_IPv4_UNICAST, false, true, true,
420 TABLE_ACL);
421 populateTableMissEntry(TABLE_MPLS, false, true, true,
422 TABLE_ACL);
423 populateTableMissEntry(TABLE_ACL, false, false, false, -1);
424 }
425
Saurav Dasd84178f2014-09-29 17:48:54 -0700426 private void sendHandshakeBarrier() throws IOException {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700427 long xid = getNextTransactionId();
428 barrierXidToWaitFor = xid;
429 OFBarrierRequest br = getFactory()
430 .buildBarrierRequest()
431 .setXid(xid)
432 .build();
433 write(br, null);
434 }
435
436 /**
437 * Adds a table-miss-entry to a pipeline table.
438 * <p>
439 * The table-miss-entry can be added with 'write-actions' or
440 * 'apply-actions'. It can also add a 'goto-table' instruction. By default
441 * if none of the booleans in the call are set, then the table-miss entry is
442 * added with no instructions, which means that if a packet hits the
443 * table-miss-entry, pipeline execution will stop, and the action set
444 * associated with the packet will be executed.
445 *
446 * @param tableToAdd the table to where the table-miss-entry will be added
447 * @param toControllerNow as an APPLY_ACTION instruction
448 * @param toControllerWrite as a WRITE_ACTION instruction
449 * @param toTable as a GOTO_TABLE instruction
450 * @param tableToSend the table to send as per the GOTO_TABLE instruction it
451 * needs to be set if 'toTable' is true. Ignored of 'toTable' is
452 * false.
453 * @throws IOException
454 */
455 @SuppressWarnings("unchecked")
456 private void populateTableMissEntry(int tableToAdd, boolean toControllerNow,
457 boolean toControllerWrite,
458 boolean toTable, int tableToSend) throws IOException {
459 OFOxmList oxmList = OFOxmList.EMPTY;
460 OFMatchV3 match = factory.buildMatchV3()
461 .setOxmList(oxmList)
462 .build();
463 OFAction outc = factory.actions()
464 .buildOutput()
465 .setPort(OFPort.CONTROLLER)
466 .setMaxLen(OFPCML_NO_BUFFER)
467 .build();
468 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
469 if (toControllerNow) {
470 // table-miss instruction to send to controller immediately
471 OFInstruction instr = factory.instructions()
472 .buildApplyActions()
473 .setActions(Collections.singletonList(outc))
474 .build();
475 instructions.add(instr);
476 }
477
478 if (toControllerWrite) {
479 // table-miss instruction to write-action to send to controller
480 // this will be executed whenever the action-set gets executed
481 OFInstruction instr = factory.instructions()
482 .buildWriteActions()
483 .setActions(Collections.singletonList(outc))
484 .build();
485 instructions.add(instr);
486 }
487
488 if (toTable) {
489 // table-miss instruction to goto-table x
490 OFInstruction instr = factory.instructions()
491 .gotoTable(TableId.of(tableToSend));
492 instructions.add(instr);
493 }
494
495 if (!toControllerNow && !toControllerWrite && !toTable) {
496 // table-miss has no instruction - at which point action-set will be
497 // executed - if there is an action to output/group in the action
498 // set
499 // the packet will be sent there, otherwise it will be dropped.
500 instructions = (List<OFInstruction>) Collections.EMPTY_LIST;
501 }
502
503 OFMessage tableMissEntry = factory.buildFlowAdd()
504 .setTableId(TableId.of(tableToAdd))
505 .setMatch(match) // match everything
506 .setInstructions(instructions)
507 .setPriority(MIN_PRIORITY)
508 .setBufferId(OFBufferId.NO_BUFFER)
509 .setIdleTimeout(0)
510 .setHardTimeout(0)
511 .setXid(getNextTransactionId())
512 .build();
513 write(tableMissEntry, null);
514 }
515
516 private void getNetworkConfig() {
517 INetworkConfigService ncs = floodlightProvider.getNetworkConfigService();
518 SwitchConfigStatus scs = ncs.checkSwitchConfig(new Dpid(getId()));
519 if (scs.getConfigState() == NetworkConfigState.ACCEPT_ADD) {
520 srConfig = (SegmentRouterConfig) scs.getSwitchConfig();
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700521 isEdgeRouter = srConfig.isEdgeRouter();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700522 } else {
523 log.error("Switch not configured as Segment-Router");
524 }
525
526 List<LinkConfig> linkConfigList = ncs.getConfiguredAllowedLinks();
527 setNeighbors(linkConfigList);
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700528
529 if (isEdgeRouter) {
530 List<SwitchConfig> switchList = ncs.getConfiguredAllowedSwitches();
531 getAllEdgeLabels(switchList);
532 }
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700533 }
534
535 private void populateTableVlan() throws IOException {
536 List<OFMessage> msglist = new ArrayList<OFMessage>();
537 for (OFPortDesc p : getPorts()) {
538 int pnum = p.getPortNo().getPortNumber();
539 if (U32.of(pnum).compareTo(U32.of(OFPort.MAX.getPortNumber())) < 1) {
540 OFOxmInPort oxp = factory.oxms().inPort(p.getPortNo());
541 OFOxmVlanVid oxv = factory.oxms()
542 .vlanVid(OFVlanVidMatch.UNTAGGED);
543 OFOxmList oxmList = OFOxmList.of(oxp, oxv);
544 OFMatchV3 match = factory.buildMatchV3()
545 .setOxmList(oxmList).build();
546
547 // TODO: match on vlan-tagged packets for vlans configured on
548 // subnet ports and strip-vlan
549
550 // Do not need to add vlans
551 /*int vlanid = getVlanConfig(pnum);
552 OFOxmVlanVid vidToSet = factory.oxms()
553 .vlanVid(OFVlanVidMatch.ofVlan(vlanid));
554 OFAction pushVlan = factory.actions().pushVlan(EthType.VLAN_FRAME);
555 OFAction setVlan = factory.actions().setField(vidToSet);
556 List<OFAction> actionlist = new ArrayList<OFAction>();
557 actionlist.add(pushVlan);
558 actionlist.add(setVlan);
559 OFInstruction appAction = factory.instructions().buildApplyActions()
560 .setActions(actionlist).build();*/
561
562 OFInstruction gotoTbl = factory.instructions().buildGotoTable()
563 .setTableId(TableId.of(TABLE_TMAC)).build();
564 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
565 // instructions.add(appAction);
566 instructions.add(gotoTbl);
567 OFMessage flowEntry = factory.buildFlowAdd()
568 .setTableId(TableId.of(TABLE_VLAN))
569 .setMatch(match)
570 .setInstructions(instructions)
571 .setPriority(1000) // does not matter - all rules
572 // exclusive
573 .setBufferId(OFBufferId.NO_BUFFER)
574 .setIdleTimeout(0)
575 .setHardTimeout(0)
576 .setXid(getNextTransactionId())
577 .build();
578 msglist.add(flowEntry);
579 }
580 }
581 write(msglist);
582 log.debug("Adding {} port/vlan-rules in sw {}", msglist.size(), getStringId());
583 }
584
585 private void populateTableTMac() throws IOException {
586 // match for router-mac and ip-packets
587 OFOxmEthType oxe = factory.oxms().ethType(EthType.IPv4);
588 OFOxmEthDst dmac = factory.oxms().ethDst(getRouterMacAddr());
589 OFOxmList oxmListIp = OFOxmList.of(dmac, oxe);
590 OFMatchV3 matchIp = factory.buildMatchV3()
591 .setOxmList(oxmListIp).build();
592 OFInstruction gotoTblIp = factory.instructions().buildGotoTable()
593 .setTableId(TableId.of(TABLE_IPv4_UNICAST)).build();
594 List<OFInstruction> instructionsIp = Collections.singletonList(gotoTblIp);
595 OFMessage ipEntry = factory.buildFlowAdd()
596 .setTableId(TableId.of(TABLE_TMAC))
597 .setMatch(matchIp)
598 .setInstructions(instructionsIp)
599 .setPriority(1000) // strict priority required lower than
600 // multicastMac
601 .setBufferId(OFBufferId.NO_BUFFER)
602 .setIdleTimeout(0)
603 .setHardTimeout(0)
604 .setXid(getNextTransactionId())
605 .build();
606
607 // match for router-mac and mpls packets
608 OFOxmEthType oxmpls = factory.oxms().ethType(EthType.MPLS_UNICAST);
609 OFOxmList oxmListMpls = OFOxmList.of(dmac, oxmpls);
610 OFMatchV3 matchMpls = factory.buildMatchV3()
611 .setOxmList(oxmListMpls).build();
612 OFInstruction gotoTblMpls = factory.instructions().buildGotoTable()
613 .setTableId(TableId.of(TABLE_MPLS)).build();
614 List<OFInstruction> instructionsMpls = Collections.singletonList(gotoTblMpls);
615 OFMessage mplsEntry = factory.buildFlowAdd()
616 .setTableId(TableId.of(TABLE_TMAC))
617 .setMatch(matchMpls)
618 .setInstructions(instructionsMpls)
619 .setPriority(1001) // strict priority required lower than
620 // multicastMac
621 .setBufferId(OFBufferId.NO_BUFFER)
622 .setIdleTimeout(0)
623 .setHardTimeout(0)
624 .setXid(getNextTransactionId())
625 .build();
626
627 log.debug("Adding termination-mac-rules in sw {}", getStringId());
628 List<OFMessage> msglist = new ArrayList<OFMessage>(2);
629 msglist.add(ipEntry);
630 msglist.add(mplsEntry);
631 write(msglist);
632 }
633
634 private MacAddress getRouterMacAddr() {
635 if (srConfig != null) {
636 return MacAddress.of(srConfig.getRouterMac());
637 } else {
638 // return a dummy mac address - it will not be used
639 return MacAddress.of("00:00:00:00:00:00");
640 }
641 }
642
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700643 private boolean isEdgeRouter(Dpid ndpid) {
644 INetworkConfigService ncs = floodlightProvider.getNetworkConfigService();
645 SwitchConfigStatus scs = ncs.checkSwitchConfig(ndpid);
646 if (scs.getConfigState() == NetworkConfigState.ACCEPT_ADD) {
647 return ((SegmentRouterConfig) scs.getSwitchConfig()).isEdgeRouter();
648 } else {
649 // TODO: return false if router not allowed
650 return false;
651 }
652 }
653
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700654 private MacAddress getNeighborRouterMacAddress(Dpid ndpid) {
655 INetworkConfigService ncs = floodlightProvider.getNetworkConfigService();
656 SwitchConfigStatus scs = ncs.checkSwitchConfig(ndpid);
657 if (scs.getConfigState() == NetworkConfigState.ACCEPT_ADD) {
658 return MacAddress.of(((SegmentRouterConfig) scs.getSwitchConfig())
659 .getRouterMac());
660 } else {
661 // return a dummy mac address - it will not be used
662 return MacAddress.of("00:00:00:00:00:00");
663 }
664 }
665
666 private void setNeighbors(List<LinkConfig> linkConfigList) {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700667 for (LinkConfig lg : linkConfigList) {
668 if (!lg.getType().equals(NetworkConfigManager.PKT_LINK)) {
Saurav Das80d17392014-10-01 10:24:56 -0700669 continue;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700670 }
671 PktLinkConfig plg = (PktLinkConfig) lg;
672 if (plg.getDpid1() == getId()) {
673 addNeighborAtPort(new Dpid(plg.getDpid2()),
674 PortNumber.uint32(plg.getPort1()));
675 } else if (plg.getDpid2() == getId()) {
676 addNeighborAtPort(new Dpid(plg.getDpid1()),
677 PortNumber.uint32(plg.getPort2()));
678 }
679 }
680 }
681
682 private void addNeighborAtPort(Dpid neighborDpid, PortNumber portToNeighbor) {
683 if (neighbors.get(neighborDpid) != null) {
684 neighbors.get(neighborDpid).add(portToNeighbor);
685 } else {
686 Set<PortNumber> ports = new HashSet<PortNumber>();
687 ports.add(portToNeighbor);
688 neighbors.put(neighborDpid, ports);
689 }
690 }
691
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700692 private void getAllEdgeLabels(List<SwitchConfig> switchList) {
693 for (SwitchConfig sc : switchList) {
694 /* TODO: Do we need to check if the SwitchConfig is of
695 * type SegmentRouter?
696 */
697 if ((sc.getDpid() == getId()) ||
698 (((SegmentRouterConfig) sc).isEdgeRouter() != true)) {
699 continue;
700 }
701 edgeLabels.add(((SegmentRouterConfig) sc).getNodeSid());
702 }
703 }
704
705 private Set<Set<Dpid>> getAllNeighborSets(Set<Dpid> neighbors) {
706 List<Dpid> list = new ArrayList<Dpid>(neighbors);
707 Set<Set<Dpid>> sets = new HashSet<Set<Dpid>>();
708 /* get the number of elements in the neighbors */
709 int elements = list.size();
710 /* the number of members of a power set is 2^n
711 * including the empty set
712 */
713 int powerElements = (1 << elements);
714
715 /* run a binary counter for the number of power elements */
716 for (long i = 1; i < powerElements; i++) {
717 Set<Dpid> dpidSubSet = new HashSet<Dpid>();
718 boolean allEdgeRouters = true;
719 for (int j = 0; j < elements; j++) {
720 if ((i >> j) % 2 == 1) {
721 dpidSubSet.add(list.get(j));
722 if (!isEdgeRouter(list.get(j)))
723 allEdgeRouters = false;
724 }
725 }
726 if (!allEdgeRouters)
727 sets.add(dpidSubSet);
728 }
729 return sets;
730 }
731
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700732 /**
733 * createGroups creates ECMP groups for all ports on this router connected
734 * to other routers (in the OF network). The information for ports is
735 * gleaned from the configured links. If no links are configured no groups
736 * will be created, and it is up to the caller of the IOF13Switch API to
737 * create groups.
738 * <p>
739 * By default all ports connected to the same neighbor router will be part
740 * of the same ECMP group. In addition, groups will be created for all
741 * possible combinations of neighbor routers.
742 * <p>
743 * For example, consider this router (R0) connected to 3 neighbors (R1, R2,
744 * and R3). The following groups will be created in R0:
745 * <li>1) all ports to R1,
746 * <li>2) all ports to R2,
747 * <li>3) all ports to R3,
748 * <li>4) all ports to R1 and R2
749 * <li>5) all ports to R1 and R3
750 * <li>6) all ports to R2 and R3
751 * <li>7) all ports to R1, R2, and R3
752 */
753 private void createGroups() {
754 Set<Dpid> dpids = neighbors.keySet();
755 if (dpids == null || dpids.isEmpty()) {
756 return;
757 }
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700758 /* Create all possible Neighbor sets from this router
759 * NOTE: Avoid any pairings of edge routers only
760 */
761 Set<Set<Dpid>> powerSet = getAllNeighborSets(dpids);
762 Set<NeighborSet> nsSet = new HashSet<NeighborSet>();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700763 for (Set<Dpid> combo : powerSet) {
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700764 if (isEdgeRouter && !edgeLabels.isEmpty()) {
765 for (Integer edgeLabel : edgeLabels) {
766 NeighborSet ns = new NeighborSet();
767 ns.addDpids(combo);
768 ns.setEdgeLabel(edgeLabel);
769 nsSet.add(ns);
770 }
771 } else {
772 NeighborSet ns = new NeighborSet();
773 ns.addDpids(combo);
774 nsSet.add(ns);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700775 }
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700776 }
777
778 int groupid = 1;
779 for (NeighborSet ns : nsSet) {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700780 List<BucketInfo> buckets = new ArrayList<BucketInfo>();
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700781 for (Dpid d : ns.getDpids()) {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700782 for (PortNumber sp : neighbors.get(d)) {
783 BucketInfo b = new BucketInfo(d,
784 MacAddress.of(srConfig.getRouterMac()),
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700785 getNeighborRouterMacAddress(d), sp,
786 ns.getEdgeLabel());
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700787 buckets.add(b);
Srikanth Vavilapallibd9b3e22014-10-02 08:57:46 -0700788
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700789 /* Update Port Neighborset map */
Srikanth Vavilapallibd9b3e22014-10-02 08:57:46 -0700790 ArrayList<NeighborSet> portNeighborSets =
791 portNeighborSetMap.get(sp);
792 if (portNeighborSets == null) {
793 portNeighborSets = new ArrayList<NeighborSet>();
794 portNeighborSets.add(ns);
795 portNeighborSetMap.put(sp, portNeighborSets);
796 }
797 else
798 portNeighborSets.add(ns);
799 }
800 }
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700801 EcmpInfo ecmpInfo = new EcmpInfo(groupid++, buckets);
802 setEcmpGroup(ecmpInfo);
803 ecmpGroups.put(ns, ecmpInfo);
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700804 log.debug("Creating ecmp group in sw {} for neighbor set {}: {}",
805 getStringId(), ns, ecmpInfo);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700806 }
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700807
808 // temp map of ecmp groupings
809 /* Map<NeighborSet, List<BucketInfo>> temp =
810 new HashMap<NeighborSet, List<BucketInfo>>();
811 */
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700812 }
813
814 private class EcmpInfo {
815 int groupId;
816 List<BucketInfo> buckets;
817
818 EcmpInfo(int gid, List<BucketInfo> bucketInfos) {
819 groupId = gid;
820 buckets = bucketInfos;
821 }
822
823 @Override
824 public String toString() {
825 return "groupId: " + groupId + ", buckets: " + buckets;
826 }
827 }
828
829 private class BucketInfo {
830 Dpid neighborDpid;
831 MacAddress srcMac;
832 MacAddress dstMac;
833 PortNumber outport;
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700834 int mplsLabel;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700835
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700836 BucketInfo(Dpid nDpid, MacAddress smac, MacAddress dmac,
837 PortNumber p, int label) {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700838 neighborDpid = nDpid;
839 srcMac = smac;
840 dstMac = dmac;
841 outport = p;
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700842 mplsLabel = label;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700843 }
844
845 @Override
846 public String toString() {
847 return " {neighborDpid: " + neighborDpid + ", dstMac: " + dstMac +
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700848 ", srcMac: " + srcMac + ", outport: " + outport +
849 "mplsLabel: " + mplsLabel + "}";
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700850 }
851 }
852
853 private void setEcmpGroup(EcmpInfo ecmpInfo) {
854 List<OFMessage> msglist = new ArrayList<OFMessage>();
855 OFGroup group = OFGroup.of(ecmpInfo.groupId);
856
857 List<OFBucket> buckets = new ArrayList<OFBucket>();
858 for (BucketInfo b : ecmpInfo.buckets) {
859 OFOxmEthDst dmac = factory.oxms()
860 .ethDst(b.dstMac);
861 OFAction setDA = factory.actions().buildSetField()
862 .setField(dmac).build();
Saurav Das0a344b02014-09-26 14:18:52 -0700863 OFOxmEthSrc smac = factory.oxms()
864 .ethSrc(b.srcMac);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700865 OFAction setSA = factory.actions().buildSetField()
866 .setField(smac).build();
867 OFAction outp = factory.actions().buildOutput()
868 .setPort(OFPort.of(b.outport.shortValue()))
869 .build();
870 List<OFAction> actions = new ArrayList<OFAction>();
871 actions.add(setSA);
872 actions.add(setDA);
873 actions.add(outp);
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700874 if (b.mplsLabel != -1) {
875 OFAction pushLabel = factory.actions().buildPushMpls()
876 .setEthertype(EthType.MPLS_UNICAST).build();
Sangho Shin62ce5c12014-10-08 16:24:40 -0700877 OFOxmMplsLabel lid = factory.oxms()
878 .mplsLabel(U32.of(b.mplsLabel));
879 OFAction setLabel = factory.actions().buildSetField()
880 .setField(lid).build();
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700881 OFAction copyTtl = factory.actions().copyTtlOut();
882 OFAction decrTtl = factory.actions().decMplsTtl();
883 actions.add(pushLabel);
884 actions.add(setLabel);
885 actions.add(copyTtl);
886 actions.add(decrTtl);
887 }
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700888 OFBucket ofb = factory.buildBucket()
889 .setWeight(1)
890 .setActions(actions)
891 .build();
892 buckets.add(ofb);
893 }
894
895 OFMessage gm = factory.buildGroupAdd()
896 .setGroup(group)
897 .setBuckets(buckets)
898 .setGroupType(OFGroupType.SELECT)
899 .setXid(getNextTransactionId())
900 .build();
901 msglist.add(gm);
902 try {
903 write(msglist);
904 } catch (IOException e) {
905 // TODO Auto-generated catch block
906 e.printStackTrace();
907 }
908 }
909
Srikanth Vavilapalli7d873fd2014-10-04 07:50:57 -0700910 private void modifyEcmpGroup(EcmpInfo ecmpInfo) {
911 List<OFMessage> msglist = new ArrayList<OFMessage>();
912 OFGroup group = OFGroup.of(ecmpInfo.groupId);
913
914 List<OFBucket> buckets = new ArrayList<OFBucket>();
915 for (BucketInfo b : ecmpInfo.buckets) {
916 OFOxmEthDst dmac = factory.oxms()
917 .ethDst(b.dstMac);
918 OFAction setDA = factory.actions().buildSetField()
919 .setField(dmac).build();
920 OFOxmEthSrc smac = factory.oxms()
921 .ethSrc(b.srcMac);
922 OFAction setSA = factory.actions().buildSetField()
923 .setField(smac).build();
924 OFAction outp = factory.actions().buildOutput()
925 .setPort(OFPort.of(b.outport.shortValue()))
926 .build();
927 List<OFAction> actions = new ArrayList<OFAction>();
928 actions.add(setSA);
929 actions.add(setDA);
930 actions.add(outp);
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700931 if (b.mplsLabel != -1) {
932 OFAction pushLabel = factory.actions().buildPushMpls()
933 .setEthertype(EthType.MPLS_UNICAST).build();
934 OFAction setLabel = factory.actions().buildSetMplsLabel()
935 .setMplsLabel(b.mplsLabel).build();
936 OFAction copyTtl = factory.actions().copyTtlOut();
937 OFAction decrTtl = factory.actions().decMplsTtl();
938 actions.add(pushLabel);
939 actions.add(setLabel);
940 actions.add(copyTtl);
941 actions.add(decrTtl);
942 }
Srikanth Vavilapalli7d873fd2014-10-04 07:50:57 -0700943 OFBucket ofb = factory.buildBucket()
944 .setWeight(1)
945 .setActions(actions)
946 .build();
947 buckets.add(ofb);
948 }
949
950 OFMessage gm = factory.buildGroupModify()
951 .setGroup(group)
952 .setBuckets(buckets)
953 .setGroupType(OFGroupType.SELECT)
954 .setXid(getNextTransactionId())
955 .build();
956 msglist.add(gm);
957 try {
958 write(msglist);
959 } catch (IOException e) {
960 // TODO Auto-generated catch block
961 e.printStackTrace();
962 }
963 }
964
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700965 private void verifyGroups() throws IOException {
966 sendGroupDescRequest();
967 }
968
969 private void sendGroupDescRequest() throws IOException {
970 OFMessage gdr = factory.buildGroupDescStatsRequest()
971 .setXid(getNextTransactionId())
972 .build();
973 write(gdr, null);
974 }
975
976 private void assignAdjacencyLabels() {
977 // TODO
978 try {
979 nextDriverState();
980 } catch (IOException e) {
981 // TODO Auto-generated catch block
982 e.printStackTrace();
983 }
984 }
985
Saurav Das1cd10152014-09-26 09:38:07 -0700986 private OFAction getOFAction(Action action) {
987 OFAction ofAction = null;
988 if (action instanceof OutputAction) {
989 OutputAction outputAction = (OutputAction) action;
990 OFPort port = OFPort.of((int) outputAction.getPortNumber().value());
991 ofAction = factory.actions().output(port, Short.MAX_VALUE);
992 } else if (action instanceof ModifyDstMacAction) {
993 long dstMac = ((ModifyDstMacAction) action).getDstMac().toLong();
994 OFOxmEthDst dmac = factory.oxms()
995 .ethDst(MacAddress.of(dstMac));
996 ofAction = factory.actions().buildSetField()
997 .setField(dmac).build();
998 } else if (action instanceof ModifySrcMacAction) {
999 long srcMac = ((ModifySrcMacAction) action).getSrcMac().toLong();
1000 OFOxmEthSrc smac = factory.oxms()
1001 .ethSrc(MacAddress.of(srcMac));
1002 ofAction = factory.actions().buildSetField()
1003 .setField(smac).build();
Srikanth Vavilapalli68144302014-10-08 15:55:24 -07001004 /*} else if (action instanceof PushMplsAction) {
1005 ofAction = factory.actions().pushMpls(EthType.MPLS_UNICAST);
1006 } else if (action instanceof SetMplsIdAction) {
1007 int labelid = ((SetMplsIdAction) action).getMplsId();
1008 OFOxmMplsLabel lid = factory.oxms()
1009 .mplsLabel(U32.of(labelid));
1010 ofAction = factory.actions().buildSetField()
1011 .setField(lid).build();
1012 */} else if (action instanceof PopMplsAction) {
Saurav Das1cd10152014-09-26 09:38:07 -07001013 EthType ethertype = ((PopMplsAction) action).getEthType();
1014 ofAction = factory.actions().popMpls(ethertype);
1015 } else if (action instanceof GroupAction) {
1016 NeighborSet ns = ((GroupAction) action).getDpids();
1017 EcmpInfo ei = ecmpGroups.get(ns);
1018 if (ei != null) {
1019 int gid = ei.groupId;
1020 ofAction = factory.actions().buildGroup()
1021 .setGroup(OFGroup.of(gid))
1022 .build();
1023 } else {
1024 log.error("Unable to find ecmp group for neighbors {} at "
1025 + "switch {}", ns, getStringId());
1026 }
1027 } else if (action instanceof DecNwTtlAction) {
1028 ofAction = factory.actions().decNwTtl();
1029 } else if (action instanceof DecMplsTtlAction) {
1030 ofAction = factory.actions().decMplsTtl();
1031 } else if (action instanceof CopyTtlInAction) {
1032 ofAction = factory.actions().copyTtlIn();
1033 } else if (action instanceof CopyTtlOutAction) {
1034 ofAction = factory.actions().copyTtlOut();
1035 } else {
1036 log.warn("Unsupported Action type: {}", action.getClass().getName());
1037 return null;
1038 }
1039
1040 // not supported by loxigen
1041 // OFAction setBos =
1042 // factory.actions().buildSetField().setField(bos).build();
1043
1044 return ofAction;
1045 }
1046
Saurav Das0a344b02014-09-26 14:18:52 -07001047 private OFMessage getIpEntry(MatchActionOperationEntry mao) {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001048 MatchAction ma = mao.getTarget();
1049 Operator op = mao.getOperator();
1050 Ipv4Match ipm = (Ipv4Match) ma.getMatch();
1051
1052 // set match
1053 IPv4Net ipdst = ipm.getDestination();
1054 OFOxmEthType ethTypeIp = factory.oxms()
1055 .ethType(EthType.IPv4);
1056 OFOxmIpv4DstMasked ipPrefix = factory.oxms()
1057 .ipv4DstMasked(
1058 IPv4Address.of(ipdst.address().value()),
1059 IPv4Address.ofCidrMaskLength(ipdst.prefixLen())
1060 );
1061 OFOxmList oxmList = OFOxmList.of(ethTypeIp, ipPrefix);
1062 OFMatchV3 match = factory.buildMatchV3()
1063 .setOxmList(oxmList).build();
1064
1065 // set actions
1066 List<OFAction> writeActions = new ArrayList<OFAction>();
1067 for (Action action : ma.getActions()) {
Saurav Das1cd10152014-09-26 09:38:07 -07001068 OFAction ofAction = getOFAction(action);
1069 if (ofAction != null) {
1070 writeActions.add(ofAction);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001071 }
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001072 }
1073
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001074 // set instructions
1075 OFInstruction writeInstr = factory.instructions().buildWriteActions()
1076 .setActions(writeActions).build();
1077 OFInstruction gotoInstr = factory.instructions().buildGotoTable()
1078 .setTableId(TableId.of(TABLE_ACL)).build();
1079 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
1080 instructions.add(writeInstr);
1081 instructions.add(gotoInstr);
1082
Saurav Das1cd10152014-09-26 09:38:07 -07001083 // set flow priority to emulate longest prefix match
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001084 int priority = ipdst.prefixLen() * PRIORITY_MULTIPLIER;
1085 if (ipdst.prefixLen() == (short) 32) {
1086 priority = MAX_PRIORITY;
1087 }
1088
Saurav Dasbc594a42014-09-25 20:13:50 -07001089 // set flow-mod
Saurav Dase972b3a2014-09-26 15:41:06 -07001090 OFFlowMod.Builder fmBuilder = null;
1091 switch (op) {
1092 case ADD:
1093 fmBuilder = factory.buildFlowAdd();
1094 break;
1095 case REMOVE:
1096 fmBuilder = factory.buildFlowDeleteStrict();
1097 break;
Sangho Shin5be3e532014-10-03 17:20:58 -07001098 case MODIFY: // TODO
1099 fmBuilder = factory.buildFlowModifyStrict();
1100 break;
Saurav Dase972b3a2014-09-26 15:41:06 -07001101 default:
1102 log.warn("Unsupported MatchAction Operator: {}", op);
1103 return null;
Saurav Dasbc594a42014-09-25 20:13:50 -07001104 }
Saurav Dase972b3a2014-09-26 15:41:06 -07001105 OFMessage ipFlow = fmBuilder
1106 .setTableId(TableId.of(TABLE_IPv4_UNICAST))
1107 .setMatch(match)
1108 .setInstructions(instructions)
1109 .setPriority(priority)
1110 .setBufferId(OFBufferId.NO_BUFFER)
1111 .setIdleTimeout(0)
1112 .setHardTimeout(0)
1113 .setXid(getNextTransactionId())
1114 .build();
Saurav Dasbc594a42014-09-25 20:13:50 -07001115 log.debug("{} ip-rule {}-{} in sw {}",
1116 (op == MatchActionOperations.Operator.ADD) ? "Adding" : "Deleting",
1117 match, writeActions,
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001118 getStringId());
Saurav Das0a344b02014-09-26 14:18:52 -07001119 return ipFlow;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001120 }
1121
Saurav Das0a344b02014-09-26 14:18:52 -07001122 private OFMessage getMplsEntry(MatchActionOperationEntry mao) {
Saurav Das1cd10152014-09-26 09:38:07 -07001123 MatchAction ma = mao.getTarget();
1124 Operator op = mao.getOperator();
1125 MplsMatch mplsm = (MplsMatch) ma.getMatch();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001126
Saurav Das1cd10152014-09-26 09:38:07 -07001127 // set match
1128 OFOxmEthType ethTypeMpls = factory.oxms()
1129 .ethType(EthType.MPLS_UNICAST);
1130 OFOxmMplsLabel labelid = factory.oxms()
1131 .mplsLabel(U32.of(mplsm.getMplsLabel()));
1132 OFOxmList oxmList = OFOxmList.of(ethTypeMpls, labelid);
1133 OFMatchV3 matchlabel = factory.buildMatchV3()
1134 .setOxmList(oxmList).build();
1135
1136 // set actions
1137 List<OFAction> writeActions = new ArrayList<OFAction>();
1138 for (Action action : ma.getActions()) {
1139 OFAction ofAction = getOFAction(action);
1140 if (ofAction != null) {
1141 writeActions.add(ofAction);
1142 }
1143 }
1144
1145 // set instructions
1146 OFInstruction writeInstr = factory.instructions().buildWriteActions()
1147 .setActions(writeActions).build();
1148 OFInstruction gotoInstr = factory.instructions().buildGotoTable()
1149 .setTableId(TableId.of(TABLE_ACL)).build();
1150 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
1151 instructions.add(writeInstr);
1152 instructions.add(gotoInstr);
1153
Saurav Dase972b3a2014-09-26 15:41:06 -07001154 // set flow-mod
1155 OFFlowMod.Builder fmBuilder = null;
1156 switch (op) {
1157 case ADD:
1158 fmBuilder = factory.buildFlowAdd();
1159 break;
1160 case REMOVE:
1161 fmBuilder = factory.buildFlowDeleteStrict();
1162 break;
Sangho Shin5be3e532014-10-03 17:20:58 -07001163 case MODIFY: // TODO
1164 fmBuilder = factory.buildFlowModifyStrict();
1165 break;
Saurav Dase972b3a2014-09-26 15:41:06 -07001166 default:
1167 log.warn("Unsupported MatchAction Operator: {}", op);
1168 return null;
Saurav Das1cd10152014-09-26 09:38:07 -07001169 }
Saurav Dase972b3a2014-09-26 15:41:06 -07001170
1171 OFMessage mplsFlow = fmBuilder
1172 .setTableId(TableId.of(TABLE_MPLS))
1173 .setMatch(matchlabel)
1174 .setInstructions(instructions)
1175 .setPriority(MAX_PRIORITY) // exact match and exclusive
1176 .setBufferId(OFBufferId.NO_BUFFER)
1177 .setIdleTimeout(0)
1178 .setHardTimeout(0)
1179 .setXid(getNextTransactionId())
1180 .build();
Saurav Das1cd10152014-09-26 09:38:07 -07001181 log.debug("{} mpls-rule {}-{} in sw {}",
1182 (op == MatchActionOperations.Operator.ADD) ? "Adding" : "Deleting",
1183 matchlabel, writeActions,
1184 getStringId());
Saurav Das0a344b02014-09-26 14:18:52 -07001185 return mplsFlow;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001186 }
1187
Saurav Das0a344b02014-09-26 14:18:52 -07001188 private OFMessage getAclEntry(MatchActionOperationEntry mao) {
Saurav Dase972b3a2014-09-26 15:41:06 -07001189 MatchAction ma = mao.getTarget();
1190 Operator op = mao.getOperator();
1191 PacketMatch packetMatch = (PacketMatch) ma.getMatch();
1192 Builder matchBuilder = factory.buildMatch();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001193
Saurav Dase972b3a2014-09-26 15:41:06 -07001194 // set match
1195 int inport = 0;
1196 if (ma.getSwitchPort() != null) {
1197 inport = (int) ma.getSwitchPort().getPortNumber().value();
1198 }
1199 final MACAddress srcMac = packetMatch.getSrcMacAddress();
1200 final MACAddress dstMac = packetMatch.getDstMacAddress();
1201 final Short etherType = packetMatch.getEtherType();
1202 final IPv4Net srcIp = packetMatch.getSrcIpAddress();
1203 final IPv4Net dstIp = packetMatch.getDstIpAddress();
1204 final Byte ipProto = packetMatch.getIpProtocolNumber();
1205 final Short srcTcpPort = packetMatch.getSrcTcpPortNumber();
1206 final Short dstTcpPort = packetMatch.getDstTcpPortNumber();
1207 if (inport > 0) {
1208 matchBuilder.setExact(MatchField.IN_PORT,
1209 OFPort.of(inport));
1210 }
1211 if (srcMac != null) {
1212 matchBuilder.setExact(MatchField.ETH_SRC, MacAddress.of(srcMac.toLong()));
1213 }
1214 if (dstMac != null) {
1215 matchBuilder.setExact(MatchField.ETH_DST, MacAddress.of(dstMac.toLong()));
1216 }
1217 if (etherType != null) {
1218 matchBuilder.setExact(MatchField.ETH_TYPE, EthType.of(etherType));
1219 }
1220 if (srcIp != null) {
1221 matchBuilder.setMasked(MatchField.IPV4_SRC,
1222 IPv4Address.of(srcIp.address().value())
1223 .withMaskOfLength(srcIp.prefixLen()));
1224 }
1225 if (dstIp != null) {
1226 matchBuilder.setMasked(MatchField.IPV4_DST,
1227 IPv4Address.of(dstIp.address().value())
1228 .withMaskOfLength(dstIp.prefixLen()));
1229 }
1230 if (ipProto != null) {
1231 matchBuilder.setExact(MatchField.IP_PROTO, IpProtocol.of(ipProto));
1232 }
1233 if (srcTcpPort != null) {
1234 matchBuilder.setExact(MatchField.TCP_SRC, TransportPort.of(srcTcpPort));
1235 }
1236 if (dstTcpPort != null) {
1237 matchBuilder.setExact(MatchField.TCP_DST, TransportPort.of(dstTcpPort));
1238 }
1239
1240 // set actions
1241 List<OFAction> applyActions = new ArrayList<OFAction>();
1242 for (Action action : ma.getActions()) {
1243 OFAction ofAction = getOFAction(action);
1244 if (ofAction != null) {
1245 applyActions.add(ofAction);
1246 }
1247 }
1248
1249 // set instructions
1250 OFInstruction clearInstr = factory.instructions().clearActions();
1251 OFInstruction applyInstr = factory.instructions().buildApplyActions()
1252 .setActions(applyActions).build();
1253 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
1254 instructions.add(clearInstr);
1255 instructions.add(applyInstr);
1256
1257 // set flow-mod
1258 OFFlowMod.Builder fmBuilder = null;
1259 switch (op) {
1260 case ADD:
1261 fmBuilder = factory.buildFlowAdd();
1262 break;
1263 case REMOVE:
1264 fmBuilder = factory.buildFlowDeleteStrict();
1265 break;
Sangho Shin5be3e532014-10-03 17:20:58 -07001266 case MODIFY: // TODO
1267 fmBuilder = factory.buildFlowModifyStrict();
1268 break;
Saurav Dase972b3a2014-09-26 15:41:06 -07001269 default:
1270 log.warn("Unsupported MatchAction Operator: {}", op);
1271 return null;
1272 }
1273
1274 OFMessage aclFlow = fmBuilder
1275 .setTableId(TableId.of(TABLE_ACL))
1276 .setMatch(matchBuilder.build())
1277 .setInstructions(instructions)
1278 .setPriority(MAX_PRIORITY / 2) // TODO: wrong - should be MA
1279 // priority
1280 .setBufferId(OFBufferId.NO_BUFFER)
1281 .setIdleTimeout(0)
1282 .setHardTimeout(0)
1283 .setXid(getNextTransactionId())
1284 .build();
Saurav Das0a344b02014-09-26 14:18:52 -07001285 return aclFlow;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001286 }
1287
1288 // *****************************
1289 // IOF13Switch
1290 // *****************************
1291
1292 @Override
1293 public void pushFlow(MatchActionOperationEntry matchActionOp) throws IOException {
Saurav Das0a344b02014-09-26 14:18:52 -07001294 OFMessage ofm = getFlow(matchActionOp);
1295 if (ofm != null) {
1296 write(Collections.singletonList(ofm));
1297 }
1298 }
1299
1300 private OFMessage getFlow(MatchActionOperationEntry matchActionOp) {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001301 final MatchAction matchAction = matchActionOp.getTarget();
1302 final Match match = matchAction.getMatch();
1303 if (match instanceof Ipv4Match) {
Saurav Das0a344b02014-09-26 14:18:52 -07001304 return getIpEntry(matchActionOp);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001305 } else if (match instanceof MplsMatch) {
Saurav Das0a344b02014-09-26 14:18:52 -07001306 return getMplsEntry(matchActionOp);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001307 } else if (match instanceof PacketMatch) {
Saurav Das0a344b02014-09-26 14:18:52 -07001308 return getAclEntry(matchActionOp);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001309 } else {
1310 log.error("Unknown match type {} pushed to switch {}", match,
1311 getStringId());
1312 }
Saurav Das0a344b02014-09-26 14:18:52 -07001313 return null;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001314 }
1315
1316 @Override
1317 public void pushFlows(Collection<MatchActionOperationEntry> matchActionOps)
1318 throws IOException {
Saurav Das0a344b02014-09-26 14:18:52 -07001319 List<OFMessage> flowMods = new ArrayList<OFMessage>();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001320 for (MatchActionOperationEntry matchActionOp : matchActionOps) {
Saurav Das0a344b02014-09-26 14:18:52 -07001321 OFMessage ofm = getFlow(matchActionOp);
1322 if (ofm != null) {
1323 flowMods.add(ofm);
1324 }
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001325 }
Saurav Das0a344b02014-09-26 14:18:52 -07001326 write(flowMods);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001327 }
1328
1329 @Override
1330 public int getEcmpGroupId(NeighborSet ns) {
1331 EcmpInfo ei = ecmpGroups.get(ns);
1332 if (ei == null) {
1333 return -1;
1334 } else {
1335 return ei.groupId;
1336 }
1337 }
1338
1339 // *****************************
Saurav Das80d17392014-10-01 10:24:56 -07001340 // Unused
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001341 // *****************************
1342
Saurav Das80d17392014-10-01 10:24:56 -07001343 @SuppressWarnings("unused")
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001344 private void setAsyncConfig() throws IOException {
1345 List<OFMessage> msglist = new ArrayList<OFMessage>(3);
1346 OFMessage setAC = null;
1347
1348 if (role == Role.MASTER) {
1349 setAC = factory.buildAsyncSet()
1350 .setFlowRemovedMaskEqualMaster(SET_FLOW_REMOVED_MASK_MASTER)
1351 .setPacketInMaskEqualMaster(SET_PACKET_IN_MASK_MASTER)
1352 .setPortStatusMaskEqualMaster(SET_PORT_STATUS_MASK_MASTER)
1353 .setFlowRemovedMaskSlave(SET_ALL_SLAVE)
1354 .setPacketInMaskSlave(SET_ALL_SLAVE)
1355 .setPortStatusMaskSlave(SET_ALL_SLAVE)
1356 .setXid(getNextTransactionId())
1357 .build();
1358 } else if (role == Role.EQUAL) {
1359 setAC = factory.buildAsyncSet()
1360 .setFlowRemovedMaskEqualMaster(SET_FLOW_REMOVED_MASK_EQUAL)
1361 .setPacketInMaskEqualMaster(SET_PACKET_IN_MASK_EQUAL)
1362 .setPortStatusMaskEqualMaster(SET_PORT_STATUS_MASK_EQUAL)
1363 .setFlowRemovedMaskSlave(SET_ALL_SLAVE)
1364 .setPacketInMaskSlave(SET_ALL_SLAVE)
1365 .setPortStatusMaskSlave(SET_ALL_SLAVE)
1366 .setXid(getNextTransactionId())
1367 .build();
1368 }
1369 msglist.add(setAC);
1370
1371 OFMessage br = factory.buildBarrierRequest()
1372 .setXid(getNextTransactionId())
1373 .build();
1374 msglist.add(br);
1375
1376 OFMessage getAC = factory.buildAsyncGetRequest()
1377 .setXid(getNextTransactionId())
1378 .build();
1379 msglist.add(getAC);
1380
1381 write(msglist);
1382 }
1383
Saurav Das80d17392014-10-01 10:24:56 -07001384 @SuppressWarnings("unused")
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001385 private void decodeAsyncGetReply(OFAsyncGetReply rep) {
1386 long frm = rep.getFlowRemovedMaskEqualMaster();
Sangho Shin01bca862014-09-12 11:18:59 -07001387 long frs = rep.getFlowRemovedMaskSlave();
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001388 long pim = rep.getPacketInMaskEqualMaster();
Sangho Shin01bca862014-09-12 11:18:59 -07001389 long pis = rep.getPacketInMaskSlave();
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001390 long psm = rep.getPortStatusMaskEqualMaster();
Sangho Shin01bca862014-09-12 11:18:59 -07001391 long pss = rep.getPortStatusMaskSlave();
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001392
1393 if (role == Role.MASTER || role == Role.EQUAL) { // should separate
1394 log.info("FRM:{}", HexString.toHexString((frm & TEST_FLOW_REMOVED_MASK)));
1395 log.info("PIM:{}", HexString.toHexString((pim & TEST_PACKET_IN_MASK)));
1396 log.info("PSM:{}", HexString.toHexString((psm & TEST_PORT_STATUS_MASK)));
1397 }
1398
1399 }
1400
Saurav Das80d17392014-10-01 10:24:56 -07001401 @SuppressWarnings("unused")
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001402 private void getTableFeatures() throws IOException {
1403 OFMessage gtf = factory.buildTableFeaturesStatsRequest()
1404 .setXid(getNextTransactionId())
1405 .build();
1406 write(gtf, null);
1407 }
1408
Saurav Das80d17392014-10-01 10:24:56 -07001409 @SuppressWarnings("unused")
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001410 private void sendGroupFeaturesRequest() throws IOException {
1411 OFMessage gfr = factory.buildGroupFeaturesStatsRequest()
1412 .setXid(getNextTransactionId())
1413 .build();
1414 write(gfr, null);
1415 }
1416
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001417 private void processGroupFeatures(OFGroupFeaturesStatsReply gfsr) {
1418 log.info("Sw: {} Group Features {}", getStringId(), gfsr);
1419 }
1420
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001421}