diff options
Diffstat (limited to 'framework/src/onos/apps/segmentrouting')
13 files changed, 612 insertions, 150 deletions
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/ArpHandler.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/ArpHandler.java index f42f84b1..36563f01 100644 --- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/ArpHandler.java +++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/ArpHandler.java @@ -35,7 +35,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.nio.ByteBuffer; -import java.util.List; +import java.util.Set; + import static com.google.common.base.Preconditions.checkNotNull; public class ArpHandler { @@ -112,7 +113,7 @@ public class ArpHandler { private boolean isArpReqForRouter(DeviceId deviceId, ARP arpRequest) { - List<Ip4Address> gatewayIpAddresses = config.getSubnetGatewayIps(deviceId); + Set<Ip4Address> gatewayIpAddresses = config.getPortIPs(deviceId); if (gatewayIpAddresses != null) { Ip4Address targetProtocolAddress = Ip4Address.valueOf(arpRequest .getTargetProtocolAddress()); diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java index 40ee55fc..c4a91c75 100644 --- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java +++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java @@ -23,14 +23,12 @@ import org.onlab.packet.IpPrefix; import org.onosproject.net.Device; import org.onosproject.net.DeviceId; import org.onosproject.net.Link; -import org.onosproject.net.MastershipRole; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; -import java.util.List; import java.util.Set; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; @@ -97,7 +95,7 @@ public class DefaultRoutingHandler { log.debug("populateAllRoutingRules: populationStatus is STARTED"); for (Device sw : srManager.deviceService.getDevices()) { - if (srManager.mastershipService.getLocalRole(sw.id()) != MastershipRole.MASTER) { + if (!srManager.mastershipService.isLocalMaster(sw.id())) { log.debug("populateAllRoutingRules: skipping device {}...we are not master", sw.id()); continue; @@ -146,8 +144,7 @@ public class DefaultRoutingHandler { // Take the snapshots of the links updatedEcmpSpgMap = new HashMap<>(); for (Device sw : srManager.deviceService.getDevices()) { - if (srManager.mastershipService. - getLocalRole(sw.id()) != MastershipRole.MASTER) { + if (!srManager.mastershipService.isLocalMaster(sw.id())) { continue; } ECMPShortestPathGraph ecmpSpgUpdated = @@ -273,8 +270,7 @@ public class DefaultRoutingHandler { for (Device sw : srManager.deviceService.getDevices()) { log.debug("Computing the impacted routes for device {} due to link fail", sw.id()); - if (srManager.mastershipService. - getLocalRole(sw.id()) != MastershipRole.MASTER) { + if (!srManager.mastershipService.isLocalMaster(sw.id())) { continue; } ECMPShortestPathGraph ecmpSpg = currentEcmpSpgMap.get(sw.id()); @@ -320,8 +316,7 @@ public class DefaultRoutingHandler { for (Device sw : srManager.deviceService.getDevices()) { log.debug("Computing the impacted routes for device {}", sw.id()); - if (srManager.mastershipService. - getLocalRole(sw.id()) != MastershipRole.MASTER) { + if (!srManager.mastershipService.isLocalMaster(sw.id())) { log.debug("No mastership for {} and skip route optimization", sw.id()); continue; @@ -455,7 +450,7 @@ public class DefaultRoutingHandler { // If both target switch and dest switch are edge routers, then set IP // rule for both subnet and router IP. if (config.isEdgeDevice(targetSw) && config.isEdgeDevice(destSw)) { - List<Ip4Prefix> subnets = config.getSubnets(destSw); + Set<Ip4Prefix> subnets = config.getSubnets(destSw); log.debug("* populateEcmpRoutingRulePartial in device {} towards {} for subnets {}", targetSw, destSw, subnets); result = rulePopulator.populateIpRuleForSubnet(targetSw, @@ -499,14 +494,13 @@ public class DefaultRoutingHandler { } /** - * Populates table miss entries for all tables, and pipeline rules for VLAN - * and TCAM tables. XXX rename/rethink + * Populates filtering rules for permitting Router DstMac and VLAN. * * @param deviceId Switch ID to set the rules */ - public void populateTtpRules(DeviceId deviceId) { - rulePopulator.populateTableVlan(deviceId); - rulePopulator.populateTableTMac(deviceId); + public void populatePortAddressingRules(DeviceId deviceId) { + rulePopulator.populateRouterMacVlanFilters(deviceId); + rulePopulator.populateRouterIpPunts(deviceId); } /** diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DeviceConfiguration.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DeviceConfiguration.java index 0bc155b8..828c51ce 100644 --- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DeviceConfiguration.java +++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DeviceConfiguration.java @@ -15,6 +15,7 @@ */ package org.onosproject.segmentrouting; +import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; import org.onlab.packet.Ip4Address; import org.onlab.packet.Ip4Prefix; @@ -38,20 +39,20 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; /** * Segment Routing configuration component that reads the * segment routing related configuration from Network Configuration Manager * component and organizes in more accessible formats. - * - * TODO: Merge multiple Segment Routing configuration wrapper classes into one. */ public class DeviceConfiguration implements DeviceProperties { private static final Logger log = LoggerFactory .getLogger(DeviceConfiguration.class); private final List<Integer> allSegmentIds = new ArrayList<>(); - private final HashMap<DeviceId, SegmentRouterInfo> deviceConfigMap = new HashMap<>(); + private final ConcurrentHashMap<DeviceId, SegmentRouterInfo> deviceConfigMap + = new ConcurrentHashMap<>(); private class SegmentRouterInfo { int nodeSid; @@ -126,18 +127,17 @@ public class DeviceConfiguration implements DeviceProperties { } /** - * Returns the segment id of a segment router. + * Returns the Node segment id of a segment router. * * @param deviceId device identifier * @return segment id */ @Override public int getSegmentId(DeviceId deviceId) { - if (deviceConfigMap.get(deviceId) != null) { - log.trace("getSegmentId for device{} is {}", - deviceId, - deviceConfigMap.get(deviceId).nodeSid); - return deviceConfigMap.get(deviceId).nodeSid; + SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId); + if (srinfo != null) { + log.trace("getSegmentId for device{} is {}", deviceId, srinfo.nodeSid); + return srinfo.nodeSid; } else { log.warn("getSegmentId for device {} " + "throwing IllegalStateException " @@ -147,10 +147,10 @@ public class DeviceConfiguration implements DeviceProperties { } /** - * Returns the segment id of a segment router given its mac address. + * Returns the Node segment id of a segment router given its Router mac address. * * @param routerMac router mac address - * @return segment id + * @return node segment id, or -1 if not found in config */ public int getSegmentId(MacAddress routerMac) { for (Map.Entry<DeviceId, SegmentRouterInfo> entry: @@ -164,10 +164,10 @@ public class DeviceConfiguration implements DeviceProperties { } /** - * Returns the segment id of a segment router given its router ip address. + * Returns the Node segment id of a segment router given its Router ip address. * * @param routerAddress router ip address - * @return segment id + * @return node segment id, or -1 if not found in config */ public int getSegmentId(Ip4Address routerAddress) { for (Map.Entry<DeviceId, SegmentRouterInfo> entry: @@ -188,11 +188,10 @@ public class DeviceConfiguration implements DeviceProperties { */ @Override public MacAddress getDeviceMac(DeviceId deviceId) { - if (deviceConfigMap.get(deviceId) != null) { - log.trace("getDeviceMac for device{} is {}", - deviceId, - deviceConfigMap.get(deviceId).mac); - return deviceConfigMap.get(deviceId).mac; + SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId); + if (srinfo != null) { + log.trace("getDeviceMac for device{} is {}", deviceId, srinfo.mac); + return srinfo.mac; } else { log.warn("getDeviceMac for device {} " + "throwing IllegalStateException " @@ -208,11 +207,10 @@ public class DeviceConfiguration implements DeviceProperties { * @return router ip address */ public Ip4Address getRouterIp(DeviceId deviceId) { - if (deviceConfigMap.get(deviceId) != null) { - log.trace("getDeviceIp for device{} is {}", - deviceId, - deviceConfigMap.get(deviceId).ip); - return deviceConfigMap.get(deviceId).ip; + SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId); + if (srinfo != null) { + log.trace("getDeviceIp for device{} is {}", deviceId, srinfo.ip); + return srinfo.ip; } else { log.warn("getRouterIp for device {} " + "throwing IllegalStateException " @@ -223,18 +221,17 @@ public class DeviceConfiguration implements DeviceProperties { /** * Indicates if the segment router is a edge router or - * a transit/back bone router. + * a core/backbone router. * * @param deviceId device identifier * @return boolean */ @Override public boolean isEdgeDevice(DeviceId deviceId) { - if (deviceConfigMap.get(deviceId) != null) { - log.trace("isEdgeDevice for device{} is {}", - deviceId, - deviceConfigMap.get(deviceId).isEdge); - return deviceConfigMap.get(deviceId).isEdge; + SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId); + if (srinfo != null) { + log.trace("isEdgeDevice for device{} is {}", deviceId, srinfo.isEdge); + return srinfo.isEdge; } else { log.warn("isEdgeDevice for device {} " + "throwing IllegalStateException " @@ -244,15 +241,35 @@ public class DeviceConfiguration implements DeviceProperties { } /** - * Returns the segment ids of all configured segment routers. + * Returns the node segment ids of all configured segment routers. * - * @return list of segment ids + * @return list of node segment ids */ @Override public List<Integer> getAllDeviceSegmentIds() { return allSegmentIds; } + @Override + public Map<Ip4Prefix, List<PortNumber>> getSubnetPortsMap(DeviceId deviceId) { + Map<Ip4Prefix, List<PortNumber>> subnetPortMap = new HashMap<>(); + + // Construct subnet-port mapping from port-subnet mapping + Map<PortNumber, Ip4Prefix> portSubnetMap = + this.deviceConfigMap.get(deviceId).subnets; + portSubnetMap.forEach((port, subnet) -> { + if (subnetPortMap.containsKey(subnet)) { + subnetPortMap.get(subnet).add(port); + } else { + ArrayList<PortNumber> ports = new ArrayList<>(); + ports.add(port); + subnetPortMap.put(subnet, ports); + } + }); + + return subnetPortMap; + } + /** * Returns the device identifier or data plane identifier (dpid) * of a segment router given its segment id. @@ -290,37 +307,68 @@ public class DeviceConfiguration implements DeviceProperties { } /** - * Returns the configured subnet gateway ip addresses for a segment router. + * Returns the configured port ip addresses for a segment router. + * These addresses serve as gateway IP addresses for the subnets configured + * on those ports. * * @param deviceId device identifier - * @return list of ip addresses + * @return immutable set of ip addresses configured on the ports or null if not found */ - public List<Ip4Address> getSubnetGatewayIps(DeviceId deviceId) { - if (deviceConfigMap.get(deviceId) != null) { - log.trace("getSubnetGatewayIps for device{} is {}", - deviceId, - deviceConfigMap.get(deviceId).gatewayIps.values()); - return new ArrayList<>(deviceConfigMap.get(deviceId).gatewayIps.values()); - } else { - return null; + public Set<Ip4Address> getPortIPs(DeviceId deviceId) { + SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId); + if (srinfo != null) { + log.trace("getSubnetGatewayIps for device{} is {}", deviceId, + srinfo.gatewayIps.values()); + return ImmutableSet.copyOf(srinfo.gatewayIps.values()); + } + return null; + } + + /** + * Returns the configured IP addresses per port + * for a segment router. + * + * @param deviceId device identifier + * @return map of port to gateway IP addresses or null if not found + */ + public Map<PortNumber, Ip4Address> getPortIPMap(DeviceId deviceId) { + SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId); + if (srinfo != null) { + return srinfo.gatewayIps; } + return null; } /** * Returns the configured subnet prefixes for a segment router. * * @param deviceId device identifier - * @return list of ip prefixes + * @return list of ip prefixes or null if not found */ - public List<Ip4Prefix> getSubnets(DeviceId deviceId) { - if (deviceConfigMap.get(deviceId) != null) { - log.trace("getSubnets for device{} is {}", - deviceId, - deviceConfigMap.get(deviceId).subnets.values()); - return new ArrayList<>(deviceConfigMap.get(deviceId).subnets.values()); - } else { - return null; + public Set<Ip4Prefix> getSubnets(DeviceId deviceId) { + SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId); + if (srinfo != null) { + log.trace("getSubnets for device{} is {}", deviceId, + srinfo.subnets.values()); + return ImmutableSet.copyOf(srinfo.subnets.values()); } + return null; + } + + /** + * Returns the configured subnet on the given port, or null if no + * subnet has been configured on the port. + * + * @param deviceId device identifier + * @param pnum port identifier + * @return configured subnet on port, or null + */ + public Ip4Prefix getPortSubnet(DeviceId deviceId, PortNumber pnum) { + SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId); + if (srinfo != null) { + return srinfo.subnets.get(pnum); + } + return null; } /** @@ -349,7 +397,7 @@ public class DeviceConfiguration implements DeviceProperties { * specified ip address as one of its subnet gateway ip address. * * @param gatewayIpAddress router gateway ip address - * @return router mac address + * @return router mac address or null if not found */ public MacAddress getRouterMacForAGatewayIp(Ip4Address gatewayIpAddress) { for (Map.Entry<DeviceId, SegmentRouterInfo> entry: @@ -377,7 +425,7 @@ public class DeviceConfiguration implements DeviceProperties { */ public boolean inSameSubnet(DeviceId deviceId, Ip4Address hostIp) { - List<Ip4Prefix> subnets = getSubnets(deviceId); + Set<Ip4Prefix> subnets = getSubnets(deviceId); if (subnets == null) { return false; } @@ -399,8 +447,9 @@ public class DeviceConfiguration implements DeviceProperties { * @return list of port numbers */ public List<Integer> getPortsForAdjacencySid(DeviceId deviceId, int sid) { - if (deviceConfigMap.get(deviceId) != null) { - for (AdjacencySid asid : deviceConfigMap.get(deviceId).adjacencySids) { + SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId); + if (srinfo != null) { + for (AdjacencySid asid : srinfo.adjacencySids) { if (asid.getAsid() == sid) { return asid.getPorts(); } @@ -419,12 +468,13 @@ public class DeviceConfiguration implements DeviceProperties { * otherwise false */ public boolean isAdjacencySid(DeviceId deviceId, int sid) { - if (deviceConfigMap.get(deviceId) != null) { - if (deviceConfigMap.get(deviceId).adjacencySids.isEmpty()) { + SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId); + if (srinfo != null) { + if (srinfo.adjacencySids.isEmpty()) { return false; } else { for (AdjacencySid asid: - deviceConfigMap.get(deviceId).adjacencySids) { + srinfo.adjacencySids) { if (asid.getAsid() == sid) { return true; } diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java index f65f03e0..b3916b06 100644 --- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java +++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java @@ -32,7 +32,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.nio.ByteBuffer; -import java.util.List; +import java.util.Set; import static com.google.common.base.Preconditions.checkNotNull; @@ -70,7 +70,7 @@ public class IcmpHandler { DeviceId deviceId = connectPoint.deviceId(); Ip4Address destinationAddress = Ip4Address.valueOf(ipv4.getDestinationAddress()); - List<Ip4Address> gatewayIpAddresses = config.getSubnetGatewayIps(deviceId); + Set<Ip4Address> gatewayIpAddresses = config.getPortIPs(deviceId); Ip4Address routerIp = config.getRouterIp(deviceId); IpPrefix routerIpPrefix = IpPrefix.valueOf(routerIp, IpPrefix.MAX_INET_MASK_LENGTH); Ip4Address routerIpAddress = routerIpPrefix.getIp4Prefix().address(); diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java index 7641571d..d46028e7 100644 --- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java +++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java @@ -25,6 +25,7 @@ import org.onlab.packet.VlanId; import org.onosproject.segmentrouting.grouphandler.NeighborSet; import org.onosproject.net.DeviceId; import org.onosproject.net.Link; +import org.onosproject.net.Port; import org.onosproject.net.PortNumber; import org.onosproject.net.flow.DefaultTrafficSelector; import org.onosproject.net.flow.DefaultTrafficTreatment; @@ -38,11 +39,13 @@ import org.onosproject.net.flowobjective.ForwardingObjective; import org.onosproject.net.flowobjective.Objective; import org.onosproject.net.flowobjective.ObjectiveError; import org.onosproject.net.flowobjective.ForwardingObjective.Builder; +import org.onosproject.net.flowobjective.ForwardingObjective.Flag; import org.onosproject.net.flowobjective.ObjectiveContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.atomic.AtomicLong; @@ -57,6 +60,11 @@ public class RoutingRulePopulator { private AtomicLong rulePopulationCounter; private SegmentRoutingManager srManager; private DeviceConfiguration config; + + private static final int HIGHEST_PRIORITY = 0xffff; + private static final long OFPP_MAX = 0xffffff00L; + + /** * Creates a RoutingRulePopulator object. * @@ -98,7 +106,7 @@ public class RoutingRulePopulator { TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder(); TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder(); - sbuilder.matchIPDst(IpPrefix.valueOf(hostIp, 32)); + sbuilder.matchIPDst(IpPrefix.valueOf(hostIp, IpPrefix.MAX_INET_MASK_LENGTH)); sbuilder.matchEthType(Ethernet.TYPE_IPV4); tbuilder.deferred() @@ -134,7 +142,7 @@ public class RoutingRulePopulator { * @return true if all rules are set successfully, false otherwise */ public boolean populateIpRuleForSubnet(DeviceId deviceId, - List<Ip4Prefix> subnets, + Set<Ip4Prefix> subnets, DeviceId destSw, Set<DeviceId> nextHops) { @@ -350,40 +358,80 @@ public class RoutingRulePopulator { } /** - * Populates VLAN flows rules. All packets are forwarded to TMAC table. + * Creates a filtering objective to permit all untagged packets with a + * dstMac corresponding to the router's MAC address. For those pipelines + * that need to internally assign vlans to untagged packets, this method + * provides per-subnet vlan-ids as metadata. + * <p> + * Note that the vlan assignment is only done by the master-instance for a switch. + * However we send the filtering objective from slave-instances as well, so + * that drivers can obtain other information (like Router MAC and IP). * - * @param deviceId switch ID to set the rules + * @param deviceId the switch dpid for the router */ - public void populateTableVlan(DeviceId deviceId) { - FilteringObjective.Builder fob = DefaultFilteringObjective.builder(); - fob.withKey(Criteria.matchInPort(PortNumber.ALL)) + public void populateRouterMacVlanFilters(DeviceId deviceId) { + log.debug("Installing per-port filtering objective for untagged " + + "packets in device {}", deviceId); + for (Port port : srManager.deviceService.getPorts(deviceId)) { + if (port.number().toLong() > 0 && port.number().toLong() < OFPP_MAX) { + Ip4Prefix portSubnet = config.getPortSubnet(deviceId, port.number()); + VlanId assignedVlan = (portSubnet == null) + ? VlanId.vlanId(SegmentRoutingManager.ASSIGNED_VLAN_NO_SUBNET) + : srManager.getSubnetAssignedVlanId(deviceId, portSubnet); + FilteringObjective.Builder fob = DefaultFilteringObjective.builder(); + fob.withKey(Criteria.matchInPort(port.number())) + .addCondition(Criteria.matchEthDst(config.getDeviceMac(deviceId))) .addCondition(Criteria.matchVlanId(VlanId.NONE)); - fob.permit().fromApp(srManager.appId); - log.debug("populateTableVlan: Installing filtering objective for untagged packets"); - srManager.flowObjectiveService. - filter(deviceId, - fob.add(new SRObjectiveContext(deviceId, - SRObjectiveContext.ObjectiveType.FILTER))); + // vlan assignment is valid only if this instance is master + if (srManager.mastershipService.isLocalMaster(deviceId)) { + TrafficTreatment tt = DefaultTrafficTreatment.builder() + .pushVlan().setVlanId(assignedVlan).build(); + fob.setMeta(tt); + } + fob.permit().fromApp(srManager.appId); + srManager.flowObjectiveService. + filter(deviceId, fob.add(new SRObjectiveContext(deviceId, + SRObjectiveContext.ObjectiveType.FILTER))); + } + } } /** - * Populates TMAC table rules. IP packets are forwarded to IP table. MPLS - * packets are forwarded to MPLS table. + * Creates a forwarding objective to punt all IP packets, destined to the + * router's port IP addresses, to the controller. Note that the input + * port should not be matched on, as these packets can come from any input. + * Furthermore, these are applied only by the master instance. * - * @param deviceId switch ID to set the rules + * @param deviceId the switch dpid for the router */ - public void populateTableTMac(DeviceId deviceId) { - - FilteringObjective.Builder fob = DefaultFilteringObjective.builder(); - fob.withKey(Criteria.matchInPort(PortNumber.ALL)) - .addCondition(Criteria.matchEthDst(config - .getDeviceMac(deviceId))); - fob.permit().fromApp(srManager.appId); - log.debug("populateTableTMac: Installing filtering objective for router mac"); - srManager.flowObjectiveService. - filter(deviceId, - fob.add(new SRObjectiveContext(deviceId, - SRObjectiveContext.ObjectiveType.FILTER))); + public void populateRouterIpPunts(DeviceId deviceId) { + if (!srManager.mastershipService.isLocalMaster(deviceId)) { + log.debug("Not installing port-IP punts - not the master for dev:{} ", + deviceId); + return; + } + ForwardingObjective.Builder puntIp = DefaultForwardingObjective.builder(); + Set<Ip4Address> allIps = new HashSet<Ip4Address>(config.getPortIPs(deviceId)); + allIps.add(config.getRouterIp(deviceId)); + for (Ip4Address ipaddr : allIps) { + TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); + TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); + selector.matchEthType(Ethernet.TYPE_IPV4); + selector.matchIPDst(IpPrefix.valueOf(ipaddr, + IpPrefix.MAX_INET_MASK_LENGTH)); + treatment.setOutput(PortNumber.CONTROLLER); + puntIp.withSelector(selector.build()); + puntIp.withTreatment(treatment.build()); + puntIp.withFlag(Flag.VERSATILE) + .withPriority(HIGHEST_PRIORITY) + .makePermanent() + .fromApp(srManager.appId); + log.debug("Installing forwarding objective to punt port IP addresses"); + srManager.flowObjectiveService. + forward(deviceId, + puntIp.add(new SRObjectiveContext(deviceId, + SRObjectiveContext.ObjectiveType.FORWARDING))); + } } private PortNumber selectOnePort(DeviceId srcId, Set<DeviceId> destIds) { diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java index eb2cf569..9d60b279 100644 --- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java +++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java @@ -22,11 +22,17 @@ import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.ReferenceCardinality; import org.apache.felix.scr.annotations.Service; import org.onlab.packet.Ethernet; +import org.onlab.packet.VlanId; import org.onlab.packet.IPv4; +import org.onlab.packet.Ip4Address; +import org.onlab.packet.Ip4Prefix; +import org.onlab.packet.IpAddress; +import org.onlab.packet.IpPrefix; import org.onlab.util.KryoNamespace; import org.onosproject.core.ApplicationId; import org.onosproject.core.CoreService; import org.onosproject.event.Event; +import org.onosproject.net.ConnectPoint; import org.onosproject.net.config.ConfigFactory; import org.onosproject.net.config.NetworkConfigEvent; import org.onosproject.net.config.NetworkConfigRegistry; @@ -45,7 +51,6 @@ import org.onosproject.net.device.DeviceEvent; import org.onosproject.net.device.DeviceListener; import org.onosproject.net.device.DeviceService; import org.onosproject.net.flowobjective.FlowObjectiveService; -import org.onosproject.net.group.GroupKey; import org.onosproject.net.host.HostService; import org.onosproject.net.intent.IntentService; import org.onosproject.net.link.LinkEvent; @@ -56,6 +61,7 @@ import org.onosproject.net.packet.PacketContext; import org.onosproject.net.packet.PacketProcessor; import org.onosproject.net.packet.PacketService; import org.onosproject.net.topology.TopologyService; +import org.onosproject.segmentrouting.grouphandler.SubnetNextObjectiveStoreKey; import org.onosproject.store.service.EventuallyConsistentMap; import org.onosproject.store.service.EventuallyConsistentMapBuilder; import org.onosproject.store.service.StorageService; @@ -64,9 +70,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.net.URI; +import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Executors; @@ -133,8 +141,13 @@ public class SegmentRoutingManager implements SegmentRoutingService { // Per device next objective ID store with (device id + neighbor set) as key private EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey, Integer> nsNextObjStore = null; + private EventuallyConsistentMap<SubnetNextObjectiveStoreKey, Integer> subnetNextObjStore = null; private EventuallyConsistentMap<String, Tunnel> tunnelStore = null; private EventuallyConsistentMap<String, Policy> policyStore = null; + // Per device, per-subnet assigned-vlans store, with (device id + subnet + // IPv4 prefix) as key + private EventuallyConsistentMap<SubnetAssignedVidStoreKey, VlanId> + subnetVidStore = null; @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected StorageService storageService; @@ -163,6 +176,9 @@ public class SegmentRoutingManager implements SegmentRoutingService { private KryoNamespace.Builder kryoBuilder = null; + private static final short ASSIGNED_VLAN_START = 4093; + public static final short ASSIGNED_VLAN_NO_SUBNET = 4094; + @Activate protected void activate() { appId = coreService @@ -170,6 +186,8 @@ public class SegmentRoutingManager implements SegmentRoutingService { kryoBuilder = new KryoNamespace.Builder() .register(NeighborSetNextObjectiveStoreKey.class, + SubnetNextObjectiveStoreKey.class, + SubnetAssignedVidStoreKey.class, NeighborSet.class, DeviceId.class, URI.class, @@ -180,7 +198,12 @@ public class SegmentRoutingManager implements SegmentRoutingService { DefaultTunnel.class, Policy.class, TunnelPolicy.class, - Policy.Type.class + Policy.Type.class, + VlanId.class, + Ip4Address.class, + Ip4Prefix.class, + IpAddress.Version.class, + ConnectPoint.class ); log.debug("Creating EC map nsnextobjectivestore"); @@ -194,6 +217,16 @@ public class SegmentRoutingManager implements SegmentRoutingService { .build(); log.trace("Current size {}", nsNextObjStore.size()); + log.debug("Creating EC map subnetnextobjectivestore"); + EventuallyConsistentMapBuilder<SubnetNextObjectiveStoreKey, Integer> + subnetNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder(); + + subnetNextObjStore = subnetNextObjMapBuilder + .withName("subnetnextobjectivestore") + .withSerializer(kryoBuilder) + .withTimestampProvider((k, v) -> new WallClockTimestamp()) + .build(); + EventuallyConsistentMapBuilder<String, Tunnel> tunnelMapBuilder = storageService.eventuallyConsistentMapBuilder(); @@ -212,6 +245,15 @@ public class SegmentRoutingManager implements SegmentRoutingService { .withTimestampProvider((k, v) -> new WallClockTimestamp()) .build(); + EventuallyConsistentMapBuilder<SubnetAssignedVidStoreKey, VlanId> + subnetVidStoreMapBuilder = storageService.eventuallyConsistentMapBuilder(); + + subnetVidStore = subnetVidStoreMapBuilder + .withName("subnetvidstore") + .withSerializer(kryoBuilder) + .withTimestampProvider((k, v) -> new WallClockTimestamp()) + .build(); + cfgService.addListener(cfgListener); cfgService.registerConfigFactory(cfgFactory); @@ -296,23 +338,72 @@ public class SegmentRoutingManager implements SegmentRoutingService { } /** - * Returns the GroupKey object for the device and the NeighborSet given. - * XXX is this called + * Returns the vlan-id assigned to the subnet configured for a device. + * If no vlan-id has been assigned, a new one is assigned out of a pool of ids, + * if and only if this controller instance is the master for the device. + * <p> + * USAGE: The assigned vlans are meant to be applied to untagged packets on those + * switches/pipelines that need this functionality. These vids are meant + * to be used internally within a switch, and thus need to be unique only + * on a switch level. Note that packets never go out on the wire with these + * vlans. Currently, vlan ids are assigned from value 4093 down. + * Vlan id 4094 expected to be used for all ports that are not assigned subnets. + * Vlan id 4095 is reserved and unused. Only a single vlan id is assigned + * per subnet. + * XXX This method should avoid any vlans configured on the ports, but + * currently the app works only on untagged packets and as a result + * ignores any vlan configuration. * - * @param ns NeightborSet object for the GroupKey - * @return GroupKey object for the NeighborSet + * @param deviceId switch dpid + * @param subnet IPv4 prefix for which assigned vlan is desired + * @return VlanId assigned for the subnet on the device, or + * null if no vlan assignment was found and this instance is not + * the master for the device. */ - public GroupKey getGroupKey(NeighborSet ns) { - for (DefaultGroupHandler groupHandler : groupHandlerMap.values()) { - return groupHandler.getGroupKey(ns); + public VlanId getSubnetAssignedVlanId(DeviceId deviceId, Ip4Prefix subnet) { + VlanId assignedVid = subnetVidStore.get(new SubnetAssignedVidStoreKey( + deviceId, subnet)); + if (assignedVid != null) { + log.debug("Query for subnet:{} on device:{} returned assigned-vlan " + + "{}", subnet, deviceId, assignedVid); + return assignedVid; + } + //check mastership for the right to assign a vlan + if (!mastershipService.isLocalMaster(deviceId)) { + log.warn("This controller instance is not the master for device {}. " + + "Cannot assign vlan-id for subnet {}", deviceId, subnet); + return null; + } + // vlan assignment is expensive but done only once + Set<Ip4Prefix> configuredSubnets = deviceConfiguration.getSubnets(deviceId); + Set<Short> assignedVlans = new HashSet<>(); + Set<Ip4Prefix> unassignedSubnets = new HashSet<>(); + for (Ip4Prefix sub : configuredSubnets) { + VlanId v = subnetVidStore.get(new SubnetAssignedVidStoreKey(deviceId, + sub)); + if (v != null) { + assignedVlans.add(v.toShort()); + } else { + unassignedSubnets.add(sub); + } + } + short nextAssignedVlan = ASSIGNED_VLAN_START; + if (!assignedVlans.isEmpty()) { + nextAssignedVlan = (short) (Collections.min(assignedVlans) - 1); + } + for (Ip4Prefix unsub : unassignedSubnets) { + subnetVidStore.put(new SubnetAssignedVidStoreKey(deviceId, unsub), + VlanId.vlanId(nextAssignedVlan--)); + log.info("Assigned vlan: {} to subnet: {} on device: {}", + nextAssignedVlan + 1, unsub, deviceId); } - return null; + return subnetVidStore.get(new SubnetAssignedVidStoreKey(deviceId, subnet)); } /** - * Returns the next objective ID for the NeighborSet given. If the nextObjectiveID does not exist, - * a new one is created and returned. + * Returns the next objective ID for the given NeighborSet. + * If the nextObjectiveID does not exist, a new one is created and returned. * * @param deviceId Device ID * @param ns NegighborSet @@ -329,6 +420,25 @@ public class SegmentRoutingManager implements SegmentRoutingService { } } + /** + * Returns the next objective ID for the Subnet given. If the nextObjectiveID does not exist, + * a new one is created and returned. + * + * @param deviceId Device ID + * @param prefix Subnet + * @return next objective ID + */ + public int getSubnetNextObjectiveId(DeviceId deviceId, IpPrefix prefix) { + if (groupHandlerMap.get(deviceId) != null) { + log.trace("getSubnetNextObjectiveId query in device {}", deviceId); + return groupHandlerMap + .get(deviceId).getSubnetNextObjectiveId(prefix); + } else { + log.warn("getSubnetNextObjectiveId query in device {} not found", deviceId); + return -1; + } + } + private class InternalPacketProcessor implements PacketProcessor { @Override public void process(PacketContext context) { @@ -423,6 +533,8 @@ public class SegmentRoutingManager implements SegmentRoutingService { event.type() == DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED || event.type() == DeviceEvent.Type.DEVICE_UPDATED) { if (deviceService.isAvailable(((Device) event.subject()).id())) { + log.info("Processing device event {} for available device {}", + event.type(), ((Device) event.subject()).id()); processDeviceAdded((Device) event.subject()); } } else if (event.type() == DeviceEvent.Type.PORT_REMOVED) { @@ -484,20 +596,31 @@ public class SegmentRoutingManager implements SegmentRoutingService { private void processDeviceAdded(Device device) { log.debug("A new device with ID {} was added", device.id()); - //Irrespective whether the local is a MASTER or not for this device, - //create group handler instance and push default TTP flow rules. - //Because in a multi-instance setup, instances can initiate - //groups for any devices. Also the default TTP rules are needed - //to be pushed before inserting any IP table entries for any device - DefaultGroupHandler dgh = DefaultGroupHandler. + // Irrespective of whether the local is a MASTER or not for this device, + // we need to create a SR-group-handler instance. This is because in a + // multi-instance setup, any instance can initiate forwarding/next-objectives + // for any switch (even if this instance is a SLAVE or not even connected + // to the switch). To handle this, a default-group-handler instance is necessary + // per switch. + DefaultGroupHandler groupHandler = DefaultGroupHandler. createGroupHandler(device.id(), appId, deviceConfiguration, linkService, flowObjectiveService, - nsNextObjStore); - groupHandlerMap.put(device.id(), dgh); - defaultRoutingHandler.populateTtpRules(device.id()); + nsNextObjStore, + subnetNextObjStore); + groupHandlerMap.put(device.id(), groupHandler); + + // Also, in some cases, drivers may need extra + // information to process rules (eg. Router IP/MAC); and so, we send + // port addressing rules to the driver as well irrespective of whether + // this instance is the master or not. + defaultRoutingHandler.populatePortAddressingRules(device.id()); + + if (mastershipService.isLocalMaster(device.id())) { + groupHandler.createGroupsFromSubnetConfig(); + } } private void processPortRemoved(Device device, Port port) { @@ -531,18 +654,29 @@ public class SegmentRoutingManager implements SegmentRoutingService { tunnelHandler, policyStore); for (Device device : deviceService.getDevices()) { - //Irrespective whether the local is a MASTER or not for this device, - //create group handler instance and push default TTP flow rules. - //Because in a multi-instance setup, instances can initiate - //groups for any devices. Also the default TTP rules are needed - //to be pushed before inserting any IP table entries for any device + // Irrespective of whether the local is a MASTER or not for this device, + // we need to create a SR-group-handler instance. This is because in a + // multi-instance setup, any instance can initiate forwarding/next-objectives + // for any switch (even if this instance is a SLAVE or not even connected + // to the switch). To handle this, a default-group-handler instance is necessary + // per switch. DefaultGroupHandler groupHandler = DefaultGroupHandler .createGroupHandler(device.id(), appId, deviceConfiguration, linkService, flowObjectiveService, - nsNextObjStore); + nsNextObjStore, + subnetNextObjStore); groupHandlerMap.put(device.id(), groupHandler); - defaultRoutingHandler.populateTtpRules(device.id()); + + // Also, in some cases, drivers may need extra + // information to process rules (eg. Router IP/MAC); and so, we send + // port addressing rules to the driver as well, irrespective of whether + // this instance is the master or not. + defaultRoutingHandler.populatePortAddressingRules(device.id()); + + if (mastershipService.isLocalMaster(device.id())) { + groupHandler.createGroupsFromSubnetConfig(); + } } defaultRoutingHandler.startPopulationProcess(); diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SubnetAssignedVidStoreKey.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SubnetAssignedVidStoreKey.java new file mode 100644 index 00000000..84b44c97 --- /dev/null +++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SubnetAssignedVidStoreKey.java @@ -0,0 +1,66 @@ +package org.onosproject.segmentrouting; + +import java.util.Objects; + +import org.onlab.packet.Ip4Prefix; +import org.onosproject.net.DeviceId; + +/** + * Class definition for key used to map per device subnets to assigned Vlan ids. + * + */ +public class SubnetAssignedVidStoreKey { + private final DeviceId deviceId; + private final Ip4Prefix subnet; + + public SubnetAssignedVidStoreKey(DeviceId deviceId, Ip4Prefix subnet) { + this.deviceId = deviceId; + this.subnet = subnet; + } + + /** + * Returns the device identification used to create this key. + * + * @return the device identifier + */ + public DeviceId deviceId() { + return deviceId; + } + + /** + * Returns the subnet information used to create this key. + * + * @return the subnet + */ + public Ip4Prefix subnet() { + return subnet; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof SubnetAssignedVidStoreKey)) { + return false; + } + SubnetAssignedVidStoreKey that = + (SubnetAssignedVidStoreKey) o; + return (Objects.equals(this.deviceId, that.deviceId) && + Objects.equals(this.subnet, that.subnet)); + } + + @Override + public int hashCode() { + int result = 17; + result = 31 * result + Objects.hashCode(deviceId) + + Objects.hashCode(subnet); + return result; + } + + @Override + public String toString() { + return "Device: " + deviceId + " Subnet: " + subnet; + } + +} diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultEdgeGroupHandler.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultEdgeGroupHandler.java index c960adca..a5c1090f 100644 --- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultEdgeGroupHandler.java +++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultEdgeGroupHandler.java @@ -52,9 +52,12 @@ public class DefaultEdgeGroupHandler extends DefaultGroupHandler { LinkService linkService, FlowObjectiveService flowObjService, EventuallyConsistentMap< - NeighborSetNextObjectiveStoreKey, - Integer> nsNextObjStore) { - super(deviceId, appId, config, linkService, flowObjService, nsNextObjStore); + NeighborSetNextObjectiveStoreKey, + Integer> nsNextObjStore, + EventuallyConsistentMap<SubnetNextObjectiveStoreKey, + Integer> subnetNextObjStore) { + super(deviceId, appId, config, linkService, flowObjService, + nsNextObjStore, subnetNextObjStore); } @Override diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java index 9bbde2f3..69a0d86f 100644 --- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java +++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java @@ -25,10 +25,11 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Random; import java.util.Set; import java.util.stream.Collectors; +import org.onlab.packet.Ip4Prefix; +import org.onlab.packet.IpPrefix; import org.onlab.packet.MacAddress; import org.onlab.packet.MplsLabel; import org.onlab.util.KryoNamespace; @@ -74,7 +75,8 @@ public class DefaultGroupHandler { // new HashMap<NeighborSet, Integer>(); protected EventuallyConsistentMap< NeighborSetNextObjectiveStoreKey, Integer> nsNextObjStore = null; - protected Random rand = new Random(); + protected EventuallyConsistentMap< + SubnetNextObjectiveStoreKey, Integer> subnetNextObjStore = null; protected KryoNamespace.Builder kryo = new KryoNamespace.Builder() .register(URI.class).register(HashSet.class) @@ -89,8 +91,10 @@ public class DefaultGroupHandler { LinkService linkService, FlowObjectiveService flowObjService, EventuallyConsistentMap< - NeighborSetNextObjectiveStoreKey, - Integer> nsNextObjStore) { + NeighborSetNextObjectiveStoreKey, + Integer> nsNextObjStore, + EventuallyConsistentMap<SubnetNextObjectiveStoreKey, + Integer> subnetNextObjStore) { this.deviceId = checkNotNull(deviceId); this.appId = checkNotNull(appId); this.deviceConfig = checkNotNull(config); @@ -101,6 +105,7 @@ public class DefaultGroupHandler { nodeMacAddr = checkNotNull(config.getDeviceMac(deviceId)); this.flowObjectiveService = flowObjService; this.nsNextObjStore = nsNextObjStore; + this.subnetNextObjStore = subnetNextObjStore; populateNeighborMaps(); } @@ -115,7 +120,8 @@ public class DefaultGroupHandler { * @param config interface to retrieve the device properties * @param linkService link service object * @param flowObjService flow objective service object - * @param nsNextObjStore next objective store map + * @param nsNextObjStore NeighborSet next objective store map + * @param subnetNextObjStore subnet next objective store map * @return default group handler type */ public static DefaultGroupHandler createGroupHandler(DeviceId deviceId, @@ -123,18 +129,23 @@ public class DefaultGroupHandler { DeviceProperties config, LinkService linkService, FlowObjectiveService flowObjService, - EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey, - Integer> nsNextObjStore) { + EventuallyConsistentMap< + NeighborSetNextObjectiveStoreKey, + Integer> nsNextObjStore, + EventuallyConsistentMap<SubnetNextObjectiveStoreKey, + Integer> subnetNextObjStore) { if (config.isEdgeDevice(deviceId)) { return new DefaultEdgeGroupHandler(deviceId, appId, config, linkService, flowObjService, - nsNextObjStore); + nsNextObjStore, + subnetNextObjStore); } else { return new DefaultTransitGroupHandler(deviceId, appId, config, linkService, flowObjService, - nsNextObjStore); + nsNextObjStore, + subnetNextObjStore); } } @@ -323,6 +334,21 @@ public class DefaultGroupHandler { } /** + * Returns the next objective associated with the subnet. + * If there is no next objective for this subnet, this API + * would create a next objective and return. + * + * @param prefix subnet information + * @return int if found or -1 + */ + public int getSubnetNextObjectiveId(IpPrefix prefix) { + Integer nextId = subnetNextObjStore. + get(new SubnetNextObjectiveStoreKey(deviceId, prefix)); + + return (nextId != null) ? nextId : -1; + } + + /** * Checks if the next objective ID (group) for the neighbor set exists or not. * * @param ns neighbor set to check @@ -486,6 +512,43 @@ public class DefaultGroupHandler { } } + public void createGroupsFromSubnetConfig() { + Map<Ip4Prefix, List<PortNumber>> subnetPortMap = + this.deviceConfig.getSubnetPortsMap(this.deviceId); + + // Construct a broadcast group for each subnet + subnetPortMap.forEach((subnet, ports) -> { + SubnetNextObjectiveStoreKey key = + new SubnetNextObjectiveStoreKey(deviceId, subnet); + + if (subnetNextObjStore.containsKey(key)) { + log.debug("Broadcast group for device {} and subnet {} exists", + deviceId, subnet); + return; + } + + int nextId = flowObjectiveService.allocateNextId(); + + NextObjective.Builder nextObjBuilder = DefaultNextObjective + .builder().withId(nextId) + .withType(NextObjective.Type.BROADCAST).fromApp(appId); + + ports.forEach(port -> { + TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder(); + tBuilder.setOutput(port); + nextObjBuilder.addTreatment(tBuilder.build()); + }); + + NextObjective nextObj = nextObjBuilder.add(); + flowObjectiveService.next(deviceId, nextObj); + log.debug("createGroupFromSubnetConfig: Submited " + + "next objective {} in device {}", + nextId, deviceId); + + subnetNextObjStore.put(key, nextId); + }); + } + public GroupKey getGroupKey(Object obj) { return new DefaultGroupKey(kryo.build().serialize(obj)); } diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultTransitGroupHandler.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultTransitGroupHandler.java index 3cb73aba..b009e869 100644 --- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultTransitGroupHandler.java +++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultTransitGroupHandler.java @@ -45,9 +45,12 @@ public class DefaultTransitGroupHandler extends DefaultGroupHandler { LinkService linkService, FlowObjectiveService flowObjService, EventuallyConsistentMap< - NeighborSetNextObjectiveStoreKey, - Integer> nsNextObjStore) { - super(deviceId, appId, config, linkService, flowObjService, nsNextObjStore); + NeighborSetNextObjectiveStoreKey, + Integer> nsNextObjStore, + EventuallyConsistentMap<SubnetNextObjectiveStoreKey, + Integer> subnetNextObjStore) { + super(deviceId, appId, config, linkService, flowObjService, + nsNextObjStore, subnetNextObjStore); } @Override diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DeviceProperties.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DeviceProperties.java index 497f5256..d28d38d5 100644 --- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DeviceProperties.java +++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DeviceProperties.java @@ -16,9 +16,12 @@ package org.onosproject.segmentrouting.grouphandler; import java.util.List; +import java.util.Map; +import org.onlab.packet.Ip4Prefix; import org.onlab.packet.MacAddress; import org.onosproject.net.DeviceId; +import org.onosproject.net.PortNumber; /** * Mechanism through which group handler module retrieves @@ -33,6 +36,7 @@ public interface DeviceProperties { * @return segment id of a device */ int getSegmentId(DeviceId deviceId); + /** * Returns the Mac address of a device to be used in group creation. * @@ -40,6 +44,7 @@ public interface DeviceProperties { * @return mac address of a device */ MacAddress getDeviceMac(DeviceId deviceId); + /** * Indicates whether a device is edge device or transit/core device. * @@ -47,6 +52,7 @@ public interface DeviceProperties { * @return boolean */ boolean isEdgeDevice(DeviceId deviceId); + /** * Returns all segment IDs to be considered in building auto * @@ -54,4 +60,16 @@ public interface DeviceProperties { * @return list of segment IDs */ List<Integer> getAllDeviceSegmentIds(); + + /** + * Returns subnet-to-ports mapping of given device. + * + * For each entry of the map + * Key: a subnet + * Value: a list of ports, which are bound to the subnet + * + * @param deviceId device identifier + * @return a map that contains all subnet-to-ports mapping of given device + */ + Map<Ip4Prefix, List<PortNumber>> getSubnetPortsMap(DeviceId deviceId); } diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/PolicyGroupHandler.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/PolicyGroupHandler.java index e7e87839..e47a6625 100644 --- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/PolicyGroupHandler.java +++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/PolicyGroupHandler.java @@ -54,7 +54,8 @@ public class PolicyGroupHandler extends DefaultGroupHandler { * @param config interface to retrieve the device properties * @param linkService link service object * @param flowObjService flow objective service object - * @param nsNextObjStore next objective store map + * @param nsNextObjStore NeighborSet next objective store map + * @param subnetNextObjStore subnet next objective store map */ public PolicyGroupHandler(DeviceId deviceId, ApplicationId appId, @@ -62,8 +63,11 @@ public class PolicyGroupHandler extends DefaultGroupHandler { LinkService linkService, FlowObjectiveService flowObjService, EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey, - Integer> nsNextObjStore) { - super(deviceId, appId, config, linkService, flowObjService, nsNextObjStore); + Integer> nsNextObjStore, + EventuallyConsistentMap<SubnetNextObjectiveStoreKey, + Integer> subnetNextObjStore) { + super(deviceId, appId, config, linkService, flowObjService, + nsNextObjStore, subnetNextObjStore); } public PolicyGroupIdentifier createPolicyGroupChain(String id, diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/SubnetNextObjectiveStoreKey.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/SubnetNextObjectiveStoreKey.java new file mode 100644 index 00000000..d6b16c7a --- /dev/null +++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/SubnetNextObjectiveStoreKey.java @@ -0,0 +1,78 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.segmentrouting.grouphandler; + +import org.onlab.packet.IpPrefix; +import org.onosproject.net.DeviceId; + +import java.util.Objects; + +/** + * Class definition of Key for Subnet to NextObjective store. + */ +public class SubnetNextObjectiveStoreKey { + private final DeviceId deviceId; + private final IpPrefix prefix; + + public SubnetNextObjectiveStoreKey(DeviceId deviceId, + IpPrefix prefix) { + this.deviceId = deviceId; + this.prefix = prefix; + } + + /** + * Gets device id in this SubnetNextObjectiveStoreKey. + * + * @return device id + */ + public DeviceId deviceId() { + return this.deviceId; + } + + /** + * Gets subnet information in this SubnetNextObjectiveStoreKey. + * + * @return subnet information + */ + public IpPrefix prefix() { + return this.prefix; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof SubnetNextObjectiveStoreKey)) { + return false; + } + SubnetNextObjectiveStoreKey that = + (SubnetNextObjectiveStoreKey) o; + return (Objects.equals(this.deviceId, that.deviceId) && + Objects.equals(this.prefix, that.prefix)); + } + + @Override + public int hashCode() { + return Objects.hash(deviceId, prefix); + } + + @Override + public String toString() { + return "Device: " + deviceId + " Subnet: " + prefix; + } +} |