blob: c2bb3444fb3e6c1bdc483fcf3b8bd4533d0217b8 [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;
5import java.util.Collections;
6import java.util.List;
7import java.util.concurrent.ConcurrentHashMap;
8import java.util.concurrent.atomic.AtomicBoolean;
9
10import net.floodlightcontroller.core.IFloodlightProviderService.Role;
11import net.floodlightcontroller.core.SwitchDriverSubHandshakeAlreadyStarted;
12import net.floodlightcontroller.core.SwitchDriverSubHandshakeCompleted;
13import net.floodlightcontroller.core.SwitchDriverSubHandshakeNotStarted;
14import net.floodlightcontroller.core.internal.OFSwitchImplBase;
15
16import org.projectfloodlight.openflow.protocol.OFAsyncGetReply;
17import org.projectfloodlight.openflow.protocol.OFBarrierRequest;
18import org.projectfloodlight.openflow.protocol.OFBucket;
19import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
20import org.projectfloodlight.openflow.protocol.OFErrorMsg;
21import org.projectfloodlight.openflow.protocol.OFFactory;
22import org.projectfloodlight.openflow.protocol.OFGroupDescStatsReply;
23import org.projectfloodlight.openflow.protocol.OFGroupFeaturesStatsReply;
24import org.projectfloodlight.openflow.protocol.OFGroupType;
25import org.projectfloodlight.openflow.protocol.OFMatchV3;
26import org.projectfloodlight.openflow.protocol.OFMessage;
27import org.projectfloodlight.openflow.protocol.OFOxmList;
28import org.projectfloodlight.openflow.protocol.OFPortDesc;
29import org.projectfloodlight.openflow.protocol.OFStatsReply;
30import org.projectfloodlight.openflow.protocol.action.OFAction;
31import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
32import org.projectfloodlight.openflow.protocol.oxm.OFOxmEthDst;
33import org.projectfloodlight.openflow.protocol.oxm.OFOxmEthSrc;
34import org.projectfloodlight.openflow.protocol.oxm.OFOxmEthType;
35import org.projectfloodlight.openflow.protocol.oxm.OFOxmInPort;
36import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv4DstMasked;
37import org.projectfloodlight.openflow.protocol.oxm.OFOxmMetadataMasked;
38import org.projectfloodlight.openflow.protocol.oxm.OFOxmMplsLabel;
39import org.projectfloodlight.openflow.protocol.oxm.OFOxmVlanVid;
40import org.projectfloodlight.openflow.types.EthType;
41import org.projectfloodlight.openflow.types.IPv4Address;
42import org.projectfloodlight.openflow.types.MacAddress;
43import org.projectfloodlight.openflow.types.OFBufferId;
44import org.projectfloodlight.openflow.types.OFGroup;
45import org.projectfloodlight.openflow.types.OFMetadata;
46import org.projectfloodlight.openflow.types.OFPort;
47import org.projectfloodlight.openflow.types.OFVlanVidMatch;
48import org.projectfloodlight.openflow.types.TableId;
49import org.projectfloodlight.openflow.types.U32;
50import org.projectfloodlight.openflow.types.U64;
51import org.projectfloodlight.openflow.util.HexString;
52
53/**
54 * OFDescriptionStatistics Vendor (Manufacturer Desc.): Stanford University,
55 * Ericsson Research and CPqD Research. Make (Hardware Desc.) : OpenFlow 1.3
56 * Reference Userspace Switch Model (Datapath Desc.) : None Software : Serial :
57 * None
58 */
59public class OFSwitchImplCPqD13 extends OFSwitchImplBase {
60 private static final int VLAN_ID_OFFSET = 16;
61 private AtomicBoolean driverHandshakeComplete;
62 private OFFactory factory;
63 private static final int OFPCML_NO_BUFFER = 0xffff;
64 // Configuration of asynch messages to controller. We need different
65 // asynch messages depending on role-equal or role-master.
66 // We don't want to get anything if we are slave.
67 private static final long SET_FLOW_REMOVED_MASK_MASTER = 0xf;
68 private static final long SET_PACKET_IN_MASK_MASTER = 0x7;
69 private static final long SET_PORT_STATUS_MASK_MASTER = 0x7;
70 private static final long SET_FLOW_REMOVED_MASK_EQUAL = 0x0;
71 private static final long SET_PACKET_IN_MASK_EQUAL = 0x0;
72 private static final long SET_PORT_STATUS_MASK_EQUAL = 0x7;
73 private static final long SET_ALL_SLAVE = 0x0;
74
75 private static final long TEST_FLOW_REMOVED_MASK = 0xf;
76 private static final long TEST_PACKET_IN_MASK = 0x7;
77 private static final long TEST_PORT_STATUS_MASK = 0x7;
78 private long barrierXidToWaitFor = -1;
79
80 private static final int TABLE_VLAN = 0;
81 private static final int TABLE_TMAC = 1;
82 private static final int TABLE_IPV4_UNICAST = 2;
83 private static final int TABLE_MPLS = 3;
84 private static final int TABLE_META = 4;
85 private static final int TABLE_ACL = 5;
86
87 private static final short MAX_PRIORITY = (short) 0xffff;
88 private static final short SLASH_24_PRIORITY = (short) 0xfff0;
89 private static final short SLASH_16_PRIORITY = (short) 0xff00;
90 private static final short SLASH_8_PRIORITY = (short) 0xf000;
91 private static final short MIN_PRIORITY = 0x0;
92 private static final U64 METADATA_MASK = U64.of(Long.MAX_VALUE << 1 | 0x1);
93
94 ConcurrentHashMap<Integer, OFGroup> l2groups;
95
96 public OFSwitchImplCPqD13(OFDescStatsReply desc) {
97 super();
98 driverHandshakeComplete = new AtomicBoolean(false);
99 l2groups = new ConcurrentHashMap<Integer, OFGroup>();
100 setSwitchDescription(desc);
101
102 }
103
104 /* (non-Javadoc)
105 * @see java.lang.Object#toString()
106 */
107 @Override
108 public String toString() {
109 return "OFSwitchImplCPqD13 [" + ((channel != null)
110 ? channel.getRemoteAddress() : "?")
111 + " DPID[" + ((stringId != null) ? stringId : "?") + "]]";
112 }
113
114 @Override
115 public void startDriverHandshake() throws IOException {
116 log.debug("Starting driver handshake for sw {}", getStringId());
117 if (startDriverHandshakeCalled) {
118 throw new SwitchDriverSubHandshakeAlreadyStarted();
119 }
120 startDriverHandshakeCalled = true;
121 factory = floodlightProvider.getOFMessageFactory_13();
122 // configureSwitch();
123 sendBarrier(true);
124 }
125
126 @Override
127 public boolean isDriverHandshakeComplete() {
128 if (!startDriverHandshakeCalled) {
129 throw new SwitchDriverSubHandshakeNotStarted();
130 }
131 return driverHandshakeComplete.get();
132 }
133
134 @Override
135 public void processDriverHandshakeMessage(OFMessage m) {
136 if (!startDriverHandshakeCalled) {
137 throw new SwitchDriverSubHandshakeNotStarted();
138 }
139 if (driverHandshakeComplete.get()) {
140 throw new SwitchDriverSubHandshakeCompleted(m);
141 }
142
143 if (!startDriverHandshakeCalled) {
144 throw new SwitchDriverSubHandshakeNotStarted();
145 }
146 if (driverHandshakeComplete.get()) {
147 throw new SwitchDriverSubHandshakeCompleted(m);
148 }
149
150 switch (m.getType()) {
151 case BARRIER_REPLY:
152 if (m.getXid() == barrierXidToWaitFor) {
153 driverHandshakeComplete.set(true);
154 }
155 break;
156
157 case ERROR:
158 log.error("Switch {} Error {}", getStringId(), (OFErrorMsg) m);
159 break;
160
161 case FEATURES_REPLY:
162 break;
163 case FLOW_REMOVED:
164 break;
165 case GET_ASYNC_REPLY:
166 OFAsyncGetReply asrep = (OFAsyncGetReply) m;
167 decodeAsyncGetReply(asrep);
168 break;
169
170 case PACKET_IN:
171 break;
172 case PORT_STATUS:
173 break;
174 case QUEUE_GET_CONFIG_REPLY:
175 break;
176 case ROLE_REPLY:
177 break;
178
179 case STATS_REPLY:
180 processStatsReply((OFStatsReply) m);
181 break;
182
183 default:
184 log.debug("Received message {} during switch-driver subhandshake "
185 + "from switch {} ... Ignoring message", m, getStringId());
186
187 }
188 }
189
190 private void configureSwitch() throws IOException {
191 // setAsyncConfig();
192 // getTableFeatures();
193 sendGroupFeaturesRequest();
194 setL2Groups();
195 sendBarrier(false);
196 setL3Groups();
197 setL25Groups();
198 sendGroupDescRequest();
199 populateTableVlan();
200 populateTableTMac();
201 populateIpTable();
202 populateMplsTable();
203 populateTableMissEntry(TABLE_ACL, false, false, false, -1);
204 sendBarrier(true);
205 }
206
207 private void setAsyncConfig() throws IOException {
208 List<OFMessage> msglist = new ArrayList<OFMessage>(3);
209 OFMessage setAC = null;
210
211 if (role == Role.MASTER) {
212 setAC = factory.buildAsyncSet()
213 .setFlowRemovedMaskEqualMaster(SET_FLOW_REMOVED_MASK_MASTER)
214 .setPacketInMaskEqualMaster(SET_PACKET_IN_MASK_MASTER)
215 .setPortStatusMaskEqualMaster(SET_PORT_STATUS_MASK_MASTER)
216 .setFlowRemovedMaskSlave(SET_ALL_SLAVE)
217 .setPacketInMaskSlave(SET_ALL_SLAVE)
218 .setPortStatusMaskSlave(SET_ALL_SLAVE)
219 .setXid(getNextTransactionId())
220 .build();
221 } else if (role == Role.EQUAL) {
222 setAC = factory.buildAsyncSet()
223 .setFlowRemovedMaskEqualMaster(SET_FLOW_REMOVED_MASK_EQUAL)
224 .setPacketInMaskEqualMaster(SET_PACKET_IN_MASK_EQUAL)
225 .setPortStatusMaskEqualMaster(SET_PORT_STATUS_MASK_EQUAL)
226 .setFlowRemovedMaskSlave(SET_ALL_SLAVE)
227 .setPacketInMaskSlave(SET_ALL_SLAVE)
228 .setPortStatusMaskSlave(SET_ALL_SLAVE)
229 .setXid(getNextTransactionId())
230 .build();
231 }
232 msglist.add(setAC);
233
234 OFMessage br = factory.buildBarrierRequest()
235 .setXid(getNextTransactionId())
236 .build();
237 msglist.add(br);
238
239 OFMessage getAC = factory.buildAsyncGetRequest()
240 .setXid(getNextTransactionId())
241 .build();
242 msglist.add(getAC);
243
244 write(msglist);
245 }
246
247 private void decodeAsyncGetReply(OFAsyncGetReply rep) {
248 long frm = rep.getFlowRemovedMaskEqualMaster();
249 //long frs = rep.getFlowRemovedMaskSlave();
250 long pim = rep.getPacketInMaskEqualMaster();
251 //long pis = rep.getPacketInMaskSlave();
252 long psm = rep.getPortStatusMaskEqualMaster();
253 //long pss = rep.getPortStatusMaskSlave();
254
255 if (role == Role.MASTER || role == Role.EQUAL) { // should separate
256 log.info("FRM:{}", HexString.toHexString((frm & TEST_FLOW_REMOVED_MASK)));
257 log.info("PIM:{}", HexString.toHexString((pim & TEST_PACKET_IN_MASK)));
258 log.info("PSM:{}", HexString.toHexString((psm & TEST_PORT_STATUS_MASK)));
259 }
260
261 }
262
263 private void getTableFeatures() throws IOException {
264 OFMessage gtf = factory.buildTableFeaturesStatsRequest()
265 .setXid(getNextTransactionId())
266 .build();
267 write(gtf, null);
268 }
269
270 private void sendGroupFeaturesRequest() throws IOException {
271 OFMessage gfr = factory.buildGroupFeaturesStatsRequest()
272 .setXid(getNextTransactionId())
273 .build();
274 write(gfr, null);
275 }
276
277 private void sendGroupDescRequest() throws IOException {
278 OFMessage gdr = factory.buildGroupDescStatsRequest()
279 .setXid(getNextTransactionId())
280 .build();
281 write(gdr, null);
282 }
283
284 /*Create L2 interface groups for all physical ports
285 Naming convention followed is the same as OF-DPA spec
286 eg. port 1 with allowed vlan 10, is enveloped in group with id,
287 0x0 00a 0001, where the uppermost 4 bits identify an L2 interface,
288 the next 12 bits identify the vlan-id, and the lowermost 16 bits
289 identify the port number.*/
290 private void setL2Groups() throws IOException {
291 List<OFMessage> msglist = new ArrayList<OFMessage>();
292 for (OFPortDesc p : getPorts()) {
293 int pnum = p.getPortNo().getPortNumber();
294 int portVlan = getVlanConfig(pnum);
295 if (U32.of(pnum).compareTo(U32.of(OFPort.MAX.getPortNumber())) < 1) {
296 OFGroup gl2 = OFGroup.of(pnum | (portVlan << VLAN_ID_OFFSET));
297 OFAction out = factory.actions().buildOutput()
298 .setPort(p.getPortNo()).build();
299 OFAction popVlan = factory.actions().popVlan();
300 List<OFAction> actions = new ArrayList<OFAction>();
301 actions.add(popVlan);
302 actions.add(out);
303 OFBucket bucket = factory.buildBucket()
304 .setActions(actions).build();
305 List<OFBucket> buckets = Collections.singletonList(bucket);
306 OFMessage gmAdd = factory.buildGroupAdd()
307 .setGroup(gl2)
308 .setBuckets(buckets)
309 .setGroupType(OFGroupType.INDIRECT)
310 .setXid(getNextTransactionId())
311 .build();
312 msglist.add(gmAdd);
313 l2groups.put(pnum, gl2);
314 }
315 }
316 log.debug("Creating {} L2 groups in sw {}", msglist.size(), getStringId());
317 write(msglist);
318 }
319
320 private int getVlanConfig(int portnum) {
321 int portVlan = 10 * portnum;
322 if ((getId() == 0x1 && portnum == 6) ||
323 (getId() == 0x2) ||
324 (getId() == 0x3 && portnum == 2)) {
325 portVlan = 192; // 0xc0
326 }
327 return portVlan;
328 }
329
330 private MacAddress getRouterMacAddr() {
331 if (getId() == 0x3) {
332 return MacAddress.of("00:00:07:07:07:80"); // router mac
333 }
334 if (getId() == 0x1) {
335 return MacAddress.of("00:00:01:01:01:80");
336 }
337 // switch 0x2
338 return MacAddress.of("00:00:02:02:02:80");
339 }
340
341 // only for ports connected to other routers
342 private OFAction getDestAction(int portnum) {
343 OFAction setDA = null;
344 MacAddress dAddr = null;
345 if (getId() == 0x1 && portnum == 6) { // connected to switch 2
346 dAddr = MacAddress.of("00:00:02:02:02:80");
347 }
348 if (getId() == 0x2) {
349 if (portnum == 1) { // connected to sw 1
350 dAddr = MacAddress.of("00:00:01:01:01:80");
351 } else if (portnum == 2) { // connected to sw 3
352 dAddr = MacAddress.of("00:00:07:07:07:80");
353 }
354 }
355 if (getId() == 0x3) {
356 if (portnum == 2) { // connected to switch 2
357 dAddr = MacAddress.of("00:00:02:02:02:80");
358 }
359 }
360
361 if (dAddr != null) {
362 OFOxmEthDst dstAddr = factory.oxms().ethDst(dAddr);
363 setDA = factory.actions().buildSetField()
364 .setField(dstAddr).build();
365 }
366 return setDA;
367 }
368
369 /*
370 * L3 groups are created for all router ports and they all point to corresponding
371 * L2 groups. Only the ports that connect to other routers will have the
372 * DA set.
373 */
374 private void setL3Groups() throws IOException {
375 List<OFMessage> msglist = new ArrayList<OFMessage>();
376 for (OFGroup gl2 : l2groups.values()) {
377 int gnum = gl2.getGroupNumber();
378 int portnum = gnum & 0x0000ffff;
379 int vlanid = ((gnum & 0x0fff0000) >> VLAN_ID_OFFSET);
380 MacAddress sAddr = getRouterMacAddr();
381
382 OFGroup gl3 = OFGroup.of(0x20000000 | portnum);
383 OFAction group = factory.actions().buildGroup()
384 .setGroup(gl2).build();
385 OFOxmEthSrc srcAddr = factory.oxms().ethSrc(sAddr);
386 OFAction setSA = factory.actions().buildSetField()
387 .setField(srcAddr).build();
388 OFOxmVlanVid vid = factory.oxms().vlanVid(OFVlanVidMatch.ofVlan(vlanid));
389 OFAction setVlan = factory.actions().buildSetField()
390 .setField(vid).build();
391 OFAction decTtl = factory.actions().decNwTtl();
392
393 List<OFAction> actions = new ArrayList<OFAction>();
394 actions.add(decTtl); // decrement the IP TTL/do-checksum/check TTL
395 // and MTU
396 actions.add(setVlan); // set the vlan-id of the exit-port (and
397 // l2group)
398 actions.add(setSA); // set this routers mac address
399 // make L3Unicast group setDA for known (configured) ports
400 // that connect to other routers
401 OFAction setDA = getDestAction(portnum);
402 if (setDA != null) {
403 actions.add(setDA);
404 }
405 actions.add(group);
406
407 OFBucket bucket = factory.buildBucket()
408 .setActions(actions).build();
409 List<OFBucket> buckets = Collections.singletonList(bucket);
410 OFMessage gmAdd = factory.buildGroupAdd()
411 .setGroup(gl3)
412 .setBuckets(buckets)
413 .setGroupType(OFGroupType.INDIRECT)
414 .setXid(getNextTransactionId())
415 .build();
416 msglist.add(gmAdd);
417 }
418 write(msglist);
419 log.debug("Creating {} L3 groups in sw {}", msglist.size(), getStringId());
420 }
421
422 /*
423 * L2.5 or mpls-unicast groups are only created for those router ports
424 * connected to other router ports. They differ from the corresponding
425 * L3-unicast group only by the fact that they decrement the MPLS TTL
426 * instead of the IP ttl
427 */
428 private void setL25Groups() throws IOException {
429 List<OFMessage> msglist = new ArrayList<OFMessage>();
430 for (OFGroup gl2 : l2groups.values()) {
431 int gnum = gl2.getGroupNumber();
432 int portnum = gnum & 0x0000ffff;
433 int vlanid = ((gnum & 0x0fff0000) >> VLAN_ID_OFFSET);
434 MacAddress sAddr = getRouterMacAddr();
435 OFAction setDA = getDestAction(portnum);
436 // setDA will only be non-null for ports connected to routers
437 if (setDA != null) {
438 OFGroup gl3 = OFGroup.of(0xa0000000 | portnum); // different id
439 // for mpls
440 // group
441 OFAction group = factory.actions().buildGroup()
442 .setGroup(gl2).build();
443 OFOxmEthSrc srcAddr = factory.oxms().ethSrc(sAddr);
444 OFAction setSA = factory.actions().buildSetField()
445 .setField(srcAddr).build();
446 OFOxmVlanVid vid = factory.oxms().vlanVid(OFVlanVidMatch.ofVlan(vlanid));
447 OFAction setVlan = factory.actions().buildSetField()
448 .setField(vid).build();
449 OFAction decMplsTtl = factory.actions().decMplsTtl();
450 List<OFAction> actions = new ArrayList<OFAction>();
451 actions.add(decMplsTtl); // decrement the MPLS
452 // TTL/do-checksum/check TTL and MTU
453 actions.add(setVlan); // set the vlan-id of the exit-port (and
454 // l2group)
455 actions.add(setSA); // set this routers mac address
456 actions.add(setDA);
457 actions.add(group);
458 OFBucket bucket = factory.buildBucket()
459 .setActions(actions).build();
460 List<OFBucket> buckets = Collections.singletonList(bucket);
461 OFMessage gmAdd = factory.buildGroupAdd()
462 .setGroup(gl3)
463 .setBuckets(buckets)
464 .setGroupType(OFGroupType.INDIRECT)
465 .setXid(getNextTransactionId())
466 .build();
467 msglist.add(gmAdd);
468 }
469 }
470 write(msglist);
471 log.debug("Creating {} MPLS groups in sw {}", msglist.size(), getStringId());
472 }
473
474 /* Using ECMP groups
475 *
476 * OFGroup group47 = OFGroup.of(47);
477 OFAction outgroup1 = factory.actions()
478 .buildGroup()
479 .setGroup(group61)
480 .build();
481 OFBucket buc47_1 = factory.buildBucket()
482 .setWeight(1)
483 .setActions(Collections.singletonList(outgroup1))
484 .build();
485 OFAction outgroup2 = factory.actions()
486 .buildGroup()
487 .setGroup(group62)
488 .build();
489 OFBucket buc47_2 = factory.buildBucket()
490 .setWeight(1)
491 .setActions(Collections.singletonList(outgroup2))
492 .build();
493 List<OFBucket> buckets47 = new ArrayList<OFBucket>();
494 buckets47.add(buc47_1);
495 buckets47.add(buc47_2);
496 OFMessage gmS12 = factory.buildGroupAdd()
497 .setGroup(group47)
498 .setBuckets(buckets47)
499 .setGroupType(OFGroupType.SELECT)
500 .setXid(getNextTransactionId())
501 .build();
502 write(gmS12, null); */
503
504 private void processStatsReply(OFStatsReply sr) {
505 switch (sr.getStatsType()) {
506 case AGGREGATE:
507 break;
508 case DESC:
509 break;
510 case EXPERIMENTER:
511 break;
512 case FLOW:
513 break;
514 case GROUP_DESC:
515 processGroupDesc((OFGroupDescStatsReply) sr);
516 break;
517 case GROUP_FEATURES:
518 processGroupFeatures((OFGroupFeaturesStatsReply) sr);
519 break;
520 case METER_CONFIG:
521 break;
522 case METER_FEATURES:
523 break;
524 case PORT_DESC:
525 break;
526 case TABLE_FEATURES:
527 break;
528 default:
529 break;
530
531 }
532 }
533
534 private void processGroupFeatures(OFGroupFeaturesStatsReply gfsr) {
535 log.info("Sw: {} Group Features {}", getStringId(), gfsr);
536 }
537
538 private void processGroupDesc(OFGroupDescStatsReply gdsr) {
539 log.info("Sw: {} Group Desc {}", getStringId(), gdsr);
540 }
541
542 private void populateTableVlan() throws IOException {
543 // for all incoming ports assign configured port-vlans
544 // currently assign portnum*10 -> vlanid to access ports
545 // and vlan 192 to router to router ports
546 List<OFMessage> msglist = new ArrayList<OFMessage>();
547 for (OFPortDesc p : getPorts()) {
548 int pnum = p.getPortNo().getPortNumber();
549 if (U32.of(pnum).compareTo(U32.of(OFPort.MAX.getPortNumber())) < 1) {
550 int vlanid = getVlanConfig(pnum);
551 OFOxmInPort oxp = factory.oxms().inPort(p.getPortNo());
552 OFOxmVlanVid oxv = factory.oxms()
553 .vlanVid(OFVlanVidMatch.UNTAGGED);
554 OFOxmList oxmList = OFOxmList.of(oxp, oxv);
555 OFMatchV3 match = factory.buildMatchV3()
556 .setOxmList(oxmList).build();
557 OFOxmVlanVid vidToSet = factory.oxms()
558 .vlanVid(OFVlanVidMatch.ofVlan(vlanid));
559 OFAction pushVlan = factory.actions().pushVlan(EthType.VLAN_FRAME);
560 OFAction setVlan = factory.actions().setField(vidToSet);
561 List<OFAction> actionlist = new ArrayList<OFAction>();
562 actionlist.add(pushVlan);
563 actionlist.add(setVlan);
564 OFInstruction appAction = factory.instructions().buildApplyActions()
565 .setActions(actionlist).build();
566 OFInstruction gotoTbl = factory.instructions().buildGotoTable()
567 .setTableId(TableId.of(TABLE_TMAC)).build();
568 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
569 instructions.add(appAction);
570 instructions.add(gotoTbl);
571 OFMessage flowEntry = factory.buildFlowAdd()
572 .setTableId(TableId.of(TABLE_VLAN))
573 .setMatch(match)
574 .setInstructions(instructions)
575 .setPriority(1000) // does not matter - all rules
576 // exclusive
577 .setBufferId(OFBufferId.NO_BUFFER)
578 .setIdleTimeout(0)
579 .setHardTimeout(0)
580 .setXid(getNextTransactionId())
581 .build();
582 msglist.add(flowEntry);
583 }
584 }
585 // table-vlan has no table-miss entry, and so packets that miss are
586 // essentially dropped
587 write(msglist);
588 log.debug("Adding {} vlan-rules in sw {}", msglist.size(), getStringId());
589 }
590
591 private void populateTableTMac() throws IOException {
592 // match for ip packets
593 OFOxmEthType oxe = factory.oxms().ethType(EthType.IPv4);
594 OFOxmList oxmListIp = OFOxmList.of(oxe);
595 OFMatchV3 matchIp = factory.buildMatchV3()
596 .setOxmList(oxmListIp).build();
597 OFInstruction gotoTblIp = factory.instructions().buildGotoTable()
598 .setTableId(TableId.of(TABLE_IPV4_UNICAST)).build();
599 List<OFInstruction> instructionsIp = Collections.singletonList(gotoTblIp);
600 OFMessage ipEntry = factory.buildFlowAdd()
601 .setTableId(TableId.of(TABLE_TMAC))
602 .setMatch(matchIp)
603 .setInstructions(instructionsIp)
604 .setPriority(1000) // strict priority required lower than
605 // multicastMac
606 .setBufferId(OFBufferId.NO_BUFFER)
607 .setIdleTimeout(0)
608 .setHardTimeout(0)
609 .setXid(getNextTransactionId())
610 .build();
611
612 // match for mpls packets
613 OFOxmEthType oxmpls = factory.oxms().ethType(EthType.MPLS_UNICAST);
614 OFOxmList oxmListMpls = OFOxmList.of(oxmpls);
615 OFMatchV3 matchMpls = factory.buildMatchV3()
616 .setOxmList(oxmListMpls).build();
617 OFInstruction gotoTblMpls = factory.instructions().buildGotoTable()
618 .setTableId(TableId.of(TABLE_MPLS)).build();
619 List<OFInstruction> instructionsMpls = Collections.singletonList(gotoTblMpls);
620 OFMessage mplsEntry = factory.buildFlowAdd()
621 .setTableId(TableId.of(TABLE_TMAC))
622 .setMatch(matchMpls)
623 .setInstructions(instructionsMpls)
624 .setPriority(1001) // strict priority required lower than
625 // multicastMac
626 .setBufferId(OFBufferId.NO_BUFFER)
627 .setIdleTimeout(0)
628 .setHardTimeout(0)
629 .setXid(getNextTransactionId())
630 .build();
631
632 // match for everything else to send to controller. Essentially
633 // the table miss flow entry
634 populateTableMissEntry(TABLE_TMAC, true, false, false, -1);
635 log.debug("Adding termination-mac-rules in sw {}", getStringId());
636 List<OFMessage> msglist = new ArrayList<OFMessage>(2);
637 msglist.add(ipEntry);
638 msglist.add(mplsEntry);
639 write(msglist);
640 }
641
642 private List<String> getMyIps() { // send to controller
643 List<String> myIps = new ArrayList<String>();
644 if (getId() == 0x1) {
645 myIps.add("10.0.2.128");
646 myIps.add("10.0.3.128");
647 myIps.add("10.0.1.128");
648 myIps.add("192.168.0.1");
649 }
650 if (getId() == 0x2) {
651 myIps.add("192.168.0.2");
652 }
653 if (getId() == 0x3) {
654 myIps.add("192.168.0.3");
655 myIps.add("7.7.7.128");
656 }
657 return myIps;
658 }
659
660 private List<String> getMySubnetIps() { // send to controller
661 List<String> subnetIps = new ArrayList<String>();
662 if (getId() == 0x1) {
663 subnetIps.add("10.0.2.0");
664 subnetIps.add("10.0.3.0");
665 subnetIps.add("10.0.1.0");
666 }
667 // TODO needed?
668 //if (getId() == 0x2) {
669 //}
670 if (getId() == 0x3) {
671 subnetIps.add("7.7.7.0");
672 }
673 return subnetIps;
674 }
675
676 private static class RouteEntry {
677 String prefix;
678 String mask;
679 int nextHopPort;
680 String dstMac;
681 int label;
682
683 public RouteEntry(String prefix, String mask, int nextHopPort, int label) {
684 this.prefix = prefix;
685 this.mask = mask;
686 this.nextHopPort = nextHopPort;
687 this.label = label;
688 }
689
690 public RouteEntry(String prefix, int nextHopPort, String dstMac) {
691 this.prefix = prefix;
692 this.nextHopPort = nextHopPort;
693 this.dstMac = dstMac;
694 }
695 }
696
697 // send out of mpls-group where the next-hop mac-da is already set
698 private List<RouteEntry> getRouterNextHopIps() {
699 List<RouteEntry> routerNextHopIps = new ArrayList<RouteEntry>();
700 if (getId() == 0x1) {
701 routerNextHopIps
702 .add(new RouteEntry("192.168.0.2", "255.255.255.255", 6, 102));
703 routerNextHopIps
704 .add(new RouteEntry("192.168.0.3", "255.255.255.255", 6, 103));
705 routerNextHopIps.add(new RouteEntry("7.7.7.0", "255.255.255.0", 6, 103));
706 }
707 //if (getId() == 0x2) {
708 /* These are required for normal IP routing without labels.
709 routerNextHopIps.add(new RouteEntry("192.168.0.1","255.255.255.255",1));
710 routerNextHopIps.add(new RouteEntry("192.168.0.3","255.255.255.255",2));
711 routerNextHopIps.add(new RouteEntry("10.0.1.0","255.255.255.0",1));
712 routerNextHopIps.add(new RouteEntry("10.0.2.0","255.255.255.0",1));
713 routerNextHopIps.add(new RouteEntry("10.0.3.0","255.255.255.0",1));
714 routerNextHopIps.add(new RouteEntry("7.7.7.0","255.255.255.0",2));*/
715 //}
716 if (getId() == 0x3) {
717 routerNextHopIps
718 .add(new RouteEntry("192.168.0.2", "255.255.255.255", 2, 102));
719 routerNextHopIps
720 .add(new RouteEntry("192.168.0.1", "255.255.255.255", 2, 101));
721 routerNextHopIps.add(new RouteEntry("10.0.1.0", "255.255.255.0", 2, 101));
722 routerNextHopIps.add(new RouteEntry("10.0.2.0", "255.255.255.0", 2, 101));
723 routerNextHopIps.add(new RouteEntry("10.0.3.0", "255.255.255.0", 2, 101));
724 }
725 return routerNextHopIps;
726 }
727
728 // known host mac-addr, setDA/send out of l3group
729 private List<RouteEntry> getHostNextHopIps() {
730 List<RouteEntry> hostNextHopIps = new ArrayList<RouteEntry>();
731 if (getId() == 0x1) {
732 hostNextHopIps.add(new RouteEntry("10.0.2.1", 4, "00:00:00:00:02:01"));
733 hostNextHopIps.add(new RouteEntry("10.0.3.1", 5, "00:00:00:00:03:01"));
734 }
735 // TODO needed?
736 //if (getId() == 0x2) {
737 //}
738 if (getId() == 0x3) {
739 hostNextHopIps.add(new RouteEntry("7.7.7.7", 1, "00:00:07:07:07:07"));
740 }
741 return hostNextHopIps;
742 }
743
744 private void populateIpTable() throws IOException {
745 populateMyIps();
746 populateMySubnets();
747 populateRoutes();
748 populateHostRoutes();
749
750 // match for everything else to send to ACL table. Essentially
751 // the table miss flow entry
752 populateTableMissEntry(TABLE_IPV4_UNICAST, false, true,
753 true, TABLE_ACL);
754 }
755
756 private void populateMyIps() throws IOException {
757 List<OFMessage> msglist = new ArrayList<OFMessage>();
758 // first all my ip's as exact-matches
759 // write-action instruction to send to controller
760 List<String> myIps = getMyIps();
761 for (int i = 0; i < myIps.size(); i++) {
762 OFOxmEthType ethTypeIp = factory.oxms()
763 .ethType(EthType.IPv4);
764 OFOxmIpv4DstMasked ipPrefix = factory.oxms()
765 .ipv4DstMasked(IPv4Address.of(myIps.get(i)), IPv4Address.NO_MASK);
766 OFOxmList oxmListSlash32 = OFOxmList.of(ethTypeIp, ipPrefix);
767 OFMatchV3 match = factory.buildMatchV3()
768 .setOxmList(oxmListSlash32).build();
769 OFAction outc = factory.actions().buildOutput()
770 .setPort(OFPort.CONTROLLER).setMaxLen(OFPCML_NO_BUFFER)
771 .build();
772 OFInstruction writeInstr = factory.instructions().buildWriteActions()
773 .setActions(Collections.singletonList(outc)).build();
774 OFInstruction gotoInstr = factory.instructions().buildGotoTable()
775 .setTableId(TableId.of(TABLE_ACL)).build();
776 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
777 instructions.add(writeInstr);
778 instructions.add(gotoInstr);
779 OFMessage myIpEntry = factory.buildFlowAdd()
780 .setTableId(TableId.of(TABLE_IPV4_UNICAST))
781 .setMatch(match)
782 .setInstructions(instructions)
783 .setPriority(MAX_PRIORITY) // highest priority for exact
784 // match
785 .setBufferId(OFBufferId.NO_BUFFER)
786 .setIdleTimeout(0)
787 .setHardTimeout(0)
788 .setXid(getNextTransactionId())
789 .build();
790 msglist.add(myIpEntry);
791 }
792 write(msglist);
793 log.debug("Adding {} my-ip-rules in sw {}", msglist.size(), getStringId());
794 }
795
796 private void populateMySubnets() throws IOException {
797 List<OFMessage> msglist = new ArrayList<OFMessage>();
798 // next prefix-based subnet-IP's configured on my interfaces
799 // need to ARP for exact-IP, so write-action instruction to send to
800 // controller
801 // this has different mask and priority than earlier case
802 List<String> subnetIps = getMySubnetIps();
803 for (int i = 0; i < subnetIps.size(); i++) {
804 OFOxmEthType ethTypeIp = factory.oxms()
805 .ethType(EthType.IPv4);
806 OFOxmIpv4DstMasked ipPrefix = factory.oxms().ipv4DstMasked(
807 IPv4Address.of(subnetIps.get(i)),
808 IPv4Address.of(0xffffff00)); // '/24' mask
809 OFOxmList oxmListSlash24 = OFOxmList.of(ethTypeIp, ipPrefix);
810 OFMatchV3 match = factory.buildMatchV3()
811 .setOxmList(oxmListSlash24).build();
812 OFAction outc = factory.actions().buildOutput()
813 .setPort(OFPort.CONTROLLER).setMaxLen(OFPCML_NO_BUFFER)
814 .build();
815 OFInstruction writeInstr = factory.instructions().buildWriteActions()
816 .setActions(Collections.singletonList(outc)).build();
817 OFInstruction gotoInstr = factory.instructions().buildGotoTable()
818 .setTableId(TableId.of(TABLE_ACL)).build();
819 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
820 instructions.add(writeInstr);
821 instructions.add(gotoInstr);
822 OFMessage myIpEntry = factory.buildFlowAdd()
823 .setTableId(TableId.of(TABLE_IPV4_UNICAST))
824 .setMatch(match)
825 .setInstructions(instructions)
826 .setPriority(SLASH_24_PRIORITY)
827 .setBufferId(OFBufferId.NO_BUFFER)
828 .setIdleTimeout(0)
829 .setHardTimeout(0)
830 .setXid(getNextTransactionId())
831 .build();
832 msglist.add(myIpEntry);
833 }
834 write(msglist);
835 log.debug("Adding {} subnet-ip-rules in sw {}", msglist.size(), getStringId());
836 msglist.clear();
837 }
838
839 private void populateRoutes() throws IOException {
840 List<OFMessage> msglist = new ArrayList<OFMessage>();
841 // addresses where I know the next-hop's mac-address because it is a
842 // router port - so I have an L3 interface to it (and an MPLS interface)
843 List<RouteEntry> routerNextHopIps = getRouterNextHopIps();
844 for (int i = 0; i < routerNextHopIps.size(); i++) {
845 OFOxmEthType ethTypeIp = factory.oxms()
846 .ethType(EthType.IPv4);
847 OFOxmIpv4DstMasked ipPrefix = factory.oxms()
848 .ipv4DstMasked(
849 IPv4Address.of(routerNextHopIps.get(i).prefix),
850 IPv4Address.of(routerNextHopIps.get(i).mask)
851 );
852 OFOxmList oxmListSlash32 = OFOxmList.of(ethTypeIp, ipPrefix);
853 OFMatchV3 match = factory.buildMatchV3()
854 .setOxmList(oxmListSlash32).build();
855 OFAction outg = factory.actions().buildGroup()
856 .setGroup(OFGroup.of(0xa0000000 | // mpls group id
857 routerNextHopIps.get(i).nextHopPort))
858 .build();
859 // lots of actions before forwarding to mpls group, and
860 // unfortunately
861 // they need to be apply-actions
862
863 OFAction pushlabel = factory.actions().pushMpls(EthType.MPLS_UNICAST);
864 OFOxmMplsLabel l = factory.oxms()
865 .mplsLabel(U32.of(routerNextHopIps.get(i).label));
866 OFAction setlabelid = factory.actions().buildSetField()
867 .setField(l).build();
868 OFAction copyTtlOut = factory.actions().copyTtlOut();
869 // OFAction setBos =
870 // factory.actions().buildSetField().setField(bos).build();
871
872 /*
873 writeActions.add(pushlabel); // need to be apply actions so can be
874 writeActions.add(copyTtlOut); // matched in pseudo-table
875 //writeActions.add(setlabelid); // bad support in cpqd
876 //writeActions.add(setBos); no support in loxigen
877 */
878
879 List<OFAction> applyActions = new ArrayList<OFAction>();
880 applyActions.add(pushlabel);
881 applyActions.add(copyTtlOut);
882 OFInstruction applyInstr = factory.instructions().buildApplyActions()
883 .setActions(applyActions).build();
884 List<OFAction> writeActions = new ArrayList<OFAction>();
885 writeActions.add(outg); // group will decr mpls-ttl, set mac-sa/da,
886 // vlan
887 OFInstruction writeInstr = factory.instructions().buildWriteActions()
888 .setActions(writeActions).build();
889
890 // necessary to match in pseudo-table to overcome cpqd 1.3 flaw
891 OFInstruction writeMeta = factory.instructions().buildWriteMetadata()
892 .setMetadata(U64.of(routerNextHopIps.get(i).label))
893 .setMetadataMask(METADATA_MASK).build();
894 /*OFInstruction gotoInstr = factory.instructions().buildGotoTable()
895 .setTableId(TableId.of(TABLE_ACL)).build();*/
896 OFInstruction gotoInstr = factory.instructions().buildGotoTable()
897 .setTableId(TableId.of(TABLE_META)).build();
898 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
899 instructions.add(applyInstr);
900 // instructions.add(writeInstr);// cannot write here - causes switch
901 // to crash
902 instructions.add(writeMeta);
903 instructions.add(gotoInstr);
904
905 int priority = -1;
906 if (routerNextHopIps.get(i).mask.equals("255.255.255.255")) {
907 priority = MAX_PRIORITY;
908 } else {
909 priority = SLASH_24_PRIORITY;
910 }
911 OFMessage myIpEntry = factory.buildFlowAdd()
912 .setTableId(TableId.of(TABLE_IPV4_UNICAST))
913 .setMatch(match)
914 .setInstructions(instructions)
915 .setPriority(priority)
916 .setBufferId(OFBufferId.NO_BUFFER)
917 .setIdleTimeout(0)
918 .setHardTimeout(0)
919 .setXid(getNextTransactionId())
920 .build();
921 msglist.add(myIpEntry);
922
923 // need to also handle psuedo-table entries to match-metadata and
924 // set mpls
925 // label-id
926 OFOxmEthType ethTypeMpls = factory.oxms()
927 .ethType(EthType.MPLS_UNICAST);
928 OFOxmMetadataMasked meta = factory.oxms()
929 .metadataMasked(
930 OFMetadata.ofRaw(routerNextHopIps.get(i).label),
931 OFMetadata.NO_MASK);
932 OFOxmList oxmListMeta = OFOxmList.of(ethTypeMpls, meta);
933 OFMatchV3 matchMeta = factory.buildMatchV3()
934 .setOxmList(oxmListMeta).build();
935 List<OFAction> writeActions2 = new ArrayList<OFAction>();
936 writeActions2.add(setlabelid);
937 OFAction outg2 = factory.actions().buildGroup()
938 .setGroup(OFGroup.of(routerNextHopIps.get(i).nextHopPort |
939 (192 << VLAN_ID_OFFSET)))
940 .build();
941 writeActions2.add(outg2);
942 OFInstruction writeInstr2 = factory.instructions().buildWriteActions()
943 .setActions(writeActions2).build();
944 OFInstruction gotoInstr2 = factory.instructions().buildGotoTable()
945 .setTableId(TableId.of(TABLE_ACL)).build();
946 List<OFInstruction> instructions2 = new ArrayList<OFInstruction>();
947 // unfortunately have to apply this action too
948 OFInstruction applyInstr2 = factory.instructions().buildApplyActions()
949 .setActions(writeActions2).build();
950 instructions2.add(applyInstr2);
951 // instructions2.add(writeInstr2);
952 // instructions2.add(gotoInstr2);
953
954 /*OFMatchV3 match3 = factory.buildMatchV3()
955 .setOxmList(OFOxmList.of(meta)).build();
956 OFInstruction clearInstruction = factory.instructions().clearActions();
957 List<OFInstruction> instructions3 = new ArrayList<OFInstruction>();
958 OFAction outc = factory.actions().buildOutput()
959 .setPort(OFPort.CONTROLLER).setMaxLen(OFPCML_NO_BUFFER)
960 .build();
961 OFInstruction writec = factory.instructions()
962 .writeActions(Collections.singletonList(outc));
963 instructions3.add(clearInstruction);
964 instructions3.add(writec);
965 instructions3.add(gotoInstr2); */
966 OFMessage myMetaEntry = factory.buildFlowAdd()
967 .setTableId(TableId.of(TABLE_META))
968 .setMatch(matchMeta)
969 .setInstructions(instructions2)
970 .setPriority(MAX_PRIORITY)
971 .setBufferId(OFBufferId.NO_BUFFER)
972 .setIdleTimeout(0)
973 .setHardTimeout(0)
974 .setXid(getNextTransactionId())
975 .build();
976 msglist.add(myMetaEntry);
977
978 }
979 write(msglist);
980 log.debug("Adding {} next-hop-router-rules in sw {}", msglist.size(),
981 getStringId());
982
983 // add a table-miss entry to table 4 for debugging - leave it out
984 // unclear packet state - causes switch to crash
985 // populateTableMissEntry(TABLE_META, false, true,
986 // true, TABLE_ACL);
987 }
988
989 private void populateHostRoutes() throws IOException {
990 List<OFMessage> msglist = new ArrayList<OFMessage>();
991 // addresses where I know the next hop's mac-address and I can set the
992 // destination mac in the match-instruction.write-action
993 // either I sent out arp-request or I got an arp-request from this host
994 List<RouteEntry> hostNextHopIps = getHostNextHopIps();
995 for (int i = 0; i < hostNextHopIps.size(); i++) {
996 OFOxmEthType ethTypeIp = factory.oxms()
997 .ethType(EthType.IPv4);
998 OFOxmIpv4DstMasked ipPrefix = factory.oxms()
999 .ipv4DstMasked(
1000 IPv4Address.of(hostNextHopIps.get(i).prefix),
1001 IPv4Address.NO_MASK); // host addr should be /32
1002 OFOxmList oxmListSlash32 = OFOxmList.of(ethTypeIp, ipPrefix);
1003 OFMatchV3 match = factory.buildMatchV3()
1004 .setOxmList(oxmListSlash32).build();
1005 OFAction setDmac = null, outg = null;
1006 OFOxmEthDst dmac = factory.oxms()
1007 .ethDst(MacAddress.of(hostNextHopIps.get(i).dstMac));
1008 setDmac = factory.actions().buildSetField()
1009 .setField(dmac).build();
1010 outg = factory.actions().buildGroup()
1011 .setGroup(OFGroup.of(0x20000000 | hostNextHopIps.get(i).nextHopPort)) // l3group
1012 // id
1013 .build();
1014 List<OFAction> writeActions = new ArrayList<OFAction>();
1015 writeActions.add(setDmac);
1016 writeActions.add(outg);
1017 OFInstruction writeInstr = factory.instructions().buildWriteActions()
1018 .setActions(writeActions).build();
1019 OFInstruction gotoInstr = factory.instructions().buildGotoTable()
1020 .setTableId(TableId.of(TABLE_ACL)).build();
1021 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
1022 instructions.add(writeInstr);
1023 instructions.add(gotoInstr);
1024 OFMessage myIpEntry = factory.buildFlowAdd()
1025 .setTableId(TableId.of(TABLE_IPV4_UNICAST))
1026 .setMatch(match)
1027 .setInstructions(instructions)
1028 .setPriority(MAX_PRIORITY) // highest priority for exact
1029 // match
1030 .setBufferId(OFBufferId.NO_BUFFER)
1031 .setIdleTimeout(0)
1032 .setHardTimeout(0)
1033 .setXid(getNextTransactionId())
1034 .build();
1035 msglist.add(myIpEntry);
1036 }
1037 write(msglist);
1038 log.debug("Adding {} next-hop-host-rules in sw {}", msglist.size(), getStringId());
1039 }
1040
1041 private static class MplsEntry {
1042 int labelid;
1043 int portnum;
1044
1045 public MplsEntry(int labelid, int portnum) {
1046 this.labelid = labelid;
1047 this.portnum = portnum;
1048 }
1049 }
1050
1051 private List<MplsEntry> getMplsEntries() {
1052 List<MplsEntry> myLabels = new ArrayList<MplsEntry>();
1053 if (getId() == 0x1) {
1054 myLabels.add(new MplsEntry(101, OFPort.CONTROLLER.getPortNumber()));
1055 myLabels.add(new MplsEntry(103, 6));
1056 }
1057 if (getId() == 0x2) {
1058 myLabels.add(new MplsEntry(103, 2));
1059 myLabels.add(new MplsEntry(102, OFPort.CONTROLLER.getPortNumber()));
1060 myLabels.add(new MplsEntry(101, 1));
1061 }
1062 if (getId() == 0x3) {
1063 myLabels.add(new MplsEntry(103, OFPort.CONTROLLER.getPortNumber()));
1064 myLabels.add(new MplsEntry(101, 2));
1065 }
1066 return myLabels;
1067 }
1068
1069 private void populateMplsTable() throws IOException {
1070 List<OFMessage> msglist = new ArrayList<OFMessage>();
1071 List<MplsEntry> lfibEntries = getMplsEntries();
1072 for (int i = 0; i < lfibEntries.size(); i++) {
1073 OFOxmEthType ethTypeMpls = factory.oxms()
1074 .ethType(EthType.MPLS_UNICAST);
1075 OFOxmMplsLabel labelid = factory.oxms()
1076 .mplsLabel(U32.of(lfibEntries.get(i).labelid));
1077 OFOxmList oxmList = OFOxmList.of(ethTypeMpls, labelid);
1078 OFMatchV3 matchlabel = factory.buildMatchV3()
1079 .setOxmList(oxmList).build();
1080 OFAction poplabel = factory.actions().popMpls(EthType.IPv4);
1081 OFAction sendTo = null;
1082 if (lfibEntries.get(i).portnum == OFPort.CONTROLLER.getPortNumber()) {
1083 sendTo = factory.actions().output(OFPort.CONTROLLER,
1084 OFPCML_NO_BUFFER);
1085 } else {
1086 sendTo = factory.actions().group(OFGroup.of(
1087 0xa0000000 | lfibEntries.get(i).portnum));
1088 }
1089 List<OFAction> writeActions = new ArrayList<OFAction>();
1090 writeActions.add(poplabel);
1091 writeActions.add(sendTo);
1092 OFInstruction writeInstr = factory.instructions().buildWriteActions()
1093 .setActions(writeActions).build();
1094 OFInstruction gotoInstr = factory.instructions().buildGotoTable()
1095 .setTableId(TableId.of(TABLE_ACL)).build();
1096 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
1097 instructions.add(writeInstr);
1098 instructions.add(gotoInstr);
1099 OFMessage myMplsEntry = factory.buildFlowAdd()
1100 .setTableId(TableId.of(TABLE_MPLS))
1101 .setMatch(matchlabel)
1102 .setInstructions(instructions)
1103 .setPriority(MAX_PRIORITY) // exact match and exclusive
1104 .setBufferId(OFBufferId.NO_BUFFER)
1105 .setIdleTimeout(0)
1106 .setHardTimeout(0)
1107 .setXid(getNextTransactionId())
1108 .build();
1109 msglist.add(myMplsEntry);
1110 }
1111 write(msglist);
1112 log.debug("Adding {} mpls-forwarding-rules in sw {}", msglist.size(),
1113 getStringId());
1114
1115 // match for everything else to send to ACL table. Essentially
1116 // the table miss flow entry
1117 populateTableMissEntry(TABLE_MPLS, false, true,
1118 true, TABLE_ACL);
1119
1120 }
1121
1122 /**
1123 * By default if none of the booleans in the call are set, then the
1124 * table-miss entry is added with no instructions, which means that pipeline
1125 * execution will stop, and the action set associated with the packet will
1126 * be executed.
1127 *
1128 * @param tableToAdd
1129 * @param toControllerNow as an APPLY_ACTION instruction
1130 * @param toControllerWrite as a WRITE_ACITION instruction
1131 * @param toTable as a GOTO_TABLE instruction
1132 * @param tableToSend
1133 * @throws IOException
1134 */
1135 @SuppressWarnings("unchecked")
1136 private void populateTableMissEntry(int tableToAdd, boolean toControllerNow,
1137 boolean toControllerWrite,
1138 boolean toTable, int tableToSend) throws IOException {
1139 OFOxmList oxmList = OFOxmList.EMPTY;
1140 OFMatchV3 match = factory.buildMatchV3()
1141 .setOxmList(oxmList)
1142 .build();
1143 OFAction outc = factory.actions()
1144 .buildOutput()
1145 .setPort(OFPort.CONTROLLER)
1146 .setMaxLen(OFPCML_NO_BUFFER)
1147 .build();
1148 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
1149 if (toControllerNow) {
1150 // table-miss instruction to send to controller immediately
1151 OFInstruction instr = factory.instructions()
1152 .buildApplyActions()
1153 .setActions(Collections.singletonList(outc))
1154 .build();
1155 instructions.add(instr);
1156 }
1157
1158 if (toControllerWrite) {
1159 // table-miss instruction to write-action to send to controller
1160 // this will be executed whenever the action-set gets executed
1161 OFInstruction instr = factory.instructions()
1162 .buildWriteActions()
1163 .setActions(Collections.singletonList(outc))
1164 .build();
1165 instructions.add(instr);
1166 }
1167
1168 if (toTable) {
1169 // table-miss instruction to goto-table x
1170 OFInstruction instr = factory.instructions()
1171 .gotoTable(TableId.of(tableToSend));
1172 instructions.add(instr);
1173 }
1174
1175 if (!toControllerNow && !toControllerWrite && !toTable) {
1176 // table-miss has no instruction - at which point action-set will be
1177 // executed - if there is an action to output/group in the action
1178 // set
1179 // the packet will be sent there, otherwise it will be dropped.
1180 instructions = (List<OFInstruction>) Collections.EMPTY_LIST;
1181 }
1182
1183 OFMessage tableMissEntry = factory.buildFlowAdd()
1184 .setTableId(TableId.of(tableToAdd))
1185 .setMatch(match) // match everything
1186 .setInstructions(instructions)
1187 .setPriority(MIN_PRIORITY)
1188 .setBufferId(OFBufferId.NO_BUFFER)
1189 .setIdleTimeout(0)
1190 .setHardTimeout(0)
1191 .setXid(getNextTransactionId())
1192 .build();
1193 write(tableMissEntry, null);
1194 }
1195
1196 private void sendBarrier(boolean finalBarrier) throws IOException {
1197 int xid = getNextTransactionId();
1198 if (finalBarrier) {
1199 barrierXidToWaitFor = xid;
1200 }
1201 OFBarrierRequest br = factory
1202 .buildBarrierRequest()
1203 .setXid(xid)
1204 .build();
1205 write(br, null);
1206 }
1207
1208}