CORD-800 Use new interface vlan config for VLAN assignment
In addition
- Change the name and type of INTERNAL_VLAN
Change-Id: I48bb89cc1cb1fe4155b4d889b1e7384c8bf673fa
diff --git a/src/main/java/org/onosproject/segmentrouting/ArpHandler.java b/src/main/java/org/onosproject/segmentrouting/ArpHandler.java
index 30c6ada..8f0b7d3 100644
--- a/src/main/java/org/onosproject/segmentrouting/ArpHandler.java
+++ b/src/main/java/org/onosproject/segmentrouting/ArpHandler.java
@@ -135,8 +135,7 @@
// ARP reply for unknown host, Flood in the subnet.
} else {
// Don't flood to non-edge ports
- if (pkt.vlan().equals(
- VlanId.vlanId(SegmentRoutingManager.ASSIGNED_VLAN_NO_SUBNET))) {
+ if (pkt.vlan().equals(SegmentRoutingManager.INTERNAL_VLAN)) {
return;
}
flood(pkt);
diff --git a/src/main/java/org/onosproject/segmentrouting/HostHandler.java b/src/main/java/org/onosproject/segmentrouting/HostHandler.java
index 62ab1ce..b229793 100644
--- a/src/main/java/org/onosproject/segmentrouting/HostHandler.java
+++ b/src/main/java/org/onosproject/segmentrouting/HostHandler.java
@@ -16,10 +16,10 @@
package org.onosproject.segmentrouting;
-import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
+import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.HostLocation;
@@ -42,6 +42,8 @@
import com.google.common.collect.Sets;
import java.util.Set;
+import static org.onosproject.segmentrouting.SegmentRoutingManager.INTERNAL_VLAN;
+
/**
* Handles host-related events.
*/
@@ -258,15 +260,8 @@
private ForwardingObjective.Builder hostFwdObjBuilder(
DeviceId deviceId, MacAddress mac, VlanId vlanId,
PortNumber outport) {
- // Get assigned VLAN for the subnets
- VlanId outvlan = null;
- // FIXME L2 forwarding should consider also IPv6
- Ip4Prefix subnet = srManager.deviceConfiguration.getPortIPv4Subnet(deviceId, outport);
- if (subnet == null) {
- outvlan = VlanId.vlanId(SegmentRoutingManager.ASSIGNED_VLAN_NO_SUBNET);
- } else {
- outvlan = srManager.getSubnetAssignedVlanId(deviceId, subnet);
- }
+ VlanId untaggedVlan = srManager.getUntaggedVlanId(new ConnectPoint(deviceId, outport));
+ VlanId outvlan = (untaggedVlan != null) ? untaggedVlan : INTERNAL_VLAN;
// match rule
TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
diff --git a/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java b/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java
index c924929..16784c2 100644
--- a/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java
+++ b/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java
@@ -387,7 +387,7 @@
/*
* We don't have to flood towards spine facing ports.
*/
- if (pkt.vlan().equals(VlanId.vlanId(SegmentRoutingManager.ASSIGNED_VLAN_NO_SUBNET))) {
+ if (pkt.vlan().equals(SegmentRoutingManager.INTERNAL_VLAN)) {
return;
}
log.debug("Flooding the reply to the subnet");
diff --git a/src/main/java/org/onosproject/segmentrouting/McastHandler.java b/src/main/java/org/onosproject/segmentrouting/McastHandler.java
index f95addc..c1fa518 100644
--- a/src/main/java/org/onosproject/segmentrouting/McastHandler.java
+++ b/src/main/java/org/onosproject/segmentrouting/McastHandler.java
@@ -20,7 +20,6 @@
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.onlab.packet.Ethernet;
-import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
@@ -69,6 +68,7 @@
import java.util.stream.Collectors;
import static com.google.common.base.Preconditions.checkState;
+import static org.onosproject.segmentrouting.SegmentRoutingManager.INTERNAL_VLAN;
/**
* Handles multicast-related events.
@@ -375,19 +375,14 @@
return;
}
- // Reuse unicast VLAN if the port has subnet configured
- Ip4Prefix portSubnet = srManager.deviceConfiguration.getPortIPv4Subnet(deviceId, port);
- VlanId unicastVlan = srManager.getSubnetAssignedVlanId(deviceId, portSubnet);
- final VlanId finalVlanId = (unicastVlan != null) ? unicastVlan : assignedVlan;
-
FilteringObjective.Builder filtObjBuilder =
- filterObjBuilder(deviceId, port, finalVlanId);
+ filterObjBuilder(deviceId, port, assignedVlan);
ObjectiveContext context = new DefaultObjectiveContext(
(objective) -> log.debug("Successfully add filter on {}/{}, vlan {}",
- deviceId, port.toLong(), finalVlanId),
+ deviceId, port.toLong(), assignedVlan),
(objective, error) ->
log.warn("Failed to add filter on {}/{}, vlan {}: {}",
- deviceId, port.toLong(), finalVlanId, error));
+ deviceId, port.toLong(), assignedVlan, error));
srManager.flowObjectiveService.filter(deviceId, filtObjBuilder.add(context));
}
@@ -763,15 +758,11 @@
}
// Reuse unicast VLAN if the port has subnet configured
if (cp != null) {
- Ip4Prefix portSubnet = srManager.deviceConfiguration
- .getPortIPv4Subnet(cp.deviceId(), cp.port());
- VlanId unicastVlan = srManager.getSubnetAssignedVlanId(cp.deviceId(), portSubnet);
- if (unicastVlan != null) {
- return unicastVlan;
- }
+ VlanId untaggedVlan = srManager.getUntaggedVlanId(cp);
+ return (untaggedVlan != null) ? untaggedVlan : INTERNAL_VLAN;
}
- // By default, use VLAN_NO_SUBNET
- return VlanId.vlanId(SegmentRoutingManager.ASSIGNED_VLAN_NO_SUBNET);
+ // Use DEFAULT_VLAN if none of the above matches
+ return SegmentRoutingManager.INTERNAL_VLAN;
}
/**
diff --git a/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java b/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
index 050bb97..54e43d5 100644
--- a/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
+++ b/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
@@ -19,13 +19,13 @@
import org.onlab.packet.EthType;
import org.onlab.packet.Ethernet;
import org.onlab.packet.Ip4Address;
-import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.Ip6Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.MplsLabel;
import org.onlab.packet.VlanId;
+import org.onosproject.incubator.net.intf.Interface;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.flowobjective.DefaultObjectiveContext;
import org.onosproject.net.flowobjective.Objective;
@@ -35,7 +35,6 @@
import org.onosproject.segmentrouting.DefaultRoutingHandler.PortFilterInfo;
import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
import org.onosproject.segmentrouting.config.DeviceConfiguration;
-import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
import org.onosproject.segmentrouting.grouphandler.NeighborSet;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Port;
@@ -62,12 +61,14 @@
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
+import java.util.stream.Collectors;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.onlab.packet.Ethernet.TYPE_ARP;
import static org.onlab.packet.Ethernet.TYPE_IPV6;
import static org.onlab.packet.ICMP6.NEIGHBOR_SOLICITATION;
import static org.onlab.packet.IPv6.PROTOCOL_ICMP6;
+import static org.onosproject.segmentrouting.SegmentRoutingManager.INTERNAL_VLAN;
/**
* Populator of segment routing flow rules.
@@ -203,13 +204,9 @@
// All forwarding is via Groups. Drivers can re-purpose to flow-actions if needed.
// for switch pipelines that need it, provide outgoing vlan as metadata
- VlanId outvlan;
- Ip4Prefix subnet = srManager.deviceConfiguration.getPortIPv4Subnet(deviceId, outPort);
- if (subnet == null) {
- outvlan = VlanId.vlanId(SegmentRoutingManager.ASSIGNED_VLAN_NO_SUBNET);
- } else {
- outvlan = srManager.getSubnetAssignedVlanId(deviceId, subnet);
- }
+ VlanId untaggedVlan = srManager.getUntaggedVlanId(new ConnectPoint(deviceId, outPort));
+ VlanId outvlan = (untaggedVlan != null) ? untaggedVlan : INTERNAL_VLAN;
+
TrafficSelector meta = DefaultTrafficSelector.builder()
.matchVlanId(outvlan).build();
int portNextObjId = srManager.getPortNextObjectiveId(deviceId, outPort,
@@ -307,8 +304,7 @@
// if needed by the switch pipeline. Since neighbor sets are always to
// other neighboring routers, there is no subnet assigned on those ports.
TrafficSelector.Builder metabuilder = DefaultTrafficSelector.builder(selector);
- metabuilder.matchVlanId(
- VlanId.vlanId(SegmentRoutingManager.ASSIGNED_VLAN_NO_SUBNET));
+ metabuilder.matchVlanId(SegmentRoutingManager.INTERNAL_VLAN);
int nextId = srManager.getNextObjectiveId(deviceId, ns, metabuilder.build());
if (nextId <= 0) {
@@ -404,8 +400,7 @@
// if needed by the switch pipeline. Since mpls next-hops are always to
// other neighboring routers, there is no subnet assigned on those ports.
TrafficSelector.Builder metabuilder = DefaultTrafficSelector.builder(selector);
- metabuilder.matchVlanId(
- VlanId.vlanId(SegmentRoutingManager.ASSIGNED_VLAN_NO_SUBNET));
+ metabuilder.matchVlanId(SegmentRoutingManager.INTERNAL_VLAN);
if (nextHops.size() == 1 && destSwId.equals(nextHops.toArray()[0])) {
// If the next hop is the destination router for the segment, do pop
@@ -679,7 +674,6 @@
return;
}
-
private FilteringObjective.Builder buildFilteringObjective(DeviceId deviceId,
PortNumber portnum) {
MacAddress deviceMac;
@@ -691,23 +685,9 @@
}
// suppressed ports still have filtering rules pushed by SR using default vlan
ConnectPoint connectPoint = new ConnectPoint(deviceId, portnum);
- boolean isSuppressed = false;
- SegmentRoutingAppConfig appConfig = srManager.cfgService
- .getConfig(srManager.appId, SegmentRoutingAppConfig.class);
- if (appConfig != null && appConfig.suppressSubnet().contains(connectPoint)) {
- isSuppressed = true;
- }
- Ip4Prefix portSubnet = config.getPortIPv4Subnet(deviceId, portnum);
- VlanId assignedVlan = (portSubnet == null || isSuppressed)
- ? VlanId.vlanId(SegmentRoutingManager.ASSIGNED_VLAN_NO_SUBNET)
- : srManager.getSubnetAssignedVlanId(deviceId, portSubnet);
-
- if (assignedVlan == null) {
- log.warn("Assigned vlan is null for {} in {} - Processing "
- + "SinglePortFilters aborted", portnum, deviceId);
- return null;
- }
+ VlanId untaggedVlan = srManager.getUntaggedVlanId(connectPoint);
+ VlanId assignedVlan = (untaggedVlan != null) ? untaggedVlan : INTERNAL_VLAN;
FilteringObjective.Builder fob = DefaultFilteringObjective.builder();
fob.withKey(Criteria.matchInPort(portnum))
@@ -870,22 +850,20 @@
* @param deviceId switch ID to set the rules
*/
public void populateSubnetBroadcastRule(DeviceId deviceId) {
- config.getSubnets(deviceId).forEach(subnet -> {
- if (subnet.isIp4()) {
- if (subnet.prefixLength() == 0 || subnet.prefixLength() == IpPrefix.MAX_INET_MASK_LENGTH) {
- return;
- }
- } else {
- if (subnet.prefixLength() == 0 || subnet.prefixLength() == IpPrefix.MAX_INET6_MASK_LENGTH) {
- return;
- }
- }
- int nextId = srManager.getSubnetNextObjectiveId(deviceId, subnet);
- VlanId vlanId = srManager.getSubnetAssignedVlanId(deviceId, subnet);
+ Set<Interface> interfaces = srManager.interfaceService.getInterfaces();
+ Set<VlanId> vlans =
+ interfaces.stream()
+ .filter(intf -> intf.connectPoint().deviceId().equals(deviceId) &&
+ !intf.vlanUntagged().equals(VlanId.NONE))
+ .map(Interface::vlanUntagged)
+ .collect(Collectors.toSet());
- if (nextId < 0 || vlanId == null) {
- log.error("Cannot install subnet {} broadcast rule in dev:{} due"
- + "to vlanId:{} or nextId:{}", subnet, deviceId, vlanId, nextId);
+ vlans.forEach(vlanId -> {
+ int nextId = srManager.getVlanNextObjectiveId(deviceId, vlanId);
+
+ if (nextId < 0) {
+ log.error("Cannot install vlan {} broadcast rule in dev:{} due"
+ + "to vlanId:{} or nextId:{}", vlanId, deviceId, vlanId, nextId);
return;
}
@@ -903,9 +881,9 @@
.fromApp(srManager.appId)
.makePermanent();
ObjectiveContext context = new DefaultObjectiveContext(
- (objective) -> log.debug("Subnet broadcast rule for {} populated", subnet),
+ (objective) -> log.debug("Vlan broadcast rule for {} populated", vlanId),
(objective, error) ->
- log.warn("Failed to populate subnet broadcast rule for {}: {}", subnet, error));
+ log.warn("Failed to populate vlan broadcast rule for {}: {}", vlanId, error));
srManager.flowObjectiveService.forward(deviceId, fob.add(context));
});
}
diff --git a/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java b/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
index 8cd657b..0c30cef 100644
--- a/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
+++ b/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
@@ -26,7 +26,6 @@
import org.onlab.packet.ICMP6;
import org.onlab.packet.IPv4;
import org.onlab.packet.IPv6;
-import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.VlanId;
import org.onlab.util.KryoNamespace;
@@ -88,7 +87,7 @@
import org.onosproject.segmentrouting.storekey.NeighborSetNextObjectiveStoreKey;
import org.onosproject.segmentrouting.storekey.PortNextObjectiveStoreKey;
import org.onosproject.segmentrouting.storekey.SubnetAssignedVidStoreKey;
-import org.onosproject.segmentrouting.storekey.SubnetNextObjectiveStoreKey;
+import org.onosproject.segmentrouting.storekey.VlanNextObjectiveStoreKey;
import org.onosproject.segmentrouting.storekey.XConnectStoreKey;
import org.onosproject.segmentrouting.pwaas.L2TunnelHandler;
import org.onosproject.store.serializers.KryoNamespaces;
@@ -102,8 +101,6 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.Collections;
-import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -113,7 +110,6 @@
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
import static com.google.common.base.Preconditions.checkState;
import static org.onlab.packet.Ethernet.TYPE_ARP;
@@ -224,17 +220,14 @@
/**
* Per device next objective ID store with (device id + subnet) as key.
*/
- public EventuallyConsistentMap<SubnetNextObjectiveStoreKey, Integer>
- subnetNextObjStore = null;
+ public EventuallyConsistentMap<VlanNextObjectiveStoreKey, Integer>
+ vlanNextObjStore = null;
/**
* Per device next objective ID store with (device id + port) as key.
*/
public EventuallyConsistentMap<PortNextObjectiveStoreKey, Integer>
portNextObjStore = null;
- // Per device, per-subnet assigned-vlans store, with (device id + subnet
- // IPv4 prefix) as key
- private EventuallyConsistentMap<SubnetAssignedVidStoreKey, VlanId>
- subnetVidStore = null;
+
private EventuallyConsistentMap<String, Tunnel> tunnelStore = null;
private EventuallyConsistentMap<String, Policy> policyStore = null;
@@ -298,14 +291,11 @@
* Segment Routing App ID.
*/
public static final String APP_NAME = "org.onosproject.segmentrouting";
- /**
- * The starting value of per-subnet VLAN ID assignment.
- */
- private static final short ASSIGNED_VLAN_START = 4093;
+
/**
* The default VLAN ID assigned to the interfaces without subnet config.
*/
- public static final short ASSIGNED_VLAN_NO_SUBNET = 4094;
+ public static final VlanId INTERNAL_VLAN = VlanId.vlanId((short) 4094);
@Activate
protected void activate() {
@@ -321,11 +311,11 @@
.build();
log.trace("Current size {}", nsNextObjStore.size());
- log.debug("Creating EC map subnetnextobjectivestore");
- EventuallyConsistentMapBuilder<SubnetNextObjectiveStoreKey, Integer>
- subnetNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
- subnetNextObjStore = subnetNextObjMapBuilder
- .withName("subnetnextobjectivestore")
+ log.debug("Creating EC map vlannextobjectivestore");
+ EventuallyConsistentMapBuilder<VlanNextObjectiveStoreKey, Integer>
+ vlanNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
+ vlanNextObjStore = vlanNextObjMapBuilder
+ .withName("vlannextobjectivestore")
.withSerializer(createSerializer())
.withTimestampProvider((k, v) -> new WallClockTimestamp())
.build();
@@ -355,14 +345,6 @@
.withTimestampProvider((k, v) -> new WallClockTimestamp())
.build();
- EventuallyConsistentMapBuilder<SubnetAssignedVidStoreKey, VlanId>
- subnetVidStoreMapBuilder = storageService.eventuallyConsistentMapBuilder();
- subnetVidStore = subnetVidStoreMapBuilder
- .withName("subnetvidstore")
- .withSerializer(createSerializer())
- .withTimestampProvider((k, v) -> new WallClockTimestamp())
- .build();
-
compCfgService.preSetProperty("org.onosproject.net.group.impl.GroupManager",
"purgeOnDisconnection", "true");
compCfgService.preSetProperty("org.onosproject.net.flow.impl.FlowRuleManager",
@@ -413,7 +395,7 @@
return new KryoNamespace.Builder()
.register(KryoNamespaces.API)
.register(NeighborSetNextObjectiveStoreKey.class,
- SubnetNextObjectiveStoreKey.class,
+ VlanNextObjectiveStoreKey.class,
SubnetAssignedVidStoreKey.class,
NeighborSet.class,
Tunnel.class,
@@ -450,11 +432,10 @@
groupHandlerMap.clear();
nsNextObjStore.destroy();
- subnetNextObjStore.destroy();
+ vlanNextObjStore.destroy();
portNextObjStore.destroy();
tunnelStore.destroy();
policyStore.destroy();
- subnetVidStore.destroy();
log.info("Stopped");
}
@@ -539,69 +520,16 @@
}
/**
- * 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.
+ * Returns untagged VLAN configured on given connect point.
*
- * @param deviceId switch dpid
- * @param subnet IP 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.
+ * @param connectPoint connect point
+ * @return untagged VLAN or null if not configured
*/
- // TODO: We should avoid assigning VLAN IDs that are used by VLAN cross-connection.
- public VlanId getSubnetAssignedVlanId(DeviceId deviceId, IpPrefix 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
- // FIXME for now we will do assignment considering only the ipv4 subnet.
- Set<Ip4Prefix> configuredSubnets = deviceConfiguration.getSubnets(deviceId)
- .stream()
- .filter(IpPrefix::isIp4)
- .map(IpPrefix::getIp4Prefix)
- .collect(Collectors.toSet());
- 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 subnetVidStore.get(new SubnetAssignedVidStoreKey(deviceId, subnet));
+ public VlanId getUntaggedVlanId(ConnectPoint connectPoint) {
+ return interfaceService.getInterfacesByPort(connectPoint).stream()
+ .filter(intf -> !intf.vlanUntagged().equals(VlanId.NONE))
+ .map(Interface::vlanUntagged)
+ .findFirst().orElse(null);
}
/**
@@ -648,19 +576,19 @@
/**
* Returns the next objective ID for the given subnet prefix. It is expected
+ * Returns the next objective ID for the given vlan id. It is expected
* that the next-objective has been pre-created from configuration.
*
* @param deviceId Device ID
- * @param prefix Subnet
+ * @param vlanId VLAN ID
* @return next objective ID or -1 if it was not found
*/
- public int getSubnetNextObjectiveId(DeviceId deviceId, IpPrefix prefix) {
+ public int getVlanNextObjectiveId(DeviceId deviceId, VlanId vlanId) {
if (groupHandlerMap.get(deviceId) != null) {
- log.trace("getSubnetNextObjectiveId query in device {}", deviceId);
- return groupHandlerMap
- .get(deviceId).getSubnetNextObjectiveId(prefix);
+ log.trace("getVlanNextObjectiveId query in device {}", deviceId);
+ return groupHandlerMap.get(deviceId).getVlanNextObjectiveId(vlanId);
} else {
- log.warn("getSubnetNextObjectiveId query - groupHandler for "
+ log.warn("getVlanNextObjectiveId query - groupHandler for "
+ "device {} not found", deviceId);
return -1;
}
@@ -963,7 +891,7 @@
xConnectHandler.init(deviceId);
cordConfigHandler.init(deviceId);
DefaultGroupHandler groupHandler = groupHandlerMap.get(deviceId);
- groupHandler.createGroupsFromSubnetConfig();
+ groupHandler.createGroupsFromVlanConfig();
routingRulePopulator.populateSubnetBroadcastRule(deviceId);
}
@@ -977,21 +905,16 @@
.forEach(entry -> {
nsNextObjStore.remove(entry.getKey());
});
- subnetNextObjStore.entrySet().stream()
+ vlanNextObjStore.entrySet().stream()
.filter(entry -> entry.getKey().deviceId().equals(device.id()))
.forEach(entry -> {
- subnetNextObjStore.remove(entry.getKey());
+ vlanNextObjStore.remove(entry.getKey());
});
portNextObjStore.entrySet().stream()
.filter(entry -> entry.getKey().deviceId().equals(device.id()))
.forEach(entry -> {
portNextObjStore.remove(entry.getKey());
});
- subnetVidStore.entrySet().stream()
- .filter(entry -> entry.getKey().deviceId().equals(device.id()))
- .forEach(entry -> {
- subnetVidStore.remove(entry.getKey());
- });
groupHandlerMap.remove(device.id());
defaultRoutingHandler.purgeEcmpGraph(device.id());
mcastHandler.removeDevice(device.id());
@@ -1028,29 +951,30 @@
// to switch ports, link-events should take care of any re-routing or
// group editing necessary for port up/down. Here we only process edge ports
// that are already configured.
- Ip4Prefix configuredSubnet = deviceConfiguration.getPortIPv4Subnet(device.id(),
- port.number());
- if (configuredSubnet == null) {
+ VlanId untaggedVlan = getUntaggedVlanId(new ConnectPoint(device.id(), port.number()));
+ VlanId vlanId = (untaggedVlan != null) ? untaggedVlan : INTERNAL_VLAN;
+
+ if (vlanId.equals(INTERNAL_VLAN)) {
log.debug("Not handling port updated event for unconfigured port "
+ "dev/port: {}/{}", device.id(), port.number());
return;
}
- processEdgePort(device, port, configuredSubnet);
+ processEdgePort(device, port, vlanId);
}
- private void processEdgePort(Device device, Port port, Ip4Prefix subnet) {
+ private void processEdgePort(Device device, Port port, VlanId vlanId) {
boolean portUp = port.isEnabled();
if (portUp) {
log.info("Device:EdgePort {}:{} is enabled in subnet: {}", device.id(),
- port.number(), subnet);
+ port.number(), vlanId);
} else {
log.info("Device:EdgePort {}:{} is disabled in subnet: {}", device.id(),
- port.number(), subnet);
+ port.number(), vlanId);
}
DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
if (groupHandler != null) {
- groupHandler.processEdgePort(port.number(), subnet, portUp);
+ groupHandler.processEdgePort(port.number(), vlanId, portUp);
} else {
log.warn("Group handler not found for dev:{}. Not handling edge port"
+ " {} event for port:{}", device.id(),
diff --git a/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java b/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
index 0e8f220..2b1a8c2 100644
--- a/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
+++ b/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
@@ -15,15 +15,16 @@
*/
package org.onosproject.segmentrouting.grouphandler;
+
import com.google.common.collect.Iterables;
import org.apache.commons.lang3.RandomUtils;
-import org.onlab.packet.Ip4Prefix;
-import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.MplsLabel;
import org.onlab.packet.VlanId;
import org.onlab.util.KryoNamespace;
import org.onosproject.core.ApplicationId;
+import org.onosproject.incubator.net.intf.Interface;
+import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.PortNumber;
@@ -42,7 +43,7 @@
import org.onosproject.segmentrouting.config.DeviceProperties;
import org.onosproject.segmentrouting.storekey.NeighborSetNextObjectiveStoreKey;
import org.onosproject.segmentrouting.storekey.PortNextObjectiveStoreKey;
-import org.onosproject.segmentrouting.storekey.SubnetNextObjectiveStoreKey;
+import org.onosproject.segmentrouting.storekey.VlanNextObjectiveStoreKey;
import org.onosproject.store.service.EventuallyConsistentMap;
import org.slf4j.Logger;
@@ -57,6 +58,7 @@
import java.util.stream.Collectors;
import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onosproject.segmentrouting.SegmentRoutingManager.INTERNAL_VLAN;
import static org.slf4j.LoggerFactory.getLogger;
/**
@@ -88,8 +90,8 @@
protected EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey, Integer>
nsNextObjStore = null;
// distributed store for (device+subnet-ip-prefix) mapped to next-id
- protected EventuallyConsistentMap<SubnetNextObjectiveStoreKey, Integer>
- subnetNextObjStore = null;
+ protected EventuallyConsistentMap<VlanNextObjectiveStoreKey, Integer>
+ vlanNextObjStore = null;
// distributed store for (device+port+treatment) mapped to next-id
protected EventuallyConsistentMap<PortNextObjectiveStoreKey, Integer>
portNextObjStore = null;
@@ -124,7 +126,7 @@
}
this.flowObjectiveService = flowObjService;
this.nsNextObjStore = srManager.nsNextObjStore;
- this.subnetNextObjStore = srManager.subnetNextObjStore;
+ this.vlanNextObjStore = srManager.vlanNextObjStore;
this.portNextObjStore = srManager.portNextObjStore;
this.srManager = srManager;
@@ -247,8 +249,7 @@
// if needed by the switch pipeline. Since hashed next-hops are always to
// other neighboring routers, there is no subnet assigned on those ports.
TrafficSelector.Builder metabuilder = DefaultTrafficSelector.builder();
- metabuilder.matchVlanId(
- VlanId.vlanId(SegmentRoutingManager.ASSIGNED_VLAN_NO_SUBNET));
+ metabuilder.matchVlanId(INTERNAL_VLAN);
NextObjective.Builder nextObjBuilder = DefaultNextObjective.builder()
.withId(nextId)
@@ -363,20 +364,20 @@
* Should only be called by the master instance for this device/port.
*
* @param port the port on this device that needs to be added/removed to a bcast group
- * @param subnet the subnet corresponding to the broadcast group
+ * @param vlanId the vlan id corresponding to the broadcast group
* @param portUp true if port is enabled, false if disabled
*/
- public void processEdgePort(PortNumber port, Ip4Prefix subnet, boolean portUp) {
+ public void processEdgePort(PortNumber port, VlanId vlanId, boolean portUp) {
//get the next id for the subnet and edit it.
- Integer nextId = getSubnetNextObjectiveId(subnet);
+ Integer nextId = getVlanNextObjectiveId(vlanId);
if (nextId == -1) {
if (portUp) {
log.debug("**Creating flooding group for first port enabled in"
- + " subnet {} on dev {} port {}", subnet, deviceId, port);
- createBcastGroupFromSubnet(subnet, Collections.singletonList(port));
+ + " subnet {} on dev {} port {}", vlanId, deviceId, port);
+ createBcastGroupFromVlan(vlanId, Collections.singleton(port));
} else {
log.warn("Could not find flooding group for subnet {} on dev:{} when"
- + " removing port:{}", subnet, deviceId, port);
+ + " removing port:{}", vlanId, deviceId, port);
}
return;
}
@@ -390,8 +391,9 @@
tBuilder.popVlan();
tBuilder.setOutput(port);
- VlanId assignedVlanId =
- srManager.getSubnetAssignedVlanId(this.deviceId, subnet);
+ VlanId untaggedVlan = srManager.getUntaggedVlanId(new ConnectPoint(deviceId, port));
+ VlanId assignedVlanId = (untaggedVlan != null) ? untaggedVlan : INTERNAL_VLAN;
+
TrafficSelector metadata =
DefaultTrafficSelector.builder().matchVlanId(assignedVlanId).build();
@@ -460,18 +462,18 @@
}
/**
- * Returns the next objective of type broadcast associated with the subnet,
+ * Returns the next objective of type broadcast associated with the vlan,
* or -1 if no such objective exists. Note that this method does NOT create
* the next objective as a side-effect. It is expected that is objective is
* created at startup from network configuration. Typically this is used
* for L2 flooding within the subnet configured on the switch.
*
- * @param prefix subnet information
+ * @param vlanId vlan id
* @return int if found or -1
*/
- public int getSubnetNextObjectiveId(IpPrefix prefix) {
- Integer nextId = subnetNextObjStore.
- get(new SubnetNextObjectiveStoreKey(deviceId, prefix));
+ public int getVlanNextObjectiveId(VlanId vlanId) {
+ Integer nextId = vlanNextObjStore.
+ get(new VlanNextObjectiveStoreKey(deviceId, vlanId));
return (nextId != null) ? nextId : -1;
}
@@ -733,43 +735,43 @@
* Creates broadcast groups for all ports in the same subnet for
* all configured subnets.
*/
- public void createGroupsFromSubnetConfig() {
- Map<IpPrefix, List<PortNumber>> subnetPortMap;
- try {
- subnetPortMap = this.deviceConfig.getSubnetPortsMap(this.deviceId);
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage()
- + " Not creating broadcast groups for device: " + deviceId);
- return;
- }
- // Construct a broadcast group for each subnet
- subnetPortMap.forEach((subnet, ports) -> {
- if (subnet.isIp4()) {
- createBcastGroupFromSubnet(subnet.getIp4Prefix(), ports);
- }
+ public void createGroupsFromVlanConfig() {
+ Set<Interface> interfaces = srManager.interfaceService.getInterfaces();
+ Set<VlanId> vlans =
+ interfaces.stream()
+ .filter(intf -> intf.connectPoint().deviceId().equals(deviceId) &&
+ !intf.vlanUntagged().equals(VlanId.NONE))
+ .map(Interface::vlanUntagged)
+ .collect(Collectors.toSet());
+
+ vlans.forEach(vlanId -> {
+ Set<PortNumber> ports = interfaces.stream()
+ .filter(intf -> intf.connectPoint().deviceId().equals(deviceId) &&
+ intf.vlanUntagged().equals(vlanId))
+ .map(Interface::connectPoint)
+ .map(ConnectPoint::port)
+ .collect(Collectors.toSet());
+ createBcastGroupFromVlan(vlanId, ports);
});
}
/**
- * Creates a single broadcast group from a given subnet and list of ports.
+ * Creates a single broadcast group from a given vlan id and list of ports.
*
- * @param subnet a configured subnet
+ * @param vlanId vlan id
* @param ports list of ports in the subnet
*/
- public void createBcastGroupFromSubnet(Ip4Prefix subnet, List<PortNumber> ports) {
- SubnetNextObjectiveStoreKey key =
- new SubnetNextObjectiveStoreKey(deviceId, subnet);
+ public void createBcastGroupFromVlan(VlanId vlanId, Set<PortNumber> ports) {
+ VlanNextObjectiveStoreKey key = new VlanNextObjectiveStoreKey(deviceId, vlanId);
- if (subnetNextObjStore.containsKey(key)) {
+ if (vlanNextObjStore.containsKey(key)) {
log.debug("Broadcast group for device {} and subnet {} exists",
- deviceId, subnet);
+ deviceId, vlanId);
return;
}
- VlanId assignedVlanId =
- srManager.getSubnetAssignedVlanId(this.deviceId, subnet);
TrafficSelector metadata =
- DefaultTrafficSelector.builder().matchVlanId(assignedVlanId).build();
+ DefaultTrafficSelector.builder().matchVlanId(vlanId).build();
int nextId = flowObjectiveService.allocateNextId();
@@ -787,10 +789,10 @@
NextObjective nextObj = nextObjBuilder.add();
flowObjectiveService.next(deviceId, nextObj);
- log.debug("createBcastGroupFromSubnet: Submited next objective {} in device {}",
+ log.debug("createBcastGroupFromVlan: Submited next objective {} in device {}",
nextId, deviceId);
- subnetNextObjStore.put(key, nextId);
+ vlanNextObjStore.put(key, nextId);
}
/**
@@ -870,8 +872,8 @@
portNextObjStore.entrySet()) {
removeGroup(entry.getValue());
}
- for (Map.Entry<SubnetNextObjectiveStoreKey, Integer> entry:
- subnetNextObjStore.entrySet()) {
+ for (Map.Entry<VlanNextObjectiveStoreKey, Integer> entry:
+ vlanNextObjStore.entrySet()) {
removeGroup(entry.getValue());
}
// should probably clean local stores port-neighbor
diff --git a/src/main/java/org/onosproject/segmentrouting/storekey/SubnetNextObjectiveStoreKey.java b/src/main/java/org/onosproject/segmentrouting/storekey/SubnetNextObjectiveStoreKey.java
deleted file mode 100644
index c6e9246..0000000
--- a/src/main/java/org/onosproject/segmentrouting/storekey/SubnetNextObjectiveStoreKey.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2016-present 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.storekey;
-
-import org.onlab.packet.IpPrefix;
-import org.onosproject.net.DeviceId;
-
-import java.util.Objects;
-
-/**
- * Key of Subnet to NextObjective store.
- */
-public class SubnetNextObjectiveStoreKey {
- private final DeviceId deviceId;
- private final IpPrefix prefix;
-
- /**
- * Constructs the key of subnet next objective store.
- *
- * @param deviceId device ID
- * @param prefix subnet information
- */
- 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;
- }
-}
diff --git a/src/main/java/org/onosproject/segmentrouting/storekey/VlanNextObjectiveStoreKey.java b/src/main/java/org/onosproject/segmentrouting/storekey/VlanNextObjectiveStoreKey.java
new file mode 100644
index 0000000..3edb9c8
--- /dev/null
+++ b/src/main/java/org/onosproject/segmentrouting/storekey/VlanNextObjectiveStoreKey.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2016-present 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.storekey;
+
+import org.onlab.packet.VlanId;
+import org.onosproject.net.DeviceId;
+
+import java.util.Objects;
+
+/**
+ * Key of VLAN to NextObjective store.
+ */
+public class VlanNextObjectiveStoreKey {
+ private final DeviceId deviceId;
+ private final VlanId vlanId;
+
+ /**
+ * Constructs the key of VLAN next objective store.
+ *
+ * @param deviceId device ID
+ * @param vlanId VLAN information
+ */
+ public VlanNextObjectiveStoreKey(DeviceId deviceId,
+ VlanId vlanId) {
+ this.deviceId = deviceId;
+ this.vlanId = vlanId;
+ }
+
+ /**
+ * Gets device id in this VlanNextObjectiveStoreKey.
+ *
+ * @return device id
+ */
+ public DeviceId deviceId() {
+ return this.deviceId;
+ }
+
+ /**
+ * Gets vlan information in this VlanNextObjectiveStoreKey.
+ *
+ * @return vlan id
+ */
+ public VlanId vlanId() {
+ return this.vlanId;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof VlanNextObjectiveStoreKey)) {
+ return false;
+ }
+ VlanNextObjectiveStoreKey that =
+ (VlanNextObjectiveStoreKey) o;
+ return (Objects.equals(this.deviceId, that.deviceId) &&
+ Objects.equals(this.vlanId, that.vlanId));
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(deviceId, vlanId);
+ }
+
+ @Override
+ public String toString() {
+ return "deviceId: " + deviceId + " vlanId: " + vlanId;
+ }
+}