Route reprogamming using group substitution during next hop movement
Change-Id: Idf8362dac522722ca67747e245bfd836e6ee6292
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
index 6c72a06..e78b152 100644
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
+++ b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
@@ -27,6 +27,7 @@
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.VlanId;
+import org.onlab.packet.MacAddress;
import org.onlab.util.KryoNamespace;
import org.onlab.util.Tools;
import org.onosproject.cfg.ComponentConfigService;
@@ -115,6 +116,7 @@
import org.onosproject.segmentrouting.storekey.DummyVlanIdStoreKey;
import org.onosproject.segmentrouting.storekey.PortNextObjectiveStoreKey;
import org.onosproject.segmentrouting.storekey.VlanNextObjectiveStoreKey;
+import org.onosproject.segmentrouting.storekey.MacVlanNextObjectiveStoreKey;
import org.onosproject.segmentrouting.storekey.XConnectStoreKey;
import org.onosproject.segmentrouting.xconnect.api.XconnectService;
import org.onosproject.store.serializers.KryoNamespaces;
@@ -346,7 +348,7 @@
vlanNextObjStore = null;
/**
* Per device next objective ID store with (device id + port + treatment + meta) as key.
- * Used to keep track on L2 interface group and L3 unicast group information.
+ * Used to keep track on L2 interface group and L3 unicast group information for direct hosts.
*/
private EventuallyConsistentMap<PortNextObjectiveStoreKey, Integer>
portNextObjStore = null;
@@ -358,6 +360,13 @@
private EventuallyConsistentMap<DummyVlanIdStoreKey, VlanId>
dummyVlanIdStore = null;
+ /**
+ * Per device next objective ID store with (device id + MAC address + vlan) as key.
+ * Used to keep track of L3 unicast group for indirect hosts.
+ */
+ private EventuallyConsistentMap<MacVlanNextObjectiveStoreKey, Integer>
+ macVlanNextObjStore = null;
+
private EventuallyConsistentMap<String, Tunnel> tunnelStore = null;
private EventuallyConsistentMap<String, Policy> policyStore = null;
@@ -471,6 +480,15 @@
.withTimestampProvider((k, v) -> new WallClockTimestamp())
.build();
+ log.debug("Creating EC map macvlannextobjectivestore");
+ EventuallyConsistentMapBuilder<MacVlanNextObjectiveStoreKey, Integer>
+ macVlanNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
+ macVlanNextObjStore = macVlanNextObjMapBuilder
+ .withName("macvlannextobjectivestore")
+ .withSerializer(createSerializer())
+ .withTimestampProvider((k, v) -> new WallClockTimestamp())
+ .build();
+
log.debug("Creating EC map subnetnextobjectivestore");
EventuallyConsistentMapBuilder<PortNextObjectiveStoreKey, Integer>
portNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
@@ -602,7 +620,8 @@
L2TunnelPolicy.class,
DefaultL2Tunnel.class,
DefaultL2TunnelPolicy.class,
- DummyVlanIdStoreKey.class
+ DummyVlanIdStoreKey.class,
+ MacVlanNextObjectiveStoreKey.class
);
}
@@ -650,6 +669,7 @@
dsNextObjStore.destroy();
vlanNextObjStore.destroy();
+ macVlanNextObjStore.destroy();
portNextObjStore.destroy();
dummyVlanIdStore.destroy();
tunnelStore.destroy();
@@ -947,6 +967,15 @@
}
@Override
+ public ImmutableMap<MacVlanNextObjectiveStoreKey, Integer> getMacVlanNextObjStore() {
+ if (macVlanNextObjStore != null) {
+ return ImmutableMap.copyOf(macVlanNextObjStore.entrySet());
+ } else {
+ return ImmutableMap.of();
+ }
+ }
+
+ @Override
public ImmutableMap<PortNextObjectiveStoreKey, Integer> getPortNextObjStore() {
if (portNextObjStore != null) {
return ImmutableMap.copyOf(portNextObjStore.entrySet());
@@ -989,6 +1018,13 @@
}
});
}
+ if (macVlanNextObjStore != null) {
+ macVlanNextObjStore.entrySet().forEach(e -> {
+ if (e.getValue() == nextId) {
+ macVlanNextObjStore.remove(e.getKey());
+ }
+ });
+ }
if (portNextObjStore != null) {
portNextObjStore.entrySet().forEach(e -> {
if (e.getValue() == nextId) {
@@ -1109,8 +1145,18 @@
}
/**
+ * Per device next objective ID store with (device id + MAC address + vlan) as key.
+ * Used to keep track on L3 Unicast group information for indirect hosts.
+ *
+ * @return mac vlan next object store
+ */
+ public EventuallyConsistentMap<MacVlanNextObjectiveStoreKey, Integer> macVlanNextObjStore() {
+ return macVlanNextObjStore;
+ }
+
+ /**
* Per device next objective ID store with (device id + port + treatment + meta) as key.
- * Used to keep track on L2 interface group and L3 unicast group information.
+ * Used to keep track on L2 interface group and L3 unicast group information for direct hosts.
*
* @return port next object store.
*/
@@ -1254,6 +1300,76 @@
}
/**
+ * Returns the next Objective ID for the given mac and vlan, given the treatment.
+ * There could be multiple different treatments to the same outport, which
+ * would result in different objectives. If the next object does not exist,
+ * and should be created, a new one is created and its id is returned.
+ *
+ * @param deviceId Device ID
+ * @param macAddr mac of host for which Next ID is required.
+ * @param vlanId vlan of host for which Next ID is required.
+ * @param treatment the actions to apply on the packets (should include outport)
+ * @param meta metadata passed into the creation of a Next Objective if necessary
+ * @param createIfMissing true if a next object should be created if not found
+ * @return next objective ID or -1 if an error occurred during retrieval or creation
+ */
+ public int getMacVlanNextObjectiveId(DeviceId deviceId, MacAddress macAddr, VlanId vlanId,
+ TrafficTreatment treatment,
+ TrafficSelector meta,
+ boolean createIfMissing) {
+ DefaultGroupHandler ghdlr = groupHandlerMap.get(deviceId);
+ if (ghdlr != null) {
+ return ghdlr.getMacVlanNextObjectiveId(macAddr, vlanId, treatment, meta, createIfMissing);
+ } else {
+ log.warn("getMacVlanNextObjectiveId query - groupHandler for device {}"
+ + " not found", deviceId);
+ return -1;
+ }
+ }
+
+ /**
+ * Returns the next ID for the given host port from the store.
+ *
+ * @param deviceId Device ID
+ * @param hostMac mac of host for which Next ID is required.
+ * @param hostVlanId vlan of host for which Next ID is required.
+ * @param port port of device for which next ID is required.
+ * @return next objective ID or -1 if an error occurred during retrieval
+ */
+ public int getNextIdForHostPort(DeviceId deviceId, MacAddress hostMac,
+ VlanId hostVlanId, PortNumber port) {
+ DefaultGroupHandler ghdlr = groupHandlerMap.get(deviceId);
+ if (ghdlr != null) {
+ return ghdlr.getNextIdForHostPort(hostMac, hostVlanId, port);
+ } else {
+ log.warn("getNextIdForHostPort query - groupHandler for device {}"
+ + " not found", deviceId);
+ return -1;
+ }
+ }
+
+ /**
+ * Updates the next objective for the given nextId .
+ *
+ * @param deviceId Device ID
+ * @param hostMac mac of host for which Next obj is to be updated.
+ * @param hostVlanId vlan of host for which Next obj is to be updated.
+ * @param port port with which to update the Next Obj.
+ * @param nextId of Next Obj which needs to be updated.
+ */
+ public void updateMacVlanTreatment(DeviceId deviceId, MacAddress hostMac,
+ VlanId hostVlanId, PortNumber port, int nextId) {
+ DefaultGroupHandler ghdlr = groupHandlerMap.get(deviceId);
+ if (ghdlr != null) {
+ ghdlr.updateL3UcastGroupBucket(hostMac, hostVlanId, port, nextId);
+ } else {
+ log.warn("updateL3UcastGroupBucket query - groupHandler for device {}"
+ + " not found", deviceId);
+ }
+ }
+
+
+ /**
* Returns the group handler object for the specified device id.
*
* @param devId the device identifier
@@ -1584,6 +1700,9 @@
vlanNextObjStore.entrySet().stream()
.filter(entry -> entry.getKey().deviceId().equals(device.id()))
.forEach(entry -> vlanNextObjStore.remove(entry.getKey()));
+ macVlanNextObjStore.entrySet().stream()
+ .filter(entry -> entry.getKey().deviceId().equals(device.id()))
+ .forEach(entry -> macVlanNextObjStore.remove(entry.getKey()));
portNextObjStore.entrySet().stream()
.filter(entry -> entry.getKey().deviceId().equals(device.id()))
.forEach(entry -> portNextObjStore.remove(entry.getKey()));