blob: 42e4de16ea1a31e345560b6058ec27fc0c4fd98d [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 }
722 }
723
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700724 private boolean isNodeLabelAndEdgeLabelSame(Dpid dpid, int edgeLabel) {
725 INetworkConfigService ncs = floodlightProvider.getNetworkConfigService();
726 SwitchConfigStatus scs = ncs.checkSwitchConfig(dpid);
727 if (scs.getConfigState() == NetworkConfigState.ACCEPT_ADD) {
728 return (((SegmentRouterConfig) scs.getSwitchConfig()).
729 getNodeSid() == edgeLabel);
730 } else {
731 // TODO: return false if router not allowed
732 return false;
733 }
734 }
735
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700736 private Set<Set<Dpid>> getAllNeighborSets(Set<Dpid> neighbors) {
737 List<Dpid> list = new ArrayList<Dpid>(neighbors);
738 Set<Set<Dpid>> sets = new HashSet<Set<Dpid>>();
739 /* get the number of elements in the neighbors */
740 int elements = list.size();
741 /* the number of members of a power set is 2^n
742 * including the empty set
743 */
744 int powerElements = (1 << elements);
745
746 /* run a binary counter for the number of power elements */
747 for (long i = 1; i < powerElements; i++) {
748 Set<Dpid> dpidSubSet = new HashSet<Dpid>();
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700749 for (int j = 0; j < elements; j++) {
750 if ((i >> j) % 2 == 1) {
751 dpidSubSet.add(list.get(j));
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700752 }
753 }
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700754 /* NOTE: Avoid any pairings of edge routers only
755 * at a backbone router */
756 boolean avoidEdgeRouterPairing = true;
757 if ((!isEdgeRouter) && (dpidSubSet.size() > 1)) {
Srikanth Vavilapalli696010f2014-10-08 17:00:17 -0700758 for (Dpid dpid : dpidSubSet) {
759 if (!isEdgeRouter(dpid)) {
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700760 avoidEdgeRouterPairing = false;
Srikanth Vavilapalli696010f2014-10-08 17:00:17 -0700761 break;
762 }
763 }
764 }
765 else
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700766 avoidEdgeRouterPairing = false;
Srikanth Vavilapalli696010f2014-10-08 17:00:17 -0700767
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700768 if (!avoidEdgeRouterPairing)
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700769 sets.add(dpidSubSet);
770 }
771 return sets;
772 }
773
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700774 /**
775 * createGroups creates ECMP groups for all ports on this router connected
776 * to other routers (in the OF network). The information for ports is
777 * gleaned from the configured links. If no links are configured no groups
778 * will be created, and it is up to the caller of the IOF13Switch API to
779 * create groups.
780 * <p>
781 * By default all ports connected to the same neighbor router will be part
782 * of the same ECMP group. In addition, groups will be created for all
783 * possible combinations of neighbor routers.
784 * <p>
785 * For example, consider this router (R0) connected to 3 neighbors (R1, R2,
786 * and R3). The following groups will be created in R0:
787 * <li>1) all ports to R1,
788 * <li>2) all ports to R2,
789 * <li>3) all ports to R3,
790 * <li>4) all ports to R1 and R2
791 * <li>5) all ports to R1 and R3
792 * <li>6) all ports to R2 and R3
793 * <li>7) all ports to R1, R2, and R3
794 */
795 private void createGroups() {
796 Set<Dpid> dpids = neighbors.keySet();
797 if (dpids == null || dpids.isEmpty()) {
798 return;
799 }
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700800 /* Create all possible Neighbor sets from this router
801 * NOTE: Avoid any pairings of edge routers only
802 */
803 Set<Set<Dpid>> powerSet = getAllNeighborSets(dpids);
804 Set<NeighborSet> nsSet = new HashSet<NeighborSet>();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700805 for (Set<Dpid> combo : powerSet) {
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700806 if (combo.isEmpty())
807 continue;
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700808 if (isEdgeRouter && !edgeLabels.isEmpty()) {
809 for (Integer edgeLabel : edgeLabels) {
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700810 /* If it is local node's edge label, continue */
811 if (edgeLabel == sid)
812 continue;
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700813 NeighborSet ns = new NeighborSet();
814 ns.addDpids(combo);
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700815 /* Check if the edge label being set is of the
816 * same node in the Neighbor set
817 */
818 if ((combo.size() != 1) ||
819 (!isNodeLabelAndEdgeLabelSame(
820 combo.iterator().next(), edgeLabel))){
821 ns.setEdgeLabel(edgeLabel);
822 }
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700823 nsSet.add(ns);
824 }
825 } else {
826 NeighborSet ns = new NeighborSet();
827 ns.addDpids(combo);
828 nsSet.add(ns);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700829 }
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700830 }
831
832 int groupid = 1;
833 for (NeighborSet ns : nsSet) {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700834 List<BucketInfo> buckets = new ArrayList<BucketInfo>();
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700835 for (Dpid d : ns.getDpids()) {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700836 for (PortNumber sp : neighbors.get(d)) {
837 BucketInfo b = new BucketInfo(d,
838 MacAddress.of(srConfig.getRouterMac()),
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700839 getNeighborRouterMacAddress(d), sp,
840 ns.getEdgeLabel());
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700841 buckets.add(b);
Srikanth Vavilapallibd9b3e22014-10-02 08:57:46 -0700842
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700843 /* Update Port Neighborset map */
Srikanth Vavilapallibd9b3e22014-10-02 08:57:46 -0700844 ArrayList<NeighborSet> portNeighborSets =
845 portNeighborSetMap.get(sp);
846 if (portNeighborSets == null) {
847 portNeighborSets = new ArrayList<NeighborSet>();
848 portNeighborSets.add(ns);
849 portNeighborSetMap.put(sp, portNeighborSets);
850 }
851 else
852 portNeighborSets.add(ns);
853 }
854 }
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700855 EcmpInfo ecmpInfo = new EcmpInfo(groupid++, buckets);
856 setEcmpGroup(ecmpInfo);
857 ecmpGroups.put(ns, ecmpInfo);
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700858 log.debug("Creating ecmp group in sw {} for neighbor set {}: {}",
859 getStringId(), ns, ecmpInfo);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700860 }
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700861
862 // temp map of ecmp groupings
863 /* Map<NeighborSet, List<BucketInfo>> temp =
864 new HashMap<NeighborSet, List<BucketInfo>>();
865 */
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700866 }
867
868 private class EcmpInfo {
869 int groupId;
870 List<BucketInfo> buckets;
871
872 EcmpInfo(int gid, List<BucketInfo> bucketInfos) {
873 groupId = gid;
874 buckets = bucketInfos;
875 }
876
877 @Override
878 public String toString() {
879 return "groupId: " + groupId + ", buckets: " + buckets;
880 }
881 }
882
883 private class BucketInfo {
884 Dpid neighborDpid;
885 MacAddress srcMac;
886 MacAddress dstMac;
887 PortNumber outport;
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700888 int mplsLabel;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700889
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700890 BucketInfo(Dpid nDpid, MacAddress smac, MacAddress dmac,
891 PortNumber p, int label) {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700892 neighborDpid = nDpid;
893 srcMac = smac;
894 dstMac = dmac;
895 outport = p;
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700896 mplsLabel = label;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700897 }
898
899 @Override
900 public String toString() {
901 return " {neighborDpid: " + neighborDpid + ", dstMac: " + dstMac +
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700902 ", srcMac: " + srcMac + ", outport: " + outport +
903 "mplsLabel: " + mplsLabel + "}";
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700904 }
905 }
906
907 private void setEcmpGroup(EcmpInfo ecmpInfo) {
908 List<OFMessage> msglist = new ArrayList<OFMessage>();
909 OFGroup group = OFGroup.of(ecmpInfo.groupId);
910
911 List<OFBucket> buckets = new ArrayList<OFBucket>();
912 for (BucketInfo b : ecmpInfo.buckets) {
913 OFOxmEthDst dmac = factory.oxms()
914 .ethDst(b.dstMac);
915 OFAction setDA = factory.actions().buildSetField()
916 .setField(dmac).build();
Saurav Das0a344b02014-09-26 14:18:52 -0700917 OFOxmEthSrc smac = factory.oxms()
918 .ethSrc(b.srcMac);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700919 OFAction setSA = factory.actions().buildSetField()
920 .setField(smac).build();
921 OFAction outp = factory.actions().buildOutput()
922 .setPort(OFPort.of(b.outport.shortValue()))
923 .build();
924 List<OFAction> actions = new ArrayList<OFAction>();
925 actions.add(setSA);
926 actions.add(setDA);
927 actions.add(outp);
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700928 if (b.mplsLabel != -1) {
929 OFAction pushLabel = factory.actions().buildPushMpls()
930 .setEthertype(EthType.MPLS_UNICAST).build();
Sangho Shin62ce5c12014-10-08 16:24:40 -0700931 OFOxmMplsLabel lid = factory.oxms()
932 .mplsLabel(U32.of(b.mplsLabel));
933 OFAction setLabel = factory.actions().buildSetField()
934 .setField(lid).build();
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700935 OFAction copyTtl = factory.actions().copyTtlOut();
936 OFAction decrTtl = factory.actions().decMplsTtl();
937 actions.add(pushLabel);
938 actions.add(setLabel);
939 actions.add(copyTtl);
940 actions.add(decrTtl);
941 }
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700942 OFBucket ofb = factory.buildBucket()
943 .setWeight(1)
944 .setActions(actions)
945 .build();
946 buckets.add(ofb);
947 }
948
949 OFMessage gm = factory.buildGroupAdd()
950 .setGroup(group)
951 .setBuckets(buckets)
952 .setGroupType(OFGroupType.SELECT)
953 .setXid(getNextTransactionId())
954 .build();
955 msglist.add(gm);
956 try {
957 write(msglist);
958 } catch (IOException e) {
959 // TODO Auto-generated catch block
960 e.printStackTrace();
961 }
962 }
963
Srikanth Vavilapalli7d873fd2014-10-04 07:50:57 -0700964 private void modifyEcmpGroup(EcmpInfo ecmpInfo) {
965 List<OFMessage> msglist = new ArrayList<OFMessage>();
966 OFGroup group = OFGroup.of(ecmpInfo.groupId);
967
968 List<OFBucket> buckets = new ArrayList<OFBucket>();
969 for (BucketInfo b : ecmpInfo.buckets) {
970 OFOxmEthDst dmac = factory.oxms()
971 .ethDst(b.dstMac);
972 OFAction setDA = factory.actions().buildSetField()
973 .setField(dmac).build();
974 OFOxmEthSrc smac = factory.oxms()
975 .ethSrc(b.srcMac);
976 OFAction setSA = factory.actions().buildSetField()
977 .setField(smac).build();
978 OFAction outp = factory.actions().buildOutput()
979 .setPort(OFPort.of(b.outport.shortValue()))
980 .build();
981 List<OFAction> actions = new ArrayList<OFAction>();
982 actions.add(setSA);
983 actions.add(setDA);
984 actions.add(outp);
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700985 if (b.mplsLabel != -1) {
986 OFAction pushLabel = factory.actions().buildPushMpls()
987 .setEthertype(EthType.MPLS_UNICAST).build();
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700988 OFOxmMplsLabel lid = factory.oxms()
989 .mplsLabel(U32.of(b.mplsLabel));
990 OFAction setLabel = factory.actions().buildSetField()
991 .setField(lid).build();
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700992 OFAction copyTtl = factory.actions().copyTtlOut();
993 OFAction decrTtl = factory.actions().decMplsTtl();
994 actions.add(pushLabel);
995 actions.add(setLabel);
996 actions.add(copyTtl);
997 actions.add(decrTtl);
998 }
Srikanth Vavilapalli7d873fd2014-10-04 07:50:57 -0700999 OFBucket ofb = factory.buildBucket()
1000 .setWeight(1)
1001 .setActions(actions)
1002 .build();
1003 buckets.add(ofb);
1004 }
1005
1006 OFMessage gm = factory.buildGroupModify()
1007 .setGroup(group)
1008 .setBuckets(buckets)
1009 .setGroupType(OFGroupType.SELECT)
1010 .setXid(getNextTransactionId())
1011 .build();
1012 msglist.add(gm);
1013 try {
1014 write(msglist);
1015 } catch (IOException e) {
1016 // TODO Auto-generated catch block
1017 e.printStackTrace();
1018 }
1019 }
1020
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001021 private void verifyGroups() throws IOException {
1022 sendGroupDescRequest();
1023 }
1024
1025 private void sendGroupDescRequest() throws IOException {
1026 OFMessage gdr = factory.buildGroupDescStatsRequest()
1027 .setXid(getNextTransactionId())
1028 .build();
1029 write(gdr, null);
1030 }
1031
1032 private void assignAdjacencyLabels() {
1033 // TODO
1034 try {
1035 nextDriverState();
1036 } catch (IOException e) {
1037 // TODO Auto-generated catch block
1038 e.printStackTrace();
1039 }
1040 }
1041
Saurav Das1cd10152014-09-26 09:38:07 -07001042 private OFAction getOFAction(Action action) {
1043 OFAction ofAction = null;
1044 if (action instanceof OutputAction) {
1045 OutputAction outputAction = (OutputAction) action;
1046 OFPort port = OFPort.of((int) outputAction.getPortNumber().value());
1047 ofAction = factory.actions().output(port, Short.MAX_VALUE);
1048 } else if (action instanceof ModifyDstMacAction) {
1049 long dstMac = ((ModifyDstMacAction) action).getDstMac().toLong();
1050 OFOxmEthDst dmac = factory.oxms()
1051 .ethDst(MacAddress.of(dstMac));
1052 ofAction = factory.actions().buildSetField()
1053 .setField(dmac).build();
1054 } else if (action instanceof ModifySrcMacAction) {
1055 long srcMac = ((ModifySrcMacAction) action).getSrcMac().toLong();
1056 OFOxmEthSrc smac = factory.oxms()
1057 .ethSrc(MacAddress.of(srcMac));
1058 ofAction = factory.actions().buildSetField()
1059 .setField(smac).build();
Srikanth Vavilapalli68144302014-10-08 15:55:24 -07001060 /*} else if (action instanceof PushMplsAction) {
1061 ofAction = factory.actions().pushMpls(EthType.MPLS_UNICAST);
1062 } else if (action instanceof SetMplsIdAction) {
1063 int labelid = ((SetMplsIdAction) action).getMplsId();
1064 OFOxmMplsLabel lid = factory.oxms()
1065 .mplsLabel(U32.of(labelid));
1066 ofAction = factory.actions().buildSetField()
1067 .setField(lid).build();
1068 */} else if (action instanceof PopMplsAction) {
Saurav Das1cd10152014-09-26 09:38:07 -07001069 EthType ethertype = ((PopMplsAction) action).getEthType();
1070 ofAction = factory.actions().popMpls(ethertype);
1071 } else if (action instanceof GroupAction) {
1072 NeighborSet ns = ((GroupAction) action).getDpids();
1073 EcmpInfo ei = ecmpGroups.get(ns);
1074 if (ei != null) {
1075 int gid = ei.groupId;
1076 ofAction = factory.actions().buildGroup()
1077 .setGroup(OFGroup.of(gid))
1078 .build();
1079 } else {
1080 log.error("Unable to find ecmp group for neighbors {} at "
1081 + "switch {}", ns, getStringId());
1082 }
1083 } else if (action instanceof DecNwTtlAction) {
1084 ofAction = factory.actions().decNwTtl();
1085 } else if (action instanceof DecMplsTtlAction) {
1086 ofAction = factory.actions().decMplsTtl();
1087 } else if (action instanceof CopyTtlInAction) {
1088 ofAction = factory.actions().copyTtlIn();
1089 } else if (action instanceof CopyTtlOutAction) {
1090 ofAction = factory.actions().copyTtlOut();
1091 } else {
1092 log.warn("Unsupported Action type: {}", action.getClass().getName());
1093 return null;
1094 }
1095
1096 // not supported by loxigen
1097 // OFAction setBos =
1098 // factory.actions().buildSetField().setField(bos).build();
1099
1100 return ofAction;
1101 }
1102
Saurav Das0a344b02014-09-26 14:18:52 -07001103 private OFMessage getIpEntry(MatchActionOperationEntry mao) {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001104 MatchAction ma = mao.getTarget();
1105 Operator op = mao.getOperator();
1106 Ipv4Match ipm = (Ipv4Match) ma.getMatch();
1107
1108 // set match
1109 IPv4Net ipdst = ipm.getDestination();
1110 OFOxmEthType ethTypeIp = factory.oxms()
1111 .ethType(EthType.IPv4);
1112 OFOxmIpv4DstMasked ipPrefix = factory.oxms()
1113 .ipv4DstMasked(
1114 IPv4Address.of(ipdst.address().value()),
1115 IPv4Address.ofCidrMaskLength(ipdst.prefixLen())
1116 );
1117 OFOxmList oxmList = OFOxmList.of(ethTypeIp, ipPrefix);
1118 OFMatchV3 match = factory.buildMatchV3()
1119 .setOxmList(oxmList).build();
1120
1121 // set actions
1122 List<OFAction> writeActions = new ArrayList<OFAction>();
1123 for (Action action : ma.getActions()) {
Saurav Das1cd10152014-09-26 09:38:07 -07001124 OFAction ofAction = getOFAction(action);
1125 if (ofAction != null) {
1126 writeActions.add(ofAction);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001127 }
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001128 }
1129
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001130 // set instructions
1131 OFInstruction writeInstr = factory.instructions().buildWriteActions()
1132 .setActions(writeActions).build();
1133 OFInstruction gotoInstr = factory.instructions().buildGotoTable()
1134 .setTableId(TableId.of(TABLE_ACL)).build();
1135 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
1136 instructions.add(writeInstr);
1137 instructions.add(gotoInstr);
1138
Saurav Das1cd10152014-09-26 09:38:07 -07001139 // set flow priority to emulate longest prefix match
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001140 int priority = ipdst.prefixLen() * PRIORITY_MULTIPLIER;
1141 if (ipdst.prefixLen() == (short) 32) {
1142 priority = MAX_PRIORITY;
1143 }
1144
Saurav Dasbc594a42014-09-25 20:13:50 -07001145 // set flow-mod
Saurav Dase972b3a2014-09-26 15:41:06 -07001146 OFFlowMod.Builder fmBuilder = null;
1147 switch (op) {
1148 case ADD:
1149 fmBuilder = factory.buildFlowAdd();
1150 break;
1151 case REMOVE:
1152 fmBuilder = factory.buildFlowDeleteStrict();
1153 break;
Sangho Shin5be3e532014-10-03 17:20:58 -07001154 case MODIFY: // TODO
1155 fmBuilder = factory.buildFlowModifyStrict();
1156 break;
Saurav Dase972b3a2014-09-26 15:41:06 -07001157 default:
1158 log.warn("Unsupported MatchAction Operator: {}", op);
1159 return null;
Saurav Dasbc594a42014-09-25 20:13:50 -07001160 }
Saurav Dase972b3a2014-09-26 15:41:06 -07001161 OFMessage ipFlow = fmBuilder
1162 .setTableId(TableId.of(TABLE_IPv4_UNICAST))
1163 .setMatch(match)
1164 .setInstructions(instructions)
1165 .setPriority(priority)
1166 .setBufferId(OFBufferId.NO_BUFFER)
1167 .setIdleTimeout(0)
1168 .setHardTimeout(0)
1169 .setXid(getNextTransactionId())
1170 .build();
Saurav Dasbc594a42014-09-25 20:13:50 -07001171 log.debug("{} ip-rule {}-{} in sw {}",
1172 (op == MatchActionOperations.Operator.ADD) ? "Adding" : "Deleting",
1173 match, writeActions,
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001174 getStringId());
Saurav Das0a344b02014-09-26 14:18:52 -07001175 return ipFlow;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001176 }
1177
Saurav Das0a344b02014-09-26 14:18:52 -07001178 private OFMessage getMplsEntry(MatchActionOperationEntry mao) {
Saurav Das1cd10152014-09-26 09:38:07 -07001179 MatchAction ma = mao.getTarget();
1180 Operator op = mao.getOperator();
1181 MplsMatch mplsm = (MplsMatch) ma.getMatch();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001182
Saurav Das1cd10152014-09-26 09:38:07 -07001183 // set match
1184 OFOxmEthType ethTypeMpls = factory.oxms()
1185 .ethType(EthType.MPLS_UNICAST);
1186 OFOxmMplsLabel labelid = factory.oxms()
1187 .mplsLabel(U32.of(mplsm.getMplsLabel()));
1188 OFOxmList oxmList = OFOxmList.of(ethTypeMpls, labelid);
1189 OFMatchV3 matchlabel = factory.buildMatchV3()
1190 .setOxmList(oxmList).build();
1191
1192 // set actions
1193 List<OFAction> writeActions = new ArrayList<OFAction>();
1194 for (Action action : ma.getActions()) {
1195 OFAction ofAction = getOFAction(action);
1196 if (ofAction != null) {
1197 writeActions.add(ofAction);
1198 }
1199 }
1200
1201 // set instructions
1202 OFInstruction writeInstr = factory.instructions().buildWriteActions()
1203 .setActions(writeActions).build();
1204 OFInstruction gotoInstr = factory.instructions().buildGotoTable()
1205 .setTableId(TableId.of(TABLE_ACL)).build();
1206 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
1207 instructions.add(writeInstr);
1208 instructions.add(gotoInstr);
1209
Saurav Dase972b3a2014-09-26 15:41:06 -07001210 // set flow-mod
1211 OFFlowMod.Builder fmBuilder = null;
1212 switch (op) {
1213 case ADD:
1214 fmBuilder = factory.buildFlowAdd();
1215 break;
1216 case REMOVE:
1217 fmBuilder = factory.buildFlowDeleteStrict();
1218 break;
Sangho Shin5be3e532014-10-03 17:20:58 -07001219 case MODIFY: // TODO
1220 fmBuilder = factory.buildFlowModifyStrict();
1221 break;
Saurav Dase972b3a2014-09-26 15:41:06 -07001222 default:
1223 log.warn("Unsupported MatchAction Operator: {}", op);
1224 return null;
Saurav Das1cd10152014-09-26 09:38:07 -07001225 }
Saurav Dase972b3a2014-09-26 15:41:06 -07001226
1227 OFMessage mplsFlow = fmBuilder
1228 .setTableId(TableId.of(TABLE_MPLS))
1229 .setMatch(matchlabel)
1230 .setInstructions(instructions)
1231 .setPriority(MAX_PRIORITY) // exact match and exclusive
1232 .setBufferId(OFBufferId.NO_BUFFER)
1233 .setIdleTimeout(0)
1234 .setHardTimeout(0)
1235 .setXid(getNextTransactionId())
1236 .build();
Saurav Das1cd10152014-09-26 09:38:07 -07001237 log.debug("{} mpls-rule {}-{} in sw {}",
1238 (op == MatchActionOperations.Operator.ADD) ? "Adding" : "Deleting",
1239 matchlabel, writeActions,
1240 getStringId());
Saurav Das0a344b02014-09-26 14:18:52 -07001241 return mplsFlow;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001242 }
1243
Saurav Das0a344b02014-09-26 14:18:52 -07001244 private OFMessage getAclEntry(MatchActionOperationEntry mao) {
Saurav Dase972b3a2014-09-26 15:41:06 -07001245 MatchAction ma = mao.getTarget();
1246 Operator op = mao.getOperator();
1247 PacketMatch packetMatch = (PacketMatch) ma.getMatch();
1248 Builder matchBuilder = factory.buildMatch();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001249
Saurav Dase972b3a2014-09-26 15:41:06 -07001250 // set match
1251 int inport = 0;
1252 if (ma.getSwitchPort() != null) {
1253 inport = (int) ma.getSwitchPort().getPortNumber().value();
1254 }
1255 final MACAddress srcMac = packetMatch.getSrcMacAddress();
1256 final MACAddress dstMac = packetMatch.getDstMacAddress();
1257 final Short etherType = packetMatch.getEtherType();
1258 final IPv4Net srcIp = packetMatch.getSrcIpAddress();
1259 final IPv4Net dstIp = packetMatch.getDstIpAddress();
1260 final Byte ipProto = packetMatch.getIpProtocolNumber();
1261 final Short srcTcpPort = packetMatch.getSrcTcpPortNumber();
1262 final Short dstTcpPort = packetMatch.getDstTcpPortNumber();
1263 if (inport > 0) {
1264 matchBuilder.setExact(MatchField.IN_PORT,
1265 OFPort.of(inport));
1266 }
1267 if (srcMac != null) {
1268 matchBuilder.setExact(MatchField.ETH_SRC, MacAddress.of(srcMac.toLong()));
1269 }
1270 if (dstMac != null) {
1271 matchBuilder.setExact(MatchField.ETH_DST, MacAddress.of(dstMac.toLong()));
1272 }
1273 if (etherType != null) {
1274 matchBuilder.setExact(MatchField.ETH_TYPE, EthType.of(etherType));
1275 }
1276 if (srcIp != null) {
1277 matchBuilder.setMasked(MatchField.IPV4_SRC,
1278 IPv4Address.of(srcIp.address().value())
1279 .withMaskOfLength(srcIp.prefixLen()));
1280 }
1281 if (dstIp != null) {
1282 matchBuilder.setMasked(MatchField.IPV4_DST,
1283 IPv4Address.of(dstIp.address().value())
1284 .withMaskOfLength(dstIp.prefixLen()));
1285 }
1286 if (ipProto != null) {
1287 matchBuilder.setExact(MatchField.IP_PROTO, IpProtocol.of(ipProto));
1288 }
1289 if (srcTcpPort != null) {
1290 matchBuilder.setExact(MatchField.TCP_SRC, TransportPort.of(srcTcpPort));
1291 }
1292 if (dstTcpPort != null) {
1293 matchBuilder.setExact(MatchField.TCP_DST, TransportPort.of(dstTcpPort));
1294 }
1295
1296 // set actions
1297 List<OFAction> applyActions = new ArrayList<OFAction>();
1298 for (Action action : ma.getActions()) {
1299 OFAction ofAction = getOFAction(action);
1300 if (ofAction != null) {
1301 applyActions.add(ofAction);
1302 }
1303 }
1304
1305 // set instructions
1306 OFInstruction clearInstr = factory.instructions().clearActions();
1307 OFInstruction applyInstr = factory.instructions().buildApplyActions()
1308 .setActions(applyActions).build();
1309 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
1310 instructions.add(clearInstr);
1311 instructions.add(applyInstr);
1312
1313 // set flow-mod
1314 OFFlowMod.Builder fmBuilder = null;
1315 switch (op) {
1316 case ADD:
1317 fmBuilder = factory.buildFlowAdd();
1318 break;
1319 case REMOVE:
1320 fmBuilder = factory.buildFlowDeleteStrict();
1321 break;
Sangho Shin5be3e532014-10-03 17:20:58 -07001322 case MODIFY: // TODO
1323 fmBuilder = factory.buildFlowModifyStrict();
1324 break;
Saurav Dase972b3a2014-09-26 15:41:06 -07001325 default:
1326 log.warn("Unsupported MatchAction Operator: {}", op);
1327 return null;
1328 }
1329
1330 OFMessage aclFlow = fmBuilder
1331 .setTableId(TableId.of(TABLE_ACL))
1332 .setMatch(matchBuilder.build())
1333 .setInstructions(instructions)
1334 .setPriority(MAX_PRIORITY / 2) // TODO: wrong - should be MA
1335 // priority
1336 .setBufferId(OFBufferId.NO_BUFFER)
1337 .setIdleTimeout(0)
1338 .setHardTimeout(0)
1339 .setXid(getNextTransactionId())
1340 .build();
Saurav Das0a344b02014-09-26 14:18:52 -07001341 return aclFlow;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001342 }
1343
1344 // *****************************
1345 // IOF13Switch
1346 // *****************************
1347
1348 @Override
1349 public void pushFlow(MatchActionOperationEntry matchActionOp) throws IOException {
Saurav Das0a344b02014-09-26 14:18:52 -07001350 OFMessage ofm = getFlow(matchActionOp);
1351 if (ofm != null) {
1352 write(Collections.singletonList(ofm));
1353 }
1354 }
1355
1356 private OFMessage getFlow(MatchActionOperationEntry matchActionOp) {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001357 final MatchAction matchAction = matchActionOp.getTarget();
1358 final Match match = matchAction.getMatch();
1359 if (match instanceof Ipv4Match) {
Saurav Das0a344b02014-09-26 14:18:52 -07001360 return getIpEntry(matchActionOp);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001361 } else if (match instanceof MplsMatch) {
Saurav Das0a344b02014-09-26 14:18:52 -07001362 return getMplsEntry(matchActionOp);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001363 } else if (match instanceof PacketMatch) {
Saurav Das0a344b02014-09-26 14:18:52 -07001364 return getAclEntry(matchActionOp);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001365 } else {
1366 log.error("Unknown match type {} pushed to switch {}", match,
1367 getStringId());
1368 }
Saurav Das0a344b02014-09-26 14:18:52 -07001369 return null;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001370 }
1371
1372 @Override
1373 public void pushFlows(Collection<MatchActionOperationEntry> matchActionOps)
1374 throws IOException {
Saurav Das0a344b02014-09-26 14:18:52 -07001375 List<OFMessage> flowMods = new ArrayList<OFMessage>();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001376 for (MatchActionOperationEntry matchActionOp : matchActionOps) {
Saurav Das0a344b02014-09-26 14:18:52 -07001377 OFMessage ofm = getFlow(matchActionOp);
1378 if (ofm != null) {
1379 flowMods.add(ofm);
1380 }
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001381 }
Saurav Das0a344b02014-09-26 14:18:52 -07001382 write(flowMods);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001383 }
1384
1385 @Override
1386 public int getEcmpGroupId(NeighborSet ns) {
1387 EcmpInfo ei = ecmpGroups.get(ns);
1388 if (ei == null) {
1389 return -1;
1390 } else {
1391 return ei.groupId;
1392 }
1393 }
1394
1395 // *****************************
Saurav Das80d17392014-10-01 10:24:56 -07001396 // Unused
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001397 // *****************************
1398
Saurav Das80d17392014-10-01 10:24:56 -07001399 @SuppressWarnings("unused")
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001400 private void setAsyncConfig() throws IOException {
1401 List<OFMessage> msglist = new ArrayList<OFMessage>(3);
1402 OFMessage setAC = null;
1403
1404 if (role == Role.MASTER) {
1405 setAC = factory.buildAsyncSet()
1406 .setFlowRemovedMaskEqualMaster(SET_FLOW_REMOVED_MASK_MASTER)
1407 .setPacketInMaskEqualMaster(SET_PACKET_IN_MASK_MASTER)
1408 .setPortStatusMaskEqualMaster(SET_PORT_STATUS_MASK_MASTER)
1409 .setFlowRemovedMaskSlave(SET_ALL_SLAVE)
1410 .setPacketInMaskSlave(SET_ALL_SLAVE)
1411 .setPortStatusMaskSlave(SET_ALL_SLAVE)
1412 .setXid(getNextTransactionId())
1413 .build();
1414 } else if (role == Role.EQUAL) {
1415 setAC = factory.buildAsyncSet()
1416 .setFlowRemovedMaskEqualMaster(SET_FLOW_REMOVED_MASK_EQUAL)
1417 .setPacketInMaskEqualMaster(SET_PACKET_IN_MASK_EQUAL)
1418 .setPortStatusMaskEqualMaster(SET_PORT_STATUS_MASK_EQUAL)
1419 .setFlowRemovedMaskSlave(SET_ALL_SLAVE)
1420 .setPacketInMaskSlave(SET_ALL_SLAVE)
1421 .setPortStatusMaskSlave(SET_ALL_SLAVE)
1422 .setXid(getNextTransactionId())
1423 .build();
1424 }
1425 msglist.add(setAC);
1426
1427 OFMessage br = factory.buildBarrierRequest()
1428 .setXid(getNextTransactionId())
1429 .build();
1430 msglist.add(br);
1431
1432 OFMessage getAC = factory.buildAsyncGetRequest()
1433 .setXid(getNextTransactionId())
1434 .build();
1435 msglist.add(getAC);
1436
1437 write(msglist);
1438 }
1439
Saurav Das80d17392014-10-01 10:24:56 -07001440 @SuppressWarnings("unused")
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001441 private void decodeAsyncGetReply(OFAsyncGetReply rep) {
1442 long frm = rep.getFlowRemovedMaskEqualMaster();
Sangho Shin01bca862014-09-12 11:18:59 -07001443 long frs = rep.getFlowRemovedMaskSlave();
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001444 long pim = rep.getPacketInMaskEqualMaster();
Sangho Shin01bca862014-09-12 11:18:59 -07001445 long pis = rep.getPacketInMaskSlave();
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001446 long psm = rep.getPortStatusMaskEqualMaster();
Sangho Shin01bca862014-09-12 11:18:59 -07001447 long pss = rep.getPortStatusMaskSlave();
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001448
1449 if (role == Role.MASTER || role == Role.EQUAL) { // should separate
1450 log.info("FRM:{}", HexString.toHexString((frm & TEST_FLOW_REMOVED_MASK)));
1451 log.info("PIM:{}", HexString.toHexString((pim & TEST_PACKET_IN_MASK)));
1452 log.info("PSM:{}", HexString.toHexString((psm & TEST_PORT_STATUS_MASK)));
1453 }
1454
1455 }
1456
Saurav Das80d17392014-10-01 10:24:56 -07001457 @SuppressWarnings("unused")
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001458 private void getTableFeatures() throws IOException {
1459 OFMessage gtf = factory.buildTableFeaturesStatsRequest()
1460 .setXid(getNextTransactionId())
1461 .build();
1462 write(gtf, null);
1463 }
1464
Saurav Das80d17392014-10-01 10:24:56 -07001465 @SuppressWarnings("unused")
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001466 private void sendGroupFeaturesRequest() throws IOException {
1467 OFMessage gfr = factory.buildGroupFeaturesStatsRequest()
1468 .setXid(getNextTransactionId())
1469 .build();
1470 write(gfr, null);
1471 }
1472
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001473 private void processGroupFeatures(OFGroupFeaturesStatsReply gfsr) {
1474 log.info("Sw: {} Group Features {}", getStringId(), gfsr);
1475 }
1476
Fahad Naeem Khand563af62014-10-08 17:37:25 -07001477 @Override
1478 public TableId getTableId(String tableType) {
1479 tableType = tableType.toLowerCase();
1480 if(tableType.contentEquals("ip")){
1481 return TableId.of(OFSwitchImplCPqD13.TABLE_IPv4_UNICAST);
1482 }
1483 else if (tableType.contentEquals("mpls")){
1484 return TableId.of(OFSwitchImplCPqD13.TABLE_MPLS);
1485 }
1486 else if (tableType.contentEquals("acl")){
1487 return TableId.of(OFSwitchImplCPqD13.TABLE_ACL);
1488 }
1489 else{
1490 log.warn("Invalid tableType: {}", tableType);
1491 return null;
1492 }
1493 }
1494
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001495}