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