blob: 075cb06e88a47c21641a32a277b22a2743353bc4 [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 Vavilapalli4ae146e2014-10-09 14:35:26 -0700133 private ConcurrentMap<PortNumber, Dpid> portToNeighbors;
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700134 private List<Integer> edgeLabels;
135 private boolean isEdgeRouter;
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700136 private int sid;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700137 private ConcurrentMap<NeighborSet, EcmpInfo> ecmpGroups;
Srikanth Vavilapallib95e6e02014-10-02 13:56:39 -0700138 private ConcurrentMap<PortNumber, ArrayList<NeighborSet>> portNeighborSetMap;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700139
140
Jonathan Hartcb34f382014-08-12 21:11:03 -0700141
142 public OFSwitchImplCPqD13(OFDescStatsReply desc, boolean usePipeline13) {
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700143 super();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700144 haltStateMachine = new AtomicBoolean(false);
145 driverState = DriverState.INIT;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700146 driverHandshakeComplete = new AtomicBoolean(false);
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700147 setSwitchDescription(desc);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700148 neighbors = new ConcurrentHashMap<Dpid, Set<PortNumber>>();
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700149 portToNeighbors = new ConcurrentHashMap<PortNumber, Dpid>();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700150 ecmpGroups = new ConcurrentHashMap<NeighborSet, EcmpInfo>();
Srikanth Vavilapallib95e6e02014-10-02 13:56:39 -0700151 portNeighborSetMap =
152 new ConcurrentHashMap<PortNumber, ArrayList<NeighborSet>>();
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700153 edgeLabels = new ArrayList<Integer>();
154 isEdgeRouter = false;
Jonathan Hartcb34f382014-08-12 21:11:03 -0700155 this.usePipeline13 = usePipeline13;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700156 }
157
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700158 // *****************************
159 // OFSwitchImplBase
160 // *****************************
161
162
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700163 /* (non-Javadoc)
164 * @see java.lang.Object#toString()
165 */
166 @Override
167 public String toString() {
168 return "OFSwitchImplCPqD13 [" + ((channel != null)
169 ? channel.getRemoteAddress() : "?")
170 + " DPID[" + ((stringId != null) ? stringId : "?") + "]]";
171 }
172
173 @Override
174 public void startDriverHandshake() throws IOException {
175 log.debug("Starting driver handshake for sw {}", getStringId());
176 if (startDriverHandshakeCalled) {
177 throw new SwitchDriverSubHandshakeAlreadyStarted();
178 }
179 startDriverHandshakeCalled = true;
Jonathan Harta213bce2014-08-11 15:44:07 -0700180 factory = getFactory();
Jonathan Hartcb34f382014-08-12 21:11:03 -0700181 if (!usePipeline13) {
182 // Send packet-in to controller if a packet misses the first table
183 populateTableMissEntry(0, true, false, false, 0);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700184 driverHandshakeComplete.set(true);
Sangho Shin01bca862014-09-12 11:18:59 -0700185 } else {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700186 nextDriverState();
Sangho Shin01bca862014-09-12 11:18:59 -0700187 }
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700188 }
189
190 @Override
191 public boolean isDriverHandshakeComplete() {
Sangho Shin01bca862014-09-12 11:18:59 -0700192 if (!startDriverHandshakeCalled)
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700193 throw new SwitchDriverSubHandshakeNotStarted();
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700194 return driverHandshakeComplete.get();
195 }
196
197 @Override
198 public void processDriverHandshakeMessage(OFMessage m) {
Sangho Shin01bca862014-09-12 11:18:59 -0700199 if (!startDriverHandshakeCalled)
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700200 throw new SwitchDriverSubHandshakeNotStarted();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700201 if (isDriverHandshakeComplete())
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700202 throw new SwitchDriverSubHandshakeCompleted(m);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700203 try {
204 processOFMessage(this, m);
205 } catch (IOException e) {
206 log.error("Error generated when processing OFMessage", e.getCause());
207 }
208 }
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700209
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700210 @Override
211 public String getSwitchDriverState() {
212 return driverState.toString();
213 }
214
Srikanth Vavilapallibd9b3e22014-10-02 08:57:46 -0700215 public void removePortFromGroups(PortNumber port) {
216 ArrayList<NeighborSet> portNSSet = portNeighborSetMap.get(port);
Sangho Shin5be3e532014-10-03 17:20:58 -0700217 if (portNSSet == null)
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700218 {
Srikanth Vavilapalli7d873fd2014-10-04 07:50:57 -0700219 /* No Groups are created with this port yet */
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700220 log.warn("removePortFromGroups: No groups exist with Switch {} port {}",
221 getStringId(), port);
Sangho Shin5be3e532014-10-03 17:20:58 -0700222 return;
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700223 }
Srikanth Vavilapallibd9b3e22014-10-02 08:57:46 -0700224 for (NeighborSet ns : portNSSet) {
225 /* Delete the first matched bucket */
Srikanth Vavilapalli7d873fd2014-10-04 07:50:57 -0700226 EcmpInfo portEcmpInfo = ecmpGroups.get(ns);
227 Iterator<BucketInfo> it = portEcmpInfo.buckets.iterator();
Srikanth Vavilapallibd9b3e22014-10-02 08:57:46 -0700228 while (it.hasNext()) {
229 BucketInfo bucket = it.next();
230 if (bucket.outport.equals(port)) {
231 it.remove();
Srikanth Vavilapallibd9b3e22014-10-02 08:57:46 -0700232 }
233 }
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700234 modifyEcmpGroup(portEcmpInfo);
Srikanth Vavilapallibd9b3e22014-10-02 08:57:46 -0700235 }
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700236 /* Don't delete the entry from portNeighborSetMap because
237 * when the port is up again this info is needed
238 */
Srikanth Vavilapalli7d873fd2014-10-04 07:50:57 -0700239 return;
Srikanth Vavilapallibd9b3e22014-10-02 08:57:46 -0700240 }
241
242 public void addPortToGroups(PortNumber port) {
243 ArrayList<NeighborSet> portNSSet = portNeighborSetMap.get(port);
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700244 if (portNSSet == null) {
245 /* Unknown Port */
246 log.warn("addPortToGroups: Switch {} port {} is unknown",
247 getStringId(), port);
Srikanth Vavilapallibd9b3e22014-10-02 08:57:46 -0700248 return;
249 }
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700250 Dpid neighborDpid = portToNeighbors.get(port);
251 for (NeighborSet ns : portNSSet) {
252 /* Delete the first matched bucket */
253 EcmpInfo portEcmpInfo = ecmpGroups.get(ns);
254 BucketInfo b = new BucketInfo(neighborDpid,
255 MacAddress.of(srConfig.getRouterMac()),
256 getNeighborRouterMacAddress(neighborDpid),
257 port,
258 ns.getEdgeLabel());
259 List<BucketInfo> buckets = portEcmpInfo.buckets;
260 if (buckets == null) {
261 buckets = new ArrayList<BucketInfo>();
262 buckets.add(b);
263 portEcmpInfo.buckets = buckets;
264 } else {
265 buckets.add(b);
266 }
267 modifyEcmpGroup(portEcmpInfo);
268 }
Srikanth Vavilapallibd9b3e22014-10-02 08:57:46 -0700269 return;
270 }
271
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700272 // *****************************
273 // Driver handshake state-machine
274 // *****************************
275
276 enum DriverState {
277 INIT,
278 SET_TABLE_MISS_ENTRIES,
279 SET_TABLE_VLAN_TMAC,
280 SET_GROUPS,
281 VERIFY_GROUPS,
282 SET_ADJACENCY_LABELS,
283 EXIT
284 }
285
286 protected void nextDriverState() throws IOException {
287 DriverState currentState = driverState;
Saurav Das80d17392014-10-01 10:24:56 -0700288 if (haltStateMachine.get()) {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700289 return;
Saurav Das80d17392014-10-01 10:24:56 -0700290 }
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700291 switch (currentState) {
292 case INIT:
293 driverState = DriverState.SET_TABLE_MISS_ENTRIES;
294 setTableMissEntries();
Saurav Dasd84178f2014-09-29 17:48:54 -0700295 sendHandshakeBarrier();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700296 break;
297 case SET_TABLE_MISS_ENTRIES:
298 driverState = DriverState.SET_TABLE_VLAN_TMAC;
299 getNetworkConfig();
300 populateTableVlan();
301 populateTableTMac();
Saurav Dasd84178f2014-09-29 17:48:54 -0700302 sendHandshakeBarrier();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700303 break;
304 case SET_TABLE_VLAN_TMAC:
305 driverState = DriverState.SET_GROUPS;
306 createGroups();
Saurav Dasd84178f2014-09-29 17:48:54 -0700307 sendHandshakeBarrier();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700308 break;
309 case SET_GROUPS:
310 driverState = DriverState.VERIFY_GROUPS;
311 verifyGroups();
312 break;
313 case VERIFY_GROUPS:
314 driverState = DriverState.SET_ADJACENCY_LABELS;
315 assignAdjacencyLabels();
316 break;
317 case SET_ADJACENCY_LABELS:
318 driverState = DriverState.EXIT;
319 driverHandshakeComplete.set(true);
320 break;
321 case EXIT:
322 default:
323 driverState = DriverState.EXIT;
324 log.error("Driver handshake has exited for sw: {}", getStringId());
325 }
326 }
327
328 void processOFMessage(IOFSwitch sw, OFMessage m) throws IOException {
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700329 switch (m.getType()) {
330 case BARRIER_REPLY:
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700331 processBarrierReply(m);
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700332 break;
333
334 case ERROR:
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700335 processErrorMessage(m);
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700336 break;
337
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700338 case GET_ASYNC_REPLY:
339 OFAsyncGetReply asrep = (OFAsyncGetReply) m;
340 decodeAsyncGetReply(asrep);
341 break;
342
343 case PACKET_IN:
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700344 // not ready to handle packet-ins
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700345 break;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700346
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700347 case QUEUE_GET_CONFIG_REPLY:
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700348 // not doing queue config yet
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700349 break;
350
351 case STATS_REPLY:
352 processStatsReply((OFStatsReply) m);
353 break;
354
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700355 case ROLE_REPLY: // channelHandler should handle this
356 case PORT_STATUS: // channelHandler should handle this
357 case FEATURES_REPLY: // don't care
358 case FLOW_REMOVED: // don't care
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700359 default:
360 log.debug("Received message {} during switch-driver subhandshake "
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700361 + "from switch {} ... Ignoring message", m, sw.getStringId());
362 }
363 }
364
365 private void processStatsReply(OFStatsReply sr) {
366 switch (sr.getStatsType()) {
367 case AGGREGATE:
368 break;
369 case DESC:
370 break;
371 case EXPERIMENTER:
372 break;
373 case FLOW:
374 break;
375 case GROUP_DESC:
376 processGroupDesc((OFGroupDescStatsReply) sr);
377 break;
378 case GROUP_FEATURES:
379 processGroupFeatures((OFGroupFeaturesStatsReply) sr);
380 break;
381 case METER_CONFIG:
382 break;
383 case METER_FEATURES:
384 break;
385 case PORT_DESC:
386 break;
387 case TABLE_FEATURES:
388 break;
389 default:
390 break;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700391
392 }
393 }
394
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700395 private void processErrorMessage(OFMessage m) {
396 log.error("Switch {} Error {} in DriverState", getStringId(),
397 (OFErrorMsg) m, driverState);
398 }
399
400 private void processBarrierReply(OFMessage m) throws IOException {
401 if (m.getXid() == barrierXidToWaitFor) {
402 // Driver state-machine progresses to the next state.
403 // If Barrier messages is not received, then eventually
404 // the ChannelHandler state machine will timeout, and the switch
405 // will be disconnected.
406 nextDriverState();
407 } else {
408 log.error("Received incorrect barrier-message xid {} (expected: {}) in "
409 + "switch-driver state {} for switch {}", m, barrierXidToWaitFor,
410 driverState, getStringId());
411 }
412 }
413
414 private void processGroupDesc(OFGroupDescStatsReply gdsr) {
415 log.info("Sw: {} Group Desc {}", getStringId(), gdsr);
416 try {
417 nextDriverState();
418 } catch (IOException e) {
419 // TODO Auto-generated catch block
420 e.printStackTrace();
421 }
422 }
423
424 // *****************************
425 // Utility methods
426 // *****************************
427
428 void setTableMissEntries() throws IOException {
429 // set all table-miss-entries
430 populateTableMissEntry(TABLE_VLAN, true, false, false, -1);
431 populateTableMissEntry(TABLE_TMAC, true, false, false, -1);
432 populateTableMissEntry(TABLE_IPv4_UNICAST, false, true, true,
433 TABLE_ACL);
434 populateTableMissEntry(TABLE_MPLS, false, true, true,
435 TABLE_ACL);
436 populateTableMissEntry(TABLE_ACL, false, false, false, -1);
437 }
438
Saurav Dasd84178f2014-09-29 17:48:54 -0700439 private void sendHandshakeBarrier() throws IOException {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700440 long xid = getNextTransactionId();
441 barrierXidToWaitFor = xid;
442 OFBarrierRequest br = getFactory()
443 .buildBarrierRequest()
444 .setXid(xid)
445 .build();
446 write(br, null);
447 }
448
449 /**
450 * Adds a table-miss-entry to a pipeline table.
451 * <p>
452 * The table-miss-entry can be added with 'write-actions' or
453 * 'apply-actions'. It can also add a 'goto-table' instruction. By default
454 * if none of the booleans in the call are set, then the table-miss entry is
455 * added with no instructions, which means that if a packet hits the
456 * table-miss-entry, pipeline execution will stop, and the action set
457 * associated with the packet will be executed.
458 *
459 * @param tableToAdd the table to where the table-miss-entry will be added
460 * @param toControllerNow as an APPLY_ACTION instruction
461 * @param toControllerWrite as a WRITE_ACTION instruction
462 * @param toTable as a GOTO_TABLE instruction
463 * @param tableToSend the table to send as per the GOTO_TABLE instruction it
464 * needs to be set if 'toTable' is true. Ignored of 'toTable' is
465 * false.
466 * @throws IOException
467 */
468 @SuppressWarnings("unchecked")
469 private void populateTableMissEntry(int tableToAdd, boolean toControllerNow,
470 boolean toControllerWrite,
471 boolean toTable, int tableToSend) throws IOException {
472 OFOxmList oxmList = OFOxmList.EMPTY;
473 OFMatchV3 match = factory.buildMatchV3()
474 .setOxmList(oxmList)
475 .build();
476 OFAction outc = factory.actions()
477 .buildOutput()
478 .setPort(OFPort.CONTROLLER)
479 .setMaxLen(OFPCML_NO_BUFFER)
480 .build();
481 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
482 if (toControllerNow) {
483 // table-miss instruction to send to controller immediately
484 OFInstruction instr = factory.instructions()
485 .buildApplyActions()
486 .setActions(Collections.singletonList(outc))
487 .build();
488 instructions.add(instr);
489 }
490
491 if (toControllerWrite) {
492 // table-miss instruction to write-action to send to controller
493 // this will be executed whenever the action-set gets executed
494 OFInstruction instr = factory.instructions()
495 .buildWriteActions()
496 .setActions(Collections.singletonList(outc))
497 .build();
498 instructions.add(instr);
499 }
500
501 if (toTable) {
502 // table-miss instruction to goto-table x
503 OFInstruction instr = factory.instructions()
504 .gotoTable(TableId.of(tableToSend));
505 instructions.add(instr);
506 }
507
508 if (!toControllerNow && !toControllerWrite && !toTable) {
509 // table-miss has no instruction - at which point action-set will be
510 // executed - if there is an action to output/group in the action
511 // set
512 // the packet will be sent there, otherwise it will be dropped.
513 instructions = (List<OFInstruction>) Collections.EMPTY_LIST;
514 }
515
516 OFMessage tableMissEntry = factory.buildFlowAdd()
517 .setTableId(TableId.of(tableToAdd))
518 .setMatch(match) // match everything
519 .setInstructions(instructions)
520 .setPriority(MIN_PRIORITY)
521 .setBufferId(OFBufferId.NO_BUFFER)
522 .setIdleTimeout(0)
523 .setHardTimeout(0)
524 .setXid(getNextTransactionId())
525 .build();
526 write(tableMissEntry, null);
527 }
528
529 private void getNetworkConfig() {
530 INetworkConfigService ncs = floodlightProvider.getNetworkConfigService();
531 SwitchConfigStatus scs = ncs.checkSwitchConfig(new Dpid(getId()));
532 if (scs.getConfigState() == NetworkConfigState.ACCEPT_ADD) {
533 srConfig = (SegmentRouterConfig) scs.getSwitchConfig();
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700534 isEdgeRouter = srConfig.isEdgeRouter();
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700535 sid = srConfig.getNodeSid();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700536 } else {
537 log.error("Switch not configured as Segment-Router");
538 }
539
540 List<LinkConfig> linkConfigList = ncs.getConfiguredAllowedLinks();
541 setNeighbors(linkConfigList);
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700542
543 if (isEdgeRouter) {
544 List<SwitchConfig> switchList = ncs.getConfiguredAllowedSwitches();
545 getAllEdgeLabels(switchList);
546 }
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700547 }
548
549 private void populateTableVlan() throws IOException {
550 List<OFMessage> msglist = new ArrayList<OFMessage>();
551 for (OFPortDesc p : getPorts()) {
552 int pnum = p.getPortNo().getPortNumber();
553 if (U32.of(pnum).compareTo(U32.of(OFPort.MAX.getPortNumber())) < 1) {
554 OFOxmInPort oxp = factory.oxms().inPort(p.getPortNo());
555 OFOxmVlanVid oxv = factory.oxms()
556 .vlanVid(OFVlanVidMatch.UNTAGGED);
557 OFOxmList oxmList = OFOxmList.of(oxp, oxv);
558 OFMatchV3 match = factory.buildMatchV3()
559 .setOxmList(oxmList).build();
560
561 // TODO: match on vlan-tagged packets for vlans configured on
562 // subnet ports and strip-vlan
563
564 // Do not need to add vlans
565 /*int vlanid = getVlanConfig(pnum);
566 OFOxmVlanVid vidToSet = factory.oxms()
567 .vlanVid(OFVlanVidMatch.ofVlan(vlanid));
568 OFAction pushVlan = factory.actions().pushVlan(EthType.VLAN_FRAME);
569 OFAction setVlan = factory.actions().setField(vidToSet);
570 List<OFAction> actionlist = new ArrayList<OFAction>();
571 actionlist.add(pushVlan);
572 actionlist.add(setVlan);
573 OFInstruction appAction = factory.instructions().buildApplyActions()
574 .setActions(actionlist).build();*/
575
576 OFInstruction gotoTbl = factory.instructions().buildGotoTable()
577 .setTableId(TableId.of(TABLE_TMAC)).build();
578 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
579 // instructions.add(appAction);
580 instructions.add(gotoTbl);
581 OFMessage flowEntry = factory.buildFlowAdd()
582 .setTableId(TableId.of(TABLE_VLAN))
583 .setMatch(match)
584 .setInstructions(instructions)
585 .setPriority(1000) // does not matter - all rules
586 // exclusive
587 .setBufferId(OFBufferId.NO_BUFFER)
588 .setIdleTimeout(0)
589 .setHardTimeout(0)
590 .setXid(getNextTransactionId())
591 .build();
592 msglist.add(flowEntry);
593 }
594 }
595 write(msglist);
596 log.debug("Adding {} port/vlan-rules in sw {}", msglist.size(), getStringId());
597 }
598
599 private void populateTableTMac() throws IOException {
600 // match for router-mac and ip-packets
601 OFOxmEthType oxe = factory.oxms().ethType(EthType.IPv4);
602 OFOxmEthDst dmac = factory.oxms().ethDst(getRouterMacAddr());
603 OFOxmList oxmListIp = OFOxmList.of(dmac, oxe);
604 OFMatchV3 matchIp = factory.buildMatchV3()
605 .setOxmList(oxmListIp).build();
606 OFInstruction gotoTblIp = factory.instructions().buildGotoTable()
607 .setTableId(TableId.of(TABLE_IPv4_UNICAST)).build();
608 List<OFInstruction> instructionsIp = Collections.singletonList(gotoTblIp);
609 OFMessage ipEntry = factory.buildFlowAdd()
610 .setTableId(TableId.of(TABLE_TMAC))
611 .setMatch(matchIp)
612 .setInstructions(instructionsIp)
613 .setPriority(1000) // strict priority required lower than
614 // multicastMac
615 .setBufferId(OFBufferId.NO_BUFFER)
616 .setIdleTimeout(0)
617 .setHardTimeout(0)
618 .setXid(getNextTransactionId())
619 .build();
620
621 // match for router-mac and mpls packets
622 OFOxmEthType oxmpls = factory.oxms().ethType(EthType.MPLS_UNICAST);
623 OFOxmList oxmListMpls = OFOxmList.of(dmac, oxmpls);
624 OFMatchV3 matchMpls = factory.buildMatchV3()
625 .setOxmList(oxmListMpls).build();
626 OFInstruction gotoTblMpls = factory.instructions().buildGotoTable()
627 .setTableId(TableId.of(TABLE_MPLS)).build();
628 List<OFInstruction> instructionsMpls = Collections.singletonList(gotoTblMpls);
629 OFMessage mplsEntry = factory.buildFlowAdd()
630 .setTableId(TableId.of(TABLE_TMAC))
631 .setMatch(matchMpls)
632 .setInstructions(instructionsMpls)
633 .setPriority(1001) // strict priority required lower than
634 // multicastMac
635 .setBufferId(OFBufferId.NO_BUFFER)
636 .setIdleTimeout(0)
637 .setHardTimeout(0)
638 .setXid(getNextTransactionId())
639 .build();
640
641 log.debug("Adding termination-mac-rules in sw {}", getStringId());
642 List<OFMessage> msglist = new ArrayList<OFMessage>(2);
643 msglist.add(ipEntry);
644 msglist.add(mplsEntry);
645 write(msglist);
646 }
647
648 private MacAddress getRouterMacAddr() {
649 if (srConfig != null) {
650 return MacAddress.of(srConfig.getRouterMac());
651 } else {
652 // return a dummy mac address - it will not be used
653 return MacAddress.of("00:00:00:00:00:00");
654 }
655 }
656
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700657 private boolean isEdgeRouter(Dpid ndpid) {
658 INetworkConfigService ncs = floodlightProvider.getNetworkConfigService();
659 SwitchConfigStatus scs = ncs.checkSwitchConfig(ndpid);
660 if (scs.getConfigState() == NetworkConfigState.ACCEPT_ADD) {
661 return ((SegmentRouterConfig) scs.getSwitchConfig()).isEdgeRouter();
662 } else {
663 // TODO: return false if router not allowed
664 return false;
665 }
666 }
667
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700668 private MacAddress getNeighborRouterMacAddress(Dpid ndpid) {
669 INetworkConfigService ncs = floodlightProvider.getNetworkConfigService();
670 SwitchConfigStatus scs = ncs.checkSwitchConfig(ndpid);
671 if (scs.getConfigState() == NetworkConfigState.ACCEPT_ADD) {
672 return MacAddress.of(((SegmentRouterConfig) scs.getSwitchConfig())
673 .getRouterMac());
674 } else {
675 // return a dummy mac address - it will not be used
676 return MacAddress.of("00:00:00:00:00:00");
677 }
678 }
679
680 private void setNeighbors(List<LinkConfig> linkConfigList) {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700681 for (LinkConfig lg : linkConfigList) {
682 if (!lg.getType().equals(NetworkConfigManager.PKT_LINK)) {
Saurav Das80d17392014-10-01 10:24:56 -0700683 continue;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700684 }
685 PktLinkConfig plg = (PktLinkConfig) lg;
686 if (plg.getDpid1() == getId()) {
687 addNeighborAtPort(new Dpid(plg.getDpid2()),
688 PortNumber.uint32(plg.getPort1()));
689 } else if (plg.getDpid2() == getId()) {
690 addNeighborAtPort(new Dpid(plg.getDpid1()),
691 PortNumber.uint32(plg.getPort2()));
692 }
693 }
694 }
695
696 private void addNeighborAtPort(Dpid neighborDpid, PortNumber portToNeighbor) {
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700697 /* Update NeighborToPort database */
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700698 if (neighbors.get(neighborDpid) != null) {
699 neighbors.get(neighborDpid).add(portToNeighbor);
700 } else {
701 Set<PortNumber> ports = new HashSet<PortNumber>();
702 ports.add(portToNeighbor);
703 neighbors.put(neighborDpid, ports);
704 }
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700705
706 /* Update portToNeighbors database */
707 if (portToNeighbors.get(portToNeighbor) == null)
708 portToNeighbors.put(portToNeighbor, neighborDpid);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700709 }
710
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700711 private void getAllEdgeLabels(List<SwitchConfig> switchList) {
712 for (SwitchConfig sc : switchList) {
713 /* TODO: Do we need to check if the SwitchConfig is of
714 * type SegmentRouter?
715 */
716 if ((sc.getDpid() == getId()) ||
717 (((SegmentRouterConfig) sc).isEdgeRouter() != true)) {
718 continue;
719 }
720 edgeLabels.add(((SegmentRouterConfig) sc).getNodeSid());
721 }
Srikanth Vavilapallica2263c2014-10-09 15:19:11 -0700722 log.debug("getAllEdgeLabels: Node Labels found {}", edgeLabels);
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700723 }
724
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700725 private boolean isNodeLabelAndEdgeLabelSame(Dpid dpid, int edgeLabel) {
726 INetworkConfigService ncs = floodlightProvider.getNetworkConfigService();
727 SwitchConfigStatus scs = ncs.checkSwitchConfig(dpid);
728 if (scs.getConfigState() == NetworkConfigState.ACCEPT_ADD) {
729 return (((SegmentRouterConfig) scs.getSwitchConfig()).
730 getNodeSid() == edgeLabel);
731 } else {
732 // TODO: return false if router not allowed
733 return false;
734 }
735 }
736
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700737 private Set<Set<Dpid>> getAllNeighborSets(Set<Dpid> neighbors) {
738 List<Dpid> list = new ArrayList<Dpid>(neighbors);
739 Set<Set<Dpid>> sets = new HashSet<Set<Dpid>>();
740 /* get the number of elements in the neighbors */
741 int elements = list.size();
742 /* the number of members of a power set is 2^n
743 * including the empty set
744 */
745 int powerElements = (1 << elements);
746
747 /* run a binary counter for the number of power elements */
748 for (long i = 1; i < powerElements; i++) {
749 Set<Dpid> dpidSubSet = new HashSet<Dpid>();
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700750 for (int j = 0; j < elements; j++) {
751 if ((i >> j) % 2 == 1) {
752 dpidSubSet.add(list.get(j));
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700753 }
754 }
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700755 /* NOTE: Avoid any pairings of edge routers only
756 * at a backbone router */
757 boolean avoidEdgeRouterPairing = true;
758 if ((!isEdgeRouter) && (dpidSubSet.size() > 1)) {
Srikanth Vavilapalli696010f2014-10-08 17:00:17 -0700759 for (Dpid dpid : dpidSubSet) {
760 if (!isEdgeRouter(dpid)) {
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700761 avoidEdgeRouterPairing = false;
Srikanth Vavilapalli696010f2014-10-08 17:00:17 -0700762 break;
763 }
764 }
765 }
766 else
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700767 avoidEdgeRouterPairing = false;
Srikanth Vavilapalli696010f2014-10-08 17:00:17 -0700768
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700769 if (!avoidEdgeRouterPairing)
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700770 sets.add(dpidSubSet);
771 }
772 return sets;
773 }
774
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700775 /**
776 * createGroups creates ECMP groups for all ports on this router connected
777 * to other routers (in the OF network). The information for ports is
778 * gleaned from the configured links. If no links are configured no groups
779 * will be created, and it is up to the caller of the IOF13Switch API to
780 * create groups.
781 * <p>
782 * By default all ports connected to the same neighbor router will be part
783 * of the same ECMP group. In addition, groups will be created for all
784 * possible combinations of neighbor routers.
785 * <p>
786 * For example, consider this router (R0) connected to 3 neighbors (R1, R2,
787 * and R3). The following groups will be created in R0:
788 * <li>1) all ports to R1,
789 * <li>2) all ports to R2,
790 * <li>3) all ports to R3,
791 * <li>4) all ports to R1 and R2
792 * <li>5) all ports to R1 and R3
793 * <li>6) all ports to R2 and R3
794 * <li>7) all ports to R1, R2, and R3
795 */
796 private void createGroups() {
797 Set<Dpid> dpids = neighbors.keySet();
798 if (dpids == null || dpids.isEmpty()) {
799 return;
800 }
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700801 /* Create all possible Neighbor sets from this router
802 * NOTE: Avoid any pairings of edge routers only
803 */
804 Set<Set<Dpid>> powerSet = getAllNeighborSets(dpids);
Srikanth Vavilapallica2263c2014-10-09 15:19:11 -0700805 log.debug("The size of neighbor powerset for sw {} is ",
806 getStringId(), powerSet.size());
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700807 Set<NeighborSet> nsSet = new HashSet<NeighborSet>();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700808 for (Set<Dpid> combo : powerSet) {
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700809 if (combo.isEmpty())
810 continue;
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700811 if (isEdgeRouter && !edgeLabels.isEmpty()) {
812 for (Integer edgeLabel : edgeLabels) {
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700813 /* If it is local node's edge label, continue */
814 if (edgeLabel == sid)
815 continue;
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700816 NeighborSet ns = new NeighborSet();
817 ns.addDpids(combo);
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700818 /* Check if the edge label being set is of the
819 * same node in the Neighbor set
820 */
821 if ((combo.size() != 1) ||
822 (!isNodeLabelAndEdgeLabelSame(
823 combo.iterator().next(), edgeLabel))){
824 ns.setEdgeLabel(edgeLabel);
825 }
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700826 nsSet.add(ns);
827 }
828 } else {
829 NeighborSet ns = new NeighborSet();
830 ns.addDpids(combo);
831 nsSet.add(ns);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700832 }
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700833 }
Srikanth Vavilapallica2263c2014-10-09 15:19:11 -0700834 log.debug("The neighborset with label for sw {} is ",
835 getStringId(), nsSet);
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700836
837 int groupid = 1;
838 for (NeighborSet ns : nsSet) {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700839 List<BucketInfo> buckets = new ArrayList<BucketInfo>();
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700840 for (Dpid d : ns.getDpids()) {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700841 for (PortNumber sp : neighbors.get(d)) {
842 BucketInfo b = new BucketInfo(d,
843 MacAddress.of(srConfig.getRouterMac()),
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700844 getNeighborRouterMacAddress(d), sp,
845 ns.getEdgeLabel());
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700846 buckets.add(b);
Srikanth Vavilapallibd9b3e22014-10-02 08:57:46 -0700847
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700848 /* Update Port Neighborset map */
Srikanth Vavilapallibd9b3e22014-10-02 08:57:46 -0700849 ArrayList<NeighborSet> portNeighborSets =
850 portNeighborSetMap.get(sp);
851 if (portNeighborSets == null) {
852 portNeighborSets = new ArrayList<NeighborSet>();
853 portNeighborSets.add(ns);
854 portNeighborSetMap.put(sp, portNeighborSets);
855 }
856 else
857 portNeighborSets.add(ns);
858 }
859 }
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700860 EcmpInfo ecmpInfo = new EcmpInfo(groupid++, buckets);
861 setEcmpGroup(ecmpInfo);
862 ecmpGroups.put(ns, ecmpInfo);
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700863 log.debug("Creating ecmp group in sw {} for neighbor set {}: {}",
864 getStringId(), ns, ecmpInfo);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700865 }
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700866
867 // temp map of ecmp groupings
868 /* Map<NeighborSet, List<BucketInfo>> temp =
869 new HashMap<NeighborSet, List<BucketInfo>>();
870 */
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700871 }
872
873 private class EcmpInfo {
874 int groupId;
875 List<BucketInfo> buckets;
876
877 EcmpInfo(int gid, List<BucketInfo> bucketInfos) {
878 groupId = gid;
879 buckets = bucketInfos;
880 }
881
882 @Override
883 public String toString() {
884 return "groupId: " + groupId + ", buckets: " + buckets;
885 }
886 }
887
888 private class BucketInfo {
889 Dpid neighborDpid;
890 MacAddress srcMac;
891 MacAddress dstMac;
892 PortNumber outport;
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700893 int mplsLabel;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700894
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700895 BucketInfo(Dpid nDpid, MacAddress smac, MacAddress dmac,
896 PortNumber p, int label) {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700897 neighborDpid = nDpid;
898 srcMac = smac;
899 dstMac = dmac;
900 outport = p;
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700901 mplsLabel = label;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700902 }
903
904 @Override
905 public String toString() {
906 return " {neighborDpid: " + neighborDpid + ", dstMac: " + dstMac +
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700907 ", srcMac: " + srcMac + ", outport: " + outport +
908 "mplsLabel: " + mplsLabel + "}";
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700909 }
910 }
911
912 private void setEcmpGroup(EcmpInfo ecmpInfo) {
913 List<OFMessage> msglist = new ArrayList<OFMessage>();
914 OFGroup group = OFGroup.of(ecmpInfo.groupId);
915
916 List<OFBucket> buckets = new ArrayList<OFBucket>();
917 for (BucketInfo b : ecmpInfo.buckets) {
918 OFOxmEthDst dmac = factory.oxms()
919 .ethDst(b.dstMac);
920 OFAction setDA = factory.actions().buildSetField()
921 .setField(dmac).build();
Saurav Das0a344b02014-09-26 14:18:52 -0700922 OFOxmEthSrc smac = factory.oxms()
923 .ethSrc(b.srcMac);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700924 OFAction setSA = factory.actions().buildSetField()
925 .setField(smac).build();
926 OFAction outp = factory.actions().buildOutput()
927 .setPort(OFPort.of(b.outport.shortValue()))
928 .build();
929 List<OFAction> actions = new ArrayList<OFAction>();
930 actions.add(setSA);
931 actions.add(setDA);
932 actions.add(outp);
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700933 if (b.mplsLabel != -1) {
934 OFAction pushLabel = factory.actions().buildPushMpls()
935 .setEthertype(EthType.MPLS_UNICAST).build();
Sangho Shin62ce5c12014-10-08 16:24:40 -0700936 OFOxmMplsLabel lid = factory.oxms()
937 .mplsLabel(U32.of(b.mplsLabel));
938 OFAction setLabel = factory.actions().buildSetField()
939 .setField(lid).build();
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700940 OFAction copyTtl = factory.actions().copyTtlOut();
941 OFAction decrTtl = factory.actions().decMplsTtl();
942 actions.add(pushLabel);
943 actions.add(setLabel);
944 actions.add(copyTtl);
945 actions.add(decrTtl);
946 }
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700947 OFBucket ofb = factory.buildBucket()
948 .setWeight(1)
949 .setActions(actions)
950 .build();
951 buckets.add(ofb);
952 }
953
954 OFMessage gm = factory.buildGroupAdd()
955 .setGroup(group)
956 .setBuckets(buckets)
957 .setGroupType(OFGroupType.SELECT)
958 .setXid(getNextTransactionId())
959 .build();
960 msglist.add(gm);
961 try {
962 write(msglist);
963 } catch (IOException e) {
964 // TODO Auto-generated catch block
965 e.printStackTrace();
966 }
967 }
968
Srikanth Vavilapalli7d873fd2014-10-04 07:50:57 -0700969 private void modifyEcmpGroup(EcmpInfo ecmpInfo) {
970 List<OFMessage> msglist = new ArrayList<OFMessage>();
971 OFGroup group = OFGroup.of(ecmpInfo.groupId);
972
973 List<OFBucket> buckets = new ArrayList<OFBucket>();
974 for (BucketInfo b : ecmpInfo.buckets) {
975 OFOxmEthDst dmac = factory.oxms()
976 .ethDst(b.dstMac);
977 OFAction setDA = factory.actions().buildSetField()
978 .setField(dmac).build();
979 OFOxmEthSrc smac = factory.oxms()
980 .ethSrc(b.srcMac);
981 OFAction setSA = factory.actions().buildSetField()
982 .setField(smac).build();
983 OFAction outp = factory.actions().buildOutput()
984 .setPort(OFPort.of(b.outport.shortValue()))
985 .build();
986 List<OFAction> actions = new ArrayList<OFAction>();
987 actions.add(setSA);
988 actions.add(setDA);
989 actions.add(outp);
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700990 if (b.mplsLabel != -1) {
991 OFAction pushLabel = factory.actions().buildPushMpls()
992 .setEthertype(EthType.MPLS_UNICAST).build();
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700993 OFOxmMplsLabel lid = factory.oxms()
994 .mplsLabel(U32.of(b.mplsLabel));
995 OFAction setLabel = factory.actions().buildSetField()
996 .setField(lid).build();
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700997 OFAction copyTtl = factory.actions().copyTtlOut();
998 OFAction decrTtl = factory.actions().decMplsTtl();
999 actions.add(pushLabel);
1000 actions.add(setLabel);
1001 actions.add(copyTtl);
1002 actions.add(decrTtl);
1003 }
Srikanth Vavilapalli7d873fd2014-10-04 07:50:57 -07001004 OFBucket ofb = factory.buildBucket()
1005 .setWeight(1)
1006 .setActions(actions)
1007 .build();
1008 buckets.add(ofb);
1009 }
1010
1011 OFMessage gm = factory.buildGroupModify()
1012 .setGroup(group)
1013 .setBuckets(buckets)
1014 .setGroupType(OFGroupType.SELECT)
1015 .setXid(getNextTransactionId())
1016 .build();
1017 msglist.add(gm);
1018 try {
1019 write(msglist);
1020 } catch (IOException e) {
1021 // TODO Auto-generated catch block
1022 e.printStackTrace();
1023 }
1024 }
1025
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001026 private void verifyGroups() throws IOException {
1027 sendGroupDescRequest();
1028 }
1029
1030 private void sendGroupDescRequest() throws IOException {
1031 OFMessage gdr = factory.buildGroupDescStatsRequest()
1032 .setXid(getNextTransactionId())
1033 .build();
1034 write(gdr, null);
1035 }
1036
1037 private void assignAdjacencyLabels() {
1038 // TODO
1039 try {
1040 nextDriverState();
1041 } catch (IOException e) {
1042 // TODO Auto-generated catch block
1043 e.printStackTrace();
1044 }
1045 }
1046
Saurav Das1cd10152014-09-26 09:38:07 -07001047 private OFAction getOFAction(Action action) {
1048 OFAction ofAction = null;
1049 if (action instanceof OutputAction) {
1050 OutputAction outputAction = (OutputAction) action;
1051 OFPort port = OFPort.of((int) outputAction.getPortNumber().value());
1052 ofAction = factory.actions().output(port, Short.MAX_VALUE);
1053 } else if (action instanceof ModifyDstMacAction) {
1054 long dstMac = ((ModifyDstMacAction) action).getDstMac().toLong();
1055 OFOxmEthDst dmac = factory.oxms()
1056 .ethDst(MacAddress.of(dstMac));
1057 ofAction = factory.actions().buildSetField()
1058 .setField(dmac).build();
1059 } else if (action instanceof ModifySrcMacAction) {
1060 long srcMac = ((ModifySrcMacAction) action).getSrcMac().toLong();
1061 OFOxmEthSrc smac = factory.oxms()
1062 .ethSrc(MacAddress.of(srcMac));
1063 ofAction = factory.actions().buildSetField()
1064 .setField(smac).build();
Srikanth Vavilapalli68144302014-10-08 15:55:24 -07001065 /*} else if (action instanceof PushMplsAction) {
1066 ofAction = factory.actions().pushMpls(EthType.MPLS_UNICAST);
1067 } else if (action instanceof SetMplsIdAction) {
1068 int labelid = ((SetMplsIdAction) action).getMplsId();
1069 OFOxmMplsLabel lid = factory.oxms()
1070 .mplsLabel(U32.of(labelid));
1071 ofAction = factory.actions().buildSetField()
1072 .setField(lid).build();
1073 */} else if (action instanceof PopMplsAction) {
Saurav Das1cd10152014-09-26 09:38:07 -07001074 EthType ethertype = ((PopMplsAction) action).getEthType();
1075 ofAction = factory.actions().popMpls(ethertype);
1076 } else if (action instanceof GroupAction) {
1077 NeighborSet ns = ((GroupAction) action).getDpids();
1078 EcmpInfo ei = ecmpGroups.get(ns);
1079 if (ei != null) {
1080 int gid = ei.groupId;
1081 ofAction = factory.actions().buildGroup()
1082 .setGroup(OFGroup.of(gid))
1083 .build();
1084 } else {
1085 log.error("Unable to find ecmp group for neighbors {} at "
1086 + "switch {}", ns, getStringId());
1087 }
1088 } else if (action instanceof DecNwTtlAction) {
1089 ofAction = factory.actions().decNwTtl();
1090 } else if (action instanceof DecMplsTtlAction) {
1091 ofAction = factory.actions().decMplsTtl();
1092 } else if (action instanceof CopyTtlInAction) {
1093 ofAction = factory.actions().copyTtlIn();
1094 } else if (action instanceof CopyTtlOutAction) {
1095 ofAction = factory.actions().copyTtlOut();
1096 } else {
1097 log.warn("Unsupported Action type: {}", action.getClass().getName());
1098 return null;
1099 }
1100
1101 // not supported by loxigen
1102 // OFAction setBos =
1103 // factory.actions().buildSetField().setField(bos).build();
1104
1105 return ofAction;
1106 }
1107
Saurav Das0a344b02014-09-26 14:18:52 -07001108 private OFMessage getIpEntry(MatchActionOperationEntry mao) {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001109 MatchAction ma = mao.getTarget();
1110 Operator op = mao.getOperator();
1111 Ipv4Match ipm = (Ipv4Match) ma.getMatch();
1112
1113 // set match
1114 IPv4Net ipdst = ipm.getDestination();
1115 OFOxmEthType ethTypeIp = factory.oxms()
1116 .ethType(EthType.IPv4);
1117 OFOxmIpv4DstMasked ipPrefix = factory.oxms()
1118 .ipv4DstMasked(
1119 IPv4Address.of(ipdst.address().value()),
1120 IPv4Address.ofCidrMaskLength(ipdst.prefixLen())
1121 );
1122 OFOxmList oxmList = OFOxmList.of(ethTypeIp, ipPrefix);
1123 OFMatchV3 match = factory.buildMatchV3()
1124 .setOxmList(oxmList).build();
1125
1126 // set actions
1127 List<OFAction> writeActions = new ArrayList<OFAction>();
1128 for (Action action : ma.getActions()) {
Saurav Das1cd10152014-09-26 09:38:07 -07001129 OFAction ofAction = getOFAction(action);
1130 if (ofAction != null) {
1131 writeActions.add(ofAction);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001132 }
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001133 }
1134
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001135 // set instructions
1136 OFInstruction writeInstr = factory.instructions().buildWriteActions()
1137 .setActions(writeActions).build();
1138 OFInstruction gotoInstr = factory.instructions().buildGotoTable()
1139 .setTableId(TableId.of(TABLE_ACL)).build();
1140 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
1141 instructions.add(writeInstr);
1142 instructions.add(gotoInstr);
1143
Saurav Das1cd10152014-09-26 09:38:07 -07001144 // set flow priority to emulate longest prefix match
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001145 int priority = ipdst.prefixLen() * PRIORITY_MULTIPLIER;
1146 if (ipdst.prefixLen() == (short) 32) {
1147 priority = MAX_PRIORITY;
1148 }
1149
Saurav Dasbc594a42014-09-25 20:13:50 -07001150 // set flow-mod
Saurav Dase972b3a2014-09-26 15:41:06 -07001151 OFFlowMod.Builder fmBuilder = null;
1152 switch (op) {
1153 case ADD:
1154 fmBuilder = factory.buildFlowAdd();
1155 break;
1156 case REMOVE:
1157 fmBuilder = factory.buildFlowDeleteStrict();
1158 break;
Sangho Shin5be3e532014-10-03 17:20:58 -07001159 case MODIFY: // TODO
1160 fmBuilder = factory.buildFlowModifyStrict();
1161 break;
Saurav Dase972b3a2014-09-26 15:41:06 -07001162 default:
1163 log.warn("Unsupported MatchAction Operator: {}", op);
1164 return null;
Saurav Dasbc594a42014-09-25 20:13:50 -07001165 }
Saurav Dase972b3a2014-09-26 15:41:06 -07001166 OFMessage ipFlow = fmBuilder
1167 .setTableId(TableId.of(TABLE_IPv4_UNICAST))
1168 .setMatch(match)
1169 .setInstructions(instructions)
1170 .setPriority(priority)
1171 .setBufferId(OFBufferId.NO_BUFFER)
1172 .setIdleTimeout(0)
1173 .setHardTimeout(0)
1174 .setXid(getNextTransactionId())
1175 .build();
Saurav Dasbc594a42014-09-25 20:13:50 -07001176 log.debug("{} ip-rule {}-{} in sw {}",
1177 (op == MatchActionOperations.Operator.ADD) ? "Adding" : "Deleting",
1178 match, writeActions,
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001179 getStringId());
Saurav Das0a344b02014-09-26 14:18:52 -07001180 return ipFlow;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001181 }
1182
Saurav Das0a344b02014-09-26 14:18:52 -07001183 private OFMessage getMplsEntry(MatchActionOperationEntry mao) {
Saurav Das1cd10152014-09-26 09:38:07 -07001184 MatchAction ma = mao.getTarget();
1185 Operator op = mao.getOperator();
1186 MplsMatch mplsm = (MplsMatch) ma.getMatch();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001187
Saurav Das1cd10152014-09-26 09:38:07 -07001188 // set match
1189 OFOxmEthType ethTypeMpls = factory.oxms()
1190 .ethType(EthType.MPLS_UNICAST);
1191 OFOxmMplsLabel labelid = factory.oxms()
1192 .mplsLabel(U32.of(mplsm.getMplsLabel()));
1193 OFOxmList oxmList = OFOxmList.of(ethTypeMpls, labelid);
1194 OFMatchV3 matchlabel = factory.buildMatchV3()
1195 .setOxmList(oxmList).build();
1196
1197 // set actions
1198 List<OFAction> writeActions = new ArrayList<OFAction>();
1199 for (Action action : ma.getActions()) {
1200 OFAction ofAction = getOFAction(action);
1201 if (ofAction != null) {
1202 writeActions.add(ofAction);
1203 }
1204 }
1205
1206 // set instructions
1207 OFInstruction writeInstr = factory.instructions().buildWriteActions()
1208 .setActions(writeActions).build();
1209 OFInstruction gotoInstr = factory.instructions().buildGotoTable()
1210 .setTableId(TableId.of(TABLE_ACL)).build();
1211 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
1212 instructions.add(writeInstr);
1213 instructions.add(gotoInstr);
1214
Saurav Dase972b3a2014-09-26 15:41:06 -07001215 // set flow-mod
1216 OFFlowMod.Builder fmBuilder = null;
1217 switch (op) {
1218 case ADD:
1219 fmBuilder = factory.buildFlowAdd();
1220 break;
1221 case REMOVE:
1222 fmBuilder = factory.buildFlowDeleteStrict();
1223 break;
Sangho Shin5be3e532014-10-03 17:20:58 -07001224 case MODIFY: // TODO
1225 fmBuilder = factory.buildFlowModifyStrict();
1226 break;
Saurav Dase972b3a2014-09-26 15:41:06 -07001227 default:
1228 log.warn("Unsupported MatchAction Operator: {}", op);
1229 return null;
Saurav Das1cd10152014-09-26 09:38:07 -07001230 }
Saurav Dase972b3a2014-09-26 15:41:06 -07001231
1232 OFMessage mplsFlow = fmBuilder
1233 .setTableId(TableId.of(TABLE_MPLS))
1234 .setMatch(matchlabel)
1235 .setInstructions(instructions)
1236 .setPriority(MAX_PRIORITY) // exact match and exclusive
1237 .setBufferId(OFBufferId.NO_BUFFER)
1238 .setIdleTimeout(0)
1239 .setHardTimeout(0)
1240 .setXid(getNextTransactionId())
1241 .build();
Saurav Das1cd10152014-09-26 09:38:07 -07001242 log.debug("{} mpls-rule {}-{} in sw {}",
1243 (op == MatchActionOperations.Operator.ADD) ? "Adding" : "Deleting",
1244 matchlabel, writeActions,
1245 getStringId());
Saurav Das0a344b02014-09-26 14:18:52 -07001246 return mplsFlow;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001247 }
1248
Saurav Das0a344b02014-09-26 14:18:52 -07001249 private OFMessage getAclEntry(MatchActionOperationEntry mao) {
Saurav Dase972b3a2014-09-26 15:41:06 -07001250 MatchAction ma = mao.getTarget();
1251 Operator op = mao.getOperator();
1252 PacketMatch packetMatch = (PacketMatch) ma.getMatch();
1253 Builder matchBuilder = factory.buildMatch();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001254
Saurav Dase972b3a2014-09-26 15:41:06 -07001255 // set match
1256 int inport = 0;
1257 if (ma.getSwitchPort() != null) {
1258 inport = (int) ma.getSwitchPort().getPortNumber().value();
1259 }
1260 final MACAddress srcMac = packetMatch.getSrcMacAddress();
1261 final MACAddress dstMac = packetMatch.getDstMacAddress();
1262 final Short etherType = packetMatch.getEtherType();
1263 final IPv4Net srcIp = packetMatch.getSrcIpAddress();
1264 final IPv4Net dstIp = packetMatch.getDstIpAddress();
1265 final Byte ipProto = packetMatch.getIpProtocolNumber();
1266 final Short srcTcpPort = packetMatch.getSrcTcpPortNumber();
1267 final Short dstTcpPort = packetMatch.getDstTcpPortNumber();
1268 if (inport > 0) {
1269 matchBuilder.setExact(MatchField.IN_PORT,
1270 OFPort.of(inport));
1271 }
1272 if (srcMac != null) {
1273 matchBuilder.setExact(MatchField.ETH_SRC, MacAddress.of(srcMac.toLong()));
1274 }
1275 if (dstMac != null) {
1276 matchBuilder.setExact(MatchField.ETH_DST, MacAddress.of(dstMac.toLong()));
1277 }
1278 if (etherType != null) {
1279 matchBuilder.setExact(MatchField.ETH_TYPE, EthType.of(etherType));
1280 }
1281 if (srcIp != null) {
1282 matchBuilder.setMasked(MatchField.IPV4_SRC,
1283 IPv4Address.of(srcIp.address().value())
1284 .withMaskOfLength(srcIp.prefixLen()));
1285 }
1286 if (dstIp != null) {
1287 matchBuilder.setMasked(MatchField.IPV4_DST,
1288 IPv4Address.of(dstIp.address().value())
1289 .withMaskOfLength(dstIp.prefixLen()));
1290 }
1291 if (ipProto != null) {
1292 matchBuilder.setExact(MatchField.IP_PROTO, IpProtocol.of(ipProto));
1293 }
1294 if (srcTcpPort != null) {
1295 matchBuilder.setExact(MatchField.TCP_SRC, TransportPort.of(srcTcpPort));
1296 }
1297 if (dstTcpPort != null) {
1298 matchBuilder.setExact(MatchField.TCP_DST, TransportPort.of(dstTcpPort));
1299 }
1300
1301 // set actions
1302 List<OFAction> applyActions = new ArrayList<OFAction>();
1303 for (Action action : ma.getActions()) {
1304 OFAction ofAction = getOFAction(action);
1305 if (ofAction != null) {
1306 applyActions.add(ofAction);
1307 }
1308 }
1309
1310 // set instructions
1311 OFInstruction clearInstr = factory.instructions().clearActions();
1312 OFInstruction applyInstr = factory.instructions().buildApplyActions()
1313 .setActions(applyActions).build();
1314 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
1315 instructions.add(clearInstr);
1316 instructions.add(applyInstr);
1317
1318 // set flow-mod
1319 OFFlowMod.Builder fmBuilder = null;
1320 switch (op) {
1321 case ADD:
1322 fmBuilder = factory.buildFlowAdd();
1323 break;
1324 case REMOVE:
1325 fmBuilder = factory.buildFlowDeleteStrict();
1326 break;
Sangho Shin5be3e532014-10-03 17:20:58 -07001327 case MODIFY: // TODO
1328 fmBuilder = factory.buildFlowModifyStrict();
1329 break;
Saurav Dase972b3a2014-09-26 15:41:06 -07001330 default:
1331 log.warn("Unsupported MatchAction Operator: {}", op);
1332 return null;
1333 }
1334
1335 OFMessage aclFlow = fmBuilder
1336 .setTableId(TableId.of(TABLE_ACL))
1337 .setMatch(matchBuilder.build())
1338 .setInstructions(instructions)
1339 .setPriority(MAX_PRIORITY / 2) // TODO: wrong - should be MA
1340 // priority
1341 .setBufferId(OFBufferId.NO_BUFFER)
1342 .setIdleTimeout(0)
1343 .setHardTimeout(0)
1344 .setXid(getNextTransactionId())
1345 .build();
Saurav Das0a344b02014-09-26 14:18:52 -07001346 return aclFlow;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001347 }
1348
1349 // *****************************
1350 // IOF13Switch
1351 // *****************************
1352
1353 @Override
1354 public void pushFlow(MatchActionOperationEntry matchActionOp) throws IOException {
Saurav Das0a344b02014-09-26 14:18:52 -07001355 OFMessage ofm = getFlow(matchActionOp);
1356 if (ofm != null) {
1357 write(Collections.singletonList(ofm));
1358 }
1359 }
1360
1361 private OFMessage getFlow(MatchActionOperationEntry matchActionOp) {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001362 final MatchAction matchAction = matchActionOp.getTarget();
1363 final Match match = matchAction.getMatch();
1364 if (match instanceof Ipv4Match) {
Saurav Das0a344b02014-09-26 14:18:52 -07001365 return getIpEntry(matchActionOp);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001366 } else if (match instanceof MplsMatch) {
Saurav Das0a344b02014-09-26 14:18:52 -07001367 return getMplsEntry(matchActionOp);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001368 } else if (match instanceof PacketMatch) {
Saurav Das0a344b02014-09-26 14:18:52 -07001369 return getAclEntry(matchActionOp);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001370 } else {
1371 log.error("Unknown match type {} pushed to switch {}", match,
1372 getStringId());
1373 }
Saurav Das0a344b02014-09-26 14:18:52 -07001374 return null;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001375 }
1376
1377 @Override
1378 public void pushFlows(Collection<MatchActionOperationEntry> matchActionOps)
1379 throws IOException {
Saurav Das0a344b02014-09-26 14:18:52 -07001380 List<OFMessage> flowMods = new ArrayList<OFMessage>();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001381 for (MatchActionOperationEntry matchActionOp : matchActionOps) {
Saurav Das0a344b02014-09-26 14:18:52 -07001382 OFMessage ofm = getFlow(matchActionOp);
1383 if (ofm != null) {
1384 flowMods.add(ofm);
1385 }
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001386 }
Saurav Das0a344b02014-09-26 14:18:52 -07001387 write(flowMods);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001388 }
1389
1390 @Override
1391 public int getEcmpGroupId(NeighborSet ns) {
1392 EcmpInfo ei = ecmpGroups.get(ns);
1393 if (ei == null) {
1394 return -1;
1395 } else {
1396 return ei.groupId;
1397 }
1398 }
1399
1400 // *****************************
Saurav Das80d17392014-10-01 10:24:56 -07001401 // Unused
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001402 // *****************************
1403
Saurav Das80d17392014-10-01 10:24:56 -07001404 @SuppressWarnings("unused")
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001405 private void setAsyncConfig() throws IOException {
1406 List<OFMessage> msglist = new ArrayList<OFMessage>(3);
1407 OFMessage setAC = null;
1408
1409 if (role == Role.MASTER) {
1410 setAC = factory.buildAsyncSet()
1411 .setFlowRemovedMaskEqualMaster(SET_FLOW_REMOVED_MASK_MASTER)
1412 .setPacketInMaskEqualMaster(SET_PACKET_IN_MASK_MASTER)
1413 .setPortStatusMaskEqualMaster(SET_PORT_STATUS_MASK_MASTER)
1414 .setFlowRemovedMaskSlave(SET_ALL_SLAVE)
1415 .setPacketInMaskSlave(SET_ALL_SLAVE)
1416 .setPortStatusMaskSlave(SET_ALL_SLAVE)
1417 .setXid(getNextTransactionId())
1418 .build();
1419 } else if (role == Role.EQUAL) {
1420 setAC = factory.buildAsyncSet()
1421 .setFlowRemovedMaskEqualMaster(SET_FLOW_REMOVED_MASK_EQUAL)
1422 .setPacketInMaskEqualMaster(SET_PACKET_IN_MASK_EQUAL)
1423 .setPortStatusMaskEqualMaster(SET_PORT_STATUS_MASK_EQUAL)
1424 .setFlowRemovedMaskSlave(SET_ALL_SLAVE)
1425 .setPacketInMaskSlave(SET_ALL_SLAVE)
1426 .setPortStatusMaskSlave(SET_ALL_SLAVE)
1427 .setXid(getNextTransactionId())
1428 .build();
1429 }
1430 msglist.add(setAC);
1431
1432 OFMessage br = factory.buildBarrierRequest()
1433 .setXid(getNextTransactionId())
1434 .build();
1435 msglist.add(br);
1436
1437 OFMessage getAC = factory.buildAsyncGetRequest()
1438 .setXid(getNextTransactionId())
1439 .build();
1440 msglist.add(getAC);
1441
1442 write(msglist);
1443 }
1444
Saurav Das80d17392014-10-01 10:24:56 -07001445 @SuppressWarnings("unused")
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001446 private void decodeAsyncGetReply(OFAsyncGetReply rep) {
1447 long frm = rep.getFlowRemovedMaskEqualMaster();
Sangho Shin01bca862014-09-12 11:18:59 -07001448 long frs = rep.getFlowRemovedMaskSlave();
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001449 long pim = rep.getPacketInMaskEqualMaster();
Sangho Shin01bca862014-09-12 11:18:59 -07001450 long pis = rep.getPacketInMaskSlave();
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001451 long psm = rep.getPortStatusMaskEqualMaster();
Sangho Shin01bca862014-09-12 11:18:59 -07001452 long pss = rep.getPortStatusMaskSlave();
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001453
1454 if (role == Role.MASTER || role == Role.EQUAL) { // should separate
1455 log.info("FRM:{}", HexString.toHexString((frm & TEST_FLOW_REMOVED_MASK)));
1456 log.info("PIM:{}", HexString.toHexString((pim & TEST_PACKET_IN_MASK)));
1457 log.info("PSM:{}", HexString.toHexString((psm & TEST_PORT_STATUS_MASK)));
1458 }
1459
1460 }
1461
Saurav Das80d17392014-10-01 10:24:56 -07001462 @SuppressWarnings("unused")
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001463 private void getTableFeatures() throws IOException {
1464 OFMessage gtf = factory.buildTableFeaturesStatsRequest()
1465 .setXid(getNextTransactionId())
1466 .build();
1467 write(gtf, null);
1468 }
1469
Saurav Das80d17392014-10-01 10:24:56 -07001470 @SuppressWarnings("unused")
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001471 private void sendGroupFeaturesRequest() throws IOException {
1472 OFMessage gfr = factory.buildGroupFeaturesStatsRequest()
1473 .setXid(getNextTransactionId())
1474 .build();
1475 write(gfr, null);
1476 }
1477
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001478 private void processGroupFeatures(OFGroupFeaturesStatsReply gfsr) {
1479 log.info("Sw: {} Group Features {}", getStringId(), gfsr);
1480 }
1481
Fahad Naeem Khand563af62014-10-08 17:37:25 -07001482 @Override
1483 public TableId getTableId(String tableType) {
1484 tableType = tableType.toLowerCase();
1485 if(tableType.contentEquals("ip")){
1486 return TableId.of(OFSwitchImplCPqD13.TABLE_IPv4_UNICAST);
1487 }
1488 else if (tableType.contentEquals("mpls")){
1489 return TableId.of(OFSwitchImplCPqD13.TABLE_MPLS);
1490 }
1491 else if (tableType.contentEquals("acl")){
1492 return TableId.of(OFSwitchImplCPqD13.TABLE_ACL);
1493 }
1494 else{
1495 log.warn("Invalid tableType: {}", tableType);
1496 return null;
1497 }
1498 }
1499
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001500}