blob: 2353fb7205d819fb5af8b9ec84c522afea43c760 [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;
Srikanth Vavilapalli25fbe392014-10-10 15:04:51 -070014import java.util.concurrent.atomic.AtomicInteger;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070015
16import net.floodlightcontroller.core.IFloodlightProviderService.Role;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -070017import net.floodlightcontroller.core.IOF13Switch;
18import net.floodlightcontroller.core.IOFSwitch;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070019import net.floodlightcontroller.core.SwitchDriverSubHandshakeAlreadyStarted;
20import net.floodlightcontroller.core.SwitchDriverSubHandshakeCompleted;
21import net.floodlightcontroller.core.SwitchDriverSubHandshakeNotStarted;
22import net.floodlightcontroller.core.internal.OFSwitchImplBase;
Saurav Dase972b3a2014-09-26 15:41:06 -070023import net.floodlightcontroller.util.MACAddress;
Srikanth Vavilapalli25fbe392014-10-10 15:04:51 -070024import net.floodlightcontroller.util.OrderedCollection;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -070025import net.onrc.onos.core.configmanager.INetworkConfigService;
26import net.onrc.onos.core.configmanager.INetworkConfigService.NetworkConfigState;
27import net.onrc.onos.core.configmanager.INetworkConfigService.SwitchConfigStatus;
28import net.onrc.onos.core.configmanager.NetworkConfig.LinkConfig;
Srikanth Vavilapalli68144302014-10-08 15:55:24 -070029import net.onrc.onos.core.configmanager.NetworkConfig.SwitchConfig;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -070030import net.onrc.onos.core.configmanager.NetworkConfigManager;
31import net.onrc.onos.core.configmanager.PktLinkConfig;
32import net.onrc.onos.core.configmanager.SegmentRouterConfig;
33import net.onrc.onos.core.matchaction.MatchAction;
34import net.onrc.onos.core.matchaction.MatchActionOperationEntry;
Saurav Dasbc594a42014-09-25 20:13:50 -070035import net.onrc.onos.core.matchaction.MatchActionOperations;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -070036import net.onrc.onos.core.matchaction.MatchActionOperations.Operator;
37import net.onrc.onos.core.matchaction.action.Action;
38import net.onrc.onos.core.matchaction.action.CopyTtlInAction;
39import net.onrc.onos.core.matchaction.action.CopyTtlOutAction;
40import net.onrc.onos.core.matchaction.action.DecMplsTtlAction;
41import net.onrc.onos.core.matchaction.action.DecNwTtlAction;
42import net.onrc.onos.core.matchaction.action.GroupAction;
43import net.onrc.onos.core.matchaction.action.ModifyDstMacAction;
44import net.onrc.onos.core.matchaction.action.ModifySrcMacAction;
45import net.onrc.onos.core.matchaction.action.OutputAction;
46import net.onrc.onos.core.matchaction.action.PopMplsAction;
Saurav Dasa962a692014-10-17 14:52:38 -070047import net.onrc.onos.core.matchaction.action.PushMplsAction;
48import net.onrc.onos.core.matchaction.action.SetMplsBosAction;
49import net.onrc.onos.core.matchaction.action.SetMplsIdAction;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -070050import net.onrc.onos.core.matchaction.match.Ipv4Match;
51import net.onrc.onos.core.matchaction.match.Match;
52import net.onrc.onos.core.matchaction.match.MplsMatch;
53import net.onrc.onos.core.matchaction.match.PacketMatch;
54import net.onrc.onos.core.util.Dpid;
55import net.onrc.onos.core.util.IPv4Net;
56import net.onrc.onos.core.util.PortNumber;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070057
58import org.projectfloodlight.openflow.protocol.OFAsyncGetReply;
59import org.projectfloodlight.openflow.protocol.OFBarrierRequest;
60import org.projectfloodlight.openflow.protocol.OFBucket;
61import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
62import org.projectfloodlight.openflow.protocol.OFErrorMsg;
63import org.projectfloodlight.openflow.protocol.OFFactory;
Saurav Dase972b3a2014-09-26 15:41:06 -070064import org.projectfloodlight.openflow.protocol.OFFlowMod;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070065import org.projectfloodlight.openflow.protocol.OFGroupDescStatsReply;
66import org.projectfloodlight.openflow.protocol.OFGroupFeaturesStatsReply;
67import org.projectfloodlight.openflow.protocol.OFGroupType;
68import org.projectfloodlight.openflow.protocol.OFMatchV3;
69import org.projectfloodlight.openflow.protocol.OFMessage;
70import org.projectfloodlight.openflow.protocol.OFOxmList;
71import org.projectfloodlight.openflow.protocol.OFPortDesc;
Srikanth Vavilapalli25fbe392014-10-10 15:04:51 -070072import org.projectfloodlight.openflow.protocol.OFPortStatus;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070073import org.projectfloodlight.openflow.protocol.OFStatsReply;
74import org.projectfloodlight.openflow.protocol.action.OFAction;
75import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
Saurav Dase972b3a2014-09-26 15:41:06 -070076import org.projectfloodlight.openflow.protocol.match.Match.Builder;
77import org.projectfloodlight.openflow.protocol.match.MatchField;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070078import org.projectfloodlight.openflow.protocol.oxm.OFOxmEthDst;
79import org.projectfloodlight.openflow.protocol.oxm.OFOxmEthSrc;
80import org.projectfloodlight.openflow.protocol.oxm.OFOxmEthType;
81import org.projectfloodlight.openflow.protocol.oxm.OFOxmInPort;
82import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv4DstMasked;
Saurav Dascc3e35f2014-10-10 15:33:32 -070083import org.projectfloodlight.openflow.protocol.oxm.OFOxmMplsBos;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070084import org.projectfloodlight.openflow.protocol.oxm.OFOxmMplsLabel;
85import org.projectfloodlight.openflow.protocol.oxm.OFOxmVlanVid;
86import org.projectfloodlight.openflow.types.EthType;
87import org.projectfloodlight.openflow.types.IPv4Address;
Saurav Dase972b3a2014-09-26 15:41:06 -070088import org.projectfloodlight.openflow.types.IpProtocol;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070089import org.projectfloodlight.openflow.types.MacAddress;
Saurav Dascc3e35f2014-10-10 15:33:32 -070090import org.projectfloodlight.openflow.types.OFBooleanValue;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070091import org.projectfloodlight.openflow.types.OFBufferId;
92import org.projectfloodlight.openflow.types.OFGroup;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070093import org.projectfloodlight.openflow.types.OFPort;
94import org.projectfloodlight.openflow.types.OFVlanVidMatch;
95import org.projectfloodlight.openflow.types.TableId;
Saurav Dase972b3a2014-09-26 15:41:06 -070096import org.projectfloodlight.openflow.types.TransportPort;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070097import org.projectfloodlight.openflow.types.U32;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070098import org.projectfloodlight.openflow.util.HexString;
99
100/**
101 * OFDescriptionStatistics Vendor (Manufacturer Desc.): Stanford University,
102 * Ericsson Research and CPqD Research. Make (Hardware Desc.) : OpenFlow 1.3
103 * Reference Userspace Switch Model (Datapath Desc.) : None Software : Serial :
104 * None
105 */
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700106public class OFSwitchImplCPqD13 extends OFSwitchImplBase implements IOF13Switch {
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700107 private AtomicBoolean driverHandshakeComplete;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700108 private AtomicBoolean haltStateMachine;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700109 private OFFactory factory;
110 private static final int OFPCML_NO_BUFFER = 0xffff;
111 // Configuration of asynch messages to controller. We need different
112 // asynch messages depending on role-equal or role-master.
113 // We don't want to get anything if we are slave.
114 private static final long SET_FLOW_REMOVED_MASK_MASTER = 0xf;
115 private static final long SET_PACKET_IN_MASK_MASTER = 0x7;
116 private static final long SET_PORT_STATUS_MASK_MASTER = 0x7;
117 private static final long SET_FLOW_REMOVED_MASK_EQUAL = 0x0;
118 private static final long SET_PACKET_IN_MASK_EQUAL = 0x0;
119 private static final long SET_PORT_STATUS_MASK_EQUAL = 0x7;
120 private static final long SET_ALL_SLAVE = 0x0;
121
122 private static final long TEST_FLOW_REMOVED_MASK = 0xf;
123 private static final long TEST_PACKET_IN_MASK = 0x7;
124 private static final long TEST_PORT_STATUS_MASK = 0x7;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700125
126 private static final int TABLE_VLAN = 0;
127 private static final int TABLE_TMAC = 1;
Sangho Shin01bca862014-09-12 11:18:59 -0700128 private static final int TABLE_IPv4_UNICAST = 2;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700129 private static final int TABLE_MPLS = 3;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700130 private static final int TABLE_ACL = 5;
131
132 private static final short MAX_PRIORITY = (short) 0xffff;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700133 private static final short PRIORITY_MULTIPLIER = (short) 2046;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700134 private static final short MIN_PRIORITY = 0x0;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700135
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700136 private long barrierXidToWaitFor = -1;
137 private DriverState driverState;
Jonathan Hartcb34f382014-08-12 21:11:03 -0700138 private final boolean usePipeline13;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700139 private SegmentRouterConfig srConfig;
140 private ConcurrentMap<Dpid, Set<PortNumber>> neighbors;
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700141 private ConcurrentMap<PortNumber, Dpid> portToNeighbors;
Srikanth Vavilapalli2cd0ff12014-10-10 13:07:46 -0700142 private List<Integer> segmentIds;
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700143 private boolean isEdgeRouter;
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700144 private int sid;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700145 private ConcurrentMap<NeighborSet, EcmpInfo> ecmpGroups;
Sangho Shin4b46bcd2014-10-20 15:48:47 -0700146 private ConcurrentMap<String, List<Integer>> tunnelGroupIdTable;
Srikanth Vavilapallib95e6e02014-10-02 13:56:39 -0700147 private ConcurrentMap<PortNumber, ArrayList<NeighborSet>> portNeighborSetMap;
Srikanth Vavilapalli25fbe392014-10-10 15:04:51 -0700148 private AtomicInteger groupid;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700149
Jonathan Hartcb34f382014-08-12 21:11:03 -0700150 public OFSwitchImplCPqD13(OFDescStatsReply desc, boolean usePipeline13) {
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700151 super();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700152 haltStateMachine = new AtomicBoolean(false);
153 driverState = DriverState.INIT;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700154 driverHandshakeComplete = new AtomicBoolean(false);
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700155 setSwitchDescription(desc);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700156 neighbors = new ConcurrentHashMap<Dpid, Set<PortNumber>>();
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700157 portToNeighbors = new ConcurrentHashMap<PortNumber, Dpid>();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700158 ecmpGroups = new ConcurrentHashMap<NeighborSet, EcmpInfo>();
Srikanth Vavilapallib95e6e02014-10-02 13:56:39 -0700159 portNeighborSetMap =
160 new ConcurrentHashMap<PortNumber, ArrayList<NeighborSet>>();
Sangho Shin4b46bcd2014-10-20 15:48:47 -0700161 tunnelGroupIdTable = new ConcurrentHashMap<String, List<Integer>>();
Srikanth Vavilapalli2cd0ff12014-10-10 13:07:46 -0700162 segmentIds = new ArrayList<Integer>();
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700163 isEdgeRouter = false;
Srikanth Vavilapalli25fbe392014-10-10 15:04:51 -0700164 groupid = new AtomicInteger(0);
Jonathan Hartcb34f382014-08-12 21:11:03 -0700165 this.usePipeline13 = usePipeline13;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700166 }
167
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700168 // *****************************
169 // OFSwitchImplBase
170 // *****************************
171
172
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700173 /* (non-Javadoc)
174 * @see java.lang.Object#toString()
175 */
176 @Override
177 public String toString() {
178 return "OFSwitchImplCPqD13 [" + ((channel != null)
179 ? channel.getRemoteAddress() : "?")
180 + " DPID[" + ((stringId != null) ? stringId : "?") + "]]";
181 }
182
183 @Override
184 public void startDriverHandshake() throws IOException {
185 log.debug("Starting driver handshake for sw {}", getStringId());
186 if (startDriverHandshakeCalled) {
187 throw new SwitchDriverSubHandshakeAlreadyStarted();
188 }
189 startDriverHandshakeCalled = true;
Jonathan Harta213bce2014-08-11 15:44:07 -0700190 factory = getFactory();
Jonathan Hartcb34f382014-08-12 21:11:03 -0700191 if (!usePipeline13) {
192 // Send packet-in to controller if a packet misses the first table
193 populateTableMissEntry(0, true, false, false, 0);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700194 driverHandshakeComplete.set(true);
Sangho Shin01bca862014-09-12 11:18:59 -0700195 } else {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700196 nextDriverState();
Sangho Shin01bca862014-09-12 11:18:59 -0700197 }
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700198 }
199
200 @Override
201 public boolean isDriverHandshakeComplete() {
Sangho Shin01bca862014-09-12 11:18:59 -0700202 if (!startDriverHandshakeCalled)
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700203 throw new SwitchDriverSubHandshakeNotStarted();
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700204 return driverHandshakeComplete.get();
205 }
206
207 @Override
208 public void processDriverHandshakeMessage(OFMessage m) {
Sangho Shin01bca862014-09-12 11:18:59 -0700209 if (!startDriverHandshakeCalled)
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700210 throw new SwitchDriverSubHandshakeNotStarted();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700211 if (isDriverHandshakeComplete())
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700212 throw new SwitchDriverSubHandshakeCompleted(m);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700213 try {
214 processOFMessage(this, m);
215 } catch (IOException e) {
216 log.error("Error generated when processing OFMessage", e.getCause());
217 }
218 }
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700219
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700220 @Override
221 public String getSwitchDriverState() {
222 return driverState.toString();
223 }
224
Srikanth Vavilapallibd9b3e22014-10-02 08:57:46 -0700225 public void removePortFromGroups(PortNumber port) {
Srikanth Vavilapallicf1840b2014-10-09 15:29:51 -0700226 /* FIX: removePortFromGroups is not working */
227
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700228 log.debug("removePortFromGroups: Remove port {} from Switch {}",
229 port, getStringId());
230 ArrayList<NeighborSet> portNSSet = portNeighborSetMap.get(port);
231 if (portNSSet == null)
232 {
233 /* No Groups are created with this port yet */
234 log.warn("removePortFromGroups: No groups exist with Switch {} port {}",
Srikanth Vavilapallicf1840b2014-10-09 15:29:51 -0700235 getStringId(), port);
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700236 return;
237 }
238 log.debug("removePortFromGroups: Neighborsets that the port {} is part"
239 + "of on Switch {} are {}",
240 port, getStringId(), portNSSet);
241
242 for (NeighborSet ns : portNSSet) {
243 /* Delete the first matched bucket */
244 EcmpInfo portEcmpInfo = ecmpGroups.get(ns);
245 Iterator<BucketInfo> it = portEcmpInfo.buckets.iterator();
Srikanth Vavilapalli2cd0ff12014-10-10 13:07:46 -0700246 log.debug("removePortFromGroups: Group {} on Switch {} has {} buckets",
247 portEcmpInfo.groupId, getStringId(),
248 portEcmpInfo.buckets.size());
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700249 while (it.hasNext()) {
250 BucketInfo bucket = it.next();
251 if (bucket.outport.equals(port)) {
252 it.remove();
Srikanth Vavilapallibd9b3e22014-10-02 08:57:46 -0700253 }
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700254 }
255 log.debug("removePortFromGroups: Modifying Group on Switch {} "
256 + "and Neighborset {} with {}",
257 getStringId(), ns, portEcmpInfo);
258 modifyEcmpGroup(portEcmpInfo);
259 }
260 /* Don't delete the entry from portNeighborSetMap because
Srikanth Vavilapallicf1840b2014-10-09 15:29:51 -0700261 * when the port is up again this info is needed
262 */
Srikanth Vavilapalli7d873fd2014-10-04 07:50:57 -0700263 return;
Srikanth Vavilapallibd9b3e22014-10-02 08:57:46 -0700264 }
265
266 public void addPortToGroups(PortNumber port) {
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700267 log.debug("addPortToGroups: Add port {} to Switch {}",
268 port, getStringId());
269 ArrayList<NeighborSet> portNSSet = portNeighborSetMap.get(port);
270 if (portNSSet == null) {
271 /* Unknown Port */
272 log.warn("addPortToGroups: Switch {} port {} is unknown",
Srikanth Vavilapallicf1840b2014-10-09 15:29:51 -0700273 getStringId(), port);
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700274 return;
275 }
276 log.debug("addPortToGroups: Neighborsets that the port {} is part"
277 + "of on Switch {} are {}",
278 port, getStringId(), portNSSet);
279
280 Dpid neighborDpid = portToNeighbors.get(port);
281 for (NeighborSet ns : portNSSet) {
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700282 EcmpInfo portEcmpInfo = ecmpGroups.get(ns);
Srikanth Vavilapalli2cd0ff12014-10-10 13:07:46 -0700283 /* Find if this port is already part of any bucket
284 * in this group
285 * NOTE: This is needed because in some cases
286 * (such as for configured network nodes), both driver and
287 * application detect the network elements and creates the
288 * buckets in the same group. This check is to avoid
289 * duplicate bucket creation in such scenarios
290 */
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700291 List<BucketInfo> buckets = portEcmpInfo.buckets;
292 if (buckets == null) {
293 buckets = new ArrayList<BucketInfo>();
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700294 portEcmpInfo.buckets = buckets;
295 } else {
Srikanth Vavilapalli2cd0ff12014-10-10 13:07:46 -0700296 Iterator<BucketInfo> it = buckets.iterator();
297 boolean matchingBucketExist = false;
298 while (it.hasNext()) {
299 BucketInfo bucket = it.next();
300 if (bucket.outport.equals(port)) {
301 matchingBucketExist = true;
302 break;
303 }
304 }
305 if (matchingBucketExist) {
306 log.warn("addPortToGroups: On Switch {} duplicate "
307 + "portAdd is called for port {} with buckets {}",
308 getStringId(), port, buckets);
309 continue;
310 }
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700311 }
Srikanth Vavilapalli2cd0ff12014-10-10 13:07:46 -0700312 BucketInfo b = new BucketInfo(neighborDpid,
313 MacAddress.of(srConfig.getRouterMac()),
314 getNeighborRouterMacAddress(neighborDpid),
315 port,
316 ns.getEdgeLabel());
317 buckets.add(b);
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700318 log.debug("addPortToGroups: Modifying Group on Switch {} "
319 + "and Neighborset {} with {}",
320 getStringId(), ns, portEcmpInfo);
321 modifyEcmpGroup(portEcmpInfo);
322 }
323 return;
Srikanth Vavilapallibd9b3e22014-10-02 08:57:46 -0700324 }
325
Srikanth Vavilapalli25fbe392014-10-10 15:04:51 -0700326 @Override
327 public OrderedCollection<PortChangeEvent> processOFPortStatus(OFPortStatus ps) {
328 OrderedCollection<PortChangeEvent> events = super.processOFPortStatus(ps);
329 for (PortChangeEvent e : events) {
330 switch (e.type) {
331 case DELETE:
332 case DOWN:
333 log.debug("processOFPortStatus: sw {} Port {} DOWN",
334 getStringId(), e.port.getPortNo().getPortNumber());
335 removePortFromGroups(PortNumber.uint32(
336 e.port.getPortNo().getPortNumber()));
337 break;
338 case UP:
339 log.debug("processOFPortStatus: sw {} Port {} UP",
340 getStringId(), e.port.getPortNo().getPortNumber());
341 addPortToGroups(PortNumber.uint32(
342 e.port.getPortNo().getPortNumber()));
343 }
344 }
345 return events;
346 }
347
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700348 // *****************************
349 // Driver handshake state-machine
350 // *****************************
351
352 enum DriverState {
353 INIT,
354 SET_TABLE_MISS_ENTRIES,
355 SET_TABLE_VLAN_TMAC,
356 SET_GROUPS,
357 VERIFY_GROUPS,
358 SET_ADJACENCY_LABELS,
359 EXIT
360 }
361
362 protected void nextDriverState() throws IOException {
363 DriverState currentState = driverState;
Saurav Das80d17392014-10-01 10:24:56 -0700364 if (haltStateMachine.get()) {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700365 return;
Saurav Das80d17392014-10-01 10:24:56 -0700366 }
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700367 switch (currentState) {
368 case INIT:
369 driverState = DriverState.SET_TABLE_MISS_ENTRIES;
370 setTableMissEntries();
Saurav Dasd84178f2014-09-29 17:48:54 -0700371 sendHandshakeBarrier();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700372 break;
373 case SET_TABLE_MISS_ENTRIES:
374 driverState = DriverState.SET_TABLE_VLAN_TMAC;
375 getNetworkConfig();
376 populateTableVlan();
377 populateTableTMac();
Saurav Dasd84178f2014-09-29 17:48:54 -0700378 sendHandshakeBarrier();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700379 break;
380 case SET_TABLE_VLAN_TMAC:
381 driverState = DriverState.SET_GROUPS;
382 createGroups();
Saurav Dasd84178f2014-09-29 17:48:54 -0700383 sendHandshakeBarrier();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700384 break;
385 case SET_GROUPS:
386 driverState = DriverState.VERIFY_GROUPS;
387 verifyGroups();
388 break;
389 case VERIFY_GROUPS:
390 driverState = DriverState.SET_ADJACENCY_LABELS;
391 assignAdjacencyLabels();
392 break;
393 case SET_ADJACENCY_LABELS:
394 driverState = DriverState.EXIT;
395 driverHandshakeComplete.set(true);
396 break;
397 case EXIT:
398 default:
399 driverState = DriverState.EXIT;
400 log.error("Driver handshake has exited for sw: {}", getStringId());
401 }
402 }
403
404 void processOFMessage(IOFSwitch sw, OFMessage m) throws IOException {
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700405 switch (m.getType()) {
406 case BARRIER_REPLY:
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700407 processBarrierReply(m);
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700408 break;
409
410 case ERROR:
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700411 processErrorMessage(m);
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700412 break;
413
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700414 case GET_ASYNC_REPLY:
415 OFAsyncGetReply asrep = (OFAsyncGetReply) m;
416 decodeAsyncGetReply(asrep);
417 break;
418
419 case PACKET_IN:
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700420 // not ready to handle packet-ins
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700421 break;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700422
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700423 case QUEUE_GET_CONFIG_REPLY:
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700424 // not doing queue config yet
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700425 break;
426
427 case STATS_REPLY:
428 processStatsReply((OFStatsReply) m);
429 break;
430
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700431 case ROLE_REPLY: // channelHandler should handle this
432 case PORT_STATUS: // channelHandler should handle this
433 case FEATURES_REPLY: // don't care
434 case FLOW_REMOVED: // don't care
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700435 default:
436 log.debug("Received message {} during switch-driver subhandshake "
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700437 + "from switch {} ... Ignoring message", m, sw.getStringId());
438 }
439 }
440
441 private void processStatsReply(OFStatsReply sr) {
442 switch (sr.getStatsType()) {
443 case AGGREGATE:
444 break;
445 case DESC:
446 break;
447 case EXPERIMENTER:
448 break;
449 case FLOW:
450 break;
451 case GROUP_DESC:
452 processGroupDesc((OFGroupDescStatsReply) sr);
453 break;
454 case GROUP_FEATURES:
455 processGroupFeatures((OFGroupFeaturesStatsReply) sr);
456 break;
457 case METER_CONFIG:
458 break;
459 case METER_FEATURES:
460 break;
461 case PORT_DESC:
462 break;
463 case TABLE_FEATURES:
464 break;
465 default:
466 break;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700467
468 }
469 }
470
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700471 private void processErrorMessage(OFMessage m) {
472 log.error("Switch {} Error {} in DriverState", getStringId(),
473 (OFErrorMsg) m, driverState);
474 }
475
476 private void processBarrierReply(OFMessage m) throws IOException {
477 if (m.getXid() == barrierXidToWaitFor) {
478 // Driver state-machine progresses to the next state.
479 // If Barrier messages is not received, then eventually
480 // the ChannelHandler state machine will timeout, and the switch
481 // will be disconnected.
482 nextDriverState();
483 } else {
484 log.error("Received incorrect barrier-message xid {} (expected: {}) in "
485 + "switch-driver state {} for switch {}", m, barrierXidToWaitFor,
486 driverState, getStringId());
487 }
488 }
489
490 private void processGroupDesc(OFGroupDescStatsReply gdsr) {
491 log.info("Sw: {} Group Desc {}", getStringId(), gdsr);
492 try {
493 nextDriverState();
494 } catch (IOException e) {
495 // TODO Auto-generated catch block
496 e.printStackTrace();
497 }
498 }
499
500 // *****************************
501 // Utility methods
502 // *****************************
503
504 void setTableMissEntries() throws IOException {
505 // set all table-miss-entries
506 populateTableMissEntry(TABLE_VLAN, true, false, false, -1);
507 populateTableMissEntry(TABLE_TMAC, true, false, false, -1);
508 populateTableMissEntry(TABLE_IPv4_UNICAST, false, true, true,
509 TABLE_ACL);
510 populateTableMissEntry(TABLE_MPLS, false, true, true,
511 TABLE_ACL);
512 populateTableMissEntry(TABLE_ACL, false, false, false, -1);
513 }
514
Saurav Dasd84178f2014-09-29 17:48:54 -0700515 private void sendHandshakeBarrier() throws IOException {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700516 long xid = getNextTransactionId();
517 barrierXidToWaitFor = xid;
518 OFBarrierRequest br = getFactory()
519 .buildBarrierRequest()
520 .setXid(xid)
521 .build();
522 write(br, null);
523 }
524
525 /**
526 * Adds a table-miss-entry to a pipeline table.
527 * <p>
528 * The table-miss-entry can be added with 'write-actions' or
529 * 'apply-actions'. It can also add a 'goto-table' instruction. By default
530 * if none of the booleans in the call are set, then the table-miss entry is
531 * added with no instructions, which means that if a packet hits the
532 * table-miss-entry, pipeline execution will stop, and the action set
533 * associated with the packet will be executed.
534 *
535 * @param tableToAdd the table to where the table-miss-entry will be added
536 * @param toControllerNow as an APPLY_ACTION instruction
537 * @param toControllerWrite as a WRITE_ACTION instruction
538 * @param toTable as a GOTO_TABLE instruction
539 * @param tableToSend the table to send as per the GOTO_TABLE instruction it
540 * needs to be set if 'toTable' is true. Ignored of 'toTable' is
541 * false.
542 * @throws IOException
543 */
544 @SuppressWarnings("unchecked")
545 private void populateTableMissEntry(int tableToAdd, boolean toControllerNow,
546 boolean toControllerWrite,
547 boolean toTable, int tableToSend) throws IOException {
548 OFOxmList oxmList = OFOxmList.EMPTY;
549 OFMatchV3 match = factory.buildMatchV3()
550 .setOxmList(oxmList)
551 .build();
552 OFAction outc = factory.actions()
553 .buildOutput()
554 .setPort(OFPort.CONTROLLER)
555 .setMaxLen(OFPCML_NO_BUFFER)
556 .build();
557 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
558 if (toControllerNow) {
559 // table-miss instruction to send to controller immediately
560 OFInstruction instr = factory.instructions()
561 .buildApplyActions()
562 .setActions(Collections.singletonList(outc))
563 .build();
564 instructions.add(instr);
565 }
566
567 if (toControllerWrite) {
568 // table-miss instruction to write-action to send to controller
569 // this will be executed whenever the action-set gets executed
570 OFInstruction instr = factory.instructions()
571 .buildWriteActions()
572 .setActions(Collections.singletonList(outc))
573 .build();
574 instructions.add(instr);
575 }
576
577 if (toTable) {
578 // table-miss instruction to goto-table x
579 OFInstruction instr = factory.instructions()
580 .gotoTable(TableId.of(tableToSend));
581 instructions.add(instr);
582 }
583
584 if (!toControllerNow && !toControllerWrite && !toTable) {
585 // table-miss has no instruction - at which point action-set will be
586 // executed - if there is an action to output/group in the action
587 // set
588 // the packet will be sent there, otherwise it will be dropped.
589 instructions = (List<OFInstruction>) Collections.EMPTY_LIST;
590 }
591
592 OFMessage tableMissEntry = factory.buildFlowAdd()
593 .setTableId(TableId.of(tableToAdd))
594 .setMatch(match) // match everything
595 .setInstructions(instructions)
596 .setPriority(MIN_PRIORITY)
597 .setBufferId(OFBufferId.NO_BUFFER)
598 .setIdleTimeout(0)
599 .setHardTimeout(0)
600 .setXid(getNextTransactionId())
601 .build();
602 write(tableMissEntry, null);
603 }
604
605 private void getNetworkConfig() {
606 INetworkConfigService ncs = floodlightProvider.getNetworkConfigService();
607 SwitchConfigStatus scs = ncs.checkSwitchConfig(new Dpid(getId()));
608 if (scs.getConfigState() == NetworkConfigState.ACCEPT_ADD) {
609 srConfig = (SegmentRouterConfig) scs.getSwitchConfig();
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700610 isEdgeRouter = srConfig.isEdgeRouter();
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700611 sid = srConfig.getNodeSid();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700612 } else {
613 log.error("Switch not configured as Segment-Router");
614 }
615
616 List<LinkConfig> linkConfigList = ncs.getConfiguredAllowedLinks();
617 setNeighbors(linkConfigList);
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700618
619 if (isEdgeRouter) {
620 List<SwitchConfig> switchList = ncs.getConfiguredAllowedSwitches();
Srikanth Vavilapalli2cd0ff12014-10-10 13:07:46 -0700621 getAllNodeSegmentIds(switchList);
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700622 }
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700623 }
624
625 private void populateTableVlan() throws IOException {
626 List<OFMessage> msglist = new ArrayList<OFMessage>();
627 for (OFPortDesc p : getPorts()) {
628 int pnum = p.getPortNo().getPortNumber();
629 if (U32.of(pnum).compareTo(U32.of(OFPort.MAX.getPortNumber())) < 1) {
630 OFOxmInPort oxp = factory.oxms().inPort(p.getPortNo());
631 OFOxmVlanVid oxv = factory.oxms()
632 .vlanVid(OFVlanVidMatch.UNTAGGED);
633 OFOxmList oxmList = OFOxmList.of(oxp, oxv);
634 OFMatchV3 match = factory.buildMatchV3()
635 .setOxmList(oxmList).build();
636
637 // TODO: match on vlan-tagged packets for vlans configured on
638 // subnet ports and strip-vlan
639
640 // Do not need to add vlans
641 /*int vlanid = getVlanConfig(pnum);
642 OFOxmVlanVid vidToSet = factory.oxms()
643 .vlanVid(OFVlanVidMatch.ofVlan(vlanid));
644 OFAction pushVlan = factory.actions().pushVlan(EthType.VLAN_FRAME);
645 OFAction setVlan = factory.actions().setField(vidToSet);
646 List<OFAction> actionlist = new ArrayList<OFAction>();
647 actionlist.add(pushVlan);
648 actionlist.add(setVlan);
649 OFInstruction appAction = factory.instructions().buildApplyActions()
650 .setActions(actionlist).build();*/
651
652 OFInstruction gotoTbl = factory.instructions().buildGotoTable()
653 .setTableId(TableId.of(TABLE_TMAC)).build();
654 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
655 // instructions.add(appAction);
656 instructions.add(gotoTbl);
657 OFMessage flowEntry = factory.buildFlowAdd()
658 .setTableId(TableId.of(TABLE_VLAN))
659 .setMatch(match)
660 .setInstructions(instructions)
661 .setPriority(1000) // does not matter - all rules
662 // exclusive
663 .setBufferId(OFBufferId.NO_BUFFER)
664 .setIdleTimeout(0)
665 .setHardTimeout(0)
666 .setXid(getNextTransactionId())
667 .build();
668 msglist.add(flowEntry);
669 }
670 }
671 write(msglist);
672 log.debug("Adding {} port/vlan-rules in sw {}", msglist.size(), getStringId());
673 }
674
675 private void populateTableTMac() throws IOException {
676 // match for router-mac and ip-packets
677 OFOxmEthType oxe = factory.oxms().ethType(EthType.IPv4);
678 OFOxmEthDst dmac = factory.oxms().ethDst(getRouterMacAddr());
679 OFOxmList oxmListIp = OFOxmList.of(dmac, oxe);
680 OFMatchV3 matchIp = factory.buildMatchV3()
681 .setOxmList(oxmListIp).build();
682 OFInstruction gotoTblIp = factory.instructions().buildGotoTable()
683 .setTableId(TableId.of(TABLE_IPv4_UNICAST)).build();
684 List<OFInstruction> instructionsIp = Collections.singletonList(gotoTblIp);
685 OFMessage ipEntry = factory.buildFlowAdd()
686 .setTableId(TableId.of(TABLE_TMAC))
687 .setMatch(matchIp)
688 .setInstructions(instructionsIp)
689 .setPriority(1000) // strict priority required lower than
690 // multicastMac
691 .setBufferId(OFBufferId.NO_BUFFER)
692 .setIdleTimeout(0)
693 .setHardTimeout(0)
694 .setXid(getNextTransactionId())
695 .build();
696
697 // match for router-mac and mpls packets
698 OFOxmEthType oxmpls = factory.oxms().ethType(EthType.MPLS_UNICAST);
699 OFOxmList oxmListMpls = OFOxmList.of(dmac, oxmpls);
700 OFMatchV3 matchMpls = factory.buildMatchV3()
701 .setOxmList(oxmListMpls).build();
702 OFInstruction gotoTblMpls = factory.instructions().buildGotoTable()
703 .setTableId(TableId.of(TABLE_MPLS)).build();
704 List<OFInstruction> instructionsMpls = Collections.singletonList(gotoTblMpls);
705 OFMessage mplsEntry = factory.buildFlowAdd()
706 .setTableId(TableId.of(TABLE_TMAC))
707 .setMatch(matchMpls)
708 .setInstructions(instructionsMpls)
709 .setPriority(1001) // strict priority required lower than
710 // multicastMac
711 .setBufferId(OFBufferId.NO_BUFFER)
712 .setIdleTimeout(0)
713 .setHardTimeout(0)
714 .setXid(getNextTransactionId())
715 .build();
716
717 log.debug("Adding termination-mac-rules in sw {}", getStringId());
718 List<OFMessage> msglist = new ArrayList<OFMessage>(2);
719 msglist.add(ipEntry);
720 msglist.add(mplsEntry);
721 write(msglist);
722 }
723
724 private MacAddress getRouterMacAddr() {
725 if (srConfig != null) {
726 return MacAddress.of(srConfig.getRouterMac());
727 } else {
728 // return a dummy mac address - it will not be used
729 return MacAddress.of("00:00:00:00:00:00");
730 }
731 }
732
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700733 private boolean isEdgeRouter(Dpid ndpid) {
734 INetworkConfigService ncs = floodlightProvider.getNetworkConfigService();
735 SwitchConfigStatus scs = ncs.checkSwitchConfig(ndpid);
736 if (scs.getConfigState() == NetworkConfigState.ACCEPT_ADD) {
737 return ((SegmentRouterConfig) scs.getSwitchConfig()).isEdgeRouter();
738 } else {
739 // TODO: return false if router not allowed
740 return false;
741 }
742 }
743
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700744 private MacAddress getNeighborRouterMacAddress(Dpid ndpid) {
745 INetworkConfigService ncs = floodlightProvider.getNetworkConfigService();
746 SwitchConfigStatus scs = ncs.checkSwitchConfig(ndpid);
747 if (scs.getConfigState() == NetworkConfigState.ACCEPT_ADD) {
748 return MacAddress.of(((SegmentRouterConfig) scs.getSwitchConfig())
749 .getRouterMac());
750 } else {
751 // return a dummy mac address - it will not be used
752 return MacAddress.of("00:00:00:00:00:00");
753 }
754 }
755
756 private void setNeighbors(List<LinkConfig> linkConfigList) {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700757 for (LinkConfig lg : linkConfigList) {
758 if (!lg.getType().equals(NetworkConfigManager.PKT_LINK)) {
Saurav Das80d17392014-10-01 10:24:56 -0700759 continue;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700760 }
761 PktLinkConfig plg = (PktLinkConfig) lg;
762 if (plg.getDpid1() == getId()) {
763 addNeighborAtPort(new Dpid(plg.getDpid2()),
764 PortNumber.uint32(plg.getPort1()));
765 } else if (plg.getDpid2() == getId()) {
766 addNeighborAtPort(new Dpid(plg.getDpid1()),
767 PortNumber.uint32(plg.getPort2()));
768 }
769 }
770 }
771
772 private void addNeighborAtPort(Dpid neighborDpid, PortNumber portToNeighbor) {
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700773 /* Update NeighborToPort database */
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700774 if (neighbors.get(neighborDpid) != null) {
775 neighbors.get(neighborDpid).add(portToNeighbor);
776 } else {
777 Set<PortNumber> ports = new HashSet<PortNumber>();
778 ports.add(portToNeighbor);
779 neighbors.put(neighborDpid, ports);
780 }
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700781
782 /* Update portToNeighbors database */
783 if (portToNeighbors.get(portToNeighbor) == null)
784 portToNeighbors.put(portToNeighbor, neighborDpid);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700785 }
786
Srikanth Vavilapalli2cd0ff12014-10-10 13:07:46 -0700787 private void getAllNodeSegmentIds(List<SwitchConfig> switchList) {
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700788 for (SwitchConfig sc : switchList) {
789 /* TODO: Do we need to check if the SwitchConfig is of
790 * type SegmentRouter?
791 */
Srikanth Vavilapalli2cd0ff12014-10-10 13:07:46 -0700792 if (sc.getDpid() == getId()) {
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700793 continue;
794 }
Srikanth Vavilapalli2cd0ff12014-10-10 13:07:46 -0700795 segmentIds.add(((SegmentRouterConfig) sc).getNodeSid());
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700796 }
Srikanth Vavilapalli2cd0ff12014-10-10 13:07:46 -0700797 log.debug("getAllNodeSegmentIds: at sw {} are {}",
798 getStringId(), segmentIds);
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700799 }
800
Srikanth Vavilapalli2cd0ff12014-10-10 13:07:46 -0700801 private boolean isSegmentIdSameAsNodeSegmentId(Dpid dpid, int sId) {
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700802 INetworkConfigService ncs = floodlightProvider.getNetworkConfigService();
803 SwitchConfigStatus scs = ncs.checkSwitchConfig(dpid);
804 if (scs.getConfigState() == NetworkConfigState.ACCEPT_ADD) {
805 return (((SegmentRouterConfig) scs.getSwitchConfig()).
Srikanth Vavilapalli2cd0ff12014-10-10 13:07:46 -0700806 getNodeSid() == sId);
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700807 } else {
808 // TODO: return false if router not allowed
809 return false;
810 }
811 }
812
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700813 private Set<Set<Dpid>> getAllNeighborSets(Set<Dpid> neighbors) {
814 List<Dpid> list = new ArrayList<Dpid>(neighbors);
815 Set<Set<Dpid>> sets = new HashSet<Set<Dpid>>();
816 /* get the number of elements in the neighbors */
817 int elements = list.size();
818 /* the number of members of a power set is 2^n
819 * including the empty set
820 */
821 int powerElements = (1 << elements);
822
823 /* run a binary counter for the number of power elements */
824 for (long i = 1; i < powerElements; i++) {
825 Set<Dpid> dpidSubSet = new HashSet<Dpid>();
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700826 for (int j = 0; j < elements; j++) {
827 if ((i >> j) % 2 == 1) {
828 dpidSubSet.add(list.get(j));
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700829 }
830 }
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700831 /* NOTE: Avoid any pairings of edge routers only
832 * at a backbone router */
833 boolean avoidEdgeRouterPairing = true;
834 if ((!isEdgeRouter) && (dpidSubSet.size() > 1)) {
Srikanth Vavilapalli696010f2014-10-08 17:00:17 -0700835 for (Dpid dpid : dpidSubSet) {
836 if (!isEdgeRouter(dpid)) {
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700837 avoidEdgeRouterPairing = false;
Srikanth Vavilapalli696010f2014-10-08 17:00:17 -0700838 break;
839 }
840 }
841 }
842 else
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700843 avoidEdgeRouterPairing = false;
Srikanth Vavilapalli696010f2014-10-08 17:00:17 -0700844
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700845 if (!avoidEdgeRouterPairing)
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700846 sets.add(dpidSubSet);
847 }
848 return sets;
849 }
850
Srikanth Vavilapalli25fbe392014-10-10 15:04:51 -0700851 private void createGroupForANeighborSet(NeighborSet ns, int groupId) {
852 List<BucketInfo> buckets = new ArrayList<BucketInfo>();
853 for (Dpid d : ns.getDpids()) {
854 for (PortNumber sp : neighbors.get(d)) {
855 BucketInfo b = new BucketInfo(d,
856 MacAddress.of(srConfig.getRouterMac()),
857 getNeighborRouterMacAddress(d), sp,
858 ns.getEdgeLabel());
859 buckets.add(b);
860
861 /* Update Port Neighborset map */
862 ArrayList<NeighborSet> portNeighborSets =
863 portNeighborSetMap.get(sp);
864 if (portNeighborSets == null) {
865 portNeighborSets = new ArrayList<NeighborSet>();
866 portNeighborSets.add(ns);
867 portNeighborSetMap.put(sp, portNeighborSets);
868 }
869 else
870 portNeighborSets.add(ns);
871 }
872 }
873 EcmpInfo ecmpInfo = new EcmpInfo(groupId, buckets);
874 setEcmpGroup(ecmpInfo);
875 ecmpGroups.put(ns, ecmpInfo);
876 log.debug(
877 "createGroupForANeighborSet: Creating ecmp group {} in sw {} "
878 + "for neighbor set {} with: {}",
879 groupId, getStringId(), ns, ecmpInfo);
880 return;
881 }
882
Sangho Shin15273b62014-10-16 22:22:05 -0700883 private void createGroupForMplsLabel(int groupId, String nodeId,
884 int nextGroupId, boolean bos) {
885 List<BucketInfo> buckets = new ArrayList<BucketInfo>();
886 BucketInfo bucket = new BucketInfo(nextGroupId,
887 Integer.parseInt(nodeId), bos);
888 buckets.add(bucket);
889 EcmpInfo ecmpInfo = new EcmpInfo(groupId, buckets);
890 setPolicyEcmpGroup(ecmpInfo);
891// ecmpGroups.put(ns, ecmpInfo);
892 log.debug(
893 "createGroupForANeighborSet: Creating ecmp group {} in sw {} "
894 + "for pushing label {} and group to {}",
895 groupId, getStringId(), nodeId, nextGroupId);
896 return;
897 }
898
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700899 /**
900 * createGroups creates ECMP groups for all ports on this router connected
901 * to other routers (in the OF network). The information for ports is
902 * gleaned from the configured links. If no links are configured no groups
903 * will be created, and it is up to the caller of the IOF13Switch API to
904 * create groups.
905 * <p>
906 * By default all ports connected to the same neighbor router will be part
907 * of the same ECMP group. In addition, groups will be created for all
908 * possible combinations of neighbor routers.
909 * <p>
910 * For example, consider this router (R0) connected to 3 neighbors (R1, R2,
911 * and R3). The following groups will be created in R0:
912 * <li>1) all ports to R1,
913 * <li>2) all ports to R2,
914 * <li>3) all ports to R3,
915 * <li>4) all ports to R1 and R2
916 * <li>5) all ports to R1 and R3
917 * <li>6) all ports to R2 and R3
918 * <li>7) all ports to R1, R2, and R3
919 */
920 private void createGroups() {
Sangho Shin15273b62014-10-16 22:22:05 -0700921
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700922 Set<Dpid> dpids = neighbors.keySet();
923 if (dpids == null || dpids.isEmpty()) {
924 return;
925 }
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700926 /* Create all possible Neighbor sets from this router
927 * NOTE: Avoid any pairings of edge routers only
928 */
929 Set<Set<Dpid>> powerSet = getAllNeighborSets(dpids);
Srikanth Vavilapalli2cd0ff12014-10-10 13:07:46 -0700930 log.debug("createGroups: The size of neighbor powerset for sw {} is {}",
Srikanth Vavilapallica2263c2014-10-09 15:19:11 -0700931 getStringId(), powerSet.size());
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700932 Set<NeighborSet> nsSet = new HashSet<NeighborSet>();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700933 for (Set<Dpid> combo : powerSet) {
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700934 if (combo.isEmpty())
935 continue;
Srikanth Vavilapalli2cd0ff12014-10-10 13:07:46 -0700936 if (isEdgeRouter && !segmentIds.isEmpty()) {
937 for (Integer sId : segmentIds) {
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700938 NeighborSet ns = new NeighborSet();
939 ns.addDpids(combo);
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700940 /* Check if the edge label being set is of the
941 * same node in the Neighbor set
942 */
943 if ((combo.size() != 1) ||
Srikanth Vavilapalli2cd0ff12014-10-10 13:07:46 -0700944 (!isSegmentIdSameAsNodeSegmentId(
945 combo.iterator().next(), sId))) {
946 ns.setEdgeLabel(sId);
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -0700947 }
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700948 nsSet.add(ns);
949 }
950 } else {
951 NeighborSet ns = new NeighborSet();
952 ns.addDpids(combo);
953 nsSet.add(ns);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700954 }
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700955 }
Srikanth Vavilapalli2cd0ff12014-10-10 13:07:46 -0700956 log.debug("createGroups: The neighborset with label for sw {} is {}",
Srikanth Vavilapallica2263c2014-10-09 15:19:11 -0700957 getStringId(), nsSet);
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700958
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700959 for (NeighborSet ns : nsSet) {
Srikanth Vavilapalli25fbe392014-10-10 15:04:51 -0700960 createGroupForANeighborSet(ns, groupid.incrementAndGet());
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700961 }
962 }
963
964 private class EcmpInfo {
965 int groupId;
966 List<BucketInfo> buckets;
967
968 EcmpInfo(int gid, List<BucketInfo> bucketInfos) {
969 groupId = gid;
970 buckets = bucketInfos;
971 }
972
973 @Override
974 public String toString() {
975 return "groupId: " + groupId + ", buckets: " + buckets;
976 }
977 }
978
979 private class BucketInfo {
980 Dpid neighborDpid;
981 MacAddress srcMac;
982 MacAddress dstMac;
983 PortNumber outport;
Sangho Shin15273b62014-10-16 22:22:05 -0700984 int groupNo;
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700985 int mplsLabel;
Sangho Shin15273b62014-10-16 22:22:05 -0700986 boolean bos;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700987
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700988 BucketInfo(Dpid nDpid, MacAddress smac, MacAddress dmac,
989 PortNumber p, int label) {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700990 neighborDpid = nDpid;
991 srcMac = smac;
992 dstMac = dmac;
993 outport = p;
Srikanth Vavilapalli68144302014-10-08 15:55:24 -0700994 mplsLabel = label;
Sangho Shin15273b62014-10-16 22:22:05 -0700995 groupNo = -1;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700996 }
997
Sangho Shin15273b62014-10-16 22:22:05 -0700998 BucketInfo(int no, int label, boolean b) {
999 neighborDpid = null;
1000 srcMac = null;
1001 dstMac = null;
1002 outport = null;
1003 groupNo = no;
1004 mplsLabel = label;
1005 bos = b;
1006 }
1007
1008
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001009 @Override
1010 public String toString() {
1011 return " {neighborDpid: " + neighborDpid + ", dstMac: " + dstMac +
Srikanth Vavilapalli68144302014-10-08 15:55:24 -07001012 ", srcMac: " + srcMac + ", outport: " + outport +
Sangho Shin15273b62014-10-16 22:22:05 -07001013 ", groupNo: " + groupNo +
1014 ", mplsLabel: " + mplsLabel + "}";
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001015 }
1016 }
1017
1018 private void setEcmpGroup(EcmpInfo ecmpInfo) {
1019 List<OFMessage> msglist = new ArrayList<OFMessage>();
1020 OFGroup group = OFGroup.of(ecmpInfo.groupId);
1021
1022 List<OFBucket> buckets = new ArrayList<OFBucket>();
1023 for (BucketInfo b : ecmpInfo.buckets) {
1024 OFOxmEthDst dmac = factory.oxms()
1025 .ethDst(b.dstMac);
1026 OFAction setDA = factory.actions().buildSetField()
1027 .setField(dmac).build();
Saurav Das0a344b02014-09-26 14:18:52 -07001028 OFOxmEthSrc smac = factory.oxms()
1029 .ethSrc(b.srcMac);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001030 OFAction setSA = factory.actions().buildSetField()
1031 .setField(smac).build();
1032 OFAction outp = factory.actions().buildOutput()
1033 .setPort(OFPort.of(b.outport.shortValue()))
1034 .build();
1035 List<OFAction> actions = new ArrayList<OFAction>();
1036 actions.add(setSA);
1037 actions.add(setDA);
1038 actions.add(outp);
Srikanth Vavilapalli68144302014-10-08 15:55:24 -07001039 if (b.mplsLabel != -1) {
1040 OFAction pushLabel = factory.actions().buildPushMpls()
1041 .setEthertype(EthType.MPLS_UNICAST).build();
Srikanth Vavilapalli11dc6072014-10-13 13:32:11 -07001042 OFOxmMplsBos bosX = factory.oxms()
1043 .mplsBos(OFBooleanValue.TRUE);
1044 OFAction setBX = factory.actions().buildSetField()
1045 .setField(bosX).build();
Sangho Shin62ce5c12014-10-08 16:24:40 -07001046 OFOxmMplsLabel lid = factory.oxms()
1047 .mplsLabel(U32.of(b.mplsLabel));
1048 OFAction setLabel = factory.actions().buildSetField()
1049 .setField(lid).build();
Srikanth Vavilapalli68144302014-10-08 15:55:24 -07001050 OFAction copyTtl = factory.actions().copyTtlOut();
1051 OFAction decrTtl = factory.actions().decMplsTtl();
1052 actions.add(pushLabel);
1053 actions.add(setLabel);
Srikanth Vavilapalli11dc6072014-10-13 13:32:11 -07001054 actions.add(setBX);
Srikanth Vavilapalli68144302014-10-08 15:55:24 -07001055 actions.add(copyTtl);
1056 actions.add(decrTtl);
1057 }
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001058 OFBucket ofb = factory.buildBucket()
1059 .setWeight(1)
1060 .setActions(actions)
1061 .build();
1062 buckets.add(ofb);
1063 }
1064
1065 OFMessage gm = factory.buildGroupAdd()
1066 .setGroup(group)
1067 .setBuckets(buckets)
1068 .setGroupType(OFGroupType.SELECT)
1069 .setXid(getNextTransactionId())
1070 .build();
1071 msglist.add(gm);
1072 try {
1073 write(msglist);
1074 } catch (IOException e) {
1075 // TODO Auto-generated catch block
1076 e.printStackTrace();
1077 }
1078 }
1079
Sangho Shin15273b62014-10-16 22:22:05 -07001080 private void setPolicyEcmpGroup(EcmpInfo ecmpInfo) {
1081 List<OFMessage> msglist = new ArrayList<OFMessage>();
1082 OFGroup group = OFGroup.of(ecmpInfo.groupId);
1083
1084 List<OFBucket> buckets = new ArrayList<OFBucket>();
1085 List<OFAction> actions = new ArrayList<OFAction>();
1086 for (BucketInfo b : ecmpInfo.buckets) {
1087 if (b.dstMac != null && b.srcMac != null && b.outport != null) {
1088 OFOxmEthDst dmac = factory.oxms()
1089 .ethDst(b.dstMac);
1090 OFAction setDA = factory.actions().buildSetField()
1091 .setField(dmac).build();
1092 OFOxmEthSrc smac = factory.oxms()
1093 .ethSrc(b.srcMac);
1094 OFAction setSA = factory.actions().buildSetField()
1095 .setField(smac).build();
1096 OFAction outp = factory.actions().buildOutput()
1097 .setPort(OFPort.of(b.outport.shortValue()))
1098 .build();
1099 actions.add(setSA);
1100 actions.add(setDA);
1101 actions.add(outp);
1102 }
1103 if (b.groupNo > 0) {
1104 OFAction groupTo = factory.actions().buildGroup()
1105 .setGroup(OFGroup.of(b.groupNo))
1106 .build();
1107 actions.add(groupTo);
1108 }
1109 if (b.mplsLabel != -1) {
1110 OFAction pushLabel = factory.actions().buildPushMpls()
1111 .setEthertype(EthType.MPLS_UNICAST).build();
1112
1113 OFBooleanValue bosValue = null;
1114 if (b.bos)
1115 bosValue = OFBooleanValue.TRUE;
1116 else
1117 bosValue = OFBooleanValue.FALSE;
1118 OFOxmMplsBos bosX = factory.oxms()
1119 .mplsBos(bosValue);
1120 OFAction setBX = factory.actions().buildSetField()
1121 .setField(bosX).build();
1122 OFOxmMplsLabel lid = factory.oxms()
1123 .mplsLabel(U32.of(b.mplsLabel));
1124 OFAction setLabel = factory.actions().buildSetField()
1125 .setField(lid).build();
1126 OFAction copyTtl = factory.actions().copyTtlOut();
1127 OFAction decrTtl = factory.actions().decMplsTtl();
1128 actions.add(pushLabel);
1129 actions.add(setLabel);
1130 actions.add(setBX);
1131 actions.add(copyTtl);
1132 // decrement TTL only when the first MPLS label is pushed
1133 if (b.bos)
1134 actions.add(decrTtl);
1135 }
1136 OFBucket ofb = factory.buildBucket()
1137 .setWeight(1)
1138 .setActions(actions)
1139 .build();
1140 buckets.add(ofb);
1141 }
1142
1143 OFMessage gm = factory.buildGroupAdd()
1144 .setGroup(group)
1145 .setBuckets(buckets)
1146 .setGroupType(OFGroupType.SELECT)
1147 .setXid(getNextTransactionId())
1148 .build();
1149 msglist.add(gm);
1150 try {
1151 write(msglist);
1152 } catch (IOException e) {
1153 // TODO Auto-generated catch block
1154 e.printStackTrace();
1155 }
1156 }
1157
Sangho Shin55d00e12014-10-20 12:13:07 -07001158 private void deleteGroup(int groupId) {
1159
1160 List<OFMessage> msglist = new ArrayList<OFMessage>();
1161 OFGroup group = OFGroup.of(groupId);
1162
1163 OFMessage gm = factory.buildGroupDelete()
1164 .setGroup(group)
1165 .setGroupType(OFGroupType.SELECT)
1166 .setXid(getNextTransactionId())
1167 .build();
1168 msglist.add(gm);
1169 try {
1170 write(msglist);
1171 } catch (IOException e) {
1172 // TODO Auto-generated catch block
1173 e.printStackTrace();
1174 }
1175 }
1176
Srikanth Vavilapalli7d873fd2014-10-04 07:50:57 -07001177 private void modifyEcmpGroup(EcmpInfo ecmpInfo) {
1178 List<OFMessage> msglist = new ArrayList<OFMessage>();
1179 OFGroup group = OFGroup.of(ecmpInfo.groupId);
1180
1181 List<OFBucket> buckets = new ArrayList<OFBucket>();
1182 for (BucketInfo b : ecmpInfo.buckets) {
1183 OFOxmEthDst dmac = factory.oxms()
1184 .ethDst(b.dstMac);
1185 OFAction setDA = factory.actions().buildSetField()
1186 .setField(dmac).build();
1187 OFOxmEthSrc smac = factory.oxms()
1188 .ethSrc(b.srcMac);
1189 OFAction setSA = factory.actions().buildSetField()
1190 .setField(smac).build();
1191 OFAction outp = factory.actions().buildOutput()
1192 .setPort(OFPort.of(b.outport.shortValue()))
1193 .build();
1194 List<OFAction> actions = new ArrayList<OFAction>();
1195 actions.add(setSA);
1196 actions.add(setDA);
1197 actions.add(outp);
Srikanth Vavilapalli68144302014-10-08 15:55:24 -07001198 if (b.mplsLabel != -1) {
1199 OFAction pushLabel = factory.actions().buildPushMpls()
1200 .setEthertype(EthType.MPLS_UNICAST).build();
Srikanth Vavilapalli11dc6072014-10-13 13:32:11 -07001201 OFOxmMplsBos bosX = factory.oxms()
1202 .mplsBos(OFBooleanValue.TRUE);
1203 OFAction setBX = factory.actions().buildSetField()
1204 .setField(bosX).build();
Srikanth Vavilapalli4ae146e2014-10-09 14:35:26 -07001205 OFOxmMplsLabel lid = factory.oxms()
1206 .mplsLabel(U32.of(b.mplsLabel));
1207 OFAction setLabel = factory.actions().buildSetField()
1208 .setField(lid).build();
Srikanth Vavilapalli68144302014-10-08 15:55:24 -07001209 OFAction copyTtl = factory.actions().copyTtlOut();
1210 OFAction decrTtl = factory.actions().decMplsTtl();
1211 actions.add(pushLabel);
1212 actions.add(setLabel);
Srikanth Vavilapalli11dc6072014-10-13 13:32:11 -07001213 actions.add(setBX);
Srikanth Vavilapalli68144302014-10-08 15:55:24 -07001214 actions.add(copyTtl);
1215 actions.add(decrTtl);
1216 }
Srikanth Vavilapalli7d873fd2014-10-04 07:50:57 -07001217 OFBucket ofb = factory.buildBucket()
1218 .setWeight(1)
1219 .setActions(actions)
1220 .build();
1221 buckets.add(ofb);
1222 }
1223
1224 OFMessage gm = factory.buildGroupModify()
1225 .setGroup(group)
1226 .setBuckets(buckets)
1227 .setGroupType(OFGroupType.SELECT)
1228 .setXid(getNextTransactionId())
1229 .build();
1230 msglist.add(gm);
1231 try {
1232 write(msglist);
1233 } catch (IOException e) {
1234 // TODO Auto-generated catch block
1235 e.printStackTrace();
1236 }
1237 }
1238
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001239 private void verifyGroups() throws IOException {
1240 sendGroupDescRequest();
1241 }
1242
1243 private void sendGroupDescRequest() throws IOException {
1244 OFMessage gdr = factory.buildGroupDescStatsRequest()
1245 .setXid(getNextTransactionId())
1246 .build();
1247 write(gdr, null);
1248 }
1249
1250 private void assignAdjacencyLabels() {
1251 // TODO
1252 try {
1253 nextDriverState();
1254 } catch (IOException e) {
1255 // TODO Auto-generated catch block
1256 e.printStackTrace();
1257 }
1258 }
1259
Saurav Das1cd10152014-09-26 09:38:07 -07001260 private OFAction getOFAction(Action action) {
1261 OFAction ofAction = null;
1262 if (action instanceof OutputAction) {
1263 OutputAction outputAction = (OutputAction) action;
1264 OFPort port = OFPort.of((int) outputAction.getPortNumber().value());
1265 ofAction = factory.actions().output(port, Short.MAX_VALUE);
1266 } else if (action instanceof ModifyDstMacAction) {
1267 long dstMac = ((ModifyDstMacAction) action).getDstMac().toLong();
1268 OFOxmEthDst dmac = factory.oxms()
1269 .ethDst(MacAddress.of(dstMac));
1270 ofAction = factory.actions().buildSetField()
1271 .setField(dmac).build();
1272 } else if (action instanceof ModifySrcMacAction) {
1273 long srcMac = ((ModifySrcMacAction) action).getSrcMac().toLong();
1274 OFOxmEthSrc smac = factory.oxms()
1275 .ethSrc(MacAddress.of(srcMac));
1276 ofAction = factory.actions().buildSetField()
1277 .setField(smac).build();
Saurav Dasa962a692014-10-17 14:52:38 -07001278 } else if (action instanceof PushMplsAction) {
1279 ofAction = factory.actions().pushMpls(EthType.MPLS_UNICAST);
1280 } else if (action instanceof SetMplsIdAction) {
1281 int labelid = ((SetMplsIdAction) action).getMplsId();
1282 OFOxmMplsLabel lid = factory.oxms()
1283 .mplsLabel(U32.of(labelid));
1284 ofAction = factory.actions().buildSetField()
1285 .setField(lid).build();
1286 } else if (action instanceof SetMplsBosAction) {
1287 OFBooleanValue val = OFBooleanValue.of(
1288 ((SetMplsBosAction) action).isSet());
1289 OFOxmMplsBos bos = factory.oxms().mplsBos(val);
1290 OFAction setBos = factory.actions().buildSetField()
1291 .setField(bos).build();
1292 } else if (action instanceof PopMplsAction) {
Saurav Das1cd10152014-09-26 09:38:07 -07001293 EthType ethertype = ((PopMplsAction) action).getEthType();
1294 ofAction = factory.actions().popMpls(ethertype);
1295 } else if (action instanceof GroupAction) {
Sangho Shin15273b62014-10-16 22:22:05 -07001296 int gid = -1;
1297 GroupAction ga = (GroupAction)action;
Sangho Shin81655442014-10-20 14:22:46 -07001298 if (ga.getTunnelId() != null) {
Sangho Shin4b46bcd2014-10-20 15:48:47 -07001299 List<Integer> groupIds = tunnelGroupIdTable.get(ga.getTunnelId());
Sangho Shin81655442014-10-20 14:22:46 -07001300 gid = groupIds.get(groupIds.size()-1);
Saurav Das1cd10152014-09-26 09:38:07 -07001301 }
Sangho Shin15273b62014-10-16 22:22:05 -07001302 else {
1303 NeighborSet ns = ((GroupAction) action).getDpids();
1304 EcmpInfo ei = ecmpGroups.get(ns);
1305 if (ei == null) {
1306 log.debug("Unable to find ecmp group for neighbors {} at "
1307 + "switch {} and hence creating it", ns, getStringId());
1308 createGroupForANeighborSet(ns, groupid.incrementAndGet());
1309 ei = ecmpGroups.get(ns);
1310 }
1311 gid = ei.groupId;
1312 }
Srikanth Vavilapalli846df292014-10-10 15:47:16 -07001313 ofAction = factory.actions().buildGroup()
1314 .setGroup(OFGroup.of(gid))
1315 .build();
Saurav Das1cd10152014-09-26 09:38:07 -07001316 } else if (action instanceof DecNwTtlAction) {
1317 ofAction = factory.actions().decNwTtl();
1318 } else if (action instanceof DecMplsTtlAction) {
1319 ofAction = factory.actions().decMplsTtl();
1320 } else if (action instanceof CopyTtlInAction) {
1321 ofAction = factory.actions().copyTtlIn();
1322 } else if (action instanceof CopyTtlOutAction) {
1323 ofAction = factory.actions().copyTtlOut();
1324 } else {
1325 log.warn("Unsupported Action type: {}", action.getClass().getName());
1326 return null;
1327 }
1328
Saurav Das1cd10152014-09-26 09:38:07 -07001329 return ofAction;
1330 }
1331
Saurav Das0a344b02014-09-26 14:18:52 -07001332 private OFMessage getIpEntry(MatchActionOperationEntry mao) {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001333 MatchAction ma = mao.getTarget();
1334 Operator op = mao.getOperator();
1335 Ipv4Match ipm = (Ipv4Match) ma.getMatch();
1336
1337 // set match
1338 IPv4Net ipdst = ipm.getDestination();
1339 OFOxmEthType ethTypeIp = factory.oxms()
1340 .ethType(EthType.IPv4);
1341 OFOxmIpv4DstMasked ipPrefix = factory.oxms()
1342 .ipv4DstMasked(
1343 IPv4Address.of(ipdst.address().value()),
1344 IPv4Address.ofCidrMaskLength(ipdst.prefixLen())
1345 );
1346 OFOxmList oxmList = OFOxmList.of(ethTypeIp, ipPrefix);
1347 OFMatchV3 match = factory.buildMatchV3()
1348 .setOxmList(oxmList).build();
1349
1350 // set actions
1351 List<OFAction> writeActions = new ArrayList<OFAction>();
1352 for (Action action : ma.getActions()) {
Saurav Das1cd10152014-09-26 09:38:07 -07001353 OFAction ofAction = getOFAction(action);
1354 if (ofAction != null) {
1355 writeActions.add(ofAction);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001356 }
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001357 }
1358
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001359 // set instructions
1360 OFInstruction writeInstr = factory.instructions().buildWriteActions()
1361 .setActions(writeActions).build();
1362 OFInstruction gotoInstr = factory.instructions().buildGotoTable()
1363 .setTableId(TableId.of(TABLE_ACL)).build();
1364 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
1365 instructions.add(writeInstr);
1366 instructions.add(gotoInstr);
1367
Saurav Das1cd10152014-09-26 09:38:07 -07001368 // set flow priority to emulate longest prefix match
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001369 int priority = ipdst.prefixLen() * PRIORITY_MULTIPLIER;
1370 if (ipdst.prefixLen() == (short) 32) {
1371 priority = MAX_PRIORITY;
1372 }
1373
Saurav Dasbc594a42014-09-25 20:13:50 -07001374 // set flow-mod
Saurav Dase972b3a2014-09-26 15:41:06 -07001375 OFFlowMod.Builder fmBuilder = null;
1376 switch (op) {
1377 case ADD:
1378 fmBuilder = factory.buildFlowAdd();
1379 break;
1380 case REMOVE:
1381 fmBuilder = factory.buildFlowDeleteStrict();
1382 break;
Sangho Shin5be3e532014-10-03 17:20:58 -07001383 case MODIFY: // TODO
1384 fmBuilder = factory.buildFlowModifyStrict();
1385 break;
Saurav Dase972b3a2014-09-26 15:41:06 -07001386 default:
1387 log.warn("Unsupported MatchAction Operator: {}", op);
1388 return null;
Saurav Dasbc594a42014-09-25 20:13:50 -07001389 }
Saurav Dase972b3a2014-09-26 15:41:06 -07001390 OFMessage ipFlow = fmBuilder
1391 .setTableId(TableId.of(TABLE_IPv4_UNICAST))
1392 .setMatch(match)
1393 .setInstructions(instructions)
1394 .setPriority(priority)
1395 .setBufferId(OFBufferId.NO_BUFFER)
1396 .setIdleTimeout(0)
1397 .setHardTimeout(0)
1398 .setXid(getNextTransactionId())
1399 .build();
Saurav Dasbc594a42014-09-25 20:13:50 -07001400 log.debug("{} ip-rule {}-{} in sw {}",
1401 (op == MatchActionOperations.Operator.ADD) ? "Adding" : "Deleting",
1402 match, writeActions,
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001403 getStringId());
Saurav Das0a344b02014-09-26 14:18:52 -07001404 return ipFlow;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001405 }
1406
Saurav Das0a344b02014-09-26 14:18:52 -07001407 private OFMessage getMplsEntry(MatchActionOperationEntry mao) {
Saurav Das1cd10152014-09-26 09:38:07 -07001408 MatchAction ma = mao.getTarget();
1409 Operator op = mao.getOperator();
1410 MplsMatch mplsm = (MplsMatch) ma.getMatch();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001411
Saurav Das1cd10152014-09-26 09:38:07 -07001412 // set match
1413 OFOxmEthType ethTypeMpls = factory.oxms()
1414 .ethType(EthType.MPLS_UNICAST);
1415 OFOxmMplsLabel labelid = factory.oxms()
1416 .mplsLabel(U32.of(mplsm.getMplsLabel()));
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001417 OFOxmMplsBos bos = factory.oxms()
1418 .mplsBos(OFBooleanValue.of(mplsm.isBos()));
1419 OFOxmList oxmList = OFOxmList.of(ethTypeMpls, labelid, bos);
Saurav Das1cd10152014-09-26 09:38:07 -07001420 OFMatchV3 matchlabel = factory.buildMatchV3()
1421 .setOxmList(oxmList).build();
1422
1423 // set actions
1424 List<OFAction> writeActions = new ArrayList<OFAction>();
1425 for (Action action : ma.getActions()) {
1426 OFAction ofAction = getOFAction(action);
1427 if (ofAction != null) {
1428 writeActions.add(ofAction);
1429 }
1430 }
1431
1432 // set instructions
1433 OFInstruction writeInstr = factory.instructions().buildWriteActions()
1434 .setActions(writeActions).build();
1435 OFInstruction gotoInstr = factory.instructions().buildGotoTable()
1436 .setTableId(TableId.of(TABLE_ACL)).build();
1437 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
1438 instructions.add(writeInstr);
1439 instructions.add(gotoInstr);
1440
Saurav Dase972b3a2014-09-26 15:41:06 -07001441 // set flow-mod
1442 OFFlowMod.Builder fmBuilder = null;
1443 switch (op) {
1444 case ADD:
1445 fmBuilder = factory.buildFlowAdd();
1446 break;
1447 case REMOVE:
1448 fmBuilder = factory.buildFlowDeleteStrict();
1449 break;
Sangho Shin5be3e532014-10-03 17:20:58 -07001450 case MODIFY: // TODO
1451 fmBuilder = factory.buildFlowModifyStrict();
1452 break;
Saurav Dase972b3a2014-09-26 15:41:06 -07001453 default:
1454 log.warn("Unsupported MatchAction Operator: {}", op);
1455 return null;
Saurav Das1cd10152014-09-26 09:38:07 -07001456 }
Saurav Dase972b3a2014-09-26 15:41:06 -07001457
1458 OFMessage mplsFlow = fmBuilder
1459 .setTableId(TableId.of(TABLE_MPLS))
1460 .setMatch(matchlabel)
1461 .setInstructions(instructions)
1462 .setPriority(MAX_PRIORITY) // exact match and exclusive
1463 .setBufferId(OFBufferId.NO_BUFFER)
1464 .setIdleTimeout(0)
1465 .setHardTimeout(0)
1466 .setXid(getNextTransactionId())
1467 .build();
Saurav Das1cd10152014-09-26 09:38:07 -07001468 log.debug("{} mpls-rule {}-{} in sw {}",
1469 (op == MatchActionOperations.Operator.ADD) ? "Adding" : "Deleting",
1470 matchlabel, writeActions,
1471 getStringId());
Saurav Das0a344b02014-09-26 14:18:52 -07001472 return mplsFlow;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001473 }
1474
Saurav Das0a344b02014-09-26 14:18:52 -07001475 private OFMessage getAclEntry(MatchActionOperationEntry mao) {
Saurav Dase972b3a2014-09-26 15:41:06 -07001476 MatchAction ma = mao.getTarget();
1477 Operator op = mao.getOperator();
1478 PacketMatch packetMatch = (PacketMatch) ma.getMatch();
1479 Builder matchBuilder = factory.buildMatch();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001480
Saurav Dase972b3a2014-09-26 15:41:06 -07001481 // set match
1482 int inport = 0;
1483 if (ma.getSwitchPort() != null) {
1484 inport = (int) ma.getSwitchPort().getPortNumber().value();
1485 }
1486 final MACAddress srcMac = packetMatch.getSrcMacAddress();
1487 final MACAddress dstMac = packetMatch.getDstMacAddress();
1488 final Short etherType = packetMatch.getEtherType();
1489 final IPv4Net srcIp = packetMatch.getSrcIpAddress();
1490 final IPv4Net dstIp = packetMatch.getDstIpAddress();
1491 final Byte ipProto = packetMatch.getIpProtocolNumber();
1492 final Short srcTcpPort = packetMatch.getSrcTcpPortNumber();
1493 final Short dstTcpPort = packetMatch.getDstTcpPortNumber();
1494 if (inport > 0) {
1495 matchBuilder.setExact(MatchField.IN_PORT,
1496 OFPort.of(inport));
1497 }
1498 if (srcMac != null) {
1499 matchBuilder.setExact(MatchField.ETH_SRC, MacAddress.of(srcMac.toLong()));
1500 }
1501 if (dstMac != null) {
1502 matchBuilder.setExact(MatchField.ETH_DST, MacAddress.of(dstMac.toLong()));
1503 }
1504 if (etherType != null) {
1505 matchBuilder.setExact(MatchField.ETH_TYPE, EthType.of(etherType));
1506 }
1507 if (srcIp != null) {
1508 matchBuilder.setMasked(MatchField.IPV4_SRC,
1509 IPv4Address.of(srcIp.address().value())
1510 .withMaskOfLength(srcIp.prefixLen()));
1511 }
1512 if (dstIp != null) {
1513 matchBuilder.setMasked(MatchField.IPV4_DST,
1514 IPv4Address.of(dstIp.address().value())
1515 .withMaskOfLength(dstIp.prefixLen()));
1516 }
1517 if (ipProto != null) {
1518 matchBuilder.setExact(MatchField.IP_PROTO, IpProtocol.of(ipProto));
1519 }
1520 if (srcTcpPort != null) {
1521 matchBuilder.setExact(MatchField.TCP_SRC, TransportPort.of(srcTcpPort));
1522 }
1523 if (dstTcpPort != null) {
1524 matchBuilder.setExact(MatchField.TCP_DST, TransportPort.of(dstTcpPort));
1525 }
1526
1527 // set actions
Saurav Dascc3e35f2014-10-10 15:33:32 -07001528 List<OFAction> writeActions = new ArrayList<OFAction>();
Saurav Dase972b3a2014-09-26 15:41:06 -07001529 for (Action action : ma.getActions()) {
1530 OFAction ofAction = getOFAction(action);
1531 if (ofAction != null) {
Saurav Dascc3e35f2014-10-10 15:33:32 -07001532 writeActions.add(ofAction);
Saurav Dase972b3a2014-09-26 15:41:06 -07001533 }
1534 }
1535
1536 // set instructions
1537 OFInstruction clearInstr = factory.instructions().clearActions();
Saurav Dascc3e35f2014-10-10 15:33:32 -07001538 OFInstruction writeInstr = factory.instructions().buildWriteActions()
1539 .setActions(writeActions).build();
Saurav Dase972b3a2014-09-26 15:41:06 -07001540 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
1541 instructions.add(clearInstr);
Saurav Dascc3e35f2014-10-10 15:33:32 -07001542 instructions.add(writeInstr);
Saurav Dase972b3a2014-09-26 15:41:06 -07001543
1544 // set flow-mod
1545 OFFlowMod.Builder fmBuilder = null;
1546 switch (op) {
1547 case ADD:
1548 fmBuilder = factory.buildFlowAdd();
1549 break;
1550 case REMOVE:
1551 fmBuilder = factory.buildFlowDeleteStrict();
1552 break;
Sangho Shin5be3e532014-10-03 17:20:58 -07001553 case MODIFY: // TODO
1554 fmBuilder = factory.buildFlowModifyStrict();
1555 break;
Saurav Dase972b3a2014-09-26 15:41:06 -07001556 default:
1557 log.warn("Unsupported MatchAction Operator: {}", op);
1558 return null;
1559 }
1560
1561 OFMessage aclFlow = fmBuilder
1562 .setTableId(TableId.of(TABLE_ACL))
1563 .setMatch(matchBuilder.build())
1564 .setInstructions(instructions)
Sangho Shin6f47dd32014-10-17 23:10:39 -07001565 .setPriority(ma.getPriority()) // exact match and exclusive
Saurav Dase972b3a2014-09-26 15:41:06 -07001566 .setBufferId(OFBufferId.NO_BUFFER)
1567 .setIdleTimeout(0)
1568 .setHardTimeout(0)
1569 .setXid(getNextTransactionId())
1570 .build();
Sangho Shin15273b62014-10-16 22:22:05 -07001571
Saurav Das0a344b02014-09-26 14:18:52 -07001572 return aclFlow;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001573 }
1574
1575 // *****************************
1576 // IOF13Switch
1577 // *****************************
1578
1579 @Override
1580 public void pushFlow(MatchActionOperationEntry matchActionOp) throws IOException {
Saurav Das0a344b02014-09-26 14:18:52 -07001581 OFMessage ofm = getFlow(matchActionOp);
1582 if (ofm != null) {
1583 write(Collections.singletonList(ofm));
1584 }
1585 }
1586
1587 private OFMessage getFlow(MatchActionOperationEntry matchActionOp) {
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001588 final MatchAction matchAction = matchActionOp.getTarget();
1589 final Match match = matchAction.getMatch();
1590 if (match instanceof Ipv4Match) {
Saurav Das0a344b02014-09-26 14:18:52 -07001591 return getIpEntry(matchActionOp);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001592 } else if (match instanceof MplsMatch) {
Saurav Das0a344b02014-09-26 14:18:52 -07001593 return getMplsEntry(matchActionOp);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001594 } else if (match instanceof PacketMatch) {
Saurav Das0a344b02014-09-26 14:18:52 -07001595 return getAclEntry(matchActionOp);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001596 } else {
1597 log.error("Unknown match type {} pushed to switch {}", match,
1598 getStringId());
1599 }
Saurav Das0a344b02014-09-26 14:18:52 -07001600 return null;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001601 }
1602
1603 @Override
1604 public void pushFlows(Collection<MatchActionOperationEntry> matchActionOps)
1605 throws IOException {
Saurav Das0a344b02014-09-26 14:18:52 -07001606 List<OFMessage> flowMods = new ArrayList<OFMessage>();
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001607 for (MatchActionOperationEntry matchActionOp : matchActionOps) {
Saurav Das0a344b02014-09-26 14:18:52 -07001608 OFMessage ofm = getFlow(matchActionOp);
1609 if (ofm != null) {
1610 flowMods.add(ofm);
1611 }
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001612 }
Saurav Das0a344b02014-09-26 14:18:52 -07001613 write(flowMods);
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001614 }
1615
1616 @Override
1617 public int getEcmpGroupId(NeighborSet ns) {
1618 EcmpInfo ei = ecmpGroups.get(ns);
1619 if (ei == null) {
1620 return -1;
1621 } else {
1622 return ei.groupId;
1623 }
1624 }
1625
Saurav Dascc3e35f2014-10-10 15:33:32 -07001626 @Override
1627 public TableId getTableId(String tableType) {
1628 tableType = tableType.toLowerCase();
1629 if (tableType.contentEquals("ip")) {
1630 return TableId.of(OFSwitchImplCPqD13.TABLE_IPv4_UNICAST);
1631 }
1632 else if (tableType.contentEquals("mpls")) {
1633 return TableId.of(OFSwitchImplCPqD13.TABLE_MPLS);
1634 }
1635 else if (tableType.contentEquals("acl")) {
1636 return TableId.of(OFSwitchImplCPqD13.TABLE_ACL);
1637 }
1638 else {
1639 log.warn("Invalid tableType: {}", tableType);
1640 return null;
1641 }
1642 }
1643
Sangho Shin4b46bcd2014-10-20 15:48:47 -07001644 @Override
1645 public void createTunnel(String tunnelId, List<String> route, NeighborSet ns) {
1646
1647 List<Integer> groups = new ArrayList<Integer>();
Sangho Shin15273b62014-10-16 22:22:05 -07001648
1649 // create a last group of the group chaining
1650 int finalGroupId = groupid.incrementAndGet();
1651 createGroupForANeighborSet(ns, finalGroupId);
Sangho Shin4b46bcd2014-10-20 15:48:47 -07001652 groups.add(Integer.valueOf(finalGroupId));
Sangho Shin15273b62014-10-16 22:22:05 -07001653
1654 int groupId = 0;
1655 int nextGroupId = finalGroupId;
1656 boolean bos = false;
1657
Sangho Shine020cc32014-10-20 13:28:02 -07001658 // process the node ID in order
Sangho Shin15273b62014-10-16 22:22:05 -07001659 for (int i = 0; i < route.size(); i++) {
1660 String nodeId = route.get(i);
1661 groupId = groupid.incrementAndGet();
Sangho Shine020cc32014-10-20 13:28:02 -07001662 groups.add(Integer.valueOf(groupId));
Sangho Shin15273b62014-10-16 22:22:05 -07001663 if (i == route.size()-1)
1664 bos = true;
1665 createGroupForMplsLabel(groupId, nodeId, nextGroupId, bos);
1666 nextGroupId = groupId;
1667 }
Sangho Shin4b46bcd2014-10-20 15:48:47 -07001668 tunnelGroupIdTable.putIfAbsent(tunnelId, groups);
Sangho Shin15273b62014-10-16 22:22:05 -07001669 }
1670
Sangho Shin4b46bcd2014-10-20 15:48:47 -07001671 @Override
1672 public void removeTunnel(String tunnelId) {
1673 List<Integer> groups = tunnelGroupIdTable.get(tunnelId);
Sangho Shin1ad7be02014-10-20 16:56:49 -07001674 if (groups == null)
1675 return;
1676
Sangho Shin4b46bcd2014-10-20 15:48:47 -07001677 // we need to delete groups in reverse order
1678 for (int i = groups.size() - 1; i >= 0; i--) {
1679 int groupId = groups.get(i);
1680 deleteGroup(groupId);
1681 }
1682 tunnelGroupIdTable.remove(tunnelId);
1683 }
Sangho Shin15273b62014-10-16 22:22:05 -07001684
Sangho Shin1ad7be02014-10-20 16:56:49 -07001685 @Override
1686 public int getTunnelGroupId(String tunnelId) {
1687 List<Integer> groups = tunnelGroupIdTable.get(tunnelId);
1688 if (groups == null)
1689 return -1;
1690
1691 return groups.get(0);
1692 }
1693
1694
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001695 // *****************************
Saurav Das80d17392014-10-01 10:24:56 -07001696 // Unused
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001697 // *****************************
1698
Saurav Das80d17392014-10-01 10:24:56 -07001699 @SuppressWarnings("unused")
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001700 private void setAsyncConfig() throws IOException {
1701 List<OFMessage> msglist = new ArrayList<OFMessage>(3);
1702 OFMessage setAC = null;
1703
1704 if (role == Role.MASTER) {
1705 setAC = factory.buildAsyncSet()
1706 .setFlowRemovedMaskEqualMaster(SET_FLOW_REMOVED_MASK_MASTER)
1707 .setPacketInMaskEqualMaster(SET_PACKET_IN_MASK_MASTER)
1708 .setPortStatusMaskEqualMaster(SET_PORT_STATUS_MASK_MASTER)
1709 .setFlowRemovedMaskSlave(SET_ALL_SLAVE)
1710 .setPacketInMaskSlave(SET_ALL_SLAVE)
1711 .setPortStatusMaskSlave(SET_ALL_SLAVE)
1712 .setXid(getNextTransactionId())
1713 .build();
1714 } else if (role == Role.EQUAL) {
1715 setAC = factory.buildAsyncSet()
1716 .setFlowRemovedMaskEqualMaster(SET_FLOW_REMOVED_MASK_EQUAL)
1717 .setPacketInMaskEqualMaster(SET_PACKET_IN_MASK_EQUAL)
1718 .setPortStatusMaskEqualMaster(SET_PORT_STATUS_MASK_EQUAL)
1719 .setFlowRemovedMaskSlave(SET_ALL_SLAVE)
1720 .setPacketInMaskSlave(SET_ALL_SLAVE)
1721 .setPortStatusMaskSlave(SET_ALL_SLAVE)
1722 .setXid(getNextTransactionId())
1723 .build();
1724 }
1725 msglist.add(setAC);
1726
1727 OFMessage br = factory.buildBarrierRequest()
1728 .setXid(getNextTransactionId())
1729 .build();
1730 msglist.add(br);
1731
1732 OFMessage getAC = factory.buildAsyncGetRequest()
1733 .setXid(getNextTransactionId())
1734 .build();
1735 msglist.add(getAC);
1736
1737 write(msglist);
1738 }
1739
Saurav Das80d17392014-10-01 10:24:56 -07001740 @SuppressWarnings("unused")
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001741 private void decodeAsyncGetReply(OFAsyncGetReply rep) {
1742 long frm = rep.getFlowRemovedMaskEqualMaster();
Sangho Shin01bca862014-09-12 11:18:59 -07001743 long frs = rep.getFlowRemovedMaskSlave();
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001744 long pim = rep.getPacketInMaskEqualMaster();
Sangho Shin01bca862014-09-12 11:18:59 -07001745 long pis = rep.getPacketInMaskSlave();
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001746 long psm = rep.getPortStatusMaskEqualMaster();
Sangho Shin01bca862014-09-12 11:18:59 -07001747 long pss = rep.getPortStatusMaskSlave();
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001748
1749 if (role == Role.MASTER || role == Role.EQUAL) { // should separate
1750 log.info("FRM:{}", HexString.toHexString((frm & TEST_FLOW_REMOVED_MASK)));
1751 log.info("PIM:{}", HexString.toHexString((pim & TEST_PACKET_IN_MASK)));
1752 log.info("PSM:{}", HexString.toHexString((psm & TEST_PORT_STATUS_MASK)));
1753 }
1754
1755 }
1756
Saurav Das80d17392014-10-01 10:24:56 -07001757 @SuppressWarnings("unused")
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001758 private void getTableFeatures() throws IOException {
1759 OFMessage gtf = factory.buildTableFeaturesStatsRequest()
1760 .setXid(getNextTransactionId())
1761 .build();
1762 write(gtf, null);
1763 }
1764
Saurav Das80d17392014-10-01 10:24:56 -07001765 @SuppressWarnings("unused")
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001766 private void sendGroupFeaturesRequest() throws IOException {
1767 OFMessage gfr = factory.buildGroupFeaturesStatsRequest()
1768 .setXid(getNextTransactionId())
1769 .build();
1770 write(gfr, null);
1771 }
1772
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001773 private void processGroupFeatures(OFGroupFeaturesStatsReply gfsr) {
1774 log.info("Sw: {} Group Features {}", getStringId(), gfsr);
1775 }
1776
Saurav Dascc3e35f2014-10-10 15:33:32 -07001777 @SuppressWarnings("unused")
1778 private void testMultipleLabels() {
1779 if (getId() == 1) {
1780 List<OFMessage> msglist = new ArrayList<OFMessage>();
1781
1782 // first all the indirect groups
1783
1784 // the group to switch 2 with outer label
1785 OFGroup g1 = OFGroup.of(201);
1786 OFOxmEthDst dmac1 = factory.oxms().ethDst(MacAddress.of("00:00:02:02:02:80"));
1787 OFAction push1 = factory.actions().pushMpls(EthType.MPLS_UNICAST);
1788 OFOxmMplsLabel lid1 = factory.oxms()
1789 .mplsLabel(U32.of(105)); // outer label
1790 OFAction setMpls1 = factory.actions().buildSetField()
1791 .setField(lid1).build();
1792 OFOxmMplsBos bos1 = factory.oxms()
1793 .mplsBos(OFBooleanValue.FALSE);
1794 OFAction setB1 = factory.actions().buildSetField()
1795 .setField(bos1).build();
1796 OFAction setDA1 = factory.actions().buildSetField()
1797 .setField(dmac1).build();
1798 OFAction outp1 = factory.actions().buildOutput()
1799 .setPort(OFPort.of(2))
1800 .build();
1801 List<OFAction> a1 = new ArrayList<OFAction>();
1802 a1.add(push1);
1803 a1.add(setMpls1);
1804 a1.add(setB1);
1805 a1.add(setDA1);
1806 a1.add(outp1);
1807 OFBucket b1 = factory.buildBucket()
1808 .setActions(a1)
1809 .build();
1810 OFMessage gm1 = factory.buildGroupAdd()
1811 .setGroup(g1)
1812 .setBuckets(Collections.singletonList(b1))
1813 .setGroupType(OFGroupType.INDIRECT)
1814 .setXid(getNextTransactionId())
1815 .build();
1816 msglist.add(gm1);
1817
1818 // the group to switch 3 with outer label
1819 OFGroup g2 = OFGroup.of(301);
1820 OFOxmEthDst dmac2 = factory.oxms().ethDst(MacAddress.of("00:00:03:03:03:80"));
1821 OFAction push2 = factory.actions().pushMpls(EthType.MPLS_UNICAST);
1822 OFOxmMplsLabel lid2 = factory.oxms()
1823 .mplsLabel(U32.of(104)); // outer label
1824 OFAction setMpls2 = factory.actions().buildSetField()
1825 .setField(lid2).build();
1826 OFOxmMplsBos bos2 = factory.oxms()
1827 .mplsBos(OFBooleanValue.FALSE);
1828 OFAction setB2 = factory.actions().buildSetField()
1829 .setField(bos2).build();
1830 OFAction setDA2 = factory.actions().buildSetField()
1831 .setField(dmac2).build();
1832 OFAction outp2 = factory.actions().buildOutput()
1833 .setPort(OFPort.of(3))
1834 .build();
1835 List<OFAction> a2 = new ArrayList<OFAction>();
1836 a2.add(push2);
1837 a2.add(setMpls2);
1838 a2.add(setB2);
1839 a2.add(setDA2);
1840 a2.add(outp2);
1841 OFBucket b2 = factory.buildBucket()
1842 .setActions(a2)
1843 .build();
1844 OFMessage gm2 = factory.buildGroupAdd()
1845 .setGroup(g2)
1846 .setBuckets(Collections.singletonList(b2))
1847 .setGroupType(OFGroupType.INDIRECT)
1848 .setXid(getNextTransactionId())
1849 .build();
1850 msglist.add(gm2);
1851
1852 // now add main ECMP group with inner labels
1853 OFGroup group = OFGroup.of(786);
1854 List<OFBucket> buckets = new ArrayList<OFBucket>();
1855 for (int i = 0; i < 2; i++) { // 2 buckets
1856
1857 List<OFAction> actions = new ArrayList<OFAction>();
1858 OFOxmEthSrc smac = factory.oxms()
1859 .ethSrc(MacAddress.of("00:00:01:01:01:80"));
1860 OFAction setSA = factory.actions().buildSetField()
1861 .setField(smac).build();
1862 actions.add(setSA);
1863
1864 if (i == 0) {
1865 // send to switch 2
1866 OFAction pushX = factory.actions().pushMpls(EthType.MPLS_UNICAST);
1867 OFOxmMplsLabel lidX = factory.oxms()
1868 .mplsLabel(U32.of(106)); // inner label
1869 OFAction setX = factory.actions().buildSetField()
1870 .setField(lidX).build();
1871 OFOxmMplsBos bosX = factory.oxms()
1872 .mplsBos(OFBooleanValue.TRUE);
1873 OFAction setBX = factory.actions().buildSetField()
1874 .setField(bosX).build();
1875 OFAction ogX = factory.actions().buildGroup()
1876 .setGroup(g1).build();
1877 actions.add(pushX);
1878 actions.add(setX);
1879 actions.add(setBX);
1880 actions.add(ogX);
1881
1882 } else {
1883 // send to switch 3
1884 OFAction pushY = factory.actions().pushMpls(EthType.MPLS_UNICAST);
1885 OFOxmMplsLabel lidY = factory.oxms()
1886 .mplsLabel(U32.of(106)); // inner label
1887 OFAction setY = factory.actions().buildSetField()
1888 .setField(lidY).build();
1889 OFOxmMplsBos bosY = factory.oxms()
1890 .mplsBos(OFBooleanValue.TRUE);
1891 OFAction setBY = factory.actions().buildSetField()
1892 .setField(bosY).build();
1893 OFAction ogY = factory.actions().buildGroup()
1894 .setGroup(g2).build();
1895 actions.add(pushY);
1896 actions.add(setY);
1897 actions.add(setBY);
1898 actions.add(ogY);
1899 }
1900
1901 OFBucket ofb = factory.buildBucket()
1902 .setWeight(1)
1903 .setActions(actions)
1904 .build();
1905 buckets.add(ofb);
1906 }
1907
1908 OFMessage gm = factory.buildGroupAdd()
1909 .setGroup(group)
1910 .setBuckets(buckets)
1911 .setGroupType(OFGroupType.SELECT)
1912 .setXid(getNextTransactionId())
1913 .build();
1914 msglist.add(gm);
1915
1916 // create an ACL entry to use this ecmp group
1917 Builder matchBuilder = factory.buildMatch();
1918 matchBuilder.setExact(MatchField.ETH_TYPE, EthType.of(0x800));
1919 matchBuilder.setMasked(MatchField.IPV4_DST,
1920 IPv4Address.of("7.7.7.0")
1921 .withMaskOfLength(24));
1922
1923 OFAction grp = factory.actions().buildGroup()
1924 .setGroup(OFGroup.of(786))
1925 .build();
1926 List<OFAction> writeActions = Collections.singletonList(grp);
1927
1928 OFInstruction clearInstr = factory.instructions().clearActions();
1929 OFInstruction writeInstr = factory.instructions().buildWriteActions()
1930 .setActions(writeActions).build();
1931 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
1932 instructions.add(clearInstr);
1933 instructions.add(writeInstr);
1934
1935 OFFlowMod.Builder fmBuilder = factory.buildFlowAdd();
1936
1937 OFMessage aclFlow = fmBuilder
1938 .setTableId(TableId.of(TABLE_ACL))
1939 .setMatch(matchBuilder.build())
1940 .setInstructions(instructions)
1941 .setPriority(10) // TODO: wrong - should be MA
1942 // priority
1943 .setBufferId(OFBufferId.NO_BUFFER)
1944 .setIdleTimeout(0)
1945 .setHardTimeout(0)
1946 .setXid(getNextTransactionId())
1947 .build();
1948 msglist.add(aclFlow);
1949
1950 try {
1951 write(msglist);
1952 } catch (IOException e) {
1953 // TODO Auto-generated catch block
1954 e.printStackTrace();
1955 }
Fahad Naeem Khand563af62014-10-08 17:37:25 -07001956 }
1957 }
1958
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001959}