Committed by
Gerrit Code Review
Segment Routing refactor with flow objectives
Change-Id: I0b87f89bb8b18522b9d38bdf5e96f55485b6f1e3
Showing
22 changed files
with
1580 additions
and
534 deletions
| ... | @@ -24,7 +24,6 @@ import org.onosproject.net.Device; | ... | @@ -24,7 +24,6 @@ import org.onosproject.net.Device; |
| 24 | import org.onosproject.net.DeviceId; | 24 | import org.onosproject.net.DeviceId; |
| 25 | import org.onosproject.net.Link; | 25 | import org.onosproject.net.Link; |
| 26 | import org.onosproject.net.MastershipRole; | 26 | import org.onosproject.net.MastershipRole; |
| 27 | -import org.onosproject.net.flow.FlowRule; | ||
| 28 | import org.slf4j.Logger; | 27 | import org.slf4j.Logger; |
| 29 | import org.slf4j.LoggerFactory; | 28 | import org.slf4j.LoggerFactory; |
| 30 | 29 | ||
| ... | @@ -38,7 +37,8 @@ import static com.google.common.base.Preconditions.checkNotNull; | ... | @@ -38,7 +37,8 @@ import static com.google.common.base.Preconditions.checkNotNull; |
| 38 | 37 | ||
| 39 | public class DefaultRoutingHandler { | 38 | public class DefaultRoutingHandler { |
| 40 | 39 | ||
| 41 | - private static Logger log = LoggerFactory.getLogger(DefaultRoutingHandler.class); | 40 | + private static Logger log = LoggerFactory |
| 41 | + .getLogger(DefaultRoutingHandler.class); | ||
| 42 | 42 | ||
| 43 | private SegmentRoutingManager srManager; | 43 | private SegmentRoutingManager srManager; |
| 44 | private RoutingRulePopulator rulePopulator; | 44 | private RoutingRulePopulator rulePopulator; |
| ... | @@ -56,7 +56,8 @@ public class DefaultRoutingHandler { | ... | @@ -56,7 +56,8 @@ public class DefaultRoutingHandler { |
| 56 | // population process started. | 56 | // population process started. |
| 57 | STARTED, | 57 | STARTED, |
| 58 | 58 | ||
| 59 | - // population process was aborted due to errors, mostly for groups not found. | 59 | + // population process was aborted due to errors, mostly for groups not |
| 60 | + // found. | ||
| 60 | ABORTED, | 61 | ABORTED, |
| 61 | 62 | ||
| 62 | // population process was finished successfully. | 63 | // population process was finished successfully. |
| ... | @@ -89,8 +90,7 @@ public class DefaultRoutingHandler { | ... | @@ -89,8 +90,7 @@ public class DefaultRoutingHandler { |
| 89 | log.info("Starts to populate routing rules"); | 90 | log.info("Starts to populate routing rules"); |
| 90 | 91 | ||
| 91 | for (Device sw : srManager.deviceService.getDevices()) { | 92 | for (Device sw : srManager.deviceService.getDevices()) { |
| 92 | - if (srManager.mastershipService. | 93 | + if (srManager.mastershipService.getLocalRole(sw.id()) != MastershipRole.MASTER) { |
| 93 | - getLocalRole(sw.id()) != MastershipRole.MASTER) { | ||
| 94 | continue; | 94 | continue; |
| 95 | } | 95 | } |
| 96 | 96 | ||
| ... | @@ -323,11 +323,11 @@ public class DefaultRoutingHandler { | ... | @@ -323,11 +323,11 @@ public class DefaultRoutingHandler { |
| 323 | private boolean populateEcmpRoutingRules(DeviceId destSw, | 323 | private boolean populateEcmpRoutingRules(DeviceId destSw, |
| 324 | ECMPShortestPathGraph ecmpSPG) { | 324 | ECMPShortestPathGraph ecmpSPG) { |
| 325 | 325 | ||
| 326 | - HashMap<Integer, HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>>> switchVia = | 326 | + HashMap<Integer, HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>>> switchVia = ecmpSPG |
| 327 | - ecmpSPG.getAllLearnedSwitchesAndVia(); | 327 | + .getAllLearnedSwitchesAndVia(); |
| 328 | for (Integer itrIdx : switchVia.keySet()) { | 328 | for (Integer itrIdx : switchVia.keySet()) { |
| 329 | - HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>> swViaMap = | 329 | + HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>> swViaMap = switchVia |
| 330 | - switchVia.get(itrIdx); | 330 | + .get(itrIdx); |
| 331 | for (DeviceId targetSw : swViaMap.keySet()) { | 331 | for (DeviceId targetSw : swViaMap.keySet()) { |
| 332 | Set<DeviceId> nextHops = new HashSet<>(); | 332 | Set<DeviceId> nextHops = new HashSet<>(); |
| 333 | 333 | ||
| ... | @@ -347,15 +347,17 @@ public class DefaultRoutingHandler { | ... | @@ -347,15 +347,17 @@ public class DefaultRoutingHandler { |
| 347 | return true; | 347 | return true; |
| 348 | } | 348 | } |
| 349 | 349 | ||
| 350 | - private boolean populateEcmpRoutingRulePartial(DeviceId targetSw, DeviceId destSw, | 350 | + private boolean populateEcmpRoutingRulePartial(DeviceId targetSw, |
| 351 | - Set<DeviceId> nextHops) { | 351 | + DeviceId destSw, |
| 352 | + Set<DeviceId> nextHops) { | ||
| 352 | boolean result; | 353 | boolean result; |
| 353 | 354 | ||
| 354 | if (nextHops.isEmpty()) { | 355 | if (nextHops.isEmpty()) { |
| 355 | nextHops.add(destSw); | 356 | nextHops.add(destSw); |
| 356 | } | 357 | } |
| 357 | 358 | ||
| 358 | - // If both target switch and dest switch are edge routers, then set IP rule | 359 | + // If both target switch and dest switch are edge routers, then set IP |
| 360 | + // rule | ||
| 359 | // for both subnet and router IP. | 361 | // for both subnet and router IP. |
| 360 | if (config.isEdgeDevice(targetSw) && config.isEdgeDevice(destSw)) { | 362 | if (config.isEdgeDevice(targetSw) && config.isEdgeDevice(destSw)) { |
| 361 | List<Ip4Prefix> subnets = config.getSubnets(destSw); | 363 | List<Ip4Prefix> subnets = config.getSubnets(destSw); |
| ... | @@ -374,7 +376,7 @@ public class DefaultRoutingHandler { | ... | @@ -374,7 +376,7 @@ public class DefaultRoutingHandler { |
| 374 | return false; | 376 | return false; |
| 375 | } | 377 | } |
| 376 | 378 | ||
| 377 | - // If the target switch is an edge router, then set IP rules for the router IP. | 379 | + // TODO: If the target switch is an edge router, then set IP rules for the router IP. |
| 378 | } else if (config.isEdgeDevice(targetSw)) { | 380 | } else if (config.isEdgeDevice(targetSw)) { |
| 379 | Ip4Address routerIp = config.getRouterIp(destSw); | 381 | Ip4Address routerIp = config.getRouterIp(destSw); |
| 380 | IpPrefix routerIpPrefix = IpPrefix.valueOf(routerIp, IpPrefix.MAX_INET_MASK_LENGTH); | 382 | IpPrefix routerIpPrefix = IpPrefix.valueOf(routerIp, IpPrefix.MAX_INET_MASK_LENGTH); |
| ... | @@ -383,7 +385,7 @@ public class DefaultRoutingHandler { | ... | @@ -383,7 +385,7 @@ public class DefaultRoutingHandler { |
| 383 | return false; | 385 | return false; |
| 384 | } | 386 | } |
| 385 | 387 | ||
| 386 | - // If the target switch is an transit router, then set MPLS rules only. | 388 | + // TODO: If the target switch is an transit router, then set MPLS rules only. |
| 387 | } else if (!config.isEdgeDevice(targetSw)) { | 389 | } else if (!config.isEdgeDevice(targetSw)) { |
| 388 | result = rulePopulator.populateMplsRule(targetSw, destSw, nextHops); | 390 | result = rulePopulator.populateMplsRule(targetSw, destSw, nextHops); |
| 389 | if (!result) { | 391 | if (!result) { |
| ... | @@ -395,38 +397,25 @@ public class DefaultRoutingHandler { | ... | @@ -395,38 +397,25 @@ public class DefaultRoutingHandler { |
| 395 | } | 397 | } |
| 396 | 398 | ||
| 397 | /** | 399 | /** |
| 398 | - * Populates table miss entries for all tables, and pipeline rules for | 400 | + * Populates table miss entries for all tables, and pipeline rules for VLAN |
| 399 | - * VLAN and TACM tables. | 401 | + * and TACM tables. |
| 400 | * | 402 | * |
| 401 | * @param deviceId Switch ID to set the rules | 403 | * @param deviceId Switch ID to set the rules |
| 402 | */ | 404 | */ |
| 403 | public void populateTtpRules(DeviceId deviceId) { | 405 | public void populateTtpRules(DeviceId deviceId) { |
| 404 | - | ||
| 405 | - rulePopulator.populateTableMissEntry(deviceId, FlowRule.Type.VLAN, | ||
| 406 | - true, false, false, FlowRule.Type.DEFAULT); | ||
| 407 | - rulePopulator.populateTableMissEntry(deviceId, FlowRule.Type.ETHER, | ||
| 408 | - true, false, false, FlowRule.Type.DEFAULT); | ||
| 409 | - rulePopulator.populateTableMissEntry(deviceId, FlowRule.Type.IP, | ||
| 410 | - false, true, true, FlowRule.Type.ACL); | ||
| 411 | - rulePopulator.populateTableMissEntry(deviceId, FlowRule.Type.MPLS, | ||
| 412 | - false, true, true, FlowRule.Type.ACL); | ||
| 413 | - rulePopulator.populateTableMissEntry(deviceId, FlowRule.Type.ACL, | ||
| 414 | - false, false, false, FlowRule.Type.DEFAULT); | ||
| 415 | - | ||
| 416 | rulePopulator.populateTableVlan(deviceId); | 406 | rulePopulator.populateTableVlan(deviceId); |
| 417 | rulePopulator.populateTableTMac(deviceId); | 407 | rulePopulator.populateTableTMac(deviceId); |
| 418 | } | 408 | } |
| 419 | 409 | ||
| 420 | /** | 410 | /** |
| 421 | - * Start the flow rule population process if it was never started. | 411 | + * Start the flow rule population process if it was never started. The |
| 422 | - * The process finishes successfully when all flow rules are set and | 412 | + * process finishes successfully when all flow rules are set and stops with |
| 423 | - * stops with ABORTED status when any groups required for flows is not | 413 | + * ABORTED status when any groups required for flows is not set yet. |
| 424 | - * set yet. | ||
| 425 | */ | 414 | */ |
| 426 | public void startPopulationProcess() { | 415 | public void startPopulationProcess() { |
| 427 | synchronized (populationStatus) { | 416 | synchronized (populationStatus) { |
| 428 | - if (populationStatus == Status.IDLE || | 417 | + if (populationStatus == Status.IDLE |
| 429 | - populationStatus == Status.SUCCEEDED) { | 418 | + || populationStatus == Status.SUCCEEDED) { |
| 430 | populationStatus = Status.STARTED; | 419 | populationStatus = Status.STARTED; |
| 431 | populateAllRoutingRules(); | 420 | populateAllRoutingRules(); |
| 432 | } | 421 | } |
| ... | @@ -441,7 +430,8 @@ public class DefaultRoutingHandler { | ... | @@ -441,7 +430,8 @@ public class DefaultRoutingHandler { |
| 441 | synchronized (populationStatus) { | 430 | synchronized (populationStatus) { |
| 442 | if (populationStatus == Status.ABORTED) { | 431 | if (populationStatus == Status.ABORTED) { |
| 443 | populationStatus = Status.STARTED; | 432 | populationStatus = Status.STARTED; |
| 444 | - // TODO: we need to restart from the point aborted instead of restarting. | 433 | + // TODO: we need to restart from the point aborted instead of |
| 434 | + // restarting. | ||
| 445 | populateAllRoutingRules(); | 435 | populateAllRoutingRules(); |
| 446 | } | 436 | } |
| 447 | } | 437 | } | ... | ... |
apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/NetworkConfigHandler.java
0 → 100644
| 1 | +/* | ||
| 2 | + * Copyright 2015 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * 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 | ||
| 7 | + * | ||
| 8 | + * 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. | ||
| 15 | + */ | ||
| 16 | +package org.onosproject.segmentrouting; | ||
| 17 | + | ||
| 18 | +import com.google.common.collect.Lists; | ||
| 19 | + | ||
| 20 | +import org.onlab.packet.Ip4Address; | ||
| 21 | +import org.onlab.packet.Ip4Prefix; | ||
| 22 | +import org.onlab.packet.IpPrefix; | ||
| 23 | +import org.onlab.packet.MacAddress; | ||
| 24 | +import org.onosproject.net.DeviceId; | ||
| 25 | +import org.onosproject.net.Link; | ||
| 26 | +import org.onosproject.net.PortNumber; | ||
| 27 | +import org.slf4j.Logger; | ||
| 28 | +import org.slf4j.LoggerFactory; | ||
| 29 | + | ||
| 30 | +import java.util.List; | ||
| 31 | +import java.util.Set; | ||
| 32 | + | ||
| 33 | +/** | ||
| 34 | + * This class is temporary class and used only for test. | ||
| 35 | + * It will be replaced with "real" Network Config Manager. | ||
| 36 | + * | ||
| 37 | + * TODO: Knock off this wrapper and directly use DeviceConfiguration class | ||
| 38 | + */ | ||
| 39 | + | ||
| 40 | +public class NetworkConfigHandler { | ||
| 41 | + | ||
| 42 | + private static Logger log = LoggerFactory.getLogger(NetworkConfigHandler.class); | ||
| 43 | + private SegmentRoutingManager srManager; | ||
| 44 | + private DeviceConfiguration deviceConfig; | ||
| 45 | + | ||
| 46 | + public NetworkConfigHandler(SegmentRoutingManager srManager, | ||
| 47 | + DeviceConfiguration deviceConfig) { | ||
| 48 | + this.srManager = srManager; | ||
| 49 | + this.deviceConfig = deviceConfig; | ||
| 50 | + } | ||
| 51 | + | ||
| 52 | + public List<Ip4Address> getGatewayIpAddress(DeviceId deviceId) { | ||
| 53 | + return this.deviceConfig.getSubnetGatewayIps(deviceId); | ||
| 54 | + } | ||
| 55 | + | ||
| 56 | + public IpPrefix getRouterIpAddress(DeviceId deviceId) { | ||
| 57 | + return IpPrefix.valueOf(deviceConfig.getRouterIp(deviceId), 32); | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + public MacAddress getRouterMacAddress(DeviceId deviceId) { | ||
| 61 | + return deviceConfig.getDeviceMac(deviceId); | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + public boolean inSameSubnet(DeviceId deviceId, Ip4Address destIp) { | ||
| 65 | + | ||
| 66 | + List<Ip4Prefix> subnets = getSubnetInfo(deviceId); | ||
| 67 | + if (subnets == null) { | ||
| 68 | + return false; | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + return subnets.stream() | ||
| 72 | + .anyMatch((subnet) -> subnet.contains(destIp)); | ||
| 73 | + } | ||
| 74 | + | ||
| 75 | + public boolean inSameSubnet(Ip4Address address, int sid) { | ||
| 76 | + DeviceId deviceId = deviceConfig.getDeviceId(sid); | ||
| 77 | + if (deviceId == null) { | ||
| 78 | + log.warn("Cannot find a device for SID {}", sid); | ||
| 79 | + return false; | ||
| 80 | + } | ||
| 81 | + | ||
| 82 | + return inSameSubnet(deviceId, address); | ||
| 83 | + } | ||
| 84 | + | ||
| 85 | + public List<Ip4Prefix> getSubnetInfo(DeviceId deviceId) { | ||
| 86 | + return deviceConfig.getSubnets(deviceId); | ||
| 87 | + } | ||
| 88 | + | ||
| 89 | + public int getMplsId(DeviceId deviceId) { | ||
| 90 | + return deviceConfig.getSegmentId(deviceId); | ||
| 91 | + } | ||
| 92 | + | ||
| 93 | + public int getMplsId(MacAddress routerMac) { | ||
| 94 | + return deviceConfig.getSegmentId(routerMac); | ||
| 95 | + } | ||
| 96 | + | ||
| 97 | + public int getMplsId(Ip4Address routerIpAddress) { | ||
| 98 | + return deviceConfig.getSegmentId(routerIpAddress); | ||
| 99 | + } | ||
| 100 | + | ||
| 101 | + public boolean isEcmpNotSupportedInTransit(DeviceId deviceId) { | ||
| 102 | + //TODO: temporarily changing to true to test with Dell | ||
| 103 | + return true; | ||
| 104 | + } | ||
| 105 | + | ||
| 106 | + public boolean isTransitRouter(DeviceId deviceId) { | ||
| 107 | + return !(deviceConfig.isEdgeDevice(deviceId)); | ||
| 108 | + } | ||
| 109 | + | ||
| 110 | + | ||
| 111 | + public boolean isEdgeRouter(DeviceId deviceId) { | ||
| 112 | + return deviceConfig.isEdgeDevice(deviceId); | ||
| 113 | + } | ||
| 114 | + | ||
| 115 | + private List<PortNumber> getPortsToNeighbors(DeviceId deviceId, List<DeviceId> fwdSws) { | ||
| 116 | + | ||
| 117 | + List<PortNumber> portNumbers = Lists.newArrayList(); | ||
| 118 | + | ||
| 119 | + Set<Link> links = srManager.linkService.getDeviceEgressLinks(deviceId); | ||
| 120 | + for (Link link: links) { | ||
| 121 | + for (DeviceId swId: fwdSws) { | ||
| 122 | + if (link.dst().deviceId().equals(swId)) { | ||
| 123 | + portNumbers.add(link.src().port()); | ||
| 124 | + break; | ||
| 125 | + } | ||
| 126 | + } | ||
| 127 | + } | ||
| 128 | + | ||
| 129 | + return portNumbers; | ||
| 130 | + } | ||
| 131 | + | ||
| 132 | + public List<PortNumber> getPortsToDevice(DeviceId deviceId) { | ||
| 133 | + List<PortNumber> portNumbers = Lists.newArrayList(); | ||
| 134 | + | ||
| 135 | + Set<Link> links = srManager.linkService.getDeviceEgressLinks(deviceId); | ||
| 136 | + for (Link link: links) { | ||
| 137 | + if (link.dst().deviceId().equals(deviceId)) { | ||
| 138 | + portNumbers.add(link.src().port()); | ||
| 139 | + } | ||
| 140 | + } | ||
| 141 | + | ||
| 142 | + return portNumbers; | ||
| 143 | + } | ||
| 144 | + | ||
| 145 | + | ||
| 146 | + public Ip4Address getDestinationRouterAddress(Ip4Address destIpAddress) { | ||
| 147 | + return deviceConfig.getRouterIpAddressForASubnetHost(destIpAddress); | ||
| 148 | + } | ||
| 149 | + | ||
| 150 | + public DeviceId getDeviceId(Ip4Address ip4Address) { | ||
| 151 | + return deviceConfig.getDeviceId(ip4Address); | ||
| 152 | + } | ||
| 153 | + | ||
| 154 | + public MacAddress getRouterMac(Ip4Address targetAddress) { | ||
| 155 | + return deviceConfig.getRouterMacForAGatewayIp(targetAddress); | ||
| 156 | + } | ||
| 157 | +} |
| ... | @@ -21,23 +21,25 @@ import org.onlab.packet.Ip4Prefix; | ... | @@ -21,23 +21,25 @@ import org.onlab.packet.Ip4Prefix; |
| 21 | import org.onlab.packet.IpPrefix; | 21 | import org.onlab.packet.IpPrefix; |
| 22 | import org.onlab.packet.MacAddress; | 22 | import org.onlab.packet.MacAddress; |
| 23 | import org.onlab.packet.MplsLabel; | 23 | import org.onlab.packet.MplsLabel; |
| 24 | +import org.onlab.packet.VlanId; | ||
| 24 | import org.onosproject.segmentrouting.grouphandler.NeighborSet; | 25 | import org.onosproject.segmentrouting.grouphandler.NeighborSet; |
| 25 | import org.onosproject.net.DeviceId; | 26 | import org.onosproject.net.DeviceId; |
| 26 | import org.onosproject.net.Link; | 27 | import org.onosproject.net.Link; |
| 27 | import org.onosproject.net.PortNumber; | 28 | import org.onosproject.net.PortNumber; |
| 28 | -import org.onosproject.net.flow.DefaultFlowRule; | ||
| 29 | import org.onosproject.net.flow.DefaultTrafficSelector; | 29 | import org.onosproject.net.flow.DefaultTrafficSelector; |
| 30 | import org.onosproject.net.flow.DefaultTrafficTreatment; | 30 | import org.onosproject.net.flow.DefaultTrafficTreatment; |
| 31 | -import org.onosproject.net.flow.FlowRule; | ||
| 32 | import org.onosproject.net.flow.TrafficSelector; | 31 | import org.onosproject.net.flow.TrafficSelector; |
| 33 | import org.onosproject.net.flow.TrafficTreatment; | 32 | import org.onosproject.net.flow.TrafficTreatment; |
| 34 | -import org.onosproject.net.group.DefaultGroupKey; | 33 | +import org.onosproject.net.flow.criteria.Criteria; |
| 35 | -import org.onosproject.net.group.Group; | 34 | +import org.onosproject.net.flowobjective.DefaultFilteringObjective; |
| 35 | +import org.onosproject.net.flowobjective.DefaultForwardingObjective; | ||
| 36 | +import org.onosproject.net.flowobjective.FilteringObjective; | ||
| 37 | +import org.onosproject.net.flowobjective.ForwardingObjective; | ||
| 38 | +import org.onosproject.net.flowobjective.ForwardingObjective.Builder; | ||
| 36 | import org.slf4j.Logger; | 39 | import org.slf4j.Logger; |
| 37 | import org.slf4j.LoggerFactory; | 40 | import org.slf4j.LoggerFactory; |
| 38 | 41 | ||
| 39 | import java.util.ArrayList; | 42 | import java.util.ArrayList; |
| 40 | -import java.util.Collection; | ||
| 41 | import java.util.List; | 43 | import java.util.List; |
| 42 | import java.util.Set; | 44 | import java.util.Set; |
| 43 | import java.util.concurrent.atomic.AtomicLong; | 45 | import java.util.concurrent.atomic.AtomicLong; |
| ... | @@ -46,7 +48,8 @@ import static com.google.common.base.Preconditions.checkNotNull; | ... | @@ -46,7 +48,8 @@ import static com.google.common.base.Preconditions.checkNotNull; |
| 46 | 48 | ||
| 47 | public class RoutingRulePopulator { | 49 | public class RoutingRulePopulator { |
| 48 | 50 | ||
| 49 | - private static final Logger log = LoggerFactory.getLogger(RoutingRulePopulator.class); | 51 | + private static final Logger log = LoggerFactory |
| 52 | + .getLogger(RoutingRulePopulator.class); | ||
| 50 | 53 | ||
| 51 | private AtomicLong rulePopulationCounter; | 54 | private AtomicLong rulePopulationCounter; |
| 52 | private SegmentRoutingManager srManager; | 55 | private SegmentRoutingManager srManager; |
| ... | @@ -77,7 +80,8 @@ public class RoutingRulePopulator { | ... | @@ -77,7 +80,8 @@ public class RoutingRulePopulator { |
| 77 | } | 80 | } |
| 78 | 81 | ||
| 79 | /** | 82 | /** |
| 80 | - * Populates IP flow rules for specific hosts directly connected to the switch. | 83 | + * Populates IP flow rules for specific hosts directly connected to the |
| 84 | + * switch. | ||
| 81 | * | 85 | * |
| 82 | * @param deviceId switch ID to set the rules | 86 | * @param deviceId switch ID to set the rules |
| 83 | * @param hostIp host IP address | 87 | * @param hostIp host IP address |
| ... | @@ -99,12 +103,15 @@ public class RoutingRulePopulator { | ... | @@ -99,12 +103,15 @@ public class RoutingRulePopulator { |
| 99 | TrafficTreatment treatment = tbuilder.build(); | 103 | TrafficTreatment treatment = tbuilder.build(); |
| 100 | TrafficSelector selector = sbuilder.build(); | 104 | TrafficSelector selector = sbuilder.build(); |
| 101 | 105 | ||
| 102 | - FlowRule f = new DefaultFlowRule(deviceId, selector, treatment, 100, | 106 | + ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective |
| 103 | - srManager.appId, 600, false, FlowRule.Type.IP); | 107 | + .builder().fromApp(srManager.appId).makePermanent() |
| 108 | + .withSelector(selector).withTreatment(treatment) | ||
| 109 | + .withPriority(100).withFlag(ForwardingObjective.Flag.SPECIFIC); | ||
| 104 | 110 | ||
| 105 | - srManager.flowRuleService.applyFlowRules(f); | 111 | + log.debug("Installing IPv4 forwarding objective " |
| 112 | + + "for host {} in switch {}", hostIp, deviceId); | ||
| 113 | + srManager.flowObjectiveService.forward(deviceId, fwdBuilder.add()); | ||
| 106 | rulePopulationCounter.incrementAndGet(); | 114 | rulePopulationCounter.incrementAndGet(); |
| 107 | - log.debug("Flow rule {} is set to switch {}", f, deviceId); | ||
| 108 | } | 115 | } |
| 109 | 116 | ||
| 110 | /** | 117 | /** |
| ... | @@ -116,11 +123,12 @@ public class RoutingRulePopulator { | ... | @@ -116,11 +123,12 @@ public class RoutingRulePopulator { |
| 116 | * @param nextHops next hop switch ID list | 123 | * @param nextHops next hop switch ID list |
| 117 | * @return true if all rules are set successfully, false otherwise | 124 | * @return true if all rules are set successfully, false otherwise |
| 118 | */ | 125 | */ |
| 119 | - public boolean populateIpRuleForSubnet(DeviceId deviceId, List<Ip4Prefix> subnets, | 126 | + public boolean populateIpRuleForSubnet(DeviceId deviceId, |
| 120 | - DeviceId destSw, Set<DeviceId> nextHops) { | 127 | + List<Ip4Prefix> subnets, |
| 128 | + DeviceId destSw, | ||
| 129 | + Set<DeviceId> nextHops) { | ||
| 121 | 130 | ||
| 122 | - //List<IpPrefix> subnets = extractSubnet(subnetInfo); | 131 | + for (IpPrefix subnet : subnets) { |
| 123 | - for (IpPrefix subnet: subnets) { | ||
| 124 | if (!populateIpRuleForRouter(deviceId, subnet, destSw, nextHops)) { | 132 | if (!populateIpRuleForRouter(deviceId, subnet, destSw, nextHops)) { |
| 125 | return false; | 133 | return false; |
| 126 | } | 134 | } |
| ... | @@ -138,8 +146,9 @@ public class RoutingRulePopulator { | ... | @@ -138,8 +146,9 @@ public class RoutingRulePopulator { |
| 138 | * @param nextHops next hop switch ID list | 146 | * @param nextHops next hop switch ID list |
| 139 | * @return true if all rules are set successfully, false otherwise | 147 | * @return true if all rules are set successfully, false otherwise |
| 140 | */ | 148 | */ |
| 141 | - public boolean populateIpRuleForRouter(DeviceId deviceId, IpPrefix ipPrefix, | 149 | + public boolean populateIpRuleForRouter(DeviceId deviceId, |
| 142 | - DeviceId destSw, Set<DeviceId> nextHops) { | 150 | + IpPrefix ipPrefix, DeviceId destSw, |
| 151 | + Set<DeviceId> nextHops) { | ||
| 143 | 152 | ||
| 144 | TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder(); | 153 | TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder(); |
| 145 | TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder(); | 154 | TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder(); |
| ... | @@ -149,7 +158,8 @@ public class RoutingRulePopulator { | ... | @@ -149,7 +158,8 @@ public class RoutingRulePopulator { |
| 149 | 158 | ||
| 150 | NeighborSet ns = null; | 159 | NeighborSet ns = null; |
| 151 | 160 | ||
| 152 | - //If the next hop is the same as the final destination, then MPLS label is not set. | 161 | + // If the next hop is the same as the final destination, then MPLS label |
| 162 | + // is not set. | ||
| 153 | if (nextHops.size() == 1 && nextHops.toArray()[0].equals(destSw)) { | 163 | if (nextHops.size() == 1 && nextHops.toArray()[0].equals(destSw)) { |
| 154 | tbuilder.decNwTtl(); | 164 | tbuilder.decNwTtl(); |
| 155 | ns = new NeighborSet(nextHops); | 165 | ns = new NeighborSet(nextHops); |
| ... | @@ -158,34 +168,28 @@ public class RoutingRulePopulator { | ... | @@ -158,34 +168,28 @@ public class RoutingRulePopulator { |
| 158 | ns = new NeighborSet(nextHops, config.getSegmentId(destSw)); | 168 | ns = new NeighborSet(nextHops, config.getSegmentId(destSw)); |
| 159 | } | 169 | } |
| 160 | 170 | ||
| 161 | - DefaultGroupKey groupKey = (DefaultGroupKey) srManager.getGroupKey(ns); | ||
| 162 | - if (groupKey == null) { | ||
| 163 | - log.warn("Group key is not found for ns {}", ns); | ||
| 164 | - return false; | ||
| 165 | - } | ||
| 166 | - Group group = srManager.groupService.getGroup(deviceId, groupKey); | ||
| 167 | - if (group != null) { | ||
| 168 | - tbuilder.group(group.id()); | ||
| 169 | - } else { | ||
| 170 | - log.warn("No group found for NeighborSet {} from {} to {}", | ||
| 171 | - ns, deviceId, destSw); | ||
| 172 | - return false; | ||
| 173 | - } | ||
| 174 | - | ||
| 175 | TrafficTreatment treatment = tbuilder.build(); | 171 | TrafficTreatment treatment = tbuilder.build(); |
| 176 | TrafficSelector selector = sbuilder.build(); | 172 | TrafficSelector selector = sbuilder.build(); |
| 177 | 173 | ||
| 178 | - FlowRule f = new DefaultFlowRule(deviceId, selector, treatment, 100, | 174 | + ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective |
| 179 | - srManager.appId, 600, false, FlowRule.Type.IP); | 175 | + .builder() |
| 180 | - | 176 | + .fromApp(srManager.appId) |
| 181 | - srManager.flowRuleService.applyFlowRules(f); | 177 | + .makePermanent() |
| 178 | + .nextStep(srManager.getNextObjectiveId(deviceId, ns)) | ||
| 179 | + .withTreatment(treatment) | ||
| 180 | + .withSelector(selector) | ||
| 181 | + .withPriority(100) | ||
| 182 | + .withFlag(ForwardingObjective.Flag.SPECIFIC); | ||
| 183 | + log.debug("Installing IPv4 forwarding objective " | ||
| 184 | + + "for router IP/subnet {} in switch {}", | ||
| 185 | + ipPrefix, | ||
| 186 | + deviceId); | ||
| 187 | + srManager.flowObjectiveService.forward(deviceId, fwdBuilder.add()); | ||
| 182 | rulePopulationCounter.incrementAndGet(); | 188 | rulePopulationCounter.incrementAndGet(); |
| 183 | - log.debug("IP flow rule {} is set to switch {}", f, deviceId); | ||
| 184 | 189 | ||
| 185 | return true; | 190 | return true; |
| 186 | } | 191 | } |
| 187 | 192 | ||
| 188 | - | ||
| 189 | /** | 193 | /** |
| 190 | * Populates MPLS flow rules to all transit routers. | 194 | * Populates MPLS flow rules to all transit routers. |
| 191 | * | 195 | * |
| ... | @@ -194,35 +198,53 @@ public class RoutingRulePopulator { | ... | @@ -194,35 +198,53 @@ public class RoutingRulePopulator { |
| 194 | * @param nextHops next hops switch ID list | 198 | * @param nextHops next hops switch ID list |
| 195 | * @return true if all rules are set successfully, false otherwise | 199 | * @return true if all rules are set successfully, false otherwise |
| 196 | */ | 200 | */ |
| 197 | - public boolean populateMplsRule(DeviceId deviceId, DeviceId destSwId, Set<DeviceId> nextHops) { | 201 | + public boolean populateMplsRule(DeviceId deviceId, DeviceId destSwId, |
| 202 | + Set<DeviceId> nextHops) { | ||
| 198 | 203 | ||
| 199 | TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder(); | 204 | TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder(); |
| 200 | - Collection<TrafficTreatment> treatments = new ArrayList<>(); | 205 | + List<ForwardingObjective.Builder> fwdObjBuilders = new ArrayList<ForwardingObjective.Builder>(); |
| 201 | 206 | ||
| 202 | // TODO Handle the case of Bos == false | 207 | // TODO Handle the case of Bos == false |
| 203 | sbuilder.matchMplsLabel(MplsLabel.mplsLabel(config.getSegmentId(destSwId))); | 208 | sbuilder.matchMplsLabel(MplsLabel.mplsLabel(config.getSegmentId(destSwId))); |
| 204 | sbuilder.matchEthType(Ethernet.MPLS_UNICAST); | 209 | sbuilder.matchEthType(Ethernet.MPLS_UNICAST); |
| 205 | 210 | ||
| 206 | - //If the next hop is the destination router, do PHP | 211 | + // If the next hop is the destination router, do PHP |
| 207 | if (nextHops.size() == 1 && destSwId.equals(nextHops.toArray()[0])) { | 212 | if (nextHops.size() == 1 && destSwId.equals(nextHops.toArray()[0])) { |
| 208 | - TrafficTreatment treatmentBos = | 213 | + ForwardingObjective.Builder fwdObjBosBuilder = |
| 209 | - getMplsTreatment(deviceId, destSwId, nextHops, true, true); | 214 | + getMplsForwardingObjective(deviceId, |
| 210 | - TrafficTreatment treatment = | 215 | + destSwId, |
| 211 | - getMplsTreatment(deviceId, destSwId, nextHops, true, false); | 216 | + nextHops, |
| 212 | - if (treatmentBos != null) { | 217 | + true, |
| 213 | - treatments.add(treatmentBos); | 218 | + true); |
| 219 | + // TODO: Check with Sangho on why we need this | ||
| 220 | + ForwardingObjective.Builder fwdObjNoBosBuilder = | ||
| 221 | + getMplsForwardingObjective(deviceId, | ||
| 222 | + destSwId, | ||
| 223 | + nextHops, | ||
| 224 | + true, | ||
| 225 | + false); | ||
| 226 | + if (fwdObjBosBuilder != null) { | ||
| 227 | + fwdObjBuilders.add(fwdObjBosBuilder); | ||
| 214 | } else { | 228 | } else { |
| 215 | log.warn("Failed to set MPLS rules."); | 229 | log.warn("Failed to set MPLS rules."); |
| 216 | return false; | 230 | return false; |
| 217 | } | 231 | } |
| 218 | } else { | 232 | } else { |
| 219 | - TrafficTreatment treatmentBos = | 233 | + ForwardingObjective.Builder fwdObjBosBuilder = |
| 220 | - getMplsTreatment(deviceId, destSwId, nextHops, false, true); | 234 | + getMplsForwardingObjective(deviceId, |
| 221 | - TrafficTreatment treatment = | 235 | + destSwId, |
| 222 | - getMplsTreatment(deviceId, destSwId, nextHops, false, false); | 236 | + nextHops, |
| 223 | - | 237 | + false, |
| 224 | - if (treatmentBos != null) { | 238 | + true); |
| 225 | - treatments.add(treatmentBos); | 239 | + // TODO: Check with Sangho on why we need this |
| 240 | + ForwardingObjective.Builder fwdObjNoBosBuilder = | ||
| 241 | + getMplsForwardingObjective(deviceId, | ||
| 242 | + destSwId, | ||
| 243 | + nextHops, | ||
| 244 | + false, | ||
| 245 | + false); | ||
| 246 | + if (fwdObjBosBuilder != null) { | ||
| 247 | + fwdObjBuilders.add(fwdObjBosBuilder); | ||
| 226 | } else { | 248 | } else { |
| 227 | log.warn("Failed to set MPLS rules."); | 249 | log.warn("Failed to set MPLS rules."); |
| 228 | return false; | 250 | return false; |
| ... | @@ -230,34 +252,42 @@ public class RoutingRulePopulator { | ... | @@ -230,34 +252,42 @@ public class RoutingRulePopulator { |
| 230 | } | 252 | } |
| 231 | 253 | ||
| 232 | TrafficSelector selector = sbuilder.build(); | 254 | TrafficSelector selector = sbuilder.build(); |
| 233 | - for (TrafficTreatment treatment: treatments) { | 255 | + for (ForwardingObjective.Builder fwdObjBuilder : fwdObjBuilders) { |
| 234 | - FlowRule f = new DefaultFlowRule(deviceId, selector, treatment, 100, | 256 | + ((Builder) ((Builder) fwdObjBuilder.fromApp(srManager.appId) |
| 235 | - srManager.appId, 600, false, FlowRule.Type.MPLS); | 257 | + .makePermanent()).withSelector(selector) |
| 236 | - srManager.flowRuleService.applyFlowRules(f); | 258 | + .withPriority(100)) |
| 259 | + .withFlag(ForwardingObjective.Flag.SPECIFIC); | ||
| 260 | + log.debug("Installing MPLS forwarding objective in switch {}", | ||
| 261 | + deviceId); | ||
| 262 | + srManager.flowObjectiveService.forward(deviceId, | ||
| 263 | + fwdObjBuilder.add()); | ||
| 237 | rulePopulationCounter.incrementAndGet(); | 264 | rulePopulationCounter.incrementAndGet(); |
| 238 | - log.debug("MPLS rule {} is set to {}", f, deviceId); | ||
| 239 | } | 265 | } |
| 240 | 266 | ||
| 241 | return true; | 267 | return true; |
| 242 | } | 268 | } |
| 243 | 269 | ||
| 270 | + private ForwardingObjective.Builder getMplsForwardingObjective(DeviceId deviceId, | ||
| 271 | + DeviceId destSw, | ||
| 272 | + Set<DeviceId> nextHops, | ||
| 273 | + boolean phpRequired, | ||
| 274 | + boolean isBos) { | ||
| 244 | 275 | ||
| 245 | - private TrafficTreatment getMplsTreatment(DeviceId deviceId, DeviceId destSw, | 276 | + ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective |
| 246 | - Set<DeviceId> nextHops, | 277 | + .builder().withFlag(ForwardingObjective.Flag.SPECIFIC); |
| 247 | - boolean phpRequired, boolean isBos) { | ||
| 248 | 278 | ||
| 249 | TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder(); | 279 | TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder(); |
| 250 | 280 | ||
| 251 | if (phpRequired) { | 281 | if (phpRequired) { |
| 282 | + log.debug("getMplsForwardingObjective: php required"); | ||
| 252 | tbuilder.copyTtlIn(); | 283 | tbuilder.copyTtlIn(); |
| 253 | if (isBos) { | 284 | if (isBos) { |
| 254 | - tbuilder.popMpls(Ethernet.TYPE_IPV4) | 285 | + tbuilder.popMpls(Ethernet.TYPE_IPV4).decNwTtl(); |
| 255 | - .decNwTtl(); | ||
| 256 | } else { | 286 | } else { |
| 257 | - tbuilder.popMpls(Ethernet.MPLS_UNICAST) | 287 | + tbuilder.popMpls(Ethernet.MPLS_UNICAST).decMplsTtl(); |
| 258 | - .decMplsTtl(); | ||
| 259 | } | 288 | } |
| 260 | } else { | 289 | } else { |
| 290 | + log.debug("getMplsForwardingObjective: php not required"); | ||
| 261 | tbuilder.decMplsTtl(); | 291 | tbuilder.decMplsTtl(); |
| 262 | } | 292 | } |
| 263 | 293 | ||
| ... | @@ -271,24 +301,14 @@ public class RoutingRulePopulator { | ... | @@ -271,24 +301,14 @@ public class RoutingRulePopulator { |
| 271 | tbuilder.setEthSrc(config.getDeviceMac(deviceId)) | 301 | tbuilder.setEthSrc(config.getDeviceMac(deviceId)) |
| 272 | .setEthDst(config.getDeviceMac(nextHop)) | 302 | .setEthDst(config.getDeviceMac(nextHop)) |
| 273 | .setOutput(link.src().port()); | 303 | .setOutput(link.src().port()); |
| 304 | + fwdBuilder.withTreatment(tbuilder.build()); | ||
| 274 | } else { | 305 | } else { |
| 275 | NeighborSet ns = new NeighborSet(nextHops); | 306 | NeighborSet ns = new NeighborSet(nextHops); |
| 276 | - DefaultGroupKey groupKey = (DefaultGroupKey) srManager.getGroupKey(ns); | 307 | + fwdBuilder.nextStep(srManager |
| 277 | - if (groupKey == null) { | 308 | + .getNextObjectiveId(deviceId, ns)); |
| 278 | - log.warn("Group key is not found for ns {}", ns); | ||
| 279 | - return null; | ||
| 280 | - } | ||
| 281 | - Group group = srManager.groupService.getGroup(deviceId, groupKey); | ||
| 282 | - if (group != null) { | ||
| 283 | - tbuilder.group(group.id()); | ||
| 284 | - } else { | ||
| 285 | - log.warn("No group found for ns {} key {} in {}", ns, | ||
| 286 | - srManager.getGroupKey(ns), deviceId); | ||
| 287 | - return null; | ||
| 288 | - } | ||
| 289 | } | 309 | } |
| 290 | 310 | ||
| 291 | - return tbuilder.build(); | 311 | + return fwdBuilder; |
| 292 | } | 312 | } |
| 293 | 313 | ||
| 294 | private boolean isECMPSupportedInTransitRouter() { | 314 | private boolean isECMPSupportedInTransitRouter() { |
| ... | @@ -298,109 +318,41 @@ public class RoutingRulePopulator { | ... | @@ -298,109 +318,41 @@ public class RoutingRulePopulator { |
| 298 | } | 318 | } |
| 299 | 319 | ||
| 300 | /** | 320 | /** |
| 301 | - * Populates VLAN flows rules. | 321 | + * Populates VLAN flows rules. All packets are forwarded to TMAC table. |
| 302 | - * All packets are forwarded to TMAC table. | ||
| 303 | * | 322 | * |
| 304 | * @param deviceId switch ID to set the rules | 323 | * @param deviceId switch ID to set the rules |
| 305 | */ | 324 | */ |
| 306 | public void populateTableVlan(DeviceId deviceId) { | 325 | public void populateTableVlan(DeviceId deviceId) { |
| 307 | - TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder(); | 326 | + FilteringObjective.Builder fob = DefaultFilteringObjective.builder(); |
| 308 | - TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder(); | 327 | + fob.withKey(Criteria.matchInPort(PortNumber.ALL)) |
| 309 | - | 328 | + .addCondition(Criteria.matchVlanId(VlanId.NONE)); |
| 310 | - tbuilder.transition(FlowRule.Type.ETHER); | 329 | + fob.permit().fromApp(srManager.appId); |
| 311 | - | 330 | + log.debug("populateTableVlan: Installing filtering objective for untagged packets"); |
| 312 | - TrafficTreatment treatment = tbuilder.build(); | 331 | + srManager.flowObjectiveService.filter(deviceId, fob.add()); |
| 313 | - TrafficSelector selector = sbuilder.build(); | ||
| 314 | - | ||
| 315 | - FlowRule f = new DefaultFlowRule(deviceId, selector, treatment, 100, | ||
| 316 | - srManager.appId, 600, false, FlowRule.Type.VLAN); | ||
| 317 | - | ||
| 318 | - srManager.flowRuleService.applyFlowRules(f); | ||
| 319 | - | ||
| 320 | - log.debug("Vlan flow rule {} is set to switch {}", f, deviceId); | ||
| 321 | } | 332 | } |
| 322 | 333 | ||
| 323 | /** | 334 | /** |
| 324 | - * Populates TMAC table rules. | 335 | + * Populates TMAC table rules. IP packets are forwarded to IP table. MPLS |
| 325 | - * IP packets are forwarded to IP table. | 336 | + * packets are forwarded to MPLS table. |
| 326 | - * MPLS packets are forwarded to MPLS table. | ||
| 327 | * | 337 | * |
| 328 | * @param deviceId switch ID to set the rules | 338 | * @param deviceId switch ID to set the rules |
| 329 | */ | 339 | */ |
| 330 | public void populateTableTMac(DeviceId deviceId) { | 340 | public void populateTableTMac(DeviceId deviceId) { |
| 331 | 341 | ||
| 332 | - // flow rule for IP packets | 342 | + FilteringObjective.Builder fob = DefaultFilteringObjective.builder(); |
| 333 | - TrafficSelector selectorIp = DefaultTrafficSelector.builder() | 343 | + fob.withKey(Criteria.matchInPort(PortNumber.ALL)) |
| 334 | - .matchEthType(Ethernet.TYPE_IPV4) | 344 | + .addCondition(Criteria.matchEthDst(config |
| 335 | - .matchEthDst(config.getDeviceMac(deviceId)) | 345 | + .getDeviceMac(deviceId))); |
| 336 | - .build(); | 346 | + fob.permit().fromApp(srManager.appId); |
| 337 | - TrafficTreatment treatmentIp = DefaultTrafficTreatment.builder() | 347 | + log.debug("populateTableVlan: Installing filtering objective for router mac"); |
| 338 | - .transition(FlowRule.Type.IP) | 348 | + srManager.flowObjectiveService.filter(deviceId, fob.add()); |
| 339 | - .build(); | ||
| 340 | - | ||
| 341 | - FlowRule flowIp = new DefaultFlowRule(deviceId, selectorIp, treatmentIp, 100, | ||
| 342 | - srManager.appId, 600, false, FlowRule.Type.ETHER); | ||
| 343 | - | ||
| 344 | - srManager.flowRuleService.applyFlowRules(flowIp); | ||
| 345 | - | ||
| 346 | - // flow rule for MPLS packets | ||
| 347 | - TrafficSelector selectorMpls = DefaultTrafficSelector.builder() | ||
| 348 | - .matchEthType(Ethernet.MPLS_UNICAST) | ||
| 349 | - .matchEthDst(config.getDeviceMac(deviceId)) | ||
| 350 | - .build(); | ||
| 351 | - TrafficTreatment treatmentMpls = DefaultTrafficTreatment.builder() | ||
| 352 | - .transition(FlowRule.Type.MPLS) | ||
| 353 | - .build(); | ||
| 354 | - | ||
| 355 | - FlowRule flowMpls = new DefaultFlowRule(deviceId, selectorMpls, treatmentMpls, 100, | ||
| 356 | - srManager.appId, 600, false, FlowRule.Type.ETHER); | ||
| 357 | - | ||
| 358 | - srManager.flowRuleService.applyFlowRules(flowMpls); | ||
| 359 | - | ||
| 360 | - } | ||
| 361 | - | ||
| 362 | - /** | ||
| 363 | - * Populates a table miss entry. | ||
| 364 | - * | ||
| 365 | - * @param deviceId switch ID to set rules | ||
| 366 | - * @param tableToAdd table to set the rules | ||
| 367 | - * @param toControllerNow flag to send packets to controller immediately | ||
| 368 | - * @param toControllerWrite flag to send packets to controller at the end of pipeline | ||
| 369 | - * @param toTable flag to send packets to a specific table | ||
| 370 | - * @param tableToSend table type to send packets when the toTable flag is set | ||
| 371 | - */ | ||
| 372 | - public void populateTableMissEntry(DeviceId deviceId, FlowRule.Type tableToAdd, boolean toControllerNow, | ||
| 373 | - boolean toControllerWrite, | ||
| 374 | - boolean toTable, FlowRule.Type tableToSend) { | ||
| 375 | - // TODO: Change arguments to EnumSet | ||
| 376 | - TrafficSelector selector = DefaultTrafficSelector.builder() | ||
| 377 | - .build(); | ||
| 378 | - TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder(); | ||
| 379 | - | ||
| 380 | - if (toControllerNow) { | ||
| 381 | - tBuilder.setOutput(PortNumber.CONTROLLER); | ||
| 382 | - } | ||
| 383 | - | ||
| 384 | - if (toControllerWrite) { | ||
| 385 | - tBuilder.deferred().setOutput(PortNumber.CONTROLLER); | ||
| 386 | - } | ||
| 387 | - | ||
| 388 | - if (toTable) { | ||
| 389 | - tBuilder.transition(tableToSend); | ||
| 390 | - } | ||
| 391 | - | ||
| 392 | - FlowRule flow = new DefaultFlowRule(deviceId, selector, tBuilder.build(), 0, | ||
| 393 | - srManager.appId, 600, false, tableToAdd); | ||
| 394 | - | ||
| 395 | - srManager.flowRuleService.applyFlowRules(flow); | ||
| 396 | - | ||
| 397 | } | 349 | } |
| 398 | 350 | ||
| 399 | private Link selectOneLink(DeviceId srcId, Set<DeviceId> destIds) { | 351 | private Link selectOneLink(DeviceId srcId, Set<DeviceId> destIds) { |
| 400 | 352 | ||
| 401 | Set<Link> links = srManager.linkService.getDeviceEgressLinks(srcId); | 353 | Set<Link> links = srManager.linkService.getDeviceEgressLinks(srcId); |
| 402 | DeviceId destId = (DeviceId) destIds.toArray()[0]; | 354 | DeviceId destId = (DeviceId) destIds.toArray()[0]; |
| 403 | - for (Link link: links) { | 355 | + for (Link link : links) { |
| 404 | if (link.dst().deviceId().equals(destId)) { | 356 | if (link.dst().deviceId().equals(destId)) { |
| 405 | return link; | 357 | return link; |
| 406 | } | 358 | } | ... | ... |
| ... | @@ -36,12 +36,10 @@ import org.onosproject.net.Port; | ... | @@ -36,12 +36,10 @@ import org.onosproject.net.Port; |
| 36 | import org.onosproject.net.device.DeviceEvent; | 36 | import org.onosproject.net.device.DeviceEvent; |
| 37 | import org.onosproject.net.device.DeviceListener; | 37 | import org.onosproject.net.device.DeviceListener; |
| 38 | import org.onosproject.net.device.DeviceService; | 38 | import org.onosproject.net.device.DeviceService; |
| 39 | -import org.onosproject.net.flow.FlowRuleService; | 39 | +import org.onosproject.net.flowobjective.FlowObjectiveService; |
| 40 | import org.onosproject.net.group.Group; | 40 | import org.onosproject.net.group.Group; |
| 41 | import org.onosproject.net.group.GroupEvent; | 41 | import org.onosproject.net.group.GroupEvent; |
| 42 | import org.onosproject.net.group.GroupKey; | 42 | import org.onosproject.net.group.GroupKey; |
| 43 | -import org.onosproject.net.group.GroupListener; | ||
| 44 | -import org.onosproject.net.group.GroupService; | ||
| 45 | import org.onosproject.net.host.HostService; | 43 | import org.onosproject.net.host.HostService; |
| 46 | import org.onosproject.net.intent.IntentService; | 44 | import org.onosproject.net.intent.IntentService; |
| 47 | import org.onosproject.net.link.LinkEvent; | 45 | import org.onosproject.net.link.LinkEvent; |
| ... | @@ -68,7 +66,8 @@ import java.util.concurrent.TimeUnit; | ... | @@ -68,7 +66,8 @@ import java.util.concurrent.TimeUnit; |
| 68 | @Component(immediate = true) | 66 | @Component(immediate = true) |
| 69 | public class SegmentRoutingManager { | 67 | public class SegmentRoutingManager { |
| 70 | 68 | ||
| 71 | - private static Logger log = LoggerFactory.getLogger(SegmentRoutingManager.class); | 69 | + private static Logger log = LoggerFactory |
| 70 | + .getLogger(SegmentRoutingManager.class); | ||
| 72 | 71 | ||
| 73 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 72 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
| 74 | protected CoreService coreService; | 73 | protected CoreService coreService; |
| ... | @@ -89,15 +88,12 @@ public class SegmentRoutingManager { | ... | @@ -89,15 +88,12 @@ public class SegmentRoutingManager { |
| 89 | protected DeviceService deviceService; | 88 | protected DeviceService deviceService; |
| 90 | 89 | ||
| 91 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 90 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
| 92 | - protected FlowRuleService flowRuleService; | 91 | + protected FlowObjectiveService flowObjectiveService; |
| 93 | 92 | ||
| 94 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 93 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
| 95 | protected LinkService linkService; | 94 | protected LinkService linkService; |
| 96 | 95 | ||
| 97 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 96 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
| 98 | - protected GroupService groupService; | ||
| 99 | - | ||
| 100 | - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 101 | protected MastershipService mastershipService; | 97 | protected MastershipService mastershipService; |
| 102 | protected ArpHandler arpHandler = null; | 98 | protected ArpHandler arpHandler = null; |
| 103 | protected IcmpHandler icmpHandler = null; | 99 | protected IcmpHandler icmpHandler = null; |
| ... | @@ -110,12 +106,12 @@ public class SegmentRoutingManager { | ... | @@ -110,12 +106,12 @@ public class SegmentRoutingManager { |
| 110 | private InternalPacketProcessor processor = new InternalPacketProcessor(); | 106 | private InternalPacketProcessor processor = new InternalPacketProcessor(); |
| 111 | private InternalEventHandler eventHandler = new InternalEventHandler(); | 107 | private InternalEventHandler eventHandler = new InternalEventHandler(); |
| 112 | 108 | ||
| 113 | - private ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1); | 109 | + private ScheduledExecutorService executorService = Executors |
| 110 | + .newScheduledThreadPool(1); | ||
| 114 | 111 | ||
| 115 | private static ScheduledFuture<?> eventHandlerFuture = null; | 112 | private static ScheduledFuture<?> eventHandlerFuture = null; |
| 116 | private ConcurrentLinkedQueue<Event> eventQueue = new ConcurrentLinkedQueue<Event>(); | 113 | private ConcurrentLinkedQueue<Event> eventQueue = new ConcurrentLinkedQueue<Event>(); |
| 117 | - private Map<DeviceId, DefaultGroupHandler> groupHandlerMap | 114 | + private Map<DeviceId, DefaultGroupHandler> groupHandlerMap = new ConcurrentHashMap<DeviceId, DefaultGroupHandler>(); |
| 118 | - = new ConcurrentHashMap<DeviceId, DefaultGroupHandler>(); | ||
| 119 | 115 | ||
| 120 | private NetworkConfigManager networkConfigService = new NetworkConfigManager();; | 116 | private NetworkConfigManager networkConfigService = new NetworkConfigManager();; |
| 121 | 117 | ||
| ... | @@ -125,7 +121,8 @@ public class SegmentRoutingManager { | ... | @@ -125,7 +121,8 @@ public class SegmentRoutingManager { |
| 125 | 121 | ||
| 126 | @Activate | 122 | @Activate |
| 127 | protected void activate() { | 123 | protected void activate() { |
| 128 | - appId = coreService.registerApplication("org.onosproject.segmentrouting"); | 124 | + appId = coreService |
| 125 | + .registerApplication("org.onosproject.segmentrouting"); | ||
| 129 | networkConfigService.init(); | 126 | networkConfigService.init(); |
| 130 | deviceConfiguration = new DeviceConfiguration(networkConfigService); | 127 | deviceConfiguration = new DeviceConfiguration(networkConfigService); |
| 131 | arpHandler = new ArpHandler(this); | 128 | arpHandler = new ArpHandler(this); |
| ... | @@ -136,25 +133,22 @@ public class SegmentRoutingManager { | ... | @@ -136,25 +133,22 @@ public class SegmentRoutingManager { |
| 136 | 133 | ||
| 137 | packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 2); | 134 | packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 2); |
| 138 | linkService.addListener(new InternalLinkListener()); | 135 | linkService.addListener(new InternalLinkListener()); |
| 139 | - groupService.addListener(new InternalGroupListener()); | ||
| 140 | deviceService.addListener(new InternalDeviceListener()); | 136 | deviceService.addListener(new InternalDeviceListener()); |
| 141 | 137 | ||
| 142 | - for (Device device: deviceService.getDevices()) { | 138 | + for (Device device : deviceService.getDevices()) { |
| 143 | - if (mastershipService. | 139 | + if (mastershipService.getLocalRole(device.id()) == MastershipRole.MASTER) { |
| 144 | - getLocalRole(device.id()) == MastershipRole.MASTER) { | 140 | + DefaultGroupHandler groupHandler = DefaultGroupHandler |
| 145 | - DefaultGroupHandler groupHandler = | 141 | + .createGroupHandler(device.id(), appId, |
| 146 | - DefaultGroupHandler.createGroupHandler(device.id(), | 142 | + deviceConfiguration, linkService, |
| 147 | - appId, deviceConfiguration, linkService, groupService); | 143 | + flowObjectiveService); |
| 148 | - groupHandler.createGroups(); | ||
| 149 | groupHandlerMap.put(device.id(), groupHandler); | 144 | groupHandlerMap.put(device.id(), groupHandler); |
| 150 | defaultRoutingHandler.populateTtpRules(device.id()); | 145 | defaultRoutingHandler.populateTtpRules(device.id()); |
| 151 | log.debug("Initiating default group handling for {}", device.id()); | 146 | log.debug("Initiating default group handling for {}", device.id()); |
| 152 | } else { | 147 | } else { |
| 153 | log.debug("Activate: Local role {} " | 148 | log.debug("Activate: Local role {} " |
| 154 | - + "is not MASTER for device {}", | 149 | + + "is not MASTER for device {}", |
| 155 | - mastershipService. | 150 | + mastershipService.getLocalRole(device.id()), |
| 156 | - getLocalRole(device.id()), | 151 | + device.id()); |
| 157 | - device.id()); | ||
| 158 | } | 152 | } |
| 159 | } | 153 | } |
| 160 | 154 | ||
| ... | @@ -177,13 +171,19 @@ public class SegmentRoutingManager { | ... | @@ -177,13 +171,19 @@ public class SegmentRoutingManager { |
| 177 | */ | 171 | */ |
| 178 | public GroupKey getGroupKey(NeighborSet ns) { | 172 | public GroupKey getGroupKey(NeighborSet ns) { |
| 179 | 173 | ||
| 180 | - for (DefaultGroupHandler groupHandler: groupHandlerMap.values()) { | 174 | + for (DefaultGroupHandler groupHandler : groupHandlerMap.values()) { |
| 181 | return groupHandler.getGroupKey(ns); | 175 | return groupHandler.getGroupKey(ns); |
| 182 | } | 176 | } |
| 183 | 177 | ||
| 184 | return null; | 178 | return null; |
| 185 | } | 179 | } |
| 186 | 180 | ||
| 181 | + public int getNextObjectiveId(DeviceId deviceId, NeighborSet ns) { | ||
| 182 | + | ||
| 183 | + return (groupHandlerMap.get(deviceId) != null) ? groupHandlerMap | ||
| 184 | + .get(deviceId).getNextObjectiveId(ns) : -1; | ||
| 185 | + } | ||
| 186 | + | ||
| 187 | private class InternalPacketProcessor implements PacketProcessor { | 187 | private class InternalPacketProcessor implements PacketProcessor { |
| 188 | 188 | ||
| 189 | @Override | 189 | @Override |
| ... | @@ -213,8 +213,8 @@ public class SegmentRoutingManager { | ... | @@ -213,8 +213,8 @@ public class SegmentRoutingManager { |
| 213 | private class InternalLinkListener implements LinkListener { | 213 | private class InternalLinkListener implements LinkListener { |
| 214 | @Override | 214 | @Override |
| 215 | public void event(LinkEvent event) { | 215 | public void event(LinkEvent event) { |
| 216 | - if (event.type() == LinkEvent.Type.LINK_ADDED || | 216 | + if (event.type() == LinkEvent.Type.LINK_ADDED |
| 217 | - event.type() == LinkEvent.Type.LINK_REMOVED) { | 217 | + || event.type() == LinkEvent.Type.LINK_REMOVED) { |
| 218 | scheduleEventHandlerIfNotScheduled(event); | 218 | scheduleEventHandlerIfNotScheduled(event); |
| 219 | } | 219 | } |
| 220 | } | 220 | } |
| ... | @@ -224,12 +224,10 @@ public class SegmentRoutingManager { | ... | @@ -224,12 +224,10 @@ public class SegmentRoutingManager { |
| 224 | 224 | ||
| 225 | @Override | 225 | @Override |
| 226 | public void event(DeviceEvent event) { | 226 | public void event(DeviceEvent event) { |
| 227 | - if (mastershipService. | 227 | + if (mastershipService.getLocalRole(event.subject().id()) != MastershipRole.MASTER) { |
| 228 | - getLocalRole(event.subject().id()) != MastershipRole.MASTER) { | ||
| 229 | log.debug("Local role {} is not MASTER for device {}", | 228 | log.debug("Local role {} is not MASTER for device {}", |
| 230 | - mastershipService. | 229 | + mastershipService.getLocalRole(event.subject().id()), |
| 231 | - getLocalRole(event.subject().id()), | 230 | + event.subject().id()); |
| 232 | - event.subject().id()); | ||
| 233 | return; | 231 | return; |
| 234 | } | 232 | } |
| 235 | 233 | ||
| ... | @@ -245,38 +243,18 @@ public class SegmentRoutingManager { | ... | @@ -245,38 +243,18 @@ public class SegmentRoutingManager { |
| 245 | } | 243 | } |
| 246 | } | 244 | } |
| 247 | 245 | ||
| 248 | - private class InternalGroupListener implements GroupListener { | ||
| 249 | - | ||
| 250 | - @Override | ||
| 251 | - public void event(GroupEvent event) { | ||
| 252 | - switch (event.type()) { | ||
| 253 | - case GROUP_ADDED: | ||
| 254 | - scheduleEventHandlerIfNotScheduled(event); | ||
| 255 | - break; | ||
| 256 | - case GROUP_ADD_REQUESTED: | ||
| 257 | - log.info("Group add requested"); | ||
| 258 | - break; | ||
| 259 | - case GROUP_UPDATED: | ||
| 260 | - break; | ||
| 261 | - default: | ||
| 262 | - log.warn("Unhandled group event type: {}", event.type()); | ||
| 263 | - } | ||
| 264 | - } | ||
| 265 | - } | ||
| 266 | - | ||
| 267 | private void scheduleEventHandlerIfNotScheduled(Event event) { | 246 | private void scheduleEventHandlerIfNotScheduled(Event event) { |
| 268 | 247 | ||
| 269 | eventQueue.add(event); | 248 | eventQueue.add(event); |
| 270 | numOfEvents++; | 249 | numOfEvents++; |
| 271 | - if (eventHandlerFuture == null || | 250 | + if (eventHandlerFuture == null || eventHandlerFuture.isDone()) { |
| 272 | - eventHandlerFuture.isDone()) { | 251 | + eventHandlerFuture = executorService |
| 273 | - eventHandlerFuture = executorService.schedule(eventHandler, | 252 | + .schedule(eventHandler, 100, TimeUnit.MILLISECONDS); |
| 274 | - 100, TimeUnit.MILLISECONDS); | ||
| 275 | numOfHandlerScheduled++; | 253 | numOfHandlerScheduled++; |
| 276 | } | 254 | } |
| 277 | 255 | ||
| 278 | log.trace("numOfEvents {}, numOfEventHanlderScheduled {}", numOfEvents, | 256 | log.trace("numOfEvents {}, numOfEventHanlderScheduled {}", numOfEvents, |
| 279 | - numOfHandlerScheduled); | 257 | + numOfHandlerScheduled); |
| 280 | 258 | ||
| 281 | } | 259 | } |
| 282 | 260 | ||
| ... | @@ -301,25 +279,22 @@ public class SegmentRoutingManager { | ... | @@ -301,25 +279,22 @@ public class SegmentRoutingManager { |
| 301 | } | 279 | } |
| 302 | } else if (event.type() == DeviceEvent.Type.PORT_REMOVED) { | 280 | } else if (event.type() == DeviceEvent.Type.PORT_REMOVED) { |
| 303 | processPortRemoved((Device) event.subject(), | 281 | processPortRemoved((Device) event.subject(), |
| 304 | - ((DeviceEvent) event).port()); | 282 | + ((DeviceEvent) event).port()); |
| 305 | } else { | 283 | } else { |
| 306 | log.warn("Unhandled event type: {}", event.type()); | 284 | log.warn("Unhandled event type: {}", event.type()); |
| 307 | } | 285 | } |
| 308 | } | 286 | } |
| 309 | log.debug("numOfHandlerExecution {} numOfEventHanlderScheduled {} numOfEvents {}", | 287 | log.debug("numOfHandlerExecution {} numOfEventHanlderScheduled {} numOfEvents {}", |
| 310 | - numOfHandlerExecution, numOfHandlerScheduled, numOfEvents); | 288 | + numOfHandlerExecution, numOfHandlerScheduled, numOfEvents); |
| 311 | } | 289 | } |
| 312 | } | 290 | } |
| 313 | 291 | ||
| 314 | - | ||
| 315 | - | ||
| 316 | private void processLinkAdded(Link link) { | 292 | private void processLinkAdded(Link link) { |
| 317 | log.debug("A new link {} was added", link.toString()); | 293 | log.debug("A new link {} was added", link.toString()); |
| 318 | 294 | ||
| 319 | - if (mastershipService. | 295 | + if (mastershipService.getLocalRole(link.src().deviceId()) == MastershipRole.MASTER) { |
| 320 | - getLocalRole(link.src().deviceId()) == MastershipRole.MASTER) { | 296 | + DefaultGroupHandler groupHandler = groupHandlerMap.get(link.src() |
| 321 | - DefaultGroupHandler groupHandler = | 297 | + .deviceId()); |
| 322 | - groupHandlerMap.get(link.src().deviceId()); | ||
| 323 | if (groupHandler != null) { | 298 | if (groupHandler != null) { |
| 324 | groupHandler.linkUp(link); | 299 | groupHandler.linkUp(link); |
| 325 | } | 300 | } |
| ... | @@ -332,7 +307,6 @@ public class SegmentRoutingManager { | ... | @@ -332,7 +307,6 @@ public class SegmentRoutingManager { |
| 332 | defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(link); | 307 | defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(link); |
| 333 | } | 308 | } |
| 334 | 309 | ||
| 335 | - | ||
| 336 | private void processGroupAdded(Group group) { | 310 | private void processGroupAdded(Group group) { |
| 337 | log.debug("A new group with ID {} was added", group.id()); | 311 | log.debug("A new group with ID {} was added", group.id()); |
| 338 | defaultRoutingHandler.resumePopulationProcess(); | 312 | defaultRoutingHandler.resumePopulationProcess(); |
| ... | @@ -341,20 +315,14 @@ public class SegmentRoutingManager { | ... | @@ -341,20 +315,14 @@ public class SegmentRoutingManager { |
| 341 | private void processDeviceAdded(Device device) { | 315 | private void processDeviceAdded(Device device) { |
| 342 | log.debug("A new device with ID {} was added", device.id()); | 316 | log.debug("A new device with ID {} was added", device.id()); |
| 343 | defaultRoutingHandler.populateTtpRules(device.id()); | 317 | defaultRoutingHandler.populateTtpRules(device.id()); |
| 344 | - DefaultGroupHandler dgh = DefaultGroupHandler.createGroupHandler( | 318 | + DefaultGroupHandler dgh = DefaultGroupHandler.createGroupHandler(device |
| 345 | - device.id(), | 319 | + .id(), appId, deviceConfiguration, linkService, flowObjectiveService); |
| 346 | - appId, | ||
| 347 | - deviceConfiguration, | ||
| 348 | - linkService, | ||
| 349 | - groupService); | ||
| 350 | - dgh.createGroups(); | ||
| 351 | groupHandlerMap.put(device.id(), dgh); | 320 | groupHandlerMap.put(device.id(), dgh); |
| 352 | } | 321 | } |
| 353 | 322 | ||
| 354 | private void processPortRemoved(Device device, Port port) { | 323 | private void processPortRemoved(Device device, Port port) { |
| 355 | log.debug("Port {} was removed", port.toString()); | 324 | log.debug("Port {} was removed", port.toString()); |
| 356 | - DefaultGroupHandler groupHandler = | 325 | + DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id()); |
| 357 | - groupHandlerMap.get(device.id()); | ||
| 358 | if (groupHandler != null) { | 326 | if (groupHandler != null) { |
| 359 | groupHandler.portDown(port.number()); | 327 | groupHandler.portDown(port.number()); |
| 360 | } | 328 | } | ... | ... |
| ... | @@ -15,7 +15,6 @@ | ... | @@ -15,7 +15,6 @@ |
| 15 | */ | 15 | */ |
| 16 | package org.onosproject.segmentrouting.grouphandler; | 16 | package org.onosproject.segmentrouting.grouphandler; |
| 17 | 17 | ||
| 18 | -import java.util.Arrays; | ||
| 19 | import java.util.HashSet; | 18 | import java.util.HashSet; |
| 20 | import java.util.List; | 19 | import java.util.List; |
| 21 | import java.util.Set; | 20 | import java.util.Set; |
| ... | @@ -26,10 +25,7 @@ import org.onosproject.net.DeviceId; | ... | @@ -26,10 +25,7 @@ import org.onosproject.net.DeviceId; |
| 26 | import org.onosproject.net.Link; | 25 | import org.onosproject.net.Link; |
| 27 | import org.onosproject.net.flow.DefaultTrafficTreatment; | 26 | import org.onosproject.net.flow.DefaultTrafficTreatment; |
| 28 | import org.onosproject.net.flow.TrafficTreatment; | 27 | import org.onosproject.net.flow.TrafficTreatment; |
| 29 | -import org.onosproject.net.group.DefaultGroupBucket; | 28 | +import org.onosproject.net.flowobjective.FlowObjectiveService; |
| 30 | -import org.onosproject.net.group.GroupBucket; | ||
| 31 | -import org.onosproject.net.group.GroupBuckets; | ||
| 32 | -import org.onosproject.net.group.GroupService; | ||
| 33 | import org.onosproject.net.link.LinkService; | 29 | import org.onosproject.net.link.LinkService; |
| 34 | 30 | ||
| 35 | /** | 31 | /** |
| ... | @@ -55,8 +51,8 @@ public class DefaultEdgeGroupHandler extends DefaultGroupHandler { | ... | @@ -55,8 +51,8 @@ public class DefaultEdgeGroupHandler extends DefaultGroupHandler { |
| 55 | ApplicationId appId, | 51 | ApplicationId appId, |
| 56 | DeviceProperties config, | 52 | DeviceProperties config, |
| 57 | LinkService linkService, | 53 | LinkService linkService, |
| 58 | - GroupService groupService) { | 54 | + FlowObjectiveService flowObjService) { |
| 59 | - super(deviceId, appId, config, linkService, groupService); | 55 | + super(deviceId, appId, config, linkService, flowObjService); |
| 60 | } | 56 | } |
| 61 | 57 | ||
| 62 | @Override | 58 | @Override |
| ... | @@ -130,7 +126,7 @@ public class DefaultEdgeGroupHandler extends DefaultGroupHandler { | ... | @@ -130,7 +126,7 @@ public class DefaultEdgeGroupHandler extends DefaultGroupHandler { |
| 130 | .setMpls(MplsLabel. | 126 | .setMpls(MplsLabel. |
| 131 | mplsLabel(ns.getEdgeLabel())); | 127 | mplsLabel(ns.getEdgeLabel())); |
| 132 | } | 128 | } |
| 133 | - GroupBucket updatedBucket = DefaultGroupBucket. | 129 | + /*GroupBucket updatedBucket = DefaultGroupBucket. |
| 134 | createSelectGroupBucket(tBuilder.build()); | 130 | createSelectGroupBucket(tBuilder.build()); |
| 135 | GroupBuckets updatedBuckets = new GroupBuckets( | 131 | GroupBuckets updatedBuckets = new GroupBuckets( |
| 136 | Arrays.asList(updatedBucket)); | 132 | Arrays.asList(updatedBucket)); |
| ... | @@ -140,7 +136,8 @@ public class DefaultEdgeGroupHandler extends DefaultGroupHandler { | ... | @@ -140,7 +136,8 @@ public class DefaultEdgeGroupHandler extends DefaultGroupHandler { |
| 140 | getGroupKey(ns), | 136 | getGroupKey(ns), |
| 141 | updatedBuckets, | 137 | updatedBuckets, |
| 142 | getGroupKey(ns), | 138 | getGroupKey(ns), |
| 143 | - appId); | 139 | + appId);*/ |
| 140 | + //TODO: Use nextObjective APIs to update the next objective | ||
| 144 | } | 141 | } |
| 145 | } | 142 | } |
| 146 | 143 | ... | ... |
| ... | @@ -20,10 +20,11 @@ import static org.slf4j.LoggerFactory.getLogger; | ... | @@ -20,10 +20,11 @@ import static org.slf4j.LoggerFactory.getLogger; |
| 20 | 20 | ||
| 21 | import java.net.URI; | 21 | import java.net.URI; |
| 22 | import java.util.ArrayList; | 22 | import java.util.ArrayList; |
| 23 | -import java.util.Arrays; | 23 | +import java.util.Collections; |
| 24 | import java.util.HashMap; | 24 | import java.util.HashMap; |
| 25 | import java.util.HashSet; | 25 | import java.util.HashSet; |
| 26 | import java.util.List; | 26 | import java.util.List; |
| 27 | +import java.util.Random; | ||
| 27 | import java.util.Set; | 28 | import java.util.Set; |
| 28 | 29 | ||
| 29 | import org.onlab.packet.MacAddress; | 30 | import org.onlab.packet.MacAddress; |
| ... | @@ -35,25 +36,18 @@ import org.onosproject.net.Link; | ... | @@ -35,25 +36,18 @@ import org.onosproject.net.Link; |
| 35 | import org.onosproject.net.PortNumber; | 36 | import org.onosproject.net.PortNumber; |
| 36 | import org.onosproject.net.flow.DefaultTrafficTreatment; | 37 | import org.onosproject.net.flow.DefaultTrafficTreatment; |
| 37 | import org.onosproject.net.flow.TrafficTreatment; | 38 | import org.onosproject.net.flow.TrafficTreatment; |
| 38 | -import org.onosproject.net.group.DefaultGroupBucket; | 39 | +import org.onosproject.net.flowobjective.DefaultNextObjective; |
| 39 | -import org.onosproject.net.group.DefaultGroupDescription; | 40 | +import org.onosproject.net.flowobjective.FlowObjectiveService; |
| 41 | +import org.onosproject.net.flowobjective.NextObjective; | ||
| 40 | import org.onosproject.net.group.DefaultGroupKey; | 42 | import org.onosproject.net.group.DefaultGroupKey; |
| 41 | -import org.onosproject.net.group.Group; | ||
| 42 | -import org.onosproject.net.group.GroupBucket; | ||
| 43 | -import org.onosproject.net.group.GroupBuckets; | ||
| 44 | -import org.onosproject.net.group.GroupDescription; | ||
| 45 | -import org.onosproject.net.group.GroupEvent; | ||
| 46 | import org.onosproject.net.group.GroupKey; | 43 | import org.onosproject.net.group.GroupKey; |
| 47 | -import org.onosproject.net.group.GroupListener; | ||
| 48 | -import org.onosproject.net.group.GroupService; | ||
| 49 | import org.onosproject.net.link.LinkService; | 44 | import org.onosproject.net.link.LinkService; |
| 50 | import org.slf4j.Logger; | 45 | import org.slf4j.Logger; |
| 51 | 46 | ||
| 52 | /** | 47 | /** |
| 53 | - * Default ECMP group handler creation module. This | 48 | + * Default ECMP group handler creation module. This component creates a set of |
| 54 | - * component creates a set of ECMP groups for every neighbor | 49 | + * ECMP groups for every neighbor that this device is connected to based on |
| 55 | - * that this device is connected to based on whether the | 50 | + * whether the current device is an edge device or a transit device. |
| 56 | - * current device is an edge device or a transit device. | ||
| 57 | */ | 51 | */ |
| 58 | public class DefaultGroupHandler { | 52 | public class DefaultGroupHandler { |
| 59 | protected final Logger log = getLogger(getClass()); | 53 | protected final Logger log = getLogger(getClass()); |
| ... | @@ -66,88 +60,78 @@ public class DefaultGroupHandler { | ... | @@ -66,88 +60,78 @@ public class DefaultGroupHandler { |
| 66 | protected final boolean isEdgeRouter; | 60 | protected final boolean isEdgeRouter; |
| 67 | protected final MacAddress nodeMacAddr; | 61 | protected final MacAddress nodeMacAddr; |
| 68 | protected LinkService linkService; | 62 | protected LinkService linkService; |
| 69 | - protected GroupService groupService; | 63 | + protected FlowObjectiveService flowObjectiveService; |
| 70 | 64 | ||
| 71 | protected HashMap<DeviceId, Set<PortNumber>> devicePortMap = | 65 | protected HashMap<DeviceId, Set<PortNumber>> devicePortMap = |
| 72 | new HashMap<DeviceId, Set<PortNumber>>(); | 66 | new HashMap<DeviceId, Set<PortNumber>>(); |
| 73 | protected HashMap<PortNumber, DeviceId> portDeviceMap = | 67 | protected HashMap<PortNumber, DeviceId> portDeviceMap = |
| 74 | new HashMap<PortNumber, DeviceId>(); | 68 | new HashMap<PortNumber, DeviceId>(); |
| 69 | + protected HashMap<GroupKey, Integer> deviceNextObjectiveIds = | ||
| 70 | + new HashMap<GroupKey, Integer>(); | ||
| 71 | + protected Random rand = new Random(); | ||
| 75 | 72 | ||
| 76 | - private GroupListener listener = new InternalGroupListener(); | ||
| 77 | protected KryoNamespace.Builder kryo = new KryoNamespace.Builder() | 73 | protected KryoNamespace.Builder kryo = new KryoNamespace.Builder() |
| 78 | - .register(URI.class) | 74 | + .register(URI.class).register(HashSet.class) |
| 79 | - .register(HashSet.class) | 75 | + .register(DeviceId.class).register(PortNumber.class) |
| 80 | - .register(DeviceId.class) | 76 | + .register(NeighborSet.class).register(PolicyGroupIdentifier.class) |
| 81 | - .register(PortNumber.class) | 77 | + .register(PolicyGroupParams.class) |
| 82 | - .register(NeighborSet.class) | 78 | + .register(GroupBucketIdentifier.class) |
| 83 | - .register(PolicyGroupIdentifier.class) | 79 | + .register(GroupBucketIdentifier.BucketOutputType.class); |
| 84 | - .register(PolicyGroupParams.class) | 80 | + |
| 85 | - .register(GroupBucketIdentifier.class) | 81 | + protected DefaultGroupHandler(DeviceId deviceId, ApplicationId appId, |
| 86 | - .register(GroupBucketIdentifier.BucketOutputType.class); | 82 | + DeviceProperties config, |
| 87 | - | 83 | + LinkService linkService, |
| 88 | - protected DefaultGroupHandler(DeviceId deviceId, | 84 | + FlowObjectiveService flowObjService) { |
| 89 | - ApplicationId appId, | ||
| 90 | - DeviceProperties config, | ||
| 91 | - LinkService linkService, | ||
| 92 | - GroupService groupService) { | ||
| 93 | this.deviceId = checkNotNull(deviceId); | 85 | this.deviceId = checkNotNull(deviceId); |
| 94 | this.appId = checkNotNull(appId); | 86 | this.appId = checkNotNull(appId); |
| 95 | this.deviceConfig = checkNotNull(config); | 87 | this.deviceConfig = checkNotNull(config); |
| 96 | this.linkService = checkNotNull(linkService); | 88 | this.linkService = checkNotNull(linkService); |
| 97 | - this.groupService = checkNotNull(groupService); | ||
| 98 | allSegmentIds = checkNotNull(config.getAllDeviceSegmentIds()); | 89 | allSegmentIds = checkNotNull(config.getAllDeviceSegmentIds()); |
| 99 | nodeSegmentId = config.getSegmentId(deviceId); | 90 | nodeSegmentId = config.getSegmentId(deviceId); |
| 100 | isEdgeRouter = config.isEdgeDevice(deviceId); | 91 | isEdgeRouter = config.isEdgeDevice(deviceId); |
| 101 | nodeMacAddr = checkNotNull(config.getDeviceMac(deviceId)); | 92 | nodeMacAddr = checkNotNull(config.getDeviceMac(deviceId)); |
| 102 | - | 93 | + this.flowObjectiveService = flowObjService; |
| 103 | - this.groupService.addListener(listener); | ||
| 104 | 94 | ||
| 105 | populateNeighborMaps(); | 95 | populateNeighborMaps(); |
| 106 | } | 96 | } |
| 107 | 97 | ||
| 108 | /** | 98 | /** |
| 109 | - * Creates a group handler object based on the type of device. If | 99 | + * Creates a group handler object based on the type of device. If device is |
| 110 | - * device is of edge type it returns edge group handler, else it | 100 | + * of edge type it returns edge group handler, else it returns transit group |
| 111 | - * returns transit group handler. | 101 | + * handler. |
| 112 | * | 102 | * |
| 113 | * @param deviceId device identifier | 103 | * @param deviceId device identifier |
| 114 | * @param appId application identifier | 104 | * @param appId application identifier |
| 115 | * @param config interface to retrieve the device properties | 105 | * @param config interface to retrieve the device properties |
| 116 | * @param linkService link service object | 106 | * @param linkService link service object |
| 117 | - * @param groupService group service object | 107 | + * @param flowObjService flow objective service object |
| 118 | * @return default group handler type | 108 | * @return default group handler type |
| 119 | */ | 109 | */ |
| 120 | public static DefaultGroupHandler createGroupHandler(DeviceId deviceId, | 110 | public static DefaultGroupHandler createGroupHandler(DeviceId deviceId, |
| 121 | - ApplicationId appId, | 111 | + ApplicationId appId, |
| 122 | - DeviceProperties config, | 112 | + DeviceProperties config, |
| 123 | - LinkService linkService, | 113 | + LinkService linkService, |
| 124 | - GroupService groupService) { | 114 | + FlowObjectiveService flowObjService) { |
| 125 | if (config.isEdgeDevice(deviceId)) { | 115 | if (config.isEdgeDevice(deviceId)) { |
| 126 | - return new DefaultEdgeGroupHandler(deviceId, | 116 | + return new DefaultEdgeGroupHandler(deviceId, appId, config, |
| 127 | - appId, | 117 | + linkService, flowObjService); |
| 128 | - config, | ||
| 129 | - linkService, | ||
| 130 | - groupService); | ||
| 131 | } else { | 118 | } else { |
| 132 | - return new DefaultTransitGroupHandler(deviceId, | 119 | + return new DefaultTransitGroupHandler(deviceId, appId, config, |
| 133 | - appId, | 120 | + linkService, flowObjService); |
| 134 | - config, | ||
| 135 | - linkService, | ||
| 136 | - groupService); | ||
| 137 | } | 121 | } |
| 138 | } | 122 | } |
| 139 | 123 | ||
| 140 | /** | 124 | /** |
| 141 | - * Creates the auto created groups for this device based on the | 125 | + * Creates the auto created groups for this device based on the current |
| 142 | - * current snapshot of the topology. | 126 | + * snapshot of the topology. |
| 143 | */ | 127 | */ |
| 144 | - //Empty implementations to be overridden by derived classes | 128 | + // Empty implementations to be overridden by derived classes |
| 145 | public void createGroups() { | 129 | public void createGroups() { |
| 146 | } | 130 | } |
| 147 | 131 | ||
| 148 | /** | 132 | /** |
| 149 | - * Performs group creation or update procedures when a new link | 133 | + * Performs group creation or update procedures when a new link is |
| 150 | - * is discovered on this device. | 134 | + * discovered on this device. |
| 151 | * | 135 | * |
| 152 | * @param newLink new neighbor link | 136 | * @param newLink new neighbor link |
| 153 | */ | 137 | */ |
| ... | @@ -158,16 +142,14 @@ public class DefaultGroupHandler { | ... | @@ -158,16 +142,14 @@ public class DefaultGroupHandler { |
| 158 | return; | 142 | return; |
| 159 | } | 143 | } |
| 160 | 144 | ||
| 161 | - | ||
| 162 | if (!newLink.src().deviceId().equals(deviceId)) { | 145 | if (!newLink.src().deviceId().equals(deviceId)) { |
| 163 | log.warn("linkUp: deviceId{} doesn't match with link src{}", | 146 | log.warn("linkUp: deviceId{} doesn't match with link src{}", |
| 164 | - deviceId, | 147 | + deviceId, newLink.src().deviceId()); |
| 165 | - newLink.src().deviceId()); | ||
| 166 | return; | 148 | return; |
| 167 | } | 149 | } |
| 168 | 150 | ||
| 169 | - log.debug("Device {} linkUp at local port {} to neighbor {}", | 151 | + log.debug("Device {} linkUp at local port {} to neighbor {}", deviceId, |
| 170 | - deviceId, newLink.src().port(), newLink.dst().deviceId()); | 152 | + newLink.src().port(), newLink.dst().deviceId()); |
| 171 | if (devicePortMap.get(newLink.dst().deviceId()) == null) { | 153 | if (devicePortMap.get(newLink.dst().deviceId()) == null) { |
| 172 | // New Neighbor | 154 | // New Neighbor |
| 173 | newNeighbor(newLink); | 155 | newNeighbor(newLink); |
| ... | @@ -178,8 +160,7 @@ public class DefaultGroupHandler { | ... | @@ -178,8 +160,7 @@ public class DefaultGroupHandler { |
| 178 | } | 160 | } |
| 179 | 161 | ||
| 180 | /** | 162 | /** |
| 181 | - * Performs group recovery procedures when a port goes down | 163 | + * Performs group recovery procedures when a port goes down on this device. |
| 182 | - * on this device. | ||
| 183 | * | 164 | * |
| 184 | * @param port port number that has gone down | 165 | * @param port port number that has gone down |
| 185 | */ | 166 | */ |
| ... | @@ -188,35 +169,34 @@ public class DefaultGroupHandler { | ... | @@ -188,35 +169,34 @@ public class DefaultGroupHandler { |
| 188 | log.warn("portDown: unknown port"); | 169 | log.warn("portDown: unknown port"); |
| 189 | return; | 170 | return; |
| 190 | } | 171 | } |
| 191 | - log.debug("Device {} portDown {} to neighbor {}", | 172 | + log.debug("Device {} portDown {} to neighbor {}", deviceId, port, |
| 192 | - deviceId, port, portDeviceMap.get(port)); | 173 | + portDeviceMap.get(port)); |
| 193 | - Set<NeighborSet> nsSet = computeImpactedNeighborsetForPortEvent( | 174 | + Set<NeighborSet> nsSet = computeImpactedNeighborsetForPortEvent(portDeviceMap |
| 194 | - portDeviceMap.get(port), | 175 | + .get(port), |
| 195 | - devicePortMap.keySet()); | 176 | + devicePortMap |
| 177 | + .keySet()); | ||
| 196 | for (NeighborSet ns : nsSet) { | 178 | for (NeighborSet ns : nsSet) { |
| 197 | // Create the bucket to be removed | 179 | // Create the bucket to be removed |
| 198 | - TrafficTreatment.Builder tBuilder = | 180 | + TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment |
| 199 | - DefaultTrafficTreatment.builder(); | 181 | + .builder(); |
| 200 | tBuilder.setOutput(port) | 182 | tBuilder.setOutput(port) |
| 201 | - .setEthDst(deviceConfig.getDeviceMac( | 183 | + .setEthDst(deviceConfig.getDeviceMac(portDeviceMap |
| 202 | - portDeviceMap.get(port))) | 184 | + .get(port))).setEthSrc(nodeMacAddr); |
| 203 | - .setEthSrc(nodeMacAddr); | ||
| 204 | if (ns.getEdgeLabel() != NeighborSet.NO_EDGE_LABEL) { | 185 | if (ns.getEdgeLabel() != NeighborSet.NO_EDGE_LABEL) { |
| 205 | - tBuilder.pushMpls() | 186 | + tBuilder.pushMpls().setMpls(MplsLabel.mplsLabel(ns |
| 206 | - .setMpls(MplsLabel.mplsLabel(ns.getEdgeLabel())); | 187 | + .getEdgeLabel())); |
| 207 | } | 188 | } |
| 208 | - GroupBucket removeBucket = DefaultGroupBucket. | 189 | + /* |
| 209 | - createSelectGroupBucket(tBuilder.build()); | 190 | + * GroupBucket removeBucket = DefaultGroupBucket. |
| 210 | - GroupBuckets removeBuckets = new GroupBuckets( | 191 | + * createSelectGroupBucket(tBuilder.build()); GroupBuckets |
| 211 | - Arrays.asList(removeBucket)); | 192 | + * removeBuckets = new GroupBuckets( Arrays.asList(removeBucket)); |
| 212 | - log.debug("portDown in device{}: " | 193 | + * log.debug("portDown in device{}: " + |
| 213 | - + "groupService.removeBucketsFromGroup " | 194 | + * "groupService.removeBucketsFromGroup " + "for neighborset{}", |
| 214 | - + "for neighborset{}", deviceId, ns); | 195 | + * deviceId, ns); groupService.removeBucketsFromGroup(deviceId, |
| 215 | - groupService.removeBucketsFromGroup(deviceId, | 196 | + * getGroupKey(ns), removeBuckets, getGroupKey(ns), appId); |
| 216 | - getGroupKey(ns), | 197 | + */ |
| 217 | - removeBuckets, | 198 | + //TODO: Use next objective API to update the previously created |
| 218 | - getGroupKey(ns), | 199 | + //next objectives. |
| 219 | - appId); | ||
| 220 | } | 200 | } |
| 221 | 201 | ||
| 222 | devicePortMap.get(portDeviceMap.get(port)).remove(port); | 202 | devicePortMap.get(portDeviceMap.get(port)).remove(port); |
| ... | @@ -224,33 +204,44 @@ public class DefaultGroupHandler { | ... | @@ -224,33 +204,44 @@ public class DefaultGroupHandler { |
| 224 | } | 204 | } |
| 225 | 205 | ||
| 226 | /** | 206 | /** |
| 227 | - * Returns a group associated with the key. | 207 | + * Returns the next objective associated with the neighborset. |
| 208 | + * If there is no next objective for this neighborset, this API | ||
| 209 | + * would create a next objective and return. | ||
| 228 | * | 210 | * |
| 229 | - * @param key cookie associated with the group | 211 | + * @param ns neighborset |
| 230 | - * @return group if found or null | 212 | + * @return int if found or -1 |
| 231 | */ | 213 | */ |
| 232 | - public Group getGroup(GroupKey key) { | 214 | + public int getNextObjectiveId(NeighborSet ns) { |
| 233 | - return groupService.getGroup(deviceId, key); | 215 | + Integer nextId = deviceNextObjectiveIds.get(getGroupKey(ns)); |
| 216 | + if (nextId == null) { | ||
| 217 | + createGroupsFromNeighborsets(Collections.singleton(ns)); | ||
| 218 | + nextId = deviceNextObjectiveIds.get(getGroupKey(ns)); | ||
| 219 | + if (nextId == null) { | ||
| 220 | + log.warn("getNextObjectiveId: unable to create next objective"); | ||
| 221 | + return -1; | ||
| 222 | + } | ||
| 223 | + } | ||
| 224 | + return nextId.intValue(); | ||
| 234 | } | 225 | } |
| 235 | 226 | ||
| 236 | - //Empty implementation | 227 | + // Empty implementation |
| 237 | protected void newNeighbor(Link newLink) { | 228 | protected void newNeighbor(Link newLink) { |
| 238 | } | 229 | } |
| 239 | 230 | ||
| 240 | - //Empty implementation | 231 | + // Empty implementation |
| 241 | protected void newPortToExistingNeighbor(Link newLink) { | 232 | protected void newPortToExistingNeighbor(Link newLink) { |
| 242 | } | 233 | } |
| 243 | 234 | ||
| 244 | - //Empty implementation | 235 | + // Empty implementation |
| 245 | - protected Set<NeighborSet> computeImpactedNeighborsetForPortEvent( | 236 | + protected Set<NeighborSet> |
| 246 | - DeviceId impactedNeighbor, | 237 | + computeImpactedNeighborsetForPortEvent(DeviceId impactedNeighbor, |
| 247 | - Set<DeviceId> updatedNeighbors) { | 238 | + Set<DeviceId> updatedNeighbors) { |
| 248 | return null; | 239 | return null; |
| 249 | } | 240 | } |
| 250 | 241 | ||
| 251 | private void populateNeighborMaps() { | 242 | private void populateNeighborMaps() { |
| 252 | Set<Link> outgoingLinks = linkService.getDeviceEgressLinks(deviceId); | 243 | Set<Link> outgoingLinks = linkService.getDeviceEgressLinks(deviceId); |
| 253 | - for (Link link:outgoingLinks) { | 244 | + for (Link link : outgoingLinks) { |
| 254 | if (link.type() != Link.Type.DIRECT) { | 245 | if (link.type() != Link.Type.DIRECT) { |
| 255 | continue; | 246 | continue; |
| 256 | } | 247 | } |
| ... | @@ -258,7 +249,8 @@ public class DefaultGroupHandler { | ... | @@ -258,7 +249,8 @@ public class DefaultGroupHandler { |
| 258 | } | 249 | } |
| 259 | } | 250 | } |
| 260 | 251 | ||
| 261 | - protected void addNeighborAtPort(DeviceId neighborId, PortNumber portToNeighbor) { | 252 | + protected void addNeighborAtPort(DeviceId neighborId, |
| 253 | + PortNumber portToNeighbor) { | ||
| 262 | // Update DeviceToPort database | 254 | // Update DeviceToPort database |
| 263 | log.debug("Device {} addNeighborAtPort: neighbor {} at port {}", | 255 | log.debug("Device {} addNeighborAtPort: neighbor {} at port {}", |
| 264 | deviceId, neighborId, portToNeighbor); | 256 | deviceId, neighborId, portToNeighbor); |
| ... | @@ -276,8 +268,7 @@ public class DefaultGroupHandler { | ... | @@ -276,8 +268,7 @@ public class DefaultGroupHandler { |
| 276 | } | 268 | } |
| 277 | } | 269 | } |
| 278 | 270 | ||
| 279 | - protected Set<Set<DeviceId>> | 271 | + protected Set<Set<DeviceId>> getPowerSetOfNeighbors(Set<DeviceId> neighbors) { |
| 280 | - getPowerSetOfNeighbors(Set<DeviceId> neighbors) { | ||
| 281 | List<DeviceId> list = new ArrayList<DeviceId>(neighbors); | 272 | List<DeviceId> list = new ArrayList<DeviceId>(neighbors); |
| 282 | Set<Set<DeviceId>> sets = new HashSet<Set<DeviceId>>(); | 273 | Set<Set<DeviceId>> sets = new HashSet<Set<DeviceId>>(); |
| 283 | // get the number of elements in the neighbors | 274 | // get the number of elements in the neighbors |
| ... | @@ -304,15 +295,14 @@ public class DefaultGroupHandler { | ... | @@ -304,15 +295,14 @@ public class DefaultGroupHandler { |
| 304 | return (deviceConfig.getSegmentId(deviceId) == sId); | 295 | return (deviceConfig.getSegmentId(deviceId) == sId); |
| 305 | } | 296 | } |
| 306 | 297 | ||
| 307 | - protected List<Integer> getSegmentIdsTobePairedWithNeighborSet( | 298 | + protected List<Integer> getSegmentIdsTobePairedWithNeighborSet(Set<DeviceId> neighbors) { |
| 308 | - Set<DeviceId> neighbors) { | ||
| 309 | 299 | ||
| 310 | List<Integer> nsSegmentIds = new ArrayList<Integer>(); | 300 | List<Integer> nsSegmentIds = new ArrayList<Integer>(); |
| 311 | 301 | ||
| 312 | // Always pair up with no edge label | 302 | // Always pair up with no edge label |
| 313 | - //If (neighbors.size() == 1) { | 303 | + // If (neighbors.size() == 1) { |
| 314 | nsSegmentIds.add(-1); | 304 | nsSegmentIds.add(-1); |
| 315 | - //} | 305 | + // } |
| 316 | 306 | ||
| 317 | // Filter out SegmentIds matching with the | 307 | // Filter out SegmentIds matching with the |
| 318 | // nodes in the combo | 308 | // nodes in the combo |
| ... | @@ -338,70 +328,28 @@ public class DefaultGroupHandler { | ... | @@ -338,70 +328,28 @@ public class DefaultGroupHandler { |
| 338 | 328 | ||
| 339 | protected void createGroupsFromNeighborsets(Set<NeighborSet> nsSet) { | 329 | protected void createGroupsFromNeighborsets(Set<NeighborSet> nsSet) { |
| 340 | for (NeighborSet ns : nsSet) { | 330 | for (NeighborSet ns : nsSet) { |
| 341 | - // Create the bucket array from the neighbor set | 331 | + int nextId = flowObjectiveService.allocateNextId(); |
| 342 | - List<GroupBucket> buckets = new ArrayList<GroupBucket>(); | 332 | + NextObjective.Builder nextObjBuilder = DefaultNextObjective |
| 333 | + .builder().withId(nextId) | ||
| 334 | + .withType(NextObjective.Type.HASHED).fromApp(appId); | ||
| 343 | for (DeviceId d : ns.getDeviceIds()) { | 335 | for (DeviceId d : ns.getDeviceIds()) { |
| 344 | for (PortNumber sp : devicePortMap.get(d)) { | 336 | for (PortNumber sp : devicePortMap.get(d)) { |
| 345 | - TrafficTreatment.Builder tBuilder = | 337 | + TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment |
| 346 | - DefaultTrafficTreatment.builder(); | 338 | + .builder(); |
| 347 | tBuilder.setOutput(sp) | 339 | tBuilder.setOutput(sp) |
| 348 | .setEthDst(deviceConfig.getDeviceMac(d)) | 340 | .setEthDst(deviceConfig.getDeviceMac(d)) |
| 349 | .setEthSrc(nodeMacAddr); | 341 | .setEthSrc(nodeMacAddr); |
| 350 | if (ns.getEdgeLabel() != NeighborSet.NO_EDGE_LABEL) { | 342 | if (ns.getEdgeLabel() != NeighborSet.NO_EDGE_LABEL) { |
| 351 | - tBuilder.pushMpls() | 343 | + tBuilder.pushMpls().setMpls(MplsLabel.mplsLabel(ns |
| 352 | - .setMpls(MplsLabel. | 344 | + .getEdgeLabel())); |
| 353 | - mplsLabel(ns.getEdgeLabel())); | ||
| 354 | } | 345 | } |
| 355 | - buckets.add(DefaultGroupBucket.createSelectGroupBucket( | 346 | + nextObjBuilder.addTreatment(tBuilder.build()); |
| 356 | - tBuilder.build())); | ||
| 357 | } | 347 | } |
| 358 | } | 348 | } |
| 359 | - GroupBuckets groupBuckets = new GroupBuckets(buckets); | ||
| 360 | - GroupDescription newGroupDesc = new DefaultGroupDescription( | ||
| 361 | - deviceId, | ||
| 362 | - Group.Type.SELECT, | ||
| 363 | - groupBuckets, | ||
| 364 | - getGroupKey(ns), | ||
| 365 | - appId); | ||
| 366 | - log.debug("createGroupsFromNeighborsets: " | ||
| 367 | - + "groupService.addGroup for neighborset{}", ns); | ||
| 368 | - groupService.addGroup(newGroupDesc); | ||
| 369 | - } | ||
| 370 | - } | ||
| 371 | - | ||
| 372 | - protected void handleGroupEvent(GroupEvent event) { | ||
| 373 | - switch (event.type()) { | ||
| 374 | - case GROUP_ADDED: | ||
| 375 | - log.debug("Received GROUP_ADDED from group service " | ||
| 376 | - + "for device {} with group key{} with id{}", | ||
| 377 | - event.subject().deviceId(), | ||
| 378 | - event.subject().appCookie(), | ||
| 379 | - event.subject().id()); | ||
| 380 | - break; | ||
| 381 | - case GROUP_UPDATED: | ||
| 382 | - log.trace("Received GROUP_UPDATED from group service " | ||
| 383 | - + "for device {} with group key{} with id{}", | ||
| 384 | - event.subject().deviceId(), | ||
| 385 | - event.subject().appCookie(), | ||
| 386 | - event.subject().id()); | ||
| 387 | - break; | ||
| 388 | - case GROUP_REMOVED: | ||
| 389 | - log.debug("Received GROUP_REMOVED from group service " | ||
| 390 | - + "for device {} with group key{} with id{}", | ||
| 391 | - event.subject().deviceId(), | ||
| 392 | - event.subject().appCookie(), | ||
| 393 | - event.subject().id()); | ||
| 394 | - break; | ||
| 395 | - default: | ||
| 396 | - break; | ||
| 397 | - } | ||
| 398 | - } | ||
| 399 | - | ||
| 400 | - private class InternalGroupListener implements GroupListener { | ||
| 401 | 349 | ||
| 402 | - @Override | 350 | + NextObjective nextObj = nextObjBuilder.add(); |
| 403 | - public void event(GroupEvent event) { | 351 | + flowObjectiveService.next(deviceId, nextObj); |
| 404 | - handleGroupEvent(event); | 352 | + deviceNextObjectiveIds.put(getGroupKey(ns), nextId); |
| 405 | } | 353 | } |
| 406 | } | 354 | } |
| 407 | 355 | ... | ... |
| ... | @@ -15,7 +15,6 @@ | ... | @@ -15,7 +15,6 @@ |
| 15 | */ | 15 | */ |
| 16 | package org.onosproject.segmentrouting.grouphandler; | 16 | package org.onosproject.segmentrouting.grouphandler; |
| 17 | 17 | ||
| 18 | -import java.util.Arrays; | ||
| 19 | import java.util.HashSet; | 18 | import java.util.HashSet; |
| 20 | import java.util.Set; | 19 | import java.util.Set; |
| 21 | 20 | ||
| ... | @@ -25,10 +24,7 @@ import org.onosproject.net.DeviceId; | ... | @@ -25,10 +24,7 @@ import org.onosproject.net.DeviceId; |
| 25 | import org.onosproject.net.Link; | 24 | import org.onosproject.net.Link; |
| 26 | import org.onosproject.net.flow.DefaultTrafficTreatment; | 25 | import org.onosproject.net.flow.DefaultTrafficTreatment; |
| 27 | import org.onosproject.net.flow.TrafficTreatment; | 26 | import org.onosproject.net.flow.TrafficTreatment; |
| 28 | -import org.onosproject.net.group.DefaultGroupBucket; | 27 | +import org.onosproject.net.flowobjective.FlowObjectiveService; |
| 29 | -import org.onosproject.net.group.GroupBucket; | ||
| 30 | -import org.onosproject.net.group.GroupBuckets; | ||
| 31 | -import org.onosproject.net.group.GroupService; | ||
| 32 | import org.onosproject.net.link.LinkService; | 28 | import org.onosproject.net.link.LinkService; |
| 33 | 29 | ||
| 34 | /** | 30 | /** |
| ... | @@ -49,8 +45,8 @@ public class DefaultTransitGroupHandler extends DefaultGroupHandler { | ... | @@ -49,8 +45,8 @@ public class DefaultTransitGroupHandler extends DefaultGroupHandler { |
| 49 | ApplicationId appId, | 45 | ApplicationId appId, |
| 50 | DeviceProperties config, | 46 | DeviceProperties config, |
| 51 | LinkService linkService, | 47 | LinkService linkService, |
| 52 | - GroupService groupService) { | 48 | + FlowObjectiveService flowObjService) { |
| 53 | - super(deviceId, appId, config, linkService, groupService); | 49 | + super(deviceId, appId, config, linkService, flowObjService); |
| 54 | } | 50 | } |
| 55 | 51 | ||
| 56 | @Override | 52 | @Override |
| ... | @@ -118,7 +114,7 @@ public class DefaultTransitGroupHandler extends DefaultGroupHandler { | ... | @@ -118,7 +114,7 @@ public class DefaultTransitGroupHandler extends DefaultGroupHandler { |
| 118 | .setMpls(MplsLabel. | 114 | .setMpls(MplsLabel. |
| 119 | mplsLabel(ns.getEdgeLabel())); | 115 | mplsLabel(ns.getEdgeLabel())); |
| 120 | } | 116 | } |
| 121 | - GroupBucket updatedBucket = DefaultGroupBucket. | 117 | + /*GroupBucket updatedBucket = DefaultGroupBucket. |
| 122 | createSelectGroupBucket(tBuilder.build()); | 118 | createSelectGroupBucket(tBuilder.build()); |
| 123 | GroupBuckets updatedBuckets = new GroupBuckets( | 119 | GroupBuckets updatedBuckets = new GroupBuckets( |
| 124 | Arrays.asList(updatedBucket)); | 120 | Arrays.asList(updatedBucket)); |
| ... | @@ -128,7 +124,8 @@ public class DefaultTransitGroupHandler extends DefaultGroupHandler { | ... | @@ -128,7 +124,8 @@ public class DefaultTransitGroupHandler extends DefaultGroupHandler { |
| 128 | getGroupKey(ns), | 124 | getGroupKey(ns), |
| 129 | updatedBuckets, | 125 | updatedBuckets, |
| 130 | getGroupKey(ns), | 126 | getGroupKey(ns), |
| 131 | - appId); | 127 | + appId);*/ |
| 128 | + //TODO: Use nextObjective APIs to update the next objective | ||
| 132 | } | 129 | } |
| 133 | } | 130 | } |
| 134 | 131 | ... | ... |
| ... | @@ -25,19 +25,13 @@ import java.util.List; | ... | @@ -25,19 +25,13 @@ import java.util.List; |
| 25 | 25 | ||
| 26 | import org.onlab.packet.MplsLabel; | 26 | import org.onlab.packet.MplsLabel; |
| 27 | import org.onosproject.core.ApplicationId; | 27 | import org.onosproject.core.ApplicationId; |
| 28 | -import org.onosproject.core.GroupId; | ||
| 29 | import org.onosproject.segmentrouting.grouphandler.GroupBucketIdentifier.BucketOutputType; | 28 | import org.onosproject.segmentrouting.grouphandler.GroupBucketIdentifier.BucketOutputType; |
| 30 | import org.onosproject.net.DeviceId; | 29 | import org.onosproject.net.DeviceId; |
| 31 | import org.onosproject.net.PortNumber; | 30 | import org.onosproject.net.PortNumber; |
| 32 | import org.onosproject.net.flow.DefaultTrafficTreatment; | 31 | import org.onosproject.net.flow.DefaultTrafficTreatment; |
| 33 | import org.onosproject.net.flow.TrafficTreatment; | 32 | import org.onosproject.net.flow.TrafficTreatment; |
| 34 | -import org.onosproject.net.group.DefaultGroupBucket; | 33 | +import org.onosproject.net.flowobjective.FlowObjectiveService; |
| 35 | -import org.onosproject.net.group.DefaultGroupDescription; | ||
| 36 | import org.onosproject.net.group.GroupBucket; | 34 | import org.onosproject.net.group.GroupBucket; |
| 37 | -import org.onosproject.net.group.GroupBuckets; | ||
| 38 | -import org.onosproject.net.group.GroupDescription; | ||
| 39 | -import org.onosproject.net.group.GroupEvent; | ||
| 40 | -import org.onosproject.net.group.GroupService; | ||
| 41 | import org.onosproject.net.link.LinkService; | 35 | import org.onosproject.net.link.LinkService; |
| 42 | import org.slf4j.Logger; | 36 | import org.slf4j.Logger; |
| 43 | 37 | ||
| ... | @@ -58,14 +52,14 @@ public class PolicyGroupHandler extends DefaultGroupHandler { | ... | @@ -58,14 +52,14 @@ public class PolicyGroupHandler extends DefaultGroupHandler { |
| 58 | * @param appId application identifier | 52 | * @param appId application identifier |
| 59 | * @param config interface to retrieve the device properties | 53 | * @param config interface to retrieve the device properties |
| 60 | * @param linkService link service object | 54 | * @param linkService link service object |
| 61 | - * @param groupService group service object | 55 | + * @param flowObjService flow objective service object |
| 62 | */ | 56 | */ |
| 63 | public PolicyGroupHandler(DeviceId deviceId, | 57 | public PolicyGroupHandler(DeviceId deviceId, |
| 64 | ApplicationId appId, | 58 | ApplicationId appId, |
| 65 | DeviceProperties config, | 59 | DeviceProperties config, |
| 66 | LinkService linkService, | 60 | LinkService linkService, |
| 67 | - GroupService groupService) { | 61 | + FlowObjectiveService flowObjService) { |
| 68 | - super(deviceId, appId, config, linkService, groupService); | 62 | + super(deviceId, appId, config, linkService, flowObjService); |
| 69 | } | 63 | } |
| 70 | 64 | ||
| 71 | public PolicyGroupIdentifier createPolicyGroupChain(String id, | 65 | public PolicyGroupIdentifier createPolicyGroupChain(String id, |
| ... | @@ -111,15 +105,16 @@ public class PolicyGroupHandler extends DefaultGroupHandler { | ... | @@ -111,15 +105,16 @@ public class PolicyGroupHandler extends DefaultGroupHandler { |
| 111 | .setEthSrc(nodeMacAddr) | 105 | .setEthSrc(nodeMacAddr) |
| 112 | .pushMpls() | 106 | .pushMpls() |
| 113 | .setMpls(MplsLabel.mplsLabel(label)); | 107 | .setMpls(MplsLabel.mplsLabel(label)); |
| 114 | - outBuckets.add(DefaultGroupBucket. | 108 | + /*outBuckets.add(DefaultGroupBucket. |
| 115 | createSelectGroupBucket(tBuilder.build())); | 109 | createSelectGroupBucket(tBuilder.build())); |
| 116 | GroupDescription desc = new | 110 | GroupDescription desc = new |
| 117 | DefaultGroupDescription(deviceId, | 111 | DefaultGroupDescription(deviceId, |
| 118 | GroupDescription.Type.INDIRECT, | 112 | GroupDescription.Type.INDIRECT, |
| 119 | new GroupBuckets(outBuckets)); | 113 | new GroupBuckets(outBuckets)); |
| 120 | - //TODO: BoS | 114 | + //TODO: BoS*/ |
| 121 | previousGroupkey = key; | 115 | previousGroupkey = key; |
| 122 | - groupService.addGroup(desc); | 116 | + //groupService.addGroup(desc); |
| 117 | + //TODO: Use nextObjective APIs here | ||
| 123 | } else { | 118 | } else { |
| 124 | // Intermediate Groups | 119 | // Intermediate Groups |
| 125 | GroupBucketIdentifier bucketId = | 120 | GroupBucketIdentifier bucketId = |
| ... | @@ -179,20 +174,22 @@ public class PolicyGroupHandler extends DefaultGroupHandler { | ... | @@ -179,20 +174,22 @@ public class PolicyGroupHandler extends DefaultGroupHandler { |
| 179 | .setMpls(MplsLabel.mplsLabel(bucketId.label())); | 174 | .setMpls(MplsLabel.mplsLabel(bucketId.label())); |
| 180 | } | 175 | } |
| 181 | //TODO: BoS | 176 | //TODO: BoS |
| 182 | - outBuckets.add(DefaultGroupBucket. | 177 | + /*outBuckets.add(DefaultGroupBucket. |
| 183 | - createSelectGroupBucket(tBuilder.build())); | 178 | + createSelectGroupBucket(tBuilder.build()));*/ |
| 184 | } | 179 | } |
| 185 | - GroupDescription desc = new | 180 | + /*GroupDescription desc = new |
| 186 | DefaultGroupDescription(deviceId, | 181 | DefaultGroupDescription(deviceId, |
| 187 | GroupDescription.Type.SELECT, | 182 | GroupDescription.Type.SELECT, |
| 188 | new GroupBuckets(outBuckets)); | 183 | new GroupBuckets(outBuckets)); |
| 189 | - groupService.addGroup(desc); | 184 | + groupService.addGroup(desc);*/ |
| 185 | + //TODO: Use nextObjective APIs here | ||
| 190 | } | 186 | } |
| 191 | } | 187 | } |
| 192 | return innermostGroupkey; | 188 | return innermostGroupkey; |
| 193 | } | 189 | } |
| 194 | 190 | ||
| 195 | - @Override | 191 | + //TODO: Use nextObjective APIs to handle the group chains |
| 192 | + /*@Override | ||
| 196 | protected void handleGroupEvent(GroupEvent event) { | 193 | protected void handleGroupEvent(GroupEvent event) { |
| 197 | if (event.type() == GroupEvent.Type.GROUP_ADDED) { | 194 | if (event.type() == GroupEvent.Type.GROUP_ADDED) { |
| 198 | if (dependentGroups.get(event.subject().appCookie()) != null) { | 195 | if (dependentGroups.get(event.subject().appCookie()) != null) { |
| ... | @@ -253,7 +250,7 @@ public class PolicyGroupHandler extends DefaultGroupHandler { | ... | @@ -253,7 +250,7 @@ public class PolicyGroupHandler extends DefaultGroupHandler { |
| 253 | } | 250 | } |
| 254 | } | 251 | } |
| 255 | } | 252 | } |
| 256 | - } | 253 | + }*/ |
| 257 | 254 | ||
| 258 | public PolicyGroupIdentifier generatePolicyGroupKey(String id, | 255 | public PolicyGroupIdentifier generatePolicyGroupKey(String id, |
| 259 | List<PolicyGroupParams> params) { | 256 | List<PolicyGroupParams> params) { |
| ... | @@ -343,9 +340,10 @@ public class PolicyGroupHandler extends DefaultGroupHandler { | ... | @@ -343,9 +340,10 @@ public class PolicyGroupHandler extends DefaultGroupHandler { |
| 343 | groupsToBeDeleted.add(bucketId.outGroup()); | 340 | groupsToBeDeleted.add(bucketId.outGroup()); |
| 344 | } | 341 | } |
| 345 | } | 342 | } |
| 346 | - groupService.removeGroup(deviceId, | 343 | + /*groupService.removeGroup(deviceId, |
| 347 | getGroupKey(innerMostGroupKey), | 344 | getGroupKey(innerMostGroupKey), |
| 348 | - appId); | 345 | + appId);*/ |
| 346 | + //TODO: Use nextObjective APIs here | ||
| 349 | it.remove(); | 347 | it.remove(); |
| 350 | } | 348 | } |
| 351 | } | 349 | } | ... | ... |
| ... | @@ -356,10 +356,14 @@ public final class DefaultTrafficTreatment implements TrafficTreatment { | ... | @@ -356,10 +356,14 @@ public final class DefaultTrafficTreatment implements TrafficTreatment { |
| 356 | 356 | ||
| 357 | @Override | 357 | @Override |
| 358 | public TrafficTreatment build() { | 358 | public TrafficTreatment build() { |
| 359 | - if (deferred.size() == 0 && immediate.size() == 0 | 359 | + //Don't add DROP instruction by default when instruction |
| 360 | - && table == null && !clear) { | 360 | + //set is empty. This will be handled in DefaultSingleTablePipeline |
| 361 | - drop(); | 361 | + //driver. |
| 362 | - } | 362 | + |
| 363 | + //if (deferred.size() == 0 && immediate.size() == 0 | ||
| 364 | + // && table == null && !clear) { | ||
| 365 | + // drop(); | ||
| 366 | + //} | ||
| 363 | return new DefaultTrafficTreatment(deferred, immediate, table, clear); | 367 | return new DefaultTrafficTreatment(deferred, immediate, table, clear); |
| 364 | } | 368 | } |
| 365 | 369 | ... | ... |
| ... | @@ -16,6 +16,7 @@ | ... | @@ -16,6 +16,7 @@ |
| 16 | package org.onosproject.driver.pipeline; | 16 | package org.onosproject.driver.pipeline; |
| 17 | 17 | ||
| 18 | import com.google.common.util.concurrent.SettableFuture; | 18 | import com.google.common.util.concurrent.SettableFuture; |
| 19 | + | ||
| 19 | import org.onlab.osgi.ServiceDirectory; | 20 | import org.onlab.osgi.ServiceDirectory; |
| 20 | import org.onosproject.core.DefaultGroupId; | 21 | import org.onosproject.core.DefaultGroupId; |
| 21 | import org.onosproject.net.DeviceId; | 22 | import org.onosproject.net.DeviceId; |
| ... | @@ -23,11 +24,14 @@ import org.onosproject.net.behaviour.Pipeliner; | ... | @@ -23,11 +24,14 @@ import org.onosproject.net.behaviour.Pipeliner; |
| 23 | import org.onosproject.net.behaviour.PipelinerContext; | 24 | import org.onosproject.net.behaviour.PipelinerContext; |
| 24 | import org.onosproject.net.driver.AbstractHandlerBehaviour; | 25 | import org.onosproject.net.driver.AbstractHandlerBehaviour; |
| 25 | import org.onosproject.net.flow.DefaultFlowRule; | 26 | import org.onosproject.net.flow.DefaultFlowRule; |
| 27 | +import org.onosproject.net.flow.DefaultTrafficTreatment; | ||
| 26 | import org.onosproject.net.flow.FlowRule; | 28 | import org.onosproject.net.flow.FlowRule; |
| 27 | import org.onosproject.net.flow.FlowRuleOperations; | 29 | import org.onosproject.net.flow.FlowRuleOperations; |
| 28 | import org.onosproject.net.flow.FlowRuleOperationsContext; | 30 | import org.onosproject.net.flow.FlowRuleOperationsContext; |
| 29 | import org.onosproject.net.flow.FlowRuleService; | 31 | import org.onosproject.net.flow.FlowRuleService; |
| 30 | import org.onosproject.net.flow.TrafficSelector; | 32 | import org.onosproject.net.flow.TrafficSelector; |
| 33 | +import org.onosproject.net.flow.TrafficTreatment; | ||
| 34 | +import org.onosproject.net.flow.instructions.Instructions; | ||
| 31 | import org.onosproject.net.flowobjective.FilteringObjective; | 35 | import org.onosproject.net.flowobjective.FilteringObjective; |
| 32 | import org.onosproject.net.flowobjective.ForwardingObjective; | 36 | import org.onosproject.net.flowobjective.ForwardingObjective; |
| 33 | import org.onosproject.net.flowobjective.NextObjective; | 37 | import org.onosproject.net.flowobjective.NextObjective; |
| ... | @@ -70,9 +74,18 @@ public class DefaultSingleTablePipeline extends AbstractHandlerBehaviour impleme | ... | @@ -70,9 +74,18 @@ public class DefaultSingleTablePipeline extends AbstractHandlerBehaviour impleme |
| 70 | } | 74 | } |
| 71 | 75 | ||
| 72 | TrafficSelector selector = fwd.selector(); | 76 | TrafficSelector selector = fwd.selector(); |
| 77 | + TrafficTreatment treatment = fwd.treatment(); | ||
| 78 | + if ((fwd.treatment().deferred().size() == 0) && | ||
| 79 | + (fwd.treatment().immediate().size() == 0) && | ||
| 80 | + (fwd.treatment().tableTransition() == null) && | ||
| 81 | + (!fwd.treatment().clearedDeferred())) { | ||
| 82 | + TrafficTreatment.Builder flowTreatment = DefaultTrafficTreatment.builder(); | ||
| 83 | + flowTreatment.add(Instructions.createDrop()); | ||
| 84 | + treatment = flowTreatment.build(); | ||
| 85 | + } | ||
| 73 | 86 | ||
| 74 | FlowRule rule = new DefaultFlowRule(deviceId, selector, | 87 | FlowRule rule = new DefaultFlowRule(deviceId, selector, |
| 75 | - fwd.treatment(), | 88 | + treatment, |
| 76 | fwd.priority(), fwd.appId(), | 89 | fwd.priority(), fwd.appId(), |
| 77 | new DefaultGroupId(fwd.id()), | 90 | new DefaultGroupId(fwd.id()), |
| 78 | fwd.timeout(), fwd.permanent()); | 91 | fwd.timeout(), fwd.permanent()); | ... | ... |
| 1 | +/* | ||
| 2 | + * Copyright 2015 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * 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 | ||
| 7 | + * | ||
| 8 | + * 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. | ||
| 15 | + */ | ||
| 16 | +package org.onosproject.driver.pipeline; | ||
| 17 | + | ||
| 18 | +import static org.onlab.util.Tools.groupedThreads; | ||
| 19 | +import static org.slf4j.LoggerFactory.getLogger; | ||
| 20 | + | ||
| 21 | +import com.google.common.cache.Cache; | ||
| 22 | +import com.google.common.cache.CacheBuilder; | ||
| 23 | +import com.google.common.cache.RemovalCause; | ||
| 24 | +import com.google.common.cache.RemovalNotification; | ||
| 25 | + | ||
| 26 | +import org.onlab.osgi.ServiceDirectory; | ||
| 27 | +import org.onlab.packet.Ethernet; | ||
| 28 | +import org.onlab.packet.VlanId; | ||
| 29 | +import org.onlab.util.KryoNamespace; | ||
| 30 | +import org.onosproject.core.ApplicationId; | ||
| 31 | +import org.onosproject.core.CoreService; | ||
| 32 | +import org.onosproject.net.DeviceId; | ||
| 33 | +import org.onosproject.net.PortNumber; | ||
| 34 | +import org.onosproject.net.behaviour.NextGroup; | ||
| 35 | +import org.onosproject.net.behaviour.Pipeliner; | ||
| 36 | +import org.onosproject.net.behaviour.PipelinerContext; | ||
| 37 | +import org.onosproject.net.driver.AbstractHandlerBehaviour; | ||
| 38 | +import org.onosproject.net.flow.DefaultFlowRule; | ||
| 39 | +import org.onosproject.net.flow.DefaultTrafficSelector; | ||
| 40 | +import org.onosproject.net.flow.DefaultTrafficTreatment; | ||
| 41 | +import org.onosproject.net.flow.FlowRule; | ||
| 42 | +import org.onosproject.net.flow.FlowRuleOperations; | ||
| 43 | +import org.onosproject.net.flow.FlowRuleOperationsContext; | ||
| 44 | +import org.onosproject.net.flow.FlowRuleService; | ||
| 45 | +import org.onosproject.net.flow.TrafficSelector; | ||
| 46 | +import org.onosproject.net.flow.TrafficTreatment; | ||
| 47 | +import org.onosproject.net.flow.criteria.Criteria; | ||
| 48 | +import org.onosproject.net.flow.criteria.Criterion; | ||
| 49 | +import org.onosproject.net.flow.criteria.EthCriterion; | ||
| 50 | +import org.onosproject.net.flow.criteria.EthTypeCriterion; | ||
| 51 | +import org.onosproject.net.flow.criteria.IPCriterion; | ||
| 52 | +import org.onosproject.net.flow.criteria.MplsCriterion; | ||
| 53 | +import org.onosproject.net.flow.criteria.PortCriterion; | ||
| 54 | +import org.onosproject.net.flow.criteria.VlanIdCriterion; | ||
| 55 | +import org.onosproject.net.flow.instructions.Instruction; | ||
| 56 | +import org.onosproject.net.flowobjective.FilteringObjective; | ||
| 57 | +import org.onosproject.net.flowobjective.FlowObjectiveStore; | ||
| 58 | +import org.onosproject.net.flowobjective.ForwardingObjective; | ||
| 59 | +import org.onosproject.net.flowobjective.NextObjective; | ||
| 60 | +import org.onosproject.net.flowobjective.Objective; | ||
| 61 | +import org.onosproject.net.flowobjective.ObjectiveError; | ||
| 62 | +import org.onosproject.net.group.DefaultGroupBucket; | ||
| 63 | +import org.onosproject.net.group.DefaultGroupDescription; | ||
| 64 | +import org.onosproject.net.group.DefaultGroupKey; | ||
| 65 | +import org.onosproject.net.group.Group; | ||
| 66 | +import org.onosproject.net.group.GroupBucket; | ||
| 67 | +import org.onosproject.net.group.GroupBuckets; | ||
| 68 | +import org.onosproject.net.group.GroupDescription; | ||
| 69 | +import org.onosproject.net.group.GroupEvent; | ||
| 70 | +import org.onosproject.net.group.GroupKey; | ||
| 71 | +import org.onosproject.net.group.GroupListener; | ||
| 72 | +import org.onosproject.net.group.GroupService; | ||
| 73 | +import org.slf4j.Logger; | ||
| 74 | + | ||
| 75 | +import java.util.ArrayList; | ||
| 76 | +import java.util.Collection; | ||
| 77 | +import java.util.Collections; | ||
| 78 | +import java.util.List; | ||
| 79 | +import java.util.Set; | ||
| 80 | +import java.util.concurrent.Executors; | ||
| 81 | +import java.util.concurrent.ScheduledExecutorService; | ||
| 82 | +import java.util.concurrent.TimeUnit; | ||
| 83 | +import java.util.stream.Collectors; | ||
| 84 | + | ||
| 85 | +/** | ||
| 86 | + * Driver for SPRING-OPEN pipeline. | ||
| 87 | + */ | ||
| 88 | +public class SpringOpenTTP extends AbstractHandlerBehaviour | ||
| 89 | + implements Pipeliner { | ||
| 90 | + | ||
| 91 | + // Default table ID - compatible with CpqD switch | ||
| 92 | + private static final int TABLE_VLAN = 0; | ||
| 93 | + private static final int TABLE_TMAC = 1; | ||
| 94 | + private static final int TABLE_IPV4_UNICAST = 2; | ||
| 95 | + private static final int TABLE_MPLS = 3; | ||
| 96 | + private static final int TABLE_ACL = 5; | ||
| 97 | + | ||
| 98 | + /** | ||
| 99 | + * Set the default values. These variables will get overwritten based on the | ||
| 100 | + * switch vendor type | ||
| 101 | + */ | ||
| 102 | + protected int vlanTableId = TABLE_VLAN; | ||
| 103 | + protected int tmacTableId = TABLE_TMAC; | ||
| 104 | + protected int ipv4UnicastTableId = TABLE_IPV4_UNICAST; | ||
| 105 | + protected int mplsTableId = TABLE_MPLS; | ||
| 106 | + protected int aclTableId = TABLE_ACL; | ||
| 107 | + | ||
| 108 | + protected final Logger log = getLogger(getClass()); | ||
| 109 | + | ||
| 110 | + private ServiceDirectory serviceDirectory; | ||
| 111 | + private FlowRuleService flowRuleService; | ||
| 112 | + private CoreService coreService; | ||
| 113 | + protected GroupService groupService; | ||
| 114 | + protected FlowObjectiveStore flowObjectiveStore; | ||
| 115 | + protected DeviceId deviceId; | ||
| 116 | + private ApplicationId appId; | ||
| 117 | + | ||
| 118 | + private Cache<GroupKey, NextObjective> pendingGroups; | ||
| 119 | + | ||
| 120 | + private ScheduledExecutorService groupChecker = Executors | ||
| 121 | + .newScheduledThreadPool(2, | ||
| 122 | + groupedThreads("onos/pipeliner", | ||
| 123 | + "spring-open-%d")); | ||
| 124 | + protected KryoNamespace appKryo = new KryoNamespace.Builder() | ||
| 125 | + .register(GroupKey.class).register(DefaultGroupKey.class) | ||
| 126 | + .register(SegmentRoutingGroup.class).register(byte[].class).build(); | ||
| 127 | + | ||
| 128 | + @Override | ||
| 129 | + public void init(DeviceId deviceId, PipelinerContext context) { | ||
| 130 | + this.serviceDirectory = context.directory(); | ||
| 131 | + this.deviceId = deviceId; | ||
| 132 | + | ||
| 133 | + pendingGroups = CacheBuilder | ||
| 134 | + .newBuilder() | ||
| 135 | + .expireAfterWrite(20, TimeUnit.SECONDS) | ||
| 136 | + .removalListener((RemovalNotification<GroupKey, NextObjective> notification) -> { | ||
| 137 | + if (notification.getCause() == RemovalCause.EXPIRED) { | ||
| 138 | + fail(notification.getValue(), | ||
| 139 | + ObjectiveError.GROUPINSTALLATIONFAILED); | ||
| 140 | + } | ||
| 141 | + }).build(); | ||
| 142 | + | ||
| 143 | + groupChecker.scheduleAtFixedRate(new GroupChecker(), 0, 500, | ||
| 144 | + TimeUnit.MILLISECONDS); | ||
| 145 | + | ||
| 146 | + coreService = serviceDirectory.get(CoreService.class); | ||
| 147 | + flowRuleService = serviceDirectory.get(FlowRuleService.class); | ||
| 148 | + groupService = serviceDirectory.get(GroupService.class); | ||
| 149 | + flowObjectiveStore = context.store(); | ||
| 150 | + | ||
| 151 | + groupService.addListener(new InnerGroupListener()); | ||
| 152 | + | ||
| 153 | + appId = coreService | ||
| 154 | + .registerApplication("org.onosproject.driver.SpringOpenTTP"); | ||
| 155 | + | ||
| 156 | + setTableMissEntries(); | ||
| 157 | + log.info("Spring Open TTP driver initialized"); | ||
| 158 | + } | ||
| 159 | + | ||
| 160 | + @Override | ||
| 161 | + public void filter(FilteringObjective filteringObjective) { | ||
| 162 | + if (filteringObjective.type() == FilteringObjective.Type.PERMIT) { | ||
| 163 | + log.debug("processing PERMIT filter objective"); | ||
| 164 | + processFilter(filteringObjective, | ||
| 165 | + filteringObjective.op() == Objective.Operation.ADD, | ||
| 166 | + filteringObjective.appId()); | ||
| 167 | + } else { | ||
| 168 | + log.debug("filter objective other than PERMIT not supported"); | ||
| 169 | + fail(filteringObjective, ObjectiveError.UNSUPPORTED); | ||
| 170 | + } | ||
| 171 | + } | ||
| 172 | + | ||
| 173 | + @Override | ||
| 174 | + public void forward(ForwardingObjective fwd) { | ||
| 175 | + Collection<FlowRule> rules; | ||
| 176 | + FlowRuleOperations.Builder flowBuilder = FlowRuleOperations.builder(); | ||
| 177 | + | ||
| 178 | + rules = processForward(fwd); | ||
| 179 | + switch (fwd.op()) { | ||
| 180 | + case ADD: | ||
| 181 | + rules.stream().filter(rule -> rule != null) | ||
| 182 | + .forEach(flowBuilder::add); | ||
| 183 | + break; | ||
| 184 | + case REMOVE: | ||
| 185 | + rules.stream().filter(rule -> rule != null) | ||
| 186 | + .forEach(flowBuilder::remove); | ||
| 187 | + break; | ||
| 188 | + default: | ||
| 189 | + fail(fwd, ObjectiveError.UNKNOWN); | ||
| 190 | + log.warn("Unknown forwarding type {}", fwd.op()); | ||
| 191 | + } | ||
| 192 | + | ||
| 193 | + flowRuleService.apply(flowBuilder | ||
| 194 | + .build(new FlowRuleOperationsContext() { | ||
| 195 | + @Override | ||
| 196 | + public void onSuccess(FlowRuleOperations ops) { | ||
| 197 | + pass(fwd); | ||
| 198 | + } | ||
| 199 | + | ||
| 200 | + @Override | ||
| 201 | + public void onError(FlowRuleOperations ops) { | ||
| 202 | + fail(fwd, ObjectiveError.FLOWINSTALLATIONFAILED); | ||
| 203 | + } | ||
| 204 | + })); | ||
| 205 | + | ||
| 206 | + } | ||
| 207 | + | ||
| 208 | + @Override | ||
| 209 | + public void next(NextObjective nextObjective) { | ||
| 210 | + switch (nextObjective.type()) { | ||
| 211 | + case SIMPLE: | ||
| 212 | + log.debug("processing SIMPLE next objective"); | ||
| 213 | + Collection<TrafficTreatment> treatments = nextObjective.next(); | ||
| 214 | + if (treatments.size() == 1) { | ||
| 215 | + TrafficTreatment treatment = treatments.iterator().next(); | ||
| 216 | + GroupBucket bucket = DefaultGroupBucket | ||
| 217 | + .createIndirectGroupBucket(treatment); | ||
| 218 | + final GroupKey key = new DefaultGroupKey( | ||
| 219 | + appKryo.serialize(nextObjective | ||
| 220 | + .id())); | ||
| 221 | + GroupDescription groupDescription = new DefaultGroupDescription( | ||
| 222 | + deviceId, | ||
| 223 | + GroupDescription.Type.INDIRECT, | ||
| 224 | + new GroupBuckets( | ||
| 225 | + Collections.singletonList(bucket)), | ||
| 226 | + key, | ||
| 227 | + nextObjective.appId()); | ||
| 228 | + groupService.addGroup(groupDescription); | ||
| 229 | + pendingGroups.put(key, nextObjective); | ||
| 230 | + } | ||
| 231 | + break; | ||
| 232 | + case HASHED: | ||
| 233 | + log.debug("processing HASHED next objective"); | ||
| 234 | + List<GroupBucket> buckets = nextObjective | ||
| 235 | + .next() | ||
| 236 | + .stream() | ||
| 237 | + .map((treatment) -> DefaultGroupBucket | ||
| 238 | + .createSelectGroupBucket(treatment)) | ||
| 239 | + .collect(Collectors.toList()); | ||
| 240 | + if (!buckets.isEmpty()) { | ||
| 241 | + final GroupKey key = new DefaultGroupKey( | ||
| 242 | + appKryo.serialize(nextObjective | ||
| 243 | + .id())); | ||
| 244 | + GroupDescription groupDescription = new DefaultGroupDescription( | ||
| 245 | + deviceId, | ||
| 246 | + GroupDescription.Type.SELECT, | ||
| 247 | + new GroupBuckets(buckets), | ||
| 248 | + key, | ||
| 249 | + nextObjective.appId()); | ||
| 250 | + groupService.addGroup(groupDescription); | ||
| 251 | + pendingGroups.put(key, nextObjective); | ||
| 252 | + } | ||
| 253 | + break; | ||
| 254 | + case BROADCAST: | ||
| 255 | + case FAILOVER: | ||
| 256 | + log.debug("BROADCAST and FAILOVER next objectives not supported"); | ||
| 257 | + fail(nextObjective, ObjectiveError.UNSUPPORTED); | ||
| 258 | + log.warn("Unsupported next objective type {}", nextObjective.type()); | ||
| 259 | + break; | ||
| 260 | + default: | ||
| 261 | + fail(nextObjective, ObjectiveError.UNKNOWN); | ||
| 262 | + log.warn("Unknown next objective type {}", nextObjective.type()); | ||
| 263 | + } | ||
| 264 | + | ||
| 265 | + } | ||
| 266 | + | ||
| 267 | + private Collection<FlowRule> processForward(ForwardingObjective fwd) { | ||
| 268 | + switch (fwd.flag()) { | ||
| 269 | + case SPECIFIC: | ||
| 270 | + return processSpecific(fwd); | ||
| 271 | + case VERSATILE: | ||
| 272 | + return processVersatile(fwd); | ||
| 273 | + default: | ||
| 274 | + fail(fwd, ObjectiveError.UNKNOWN); | ||
| 275 | + log.warn("Unknown forwarding flag {}", fwd.flag()); | ||
| 276 | + } | ||
| 277 | + return Collections.emptySet(); | ||
| 278 | + } | ||
| 279 | + | ||
| 280 | + private Collection<FlowRule> processVersatile(ForwardingObjective fwd) { | ||
| 281 | + fail(fwd, ObjectiveError.UNSUPPORTED); | ||
| 282 | + return Collections.emptySet(); | ||
| 283 | + } | ||
| 284 | + | ||
| 285 | + protected Collection<FlowRule> processSpecific(ForwardingObjective fwd) { | ||
| 286 | + log.debug("Processing specific"); | ||
| 287 | + TrafficSelector selector = fwd.selector(); | ||
| 288 | + EthTypeCriterion ethType = (EthTypeCriterion) selector | ||
| 289 | + .getCriterion(Criterion.Type.ETH_TYPE); | ||
| 290 | + if ((ethType == null) || | ||
| 291 | + ((((short) ethType.ethType()) != Ethernet.TYPE_IPV4) && | ||
| 292 | + (((short) ethType.ethType()) != Ethernet.MPLS_UNICAST))) { | ||
| 293 | + log.debug("processSpecific: Unsupported " | ||
| 294 | + + "forwarding objective criteraia"); | ||
| 295 | + fail(fwd, ObjectiveError.UNSUPPORTED); | ||
| 296 | + return Collections.emptySet(); | ||
| 297 | + } | ||
| 298 | + | ||
| 299 | + TrafficSelector.Builder filteredSelectorBuilder = | ||
| 300 | + DefaultTrafficSelector.builder(); | ||
| 301 | + int forTableId = -1; | ||
| 302 | + if (((short) ethType.ethType()) == Ethernet.TYPE_IPV4) { | ||
| 303 | + filteredSelectorBuilder = filteredSelectorBuilder | ||
| 304 | + .matchEthType(Ethernet.TYPE_IPV4) | ||
| 305 | + .matchIPDst(((IPCriterion) selector | ||
| 306 | + .getCriterion(Criterion.Type.IPV4_DST)) | ||
| 307 | + .ip()); | ||
| 308 | + forTableId = ipv4UnicastTableId; | ||
| 309 | + log.debug("processing IPv4 specific forwarding objective"); | ||
| 310 | + } else { | ||
| 311 | + filteredSelectorBuilder = filteredSelectorBuilder | ||
| 312 | + .matchEthType(Ethernet.MPLS_UNICAST) | ||
| 313 | + .matchMplsLabel(((MplsCriterion) | ||
| 314 | + selector.getCriterion(Criterion.Type.MPLS_LABEL)).label()); | ||
| 315 | + //TODO: Add Match for BoS | ||
| 316 | + //if (selector.getCriterion(Criterion.Type.MPLS_BOS) != null) { | ||
| 317 | + //} | ||
| 318 | + forTableId = mplsTableId; | ||
| 319 | + log.debug("processing MPLS specific forwarding objective"); | ||
| 320 | + } | ||
| 321 | + | ||
| 322 | + TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment | ||
| 323 | + .builder(); | ||
| 324 | + if (fwd.treatment() != null) { | ||
| 325 | + for (Instruction i : fwd.treatment().allInstructions()) { | ||
| 326 | + treatmentBuilder.add(i); | ||
| 327 | + } | ||
| 328 | + } | ||
| 329 | + | ||
| 330 | + //TODO: Analyze the forwarding objective here to make | ||
| 331 | + //device specific decision such as no ECMP groups in Dell | ||
| 332 | + //switches. | ||
| 333 | + if (fwd.nextId() != null) { | ||
| 334 | + NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId()); | ||
| 335 | + | ||
| 336 | + if (next != null) { | ||
| 337 | + GroupKey key = appKryo.deserialize(next.data()); | ||
| 338 | + | ||
| 339 | + Group group = groupService.getGroup(deviceId, key); | ||
| 340 | + | ||
| 341 | + if (group == null) { | ||
| 342 | + log.warn("The group left!"); | ||
| 343 | + fail(fwd, ObjectiveError.GROUPMISSING); | ||
| 344 | + return Collections.emptySet(); | ||
| 345 | + } | ||
| 346 | + treatmentBuilder.group(group.id()); | ||
| 347 | + log.debug("Adding OUTGROUP action"); | ||
| 348 | + } | ||
| 349 | + } | ||
| 350 | + | ||
| 351 | + TrafficSelector filteredSelector = filteredSelectorBuilder.build(); | ||
| 352 | + TrafficTreatment treatment = treatmentBuilder.transition(aclTableId) | ||
| 353 | + .build(); | ||
| 354 | + | ||
| 355 | + FlowRule.Builder ruleBuilder = DefaultFlowRule.builder() | ||
| 356 | + .fromApp(fwd.appId()).withPriority(fwd.priority()) | ||
| 357 | + .forDevice(deviceId).withSelector(filteredSelector) | ||
| 358 | + .withTreatment(treatment); | ||
| 359 | + | ||
| 360 | + if (fwd.permanent()) { | ||
| 361 | + ruleBuilder.makePermanent(); | ||
| 362 | + } else { | ||
| 363 | + ruleBuilder.makeTemporary(fwd.timeout()); | ||
| 364 | + } | ||
| 365 | + | ||
| 366 | + ruleBuilder.forTable(forTableId); | ||
| 367 | + return Collections.singletonList(ruleBuilder.build()); | ||
| 368 | + | ||
| 369 | + } | ||
| 370 | + | ||
| 371 | + protected List<FlowRule> processEthDstFilter(Criterion c, | ||
| 372 | + FilteringObjective filt, | ||
| 373 | + ApplicationId applicationId) { | ||
| 374 | + List<FlowRule> rules = new ArrayList<FlowRule>(); | ||
| 375 | + EthCriterion e = (EthCriterion) c; | ||
| 376 | + TrafficSelector.Builder selectorIp = DefaultTrafficSelector | ||
| 377 | + .builder(); | ||
| 378 | + TrafficTreatment.Builder treatmentIp = DefaultTrafficTreatment | ||
| 379 | + .builder(); | ||
| 380 | + selectorIp.matchEthDst(e.mac()); | ||
| 381 | + selectorIp.matchEthType(Ethernet.TYPE_IPV4); | ||
| 382 | + treatmentIp.transition(ipv4UnicastTableId); | ||
| 383 | + FlowRule ruleIp = DefaultFlowRule.builder().forDevice(deviceId) | ||
| 384 | + .withSelector(selectorIp.build()) | ||
| 385 | + .withTreatment(treatmentIp.build()) | ||
| 386 | + .withPriority(filt.priority()).fromApp(applicationId) | ||
| 387 | + .makePermanent().forTable(tmacTableId).build(); | ||
| 388 | + log.debug("adding IP ETH rule for MAC: {}", e.mac()); | ||
| 389 | + rules.add(ruleIp); | ||
| 390 | + | ||
| 391 | + TrafficSelector.Builder selectorMpls = DefaultTrafficSelector | ||
| 392 | + .builder(); | ||
| 393 | + TrafficTreatment.Builder treatmentMpls = DefaultTrafficTreatment | ||
| 394 | + .builder(); | ||
| 395 | + selectorMpls.matchEthDst(e.mac()); | ||
| 396 | + selectorMpls.matchEthType(Ethernet.MPLS_UNICAST); | ||
| 397 | + treatmentMpls.transition(mplsTableId); | ||
| 398 | + FlowRule ruleMpls = DefaultFlowRule.builder() | ||
| 399 | + .forDevice(deviceId).withSelector(selectorMpls.build()) | ||
| 400 | + .withTreatment(treatmentMpls.build()) | ||
| 401 | + .withPriority(filt.priority()).fromApp(applicationId) | ||
| 402 | + .makePermanent().forTable(tmacTableId).build(); | ||
| 403 | + log.debug("adding MPLS ETH rule for MAC: {}", e.mac()); | ||
| 404 | + rules.add(ruleMpls); | ||
| 405 | + | ||
| 406 | + return rules; | ||
| 407 | + } | ||
| 408 | + | ||
| 409 | + private void processFilter(FilteringObjective filt, boolean install, | ||
| 410 | + ApplicationId applicationId) { | ||
| 411 | + // This driver only processes filtering criteria defined with switch | ||
| 412 | + // ports as the key | ||
| 413 | + PortCriterion p; | ||
| 414 | + if (!filt.key().equals(Criteria.dummy()) | ||
| 415 | + && filt.key().type() == Criterion.Type.IN_PORT) { | ||
| 416 | + p = (PortCriterion) filt.key(); | ||
| 417 | + } else { | ||
| 418 | + log.warn("No key defined in filtering objective from app: {}. Not" | ||
| 419 | + + "processing filtering objective", applicationId); | ||
| 420 | + fail(filt, ObjectiveError.UNKNOWN); | ||
| 421 | + return; | ||
| 422 | + } | ||
| 423 | + // convert filtering conditions for switch-intfs into flowrules | ||
| 424 | + FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); | ||
| 425 | + for (Criterion c : filt.conditions()) { | ||
| 426 | + if (c.type() == Criterion.Type.ETH_DST) { | ||
| 427 | + for (FlowRule rule : processEthDstFilter(c, | ||
| 428 | + filt, | ||
| 429 | + applicationId)) { | ||
| 430 | + ops = install ? ops.add(rule) : ops.remove(rule); | ||
| 431 | + } | ||
| 432 | + } else if (c.type() == Criterion.Type.VLAN_VID) { | ||
| 433 | + VlanIdCriterion v = (VlanIdCriterion) c; | ||
| 434 | + log.debug("adding rule for VLAN: {}", v.vlanId()); | ||
| 435 | + TrafficSelector.Builder selector = DefaultTrafficSelector | ||
| 436 | + .builder(); | ||
| 437 | + TrafficTreatment.Builder treatment = DefaultTrafficTreatment | ||
| 438 | + .builder(); | ||
| 439 | + if (v.vlanId() != VlanId.NONE) { | ||
| 440 | + selector.matchVlanId(v.vlanId()); | ||
| 441 | + selector.matchInPort(p.port()); | ||
| 442 | + treatment.deferred().popVlan(); | ||
| 443 | + } | ||
| 444 | + treatment.transition(tmacTableId); | ||
| 445 | + FlowRule rule = DefaultFlowRule.builder().forDevice(deviceId) | ||
| 446 | + .withSelector(selector.build()) | ||
| 447 | + .withTreatment(treatment.build()) | ||
| 448 | + .withPriority(filt.priority()).fromApp(applicationId) | ||
| 449 | + .makePermanent().forTable(vlanTableId).build(); | ||
| 450 | + ops = install ? ops.add(rule) : ops.remove(rule); | ||
| 451 | + } else if (c.type() == Criterion.Type.IPV4_DST) { | ||
| 452 | + IPCriterion ip = (IPCriterion) c; | ||
| 453 | + log.debug("adding rule for IP: {}", ip.ip()); | ||
| 454 | + TrafficSelector.Builder selector = DefaultTrafficSelector | ||
| 455 | + .builder(); | ||
| 456 | + TrafficTreatment.Builder treatment = DefaultTrafficTreatment | ||
| 457 | + .builder(); | ||
| 458 | + selector.matchEthType(Ethernet.TYPE_IPV4); | ||
| 459 | + selector.matchIPDst(ip.ip()); | ||
| 460 | + treatment.transition(aclTableId); | ||
| 461 | + FlowRule rule = DefaultFlowRule.builder().forDevice(deviceId) | ||
| 462 | + .withSelector(selector.build()) | ||
| 463 | + .withTreatment(treatment.build()) | ||
| 464 | + .withPriority(filt.priority()).fromApp(applicationId) | ||
| 465 | + .makePermanent().forTable(ipv4UnicastTableId).build(); | ||
| 466 | + ops = install ? ops.add(rule) : ops.remove(rule); | ||
| 467 | + } else { | ||
| 468 | + log.warn("Driver does not currently process filtering condition" | ||
| 469 | + + " of type: {}", c.type()); | ||
| 470 | + fail(filt, ObjectiveError.UNSUPPORTED); | ||
| 471 | + } | ||
| 472 | + } | ||
| 473 | + // apply filtering flow rules | ||
| 474 | + flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { | ||
| 475 | + @Override | ||
| 476 | + public void onSuccess(FlowRuleOperations ops) { | ||
| 477 | + pass(filt); | ||
| 478 | + log.info("Provisioned tables for segment router"); | ||
| 479 | + } | ||
| 480 | + | ||
| 481 | + @Override | ||
| 482 | + public void onError(FlowRuleOperations ops) { | ||
| 483 | + fail(filt, ObjectiveError.FLOWINSTALLATIONFAILED); | ||
| 484 | + log.info("Failed to provision tables for segment router"); | ||
| 485 | + } | ||
| 486 | + })); | ||
| 487 | + } | ||
| 488 | + | ||
| 489 | + protected void setTableMissEntries() { | ||
| 490 | + // set all table-miss-entries | ||
| 491 | + populateTableMissEntry(vlanTableId, true, false, false, -1); | ||
| 492 | + populateTableMissEntry(tmacTableId, true, false, false, -1); | ||
| 493 | + populateTableMissEntry(ipv4UnicastTableId, false, true, true, | ||
| 494 | + aclTableId); | ||
| 495 | + populateTableMissEntry(mplsTableId, false, true, true, aclTableId); | ||
| 496 | + populateTableMissEntry(aclTableId, false, false, false, -1); | ||
| 497 | + } | ||
| 498 | + | ||
| 499 | + protected void populateTableMissEntry(int tableToAdd, | ||
| 500 | + boolean toControllerNow, | ||
| 501 | + boolean toControllerWrite, | ||
| 502 | + boolean toTable, int tableToSend) { | ||
| 503 | + TrafficSelector selector = DefaultTrafficSelector.builder().build(); | ||
| 504 | + TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder(); | ||
| 505 | + | ||
| 506 | + if (toControllerNow) { | ||
| 507 | + tBuilder.setOutput(PortNumber.CONTROLLER); | ||
| 508 | + } | ||
| 509 | + | ||
| 510 | + if (toControllerWrite) { | ||
| 511 | + tBuilder.deferred().setOutput(PortNumber.CONTROLLER); | ||
| 512 | + } | ||
| 513 | + | ||
| 514 | + if (toTable) { | ||
| 515 | + tBuilder.transition(tableToSend); | ||
| 516 | + } | ||
| 517 | + | ||
| 518 | + FlowRule flow = DefaultFlowRule.builder().forDevice(deviceId) | ||
| 519 | + .withSelector(selector).withTreatment(tBuilder.build()) | ||
| 520 | + .withPriority(0).fromApp(appId).makePermanent() | ||
| 521 | + .forTable(tableToAdd).build(); | ||
| 522 | + | ||
| 523 | + flowRuleService.applyFlowRules(flow); | ||
| 524 | + } | ||
| 525 | + | ||
| 526 | + private void pass(Objective obj) { | ||
| 527 | + if (obj.context().isPresent()) { | ||
| 528 | + obj.context().get().onSuccess(obj); | ||
| 529 | + } | ||
| 530 | + } | ||
| 531 | + | ||
| 532 | + protected void fail(Objective obj, ObjectiveError error) { | ||
| 533 | + if (obj.context().isPresent()) { | ||
| 534 | + obj.context().get().onError(obj, error); | ||
| 535 | + } | ||
| 536 | + } | ||
| 537 | + | ||
| 538 | + private class InnerGroupListener implements GroupListener { | ||
| 539 | + @Override | ||
| 540 | + public void event(GroupEvent event) { | ||
| 541 | + if (event.type() == GroupEvent.Type.GROUP_ADDED) { | ||
| 542 | + GroupKey key = event.subject().appCookie(); | ||
| 543 | + | ||
| 544 | + NextObjective obj = pendingGroups.getIfPresent(key); | ||
| 545 | + if (obj != null) { | ||
| 546 | + flowObjectiveStore | ||
| 547 | + .putNextGroup(obj.id(), | ||
| 548 | + new SegmentRoutingGroup(key)); | ||
| 549 | + pass(obj); | ||
| 550 | + pendingGroups.invalidate(key); | ||
| 551 | + } | ||
| 552 | + } | ||
| 553 | + } | ||
| 554 | + } | ||
| 555 | + | ||
| 556 | + private class GroupChecker implements Runnable { | ||
| 557 | + | ||
| 558 | + @Override | ||
| 559 | + public void run() { | ||
| 560 | + Set<GroupKey> keys = pendingGroups | ||
| 561 | + .asMap() | ||
| 562 | + .keySet() | ||
| 563 | + .stream() | ||
| 564 | + .filter(key -> groupService.getGroup(deviceId, key) != null) | ||
| 565 | + .collect(Collectors.toSet()); | ||
| 566 | + | ||
| 567 | + keys.stream() | ||
| 568 | + .forEach(key -> { | ||
| 569 | + NextObjective obj = pendingGroups | ||
| 570 | + .getIfPresent(key); | ||
| 571 | + if (obj == null) { | ||
| 572 | + return; | ||
| 573 | + } | ||
| 574 | + pass(obj); | ||
| 575 | + pendingGroups.invalidate(key); | ||
| 576 | + flowObjectiveStore.putNextGroup(obj.id(), | ||
| 577 | + new SegmentRoutingGroup( | ||
| 578 | + key)); | ||
| 579 | + }); | ||
| 580 | + } | ||
| 581 | + } | ||
| 582 | + | ||
| 583 | + private class SegmentRoutingGroup implements NextGroup { | ||
| 584 | + | ||
| 585 | + private final GroupKey key; | ||
| 586 | + | ||
| 587 | + public SegmentRoutingGroup(GroupKey key) { | ||
| 588 | + this.key = key; | ||
| 589 | + } | ||
| 590 | + | ||
| 591 | + public GroupKey key() { | ||
| 592 | + return key; | ||
| 593 | + } | ||
| 594 | + | ||
| 595 | + @Override | ||
| 596 | + public byte[] data() { | ||
| 597 | + return appKryo.serialize(key); | ||
| 598 | + } | ||
| 599 | + | ||
| 600 | + } | ||
| 601 | +} |
| 1 | +/* | ||
| 2 | + * Copyright 2015 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * 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 | ||
| 7 | + * | ||
| 8 | + * 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. | ||
| 15 | + */ | ||
| 16 | +package org.onosproject.driver.pipeline; | ||
| 17 | + | ||
| 18 | +import java.util.ArrayList; | ||
| 19 | +import java.util.Collection; | ||
| 20 | +import java.util.Collections; | ||
| 21 | +import java.util.List; | ||
| 22 | + | ||
| 23 | +import org.onlab.packet.Ethernet; | ||
| 24 | +import org.onlab.packet.MacAddress; | ||
| 25 | +import org.onosproject.core.ApplicationId; | ||
| 26 | +import org.onosproject.net.behaviour.NextGroup; | ||
| 27 | +import org.onosproject.net.flow.DefaultFlowRule; | ||
| 28 | +import org.onosproject.net.flow.DefaultTrafficSelector; | ||
| 29 | +import org.onosproject.net.flow.DefaultTrafficTreatment; | ||
| 30 | +import org.onosproject.net.flow.FlowRule; | ||
| 31 | +import org.onosproject.net.flow.TrafficSelector; | ||
| 32 | +import org.onosproject.net.flow.TrafficTreatment; | ||
| 33 | +import org.onosproject.net.flow.criteria.Criterion; | ||
| 34 | +import org.onosproject.net.flow.criteria.EthCriterion; | ||
| 35 | +import org.onosproject.net.flow.criteria.EthTypeCriterion; | ||
| 36 | +import org.onosproject.net.flow.criteria.IPCriterion; | ||
| 37 | +import org.onosproject.net.flow.criteria.MplsCriterion; | ||
| 38 | +import org.onosproject.net.flow.instructions.Instruction; | ||
| 39 | +import org.onosproject.net.flowobjective.FilteringObjective; | ||
| 40 | +import org.onosproject.net.flowobjective.ForwardingObjective; | ||
| 41 | +import org.onosproject.net.flowobjective.ObjectiveError; | ||
| 42 | +import org.onosproject.net.group.Group; | ||
| 43 | +import org.onosproject.net.group.GroupKey; | ||
| 44 | + | ||
| 45 | +/** | ||
| 46 | + * Spring-open driver implementation for Dell hardware switches. | ||
| 47 | + */ | ||
| 48 | +public class SpringOpenTTPDell extends SpringOpenTTP { | ||
| 49 | + | ||
| 50 | + /* Table IDs to be used for Dell Open Segment Routers*/ | ||
| 51 | + private static final int DELL_TABLE_VLAN = 17; | ||
| 52 | + private static final int DELL_TABLE_TMAC = 18; | ||
| 53 | + private static final int DELL_TABLE_IPV4_UNICAST = 30; | ||
| 54 | + private static final int DELL_TABLE_MPLS = 25; | ||
| 55 | + private static final int DELL_TABLE_ACL = 40; | ||
| 56 | + | ||
| 57 | + //TODO: Store this info in the distributed store. | ||
| 58 | + private MacAddress deviceTMac = null; | ||
| 59 | + | ||
| 60 | + public SpringOpenTTPDell() { | ||
| 61 | + super(); | ||
| 62 | + vlanTableId = DELL_TABLE_VLAN; | ||
| 63 | + tmacTableId = DELL_TABLE_TMAC; | ||
| 64 | + ipv4UnicastTableId = DELL_TABLE_IPV4_UNICAST; | ||
| 65 | + mplsTableId = DELL_TABLE_MPLS; | ||
| 66 | + aclTableId = DELL_TABLE_ACL; | ||
| 67 | + } | ||
| 68 | + | ||
| 69 | + @Override | ||
| 70 | + protected void setTableMissEntries() { | ||
| 71 | + // No need to set table-miss-entries in Dell switches | ||
| 72 | + return; | ||
| 73 | + } | ||
| 74 | + | ||
| 75 | + @Override | ||
| 76 | + //Dell switches need ETH_DST based match condition in all IP table entries. | ||
| 77 | + //So this method overrides the default spring-open behavior and adds | ||
| 78 | + //ETH_DST match condition while pushing IP table flow rules | ||
| 79 | + protected Collection<FlowRule> processSpecific(ForwardingObjective fwd) { | ||
| 80 | + log.debug("Processing specific"); | ||
| 81 | + TrafficSelector selector = fwd.selector(); | ||
| 82 | + EthTypeCriterion ethType = (EthTypeCriterion) selector | ||
| 83 | + .getCriterion(Criterion.Type.ETH_TYPE); | ||
| 84 | + if ((ethType == null) || | ||
| 85 | + ((((short) ethType.ethType()) != Ethernet.TYPE_IPV4) && | ||
| 86 | + (((short) ethType.ethType()) != Ethernet.MPLS_UNICAST))) { | ||
| 87 | + log.debug("processSpecific: Unsupported " | ||
| 88 | + + "forwarding objective criteraia"); | ||
| 89 | + fail(fwd, ObjectiveError.UNSUPPORTED); | ||
| 90 | + return Collections.emptySet(); | ||
| 91 | + } | ||
| 92 | + | ||
| 93 | + TrafficSelector.Builder filteredSelectorBuilder = | ||
| 94 | + DefaultTrafficSelector.builder(); | ||
| 95 | + int forTableId = -1; | ||
| 96 | + if (((short) ethType.ethType()) == Ethernet.TYPE_IPV4) { | ||
| 97 | + if (deviceTMac == null) { | ||
| 98 | + log.debug("processSpecific: ETH_DST filtering " | ||
| 99 | + + "objective is not set which is required " | ||
| 100 | + + "before sending a IPv4 forwarding objective"); | ||
| 101 | + //TODO: Map the error to more appropriate error code. | ||
| 102 | + fail(fwd, ObjectiveError.DEVICEMISSING); | ||
| 103 | + return Collections.emptySet(); | ||
| 104 | + } | ||
| 105 | + filteredSelectorBuilder = filteredSelectorBuilder | ||
| 106 | + .matchEthType(Ethernet.TYPE_IPV4) | ||
| 107 | + .matchEthDst(deviceTMac) | ||
| 108 | + .matchIPDst(((IPCriterion) selector | ||
| 109 | + .getCriterion(Criterion.Type.IPV4_DST)) | ||
| 110 | + .ip()); | ||
| 111 | + forTableId = ipv4UnicastTableId; | ||
| 112 | + log.debug("processing IPv4 specific forwarding objective"); | ||
| 113 | + } else { | ||
| 114 | + filteredSelectorBuilder = filteredSelectorBuilder | ||
| 115 | + .matchEthType(Ethernet.MPLS_UNICAST) | ||
| 116 | + .matchMplsLabel(((MplsCriterion) | ||
| 117 | + selector.getCriterion(Criterion.Type.MPLS_LABEL)).label()); | ||
| 118 | + //TODO: Add Match for BoS | ||
| 119 | + //if (selector.getCriterion(Criterion.Type.MPLS_BOS) != null) { | ||
| 120 | + //} | ||
| 121 | + forTableId = mplsTableId; | ||
| 122 | + log.debug("processing MPLS specific forwarding objective"); | ||
| 123 | + } | ||
| 124 | + | ||
| 125 | + TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment | ||
| 126 | + .builder(); | ||
| 127 | + if (fwd.treatment() != null) { | ||
| 128 | + for (Instruction i : fwd.treatment().allInstructions()) { | ||
| 129 | + treatmentBuilder.add(i); | ||
| 130 | + } | ||
| 131 | + } | ||
| 132 | + | ||
| 133 | + if (fwd.nextId() != null) { | ||
| 134 | + NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId()); | ||
| 135 | + | ||
| 136 | + if (next != null) { | ||
| 137 | + GroupKey key = appKryo.deserialize(next.data()); | ||
| 138 | + | ||
| 139 | + Group group = groupService.getGroup(deviceId, key); | ||
| 140 | + | ||
| 141 | + if (group == null) { | ||
| 142 | + log.warn("The group left!"); | ||
| 143 | + fail(fwd, ObjectiveError.GROUPMISSING); | ||
| 144 | + return Collections.emptySet(); | ||
| 145 | + } | ||
| 146 | + treatmentBuilder.group(group.id()); | ||
| 147 | + log.debug("Adding OUTGROUP action"); | ||
| 148 | + } | ||
| 149 | + } | ||
| 150 | + | ||
| 151 | + TrafficSelector filteredSelector = filteredSelectorBuilder.build(); | ||
| 152 | + TrafficTreatment treatment = treatmentBuilder.transition(aclTableId) | ||
| 153 | + .build(); | ||
| 154 | + | ||
| 155 | + FlowRule.Builder ruleBuilder = DefaultFlowRule.builder() | ||
| 156 | + .fromApp(fwd.appId()).withPriority(fwd.priority()) | ||
| 157 | + .forDevice(deviceId).withSelector(filteredSelector) | ||
| 158 | + .withTreatment(treatment); | ||
| 159 | + | ||
| 160 | + if (fwd.permanent()) { | ||
| 161 | + ruleBuilder.makePermanent(); | ||
| 162 | + } else { | ||
| 163 | + ruleBuilder.makeTemporary(fwd.timeout()); | ||
| 164 | + } | ||
| 165 | + | ||
| 166 | + ruleBuilder.forTable(forTableId); | ||
| 167 | + return Collections.singletonList(ruleBuilder.build()); | ||
| 168 | + | ||
| 169 | + } | ||
| 170 | + | ||
| 171 | + @Override | ||
| 172 | + //Dell switches need ETH_DST based match condition in all IP table entries. | ||
| 173 | + //So while processing the ETH_DST based filtering objective, store | ||
| 174 | + //the device MAC to be used locally to use it while pushing the IP rules. | ||
| 175 | + protected List<FlowRule> processEthDstFilter(Criterion c, | ||
| 176 | + FilteringObjective filt, | ||
| 177 | + ApplicationId applicationId) { | ||
| 178 | + List<FlowRule> rules = new ArrayList<FlowRule>(); | ||
| 179 | + EthCriterion e = (EthCriterion) c; | ||
| 180 | + TrafficSelector.Builder selectorIp = DefaultTrafficSelector | ||
| 181 | + .builder(); | ||
| 182 | + TrafficTreatment.Builder treatmentIp = DefaultTrafficTreatment | ||
| 183 | + .builder(); | ||
| 184 | + | ||
| 185 | + // Store device termination Mac to be used in IP flow entries | ||
| 186 | + deviceTMac = e.mac(); | ||
| 187 | + | ||
| 188 | + selectorIp.matchEthDst(e.mac()); | ||
| 189 | + selectorIp.matchEthType(Ethernet.TYPE_IPV4); | ||
| 190 | + treatmentIp.transition(ipv4UnicastTableId); | ||
| 191 | + FlowRule ruleIp = DefaultFlowRule.builder().forDevice(deviceId) | ||
| 192 | + .withSelector(selectorIp.build()) | ||
| 193 | + .withTreatment(treatmentIp.build()) | ||
| 194 | + .withPriority(filt.priority()).fromApp(applicationId) | ||
| 195 | + .makePermanent().forTable(tmacTableId).build(); | ||
| 196 | + log.debug("adding IP ETH rule for MAC: {}", e.mac()); | ||
| 197 | + rules.add(ruleIp); | ||
| 198 | + | ||
| 199 | + TrafficSelector.Builder selectorMpls = DefaultTrafficSelector | ||
| 200 | + .builder(); | ||
| 201 | + TrafficTreatment.Builder treatmentMpls = DefaultTrafficTreatment | ||
| 202 | + .builder(); | ||
| 203 | + selectorMpls.matchEthDst(e.mac()); | ||
| 204 | + selectorMpls.matchEthType(Ethernet.MPLS_UNICAST); | ||
| 205 | + treatmentMpls.transition(mplsTableId); | ||
| 206 | + FlowRule ruleMpls = DefaultFlowRule.builder() | ||
| 207 | + .forDevice(deviceId).withSelector(selectorMpls.build()) | ||
| 208 | + .withTreatment(treatmentMpls.build()) | ||
| 209 | + .withPriority(filt.priority()).fromApp(applicationId) | ||
| 210 | + .makePermanent().forTable(tmacTableId).build(); | ||
| 211 | + log.debug("adding MPLS ETH rule for MAC: {}", e.mac()); | ||
| 212 | + rules.add(ruleMpls); | ||
| 213 | + | ||
| 214 | + return rules; | ||
| 215 | + } | ||
| 216 | + | ||
| 217 | +} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| ... | @@ -23,4 +23,12 @@ | ... | @@ -23,4 +23,12 @@ |
| 23 | <behaviour api="org.onosproject.net.behaviour.Pipeliner" | 23 | <behaviour api="org.onosproject.net.behaviour.Pipeliner" |
| 24 | impl="org.onosproject.driver.pipeline.OVSCorsaPipeline"/> | 24 | impl="org.onosproject.driver.pipeline.OVSCorsaPipeline"/> |
| 25 | </driver> | 25 | </driver> |
| 26 | -</drivers> | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 26 | + <driver name="spring-open-cpqd" manufacturer="Stanford University, Ericsson Research and CPqD Research" hwVersion="OpenFlow 1.3 Reference Userspace Switch" swVersion="Apr 6 2015 16:10:53"> | ||
| 27 | + <behaviour api="org.onosproject.net.behaviour.Pipeliner" | ||
| 28 | + impl="org.onosproject.driver.pipeline.SpringOpenTTP"/> | ||
| 29 | + </driver> | ||
| 30 | + <driver name="spring-open" manufacturer="Dell " hwVersion="OpenFlow switch HW ver. 1.0" swVersion="OpenFlow switch SW ver. 1.0 and 1.3"> | ||
| 31 | + <behaviour api="org.onosproject.net.behaviour.Pipeliner" | ||
| 32 | + impl="org.onosproject.driver.pipeline.SpringOpenTTPDell"/> | ||
| 33 | + </driver> | ||
| 34 | +</drivers> | ... | ... |
| ... | @@ -19,10 +19,11 @@ package org.onosproject.openflow.controller.driver; | ... | @@ -19,10 +19,11 @@ package org.onosproject.openflow.controller.driver; |
| 19 | import java.io.IOException; | 19 | import java.io.IOException; |
| 20 | import java.net.InetSocketAddress; | 20 | import java.net.InetSocketAddress; |
| 21 | import java.net.SocketAddress; | 21 | import java.net.SocketAddress; |
| 22 | -import java.util.Collections; | 22 | +import java.util.ArrayList; |
| 23 | import java.util.List; | 23 | import java.util.List; |
| 24 | import java.util.concurrent.RejectedExecutionException; | 24 | import java.util.concurrent.RejectedExecutionException; |
| 25 | import java.util.concurrent.atomic.AtomicInteger; | 25 | import java.util.concurrent.atomic.AtomicInteger; |
| 26 | +import java.util.stream.Collectors; | ||
| 26 | 27 | ||
| 27 | import org.jboss.netty.channel.Channel; | 28 | import org.jboss.netty.channel.Channel; |
| 28 | import org.onlab.packet.IpAddress; | 29 | import org.onlab.packet.IpAddress; |
| ... | @@ -64,7 +65,7 @@ public abstract class AbstractOpenFlowSwitch implements OpenFlowSwitchDriver { | ... | @@ -64,7 +65,7 @@ public abstract class AbstractOpenFlowSwitch implements OpenFlowSwitchDriver { |
| 64 | 65 | ||
| 65 | private OFVersion ofVersion; | 66 | private OFVersion ofVersion; |
| 66 | 67 | ||
| 67 | - protected OFPortDescStatsReply ports; | 68 | + protected List<OFPortDescStatsReply> ports = new ArrayList<>(); |
| 68 | 69 | ||
| 69 | protected boolean tableFull; | 70 | protected boolean tableFull; |
| 70 | 71 | ||
| ... | @@ -251,7 +252,12 @@ public abstract class AbstractOpenFlowSwitch implements OpenFlowSwitchDriver { | ... | @@ -251,7 +252,12 @@ public abstract class AbstractOpenFlowSwitch implements OpenFlowSwitchDriver { |
| 251 | 252 | ||
| 252 | @Override | 253 | @Override |
| 253 | public void setPortDescReply(OFPortDescStatsReply portDescReply) { | 254 | public void setPortDescReply(OFPortDescStatsReply portDescReply) { |
| 254 | - this.ports = portDescReply; | 255 | + this.ports.add(portDescReply); |
| 256 | + } | ||
| 257 | + | ||
| 258 | + @Override | ||
| 259 | + public void setPortDescReplies(List<OFPortDescStatsReply> portDescReplies) { | ||
| 260 | + this.ports.addAll(portDescReplies); | ||
| 255 | } | 261 | } |
| 256 | 262 | ||
| 257 | @Override | 263 | @Override |
| ... | @@ -379,7 +385,10 @@ public abstract class AbstractOpenFlowSwitch implements OpenFlowSwitchDriver { | ... | @@ -379,7 +385,10 @@ public abstract class AbstractOpenFlowSwitch implements OpenFlowSwitchDriver { |
| 379 | 385 | ||
| 380 | @Override | 386 | @Override |
| 381 | public List<OFPortDesc> getPorts() { | 387 | public List<OFPortDesc> getPorts() { |
| 382 | - return Collections.unmodifiableList(ports.getEntries()); | 388 | + return this.ports.stream() |
| 389 | + .flatMap((portReply) -> (portReply.getEntries().stream())) | ||
| 390 | + .collect(Collectors.toList()); | ||
| 391 | + //return Collections.unmodifiableList(ports.getEntries()); | ||
| 383 | } | 392 | } |
| 384 | 393 | ||
| 385 | @Override | 394 | @Override | ... | ... |
| ... | @@ -137,6 +137,12 @@ public interface OpenFlowSwitchDriver extends OpenFlowSwitch { | ... | @@ -137,6 +137,12 @@ public interface OpenFlowSwitchDriver extends OpenFlowSwitch { |
| 137 | public void setPortDescReply(OFPortDescStatsReply portDescReply); | 137 | public void setPortDescReply(OFPortDescStatsReply portDescReply); |
| 138 | 138 | ||
| 139 | /** | 139 | /** |
| 140 | + * Sets the ports on this switch. | ||
| 141 | + * @param portDescReplies list of port set and descriptions | ||
| 142 | + */ | ||
| 143 | + public void setPortDescReplies(List<OFPortDescStatsReply> portDescReplies); | ||
| 144 | + | ||
| 145 | + /** | ||
| 140 | * Sets the features reply for this switch. | 146 | * Sets the features reply for this switch. |
| 141 | * @param featuresReply the features to set. | 147 | * @param featuresReply the features to set. |
| 142 | */ | 148 | */ | ... | ... |
| ... | @@ -97,7 +97,8 @@ class OFChannelHandler extends IdleStateAwareChannelHandler { | ... | @@ -97,7 +97,8 @@ class OFChannelHandler extends IdleStateAwareChannelHandler { |
| 97 | 97 | ||
| 98 | // Temporary storage for switch-features and port-description | 98 | // Temporary storage for switch-features and port-description |
| 99 | private OFFeaturesReply featuresReply; | 99 | private OFFeaturesReply featuresReply; |
| 100 | - private OFPortDescStatsReply portDescReply; | 100 | + private List<OFPortDescStatsReply> portDescReplies; |
| 101 | + //private OFPortDescStatsReply portDescReply; | ||
| 101 | // a concurrent ArrayList to temporarily store port status messages | 102 | // a concurrent ArrayList to temporarily store port status messages |
| 102 | // before we are ready to deal with them | 103 | // before we are ready to deal with them |
| 103 | private final CopyOnWriteArrayList<OFPortStatus> pendingPortStatusMsg; | 104 | private final CopyOnWriteArrayList<OFPortStatus> pendingPortStatusMsg; |
| ... | @@ -121,6 +122,7 @@ class OFChannelHandler extends IdleStateAwareChannelHandler { | ... | @@ -121,6 +122,7 @@ class OFChannelHandler extends IdleStateAwareChannelHandler { |
| 121 | this.controller = controller; | 122 | this.controller = controller; |
| 122 | this.state = ChannelState.INIT; | 123 | this.state = ChannelState.INIT; |
| 123 | this.pendingPortStatusMsg = new CopyOnWriteArrayList<OFPortStatus>(); | 124 | this.pendingPortStatusMsg = new CopyOnWriteArrayList<OFPortStatus>(); |
| 125 | + this.portDescReplies = new ArrayList<OFPortDescStatsReply>(); | ||
| 124 | factory13 = controller.getOFMessageFactory13(); | 126 | factory13 = controller.getOFMessageFactory13(); |
| 125 | factory10 = controller.getOFMessageFactory10(); | 127 | factory10 = controller.getOFMessageFactory10(); |
| 126 | duplicateDpidFound = Boolean.FALSE; | 128 | duplicateDpidFound = Boolean.FALSE; |
| ... | @@ -294,10 +296,15 @@ class OFChannelHandler extends IdleStateAwareChannelHandler { | ... | @@ -294,10 +296,15 @@ class OFChannelHandler extends IdleStateAwareChannelHandler { |
| 294 | } | 296 | } |
| 295 | if (m.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) { | 297 | if (m.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) { |
| 296 | log.warn("Stats reply indicates more stats from sw {} for " | 298 | log.warn("Stats reply indicates more stats from sw {} for " |
| 297 | - + "port description - not currently handled", | 299 | + + "port description", |
| 298 | h.getSwitchInfoString()); | 300 | h.getSwitchInfoString()); |
| 301 | + h.portDescReplies.add((OFPortDescStatsReply)m); | ||
| 302 | + return; | ||
| 303 | + } | ||
| 304 | + else { | ||
| 305 | + h.portDescReplies.add((OFPortDescStatsReply)m); | ||
| 299 | } | 306 | } |
| 300 | - h.portDescReply = (OFPortDescStatsReply) m; // temp store | 307 | + //h.portDescReply = (OFPortDescStatsReply) m; // temp store |
| 301 | log.info("Received port desc reply for switch at {}", | 308 | log.info("Received port desc reply for switch at {}", |
| 302 | h.getSwitchInfoString()); | 309 | h.getSwitchInfoString()); |
| 303 | try { | 310 | try { |
| ... | @@ -418,7 +425,8 @@ class OFChannelHandler extends IdleStateAwareChannelHandler { | ... | @@ -418,7 +425,8 @@ class OFChannelHandler extends IdleStateAwareChannelHandler { |
| 418 | 425 | ||
| 419 | h.sw.setOFVersion(h.ofVersion); | 426 | h.sw.setOFVersion(h.ofVersion); |
| 420 | h.sw.setFeaturesReply(h.featuresReply); | 427 | h.sw.setFeaturesReply(h.featuresReply); |
| 421 | - h.sw.setPortDescReply(h.portDescReply); | 428 | + //h.sw.setPortDescReply(h.portDescReply); |
| 429 | + h.sw.setPortDescReplies(h.portDescReplies); | ||
| 422 | h.sw.setConnected(true); | 430 | h.sw.setConnected(true); |
| 423 | h.sw.setChannel(h.channel); | 431 | h.sw.setChannel(h.channel); |
| 424 | // boolean success = h.sw.connectSwitch(); | 432 | // boolean success = h.sw.connectSwitch(); | ... | ... |
| ... | @@ -255,6 +255,10 @@ public class RoleManagerTest { | ... | @@ -255,6 +255,10 @@ public class RoleManagerTest { |
| 255 | } | 255 | } |
| 256 | 256 | ||
| 257 | @Override | 257 | @Override |
| 258 | + public void setPortDescReplies(List<OFPortDescStatsReply> portDescReplies) { | ||
| 259 | + } | ||
| 260 | + | ||
| 261 | + @Override | ||
| 258 | public void setFeaturesReply(OFFeaturesReply featuresReply) { | 262 | public void setFeaturesReply(OFFeaturesReply featuresReply) { |
| 259 | } | 263 | } |
| 260 | 264 | ... | ... |
| ... | @@ -32,6 +32,7 @@ import org.slf4j.LoggerFactory; | ... | @@ -32,6 +32,7 @@ import org.slf4j.LoggerFactory; |
| 32 | 32 | ||
| 33 | import java.util.Collections; | 33 | import java.util.Collections; |
| 34 | import java.util.List; | 34 | import java.util.List; |
| 35 | +import java.util.stream.Collectors; | ||
| 35 | 36 | ||
| 36 | /** | 37 | /** |
| 37 | * A simple implementation of a driver manager that differentiates between | 38 | * A simple implementation of a driver manager that differentiates between |
| ... | @@ -73,6 +74,14 @@ public final class DriverManager implements OpenFlowSwitchDriverFactory { | ... | @@ -73,6 +74,14 @@ public final class DriverManager implements OpenFlowSwitchDriverFactory { |
| 73 | return new OFSwitchImplSpringOpenTTP(dpid, desc); | 74 | return new OFSwitchImplSpringOpenTTP(dpid, desc); |
| 74 | } | 75 | } |
| 75 | 76 | ||
| 77 | + //TODO: Temporary work around until the configuration based | ||
| 78 | + // driver manager framework is ready | ||
| 79 | + if (vendor.contains("Dell") | ||
| 80 | + && | ||
| 81 | + hw.contains("OpenFlow switch HW ver. 1.0")) { | ||
| 82 | + return new OFSwitchImplSpringOpenTTPDellOSR(dpid, desc); | ||
| 83 | + } | ||
| 84 | + | ||
| 76 | if (hw.startsWith("Open vSwitch")) { | 85 | if (hw.startsWith("Open vSwitch")) { |
| 77 | if (ofv == OFVersion.OF_10) { | 86 | if (ofv == OFVersion.OF_10) { |
| 78 | return new OFSwitchImplOVS10(dpid, desc); | 87 | return new OFSwitchImplOVS10(dpid, desc); |
| ... | @@ -140,7 +149,9 @@ public final class DriverManager implements OpenFlowSwitchDriverFactory { | ... | @@ -140,7 +149,9 @@ public final class DriverManager implements OpenFlowSwitchDriverFactory { |
| 140 | if (this.factory().getVersion() == OFVersion.OF_10) { | 149 | if (this.factory().getVersion() == OFVersion.OF_10) { |
| 141 | return Collections.unmodifiableList(features.getPorts()); | 150 | return Collections.unmodifiableList(features.getPorts()); |
| 142 | } else { | 151 | } else { |
| 143 | - return Collections.unmodifiableList(ports.getEntries()); | 152 | + return Collections.unmodifiableList(this.ports.stream() |
| 153 | + .flatMap((portReply) -> (portReply.getEntries().stream())) | ||
| 154 | + .collect(Collectors.toList())); | ||
| 144 | } | 155 | } |
| 145 | } | 156 | } |
| 146 | 157 | ... | ... |
| ... | @@ -183,7 +183,7 @@ public class OFOpticalSwitchImplLINC13 extends AbstractOpenFlowSwitch { | ... | @@ -183,7 +183,7 @@ public class OFOpticalSwitchImplLINC13 extends AbstractOpenFlowSwitch { |
| 183 | @Override | 183 | @Override |
| 184 | public List<OFPortDesc> getPorts() { | 184 | public List<OFPortDesc> getPorts() { |
| 185 | List<OFPortDesc> portEntries = new ArrayList<>(); | 185 | List<OFPortDesc> portEntries = new ArrayList<>(); |
| 186 | - portEntries.addAll(ports.getEntries()); | 186 | + portEntries.addAll(super.getPorts()); |
| 187 | if (wPorts != null) { | 187 | if (wPorts != null) { |
| 188 | portEntries.addAll(wPorts.getEntries()); | 188 | portEntries.addAll(wPorts.getEntries()); |
| 189 | } | 189 | } | ... | ... |
| ... | @@ -34,6 +34,8 @@ import java.util.Collections; | ... | @@ -34,6 +34,8 @@ import java.util.Collections; |
| 34 | import java.util.List; | 34 | import java.util.List; |
| 35 | import java.util.concurrent.atomic.AtomicBoolean; | 35 | import java.util.concurrent.atomic.AtomicBoolean; |
| 36 | 36 | ||
| 37 | +//TODO: Knock-off this class as we don't need any switch/app specific | ||
| 38 | +//drivers in the south bound layers. | ||
| 37 | public class OFSwitchImplSpringOpenTTP extends AbstractOpenFlowSwitch { | 39 | public class OFSwitchImplSpringOpenTTP extends AbstractOpenFlowSwitch { |
| 38 | 40 | ||
| 39 | private OFFactory factory; | 41 | private OFFactory factory; |
| ... | @@ -48,8 +50,9 @@ public class OFSwitchImplSpringOpenTTP extends AbstractOpenFlowSwitch { | ... | @@ -48,8 +50,9 @@ public class OFSwitchImplSpringOpenTTP extends AbstractOpenFlowSwitch { |
| 48 | private static final int TABLE_MPLS = 3; | 50 | private static final int TABLE_MPLS = 3; |
| 49 | private static final int TABLE_ACL = 5; | 51 | private static final int TABLE_ACL = 5; |
| 50 | 52 | ||
| 51 | - /* Set the default values. These variables will get | 53 | + /* |
| 52 | - * overwritten based on the switch vendor type | 54 | + * Set the default values. These variables will get overwritten based on the |
| 55 | + * switch vendor type | ||
| 53 | */ | 56 | */ |
| 54 | protected int vlanTableId = TABLE_VLAN; | 57 | protected int vlanTableId = TABLE_VLAN; |
| 55 | protected int tmacTableId = TABLE_TMAC; | 58 | protected int tmacTableId = TABLE_TMAC; |
| ... | @@ -64,13 +67,13 @@ public class OFSwitchImplSpringOpenTTP extends AbstractOpenFlowSwitch { | ... | @@ -64,13 +67,13 @@ public class OFSwitchImplSpringOpenTTP extends AbstractOpenFlowSwitch { |
| 64 | setSwitchDescription(desc); | 67 | setSwitchDescription(desc); |
| 65 | } | 68 | } |
| 66 | 69 | ||
| 67 | - | ||
| 68 | @Override | 70 | @Override |
| 69 | public String toString() { | 71 | public String toString() { |
| 70 | - return "OFSwitchImplSpringOpenTTP [" + ((channel != null) | 72 | + return "OFSwitchImplSpringOpenTTP [" |
| 71 | - ? channel.getRemoteAddress() : "?") | 73 | + + ((channel != null) ? channel.getRemoteAddress() : "?") |
| 72 | - + " DPID[" + ((this.getStringId() != null) ? | 74 | + + " DPID[" |
| 73 | - this.getStringId() : "?") + "]]"; | 75 | + + ((this.getStringId() != null) ? this.getStringId() : "?") |
| 76 | + + "]]"; | ||
| 74 | } | 77 | } |
| 75 | 78 | ||
| 76 | @Override | 79 | @Override |
| ... | @@ -78,7 +81,6 @@ public class OFSwitchImplSpringOpenTTP extends AbstractOpenFlowSwitch { | ... | @@ -78,7 +81,6 @@ public class OFSwitchImplSpringOpenTTP extends AbstractOpenFlowSwitch { |
| 78 | return null; | 81 | return null; |
| 79 | } | 82 | } |
| 80 | 83 | ||
| 81 | - | ||
| 82 | @Override | 84 | @Override |
| 83 | public void startDriverHandshake() { | 85 | public void startDriverHandshake() { |
| 84 | log.debug("Starting driver handshake for sw {}", getStringId()); | 86 | log.debug("Starting driver handshake for sw {}", getStringId()); |
| ... | @@ -101,8 +103,6 @@ public class OFSwitchImplSpringOpenTTP extends AbstractOpenFlowSwitch { | ... | @@ -101,8 +103,6 @@ public class OFSwitchImplSpringOpenTTP extends AbstractOpenFlowSwitch { |
| 101 | return driverHandshakeComplete.get(); | 103 | return driverHandshakeComplete.get(); |
| 102 | } | 104 | } |
| 103 | 105 | ||
| 104 | - | ||
| 105 | - | ||
| 106 | @Override | 106 | @Override |
| 107 | public void processDriverHandshakeMessage(OFMessage m) { | 107 | public void processDriverHandshakeMessage(OFMessage m) { |
| 108 | if (!startDriverHandshakeCalled) { | 108 | if (!startDriverHandshakeCalled) { |
| ... | @@ -113,15 +113,14 @@ public class OFSwitchImplSpringOpenTTP extends AbstractOpenFlowSwitch { | ... | @@ -113,15 +113,14 @@ public class OFSwitchImplSpringOpenTTP extends AbstractOpenFlowSwitch { |
| 113 | } | 113 | } |
| 114 | } | 114 | } |
| 115 | 115 | ||
| 116 | - | ||
| 117 | @Override | 116 | @Override |
| 118 | public void write(OFMessage msg) { | 117 | public void write(OFMessage msg) { |
| 119 | - this.channel.write(Collections.singletonList(msg)); | 118 | + channel.write(Collections.singletonList(msg)); |
| 120 | } | 119 | } |
| 121 | 120 | ||
| 122 | @Override | 121 | @Override |
| 123 | public void write(List<OFMessage> msgs) { | 122 | public void write(List<OFMessage> msgs) { |
| 124 | - this.channel.write(msgs); | 123 | + channel.write(msgs); |
| 125 | } | 124 | } |
| 126 | 125 | ||
| 127 | @Override | 126 | @Override |
| ... | @@ -134,10 +133,10 @@ public class OFSwitchImplSpringOpenTTP extends AbstractOpenFlowSwitch { | ... | @@ -134,10 +133,10 @@ public class OFSwitchImplSpringOpenTTP extends AbstractOpenFlowSwitch { |
| 134 | for (OFInstruction i : instructions) { | 133 | for (OFInstruction i : instructions) { |
| 135 | if (i instanceof OFInstructionGotoTable) { | 134 | if (i instanceof OFInstructionGotoTable) { |
| 136 | OFInstructionGotoTable gotoTable = (OFInstructionGotoTable) i; | 135 | OFInstructionGotoTable gotoTable = (OFInstructionGotoTable) i; |
| 137 | - TableType tid = TableType.values()[gotoTable.getTableId().getValue()]; | 136 | + TableType tid = TableType.values()[gotoTable.getTableId() |
| 138 | - newInstructions.add( | 137 | + .getValue()]; |
| 139 | - gotoTable.createBuilder() | 138 | + newInstructions.add(gotoTable.createBuilder() |
| 140 | - .setTableId(getTableId(tid)).build()); | 139 | + .setTableId(getTableId(tid)).build()); |
| 141 | } else { | 140 | } else { |
| 142 | newInstructions.add(i); | 141 | newInstructions.add(i); |
| 143 | } | 142 | } |
| ... | @@ -156,38 +155,39 @@ public class OFSwitchImplSpringOpenTTP extends AbstractOpenFlowSwitch { | ... | @@ -156,38 +155,39 @@ public class OFSwitchImplSpringOpenTTP extends AbstractOpenFlowSwitch { |
| 156 | @Override | 155 | @Override |
| 157 | public TableType getTableType(TableId tid) { | 156 | public TableType getTableType(TableId tid) { |
| 158 | switch (tid.getValue()) { | 157 | switch (tid.getValue()) { |
| 159 | - case TABLE_IPV4_UNICAST: | 158 | + case TABLE_IPV4_UNICAST: |
| 160 | - return TableType.IP; | 159 | + return TableType.IP; |
| 161 | - case TABLE_MPLS: | 160 | + case TABLE_MPLS: |
| 162 | - return TableType.MPLS; | 161 | + return TableType.MPLS; |
| 163 | - case TABLE_ACL: | 162 | + case TABLE_ACL: |
| 164 | - return TableType.ACL; | 163 | + return TableType.ACL; |
| 165 | - case TABLE_VLAN: | 164 | + case TABLE_VLAN: |
| 166 | - return TableType.VLAN; | 165 | + return TableType.VLAN; |
| 167 | - case TABLE_TMAC: | 166 | + case TABLE_TMAC: |
| 168 | - return TableType.ETHER; | 167 | + return TableType.ETHER; |
| 169 | - default: | 168 | + default: |
| 170 | - log.error("Table type for Table id {} is not supported in the driver", tid); | 169 | + log.error("Table type for Table id {} is not supported in the driver", |
| 171 | - return TableType.NONE; | 170 | + tid); |
| 171 | + return TableType.NONE; | ||
| 172 | } | 172 | } |
| 173 | } | 173 | } |
| 174 | 174 | ||
| 175 | private TableId getTableId(TableType tableType) { | 175 | private TableId getTableId(TableType tableType) { |
| 176 | switch (tableType) { | 176 | switch (tableType) { |
| 177 | - case IP: | 177 | + case IP: |
| 178 | - return TableId.of(ipv4UnicastTableId); | 178 | + return TableId.of(ipv4UnicastTableId); |
| 179 | - case MPLS: | 179 | + case MPLS: |
| 180 | - return TableId.of(mplsTableId); | 180 | + return TableId.of(mplsTableId); |
| 181 | - case ACL: | 181 | + case ACL: |
| 182 | - return TableId.of(aclTableId); | 182 | + return TableId.of(aclTableId); |
| 183 | - case VLAN: | 183 | + case VLAN: |
| 184 | - return TableId.of(vlanTableId); | 184 | + return TableId.of(vlanTableId); |
| 185 | - case ETHER: | 185 | + case ETHER: |
| 186 | - return TableId.of(tmacTableId); | 186 | + return TableId.of(tmacTableId); |
| 187 | - default: { | 187 | + default: { |
| 188 | - log.error("Table type {} is not supported in the driver", tableType); | 188 | + log.error("Table type {} is not supported in the driver", tableType); |
| 189 | - return TableId.NONE; | 189 | + return TableId.NONE; |
| 190 | - } | 190 | + } |
| 191 | } | 191 | } |
| 192 | } | 192 | } |
| 193 | 193 | ... | ... |
| 1 | +/* | ||
| 2 | + * Copyright 2015 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * 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 | ||
| 7 | + * | ||
| 8 | + * 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. | ||
| 15 | + */ | ||
| 16 | +package org.onosproject.openflow.drivers; | ||
| 17 | + | ||
| 18 | +import org.onosproject.openflow.controller.Dpid; | ||
| 19 | +import org.projectfloodlight.openflow.protocol.OFDescStatsReply; | ||
| 20 | +import org.projectfloodlight.openflow.types.TableId; | ||
| 21 | + | ||
| 22 | +/** | ||
| 23 | + * OFDescriptionStatistics Vendor (Manufacturer Desc.): Dell Make (Hardware | ||
| 24 | + * Desc.) : OpenFlow 1.3 Reference Userspace Switch Model (Datapath Desc.) : | ||
| 25 | + * None Software : Serial : None. | ||
| 26 | + */ | ||
| 27 | +//TODO: Knock-off this class as we don't need any switch/app specific | ||
| 28 | +//drivers in the south bound layers. | ||
| 29 | +public class OFSwitchImplSpringOpenTTPDellOSR extends OFSwitchImplSpringOpenTTP { | ||
| 30 | + | ||
| 31 | + /* Table IDs to be used for Dell Open Segment Routers*/ | ||
| 32 | + private static final int DELL_TABLE_VLAN = 17; | ||
| 33 | + private static final int DELL_TABLE_TMAC = 18; | ||
| 34 | + private static final int DELL_TABLE_IPV4_UNICAST = 30; | ||
| 35 | + private static final int DELL_TABLE_MPLS = 25; | ||
| 36 | + private static final int DELL_TABLE_ACL = 40; | ||
| 37 | + | ||
| 38 | + public OFSwitchImplSpringOpenTTPDellOSR(Dpid dpid, OFDescStatsReply desc) { | ||
| 39 | + super(dpid, desc); | ||
| 40 | + vlanTableId = DELL_TABLE_VLAN; | ||
| 41 | + tmacTableId = DELL_TABLE_TMAC; | ||
| 42 | + ipv4UnicastTableId = DELL_TABLE_IPV4_UNICAST; | ||
| 43 | + mplsTableId = DELL_TABLE_MPLS; | ||
| 44 | + aclTableId = DELL_TABLE_ACL; | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + @Override | ||
| 48 | + public TableType getTableType(TableId tid) { | ||
| 49 | + switch (tid.getValue()) { | ||
| 50 | + case DELL_TABLE_IPV4_UNICAST: | ||
| 51 | + return TableType.IP; | ||
| 52 | + case DELL_TABLE_MPLS: | ||
| 53 | + return TableType.MPLS; | ||
| 54 | + case DELL_TABLE_ACL: | ||
| 55 | + return TableType.ACL; | ||
| 56 | + case DELL_TABLE_VLAN: | ||
| 57 | + return TableType.VLAN; | ||
| 58 | + case DELL_TABLE_TMAC: | ||
| 59 | + return TableType.ETHER; | ||
| 60 | + default: | ||
| 61 | + log.error("Table type for Table id {} is not supported in the driver", tid); | ||
| 62 | + return TableType.NONE; | ||
| 63 | + } | ||
| 64 | + } | ||
| 65 | +} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | +{ | ||
| 2 | + "comment": " Multilayer topology description and configuration", | ||
| 3 | + "restrictSwitches": true, | ||
| 4 | + "restrictLinks": true, | ||
| 5 | + | ||
| 6 | + "switchConfig": | ||
| 7 | + [ | ||
| 8 | + { "nodeDpid" : "of:00010001e88b9368", "name": "Dell-R1", "type": "Router_SR", "allowed": true, | ||
| 9 | + "latitude": 80.80, "longitude": 90.10, | ||
| 10 | + "params": { "routerIp": "192.168.0.1/32", | ||
| 11 | + "routerMac": "00:01:e8:8b:93:6b", | ||
| 12 | + "nodeSid": 101, | ||
| 13 | + "isEdgeRouter" : true, | ||
| 14 | + "subnets": [ | ||
| 15 | + { "portNo": 46, "subnetIp": "10.200.1.1/24" } | ||
| 16 | + ] | ||
| 17 | + } | ||
| 18 | + }, | ||
| 19 | + | ||
| 20 | + { "nodeDpid": "of:00010001e88b939b", "name": "Dell-R2", "type": "Router_SR", "allowed": true, | ||
| 21 | + "latitude": 80.80, "longitude": 90.10, | ||
| 22 | + "params": { "routerIp": "192.168.0.2/32", | ||
| 23 | + "routerMac": "00:01:e8:8b:93:9e", | ||
| 24 | + "nodeSid": 102, | ||
| 25 | + "isEdgeRouter" : true, | ||
| 26 | + "subnets": [ | ||
| 27 | + { "portNo": 46, "subnetIp": "10.200.2.1/24" } | ||
| 28 | + ] | ||
| 29 | + } | ||
| 30 | + }, | ||
| 31 | + | ||
| 32 | + { "nodeDpid": "of:00010001e88b938c", "name": "Dell-R3", "type": "Router_SR", "allowed": true, | ||
| 33 | + "latitude": 80.80, "longitude": 90.10, | ||
| 34 | + "params": { "routerIp": "192.168.0.3/32", | ||
| 35 | + "routerMac": "00:01:e8:8b:93:8f", | ||
| 36 | + "nodeSid": 103, | ||
| 37 | + "isEdgeRouter" : true, | ||
| 38 | + "subnets": [ | ||
| 39 | + { "portNo": 46, "subnetIp": "10.200.3.1/24" } | ||
| 40 | + ] | ||
| 41 | + } | ||
| 42 | + }, | ||
| 43 | + | ||
| 44 | + { "nodeDpid": "of:00010001e88b93ad", "name": "Dell-R4", "type": "Router_SR", "allowed": true, | ||
| 45 | + "latitude": 80.80, "longitude": 90.10, | ||
| 46 | + "params": { "routerIp": "192.168.0.4/32", | ||
| 47 | + "routerMac": "00:01:e8:8b:93:b0", | ||
| 48 | + "nodeSid": 104, | ||
| 49 | + "isEdgeRouter" : true, | ||
| 50 | + "subnets": [ | ||
| 51 | + { "portNo": 46, "subnetIp": "10.200.4.1/24" } | ||
| 52 | + ] | ||
| 53 | + } | ||
| 54 | + }, | ||
| 55 | + | ||
| 56 | + { "nodeDpid": "of:00010001e88b93bc", "name": "Dell-R5", "type": "Router_SR", "allowed": true, | ||
| 57 | + "latitude": 80.80, "longitude": 90.10, | ||
| 58 | + "params": { "routerIp": "192.168.0.5/32", | ||
| 59 | + "routerMac": "00:01:e8:8b:93:bf", | ||
| 60 | + "nodeSid": 105, | ||
| 61 | + "isEdgeRouter" : false | ||
| 62 | + } | ||
| 63 | + }, | ||
| 64 | + | ||
| 65 | + { "nodeDpid": "of:00010001e88b93c2", "name": "Dell-R6", "type": "Router_SR", "allowed": true, | ||
| 66 | + "latitude": 80.80, "longitude": 90.10, | ||
| 67 | + "params": { "routerIp": "192.168.0.6/32", | ||
| 68 | + "routerMac": "00:01:e8:8b:93:c5", | ||
| 69 | + "nodeSid": 106, | ||
| 70 | + "isEdgeRouter" : false | ||
| 71 | + } | ||
| 72 | + }, | ||
| 73 | + | ||
| 74 | + { "nodeDpid": "of:00010001e88b9398", "name": "Dell-R7", "type": "Router_SR", "allowed": true, | ||
| 75 | + "latitude": 80.80, "longitude": 90.10, | ||
| 76 | + "params": { "routerIp": "192.168.0.7/32", | ||
| 77 | + "routerMac": "00:01:e8:8b:93:9b", | ||
| 78 | + "nodeSid": 107, | ||
| 79 | + "isEdgeRouter": false | ||
| 80 | + } | ||
| 81 | + }, | ||
| 82 | + | ||
| 83 | + { "nodeDpid": "of:00010001e88b27e3", "name": "Dell-R8", "type": "Router_SR", "allowed": true, | ||
| 84 | + "latitude": 80.80, "longitude": 90.10, | ||
| 85 | + "params": { "routerIp": "192.168.0.8/32", | ||
| 86 | + "routerMac": "00:01:e8:8b:27:e6", | ||
| 87 | + "nodeSid": 108, | ||
| 88 | + "isEdgeRouter": false | ||
| 89 | + } | ||
| 90 | + } | ||
| 91 | + | ||
| 92 | + ] | ||
| 93 | +} |
-
Please register or login to post a comment