blob: 0f476b6ea7104f354be243db71774b631cb84740 [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;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07008import java.util.List;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07009import java.util.Set;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070010import java.util.concurrent.ConcurrentHashMap;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -070011import java.util.concurrent.ConcurrentMap;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070012import java.util.concurrent.atomic.AtomicBoolean;
13
14import net.floodlightcontroller.core.IFloodlightProviderService.Role;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -070015import net.floodlightcontroller.core.IOF13Switch;
16import net.floodlightcontroller.core.IOFSwitch;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070017import net.floodlightcontroller.core.SwitchDriverSubHandshakeAlreadyStarted;
18import net.floodlightcontroller.core.SwitchDriverSubHandshakeCompleted;
19import net.floodlightcontroller.core.SwitchDriverSubHandshakeNotStarted;
20import net.floodlightcontroller.core.internal.OFSwitchImplBase;
Saurav Dase972b3a2014-09-26 15:41:06 -070021import net.floodlightcontroller.util.MACAddress;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -070022import net.onrc.onos.core.configmanager.INetworkConfigService;
23import net.onrc.onos.core.configmanager.INetworkConfigService.NetworkConfigState;
24import net.onrc.onos.core.configmanager.INetworkConfigService.SwitchConfigStatus;
25import net.onrc.onos.core.configmanager.NetworkConfig.LinkConfig;
Srikanth Vavilapalli68144302014-10-08 15:55:24 -070026import net.onrc.onos.core.configmanager.NetworkConfig.SwitchConfig;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -070027import net.onrc.onos.core.configmanager.NetworkConfigManager;
28import net.onrc.onos.core.configmanager.PktLinkConfig;
29import net.onrc.onos.core.configmanager.SegmentRouterConfig;
30import net.onrc.onos.core.matchaction.MatchAction;
31import net.onrc.onos.core.matchaction.MatchActionOperationEntry;
Saurav Dasbc594a42014-09-25 20:13:50 -070032import net.onrc.onos.core.matchaction.MatchActionOperations;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -070033import net.onrc.onos.core.matchaction.MatchActionOperations.Operator;
34import net.onrc.onos.core.matchaction.action.Action;
35import net.onrc.onos.core.matchaction.action.CopyTtlInAction;
36import net.onrc.onos.core.matchaction.action.CopyTtlOutAction;
37import net.onrc.onos.core.matchaction.action.DecMplsTtlAction;
38import net.onrc.onos.core.matchaction.action.DecNwTtlAction;
39import net.onrc.onos.core.matchaction.action.GroupAction;
40import net.onrc.onos.core.matchaction.action.ModifyDstMacAction;
41import net.onrc.onos.core.matchaction.action.ModifySrcMacAction;
42import net.onrc.onos.core.matchaction.action.OutputAction;
43import net.onrc.onos.core.matchaction.action.PopMplsAction;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -070044import net.onrc.onos.core.matchaction.match.Ipv4Match;
45import net.onrc.onos.core.matchaction.match.Match;
46import net.onrc.onos.core.matchaction.match.MplsMatch;
47import net.onrc.onos.core.matchaction.match.PacketMatch;
48import net.onrc.onos.core.util.Dpid;
49import net.onrc.onos.core.util.IPv4Net;
50import net.onrc.onos.core.util.PortNumber;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070051
52import org.projectfloodlight.openflow.protocol.OFAsyncGetReply;
53import org.projectfloodlight.openflow.protocol.OFBarrierRequest;
54import org.projectfloodlight.openflow.protocol.OFBucket;
55import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
56import org.projectfloodlight.openflow.protocol.OFErrorMsg;
57import org.projectfloodlight.openflow.protocol.OFFactory;
Saurav Dase972b3a2014-09-26 15:41:06 -070058import org.projectfloodlight.openflow.protocol.OFFlowMod;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070059import org.projectfloodlight.openflow.protocol.OFGroupDescStatsReply;
60import org.projectfloodlight.openflow.protocol.OFGroupFeaturesStatsReply;
61import org.projectfloodlight.openflow.protocol.OFGroupType;
62import org.projectfloodlight.openflow.protocol.OFMatchV3;
63import org.projectfloodlight.openflow.protocol.OFMessage;
64import org.projectfloodlight.openflow.protocol.OFOxmList;
65import org.projectfloodlight.openflow.protocol.OFPortDesc;
66import org.projectfloodlight.openflow.protocol.OFStatsReply;
67import org.projectfloodlight.openflow.protocol.action.OFAction;
68import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
Saurav Dase972b3a2014-09-26 15:41:06 -070069import org.projectfloodlight.openflow.protocol.match.Match.Builder;
70import org.projectfloodlight.openflow.protocol.match.MatchField;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070071import org.projectfloodlight.openflow.protocol.oxm.OFOxmEthDst;
72import org.projectfloodlight.openflow.protocol.oxm.OFOxmEthSrc;
73import org.projectfloodlight.openflow.protocol.oxm.OFOxmEthType;
74import org.projectfloodlight.openflow.protocol.oxm.OFOxmInPort;
75import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv4DstMasked;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070076import org.projectfloodlight.openflow.protocol.oxm.OFOxmMplsLabel;
77import org.projectfloodlight.openflow.protocol.oxm.OFOxmVlanVid;
78import org.projectfloodlight.openflow.types.EthType;
79import org.projectfloodlight.openflow.types.IPv4Address;
Saurav Dase972b3a2014-09-26 15:41:06 -070080import org.projectfloodlight.openflow.types.IpProtocol;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070081import org.projectfloodlight.openflow.types.MacAddress;
82import org.projectfloodlight.openflow.types.OFBufferId;
83import org.projectfloodlight.openflow.types.OFGroup;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070084import org.projectfloodlight.openflow.types.OFPort;
85import org.projectfloodlight.openflow.types.OFVlanVidMatch;
86import org.projectfloodlight.openflow.types.TableId;
Saurav Dase972b3a2014-09-26 15:41:06 -070087import org.projectfloodlight.openflow.types.TransportPort;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070088import org.projectfloodlight.openflow.types.U32;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070089import org.projectfloodlight.openflow.util.HexString;
90
91/**
92 * OFDescriptionStatistics Vendor (Manufacturer Desc.): Stanford University,
93 * Ericsson Research and CPqD Research. Make (Hardware Desc.) : OpenFlow 1.3
94 * Reference Userspace Switch Model (Datapath Desc.) : None Software : Serial :
95 * None
96 */
Saurav Dasfc5e3eb2014-09-25 19:05:21 -070097public class OFSwitchImplCPqD13 extends OFSwitchImplBase implements IOF13Switch {
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070098 private AtomicBoolean driverHandshakeComplete;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -070099 private AtomicBoolean haltStateMachine;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700100 private OFFactory factory;
101 private static final int OFPCML_NO_BUFFER = 0xffff;
102 // Configuration of asynch messages to controller. We need different
103 // asynch messages depending on role-equal or role-master.
104 // We don't want to get anything if we are slave.
105 private static final long SET_FLOW_REMOVED_MASK_MASTER = 0xf;
106 private static final long SET_PACKET_IN_MASK_MASTER = 0x7;
107 private static final long SET_PORT_STATUS_MASK_MASTER = 0x7;
108 private static final long SET_FLOW_REMOVED_MASK_EQUAL = 0x0;
109 private static final long SET_PACKET_IN_MASK_EQUAL = 0x0;
110 private static final long SET_PORT_STATUS_MASK_EQUAL = 0x7;
111 private static final long SET_ALL_SLAVE = 0x0;
112
113 private static final long TEST_FLOW_REMOVED_MASK = 0xf;
114 private static final long TEST_PACKET_IN_MASK = 0x7;
115 private static final long TEST_PORT_STATUS_MASK = 0x7;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700116
117 private static final int TABLE_VLAN = 0;
118 private static final int TABLE_TMAC = 1;
Sangho Shin01bca862014-09-12 11:18:59 -0700119 private static final int TABLE_IPv4_UNICAST = 2;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700120 private static final int TABLE_MPLS = 3;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700121 private static final int TABLE_ACL = 5;
122
123 private static final short MAX_PRIORITY = (short) 0xffff;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700124 private static final short PRIORITY_MULTIPLIER = (short) 2046;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700125 private static final short MIN_PRIORITY = 0x0;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700126
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700127 private long barrierXidToWaitFor = -1;
128 private DriverState driverState;
Jonathan Hartcb34f382014-08-12 21:11:03 -0700129 private final boolean usePipeline13;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700130 private SegmentRouterConfig srConfig;
131 private ConcurrentMap<Dpid, Set<PortNumber>> neighbors;
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700132 private ConcurrentMap<PortNumber, Dpid> portToNeighbors;
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700133 private List<Integer> edgeLabels;
134 private boolean isEdgeRouter;
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700135 private int sid;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700136 private ConcurrentMap<NeighborSet, EcmpInfo> ecmpGroups;
Srikanth Vavilapallib95e6e02014-10-02 13:56:39 -0700137 private ConcurrentMap<PortNumber, ArrayList<NeighborSet>> portNeighborSetMap;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700138
139
Jonathan Hartcb34f382014-08-12 21:11:03 -0700140
141 public OFSwitchImplCPqD13(OFDescStatsReply desc, boolean usePipeline13) {
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700142 super();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700143 haltStateMachine = new AtomicBoolean(false);
144 driverState = DriverState.INIT;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700145 driverHandshakeComplete = new AtomicBoolean(false);
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700146 setSwitchDescription(desc);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700147 neighbors = new ConcurrentHashMap<Dpid, Set<PortNumber>>();
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700148 portToNeighbors = new ConcurrentHashMap<PortNumber, Dpid>();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700149 ecmpGroups = new ConcurrentHashMap<NeighborSet, EcmpInfo>();
Srikanth Vavilapallib95e6e02014-10-02 13:56:39 -0700150 portNeighborSetMap =
151 new ConcurrentHashMap<PortNumber, ArrayList<NeighborSet>>();
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700152 edgeLabels = new ArrayList<Integer>();
153 isEdgeRouter = false;
Jonathan Hartcb34f382014-08-12 21:11:03 -0700154 this.usePipeline13 = usePipeline13;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700155 }
156
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700157 // *****************************
158 // OFSwitchImplBase
159 // *****************************
160
161
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700162 /* (non-Javadoc)
163 * @see java.lang.Object#toString()
164 */
165 @Override
166 public String toString() {
167 return "OFSwitchImplCPqD13 [" + ((channel != null)
168 ? channel.getRemoteAddress() : "?")
169 + " DPID[" + ((stringId != null) ? stringId : "?") + "]]";
170 }
171
172 @Override
173 public void startDriverHandshake() throws IOException {
174 log.debug("Starting driver handshake for sw {}", getStringId());
175 if (startDriverHandshakeCalled) {
176 throw new SwitchDriverSubHandshakeAlreadyStarted();
177 }
178 startDriverHandshakeCalled = true;
Jonathan Harta213bce2014-08-11 15:44:07 -0700179 factory = getFactory();
Jonathan Hartcb34f382014-08-12 21:11:03 -0700180 if (!usePipeline13) {
181 // Send packet-in to controller if a packet misses the first table
182 populateTableMissEntry(0, true, false, false, 0);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700183 driverHandshakeComplete.set(true);
Sangho Shin01bca862014-09-12 11:18:59 -0700184 } else {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700185 nextDriverState();
Sangho Shin01bca862014-09-12 11:18:59 -0700186 }
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700187 }
188
189 @Override
190 public boolean isDriverHandshakeComplete() {
Sangho Shin01bca862014-09-12 11:18:59 -0700191 if (!startDriverHandshakeCalled)
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700192 throw new SwitchDriverSubHandshakeNotStarted();
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700193 return driverHandshakeComplete.get();
194 }
195
196 @Override
197 public void processDriverHandshakeMessage(OFMessage m) {
Sangho Shin01bca862014-09-12 11:18:59 -0700198 if (!startDriverHandshakeCalled)
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700199 throw new SwitchDriverSubHandshakeNotStarted();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700200 if (isDriverHandshakeComplete())
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700201 throw new SwitchDriverSubHandshakeCompleted(m);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700202 try {
203 processOFMessage(this, m);
204 } catch (IOException e) {
205 log.error("Error generated when processing OFMessage", e.getCause());
206 }
207 }
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700208
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700209 @Override
210 public String getSwitchDriverState() {
211 return driverState.toString();
212 }
213
Srikanth Vavilapallibd9b3e22014-10-02 08:57:46 -0700214 public void removePortFromGroups(PortNumber port) {
Srikanth Vavilapallicf1840b2014-10-09 15:29:51 -0700215 /* FIX: removePortFromGroups is not working */
216
217 /* ArrayList<NeighborSet> portNSSet = portNeighborSetMap.get(port);
218 if (portNSSet == null)
219 {
220 *//* No Groups are created with this port yet */
221 /* log.warn("removePortFromGroups: No groups exist with Switch {} port {}",
222 getStringId(), port);
223 return;
Srikanth Vavilapallibd9b3e22014-10-02 08:57:46 -0700224 }
Srikanth Vavilapallicf1840b2014-10-09 15:29:51 -0700225 for (NeighborSet ns : portNSSet) {
226 *//* Delete the first matched bucket */
227 /* EcmpInfo portEcmpInfo = ecmpGroups.get(ns);
228 Iterator<BucketInfo> it = portEcmpInfo.buckets.iterator();
229 while (it.hasNext()) {
230 BucketInfo bucket = it.next();
231 if (bucket.outport.equals(port)) {
232 it.remove();
233 }
234 }
235 modifyEcmpGroup(portEcmpInfo);
236 }
237 *//* Don't delete the entry from portNeighborSetMap because
238 * when the port is up again this info is needed
239 */
Srikanth Vavilapalli7d873fd2014-10-04 07:50:57 -0700240 return;
Srikanth Vavilapallibd9b3e22014-10-02 08:57:46 -0700241 }
242
243 public void addPortToGroups(PortNumber port) {
Srikanth Vavilapallicf1840b2014-10-09 15:29:51 -0700244 /* ArrayList<NeighborSet> portNSSet = portNeighborSetMap.get(port);
245 if (portNSSet == null) {
246 *//* Unknown Port */
247 /* log.warn("addPortToGroups: Switch {} port {} is unknown",
248 getStringId(), port);
249 return;
250 }
251 Dpid neighborDpid = portToNeighbors.get(port);
252 for (NeighborSet ns : portNSSet) {
253 *//* Delete the first matched bucket */
254 /* EcmpInfo portEcmpInfo = ecmpGroups.get(ns);
255 BucketInfo b = new BucketInfo(neighborDpid,
256 MacAddress.of(srConfig.getRouterMac()),
257 getNeighborRouterMacAddress(neighborDpid),
258 port,
259 ns.getEdgeLabel());
260 List<BucketInfo> buckets = portEcmpInfo.buckets;
261 if (buckets == null) {
262 buckets = new ArrayList<BucketInfo>();
263 buckets.add(b);
264 portEcmpInfo.buckets = buckets;
265 } else {
266 buckets.add(b);
267 }
268 modifyEcmpGroup(portEcmpInfo);
269 }
270 */return;
Srikanth Vavilapallibd9b3e22014-10-02 08:57:46 -0700271 }
272
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700273 // *****************************
274 // Driver handshake state-machine
275 // *****************************
276
277 enum DriverState {
278 INIT,
279 SET_TABLE_MISS_ENTRIES,
280 SET_TABLE_VLAN_TMAC,
281 SET_GROUPS,
282 VERIFY_GROUPS,
283 SET_ADJACENCY_LABELS,
284 EXIT
285 }
286
287 protected void nextDriverState() throws IOException {
288 DriverState currentState = driverState;
Saurav Das80d17392014-10-01 10:24:56 -0700289 if (haltStateMachine.get()) {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700290 return;
Saurav Das80d17392014-10-01 10:24:56 -0700291 }
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700292 switch (currentState) {
293 case INIT:
294 driverState = DriverState.SET_TABLE_MISS_ENTRIES;
295 setTableMissEntries();
Saurav Dasd84178f2014-09-29 17:48:54 -0700296 sendHandshakeBarrier();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700297 break;
298 case SET_TABLE_MISS_ENTRIES:
299 driverState = DriverState.SET_TABLE_VLAN_TMAC;
300 getNetworkConfig();
301 populateTableVlan();
302 populateTableTMac();
Saurav Dasd84178f2014-09-29 17:48:54 -0700303 sendHandshakeBarrier();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700304 break;
305 case SET_TABLE_VLAN_TMAC:
306 driverState = DriverState.SET_GROUPS;
307 createGroups();
Saurav Dasd84178f2014-09-29 17:48:54 -0700308 sendHandshakeBarrier();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700309 break;
310 case SET_GROUPS:
311 driverState = DriverState.VERIFY_GROUPS;
312 verifyGroups();
313 break;
314 case VERIFY_GROUPS:
315 driverState = DriverState.SET_ADJACENCY_LABELS;
316 assignAdjacencyLabels();
317 break;
318 case SET_ADJACENCY_LABELS:
319 driverState = DriverState.EXIT;
320 driverHandshakeComplete.set(true);
321 break;
322 case EXIT:
323 default:
324 driverState = DriverState.EXIT;
325 log.error("Driver handshake has exited for sw: {}", getStringId());
326 }
327 }
328
329 void processOFMessage(IOFSwitch sw, OFMessage m) throws IOException {
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700330 switch (m.getType()) {
331 case BARRIER_REPLY:
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700332 processBarrierReply(m);
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700333 break;
334
335 case ERROR:
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700336 processErrorMessage(m);
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700337 break;
338
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700339 case GET_ASYNC_REPLY:
340 OFAsyncGetReply asrep = (OFAsyncGetReply) m;
341 decodeAsyncGetReply(asrep);
342 break;
343
344 case PACKET_IN:
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700345 // not ready to handle packet-ins
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700346 break;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700347
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700348 case QUEUE_GET_CONFIG_REPLY:
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700349 // not doing queue config yet
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700350 break;
351
352 case STATS_REPLY:
353 processStatsReply((OFStatsReply) m);
354 break;
355
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700356 case ROLE_REPLY: // channelHandler should handle this
357 case PORT_STATUS: // channelHandler should handle this
358 case FEATURES_REPLY: // don't care
359 case FLOW_REMOVED: // don't care
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700360 default:
361 log.debug("Received message {} during switch-driver subhandshake "
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700362 + "from switch {} ... Ignoring message", m, sw.getStringId());
363 }
364 }
365
366 private void processStatsReply(OFStatsReply sr) {
367 switch (sr.getStatsType()) {
368 case AGGREGATE:
369 break;
370 case DESC:
371 break;
372 case EXPERIMENTER:
373 break;
374 case FLOW:
375 break;
376 case GROUP_DESC:
377 processGroupDesc((OFGroupDescStatsReply) sr);
378 break;
379 case GROUP_FEATURES:
380 processGroupFeatures((OFGroupFeaturesStatsReply) sr);
381 break;
382 case METER_CONFIG:
383 break;
384 case METER_FEATURES:
385 break;
386 case PORT_DESC:
387 break;
388 case TABLE_FEATURES:
389 break;
390 default:
391 break;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700392
393 }
394 }
395
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700396 private void processErrorMessage(OFMessage m) {
397 log.error("Switch {} Error {} in DriverState", getStringId(),
398 (OFErrorMsg) m, driverState);
399 }
400
401 private void processBarrierReply(OFMessage m) throws IOException {
402 if (m.getXid() == barrierXidToWaitFor) {
403 // Driver state-machine progresses to the next state.
404 // If Barrier messages is not received, then eventually
405 // the ChannelHandler state machine will timeout, and the switch
406 // will be disconnected.
407 nextDriverState();
408 } else {
409 log.error("Received incorrect barrier-message xid {} (expected: {}) in "
410 + "switch-driver state {} for switch {}", m, barrierXidToWaitFor,
411 driverState, getStringId());
412 }
413 }
414
415 private void processGroupDesc(OFGroupDescStatsReply gdsr) {
416 log.info("Sw: {} Group Desc {}", getStringId(), gdsr);
417 try {
418 nextDriverState();
419 } catch (IOException e) {
420 // TODO Auto-generated catch block
421 e.printStackTrace();
422 }
423 }
424
425 // *****************************
426 // Utility methods
427 // *****************************
428
429 void setTableMissEntries() throws IOException {
430 // set all table-miss-entries
431 populateTableMissEntry(TABLE_VLAN, true, false, false, -1);
432 populateTableMissEntry(TABLE_TMAC, true, false, false, -1);
433 populateTableMissEntry(TABLE_IPv4_UNICAST, false, true, true,
434 TABLE_ACL);
435 populateTableMissEntry(TABLE_MPLS, false, true, true,
436 TABLE_ACL);
437 populateTableMissEntry(TABLE_ACL, false, false, false, -1);
438 }
439
Saurav Dasd84178f2014-09-29 17:48:54 -0700440 private void sendHandshakeBarrier() throws IOException {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700441 long xid = getNextTransactionId();
442 barrierXidToWaitFor = xid;
443 OFBarrierRequest br = getFactory()
444 .buildBarrierRequest()
445 .setXid(xid)
446 .build();
447 write(br, null);
448 }
449
450 /**
451 * Adds a table-miss-entry to a pipeline table.
452 * <p>
453 * The table-miss-entry can be added with 'write-actions' or
454 * 'apply-actions'. It can also add a 'goto-table' instruction. By default
455 * if none of the booleans in the call are set, then the table-miss entry is
456 * added with no instructions, which means that if a packet hits the
457 * table-miss-entry, pipeline execution will stop, and the action set
458 * associated with the packet will be executed.
459 *
460 * @param tableToAdd the table to where the table-miss-entry will be added
461 * @param toControllerNow as an APPLY_ACTION instruction
462 * @param toControllerWrite as a WRITE_ACTION instruction
463 * @param toTable as a GOTO_TABLE instruction
464 * @param tableToSend the table to send as per the GOTO_TABLE instruction it
465 * needs to be set if 'toTable' is true. Ignored of 'toTable' is
466 * false.
467 * @throws IOException
468 */
469 @SuppressWarnings("unchecked")
470 private void populateTableMissEntry(int tableToAdd, boolean toControllerNow,
471 boolean toControllerWrite,
472 boolean toTable, int tableToSend) throws IOException {
473 OFOxmList oxmList = OFOxmList.EMPTY;
474 OFMatchV3 match = factory.buildMatchV3()
475 .setOxmList(oxmList)
476 .build();
477 OFAction outc = factory.actions()
478 .buildOutput()
479 .setPort(OFPort.CONTROLLER)
480 .setMaxLen(OFPCML_NO_BUFFER)
481 .build();
482 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
483 if (toControllerNow) {
484 // table-miss instruction to send to controller immediately
485 OFInstruction instr = factory.instructions()
486 .buildApplyActions()
487 .setActions(Collections.singletonList(outc))
488 .build();
489 instructions.add(instr);
490 }
491
492 if (toControllerWrite) {
493 // table-miss instruction to write-action to send to controller
494 // this will be executed whenever the action-set gets executed
495 OFInstruction instr = factory.instructions()
496 .buildWriteActions()
497 .setActions(Collections.singletonList(outc))
498 .build();
499 instructions.add(instr);
500 }
501
502 if (toTable) {
503 // table-miss instruction to goto-table x
504 OFInstruction instr = factory.instructions()
505 .gotoTable(TableId.of(tableToSend));
506 instructions.add(instr);
507 }
508
509 if (!toControllerNow && !toControllerWrite && !toTable) {
510 // table-miss has no instruction - at which point action-set will be
511 // executed - if there is an action to output/group in the action
512 // set
513 // the packet will be sent there, otherwise it will be dropped.
514 instructions = (List<OFInstruction>) Collections.EMPTY_LIST;
515 }
516
517 OFMessage tableMissEntry = factory.buildFlowAdd()
518 .setTableId(TableId.of(tableToAdd))
519 .setMatch(match) // match everything
520 .setInstructions(instructions)
521 .setPriority(MIN_PRIORITY)
522 .setBufferId(OFBufferId.NO_BUFFER)
523 .setIdleTimeout(0)
524 .setHardTimeout(0)
525 .setXid(getNextTransactionId())
526 .build();
527 write(tableMissEntry, null);
528 }
529
530 private void getNetworkConfig() {
531 INetworkConfigService ncs = floodlightProvider.getNetworkConfigService();
532 SwitchConfigStatus scs = ncs.checkSwitchConfig(new Dpid(getId()));
533 if (scs.getConfigState() == NetworkConfigState.ACCEPT_ADD) {
534 srConfig = (SegmentRouterConfig) scs.getSwitchConfig();
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700535 isEdgeRouter = srConfig.isEdgeRouter();
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700536 sid = srConfig.getNodeSid();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700537 } else {
538 log.error("Switch not configured as Segment-Router");
539 }
540
541 List<LinkConfig> linkConfigList = ncs.getConfiguredAllowedLinks();
542 setNeighbors(linkConfigList);
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700543
544 if (isEdgeRouter) {
545 List<SwitchConfig> switchList = ncs.getConfiguredAllowedSwitches();
546 getAllEdgeLabels(switchList);
547 }
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700548 }
549
550 private void populateTableVlan() throws IOException {
551 List<OFMessage> msglist = new ArrayList<OFMessage>();
552 for (OFPortDesc p : getPorts()) {
553 int pnum = p.getPortNo().getPortNumber();
554 if (U32.of(pnum).compareTo(U32.of(OFPort.MAX.getPortNumber())) < 1) {
555 OFOxmInPort oxp = factory.oxms().inPort(p.getPortNo());
556 OFOxmVlanVid oxv = factory.oxms()
557 .vlanVid(OFVlanVidMatch.UNTAGGED);
558 OFOxmList oxmList = OFOxmList.of(oxp, oxv);
559 OFMatchV3 match = factory.buildMatchV3()
560 .setOxmList(oxmList).build();
561
562 // TODO: match on vlan-tagged packets for vlans configured on
563 // subnet ports and strip-vlan
564
565 // Do not need to add vlans
566 /*int vlanid = getVlanConfig(pnum);
567 OFOxmVlanVid vidToSet = factory.oxms()
568 .vlanVid(OFVlanVidMatch.ofVlan(vlanid));
569 OFAction pushVlan = factory.actions().pushVlan(EthType.VLAN_FRAME);
570 OFAction setVlan = factory.actions().setField(vidToSet);
571 List<OFAction> actionlist = new ArrayList<OFAction>();
572 actionlist.add(pushVlan);
573 actionlist.add(setVlan);
574 OFInstruction appAction = factory.instructions().buildApplyActions()
575 .setActions(actionlist).build();*/
576
577 OFInstruction gotoTbl = factory.instructions().buildGotoTable()
578 .setTableId(TableId.of(TABLE_TMAC)).build();
579 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
580 // instructions.add(appAction);
581 instructions.add(gotoTbl);
582 OFMessage flowEntry = factory.buildFlowAdd()
583 .setTableId(TableId.of(TABLE_VLAN))
584 .setMatch(match)
585 .setInstructions(instructions)
586 .setPriority(1000) // does not matter - all rules
587 // exclusive
588 .setBufferId(OFBufferId.NO_BUFFER)
589 .setIdleTimeout(0)
590 .setHardTimeout(0)
591 .setXid(getNextTransactionId())
592 .build();
593 msglist.add(flowEntry);
594 }
595 }
596 write(msglist);
597 log.debug("Adding {} port/vlan-rules in sw {}", msglist.size(), getStringId());
598 }
599
600 private void populateTableTMac() throws IOException {
601 // match for router-mac and ip-packets
602 OFOxmEthType oxe = factory.oxms().ethType(EthType.IPv4);
603 OFOxmEthDst dmac = factory.oxms().ethDst(getRouterMacAddr());
604 OFOxmList oxmListIp = OFOxmList.of(dmac, oxe);
605 OFMatchV3 matchIp = factory.buildMatchV3()
606 .setOxmList(oxmListIp).build();
607 OFInstruction gotoTblIp = factory.instructions().buildGotoTable()
608 .setTableId(TableId.of(TABLE_IPv4_UNICAST)).build();
609 List<OFInstruction> instructionsIp = Collections.singletonList(gotoTblIp);
610 OFMessage ipEntry = factory.buildFlowAdd()
611 .setTableId(TableId.of(TABLE_TMAC))
612 .setMatch(matchIp)
613 .setInstructions(instructionsIp)
614 .setPriority(1000) // strict priority required lower than
615 // multicastMac
616 .setBufferId(OFBufferId.NO_BUFFER)
617 .setIdleTimeout(0)
618 .setHardTimeout(0)
619 .setXid(getNextTransactionId())
620 .build();
621
622 // match for router-mac and mpls packets
623 OFOxmEthType oxmpls = factory.oxms().ethType(EthType.MPLS_UNICAST);
624 OFOxmList oxmListMpls = OFOxmList.of(dmac, oxmpls);
625 OFMatchV3 matchMpls = factory.buildMatchV3()
626 .setOxmList(oxmListMpls).build();
627 OFInstruction gotoTblMpls = factory.instructions().buildGotoTable()
628 .setTableId(TableId.of(TABLE_MPLS)).build();
629 List<OFInstruction> instructionsMpls = Collections.singletonList(gotoTblMpls);
630 OFMessage mplsEntry = factory.buildFlowAdd()
631 .setTableId(TableId.of(TABLE_TMAC))
632 .setMatch(matchMpls)
633 .setInstructions(instructionsMpls)
634 .setPriority(1001) // strict priority required lower than
635 // multicastMac
636 .setBufferId(OFBufferId.NO_BUFFER)
637 .setIdleTimeout(0)
638 .setHardTimeout(0)
639 .setXid(getNextTransactionId())
640 .build();
641
642 log.debug("Adding termination-mac-rules in sw {}", getStringId());
643 List<OFMessage> msglist = new ArrayList<OFMessage>(2);
644 msglist.add(ipEntry);
645 msglist.add(mplsEntry);
646 write(msglist);
647 }
648
649 private MacAddress getRouterMacAddr() {
650 if (srConfig != null) {
651 return MacAddress.of(srConfig.getRouterMac());
652 } else {
653 // return a dummy mac address - it will not be used
654 return MacAddress.of("00:00:00:00:00:00");
655 }
656 }
657
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700658 private boolean isEdgeRouter(Dpid ndpid) {
659 INetworkConfigService ncs = floodlightProvider.getNetworkConfigService();
660 SwitchConfigStatus scs = ncs.checkSwitchConfig(ndpid);
661 if (scs.getConfigState() == NetworkConfigState.ACCEPT_ADD) {
662 return ((SegmentRouterConfig) scs.getSwitchConfig()).isEdgeRouter();
663 } else {
664 // TODO: return false if router not allowed
665 return false;
666 }
667 }
668
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700669 private MacAddress getNeighborRouterMacAddress(Dpid ndpid) {
670 INetworkConfigService ncs = floodlightProvider.getNetworkConfigService();
671 SwitchConfigStatus scs = ncs.checkSwitchConfig(ndpid);
672 if (scs.getConfigState() == NetworkConfigState.ACCEPT_ADD) {
673 return MacAddress.of(((SegmentRouterConfig) scs.getSwitchConfig())
674 .getRouterMac());
675 } else {
676 // return a dummy mac address - it will not be used
677 return MacAddress.of("00:00:00:00:00:00");
678 }
679 }
680
681 private void setNeighbors(List<LinkConfig> linkConfigList) {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700682 for (LinkConfig lg : linkConfigList) {
683 if (!lg.getType().equals(NetworkConfigManager.PKT_LINK)) {
Saurav Das80d17392014-10-01 10:24:56 -0700684 continue;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700685 }
686 PktLinkConfig plg = (PktLinkConfig) lg;
687 if (plg.getDpid1() == getId()) {
688 addNeighborAtPort(new Dpid(plg.getDpid2()),
689 PortNumber.uint32(plg.getPort1()));
690 } else if (plg.getDpid2() == getId()) {
691 addNeighborAtPort(new Dpid(plg.getDpid1()),
692 PortNumber.uint32(plg.getPort2()));
693 }
694 }
695 }
696
697 private void addNeighborAtPort(Dpid neighborDpid, PortNumber portToNeighbor) {
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700698 /* Update NeighborToPort database */
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700699 if (neighbors.get(neighborDpid) != null) {
700 neighbors.get(neighborDpid).add(portToNeighbor);
701 } else {
702 Set<PortNumber> ports = new HashSet<PortNumber>();
703 ports.add(portToNeighbor);
704 neighbors.put(neighborDpid, ports);
705 }
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700706
707 /* Update portToNeighbors database */
708 if (portToNeighbors.get(portToNeighbor) == null)
709 portToNeighbors.put(portToNeighbor, neighborDpid);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700710 }
711
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700712 private void getAllEdgeLabels(List<SwitchConfig> switchList) {
713 for (SwitchConfig sc : switchList) {
714 /* TODO: Do we need to check if the SwitchConfig is of
715 * type SegmentRouter?
716 */
717 if ((sc.getDpid() == getId()) ||
718 (((SegmentRouterConfig) sc).isEdgeRouter() != true)) {
719 continue;
720 }
721 edgeLabels.add(((SegmentRouterConfig) sc).getNodeSid());
722 }
Srikanth Vavilapallica2263c2014-10-09 15:19:11 -0700723 log.debug("getAllEdgeLabels: Node Labels found {}", edgeLabels);
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700724 }
725
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700726 private boolean isNodeLabelAndEdgeLabelSame(Dpid dpid, int edgeLabel) {
727 INetworkConfigService ncs = floodlightProvider.getNetworkConfigService();
728 SwitchConfigStatus scs = ncs.checkSwitchConfig(dpid);
729 if (scs.getConfigState() == NetworkConfigState.ACCEPT_ADD) {
730 return (((SegmentRouterConfig) scs.getSwitchConfig()).
731 getNodeSid() == edgeLabel);
732 } else {
733 // TODO: return false if router not allowed
734 return false;
735 }
736 }
737
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700738 private Set<Set<Dpid>> getAllNeighborSets(Set<Dpid> neighbors) {
739 List<Dpid> list = new ArrayList<Dpid>(neighbors);
740 Set<Set<Dpid>> sets = new HashSet<Set<Dpid>>();
741 /* get the number of elements in the neighbors */
742 int elements = list.size();
743 /* the number of members of a power set is 2^n
744 * including the empty set
745 */
746 int powerElements = (1 << elements);
747
748 /* run a binary counter for the number of power elements */
749 for (long i = 1; i < powerElements; i++) {
750 Set<Dpid> dpidSubSet = new HashSet<Dpid>();
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700751 for (int j = 0; j < elements; j++) {
752 if ((i >> j) % 2 == 1) {
753 dpidSubSet.add(list.get(j));
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700754 }
755 }
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700756 /* NOTE: Avoid any pairings of edge routers only
757 * at a backbone router */
758 boolean avoidEdgeRouterPairing = true;
759 if ((!isEdgeRouter) && (dpidSubSet.size() > 1)) {
Srikanth Vavilapalli696010f2014-10-08 17:00:17 -0700760 for (Dpid dpid : dpidSubSet) {
761 if (!isEdgeRouter(dpid)) {
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700762 avoidEdgeRouterPairing = false;
Srikanth Vavilapalli696010f2014-10-08 17:00:17 -0700763 break;
764 }
765 }
766 }
767 else
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700768 avoidEdgeRouterPairing = false;
Srikanth Vavilapalli696010f2014-10-08 17:00:17 -0700769
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700770 if (!avoidEdgeRouterPairing)
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700771 sets.add(dpidSubSet);
772 }
773 return sets;
774 }
775
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700776 /**
777 * createGroups creates ECMP groups for all ports on this router connected
778 * to other routers (in the OF network). The information for ports is
779 * gleaned from the configured links. If no links are configured no groups
780 * will be created, and it is up to the caller of the IOF13Switch API to
781 * create groups.
782 * <p>
783 * By default all ports connected to the same neighbor router will be part
784 * of the same ECMP group. In addition, groups will be created for all
785 * possible combinations of neighbor routers.
786 * <p>
787 * For example, consider this router (R0) connected to 3 neighbors (R1, R2,
788 * and R3). The following groups will be created in R0:
789 * <li>1) all ports to R1,
790 * <li>2) all ports to R2,
791 * <li>3) all ports to R3,
792 * <li>4) all ports to R1 and R2
793 * <li>5) all ports to R1 and R3
794 * <li>6) all ports to R2 and R3
795 * <li>7) all ports to R1, R2, and R3
796 */
797 private void createGroups() {
798 Set<Dpid> dpids = neighbors.keySet();
799 if (dpids == null || dpids.isEmpty()) {
800 return;
801 }
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700802 /* Create all possible Neighbor sets from this router
803 * NOTE: Avoid any pairings of edge routers only
804 */
805 Set<Set<Dpid>> powerSet = getAllNeighborSets(dpids);
Srikanth Vavilapallica2263c2014-10-09 15:19:11 -0700806 log.debug("The size of neighbor powerset for sw {} is ",
807 getStringId(), powerSet.size());
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700808 Set<NeighborSet> nsSet = new HashSet<NeighborSet>();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700809 for (Set<Dpid> combo : powerSet) {
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700810 if (combo.isEmpty())
811 continue;
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700812 if (isEdgeRouter && !edgeLabels.isEmpty()) {
813 for (Integer edgeLabel : edgeLabels) {
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700814 /* If it is local node's edge label, continue */
815 if (edgeLabel == sid)
816 continue;
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700817 NeighborSet ns = new NeighborSet();
818 ns.addDpids(combo);
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700819 /* Check if the edge label being set is of the
820 * same node in the Neighbor set
821 */
822 if ((combo.size() != 1) ||
823 (!isNodeLabelAndEdgeLabelSame(
824 combo.iterator().next(), edgeLabel))){
825 ns.setEdgeLabel(edgeLabel);
826 }
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700827 nsSet.add(ns);
828 }
829 } else {
830 NeighborSet ns = new NeighborSet();
831 ns.addDpids(combo);
832 nsSet.add(ns);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700833 }
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700834 }
Srikanth Vavilapallica2263c2014-10-09 15:19:11 -0700835 log.debug("The neighborset with label for sw {} is ",
836 getStringId(), nsSet);
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700837
838 int groupid = 1;
839 for (NeighborSet ns : nsSet) {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700840 List<BucketInfo> buckets = new ArrayList<BucketInfo>();
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700841 for (Dpid d : ns.getDpids()) {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700842 for (PortNumber sp : neighbors.get(d)) {
843 BucketInfo b = new BucketInfo(d,
844 MacAddress.of(srConfig.getRouterMac()),
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700845 getNeighborRouterMacAddress(d), sp,
846 ns.getEdgeLabel());
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700847 buckets.add(b);
Srikanth Vavilapallibd9b3e22014-10-02 08:57:46 -0700848
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700849 /* Update Port Neighborset map */
Srikanth Vavilapallibd9b3e22014-10-02 08:57:46 -0700850 ArrayList<NeighborSet> portNeighborSets =
851 portNeighborSetMap.get(sp);
852 if (portNeighborSets == null) {
853 portNeighborSets = new ArrayList<NeighborSet>();
854 portNeighborSets.add(ns);
855 portNeighborSetMap.put(sp, portNeighborSets);
856 }
857 else
858 portNeighborSets.add(ns);
859 }
860 }
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700861 EcmpInfo ecmpInfo = new EcmpInfo(groupid++, buckets);
862 setEcmpGroup(ecmpInfo);
863 ecmpGroups.put(ns, ecmpInfo);
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700864 log.debug("Creating ecmp group in sw {} for neighbor set {}: {}",
865 getStringId(), ns, ecmpInfo);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700866 }
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700867
868 // temp map of ecmp groupings
869 /* Map<NeighborSet, List<BucketInfo>> temp =
870 new HashMap<NeighborSet, List<BucketInfo>>();
871 */
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700872 }
873
874 private class EcmpInfo {
875 int groupId;
876 List<BucketInfo> buckets;
877
878 EcmpInfo(int gid, List<BucketInfo> bucketInfos) {
879 groupId = gid;
880 buckets = bucketInfos;
881 }
882
883 @Override
884 public String toString() {
885 return "groupId: " + groupId + ", buckets: " + buckets;
886 }
887 }
888
889 private class BucketInfo {
890 Dpid neighborDpid;
891 MacAddress srcMac;
892 MacAddress dstMac;
893 PortNumber outport;
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700894 int mplsLabel;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700895
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700896 BucketInfo(Dpid nDpid, MacAddress smac, MacAddress dmac,
897 PortNumber p, int label) {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700898 neighborDpid = nDpid;
899 srcMac = smac;
900 dstMac = dmac;
901 outport = p;
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700902 mplsLabel = label;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700903 }
904
905 @Override
906 public String toString() {
907 return " {neighborDpid: " + neighborDpid + ", dstMac: " + dstMac +
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700908 ", srcMac: " + srcMac + ", outport: " + outport +
909 "mplsLabel: " + mplsLabel + "}";
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700910 }
911 }
912
913 private void setEcmpGroup(EcmpInfo ecmpInfo) {
914 List<OFMessage> msglist = new ArrayList<OFMessage>();
915 OFGroup group = OFGroup.of(ecmpInfo.groupId);
916
917 List<OFBucket> buckets = new ArrayList<OFBucket>();
918 for (BucketInfo b : ecmpInfo.buckets) {
919 OFOxmEthDst dmac = factory.oxms()
920 .ethDst(b.dstMac);
921 OFAction setDA = factory.actions().buildSetField()
922 .setField(dmac).build();
Saurav Das0a344b02014-09-26 14:18:52 -0700923 OFOxmEthSrc smac = factory.oxms()
924 .ethSrc(b.srcMac);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700925 OFAction setSA = factory.actions().buildSetField()
926 .setField(smac).build();
927 OFAction outp = factory.actions().buildOutput()
928 .setPort(OFPort.of(b.outport.shortValue()))
929 .build();
930 List<OFAction> actions = new ArrayList<OFAction>();
931 actions.add(setSA);
932 actions.add(setDA);
933 actions.add(outp);
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700934 if (b.mplsLabel != -1) {
935 OFAction pushLabel = factory.actions().buildPushMpls()
936 .setEthertype(EthType.MPLS_UNICAST).build();
Sangho Shin62ce5c12014-10-08 16:24:40 -0700937 OFOxmMplsLabel lid = factory.oxms()
938 .mplsLabel(U32.of(b.mplsLabel));
939 OFAction setLabel = factory.actions().buildSetField()
940 .setField(lid).build();
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700941 OFAction copyTtl = factory.actions().copyTtlOut();
942 OFAction decrTtl = factory.actions().decMplsTtl();
943 actions.add(pushLabel);
944 actions.add(setLabel);
945 actions.add(copyTtl);
946 actions.add(decrTtl);
947 }
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700948 OFBucket ofb = factory.buildBucket()
949 .setWeight(1)
950 .setActions(actions)
951 .build();
952 buckets.add(ofb);
953 }
954
955 OFMessage gm = factory.buildGroupAdd()
956 .setGroup(group)
957 .setBuckets(buckets)
958 .setGroupType(OFGroupType.SELECT)
959 .setXid(getNextTransactionId())
960 .build();
961 msglist.add(gm);
962 try {
963 write(msglist);
964 } catch (IOException e) {
965 // TODO Auto-generated catch block
966 e.printStackTrace();
967 }
968 }
969
Srikanth Vavilapalli7d873fd2014-10-04 07:50:57 -0700970 private void modifyEcmpGroup(EcmpInfo ecmpInfo) {
971 List<OFMessage> msglist = new ArrayList<OFMessage>();
972 OFGroup group = OFGroup.of(ecmpInfo.groupId);
973
974 List<OFBucket> buckets = new ArrayList<OFBucket>();
975 for (BucketInfo b : ecmpInfo.buckets) {
976 OFOxmEthDst dmac = factory.oxms()
977 .ethDst(b.dstMac);
978 OFAction setDA = factory.actions().buildSetField()
979 .setField(dmac).build();
980 OFOxmEthSrc smac = factory.oxms()
981 .ethSrc(b.srcMac);
982 OFAction setSA = factory.actions().buildSetField()
983 .setField(smac).build();
984 OFAction outp = factory.actions().buildOutput()
985 .setPort(OFPort.of(b.outport.shortValue()))
986 .build();
987 List<OFAction> actions = new ArrayList<OFAction>();
988 actions.add(setSA);
989 actions.add(setDA);
990 actions.add(outp);
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700991 if (b.mplsLabel != -1) {
992 OFAction pushLabel = factory.actions().buildPushMpls()
993 .setEthertype(EthType.MPLS_UNICAST).build();
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700994 OFOxmMplsLabel lid = factory.oxms()
995 .mplsLabel(U32.of(b.mplsLabel));
996 OFAction setLabel = factory.actions().buildSetField()
997 .setField(lid).build();
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700998 OFAction copyTtl = factory.actions().copyTtlOut();
999 OFAction decrTtl = factory.actions().decMplsTtl();
1000 actions.add(pushLabel);
1001 actions.add(setLabel);
1002 actions.add(copyTtl);
1003 actions.add(decrTtl);
1004 }
Srikanth Vavilapalli7d873fd2014-10-04 07:50:57 -07001005 OFBucket ofb = factory.buildBucket()
1006 .setWeight(1)
1007 .setActions(actions)
1008 .build();
1009 buckets.add(ofb);
1010 }
1011
1012 OFMessage gm = factory.buildGroupModify()
1013 .setGroup(group)
1014 .setBuckets(buckets)
1015 .setGroupType(OFGroupType.SELECT)
1016 .setXid(getNextTransactionId())
1017 .build();
1018 msglist.add(gm);
1019 try {
1020 write(msglist);
1021 } catch (IOException e) {
1022 // TODO Auto-generated catch block
1023 e.printStackTrace();
1024 }
1025 }
1026
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001027 private void verifyGroups() throws IOException {
1028 sendGroupDescRequest();
1029 }
1030
1031 private void sendGroupDescRequest() throws IOException {
1032 OFMessage gdr = factory.buildGroupDescStatsRequest()
1033 .setXid(getNextTransactionId())
1034 .build();
1035 write(gdr, null);
1036 }
1037
1038 private void assignAdjacencyLabels() {
1039 // TODO
1040 try {
1041 nextDriverState();
1042 } catch (IOException e) {
1043 // TODO Auto-generated catch block
1044 e.printStackTrace();
1045 }
1046 }
1047
Saurav Das1cd10152014-09-26 09:38:07 -07001048 private OFAction getOFAction(Action action) {
1049 OFAction ofAction = null;
1050 if (action instanceof OutputAction) {
1051 OutputAction outputAction = (OutputAction) action;
1052 OFPort port = OFPort.of((int) outputAction.getPortNumber().value());
1053 ofAction = factory.actions().output(port, Short.MAX_VALUE);
1054 } else if (action instanceof ModifyDstMacAction) {
1055 long dstMac = ((ModifyDstMacAction) action).getDstMac().toLong();
1056 OFOxmEthDst dmac = factory.oxms()
1057 .ethDst(MacAddress.of(dstMac));
1058 ofAction = factory.actions().buildSetField()
1059 .setField(dmac).build();
1060 } else if (action instanceof ModifySrcMacAction) {
1061 long srcMac = ((ModifySrcMacAction) action).getSrcMac().toLong();
1062 OFOxmEthSrc smac = factory.oxms()
1063 .ethSrc(MacAddress.of(srcMac));
1064 ofAction = factory.actions().buildSetField()
1065 .setField(smac).build();
Srikanth Vavilapalli68144302014-10-08 15:55:24 -07001066 /*} else if (action instanceof PushMplsAction) {
1067 ofAction = factory.actions().pushMpls(EthType.MPLS_UNICAST);
1068 } else if (action instanceof SetMplsIdAction) {
1069 int labelid = ((SetMplsIdAction) action).getMplsId();
1070 OFOxmMplsLabel lid = factory.oxms()
1071 .mplsLabel(U32.of(labelid));
1072 ofAction = factory.actions().buildSetField()
1073 .setField(lid).build();
1074 */} else if (action instanceof PopMplsAction) {
Saurav Das1cd10152014-09-26 09:38:07 -07001075 EthType ethertype = ((PopMplsAction) action).getEthType();
1076 ofAction = factory.actions().popMpls(ethertype);
1077 } else if (action instanceof GroupAction) {
1078 NeighborSet ns = ((GroupAction) action).getDpids();
1079 EcmpInfo ei = ecmpGroups.get(ns);
1080 if (ei != null) {
1081 int gid = ei.groupId;
1082 ofAction = factory.actions().buildGroup()
1083 .setGroup(OFGroup.of(gid))
1084 .build();
1085 } else {
1086 log.error("Unable to find ecmp group for neighbors {} at "
1087 + "switch {}", ns, getStringId());
1088 }
1089 } else if (action instanceof DecNwTtlAction) {
1090 ofAction = factory.actions().decNwTtl();
1091 } else if (action instanceof DecMplsTtlAction) {
1092 ofAction = factory.actions().decMplsTtl();
1093 } else if (action instanceof CopyTtlInAction) {
1094 ofAction = factory.actions().copyTtlIn();
1095 } else if (action instanceof CopyTtlOutAction) {
1096 ofAction = factory.actions().copyTtlOut();
1097 } else {
1098 log.warn("Unsupported Action type: {}", action.getClass().getName());
1099 return null;
1100 }
1101
1102 // not supported by loxigen
1103 // OFAction setBos =
1104 // factory.actions().buildSetField().setField(bos).build();
1105
1106 return ofAction;
1107 }
1108
Saurav Das0a344b02014-09-26 14:18:52 -07001109 private OFMessage getIpEntry(MatchActionOperationEntry mao) {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001110 MatchAction ma = mao.getTarget();
1111 Operator op = mao.getOperator();
1112 Ipv4Match ipm = (Ipv4Match) ma.getMatch();
1113
1114 // set match
1115 IPv4Net ipdst = ipm.getDestination();
1116 OFOxmEthType ethTypeIp = factory.oxms()
1117 .ethType(EthType.IPv4);
1118 OFOxmIpv4DstMasked ipPrefix = factory.oxms()
1119 .ipv4DstMasked(
1120 IPv4Address.of(ipdst.address().value()),
1121 IPv4Address.ofCidrMaskLength(ipdst.prefixLen())
1122 );
1123 OFOxmList oxmList = OFOxmList.of(ethTypeIp, ipPrefix);
1124 OFMatchV3 match = factory.buildMatchV3()
1125 .setOxmList(oxmList).build();
1126
1127 // set actions
1128 List<OFAction> writeActions = new ArrayList<OFAction>();
1129 for (Action action : ma.getActions()) {
Saurav Das1cd10152014-09-26 09:38:07 -07001130 OFAction ofAction = getOFAction(action);
1131 if (ofAction != null) {
1132 writeActions.add(ofAction);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001133 }
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001134 }
1135
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001136 // set instructions
1137 OFInstruction writeInstr = factory.instructions().buildWriteActions()
1138 .setActions(writeActions).build();
1139 OFInstruction gotoInstr = factory.instructions().buildGotoTable()
1140 .setTableId(TableId.of(TABLE_ACL)).build();
1141 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
1142 instructions.add(writeInstr);
1143 instructions.add(gotoInstr);
1144
Saurav Das1cd10152014-09-26 09:38:07 -07001145 // set flow priority to emulate longest prefix match
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001146 int priority = ipdst.prefixLen() * PRIORITY_MULTIPLIER;
1147 if (ipdst.prefixLen() == (short) 32) {
1148 priority = MAX_PRIORITY;
1149 }
1150
Saurav Dasbc594a42014-09-25 20:13:50 -07001151 // set flow-mod
Saurav Dase972b3a2014-09-26 15:41:06 -07001152 OFFlowMod.Builder fmBuilder = null;
1153 switch (op) {
1154 case ADD:
1155 fmBuilder = factory.buildFlowAdd();
1156 break;
1157 case REMOVE:
1158 fmBuilder = factory.buildFlowDeleteStrict();
1159 break;
Sangho Shin5be3e532014-10-03 17:20:58 -07001160 case MODIFY: // TODO
1161 fmBuilder = factory.buildFlowModifyStrict();
1162 break;
Saurav Dase972b3a2014-09-26 15:41:06 -07001163 default:
1164 log.warn("Unsupported MatchAction Operator: {}", op);
1165 return null;
Saurav Dasbc594a42014-09-25 20:13:50 -07001166 }
Saurav Dase972b3a2014-09-26 15:41:06 -07001167 OFMessage ipFlow = fmBuilder
1168 .setTableId(TableId.of(TABLE_IPv4_UNICAST))
1169 .setMatch(match)
1170 .setInstructions(instructions)
1171 .setPriority(priority)
1172 .setBufferId(OFBufferId.NO_BUFFER)
1173 .setIdleTimeout(0)
1174 .setHardTimeout(0)
1175 .setXid(getNextTransactionId())
1176 .build();
Saurav Dasbc594a42014-09-25 20:13:50 -07001177 log.debug("{} ip-rule {}-{} in sw {}",
1178 (op == MatchActionOperations.Operator.ADD) ? "Adding" : "Deleting",
1179 match, writeActions,
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001180 getStringId());
Saurav Das0a344b02014-09-26 14:18:52 -07001181 return ipFlow;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001182 }
1183
Saurav Das0a344b02014-09-26 14:18:52 -07001184 private OFMessage getMplsEntry(MatchActionOperationEntry mao) {
Saurav Das1cd10152014-09-26 09:38:07 -07001185 MatchAction ma = mao.getTarget();
1186 Operator op = mao.getOperator();
1187 MplsMatch mplsm = (MplsMatch) ma.getMatch();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001188
Saurav Das1cd10152014-09-26 09:38:07 -07001189 // set match
1190 OFOxmEthType ethTypeMpls = factory.oxms()
1191 .ethType(EthType.MPLS_UNICAST);
1192 OFOxmMplsLabel labelid = factory.oxms()
1193 .mplsLabel(U32.of(mplsm.getMplsLabel()));
1194 OFOxmList oxmList = OFOxmList.of(ethTypeMpls, labelid);
1195 OFMatchV3 matchlabel = factory.buildMatchV3()
1196 .setOxmList(oxmList).build();
1197
1198 // set actions
1199 List<OFAction> writeActions = new ArrayList<OFAction>();
1200 for (Action action : ma.getActions()) {
1201 OFAction ofAction = getOFAction(action);
1202 if (ofAction != null) {
1203 writeActions.add(ofAction);
1204 }
1205 }
1206
1207 // set instructions
1208 OFInstruction writeInstr = factory.instructions().buildWriteActions()
1209 .setActions(writeActions).build();
1210 OFInstruction gotoInstr = factory.instructions().buildGotoTable()
1211 .setTableId(TableId.of(TABLE_ACL)).build();
1212 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
1213 instructions.add(writeInstr);
1214 instructions.add(gotoInstr);
1215
Saurav Dase972b3a2014-09-26 15:41:06 -07001216 // set flow-mod
1217 OFFlowMod.Builder fmBuilder = null;
1218 switch (op) {
1219 case ADD:
1220 fmBuilder = factory.buildFlowAdd();
1221 break;
1222 case REMOVE:
1223 fmBuilder = factory.buildFlowDeleteStrict();
1224 break;
Sangho Shin5be3e532014-10-03 17:20:58 -07001225 case MODIFY: // TODO
1226 fmBuilder = factory.buildFlowModifyStrict();
1227 break;
Saurav Dase972b3a2014-09-26 15:41:06 -07001228 default:
1229 log.warn("Unsupported MatchAction Operator: {}", op);
1230 return null;
Saurav Das1cd10152014-09-26 09:38:07 -07001231 }
Saurav Dase972b3a2014-09-26 15:41:06 -07001232
1233 OFMessage mplsFlow = fmBuilder
1234 .setTableId(TableId.of(TABLE_MPLS))
1235 .setMatch(matchlabel)
1236 .setInstructions(instructions)
1237 .setPriority(MAX_PRIORITY) // exact match and exclusive
1238 .setBufferId(OFBufferId.NO_BUFFER)
1239 .setIdleTimeout(0)
1240 .setHardTimeout(0)
1241 .setXid(getNextTransactionId())
1242 .build();
Saurav Das1cd10152014-09-26 09:38:07 -07001243 log.debug("{} mpls-rule {}-{} in sw {}",
1244 (op == MatchActionOperations.Operator.ADD) ? "Adding" : "Deleting",
1245 matchlabel, writeActions,
1246 getStringId());
Saurav Das0a344b02014-09-26 14:18:52 -07001247 return mplsFlow;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001248 }
1249
Saurav Das0a344b02014-09-26 14:18:52 -07001250 private OFMessage getAclEntry(MatchActionOperationEntry mao) {
Saurav Dase972b3a2014-09-26 15:41:06 -07001251 MatchAction ma = mao.getTarget();
1252 Operator op = mao.getOperator();
1253 PacketMatch packetMatch = (PacketMatch) ma.getMatch();
1254 Builder matchBuilder = factory.buildMatch();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001255
Saurav Dase972b3a2014-09-26 15:41:06 -07001256 // set match
1257 int inport = 0;
1258 if (ma.getSwitchPort() != null) {
1259 inport = (int) ma.getSwitchPort().getPortNumber().value();
1260 }
1261 final MACAddress srcMac = packetMatch.getSrcMacAddress();
1262 final MACAddress dstMac = packetMatch.getDstMacAddress();
1263 final Short etherType = packetMatch.getEtherType();
1264 final IPv4Net srcIp = packetMatch.getSrcIpAddress();
1265 final IPv4Net dstIp = packetMatch.getDstIpAddress();
1266 final Byte ipProto = packetMatch.getIpProtocolNumber();
1267 final Short srcTcpPort = packetMatch.getSrcTcpPortNumber();
1268 final Short dstTcpPort = packetMatch.getDstTcpPortNumber();
1269 if (inport > 0) {
1270 matchBuilder.setExact(MatchField.IN_PORT,
1271 OFPort.of(inport));
1272 }
1273 if (srcMac != null) {
1274 matchBuilder.setExact(MatchField.ETH_SRC, MacAddress.of(srcMac.toLong()));
1275 }
1276 if (dstMac != null) {
1277 matchBuilder.setExact(MatchField.ETH_DST, MacAddress.of(dstMac.toLong()));
1278 }
1279 if (etherType != null) {
1280 matchBuilder.setExact(MatchField.ETH_TYPE, EthType.of(etherType));
1281 }
1282 if (srcIp != null) {
1283 matchBuilder.setMasked(MatchField.IPV4_SRC,
1284 IPv4Address.of(srcIp.address().value())
1285 .withMaskOfLength(srcIp.prefixLen()));
1286 }
1287 if (dstIp != null) {
1288 matchBuilder.setMasked(MatchField.IPV4_DST,
1289 IPv4Address.of(dstIp.address().value())
1290 .withMaskOfLength(dstIp.prefixLen()));
1291 }
1292 if (ipProto != null) {
1293 matchBuilder.setExact(MatchField.IP_PROTO, IpProtocol.of(ipProto));
1294 }
1295 if (srcTcpPort != null) {
1296 matchBuilder.setExact(MatchField.TCP_SRC, TransportPort.of(srcTcpPort));
1297 }
1298 if (dstTcpPort != null) {
1299 matchBuilder.setExact(MatchField.TCP_DST, TransportPort.of(dstTcpPort));
1300 }
1301
1302 // set actions
1303 List<OFAction> applyActions = new ArrayList<OFAction>();
1304 for (Action action : ma.getActions()) {
1305 OFAction ofAction = getOFAction(action);
1306 if (ofAction != null) {
1307 applyActions.add(ofAction);
1308 }
1309 }
1310
1311 // set instructions
1312 OFInstruction clearInstr = factory.instructions().clearActions();
1313 OFInstruction applyInstr = factory.instructions().buildApplyActions()
1314 .setActions(applyActions).build();
1315 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
1316 instructions.add(clearInstr);
1317 instructions.add(applyInstr);
1318
1319 // set flow-mod
1320 OFFlowMod.Builder fmBuilder = null;
1321 switch (op) {
1322 case ADD:
1323 fmBuilder = factory.buildFlowAdd();
1324 break;
1325 case REMOVE:
1326 fmBuilder = factory.buildFlowDeleteStrict();
1327 break;
Sangho Shin5be3e532014-10-03 17:20:58 -07001328 case MODIFY: // TODO
1329 fmBuilder = factory.buildFlowModifyStrict();
1330 break;
Saurav Dase972b3a2014-09-26 15:41:06 -07001331 default:
1332 log.warn("Unsupported MatchAction Operator: {}", op);
1333 return null;
1334 }
1335
1336 OFMessage aclFlow = fmBuilder
1337 .setTableId(TableId.of(TABLE_ACL))
1338 .setMatch(matchBuilder.build())
1339 .setInstructions(instructions)
1340 .setPriority(MAX_PRIORITY / 2) // TODO: wrong - should be MA
1341 // priority
1342 .setBufferId(OFBufferId.NO_BUFFER)
1343 .setIdleTimeout(0)
1344 .setHardTimeout(0)
1345 .setXid(getNextTransactionId())
1346 .build();
Saurav Das0a344b02014-09-26 14:18:52 -07001347 return aclFlow;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001348 }
1349
1350 // *****************************
1351 // IOF13Switch
1352 // *****************************
1353
1354 @Override
1355 public void pushFlow(MatchActionOperationEntry matchActionOp) throws IOException {
Saurav Das0a344b02014-09-26 14:18:52 -07001356 OFMessage ofm = getFlow(matchActionOp);
1357 if (ofm != null) {
1358 write(Collections.singletonList(ofm));
1359 }
1360 }
1361
1362 private OFMessage getFlow(MatchActionOperationEntry matchActionOp) {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001363 final MatchAction matchAction = matchActionOp.getTarget();
1364 final Match match = matchAction.getMatch();
1365 if (match instanceof Ipv4Match) {
Saurav Das0a344b02014-09-26 14:18:52 -07001366 return getIpEntry(matchActionOp);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001367 } else if (match instanceof MplsMatch) {
Saurav Das0a344b02014-09-26 14:18:52 -07001368 return getMplsEntry(matchActionOp);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001369 } else if (match instanceof PacketMatch) {
Saurav Das0a344b02014-09-26 14:18:52 -07001370 return getAclEntry(matchActionOp);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001371 } else {
1372 log.error("Unknown match type {} pushed to switch {}", match,
1373 getStringId());
1374 }
Saurav Das0a344b02014-09-26 14:18:52 -07001375 return null;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001376 }
1377
1378 @Override
1379 public void pushFlows(Collection<MatchActionOperationEntry> matchActionOps)
1380 throws IOException {
Saurav Das0a344b02014-09-26 14:18:52 -07001381 List<OFMessage> flowMods = new ArrayList<OFMessage>();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001382 for (MatchActionOperationEntry matchActionOp : matchActionOps) {
Saurav Das0a344b02014-09-26 14:18:52 -07001383 OFMessage ofm = getFlow(matchActionOp);
1384 if (ofm != null) {
1385 flowMods.add(ofm);
1386 }
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001387 }
Saurav Das0a344b02014-09-26 14:18:52 -07001388 write(flowMods);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001389 }
1390
1391 @Override
1392 public int getEcmpGroupId(NeighborSet ns) {
1393 EcmpInfo ei = ecmpGroups.get(ns);
1394 if (ei == null) {
1395 return -1;
1396 } else {
1397 return ei.groupId;
1398 }
1399 }
1400
1401 // *****************************
Saurav Das80d17392014-10-01 10:24:56 -07001402 // Unused
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001403 // *****************************
1404
Saurav Das80d17392014-10-01 10:24:56 -07001405 @SuppressWarnings("unused")
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001406 private void setAsyncConfig() throws IOException {
1407 List<OFMessage> msglist = new ArrayList<OFMessage>(3);
1408 OFMessage setAC = null;
1409
1410 if (role == Role.MASTER) {
1411 setAC = factory.buildAsyncSet()
1412 .setFlowRemovedMaskEqualMaster(SET_FLOW_REMOVED_MASK_MASTER)
1413 .setPacketInMaskEqualMaster(SET_PACKET_IN_MASK_MASTER)
1414 .setPortStatusMaskEqualMaster(SET_PORT_STATUS_MASK_MASTER)
1415 .setFlowRemovedMaskSlave(SET_ALL_SLAVE)
1416 .setPacketInMaskSlave(SET_ALL_SLAVE)
1417 .setPortStatusMaskSlave(SET_ALL_SLAVE)
1418 .setXid(getNextTransactionId())
1419 .build();
1420 } else if (role == Role.EQUAL) {
1421 setAC = factory.buildAsyncSet()
1422 .setFlowRemovedMaskEqualMaster(SET_FLOW_REMOVED_MASK_EQUAL)
1423 .setPacketInMaskEqualMaster(SET_PACKET_IN_MASK_EQUAL)
1424 .setPortStatusMaskEqualMaster(SET_PORT_STATUS_MASK_EQUAL)
1425 .setFlowRemovedMaskSlave(SET_ALL_SLAVE)
1426 .setPacketInMaskSlave(SET_ALL_SLAVE)
1427 .setPortStatusMaskSlave(SET_ALL_SLAVE)
1428 .setXid(getNextTransactionId())
1429 .build();
1430 }
1431 msglist.add(setAC);
1432
1433 OFMessage br = factory.buildBarrierRequest()
1434 .setXid(getNextTransactionId())
1435 .build();
1436 msglist.add(br);
1437
1438 OFMessage getAC = factory.buildAsyncGetRequest()
1439 .setXid(getNextTransactionId())
1440 .build();
1441 msglist.add(getAC);
1442
1443 write(msglist);
1444 }
1445
Saurav Das80d17392014-10-01 10:24:56 -07001446 @SuppressWarnings("unused")
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001447 private void decodeAsyncGetReply(OFAsyncGetReply rep) {
1448 long frm = rep.getFlowRemovedMaskEqualMaster();
Sangho Shin01bca862014-09-12 11:18:59 -07001449 long frs = rep.getFlowRemovedMaskSlave();
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001450 long pim = rep.getPacketInMaskEqualMaster();
Sangho Shin01bca862014-09-12 11:18:59 -07001451 long pis = rep.getPacketInMaskSlave();
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001452 long psm = rep.getPortStatusMaskEqualMaster();
Sangho Shin01bca862014-09-12 11:18:59 -07001453 long pss = rep.getPortStatusMaskSlave();
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001454
1455 if (role == Role.MASTER || role == Role.EQUAL) { // should separate
1456 log.info("FRM:{}", HexString.toHexString((frm & TEST_FLOW_REMOVED_MASK)));
1457 log.info("PIM:{}", HexString.toHexString((pim & TEST_PACKET_IN_MASK)));
1458 log.info("PSM:{}", HexString.toHexString((psm & TEST_PORT_STATUS_MASK)));
1459 }
1460
1461 }
1462
Saurav Das80d17392014-10-01 10:24:56 -07001463 @SuppressWarnings("unused")
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001464 private void getTableFeatures() throws IOException {
1465 OFMessage gtf = factory.buildTableFeaturesStatsRequest()
1466 .setXid(getNextTransactionId())
1467 .build();
1468 write(gtf, null);
1469 }
1470
Saurav Das80d17392014-10-01 10:24:56 -07001471 @SuppressWarnings("unused")
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001472 private void sendGroupFeaturesRequest() throws IOException {
1473 OFMessage gfr = factory.buildGroupFeaturesStatsRequest()
1474 .setXid(getNextTransactionId())
1475 .build();
1476 write(gfr, null);
1477 }
1478
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001479 private void processGroupFeatures(OFGroupFeaturesStatsReply gfsr) {
1480 log.info("Sw: {} Group Features {}", getStringId(), gfsr);
1481 }
1482
Fahad Naeem Khand563af62014-10-08 17:37:25 -07001483 @Override
1484 public TableId getTableId(String tableType) {
1485 tableType = tableType.toLowerCase();
1486 if(tableType.contentEquals("ip")){
1487 return TableId.of(OFSwitchImplCPqD13.TABLE_IPv4_UNICAST);
1488 }
1489 else if (tableType.contentEquals("mpls")){
1490 return TableId.of(OFSwitchImplCPqD13.TABLE_MPLS);
1491 }
1492 else if (tableType.contentEquals("acl")){
1493 return TableId.of(OFSwitchImplCPqD13.TABLE_ACL);
1494 }
1495 else{
1496 log.warn("Invalid tableType: {}", tableType);
1497 return null;
1498 }
1499 }
1500
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001501}