blob: 483bbda2f414d9e005de10a9eb845efc6b9dbdb6 [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
alshabiba2df7b2a2015-05-06 13:57:10 -0700225 msglist.stream().forEach(m -> sendHandshakeMessage(m));
tom7ef8ff92014-09-17 13:08:06 -0700226 }
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();
alshabiba2df7b2a2015-05-06 13:57:10 -0700248 sendHandshakeMessage(gtf);
tom7ef8ff92014-09-17 13:08:06 -0700249 }
250
251 private void sendGroupFeaturesRequest() throws IOException {
252 OFMessage gfr = factory.buildGroupFeaturesStatsRequest()
253 .setXid(getNextTransactionId())
254 .build();
alshabiba2df7b2a2015-05-06 13:57:10 -0700255 sendHandshakeMessage(gfr);
tom7ef8ff92014-09-17 13:08:06 -0700256 }
257
258 private void sendGroupDescRequest() throws IOException {
259 OFMessage gdr = factory.buildGroupDescStatsRequest()
260 .setXid(getNextTransactionId())
261 .build();
alshabiba2df7b2a2015-05-06 13:57:10 -0700262 sendHandshakeMessage(gdr);
tom7ef8ff92014-09-17 13:08:06 -0700263 }
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();
alshabiba2df7b2a2015-05-06 13:57:10 -0700293 sendHandshakeMessage(gmAdd);
tom7ef8ff92014-09-17 13:08:06 -0700294 msglist.add(gmAdd);
295 l2groups.put(pnum, gl2);
296 }
297 }
298 log.debug("Creating {} L2 groups in sw {}", msglist.size(), getStringId());
tom7ef8ff92014-09-17 13:08:06 -0700299 }
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();
alshabiba2df7b2a2015-05-06 13:57:10 -0700397 sendHandshakeMessage(gmAdd);
398
tom7ef8ff92014-09-17 13:08:06 -0700399 }
alshabiba2df7b2a2015-05-06 13:57:10 -0700400
tom7ef8ff92014-09-17 13:08:06 -0700401 log.debug("Creating {} L3 groups in sw {}", msglist.size(), getStringId());
402 }
403
404 /*
405 * L2.5 or mpls-unicast groups are only created for those router ports
406 * connected to other router ports. They differ from the corresponding
407 * L3-unicast group only by the fact that they decrement the MPLS TTL
408 * instead of the IP ttl
409 */
410 private void setL25Groups() throws IOException {
alshabiba2df7b2a2015-05-06 13:57:10 -0700411
tom7ef8ff92014-09-17 13:08:06 -0700412 for (OFGroup gl2 : l2groups.values()) {
413 int gnum = gl2.getGroupNumber();
414 int portnum = gnum & 0x0000ffff;
415 int vlanid = ((gnum & 0x0fff0000) >> VLAN_ID_OFFSET);
416 MacAddress sAddr = getRouterMacAddr();
417 OFAction setDA = getDestAction(portnum);
418 // setDA will only be non-null for ports connected to routers
419 if (setDA != null) {
420 OFGroup gl3 = OFGroup.of(0xa0000000 | portnum); // different id
421 // for mpls
422 // group
423 OFAction group = factory.actions().buildGroup()
424 .setGroup(gl2).build();
425 OFOxmEthSrc srcAddr = factory.oxms().ethSrc(sAddr);
426 OFAction setSA = factory.actions().buildSetField()
427 .setField(srcAddr).build();
428 OFOxmVlanVid vid = factory.oxms().vlanVid(OFVlanVidMatch.ofVlan(vlanid));
429 OFAction setVlan = factory.actions().buildSetField()
430 .setField(vid).build();
431 OFAction decMplsTtl = factory.actions().decMplsTtl();
432 List<OFAction> actions = new ArrayList<OFAction>();
433 actions.add(decMplsTtl); // decrement the MPLS
434 // TTL/do-checksum/check TTL and MTU
435 actions.add(setVlan); // set the vlan-id of the exit-port (and
436 // l2group)
437 actions.add(setSA); // set this routers mac address
438 actions.add(setDA);
439 actions.add(group);
440 OFBucket bucket = factory.buildBucket()
441 .setActions(actions).build();
442 List<OFBucket> buckets = Collections.singletonList(bucket);
443 OFMessage gmAdd = factory.buildGroupAdd()
444 .setGroup(gl3)
445 .setBuckets(buckets)
446 .setGroupType(OFGroupType.INDIRECT)
447 .setXid(getNextTransactionId())
448 .build();
alshabiba2df7b2a2015-05-06 13:57:10 -0700449 sendHandshakeMessage(gmAdd);
450
tom7ef8ff92014-09-17 13:08:06 -0700451 }
452 }
alshabiba2df7b2a2015-05-06 13:57:10 -0700453
454 log.debug("Created MPLS groups in sw {}", getStringId());
tom7ef8ff92014-09-17 13:08:06 -0700455 }
456
457 /* Using ECMP groups
458 *
459 * OFGroup group47 = OFGroup.of(47);
460 OFAction outgroup1 = factory.actions()
461 .buildGroup()
462 .setGroup(group61)
463 .build();
464 OFBucket buc47_1 = factory.buildBucket()
465 .setWeight(1)
466 .setActions(Collections.singletonList(outgroup1))
467 .build();
468 OFAction outgroup2 = factory.actions()
469 .buildGroup()
470 .setGroup(group62)
471 .build();
472 OFBucket buc47_2 = factory.buildBucket()
473 .setWeight(1)
474 .setActions(Collections.singletonList(outgroup2))
475 .build();
476 List<OFBucket> buckets47 = new ArrayList<OFBucket>();
477 buckets47.add(buc47_1);
478 buckets47.add(buc47_2);
479 OFMessage gmS12 = factory.buildGroupAdd()
480 .setGroup(group47)
481 .setBuckets(buckets47)
482 .setGroupType(OFGroupType.SELECT)
483 .setXid(getNextTransactionId())
484 .build();
485 write(gmS12, null); */
486
487 private void processStatsReply(OFStatsReply sr) {
488 switch (sr.getStatsType()) {
489 case AGGREGATE:
490 break;
491 case DESC:
492 break;
493 case EXPERIMENTER:
494 break;
495 case FLOW:
496 break;
497 case GROUP_DESC:
498 processGroupDesc((OFGroupDescStatsReply) sr);
499 break;
500 case GROUP_FEATURES:
501 processGroupFeatures((OFGroupFeaturesStatsReply) sr);
502 break;
503 case METER_CONFIG:
504 break;
505 case METER_FEATURES:
506 break;
507 case PORT_DESC:
508 break;
509 case TABLE_FEATURES:
510 break;
511 default:
512 break;
513
514 }
515 }
516
517 private void processGroupFeatures(OFGroupFeaturesStatsReply gfsr) {
518 log.info("Sw: {} Group Features {}", getStringId(), gfsr);
519 }
520
521 private void processGroupDesc(OFGroupDescStatsReply gdsr) {
522 log.info("Sw: {} Group Desc {}", getStringId(), gdsr);
523 }
524
525 private void populateTableVlan() throws IOException {
526 // for all incoming ports assign configured port-vlans
527 // currently assign portnum*10 -> vlanid to access ports
528 // and vlan 192 to router to router ports
529 List<OFMessage> msglist = new ArrayList<OFMessage>();
530 for (OFPortDesc p : getPorts()) {
531 int pnum = p.getPortNo().getPortNumber();
532 if (U32.of(pnum).compareTo(U32.of(OFPort.MAX.getPortNumber())) < 1) {
533 int vlanid = getVlanConfig(pnum);
534 OFOxmInPort oxp = factory.oxms().inPort(p.getPortNo());
535 OFOxmVlanVid oxv = factory.oxms()
536 .vlanVid(OFVlanVidMatch.UNTAGGED);
537 OFOxmList oxmList = OFOxmList.of(oxp, oxv);
538 OFMatchV3 match = factory.buildMatchV3()
539 .setOxmList(oxmList).build();
540 OFOxmVlanVid vidToSet = factory.oxms()
541 .vlanVid(OFVlanVidMatch.ofVlan(vlanid));
542 OFAction pushVlan = factory.actions().pushVlan(EthType.VLAN_FRAME);
543 OFAction setVlan = factory.actions().setField(vidToSet);
544 List<OFAction> actionlist = new ArrayList<OFAction>();
545 actionlist.add(pushVlan);
546 actionlist.add(setVlan);
547 OFInstruction appAction = factory.instructions().buildApplyActions()
548 .setActions(actionlist).build();
549 OFInstruction gotoTbl = factory.instructions().buildGotoTable()
550 .setTableId(TableId.of(TABLE_TMAC)).build();
551 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
552 instructions.add(appAction);
553 instructions.add(gotoTbl);
554 OFMessage flowEntry = factory.buildFlowAdd()
555 .setTableId(TableId.of(TABLE_VLAN))
556 .setMatch(match)
557 .setInstructions(instructions)
558 .setPriority(1000) // does not matter - all rules
559 // exclusive
560 .setBufferId(OFBufferId.NO_BUFFER)
561 .setIdleTimeout(0)
562 .setHardTimeout(0)
563 .setXid(getNextTransactionId())
564 .build();
alshabiba2df7b2a2015-05-06 13:57:10 -0700565 sendHandshakeMessage(flowEntry);
566
tom7ef8ff92014-09-17 13:08:06 -0700567 }
568 }
569 // table-vlan has no table-miss entry, and so packets that miss are
570 // essentially dropped
alshabiba2df7b2a2015-05-06 13:57:10 -0700571
572 log.debug("Added vlan-rules in sw {}", getStringId());
tom7ef8ff92014-09-17 13:08:06 -0700573 }
574
575 private void populateTableTMac() throws IOException {
576 // match for ip packets
577 OFOxmEthType oxe = factory.oxms().ethType(EthType.IPv4);
578 OFOxmList oxmListIp = OFOxmList.of(oxe);
579 OFMatchV3 matchIp = factory.buildMatchV3()
580 .setOxmList(oxmListIp).build();
581 OFInstruction gotoTblIp = factory.instructions().buildGotoTable()
582 .setTableId(TableId.of(TABLE_IPV4_UNICAST)).build();
583 List<OFInstruction> instructionsIp = Collections.singletonList(gotoTblIp);
584 OFMessage ipEntry = factory.buildFlowAdd()
585 .setTableId(TableId.of(TABLE_TMAC))
586 .setMatch(matchIp)
587 .setInstructions(instructionsIp)
588 .setPriority(1000) // strict priority required lower than
589 // multicastMac
590 .setBufferId(OFBufferId.NO_BUFFER)
591 .setIdleTimeout(0)
592 .setHardTimeout(0)
593 .setXid(getNextTransactionId())
594 .build();
595
596 // match for mpls packets
597 OFOxmEthType oxmpls = factory.oxms().ethType(EthType.MPLS_UNICAST);
598 OFOxmList oxmListMpls = OFOxmList.of(oxmpls);
599 OFMatchV3 matchMpls = factory.buildMatchV3()
600 .setOxmList(oxmListMpls).build();
601 OFInstruction gotoTblMpls = factory.instructions().buildGotoTable()
602 .setTableId(TableId.of(TABLE_MPLS)).build();
603 List<OFInstruction> instructionsMpls = Collections.singletonList(gotoTblMpls);
604 OFMessage mplsEntry = factory.buildFlowAdd()
605 .setTableId(TableId.of(TABLE_TMAC))
606 .setMatch(matchMpls)
607 .setInstructions(instructionsMpls)
608 .setPriority(1001) // strict priority required lower than
609 // multicastMac
610 .setBufferId(OFBufferId.NO_BUFFER)
611 .setIdleTimeout(0)
612 .setHardTimeout(0)
613 .setXid(getNextTransactionId())
614 .build();
615
616 // match for everything else to send to controller. Essentially
617 // the table miss flow entry
618 populateTableMissEntry(TABLE_TMAC, true, false, false, -1);
619 log.debug("Adding termination-mac-rules in sw {}", getStringId());
620 List<OFMessage> msglist = new ArrayList<OFMessage>(2);
621 msglist.add(ipEntry);
622 msglist.add(mplsEntry);
alshabiba2df7b2a2015-05-06 13:57:10 -0700623 msglist.stream().forEach(m -> sendHandshakeMessage(m));
tom7ef8ff92014-09-17 13:08:06 -0700624 }
625
626 private List<String> getMyIps() { // send to controller
627 List<String> myIps = new ArrayList<String>();
628 if (getId() == 0x1) {
629 myIps.add("10.0.2.128");
630 myIps.add("10.0.3.128");
631 myIps.add("10.0.1.128");
632 myIps.add("192.168.0.1");
633 }
634 if (getId() == 0x2) {
635 myIps.add("192.168.0.2");
636 }
637 if (getId() == 0x3) {
638 myIps.add("192.168.0.3");
639 myIps.add("7.7.7.128");
640 }
641 return myIps;
642 }
643
644 private List<String> getMySubnetIps() { // send to controller
645 List<String> subnetIps = new ArrayList<String>();
646 if (getId() == 0x1) {
647 subnetIps.add("10.0.2.0");
648 subnetIps.add("10.0.3.0");
649 subnetIps.add("10.0.1.0");
650 }
alshabib4785eec2014-12-04 16:45:45 -0800651
tom7ef8ff92014-09-17 13:08:06 -0700652 if (getId() == 0x3) {
653 subnetIps.add("7.7.7.0");
654 }
655 return subnetIps;
656 }
tom7ef8ff92014-09-17 13:08:06 -0700657 private static class RouteEntry {
658 String prefix;
659 String mask;
660 int nextHopPort;
661 String dstMac;
662 int label;
663
664 public RouteEntry(String prefix, String mask, int nextHopPort, int label) {
665 this.prefix = prefix;
666 this.mask = mask;
667 this.nextHopPort = nextHopPort;
668 this.label = label;
669 }
670
671 public RouteEntry(String prefix, int nextHopPort, String dstMac) {
672 this.prefix = prefix;
673 this.nextHopPort = nextHopPort;
674 this.dstMac = dstMac;
675 }
676 }
677
678 // send out of mpls-group where the next-hop mac-da is already set
679 private List<RouteEntry> getRouterNextHopIps() {
680 List<RouteEntry> routerNextHopIps = new ArrayList<RouteEntry>();
681 if (getId() == 0x1) {
682 routerNextHopIps
683 .add(new RouteEntry("192.168.0.2", "255.255.255.255", 6, 102));
684 routerNextHopIps
685 .add(new RouteEntry("192.168.0.3", "255.255.255.255", 6, 103));
686 routerNextHopIps.add(new RouteEntry("7.7.7.0", "255.255.255.0", 6, 103));
687 }
688 //if (getId() == 0x2) {
689 /* These are required for normal IP routing without labels.
690 routerNextHopIps.add(new RouteEntry("192.168.0.1","255.255.255.255",1));
691 routerNextHopIps.add(new RouteEntry("192.168.0.3","255.255.255.255",2));
692 routerNextHopIps.add(new RouteEntry("10.0.1.0","255.255.255.0",1));
693 routerNextHopIps.add(new RouteEntry("10.0.2.0","255.255.255.0",1));
694 routerNextHopIps.add(new RouteEntry("10.0.3.0","255.255.255.0",1));
695 routerNextHopIps.add(new RouteEntry("7.7.7.0","255.255.255.0",2));*/
696 //}
697 if (getId() == 0x3) {
698 routerNextHopIps
699 .add(new RouteEntry("192.168.0.2", "255.255.255.255", 2, 102));
700 routerNextHopIps
701 .add(new RouteEntry("192.168.0.1", "255.255.255.255", 2, 101));
702 routerNextHopIps.add(new RouteEntry("10.0.1.0", "255.255.255.0", 2, 101));
703 routerNextHopIps.add(new RouteEntry("10.0.2.0", "255.255.255.0", 2, 101));
704 routerNextHopIps.add(new RouteEntry("10.0.3.0", "255.255.255.0", 2, 101));
705 }
706 return routerNextHopIps;
707 }
708
709 // known host mac-addr, setDA/send out of l3group
710 private List<RouteEntry> getHostNextHopIps() {
711 List<RouteEntry> hostNextHopIps = new ArrayList<RouteEntry>();
712 if (getId() == 0x1) {
713 hostNextHopIps.add(new RouteEntry("10.0.2.1", 4, "00:00:00:00:02:01"));
714 hostNextHopIps.add(new RouteEntry("10.0.3.1", 5, "00:00:00:00:03:01"));
715 }
tom7ef8ff92014-09-17 13:08:06 -0700716 if (getId() == 0x3) {
717 hostNextHopIps.add(new RouteEntry("7.7.7.7", 1, "00:00:07:07:07:07"));
718 }
719 return hostNextHopIps;
720 }
721
722 private void populateIpTable() throws IOException {
723 populateMyIps();
724 populateMySubnets();
725 populateRoutes();
726 populateHostRoutes();
727
728 // match for everything else to send to ACL table. Essentially
729 // the table miss flow entry
730 populateTableMissEntry(TABLE_IPV4_UNICAST, false, true,
731 true, TABLE_ACL);
732 }
733
734 private void populateMyIps() throws IOException {
735 List<OFMessage> msglist = new ArrayList<OFMessage>();
736 // first all my ip's as exact-matches
737 // write-action instruction to send to controller
738 List<String> myIps = getMyIps();
739 for (int i = 0; i < myIps.size(); i++) {
740 OFOxmEthType ethTypeIp = factory.oxms()
741 .ethType(EthType.IPv4);
742 OFOxmIpv4DstMasked ipPrefix = factory.oxms()
743 .ipv4DstMasked(IPv4Address.of(myIps.get(i)), IPv4Address.NO_MASK);
744 OFOxmList oxmListSlash32 = OFOxmList.of(ethTypeIp, ipPrefix);
745 OFMatchV3 match = factory.buildMatchV3()
746 .setOxmList(oxmListSlash32).build();
747 OFAction outc = factory.actions().buildOutput()
748 .setPort(OFPort.CONTROLLER).setMaxLen(OFPCML_NO_BUFFER)
749 .build();
750 OFInstruction writeInstr = factory.instructions().buildWriteActions()
751 .setActions(Collections.singletonList(outc)).build();
752 OFInstruction gotoInstr = factory.instructions().buildGotoTable()
753 .setTableId(TableId.of(TABLE_ACL)).build();
754 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
755 instructions.add(writeInstr);
756 instructions.add(gotoInstr);
757 OFMessage myIpEntry = factory.buildFlowAdd()
758 .setTableId(TableId.of(TABLE_IPV4_UNICAST))
759 .setMatch(match)
760 .setInstructions(instructions)
761 .setPriority(MAX_PRIORITY) // highest priority for exact
762 // match
763 .setBufferId(OFBufferId.NO_BUFFER)
764 .setIdleTimeout(0)
765 .setHardTimeout(0)
766 .setXid(getNextTransactionId())
767 .build();
alshabiba2df7b2a2015-05-06 13:57:10 -0700768 sendHandshakeMessage(myIpEntry);
769
tom7ef8ff92014-09-17 13:08:06 -0700770 }
alshabiba2df7b2a2015-05-06 13:57:10 -0700771 log.debug("Added {} my-ip-rules in sw {}", getStringId());
tom7ef8ff92014-09-17 13:08:06 -0700772 }
773
774 private void populateMySubnets() throws IOException {
775 List<OFMessage> msglist = new ArrayList<OFMessage>();
776 // next prefix-based subnet-IP's configured on my interfaces
777 // need to ARP for exact-IP, so write-action instruction to send to
778 // controller
779 // this has different mask and priority than earlier case
780 List<String> subnetIps = getMySubnetIps();
781 for (int i = 0; i < subnetIps.size(); i++) {
782 OFOxmEthType ethTypeIp = factory.oxms()
783 .ethType(EthType.IPv4);
784 OFOxmIpv4DstMasked ipPrefix = factory.oxms().ipv4DstMasked(
785 IPv4Address.of(subnetIps.get(i)),
786 IPv4Address.of(0xffffff00)); // '/24' mask
787 OFOxmList oxmListSlash24 = OFOxmList.of(ethTypeIp, ipPrefix);
788 OFMatchV3 match = factory.buildMatchV3()
789 .setOxmList(oxmListSlash24).build();
790 OFAction outc = factory.actions().buildOutput()
791 .setPort(OFPort.CONTROLLER).setMaxLen(OFPCML_NO_BUFFER)
792 .build();
793 OFInstruction writeInstr = factory.instructions().buildWriteActions()
794 .setActions(Collections.singletonList(outc)).build();
795 OFInstruction gotoInstr = factory.instructions().buildGotoTable()
796 .setTableId(TableId.of(TABLE_ACL)).build();
797 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
798 instructions.add(writeInstr);
799 instructions.add(gotoInstr);
800 OFMessage myIpEntry = factory.buildFlowAdd()
801 .setTableId(TableId.of(TABLE_IPV4_UNICAST))
802 .setMatch(match)
803 .setInstructions(instructions)
804 .setPriority(SLASH_24_PRIORITY)
805 .setBufferId(OFBufferId.NO_BUFFER)
806 .setIdleTimeout(0)
807 .setHardTimeout(0)
808 .setXid(getNextTransactionId())
809 .build();
alshabiba2df7b2a2015-05-06 13:57:10 -0700810 sendHandshakeMessage(myIpEntry);
811
tom7ef8ff92014-09-17 13:08:06 -0700812 }
alshabiba2df7b2a2015-05-06 13:57:10 -0700813 log.debug("Added subnet-ip-rules in sw {}", getStringId());
tom7ef8ff92014-09-17 13:08:06 -0700814 }
815
816 private void populateRoutes() throws IOException {
817 List<OFMessage> msglist = new ArrayList<OFMessage>();
818 // addresses where I know the next-hop's mac-address because it is a
819 // router port - so I have an L3 interface to it (and an MPLS interface)
820 List<RouteEntry> routerNextHopIps = getRouterNextHopIps();
821 for (int i = 0; i < routerNextHopIps.size(); i++) {
822 OFOxmEthType ethTypeIp = factory.oxms()
823 .ethType(EthType.IPv4);
824 OFOxmIpv4DstMasked ipPrefix = factory.oxms()
825 .ipv4DstMasked(
826 IPv4Address.of(routerNextHopIps.get(i).prefix),
827 IPv4Address.of(routerNextHopIps.get(i).mask)
828 );
829 OFOxmList oxmListSlash32 = OFOxmList.of(ethTypeIp, ipPrefix);
830 OFMatchV3 match = factory.buildMatchV3()
831 .setOxmList(oxmListSlash32).build();
832 OFAction outg = factory.actions().buildGroup()
833 .setGroup(OFGroup.of(0xa0000000 | // mpls group id
834 routerNextHopIps.get(i).nextHopPort))
835 .build();
836 // lots of actions before forwarding to mpls group, and
837 // unfortunately
838 // they need to be apply-actions
839
840 OFAction pushlabel = factory.actions().pushMpls(EthType.MPLS_UNICAST);
841 OFOxmMplsLabel l = factory.oxms()
842 .mplsLabel(U32.of(routerNextHopIps.get(i).label));
843 OFAction setlabelid = factory.actions().buildSetField()
844 .setField(l).build();
845 OFAction copyTtlOut = factory.actions().copyTtlOut();
846 // OFAction setBos =
847 // factory.actions().buildSetField().setField(bos).build();
848
849 /*
850 writeActions.add(pushlabel); // need to be apply actions so can be
851 writeActions.add(copyTtlOut); // matched in pseudo-table
852 //writeActions.add(setlabelid); // bad support in cpqd
853 //writeActions.add(setBos); no support in loxigen
854 */
855
856 List<OFAction> applyActions = new ArrayList<OFAction>();
857 applyActions.add(pushlabel);
858 applyActions.add(copyTtlOut);
859 OFInstruction applyInstr = factory.instructions().buildApplyActions()
860 .setActions(applyActions).build();
861 List<OFAction> writeActions = new ArrayList<OFAction>();
862 writeActions.add(outg); // group will decr mpls-ttl, set mac-sa/da,
863 // vlan
864 OFInstruction writeInstr = factory.instructions().buildWriteActions()
865 .setActions(writeActions).build();
866
867 // necessary to match in pseudo-table to overcome cpqd 1.3 flaw
868 OFInstruction writeMeta = factory.instructions().buildWriteMetadata()
869 .setMetadata(U64.of(routerNextHopIps.get(i).label))
870 .setMetadataMask(METADATA_MASK).build();
871 /*OFInstruction gotoInstr = factory.instructions().buildGotoTable()
872 .setTableId(TableId.of(TABLE_ACL)).build();*/
873 OFInstruction gotoInstr = factory.instructions().buildGotoTable()
874 .setTableId(TableId.of(TABLE_META)).build();
875 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
876 instructions.add(applyInstr);
877 // instructions.add(writeInstr);// cannot write here - causes switch
878 // to crash
879 instructions.add(writeMeta);
880 instructions.add(gotoInstr);
881
882 int priority = -1;
883 if (routerNextHopIps.get(i).mask.equals("255.255.255.255")) {
884 priority = MAX_PRIORITY;
885 } else {
886 priority = SLASH_24_PRIORITY;
887 }
888 OFMessage myIpEntry = factory.buildFlowAdd()
889 .setTableId(TableId.of(TABLE_IPV4_UNICAST))
890 .setMatch(match)
891 .setInstructions(instructions)
892 .setPriority(priority)
893 .setBufferId(OFBufferId.NO_BUFFER)
894 .setIdleTimeout(0)
895 .setHardTimeout(0)
896 .setXid(getNextTransactionId())
897 .build();
898 msglist.add(myIpEntry);
899
900 // need to also handle psuedo-table entries to match-metadata and
901 // set mpls
902 // label-id
903 OFOxmEthType ethTypeMpls = factory.oxms()
904 .ethType(EthType.MPLS_UNICAST);
905 OFOxmMetadataMasked meta = factory.oxms()
906 .metadataMasked(
907 OFMetadata.ofRaw(routerNextHopIps.get(i).label),
908 OFMetadata.NO_MASK);
909 OFOxmList oxmListMeta = OFOxmList.of(ethTypeMpls, meta);
910 OFMatchV3 matchMeta = factory.buildMatchV3()
911 .setOxmList(oxmListMeta).build();
912 List<OFAction> writeActions2 = new ArrayList<OFAction>();
913 writeActions2.add(setlabelid);
914 OFAction outg2 = factory.actions().buildGroup()
915 .setGroup(OFGroup.of(routerNextHopIps.get(i).nextHopPort |
916 (192 << VLAN_ID_OFFSET)))
917 .build();
918 writeActions2.add(outg2);
919 OFInstruction writeInstr2 = factory.instructions().buildWriteActions()
920 .setActions(writeActions2).build();
921 OFInstruction gotoInstr2 = factory.instructions().buildGotoTable()
922 .setTableId(TableId.of(TABLE_ACL)).build();
923 List<OFInstruction> instructions2 = new ArrayList<OFInstruction>();
924 // unfortunately have to apply this action too
925 OFInstruction applyInstr2 = factory.instructions().buildApplyActions()
926 .setActions(writeActions2).build();
927 instructions2.add(applyInstr2);
928 // instructions2.add(writeInstr2);
929 // instructions2.add(gotoInstr2);
930
931 /*OFMatchV3 match3 = factory.buildMatchV3()
932 .setOxmList(OFOxmList.of(meta)).build();
933 OFInstruction clearInstruction = factory.instructions().clearActions();
934 List<OFInstruction> instructions3 = new ArrayList<OFInstruction>();
935 OFAction outc = factory.actions().buildOutput()
936 .setPort(OFPort.CONTROLLER).setMaxLen(OFPCML_NO_BUFFER)
937 .build();
938 OFInstruction writec = factory.instructions()
939 .writeActions(Collections.singletonList(outc));
940 instructions3.add(clearInstruction);
941 instructions3.add(writec);
942 instructions3.add(gotoInstr2); */
943 OFMessage myMetaEntry = factory.buildFlowAdd()
944 .setTableId(TableId.of(TABLE_META))
945 .setMatch(matchMeta)
946 .setInstructions(instructions2)
947 .setPriority(MAX_PRIORITY)
948 .setBufferId(OFBufferId.NO_BUFFER)
949 .setIdleTimeout(0)
950 .setHardTimeout(0)
951 .setXid(getNextTransactionId())
952 .build();
alshabiba2df7b2a2015-05-06 13:57:10 -0700953 sendHandshakeMessage(myMetaEntry);
tom7ef8ff92014-09-17 13:08:06 -0700954 msglist.add(myMetaEntry);
955
956 }
tom7ef8ff92014-09-17 13:08:06 -0700957 log.debug("Adding {} next-hop-router-rules in sw {}", msglist.size(),
958 getStringId());
959
960 // add a table-miss entry to table 4 for debugging - leave it out
961 // unclear packet state - causes switch to crash
962 // populateTableMissEntry(TABLE_META, false, true,
963 // true, TABLE_ACL);
964 }
965
966 private void populateHostRoutes() throws IOException {
967 List<OFMessage> msglist = new ArrayList<OFMessage>();
968 // addresses where I know the next hop's mac-address and I can set the
969 // destination mac in the match-instruction.write-action
970 // either I sent out arp-request or I got an arp-request from this host
971 List<RouteEntry> hostNextHopIps = getHostNextHopIps();
972 for (int i = 0; i < hostNextHopIps.size(); i++) {
973 OFOxmEthType ethTypeIp = factory.oxms()
974 .ethType(EthType.IPv4);
975 OFOxmIpv4DstMasked ipPrefix = factory.oxms()
976 .ipv4DstMasked(
977 IPv4Address.of(hostNextHopIps.get(i).prefix),
978 IPv4Address.NO_MASK); // host addr should be /32
979 OFOxmList oxmListSlash32 = OFOxmList.of(ethTypeIp, ipPrefix);
980 OFMatchV3 match = factory.buildMatchV3()
981 .setOxmList(oxmListSlash32).build();
982 OFAction setDmac = null, outg = null;
983 OFOxmEthDst dmac = factory.oxms()
984 .ethDst(MacAddress.of(hostNextHopIps.get(i).dstMac));
985 setDmac = factory.actions().buildSetField()
986 .setField(dmac).build();
987 outg = factory.actions().buildGroup()
988 .setGroup(OFGroup.of(0x20000000 | hostNextHopIps.get(i).nextHopPort)) // l3group
989 // id
990 .build();
991 List<OFAction> writeActions = new ArrayList<OFAction>();
992 writeActions.add(setDmac);
993 writeActions.add(outg);
994 OFInstruction writeInstr = factory.instructions().buildWriteActions()
995 .setActions(writeActions).build();
996 OFInstruction gotoInstr = factory.instructions().buildGotoTable()
997 .setTableId(TableId.of(TABLE_ACL)).build();
998 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
999 instructions.add(writeInstr);
1000 instructions.add(gotoInstr);
1001 OFMessage myIpEntry = factory.buildFlowAdd()
1002 .setTableId(TableId.of(TABLE_IPV4_UNICAST))
1003 .setMatch(match)
1004 .setInstructions(instructions)
1005 .setPriority(MAX_PRIORITY) // highest priority for exact
1006 // match
1007 .setBufferId(OFBufferId.NO_BUFFER)
1008 .setIdleTimeout(0)
1009 .setHardTimeout(0)
1010 .setXid(getNextTransactionId())
1011 .build();
alshabiba2df7b2a2015-05-06 13:57:10 -07001012 sendHandshakeMessage(myIpEntry);
tom7ef8ff92014-09-17 13:08:06 -07001013 }
alshabiba2df7b2a2015-05-06 13:57:10 -07001014
tom7ef8ff92014-09-17 13:08:06 -07001015 log.debug("Adding {} next-hop-host-rules in sw {}", msglist.size(), getStringId());
1016 }
1017
1018 private static class MplsEntry {
1019 int labelid;
1020 int portnum;
1021
1022 public MplsEntry(int labelid, int portnum) {
1023 this.labelid = labelid;
1024 this.portnum = portnum;
1025 }
1026 }
1027
1028 private List<MplsEntry> getMplsEntries() {
1029 List<MplsEntry> myLabels = new ArrayList<MplsEntry>();
1030 if (getId() == 0x1) {
1031 myLabels.add(new MplsEntry(101, OFPort.CONTROLLER.getPortNumber()));
1032 myLabels.add(new MplsEntry(103, 6));
1033 }
1034 if (getId() == 0x2) {
1035 myLabels.add(new MplsEntry(103, 2));
1036 myLabels.add(new MplsEntry(102, OFPort.CONTROLLER.getPortNumber()));
1037 myLabels.add(new MplsEntry(101, 1));
1038 }
1039 if (getId() == 0x3) {
1040 myLabels.add(new MplsEntry(103, OFPort.CONTROLLER.getPortNumber()));
1041 myLabels.add(new MplsEntry(101, 2));
1042 }
1043 return myLabels;
1044 }
1045
1046 private void populateMplsTable() throws IOException {
1047 List<OFMessage> msglist = new ArrayList<OFMessage>();
1048 List<MplsEntry> lfibEntries = getMplsEntries();
1049 for (int i = 0; i < lfibEntries.size(); i++) {
1050 OFOxmEthType ethTypeMpls = factory.oxms()
1051 .ethType(EthType.MPLS_UNICAST);
1052 OFOxmMplsLabel labelid = factory.oxms()
1053 .mplsLabel(U32.of(lfibEntries.get(i).labelid));
1054 OFOxmList oxmList = OFOxmList.of(ethTypeMpls, labelid);
1055 OFMatchV3 matchlabel = factory.buildMatchV3()
1056 .setOxmList(oxmList).build();
1057 OFAction poplabel = factory.actions().popMpls(EthType.IPv4);
1058 OFAction sendTo = null;
1059 if (lfibEntries.get(i).portnum == OFPort.CONTROLLER.getPortNumber()) {
1060 sendTo = factory.actions().output(OFPort.CONTROLLER,
1061 OFPCML_NO_BUFFER);
1062 } else {
1063 sendTo = factory.actions().group(OFGroup.of(
1064 0xa0000000 | lfibEntries.get(i).portnum));
1065 }
1066 List<OFAction> writeActions = new ArrayList<OFAction>();
1067 writeActions.add(poplabel);
1068 writeActions.add(sendTo);
1069 OFInstruction writeInstr = factory.instructions().buildWriteActions()
1070 .setActions(writeActions).build();
1071 OFInstruction gotoInstr = factory.instructions().buildGotoTable()
1072 .setTableId(TableId.of(TABLE_ACL)).build();
1073 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
1074 instructions.add(writeInstr);
1075 instructions.add(gotoInstr);
1076 OFMessage myMplsEntry = factory.buildFlowAdd()
1077 .setTableId(TableId.of(TABLE_MPLS))
1078 .setMatch(matchlabel)
1079 .setInstructions(instructions)
1080 .setPriority(MAX_PRIORITY) // exact match and exclusive
1081 .setBufferId(OFBufferId.NO_BUFFER)
1082 .setIdleTimeout(0)
1083 .setHardTimeout(0)
1084 .setXid(getNextTransactionId())
1085 .build();
alshabiba2df7b2a2015-05-06 13:57:10 -07001086 sendHandshakeMessage(myMplsEntry);
tom7ef8ff92014-09-17 13:08:06 -07001087 msglist.add(myMplsEntry);
1088 }
alshabiba2df7b2a2015-05-06 13:57:10 -07001089
tom7ef8ff92014-09-17 13:08:06 -07001090 log.debug("Adding {} mpls-forwarding-rules in sw {}", msglist.size(),
1091 getStringId());
1092
1093 // match for everything else to send to ACL table. Essentially
1094 // the table miss flow entry
1095 populateTableMissEntry(TABLE_MPLS, false, true,
1096 true, TABLE_ACL);
1097
1098 }
1099
1100 /**
1101 * By default if none of the booleans in the call are set, then the
1102 * table-miss entry is added with no instructions, which means that pipeline
1103 * execution will stop, and the action set associated with the packet will
1104 * be executed.
1105 *
1106 * @param tableToAdd
1107 * @param toControllerNow as an APPLY_ACTION instruction
1108 * @param toControllerWrite as a WRITE_ACITION instruction
1109 * @param toTable as a GOTO_TABLE instruction
1110 * @param tableToSend
alshabib452234e2014-11-25 00:03:49 -05001111 * @throws java.io.IOException
tom7ef8ff92014-09-17 13:08:06 -07001112 */
1113 @SuppressWarnings("unchecked")
1114 private void populateTableMissEntry(int tableToAdd, boolean toControllerNow,
1115 boolean toControllerWrite,
1116 boolean toTable, int tableToSend) {
1117 OFOxmList oxmList = OFOxmList.EMPTY;
1118 OFMatchV3 match = factory.buildMatchV3()
1119 .setOxmList(oxmList)
1120 .build();
1121 OFAction outc = factory.actions()
1122 .buildOutput()
1123 .setPort(OFPort.CONTROLLER)
1124 .setMaxLen(OFPCML_NO_BUFFER)
1125 .build();
1126 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
1127 if (toControllerNow) {
1128 // table-miss instruction to send to controller immediately
1129 OFInstruction instr = factory.instructions()
1130 .buildApplyActions()
1131 .setActions(Collections.singletonList(outc))
1132 .build();
1133 instructions.add(instr);
1134 }
1135
1136 if (toControllerWrite) {
1137 // table-miss instruction to write-action to send to controller
1138 // this will be executed whenever the action-set gets executed
1139 OFInstruction instr = factory.instructions()
1140 .buildWriteActions()
1141 .setActions(Collections.singletonList(outc))
1142 .build();
1143 instructions.add(instr);
1144 }
1145
1146 if (toTable) {
1147 // table-miss instruction to goto-table x
1148 OFInstruction instr = factory.instructions()
1149 .gotoTable(TableId.of(tableToSend));
1150 instructions.add(instr);
1151 }
1152
1153 if (!toControllerNow && !toControllerWrite && !toTable) {
1154 // table-miss has no instruction - at which point action-set will be
1155 // executed - if there is an action to output/group in the action
1156 // set
1157 // the packet will be sent there, otherwise it will be dropped.
1158 instructions = Collections.EMPTY_LIST;
1159 }
1160
1161 OFMessage tableMissEntry = factory.buildFlowAdd()
1162 .setTableId(TableId.of(tableToAdd))
1163 .setMatch(match) // match everything
1164 .setInstructions(instructions)
1165 .setPriority(MIN_PRIORITY)
1166 .setBufferId(OFBufferId.NO_BUFFER)
1167 .setIdleTimeout(0)
1168 .setHardTimeout(0)
1169 .setXid(getNextTransactionId())
1170 .build();
Jonathan Hart147b2ac2014-10-23 10:03:52 -07001171
alshabiba2df7b2a2015-05-06 13:57:10 -07001172 sendHandshakeMessage(tableMissEntry);
tom7ef8ff92014-09-17 13:08:06 -07001173 }
1174
1175 private void sendBarrier(boolean finalBarrier) {
1176 int xid = getNextTransactionId();
1177 if (finalBarrier) {
1178 barrierXidToWaitFor = xid;
1179 }
1180 OFBarrierRequest br = factory
1181 .buildBarrierRequest()
1182 .setXid(xid)
1183 .build();
Jonathan Hart147b2ac2014-10-23 10:03:52 -07001184
alshabiba2df7b2a2015-05-06 13:57:10 -07001185 sendHandshakeMessage(br);
tom7ef8ff92014-09-17 13:08:06 -07001186 }
1187
1188 @Override
1189 public Boolean supportNxRole() {
1190 return false;
1191 }
tom7ef8ff92014-09-17 13:08:06 -07001192}