blob: 968f96041c74c860c0d3e24c541d8c46cb076d1c [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 Vavilapallibb47e782014-10-09 18:16:35 -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) {
Srikanth Vavilapallicf1840b2014-10-09 15:29:51 -0700216 /* FIX: removePortFromGroups is not working */
217
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700218 log.debug("removePortFromGroups: Remove port {} from Switch {}",
219 port, getStringId());
220 ArrayList<NeighborSet> portNSSet = portNeighborSetMap.get(port);
221 if (portNSSet == null)
222 {
223 /* No Groups are created with this port yet */
224 log.warn("removePortFromGroups: No groups exist with Switch {} port {}",
Srikanth Vavilapallicf1840b2014-10-09 15:29:51 -0700225 getStringId(), port);
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700226 return;
227 }
228 log.debug("removePortFromGroups: Neighborsets that the port {} is part"
229 + "of on Switch {} are {}",
230 port, getStringId(), portNSSet);
231
232 for (NeighborSet ns : portNSSet) {
233 /* Delete the first matched bucket */
234 EcmpInfo portEcmpInfo = ecmpGroups.get(ns);
235 Iterator<BucketInfo> it = portEcmpInfo.buckets.iterator();
236 while (it.hasNext()) {
237 BucketInfo bucket = it.next();
238 if (bucket.outport.equals(port)) {
239 it.remove();
Srikanth Vavilapallibd9b3e22014-10-02 08:57:46 -0700240 }
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700241 }
242 log.debug("removePortFromGroups: Modifying Group on Switch {} "
243 + "and Neighborset {} with {}",
244 getStringId(), ns, portEcmpInfo);
245 modifyEcmpGroup(portEcmpInfo);
246 }
247 /* Don't delete the entry from portNeighborSetMap because
Srikanth Vavilapallicf1840b2014-10-09 15:29:51 -0700248 * when the port is up again this info is needed
249 */
Srikanth Vavilapalli7d873fd2014-10-04 07:50:57 -0700250 return;
Srikanth Vavilapallibd9b3e22014-10-02 08:57:46 -0700251 }
252
253 public void addPortToGroups(PortNumber port) {
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700254 log.debug("addPortToGroups: Add port {} to Switch {}",
255 port, getStringId());
256 ArrayList<NeighborSet> portNSSet = portNeighborSetMap.get(port);
257 if (portNSSet == null) {
258 /* Unknown Port */
259 log.warn("addPortToGroups: Switch {} port {} is unknown",
Srikanth Vavilapallicf1840b2014-10-09 15:29:51 -0700260 getStringId(), port);
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700261 return;
262 }
263 log.debug("addPortToGroups: Neighborsets that the port {} is part"
264 + "of on Switch {} are {}",
265 port, getStringId(), portNSSet);
266
267 Dpid neighborDpid = portToNeighbors.get(port);
268 for (NeighborSet ns : portNSSet) {
269 /* Delete the first matched bucket */
270 EcmpInfo portEcmpInfo = ecmpGroups.get(ns);
271 BucketInfo b = new BucketInfo(neighborDpid,
Srikanth Vavilapallicf1840b2014-10-09 15:29:51 -0700272 MacAddress.of(srConfig.getRouterMac()),
273 getNeighborRouterMacAddress(neighborDpid),
274 port,
275 ns.getEdgeLabel());
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700276 List<BucketInfo> buckets = portEcmpInfo.buckets;
277 if (buckets == null) {
278 buckets = new ArrayList<BucketInfo>();
279 buckets.add(b);
280 portEcmpInfo.buckets = buckets;
281 } else {
282 buckets.add(b);
283 }
284 log.debug("addPortToGroups: Modifying Group on Switch {} "
285 + "and Neighborset {} with {}",
286 getStringId(), ns, portEcmpInfo);
287 modifyEcmpGroup(portEcmpInfo);
288 }
289 return;
Srikanth Vavilapallibd9b3e22014-10-02 08:57:46 -0700290 }
291
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700292 // *****************************
293 // Driver handshake state-machine
294 // *****************************
295
296 enum DriverState {
297 INIT,
298 SET_TABLE_MISS_ENTRIES,
299 SET_TABLE_VLAN_TMAC,
300 SET_GROUPS,
301 VERIFY_GROUPS,
302 SET_ADJACENCY_LABELS,
303 EXIT
304 }
305
306 protected void nextDriverState() throws IOException {
307 DriverState currentState = driverState;
Saurav Das80d17392014-10-01 10:24:56 -0700308 if (haltStateMachine.get()) {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700309 return;
Saurav Das80d17392014-10-01 10:24:56 -0700310 }
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700311 switch (currentState) {
312 case INIT:
313 driverState = DriverState.SET_TABLE_MISS_ENTRIES;
314 setTableMissEntries();
Saurav Dasd84178f2014-09-29 17:48:54 -0700315 sendHandshakeBarrier();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700316 break;
317 case SET_TABLE_MISS_ENTRIES:
318 driverState = DriverState.SET_TABLE_VLAN_TMAC;
319 getNetworkConfig();
320 populateTableVlan();
321 populateTableTMac();
Saurav Dasd84178f2014-09-29 17:48:54 -0700322 sendHandshakeBarrier();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700323 break;
324 case SET_TABLE_VLAN_TMAC:
325 driverState = DriverState.SET_GROUPS;
326 createGroups();
Saurav Dasd84178f2014-09-29 17:48:54 -0700327 sendHandshakeBarrier();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700328 break;
329 case SET_GROUPS:
330 driverState = DriverState.VERIFY_GROUPS;
331 verifyGroups();
332 break;
333 case VERIFY_GROUPS:
334 driverState = DriverState.SET_ADJACENCY_LABELS;
335 assignAdjacencyLabels();
336 break;
337 case SET_ADJACENCY_LABELS:
338 driverState = DriverState.EXIT;
339 driverHandshakeComplete.set(true);
340 break;
341 case EXIT:
342 default:
343 driverState = DriverState.EXIT;
344 log.error("Driver handshake has exited for sw: {}", getStringId());
345 }
346 }
347
348 void processOFMessage(IOFSwitch sw, OFMessage m) throws IOException {
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700349 switch (m.getType()) {
350 case BARRIER_REPLY:
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700351 processBarrierReply(m);
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700352 break;
353
354 case ERROR:
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700355 processErrorMessage(m);
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700356 break;
357
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700358 case GET_ASYNC_REPLY:
359 OFAsyncGetReply asrep = (OFAsyncGetReply) m;
360 decodeAsyncGetReply(asrep);
361 break;
362
363 case PACKET_IN:
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700364 // not ready to handle packet-ins
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700365 break;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700366
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700367 case QUEUE_GET_CONFIG_REPLY:
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700368 // not doing queue config yet
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700369 break;
370
371 case STATS_REPLY:
372 processStatsReply((OFStatsReply) m);
373 break;
374
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700375 case ROLE_REPLY: // channelHandler should handle this
376 case PORT_STATUS: // channelHandler should handle this
377 case FEATURES_REPLY: // don't care
378 case FLOW_REMOVED: // don't care
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700379 default:
380 log.debug("Received message {} during switch-driver subhandshake "
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700381 + "from switch {} ... Ignoring message", m, sw.getStringId());
382 }
383 }
384
385 private void processStatsReply(OFStatsReply sr) {
386 switch (sr.getStatsType()) {
387 case AGGREGATE:
388 break;
389 case DESC:
390 break;
391 case EXPERIMENTER:
392 break;
393 case FLOW:
394 break;
395 case GROUP_DESC:
396 processGroupDesc((OFGroupDescStatsReply) sr);
397 break;
398 case GROUP_FEATURES:
399 processGroupFeatures((OFGroupFeaturesStatsReply) sr);
400 break;
401 case METER_CONFIG:
402 break;
403 case METER_FEATURES:
404 break;
405 case PORT_DESC:
406 break;
407 case TABLE_FEATURES:
408 break;
409 default:
410 break;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700411
412 }
413 }
414
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700415 private void processErrorMessage(OFMessage m) {
416 log.error("Switch {} Error {} in DriverState", getStringId(),
417 (OFErrorMsg) m, driverState);
418 }
419
420 private void processBarrierReply(OFMessage m) throws IOException {
421 if (m.getXid() == barrierXidToWaitFor) {
422 // Driver state-machine progresses to the next state.
423 // If Barrier messages is not received, then eventually
424 // the ChannelHandler state machine will timeout, and the switch
425 // will be disconnected.
426 nextDriverState();
427 } else {
428 log.error("Received incorrect barrier-message xid {} (expected: {}) in "
429 + "switch-driver state {} for switch {}", m, barrierXidToWaitFor,
430 driverState, getStringId());
431 }
432 }
433
434 private void processGroupDesc(OFGroupDescStatsReply gdsr) {
435 log.info("Sw: {} Group Desc {}", getStringId(), gdsr);
436 try {
437 nextDriverState();
438 } catch (IOException e) {
439 // TODO Auto-generated catch block
440 e.printStackTrace();
441 }
442 }
443
444 // *****************************
445 // Utility methods
446 // *****************************
447
448 void setTableMissEntries() throws IOException {
449 // set all table-miss-entries
450 populateTableMissEntry(TABLE_VLAN, true, false, false, -1);
451 populateTableMissEntry(TABLE_TMAC, true, false, false, -1);
452 populateTableMissEntry(TABLE_IPv4_UNICAST, false, true, true,
453 TABLE_ACL);
454 populateTableMissEntry(TABLE_MPLS, false, true, true,
455 TABLE_ACL);
456 populateTableMissEntry(TABLE_ACL, false, false, false, -1);
457 }
458
Saurav Dasd84178f2014-09-29 17:48:54 -0700459 private void sendHandshakeBarrier() throws IOException {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700460 long xid = getNextTransactionId();
461 barrierXidToWaitFor = xid;
462 OFBarrierRequest br = getFactory()
463 .buildBarrierRequest()
464 .setXid(xid)
465 .build();
466 write(br, null);
467 }
468
469 /**
470 * Adds a table-miss-entry to a pipeline table.
471 * <p>
472 * The table-miss-entry can be added with 'write-actions' or
473 * 'apply-actions'. It can also add a 'goto-table' instruction. By default
474 * if none of the booleans in the call are set, then the table-miss entry is
475 * added with no instructions, which means that if a packet hits the
476 * table-miss-entry, pipeline execution will stop, and the action set
477 * associated with the packet will be executed.
478 *
479 * @param tableToAdd the table to where the table-miss-entry will be added
480 * @param toControllerNow as an APPLY_ACTION instruction
481 * @param toControllerWrite as a WRITE_ACTION instruction
482 * @param toTable as a GOTO_TABLE instruction
483 * @param tableToSend the table to send as per the GOTO_TABLE instruction it
484 * needs to be set if 'toTable' is true. Ignored of 'toTable' is
485 * false.
486 * @throws IOException
487 */
488 @SuppressWarnings("unchecked")
489 private void populateTableMissEntry(int tableToAdd, boolean toControllerNow,
490 boolean toControllerWrite,
491 boolean toTable, int tableToSend) throws IOException {
492 OFOxmList oxmList = OFOxmList.EMPTY;
493 OFMatchV3 match = factory.buildMatchV3()
494 .setOxmList(oxmList)
495 .build();
496 OFAction outc = factory.actions()
497 .buildOutput()
498 .setPort(OFPort.CONTROLLER)
499 .setMaxLen(OFPCML_NO_BUFFER)
500 .build();
501 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
502 if (toControllerNow) {
503 // table-miss instruction to send to controller immediately
504 OFInstruction instr = factory.instructions()
505 .buildApplyActions()
506 .setActions(Collections.singletonList(outc))
507 .build();
508 instructions.add(instr);
509 }
510
511 if (toControllerWrite) {
512 // table-miss instruction to write-action to send to controller
513 // this will be executed whenever the action-set gets executed
514 OFInstruction instr = factory.instructions()
515 .buildWriteActions()
516 .setActions(Collections.singletonList(outc))
517 .build();
518 instructions.add(instr);
519 }
520
521 if (toTable) {
522 // table-miss instruction to goto-table x
523 OFInstruction instr = factory.instructions()
524 .gotoTable(TableId.of(tableToSend));
525 instructions.add(instr);
526 }
527
528 if (!toControllerNow && !toControllerWrite && !toTable) {
529 // table-miss has no instruction - at which point action-set will be
530 // executed - if there is an action to output/group in the action
531 // set
532 // the packet will be sent there, otherwise it will be dropped.
533 instructions = (List<OFInstruction>) Collections.EMPTY_LIST;
534 }
535
536 OFMessage tableMissEntry = factory.buildFlowAdd()
537 .setTableId(TableId.of(tableToAdd))
538 .setMatch(match) // match everything
539 .setInstructions(instructions)
540 .setPriority(MIN_PRIORITY)
541 .setBufferId(OFBufferId.NO_BUFFER)
542 .setIdleTimeout(0)
543 .setHardTimeout(0)
544 .setXid(getNextTransactionId())
545 .build();
546 write(tableMissEntry, null);
547 }
548
549 private void getNetworkConfig() {
550 INetworkConfigService ncs = floodlightProvider.getNetworkConfigService();
551 SwitchConfigStatus scs = ncs.checkSwitchConfig(new Dpid(getId()));
552 if (scs.getConfigState() == NetworkConfigState.ACCEPT_ADD) {
553 srConfig = (SegmentRouterConfig) scs.getSwitchConfig();
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700554 isEdgeRouter = srConfig.isEdgeRouter();
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700555 sid = srConfig.getNodeSid();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700556 } else {
557 log.error("Switch not configured as Segment-Router");
558 }
559
560 List<LinkConfig> linkConfigList = ncs.getConfiguredAllowedLinks();
561 setNeighbors(linkConfigList);
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700562
563 if (isEdgeRouter) {
564 List<SwitchConfig> switchList = ncs.getConfiguredAllowedSwitches();
565 getAllEdgeLabels(switchList);
566 }
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700567 }
568
569 private void populateTableVlan() throws IOException {
570 List<OFMessage> msglist = new ArrayList<OFMessage>();
571 for (OFPortDesc p : getPorts()) {
572 int pnum = p.getPortNo().getPortNumber();
573 if (U32.of(pnum).compareTo(U32.of(OFPort.MAX.getPortNumber())) < 1) {
574 OFOxmInPort oxp = factory.oxms().inPort(p.getPortNo());
575 OFOxmVlanVid oxv = factory.oxms()
576 .vlanVid(OFVlanVidMatch.UNTAGGED);
577 OFOxmList oxmList = OFOxmList.of(oxp, oxv);
578 OFMatchV3 match = factory.buildMatchV3()
579 .setOxmList(oxmList).build();
580
581 // TODO: match on vlan-tagged packets for vlans configured on
582 // subnet ports and strip-vlan
583
584 // Do not need to add vlans
585 /*int vlanid = getVlanConfig(pnum);
586 OFOxmVlanVid vidToSet = factory.oxms()
587 .vlanVid(OFVlanVidMatch.ofVlan(vlanid));
588 OFAction pushVlan = factory.actions().pushVlan(EthType.VLAN_FRAME);
589 OFAction setVlan = factory.actions().setField(vidToSet);
590 List<OFAction> actionlist = new ArrayList<OFAction>();
591 actionlist.add(pushVlan);
592 actionlist.add(setVlan);
593 OFInstruction appAction = factory.instructions().buildApplyActions()
594 .setActions(actionlist).build();*/
595
596 OFInstruction gotoTbl = factory.instructions().buildGotoTable()
597 .setTableId(TableId.of(TABLE_TMAC)).build();
598 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
599 // instructions.add(appAction);
600 instructions.add(gotoTbl);
601 OFMessage flowEntry = factory.buildFlowAdd()
602 .setTableId(TableId.of(TABLE_VLAN))
603 .setMatch(match)
604 .setInstructions(instructions)
605 .setPriority(1000) // does not matter - all rules
606 // exclusive
607 .setBufferId(OFBufferId.NO_BUFFER)
608 .setIdleTimeout(0)
609 .setHardTimeout(0)
610 .setXid(getNextTransactionId())
611 .build();
612 msglist.add(flowEntry);
613 }
614 }
615 write(msglist);
616 log.debug("Adding {} port/vlan-rules in sw {}", msglist.size(), getStringId());
617 }
618
619 private void populateTableTMac() throws IOException {
620 // match for router-mac and ip-packets
621 OFOxmEthType oxe = factory.oxms().ethType(EthType.IPv4);
622 OFOxmEthDst dmac = factory.oxms().ethDst(getRouterMacAddr());
623 OFOxmList oxmListIp = OFOxmList.of(dmac, oxe);
624 OFMatchV3 matchIp = factory.buildMatchV3()
625 .setOxmList(oxmListIp).build();
626 OFInstruction gotoTblIp = factory.instructions().buildGotoTable()
627 .setTableId(TableId.of(TABLE_IPv4_UNICAST)).build();
628 List<OFInstruction> instructionsIp = Collections.singletonList(gotoTblIp);
629 OFMessage ipEntry = factory.buildFlowAdd()
630 .setTableId(TableId.of(TABLE_TMAC))
631 .setMatch(matchIp)
632 .setInstructions(instructionsIp)
633 .setPriority(1000) // 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 // match for router-mac and mpls packets
642 OFOxmEthType oxmpls = factory.oxms().ethType(EthType.MPLS_UNICAST);
643 OFOxmList oxmListMpls = OFOxmList.of(dmac, oxmpls);
644 OFMatchV3 matchMpls = factory.buildMatchV3()
645 .setOxmList(oxmListMpls).build();
646 OFInstruction gotoTblMpls = factory.instructions().buildGotoTable()
647 .setTableId(TableId.of(TABLE_MPLS)).build();
648 List<OFInstruction> instructionsMpls = Collections.singletonList(gotoTblMpls);
649 OFMessage mplsEntry = factory.buildFlowAdd()
650 .setTableId(TableId.of(TABLE_TMAC))
651 .setMatch(matchMpls)
652 .setInstructions(instructionsMpls)
653 .setPriority(1001) // strict priority required lower than
654 // multicastMac
655 .setBufferId(OFBufferId.NO_BUFFER)
656 .setIdleTimeout(0)
657 .setHardTimeout(0)
658 .setXid(getNextTransactionId())
659 .build();
660
661 log.debug("Adding termination-mac-rules in sw {}", getStringId());
662 List<OFMessage> msglist = new ArrayList<OFMessage>(2);
663 msglist.add(ipEntry);
664 msglist.add(mplsEntry);
665 write(msglist);
666 }
667
668 private MacAddress getRouterMacAddr() {
669 if (srConfig != null) {
670 return MacAddress.of(srConfig.getRouterMac());
671 } else {
672 // return a dummy mac address - it will not be used
673 return MacAddress.of("00:00:00:00:00:00");
674 }
675 }
676
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700677 private boolean isEdgeRouter(Dpid ndpid) {
678 INetworkConfigService ncs = floodlightProvider.getNetworkConfigService();
679 SwitchConfigStatus scs = ncs.checkSwitchConfig(ndpid);
680 if (scs.getConfigState() == NetworkConfigState.ACCEPT_ADD) {
681 return ((SegmentRouterConfig) scs.getSwitchConfig()).isEdgeRouter();
682 } else {
683 // TODO: return false if router not allowed
684 return false;
685 }
686 }
687
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700688 private MacAddress getNeighborRouterMacAddress(Dpid ndpid) {
689 INetworkConfigService ncs = floodlightProvider.getNetworkConfigService();
690 SwitchConfigStatus scs = ncs.checkSwitchConfig(ndpid);
691 if (scs.getConfigState() == NetworkConfigState.ACCEPT_ADD) {
692 return MacAddress.of(((SegmentRouterConfig) scs.getSwitchConfig())
693 .getRouterMac());
694 } else {
695 // return a dummy mac address - it will not be used
696 return MacAddress.of("00:00:00:00:00:00");
697 }
698 }
699
700 private void setNeighbors(List<LinkConfig> linkConfigList) {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700701 for (LinkConfig lg : linkConfigList) {
702 if (!lg.getType().equals(NetworkConfigManager.PKT_LINK)) {
Saurav Das80d17392014-10-01 10:24:56 -0700703 continue;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700704 }
705 PktLinkConfig plg = (PktLinkConfig) lg;
706 if (plg.getDpid1() == getId()) {
707 addNeighborAtPort(new Dpid(plg.getDpid2()),
708 PortNumber.uint32(plg.getPort1()));
709 } else if (plg.getDpid2() == getId()) {
710 addNeighborAtPort(new Dpid(plg.getDpid1()),
711 PortNumber.uint32(plg.getPort2()));
712 }
713 }
714 }
715
716 private void addNeighborAtPort(Dpid neighborDpid, PortNumber portToNeighbor) {
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700717 /* Update NeighborToPort database */
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700718 if (neighbors.get(neighborDpid) != null) {
719 neighbors.get(neighborDpid).add(portToNeighbor);
720 } else {
721 Set<PortNumber> ports = new HashSet<PortNumber>();
722 ports.add(portToNeighbor);
723 neighbors.put(neighborDpid, ports);
724 }
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700725
726 /* Update portToNeighbors database */
727 if (portToNeighbors.get(portToNeighbor) == null)
728 portToNeighbors.put(portToNeighbor, neighborDpid);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700729 }
730
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700731 private void getAllEdgeLabels(List<SwitchConfig> switchList) {
732 for (SwitchConfig sc : switchList) {
733 /* TODO: Do we need to check if the SwitchConfig is of
734 * type SegmentRouter?
735 */
736 if ((sc.getDpid() == getId()) ||
737 (((SegmentRouterConfig) sc).isEdgeRouter() != true)) {
738 continue;
739 }
740 edgeLabels.add(((SegmentRouterConfig) sc).getNodeSid());
741 }
Srikanth Vavilapallica2263c2014-10-09 15:19:11 -0700742 log.debug("getAllEdgeLabels: Node Labels found {}", edgeLabels);
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700743 }
744
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700745 private boolean isNodeLabelAndEdgeLabelSame(Dpid dpid, int edgeLabel) {
746 INetworkConfigService ncs = floodlightProvider.getNetworkConfigService();
747 SwitchConfigStatus scs = ncs.checkSwitchConfig(dpid);
748 if (scs.getConfigState() == NetworkConfigState.ACCEPT_ADD) {
749 return (((SegmentRouterConfig) scs.getSwitchConfig()).
750 getNodeSid() == edgeLabel);
751 } else {
752 // TODO: return false if router not allowed
753 return false;
754 }
755 }
756
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700757 private Set<Set<Dpid>> getAllNeighborSets(Set<Dpid> neighbors) {
758 List<Dpid> list = new ArrayList<Dpid>(neighbors);
759 Set<Set<Dpid>> sets = new HashSet<Set<Dpid>>();
760 /* get the number of elements in the neighbors */
761 int elements = list.size();
762 /* the number of members of a power set is 2^n
763 * including the empty set
764 */
765 int powerElements = (1 << elements);
766
767 /* run a binary counter for the number of power elements */
768 for (long i = 1; i < powerElements; i++) {
769 Set<Dpid> dpidSubSet = new HashSet<Dpid>();
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700770 for (int j = 0; j < elements; j++) {
771 if ((i >> j) % 2 == 1) {
772 dpidSubSet.add(list.get(j));
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700773 }
774 }
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700775 /* NOTE: Avoid any pairings of edge routers only
776 * at a backbone router */
777 boolean avoidEdgeRouterPairing = true;
778 if ((!isEdgeRouter) && (dpidSubSet.size() > 1)) {
Srikanth Vavilapalli696010f2014-10-08 17:00:17 -0700779 for (Dpid dpid : dpidSubSet) {
780 if (!isEdgeRouter(dpid)) {
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700781 avoidEdgeRouterPairing = false;
Srikanth Vavilapalli696010f2014-10-08 17:00:17 -0700782 break;
783 }
784 }
785 }
786 else
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700787 avoidEdgeRouterPairing = false;
Srikanth Vavilapalli696010f2014-10-08 17:00:17 -0700788
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700789 if (!avoidEdgeRouterPairing)
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700790 sets.add(dpidSubSet);
791 }
792 return sets;
793 }
794
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700795 /**
796 * createGroups creates ECMP groups for all ports on this router connected
797 * to other routers (in the OF network). The information for ports is
798 * gleaned from the configured links. If no links are configured no groups
799 * will be created, and it is up to the caller of the IOF13Switch API to
800 * create groups.
801 * <p>
802 * By default all ports connected to the same neighbor router will be part
803 * of the same ECMP group. In addition, groups will be created for all
804 * possible combinations of neighbor routers.
805 * <p>
806 * For example, consider this router (R0) connected to 3 neighbors (R1, R2,
807 * and R3). The following groups will be created in R0:
808 * <li>1) all ports to R1,
809 * <li>2) all ports to R2,
810 * <li>3) all ports to R3,
811 * <li>4) all ports to R1 and R2
812 * <li>5) all ports to R1 and R3
813 * <li>6) all ports to R2 and R3
814 * <li>7) all ports to R1, R2, and R3
815 */
816 private void createGroups() {
817 Set<Dpid> dpids = neighbors.keySet();
818 if (dpids == null || dpids.isEmpty()) {
819 return;
820 }
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700821 /* Create all possible Neighbor sets from this router
822 * NOTE: Avoid any pairings of edge routers only
823 */
824 Set<Set<Dpid>> powerSet = getAllNeighborSets(dpids);
Srikanth Vavilapallica2263c2014-10-09 15:19:11 -0700825 log.debug("The size of neighbor powerset for sw {} is ",
826 getStringId(), powerSet.size());
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700827 Set<NeighborSet> nsSet = new HashSet<NeighborSet>();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700828 for (Set<Dpid> combo : powerSet) {
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700829 if (combo.isEmpty())
830 continue;
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700831 if (isEdgeRouter && !edgeLabels.isEmpty()) {
832 for (Integer edgeLabel : edgeLabels) {
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700833 /* If it is local node's edge label, continue */
834 if (edgeLabel == sid)
835 continue;
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700836 NeighborSet ns = new NeighborSet();
837 ns.addDpids(combo);
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700838 /* Check if the edge label being set is of the
839 * same node in the Neighbor set
840 */
841 if ((combo.size() != 1) ||
842 (!isNodeLabelAndEdgeLabelSame(
843 combo.iterator().next(), edgeLabel))){
844 ns.setEdgeLabel(edgeLabel);
845 }
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700846 nsSet.add(ns);
847 }
848 } else {
849 NeighborSet ns = new NeighborSet();
850 ns.addDpids(combo);
851 nsSet.add(ns);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700852 }
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700853 }
Srikanth Vavilapallica2263c2014-10-09 15:19:11 -0700854 log.debug("The neighborset with label for sw {} is ",
855 getStringId(), nsSet);
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700856
857 int groupid = 1;
858 for (NeighborSet ns : nsSet) {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700859 List<BucketInfo> buckets = new ArrayList<BucketInfo>();
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700860 for (Dpid d : ns.getDpids()) {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700861 for (PortNumber sp : neighbors.get(d)) {
862 BucketInfo b = new BucketInfo(d,
863 MacAddress.of(srConfig.getRouterMac()),
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700864 getNeighborRouterMacAddress(d), sp,
865 ns.getEdgeLabel());
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700866 buckets.add(b);
Srikanth Vavilapallibd9b3e22014-10-02 08:57:46 -0700867
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700868 /* Update Port Neighborset map */
Srikanth Vavilapallibd9b3e22014-10-02 08:57:46 -0700869 ArrayList<NeighborSet> portNeighborSets =
870 portNeighborSetMap.get(sp);
871 if (portNeighborSets == null) {
872 portNeighborSets = new ArrayList<NeighborSet>();
873 portNeighborSets.add(ns);
874 portNeighborSetMap.put(sp, portNeighborSets);
875 }
876 else
877 portNeighborSets.add(ns);
878 }
879 }
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700880 EcmpInfo ecmpInfo = new EcmpInfo(groupid++, buckets);
881 setEcmpGroup(ecmpInfo);
882 ecmpGroups.put(ns, ecmpInfo);
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700883 log.debug("Creating ecmp group in sw {} for neighbor set {}: {}",
884 getStringId(), ns, ecmpInfo);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700885 }
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700886
887 // temp map of ecmp groupings
888 /* Map<NeighborSet, List<BucketInfo>> temp =
889 new HashMap<NeighborSet, List<BucketInfo>>();
890 */
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700891 }
892
893 private class EcmpInfo {
894 int groupId;
895 List<BucketInfo> buckets;
896
897 EcmpInfo(int gid, List<BucketInfo> bucketInfos) {
898 groupId = gid;
899 buckets = bucketInfos;
900 }
901
902 @Override
903 public String toString() {
904 return "groupId: " + groupId + ", buckets: " + buckets;
905 }
906 }
907
908 private class BucketInfo {
909 Dpid neighborDpid;
910 MacAddress srcMac;
911 MacAddress dstMac;
912 PortNumber outport;
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700913 int mplsLabel;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700914
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700915 BucketInfo(Dpid nDpid, MacAddress smac, MacAddress dmac,
916 PortNumber p, int label) {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700917 neighborDpid = nDpid;
918 srcMac = smac;
919 dstMac = dmac;
920 outport = p;
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700921 mplsLabel = label;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700922 }
923
924 @Override
925 public String toString() {
926 return " {neighborDpid: " + neighborDpid + ", dstMac: " + dstMac +
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700927 ", srcMac: " + srcMac + ", outport: " + outport +
928 "mplsLabel: " + mplsLabel + "}";
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700929 }
930 }
931
932 private void setEcmpGroup(EcmpInfo ecmpInfo) {
933 List<OFMessage> msglist = new ArrayList<OFMessage>();
934 OFGroup group = OFGroup.of(ecmpInfo.groupId);
935
936 List<OFBucket> buckets = new ArrayList<OFBucket>();
937 for (BucketInfo b : ecmpInfo.buckets) {
938 OFOxmEthDst dmac = factory.oxms()
939 .ethDst(b.dstMac);
940 OFAction setDA = factory.actions().buildSetField()
941 .setField(dmac).build();
Saurav Das0a344b02014-09-26 14:18:52 -0700942 OFOxmEthSrc smac = factory.oxms()
943 .ethSrc(b.srcMac);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700944 OFAction setSA = factory.actions().buildSetField()
945 .setField(smac).build();
946 OFAction outp = factory.actions().buildOutput()
947 .setPort(OFPort.of(b.outport.shortValue()))
948 .build();
949 List<OFAction> actions = new ArrayList<OFAction>();
950 actions.add(setSA);
951 actions.add(setDA);
952 actions.add(outp);
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700953 if (b.mplsLabel != -1) {
954 OFAction pushLabel = factory.actions().buildPushMpls()
955 .setEthertype(EthType.MPLS_UNICAST).build();
Sangho Shin62ce5c12014-10-08 16:24:40 -0700956 OFOxmMplsLabel lid = factory.oxms()
957 .mplsLabel(U32.of(b.mplsLabel));
958 OFAction setLabel = factory.actions().buildSetField()
959 .setField(lid).build();
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700960 OFAction copyTtl = factory.actions().copyTtlOut();
961 OFAction decrTtl = factory.actions().decMplsTtl();
962 actions.add(pushLabel);
963 actions.add(setLabel);
964 actions.add(copyTtl);
965 actions.add(decrTtl);
966 }
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700967 OFBucket ofb = factory.buildBucket()
968 .setWeight(1)
969 .setActions(actions)
970 .build();
971 buckets.add(ofb);
972 }
973
974 OFMessage gm = factory.buildGroupAdd()
975 .setGroup(group)
976 .setBuckets(buckets)
977 .setGroupType(OFGroupType.SELECT)
978 .setXid(getNextTransactionId())
979 .build();
980 msglist.add(gm);
981 try {
982 write(msglist);
983 } catch (IOException e) {
984 // TODO Auto-generated catch block
985 e.printStackTrace();
986 }
987 }
988
Srikanth Vavilapalli7d873fd2014-10-04 07:50:57 -0700989 private void modifyEcmpGroup(EcmpInfo ecmpInfo) {
990 List<OFMessage> msglist = new ArrayList<OFMessage>();
991 OFGroup group = OFGroup.of(ecmpInfo.groupId);
992
993 List<OFBucket> buckets = new ArrayList<OFBucket>();
994 for (BucketInfo b : ecmpInfo.buckets) {
995 OFOxmEthDst dmac = factory.oxms()
996 .ethDst(b.dstMac);
997 OFAction setDA = factory.actions().buildSetField()
998 .setField(dmac).build();
999 OFOxmEthSrc smac = factory.oxms()
1000 .ethSrc(b.srcMac);
1001 OFAction setSA = factory.actions().buildSetField()
1002 .setField(smac).build();
1003 OFAction outp = factory.actions().buildOutput()
1004 .setPort(OFPort.of(b.outport.shortValue()))
1005 .build();
1006 List<OFAction> actions = new ArrayList<OFAction>();
1007 actions.add(setSA);
1008 actions.add(setDA);
1009 actions.add(outp);
Srikanth Vavilapalli68144302014-10-08 15:55:24 -07001010 if (b.mplsLabel != -1) {
1011 OFAction pushLabel = factory.actions().buildPushMpls()
1012 .setEthertype(EthType.MPLS_UNICAST).build();
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -07001013 OFOxmMplsLabel lid = factory.oxms()
1014 .mplsLabel(U32.of(b.mplsLabel));
1015 OFAction setLabel = factory.actions().buildSetField()
1016 .setField(lid).build();
Srikanth Vavilapalli68144302014-10-08 15:55:24 -07001017 OFAction copyTtl = factory.actions().copyTtlOut();
1018 OFAction decrTtl = factory.actions().decMplsTtl();
1019 actions.add(pushLabel);
1020 actions.add(setLabel);
1021 actions.add(copyTtl);
1022 actions.add(decrTtl);
1023 }
Srikanth Vavilapalli7d873fd2014-10-04 07:50:57 -07001024 OFBucket ofb = factory.buildBucket()
1025 .setWeight(1)
1026 .setActions(actions)
1027 .build();
1028 buckets.add(ofb);
1029 }
1030
1031 OFMessage gm = factory.buildGroupModify()
1032 .setGroup(group)
1033 .setBuckets(buckets)
1034 .setGroupType(OFGroupType.SELECT)
1035 .setXid(getNextTransactionId())
1036 .build();
1037 msglist.add(gm);
1038 try {
1039 write(msglist);
1040 } catch (IOException e) {
1041 // TODO Auto-generated catch block
1042 e.printStackTrace();
1043 }
1044 }
1045
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001046 private void verifyGroups() throws IOException {
1047 sendGroupDescRequest();
1048 }
1049
1050 private void sendGroupDescRequest() throws IOException {
1051 OFMessage gdr = factory.buildGroupDescStatsRequest()
1052 .setXid(getNextTransactionId())
1053 .build();
1054 write(gdr, null);
1055 }
1056
1057 private void assignAdjacencyLabels() {
1058 // TODO
1059 try {
1060 nextDriverState();
1061 } catch (IOException e) {
1062 // TODO Auto-generated catch block
1063 e.printStackTrace();
1064 }
1065 }
1066
Saurav Das1cd10152014-09-26 09:38:07 -07001067 private OFAction getOFAction(Action action) {
1068 OFAction ofAction = null;
1069 if (action instanceof OutputAction) {
1070 OutputAction outputAction = (OutputAction) action;
1071 OFPort port = OFPort.of((int) outputAction.getPortNumber().value());
1072 ofAction = factory.actions().output(port, Short.MAX_VALUE);
1073 } else if (action instanceof ModifyDstMacAction) {
1074 long dstMac = ((ModifyDstMacAction) action).getDstMac().toLong();
1075 OFOxmEthDst dmac = factory.oxms()
1076 .ethDst(MacAddress.of(dstMac));
1077 ofAction = factory.actions().buildSetField()
1078 .setField(dmac).build();
1079 } else if (action instanceof ModifySrcMacAction) {
1080 long srcMac = ((ModifySrcMacAction) action).getSrcMac().toLong();
1081 OFOxmEthSrc smac = factory.oxms()
1082 .ethSrc(MacAddress.of(srcMac));
1083 ofAction = factory.actions().buildSetField()
1084 .setField(smac).build();
Srikanth Vavilapalli68144302014-10-08 15:55:24 -07001085 /*} else if (action instanceof PushMplsAction) {
1086 ofAction = factory.actions().pushMpls(EthType.MPLS_UNICAST);
1087 } else if (action instanceof SetMplsIdAction) {
1088 int labelid = ((SetMplsIdAction) action).getMplsId();
1089 OFOxmMplsLabel lid = factory.oxms()
1090 .mplsLabel(U32.of(labelid));
1091 ofAction = factory.actions().buildSetField()
1092 .setField(lid).build();
1093 */} else if (action instanceof PopMplsAction) {
Saurav Das1cd10152014-09-26 09:38:07 -07001094 EthType ethertype = ((PopMplsAction) action).getEthType();
1095 ofAction = factory.actions().popMpls(ethertype);
1096 } else if (action instanceof GroupAction) {
1097 NeighborSet ns = ((GroupAction) action).getDpids();
1098 EcmpInfo ei = ecmpGroups.get(ns);
1099 if (ei != null) {
1100 int gid = ei.groupId;
1101 ofAction = factory.actions().buildGroup()
1102 .setGroup(OFGroup.of(gid))
1103 .build();
1104 } else {
1105 log.error("Unable to find ecmp group for neighbors {} at "
1106 + "switch {}", ns, getStringId());
1107 }
1108 } else if (action instanceof DecNwTtlAction) {
1109 ofAction = factory.actions().decNwTtl();
1110 } else if (action instanceof DecMplsTtlAction) {
1111 ofAction = factory.actions().decMplsTtl();
1112 } else if (action instanceof CopyTtlInAction) {
1113 ofAction = factory.actions().copyTtlIn();
1114 } else if (action instanceof CopyTtlOutAction) {
1115 ofAction = factory.actions().copyTtlOut();
1116 } else {
1117 log.warn("Unsupported Action type: {}", action.getClass().getName());
1118 return null;
1119 }
1120
1121 // not supported by loxigen
1122 // OFAction setBos =
1123 // factory.actions().buildSetField().setField(bos).build();
1124
1125 return ofAction;
1126 }
1127
Saurav Das0a344b02014-09-26 14:18:52 -07001128 private OFMessage getIpEntry(MatchActionOperationEntry mao) {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001129 MatchAction ma = mao.getTarget();
1130 Operator op = mao.getOperator();
1131 Ipv4Match ipm = (Ipv4Match) ma.getMatch();
1132
1133 // set match
1134 IPv4Net ipdst = ipm.getDestination();
1135 OFOxmEthType ethTypeIp = factory.oxms()
1136 .ethType(EthType.IPv4);
1137 OFOxmIpv4DstMasked ipPrefix = factory.oxms()
1138 .ipv4DstMasked(
1139 IPv4Address.of(ipdst.address().value()),
1140 IPv4Address.ofCidrMaskLength(ipdst.prefixLen())
1141 );
1142 OFOxmList oxmList = OFOxmList.of(ethTypeIp, ipPrefix);
1143 OFMatchV3 match = factory.buildMatchV3()
1144 .setOxmList(oxmList).build();
1145
1146 // set actions
1147 List<OFAction> writeActions = new ArrayList<OFAction>();
1148 for (Action action : ma.getActions()) {
Saurav Das1cd10152014-09-26 09:38:07 -07001149 OFAction ofAction = getOFAction(action);
1150 if (ofAction != null) {
1151 writeActions.add(ofAction);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001152 }
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001153 }
1154
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001155 // set instructions
1156 OFInstruction writeInstr = factory.instructions().buildWriteActions()
1157 .setActions(writeActions).build();
1158 OFInstruction gotoInstr = factory.instructions().buildGotoTable()
1159 .setTableId(TableId.of(TABLE_ACL)).build();
1160 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
1161 instructions.add(writeInstr);
1162 instructions.add(gotoInstr);
1163
Saurav Das1cd10152014-09-26 09:38:07 -07001164 // set flow priority to emulate longest prefix match
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001165 int priority = ipdst.prefixLen() * PRIORITY_MULTIPLIER;
1166 if (ipdst.prefixLen() == (short) 32) {
1167 priority = MAX_PRIORITY;
1168 }
1169
Saurav Dasbc594a42014-09-25 20:13:50 -07001170 // set flow-mod
Saurav Dase972b3a2014-09-26 15:41:06 -07001171 OFFlowMod.Builder fmBuilder = null;
1172 switch (op) {
1173 case ADD:
1174 fmBuilder = factory.buildFlowAdd();
1175 break;
1176 case REMOVE:
1177 fmBuilder = factory.buildFlowDeleteStrict();
1178 break;
Sangho Shin5be3e532014-10-03 17:20:58 -07001179 case MODIFY: // TODO
1180 fmBuilder = factory.buildFlowModifyStrict();
1181 break;
Saurav Dase972b3a2014-09-26 15:41:06 -07001182 default:
1183 log.warn("Unsupported MatchAction Operator: {}", op);
1184 return null;
Saurav Dasbc594a42014-09-25 20:13:50 -07001185 }
Saurav Dase972b3a2014-09-26 15:41:06 -07001186 OFMessage ipFlow = fmBuilder
1187 .setTableId(TableId.of(TABLE_IPv4_UNICAST))
1188 .setMatch(match)
1189 .setInstructions(instructions)
1190 .setPriority(priority)
1191 .setBufferId(OFBufferId.NO_BUFFER)
1192 .setIdleTimeout(0)
1193 .setHardTimeout(0)
1194 .setXid(getNextTransactionId())
1195 .build();
Saurav Dasbc594a42014-09-25 20:13:50 -07001196 log.debug("{} ip-rule {}-{} in sw {}",
1197 (op == MatchActionOperations.Operator.ADD) ? "Adding" : "Deleting",
1198 match, writeActions,
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001199 getStringId());
Saurav Das0a344b02014-09-26 14:18:52 -07001200 return ipFlow;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001201 }
1202
Saurav Das0a344b02014-09-26 14:18:52 -07001203 private OFMessage getMplsEntry(MatchActionOperationEntry mao) {
Saurav Das1cd10152014-09-26 09:38:07 -07001204 MatchAction ma = mao.getTarget();
1205 Operator op = mao.getOperator();
1206 MplsMatch mplsm = (MplsMatch) ma.getMatch();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001207
Saurav Das1cd10152014-09-26 09:38:07 -07001208 // set match
1209 OFOxmEthType ethTypeMpls = factory.oxms()
1210 .ethType(EthType.MPLS_UNICAST);
1211 OFOxmMplsLabel labelid = factory.oxms()
1212 .mplsLabel(U32.of(mplsm.getMplsLabel()));
1213 OFOxmList oxmList = OFOxmList.of(ethTypeMpls, labelid);
1214 OFMatchV3 matchlabel = factory.buildMatchV3()
1215 .setOxmList(oxmList).build();
1216
1217 // set actions
1218 List<OFAction> writeActions = new ArrayList<OFAction>();
1219 for (Action action : ma.getActions()) {
1220 OFAction ofAction = getOFAction(action);
1221 if (ofAction != null) {
1222 writeActions.add(ofAction);
1223 }
1224 }
1225
1226 // set instructions
1227 OFInstruction writeInstr = factory.instructions().buildWriteActions()
1228 .setActions(writeActions).build();
1229 OFInstruction gotoInstr = factory.instructions().buildGotoTable()
1230 .setTableId(TableId.of(TABLE_ACL)).build();
1231 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
1232 instructions.add(writeInstr);
1233 instructions.add(gotoInstr);
1234
Saurav Dase972b3a2014-09-26 15:41:06 -07001235 // set flow-mod
1236 OFFlowMod.Builder fmBuilder = null;
1237 switch (op) {
1238 case ADD:
1239 fmBuilder = factory.buildFlowAdd();
1240 break;
1241 case REMOVE:
1242 fmBuilder = factory.buildFlowDeleteStrict();
1243 break;
Sangho Shin5be3e532014-10-03 17:20:58 -07001244 case MODIFY: // TODO
1245 fmBuilder = factory.buildFlowModifyStrict();
1246 break;
Saurav Dase972b3a2014-09-26 15:41:06 -07001247 default:
1248 log.warn("Unsupported MatchAction Operator: {}", op);
1249 return null;
Saurav Das1cd10152014-09-26 09:38:07 -07001250 }
Saurav Dase972b3a2014-09-26 15:41:06 -07001251
1252 OFMessage mplsFlow = fmBuilder
1253 .setTableId(TableId.of(TABLE_MPLS))
1254 .setMatch(matchlabel)
1255 .setInstructions(instructions)
1256 .setPriority(MAX_PRIORITY) // exact match and exclusive
1257 .setBufferId(OFBufferId.NO_BUFFER)
1258 .setIdleTimeout(0)
1259 .setHardTimeout(0)
1260 .setXid(getNextTransactionId())
1261 .build();
Saurav Das1cd10152014-09-26 09:38:07 -07001262 log.debug("{} mpls-rule {}-{} in sw {}",
1263 (op == MatchActionOperations.Operator.ADD) ? "Adding" : "Deleting",
1264 matchlabel, writeActions,
1265 getStringId());
Saurav Das0a344b02014-09-26 14:18:52 -07001266 return mplsFlow;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001267 }
1268
Saurav Das0a344b02014-09-26 14:18:52 -07001269 private OFMessage getAclEntry(MatchActionOperationEntry mao) {
Saurav Dase972b3a2014-09-26 15:41:06 -07001270 MatchAction ma = mao.getTarget();
1271 Operator op = mao.getOperator();
1272 PacketMatch packetMatch = (PacketMatch) ma.getMatch();
1273 Builder matchBuilder = factory.buildMatch();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001274
Saurav Dase972b3a2014-09-26 15:41:06 -07001275 // set match
1276 int inport = 0;
1277 if (ma.getSwitchPort() != null) {
1278 inport = (int) ma.getSwitchPort().getPortNumber().value();
1279 }
1280 final MACAddress srcMac = packetMatch.getSrcMacAddress();
1281 final MACAddress dstMac = packetMatch.getDstMacAddress();
1282 final Short etherType = packetMatch.getEtherType();
1283 final IPv4Net srcIp = packetMatch.getSrcIpAddress();
1284 final IPv4Net dstIp = packetMatch.getDstIpAddress();
1285 final Byte ipProto = packetMatch.getIpProtocolNumber();
1286 final Short srcTcpPort = packetMatch.getSrcTcpPortNumber();
1287 final Short dstTcpPort = packetMatch.getDstTcpPortNumber();
1288 if (inport > 0) {
1289 matchBuilder.setExact(MatchField.IN_PORT,
1290 OFPort.of(inport));
1291 }
1292 if (srcMac != null) {
1293 matchBuilder.setExact(MatchField.ETH_SRC, MacAddress.of(srcMac.toLong()));
1294 }
1295 if (dstMac != null) {
1296 matchBuilder.setExact(MatchField.ETH_DST, MacAddress.of(dstMac.toLong()));
1297 }
1298 if (etherType != null) {
1299 matchBuilder.setExact(MatchField.ETH_TYPE, EthType.of(etherType));
1300 }
1301 if (srcIp != null) {
1302 matchBuilder.setMasked(MatchField.IPV4_SRC,
1303 IPv4Address.of(srcIp.address().value())
1304 .withMaskOfLength(srcIp.prefixLen()));
1305 }
1306 if (dstIp != null) {
1307 matchBuilder.setMasked(MatchField.IPV4_DST,
1308 IPv4Address.of(dstIp.address().value())
1309 .withMaskOfLength(dstIp.prefixLen()));
1310 }
1311 if (ipProto != null) {
1312 matchBuilder.setExact(MatchField.IP_PROTO, IpProtocol.of(ipProto));
1313 }
1314 if (srcTcpPort != null) {
1315 matchBuilder.setExact(MatchField.TCP_SRC, TransportPort.of(srcTcpPort));
1316 }
1317 if (dstTcpPort != null) {
1318 matchBuilder.setExact(MatchField.TCP_DST, TransportPort.of(dstTcpPort));
1319 }
1320
1321 // set actions
1322 List<OFAction> applyActions = new ArrayList<OFAction>();
1323 for (Action action : ma.getActions()) {
1324 OFAction ofAction = getOFAction(action);
1325 if (ofAction != null) {
1326 applyActions.add(ofAction);
1327 }
1328 }
1329
1330 // set instructions
1331 OFInstruction clearInstr = factory.instructions().clearActions();
1332 OFInstruction applyInstr = factory.instructions().buildApplyActions()
1333 .setActions(applyActions).build();
1334 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
1335 instructions.add(clearInstr);
1336 instructions.add(applyInstr);
1337
1338 // set flow-mod
1339 OFFlowMod.Builder fmBuilder = null;
1340 switch (op) {
1341 case ADD:
1342 fmBuilder = factory.buildFlowAdd();
1343 break;
1344 case REMOVE:
1345 fmBuilder = factory.buildFlowDeleteStrict();
1346 break;
Sangho Shin5be3e532014-10-03 17:20:58 -07001347 case MODIFY: // TODO
1348 fmBuilder = factory.buildFlowModifyStrict();
1349 break;
Saurav Dase972b3a2014-09-26 15:41:06 -07001350 default:
1351 log.warn("Unsupported MatchAction Operator: {}", op);
1352 return null;
1353 }
1354
1355 OFMessage aclFlow = fmBuilder
1356 .setTableId(TableId.of(TABLE_ACL))
1357 .setMatch(matchBuilder.build())
1358 .setInstructions(instructions)
1359 .setPriority(MAX_PRIORITY / 2) // TODO: wrong - should be MA
1360 // priority
1361 .setBufferId(OFBufferId.NO_BUFFER)
1362 .setIdleTimeout(0)
1363 .setHardTimeout(0)
1364 .setXid(getNextTransactionId())
1365 .build();
Saurav Das0a344b02014-09-26 14:18:52 -07001366 return aclFlow;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001367 }
1368
1369 // *****************************
1370 // IOF13Switch
1371 // *****************************
1372
1373 @Override
1374 public void pushFlow(MatchActionOperationEntry matchActionOp) throws IOException {
Saurav Das0a344b02014-09-26 14:18:52 -07001375 OFMessage ofm = getFlow(matchActionOp);
1376 if (ofm != null) {
1377 write(Collections.singletonList(ofm));
1378 }
1379 }
1380
1381 private OFMessage getFlow(MatchActionOperationEntry matchActionOp) {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001382 final MatchAction matchAction = matchActionOp.getTarget();
1383 final Match match = matchAction.getMatch();
1384 if (match instanceof Ipv4Match) {
Saurav Das0a344b02014-09-26 14:18:52 -07001385 return getIpEntry(matchActionOp);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001386 } else if (match instanceof MplsMatch) {
Saurav Das0a344b02014-09-26 14:18:52 -07001387 return getMplsEntry(matchActionOp);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001388 } else if (match instanceof PacketMatch) {
Saurav Das0a344b02014-09-26 14:18:52 -07001389 return getAclEntry(matchActionOp);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001390 } else {
1391 log.error("Unknown match type {} pushed to switch {}", match,
1392 getStringId());
1393 }
Saurav Das0a344b02014-09-26 14:18:52 -07001394 return null;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001395 }
1396
1397 @Override
1398 public void pushFlows(Collection<MatchActionOperationEntry> matchActionOps)
1399 throws IOException {
Saurav Das0a344b02014-09-26 14:18:52 -07001400 List<OFMessage> flowMods = new ArrayList<OFMessage>();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001401 for (MatchActionOperationEntry matchActionOp : matchActionOps) {
Saurav Das0a344b02014-09-26 14:18:52 -07001402 OFMessage ofm = getFlow(matchActionOp);
1403 if (ofm != null) {
1404 flowMods.add(ofm);
1405 }
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001406 }
Saurav Das0a344b02014-09-26 14:18:52 -07001407 write(flowMods);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001408 }
1409
1410 @Override
1411 public int getEcmpGroupId(NeighborSet ns) {
1412 EcmpInfo ei = ecmpGroups.get(ns);
1413 if (ei == null) {
1414 return -1;
1415 } else {
1416 return ei.groupId;
1417 }
1418 }
1419
1420 // *****************************
Saurav Das80d17392014-10-01 10:24:56 -07001421 // Unused
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001422 // *****************************
1423
Saurav Das80d17392014-10-01 10:24:56 -07001424 @SuppressWarnings("unused")
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001425 private void setAsyncConfig() throws IOException {
1426 List<OFMessage> msglist = new ArrayList<OFMessage>(3);
1427 OFMessage setAC = null;
1428
1429 if (role == Role.MASTER) {
1430 setAC = factory.buildAsyncSet()
1431 .setFlowRemovedMaskEqualMaster(SET_FLOW_REMOVED_MASK_MASTER)
1432 .setPacketInMaskEqualMaster(SET_PACKET_IN_MASK_MASTER)
1433 .setPortStatusMaskEqualMaster(SET_PORT_STATUS_MASK_MASTER)
1434 .setFlowRemovedMaskSlave(SET_ALL_SLAVE)
1435 .setPacketInMaskSlave(SET_ALL_SLAVE)
1436 .setPortStatusMaskSlave(SET_ALL_SLAVE)
1437 .setXid(getNextTransactionId())
1438 .build();
1439 } else if (role == Role.EQUAL) {
1440 setAC = factory.buildAsyncSet()
1441 .setFlowRemovedMaskEqualMaster(SET_FLOW_REMOVED_MASK_EQUAL)
1442 .setPacketInMaskEqualMaster(SET_PACKET_IN_MASK_EQUAL)
1443 .setPortStatusMaskEqualMaster(SET_PORT_STATUS_MASK_EQUAL)
1444 .setFlowRemovedMaskSlave(SET_ALL_SLAVE)
1445 .setPacketInMaskSlave(SET_ALL_SLAVE)
1446 .setPortStatusMaskSlave(SET_ALL_SLAVE)
1447 .setXid(getNextTransactionId())
1448 .build();
1449 }
1450 msglist.add(setAC);
1451
1452 OFMessage br = factory.buildBarrierRequest()
1453 .setXid(getNextTransactionId())
1454 .build();
1455 msglist.add(br);
1456
1457 OFMessage getAC = factory.buildAsyncGetRequest()
1458 .setXid(getNextTransactionId())
1459 .build();
1460 msglist.add(getAC);
1461
1462 write(msglist);
1463 }
1464
Saurav Das80d17392014-10-01 10:24:56 -07001465 @SuppressWarnings("unused")
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001466 private void decodeAsyncGetReply(OFAsyncGetReply rep) {
1467 long frm = rep.getFlowRemovedMaskEqualMaster();
Sangho Shin01bca862014-09-12 11:18:59 -07001468 long frs = rep.getFlowRemovedMaskSlave();
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001469 long pim = rep.getPacketInMaskEqualMaster();
Sangho Shin01bca862014-09-12 11:18:59 -07001470 long pis = rep.getPacketInMaskSlave();
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001471 long psm = rep.getPortStatusMaskEqualMaster();
Sangho Shin01bca862014-09-12 11:18:59 -07001472 long pss = rep.getPortStatusMaskSlave();
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001473
1474 if (role == Role.MASTER || role == Role.EQUAL) { // should separate
1475 log.info("FRM:{}", HexString.toHexString((frm & TEST_FLOW_REMOVED_MASK)));
1476 log.info("PIM:{}", HexString.toHexString((pim & TEST_PACKET_IN_MASK)));
1477 log.info("PSM:{}", HexString.toHexString((psm & TEST_PORT_STATUS_MASK)));
1478 }
1479
1480 }
1481
Saurav Das80d17392014-10-01 10:24:56 -07001482 @SuppressWarnings("unused")
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001483 private void getTableFeatures() throws IOException {
1484 OFMessage gtf = factory.buildTableFeaturesStatsRequest()
1485 .setXid(getNextTransactionId())
1486 .build();
1487 write(gtf, null);
1488 }
1489
Saurav Das80d17392014-10-01 10:24:56 -07001490 @SuppressWarnings("unused")
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001491 private void sendGroupFeaturesRequest() throws IOException {
1492 OFMessage gfr = factory.buildGroupFeaturesStatsRequest()
1493 .setXid(getNextTransactionId())
1494 .build();
1495 write(gfr, null);
1496 }
1497
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001498 private void processGroupFeatures(OFGroupFeaturesStatsReply gfsr) {
1499 log.info("Sw: {} Group Features {}", getStringId(), gfsr);
1500 }
1501
Fahad Naeem Khand563af62014-10-08 17:37:25 -07001502 @Override
1503 public TableId getTableId(String tableType) {
1504 tableType = tableType.toLowerCase();
1505 if(tableType.contentEquals("ip")){
1506 return TableId.of(OFSwitchImplCPqD13.TABLE_IPv4_UNICAST);
1507 }
1508 else if (tableType.contentEquals("mpls")){
1509 return TableId.of(OFSwitchImplCPqD13.TABLE_MPLS);
1510 }
1511 else if (tableType.contentEquals("acl")){
1512 return TableId.of(OFSwitchImplCPqD13.TABLE_ACL);
1513 }
1514 else{
1515 log.warn("Invalid tableType: {}", tableType);
1516 return null;
1517 }
1518 }
1519
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001520}