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