Saurav Das
Committed by Gerrit Code Review

CORD-48 Added to support for OFDPA emulation with CPQD switch, via more table-miss-entries.

Fixed a race condition where device processing starts before config has fully loaded.
GroupHandler in SR app is now created only once, not every time a Device update happens.

Change-Id: I945c47ee9caa2f5740296f49d5d223783271bba4
...@@ -596,12 +596,18 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -596,12 +596,18 @@ public class SegmentRoutingManager implements SegmentRoutingService {
596 596
597 private void processDeviceAdded(Device device) { 597 private void processDeviceAdded(Device device) {
598 log.debug("A new device with ID {} was added", device.id()); 598 log.debug("A new device with ID {} was added", device.id());
599 + if (deviceConfiguration == null) {
600 + log.warn("Device configuration uploading. Device {} will be "
601 + + "processed after config completes.", device.id());
602 + return;
603 + }
599 // Irrespective of whether the local is a MASTER or not for this device, 604 // Irrespective of whether the local is a MASTER or not for this device,
600 // we need to create a SR-group-handler instance. This is because in a 605 // we need to create a SR-group-handler instance. This is because in a
601 // multi-instance setup, any instance can initiate forwarding/next-objectives 606 // multi-instance setup, any instance can initiate forwarding/next-objectives
602 // for any switch (even if this instance is a SLAVE or not even connected 607 // for any switch (even if this instance is a SLAVE or not even connected
603 // to the switch). To handle this, a default-group-handler instance is necessary 608 // to the switch). To handle this, a default-group-handler instance is necessary
604 // per switch. 609 // per switch.
610 + if (groupHandlerMap.get(device.id()) == null) {
605 DefaultGroupHandler groupHandler = DefaultGroupHandler. 611 DefaultGroupHandler groupHandler = DefaultGroupHandler.
606 createGroupHandler(device.id(), 612 createGroupHandler(device.id(),
607 appId, 613 appId,
...@@ -611,14 +617,14 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -611,14 +617,14 @@ public class SegmentRoutingManager implements SegmentRoutingService {
611 nsNextObjStore, 617 nsNextObjStore,
612 subnetNextObjStore); 618 subnetNextObjStore);
613 groupHandlerMap.put(device.id(), groupHandler); 619 groupHandlerMap.put(device.id(), groupHandler);
614 -
615 // Also, in some cases, drivers may need extra 620 // Also, in some cases, drivers may need extra
616 // information to process rules (eg. Router IP/MAC); and so, we send 621 // information to process rules (eg. Router IP/MAC); and so, we send
617 // port addressing rules to the driver as well irrespective of whether 622 // port addressing rules to the driver as well irrespective of whether
618 // this instance is the master or not. 623 // this instance is the master or not.
619 defaultRoutingHandler.populatePortAddressingRules(device.id()); 624 defaultRoutingHandler.populatePortAddressingRules(device.id());
620 - 625 + }
621 if (mastershipService.isLocalMaster(device.id())) { 626 if (mastershipService.isLocalMaster(device.id())) {
627 + DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
622 groupHandler.createGroupsFromSubnetConfig(); 628 groupHandler.createGroupsFromSubnetConfig();
623 } 629 }
624 } 630 }
...@@ -660,6 +666,7 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -660,6 +666,7 @@ public class SegmentRoutingManager implements SegmentRoutingService {
660 // for any switch (even if this instance is a SLAVE or not even connected 666 // for any switch (even if this instance is a SLAVE or not even connected
661 // to the switch). To handle this, a default-group-handler instance is necessary 667 // to the switch). To handle this, a default-group-handler instance is necessary
662 // per switch. 668 // per switch.
669 + if (groupHandlerMap.get(device.id()) == null) {
663 DefaultGroupHandler groupHandler = DefaultGroupHandler 670 DefaultGroupHandler groupHandler = DefaultGroupHandler
664 .createGroupHandler(device.id(), appId, 671 .createGroupHandler(device.id(), appId,
665 deviceConfiguration, linkService, 672 deviceConfiguration, linkService,
...@@ -673,8 +680,9 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -673,8 +680,9 @@ public class SegmentRoutingManager implements SegmentRoutingService {
673 // port addressing rules to the driver as well, irrespective of whether 680 // port addressing rules to the driver as well, irrespective of whether
674 // this instance is the master or not. 681 // this instance is the master or not.
675 defaultRoutingHandler.populatePortAddressingRules(device.id()); 682 defaultRoutingHandler.populatePortAddressingRules(device.id());
676 - 683 + }
677 if (mastershipService.isLocalMaster(device.id())) { 684 if (mastershipService.isLocalMaster(device.id())) {
685 + DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
678 groupHandler.createGroupsFromSubnetConfig(); 686 groupHandler.createGroupsFromSubnetConfig();
679 } 687 }
680 } 688 }
......
...@@ -17,6 +17,13 @@ package org.onosproject.driver.pipeline; ...@@ -17,6 +17,13 @@ package org.onosproject.driver.pipeline;
17 17
18 import static org.slf4j.LoggerFactory.getLogger; 18 import static org.slf4j.LoggerFactory.getLogger;
19 19
20 +import java.util.ArrayList;
21 +import java.util.List;
22 +
23 +import org.onlab.packet.VlanId;
24 +import org.onosproject.core.ApplicationId;
25 +import org.onosproject.net.Port;
26 +import org.onosproject.net.PortNumber;
20 import org.onosproject.net.flow.DefaultFlowRule; 27 import org.onosproject.net.flow.DefaultFlowRule;
21 import org.onosproject.net.flow.DefaultTrafficSelector; 28 import org.onosproject.net.flow.DefaultTrafficSelector;
22 import org.onosproject.net.flow.DefaultTrafficTreatment; 29 import org.onosproject.net.flow.DefaultTrafficTreatment;
...@@ -25,6 +32,8 @@ import org.onosproject.net.flow.FlowRuleOperations; ...@@ -25,6 +32,8 @@ import org.onosproject.net.flow.FlowRuleOperations;
25 import org.onosproject.net.flow.FlowRuleOperationsContext; 32 import org.onosproject.net.flow.FlowRuleOperationsContext;
26 import org.onosproject.net.flow.TrafficSelector; 33 import org.onosproject.net.flow.TrafficSelector;
27 import org.onosproject.net.flow.TrafficTreatment; 34 import org.onosproject.net.flow.TrafficTreatment;
35 +import org.onosproject.net.flow.criteria.PortCriterion;
36 +import org.onosproject.net.flow.criteria.VlanIdCriterion;
28 import org.slf4j.Logger; 37 import org.slf4j.Logger;
29 38
30 39
...@@ -37,16 +46,58 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline { ...@@ -37,16 +46,58 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline {
37 private final Logger log = getLogger(getClass()); 46 private final Logger log = getLogger(getClass());
38 47
39 @Override 48 @Override
49 + protected List<FlowRule> processVlanIdFilter(PortCriterion portCriterion,
50 + VlanIdCriterion vidCriterion,
51 + VlanId assignedVlan,
52 + ApplicationId applicationId) {
53 + List<FlowRule> rules = new ArrayList<FlowRule>();
54 + TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
55 + TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
56 + selector.matchVlanId(vidCriterion.vlanId());
57 + if (vidCriterion.vlanId() == VlanId.NONE) {
58 + // untagged packets are assigned vlans
59 + treatment.pushVlan().setVlanId(assignedVlan);
60 + }
61 + treatment.transition(TMAC_TABLE);
62 +
63 + // ofdpa cannot match on ALL portnumber, so we need to use separate
64 + // rules for each port.
65 + List<PortNumber> portnums = new ArrayList<PortNumber>();
66 + if (portCriterion.port() == PortNumber.ALL) {
67 + for (Port port : deviceService.getPorts(deviceId)) {
68 + if (port.number().toLong() > 0 && port.number().toLong() < OFPP_MAX) {
69 + portnums.add(port.number());
70 + }
71 + }
72 + } else {
73 + portnums.add(portCriterion.port());
74 + }
75 + for (PortNumber pnum : portnums) {
76 + selector.matchInPort(pnum);
77 + FlowRule rule = DefaultFlowRule.builder()
78 + .forDevice(deviceId)
79 + .withSelector(selector.build())
80 + .withTreatment(treatment.build())
81 + .withPriority(DEFAULT_PRIORITY)
82 + .fromApp(applicationId)
83 + .makePermanent()
84 + .forTable(VLAN_TABLE).build();
85 + rules.add(rule);
86 + }
87 + return rules;
88 + }
89 +
90 +
91 + @Override
40 protected void initializePipeline() { 92 protected void initializePipeline() {
41 processPortTable(); 93 processPortTable();
94 + // vlan table processing not required, as default is to drop packets
95 + // which can be accomplished without a table-miss-entry.
42 processTmacTable(); 96 processTmacTable();
43 processIpTable(); 97 processIpTable();
98 + processMplsTable();
44 processBridgingTable(); 99 processBridgingTable();
45 processAclTable(); 100 processAclTable();
46 - // XXX implement table miss entries and default groups
47 - //processVlanTable();
48 - //processMPLSTable();
49 - //processGroupTable();
50 } 101 }
51 102
52 @Override 103 @Override
...@@ -140,6 +191,49 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline { ...@@ -140,6 +191,49 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline {
140 })); 191 }));
141 } 192 }
142 193
194 + @Override
195 + protected void processMplsTable() {
196 + //table miss entry
197 + FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
198 + TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
199 + TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
200 + selector = DefaultTrafficSelector.builder();
201 + treatment = DefaultTrafficTreatment.builder();
202 + treatment.transition(MPLS_TABLE_1);
203 + FlowRule rule = DefaultFlowRule.builder()
204 + .forDevice(deviceId)
205 + .withSelector(selector.build())
206 + .withTreatment(treatment.build())
207 + .withPriority(LOWEST_PRIORITY)
208 + .fromApp(driverId)
209 + .makePermanent()
210 + .forTable(MPLS_TABLE_0).build();
211 + ops = ops.add(rule);
212 +
213 + treatment.transition(ACL_TABLE);
214 + rule = DefaultFlowRule.builder()
215 + .forDevice(deviceId)
216 + .withSelector(selector.build())
217 + .withTreatment(treatment.build())
218 + .withPriority(LOWEST_PRIORITY)
219 + .fromApp(driverId)
220 + .makePermanent()
221 + .forTable(MPLS_TABLE_1).build();
222 + ops = ops.add(rule);
223 +
224 + flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
225 + @Override
226 + public void onSuccess(FlowRuleOperations ops) {
227 + log.info("Initialized MPLS tables");
228 + }
229 +
230 + @Override
231 + public void onError(FlowRuleOperations ops) {
232 + log.info("Failed to initialize MPLS tables");
233 + }
234 + }));
235 + }
236 +
143 private void processBridgingTable() { 237 private void processBridgingTable() {
144 //table miss entry 238 //table miss entry
145 FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); 239 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
......
...@@ -122,7 +122,7 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline ...@@ -122,7 +122,7 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
122 protected static final long OFPP_MAX = 0xffffff00L; 122 protected static final long OFPP_MAX = 0xffffff00L;
123 123
124 private static final int HIGHEST_PRIORITY = 0xffff; 124 private static final int HIGHEST_PRIORITY = 0xffff;
125 - private static final int DEFAULT_PRIORITY = 0x8000; 125 + protected static final int DEFAULT_PRIORITY = 0x8000;
126 protected static final int LOWEST_PRIORITY = 0x0; 126 protected static final int LOWEST_PRIORITY = 0x0;
127 127
128 /* 128 /*
...@@ -458,8 +458,9 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline ...@@ -458,8 +458,9 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
458 if (vidCriterion.vlanId() == VlanId.NONE) { 458 if (vidCriterion.vlanId() == VlanId.NONE) {
459 // untagged packets are assigned vlans 459 // untagged packets are assigned vlans
460 treatment.pushVlan().setVlanId(assignedVlan); 460 treatment.pushVlan().setVlanId(assignedVlan);
461 - // XXX ofdpa may require an additional vlan match on the assigned vlan 461 + // XXX ofdpa will require an additional vlan match on the assigned vlan
462 - // and it may not require the push. 462 + // and it may not require the push. This is not in compliance with OF
463 + // standard. Waiting on what the exact flows are going to look like.
463 } 464 }
464 treatment.transition(TMAC_TABLE); 465 treatment.transition(TMAC_TABLE);
465 466
......