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
Showing
3 changed files
with
140 additions
and
37 deletions
| ... | @@ -596,29 +596,35 @@ public class SegmentRoutingManager implements SegmentRoutingService { | ... | @@ -596,29 +596,35 @@ 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. |
| 605 | - DefaultGroupHandler groupHandler = DefaultGroupHandler. | 610 | + if (groupHandlerMap.get(device.id()) == null) { |
| 606 | - createGroupHandler(device.id(), | 611 | + DefaultGroupHandler groupHandler = DefaultGroupHandler. |
| 607 | - appId, | 612 | + createGroupHandler(device.id(), |
| 608 | - deviceConfiguration, | 613 | + appId, |
| 609 | - linkService, | 614 | + deviceConfiguration, |
| 610 | - flowObjectiveService, | 615 | + linkService, |
| 611 | - nsNextObjStore, | 616 | + flowObjectiveService, |
| 612 | - subnetNextObjStore); | 617 | + nsNextObjStore, |
| 613 | - groupHandlerMap.put(device.id(), groupHandler); | 618 | + subnetNextObjStore); |
| 614 | - | 619 | + groupHandlerMap.put(device.id(), groupHandler); |
| 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,21 +666,23 @@ public class SegmentRoutingManager implements SegmentRoutingService { | ... | @@ -660,21 +666,23 @@ 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. |
| 663 | - DefaultGroupHandler groupHandler = DefaultGroupHandler | 669 | + if (groupHandlerMap.get(device.id()) == null) { |
| 664 | - .createGroupHandler(device.id(), appId, | 670 | + DefaultGroupHandler groupHandler = DefaultGroupHandler |
| 665 | - deviceConfiguration, linkService, | 671 | + .createGroupHandler(device.id(), appId, |
| 666 | - flowObjectiveService, | 672 | + deviceConfiguration, linkService, |
| 667 | - nsNextObjStore, | 673 | + flowObjectiveService, |
| 668 | - subnetNextObjStore); | 674 | + nsNextObjStore, |
| 669 | - groupHandlerMap.put(device.id(), groupHandler); | 675 | + subnetNextObjStore); |
| 670 | - | 676 | + groupHandlerMap.put(device.id(), groupHandler); |
| 671 | - // Also, in some cases, drivers may need extra | 677 | + |
| 672 | - // information to process rules (eg. Router IP/MAC); and so, we send | 678 | + // Also, in some cases, drivers may need extra |
| 673 | - // port addressing rules to the driver as well, irrespective of whether | 679 | + // information to process rules (eg. Router IP/MAC); and so, we send |
| 674 | - // this instance is the master or not. | 680 | + // port addressing rules to the driver as well, irrespective of whether |
| 675 | - defaultRoutingHandler.populatePortAddressingRules(device.id()); | 681 | + // this instance is the master or not. |
| 676 | - | 682 | + defaultRoutingHandler.populatePortAddressingRules(device.id()); |
| 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 | ... | ... |
-
Please register or login to post a comment