[CORD-200] Improves Segment Routing using Network Configuration Subsystem
The missing part of gerrit #5533
Change-Id: I0830aa80f9be0e9933a99e0c12518aef67008a53
diff --git a/src/main/java/org/onosproject/segmentrouting/DeviceConfiguration.java b/src/main/java/org/onosproject/segmentrouting/DeviceConfiguration.java
index c4bb8c8..8fdf81a 100644
--- a/src/main/java/org/onosproject/segmentrouting/DeviceConfiguration.java
+++ b/src/main/java/org/onosproject/segmentrouting/DeviceConfiguration.java
@@ -19,7 +19,12 @@
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.MacAddress;
+import org.onosproject.incubator.net.config.basics.ConfigException;
+import org.onosproject.incubator.net.config.basics.InterfaceConfig;
+import org.onosproject.incubator.net.intf.Interface;
+import org.onosproject.net.ConnectPoint;
import org.onosproject.net.config.NetworkConfigRegistry;
+import org.onosproject.net.host.InterfaceIpAddress;
import org.onosproject.segmentrouting.config.SegmentRoutingConfig;
import org.onosproject.segmentrouting.config.SegmentRoutingConfig.AdjacencySid;
import org.onosproject.segmentrouting.grouphandler.DeviceProperties;
@@ -28,8 +33,6 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import static com.google.common.base.Preconditions.checkNotNull;
-
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -49,7 +52,6 @@
.getLogger(DeviceConfiguration.class);
private final List<Integer> allSegmentIds = new ArrayList<>();
private final HashMap<DeviceId, SegmentRouterInfo> deviceConfigMap = new HashMap<>();
- private final NetworkConfigRegistry configService;
private class SegmentRouterInfo {
int nodeSid;
@@ -65,33 +67,54 @@
/**
* Constructor. Reads all the configuration for all devices of type
* Segment Router and organizes into various maps for easier access.
- *
- * @param cfgService handle to network configuration manager
- * component from where the relevant configuration is retrieved.
*/
public DeviceConfiguration(NetworkConfigRegistry cfgService) {
- this.configService = checkNotNull(cfgService);
-
- Set<DeviceId> subjectSet =
+ // Read config from device subject, excluding gatewayIps and subnets.
+ Set<DeviceId> deviceSubjects =
cfgService.getSubjects(DeviceId.class, SegmentRoutingConfig.class);
-
- subjectSet.forEach(subject -> {
+ deviceSubjects.forEach(subject -> {
SegmentRoutingConfig config =
cfgService.getConfig(subject, SegmentRoutingConfig.class);
SegmentRouterInfo info = new SegmentRouterInfo();
- info.nodeSid = config.getSid();
info.deviceId = subject;
+ info.nodeSid = config.getSid();
info.ip = config.getIp();
info.mac = config.getMac();
info.isEdge = config.isEdgeRouter();
- // TODO fecth subnet and gateway information via port subject
+ info.adjacencySids = config.getAdjacencySids();
info.gatewayIps = new HashMap<>();
info.subnets = new HashMap<>();
- info.adjacencySids = config.getAdjacencySids();
this.deviceConfigMap.put(info.deviceId, info);
this.allSegmentIds.add(info.nodeSid);
});
+
+ // Read gatewayIps and subnets from port subject.
+ Set<ConnectPoint> portSubjects =
+ cfgService.getSubjects(ConnectPoint.class, InterfaceConfig.class);
+ portSubjects.forEach(subject -> {
+ InterfaceConfig config =
+ cfgService.getConfig(subject, InterfaceConfig.class);
+ Set<Interface> networkInterfaces;
+ try {
+ networkInterfaces = config.getInterfaces();
+ } catch (ConfigException e) {
+ log.error("Error loading port configuration");
+ return;
+ }
+ networkInterfaces.forEach(networkInterface -> {
+ DeviceId dpid = networkInterface.connectPoint().deviceId();
+ PortNumber port = networkInterface.connectPoint().port();
+ SegmentRouterInfo info = this.deviceConfigMap.get(dpid);
+
+ Set<InterfaceIpAddress> interfaceAddresses = networkInterface.ipAddresses();
+ interfaceAddresses.forEach(interfaceAddress -> {
+ info.gatewayIps.put(port, interfaceAddress.ipAddress().getIp4Address());
+ info.subnets.put(port, interfaceAddress.subnetAddress().getIp4Prefix());
+ });
+ });
+
+ });
}
/**
@@ -370,7 +393,7 @@
public List<Integer> getPortsForAdjacencySid(DeviceId deviceId, int sid) {
if (deviceConfigMap.get(deviceId) != null) {
for (AdjacencySid asid : deviceConfigMap.get(deviceId).adjacencySids) {
- if (asid.getSid() == sid) {
+ if (asid.getAsid() == sid) {
return asid.getPorts();
}
}
@@ -394,7 +417,7 @@
} else {
for (AdjacencySid asid:
deviceConfigMap.get(deviceId).adjacencySids) {
- if (asid.getSid() == sid) {
+ if (asid.getAsid() == sid) {
return true;
}
}
diff --git a/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java b/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
index 764bed3..0566312 100644
--- a/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
+++ b/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
@@ -141,7 +141,9 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected NetworkConfigRegistry cfgService;
- private final InternalConfigListener cfgListener = new InternalConfigListener();
+ private final InternalConfigListener cfgListener =
+ new InternalConfigListener(this);
+
private final ConfigFactory cfgFactory =
new ConfigFactory(SubjectFactories.DEVICE_SUBJECT_FACTORY,
SegmentRoutingConfig.class,
@@ -211,40 +213,8 @@
cfgService.addListener(cfgListener);
cfgService.registerConfigFactory(cfgFactory);
- deviceConfiguration = new DeviceConfiguration(cfgService);
- arpHandler = new ArpHandler(this);
- icmpHandler = new IcmpHandler(this);
- ipHandler = new IpHandler(this);
- routingRulePopulator = new RoutingRulePopulator(this);
- defaultRoutingHandler = new DefaultRoutingHandler(this);
- tunnelHandler = new TunnelHandler(linkService, deviceConfiguration,
- groupHandlerMap, tunnelStore);
- policyHandler = new PolicyHandler(appId, deviceConfiguration,
- flowObjectiveService, tunnelHandler, policyStore);
-
- packetService.addProcessor(processor, PacketProcessor.director(2));
- linkService.addListener(new InternalLinkListener());
- deviceService.addListener(new InternalDeviceListener());
-
- 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
- DefaultGroupHandler groupHandler = DefaultGroupHandler
- .createGroupHandler(device.id(), appId,
- deviceConfiguration, linkService,
- flowObjectiveService,
- nsNextObjStore);
- groupHandlerMap.put(device.id(), groupHandler);
- defaultRoutingHandler.populateTtpRules(device.id());
- }
-
- defaultRoutingHandler.startPopulationProcess();
log.info("Started");
-
}
@Deactivate
@@ -535,12 +505,56 @@
}
private class InternalConfigListener implements NetworkConfigListener {
+ SegmentRoutingManager segmentRoutingManager;
+
+ public InternalConfigListener(SegmentRoutingManager srMgr) {
+ this.segmentRoutingManager = srMgr;
+ }
+
+ public void configureNetwork() {
+ deviceConfiguration = new DeviceConfiguration(segmentRoutingManager.cfgService);
+
+ arpHandler = new ArpHandler(segmentRoutingManager);
+ icmpHandler = new IcmpHandler(segmentRoutingManager);
+ ipHandler = new IpHandler(segmentRoutingManager);
+ routingRulePopulator = new RoutingRulePopulator(segmentRoutingManager);
+ defaultRoutingHandler = new DefaultRoutingHandler(segmentRoutingManager);
+
+ tunnelHandler = new TunnelHandler(linkService, deviceConfiguration,
+ groupHandlerMap, tunnelStore);
+ policyHandler = new PolicyHandler(appId, deviceConfiguration,
+ flowObjectiveService,
+ tunnelHandler, policyStore);
+
+ packetService.addProcessor(processor, PacketProcessor.director(2));
+ linkService.addListener(new InternalLinkListener());
+ deviceService.addListener(new InternalDeviceListener());
+
+ 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
+ DefaultGroupHandler groupHandler = DefaultGroupHandler
+ .createGroupHandler(device.id(), appId,
+ deviceConfiguration, linkService,
+ flowObjectiveService,
+ nsNextObjStore);
+ groupHandlerMap.put(device.id(), groupHandler);
+ defaultRoutingHandler.populateTtpRules(device.id());
+ }
+
+ defaultRoutingHandler.startPopulationProcess();
+ }
+
@Override
public void event(NetworkConfigEvent event) {
if ((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED) &&
event.configClass().equals(SegmentRoutingConfig.class)) {
- // TODO Support dynamic configuration in the future
+ log.info("Network configuration change detected. (Re)Configuring...");
+ configureNetwork();
return;
}
}
diff --git a/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingConfig.java b/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingConfig.java
index 618ebbc..6dc3f0d 100644
--- a/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingConfig.java
+++ b/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingConfig.java
@@ -16,6 +16,7 @@
package org.onosproject.segmentrouting.config;
+import com.fasterxml.jackson.databind.node.ArrayNode;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.MacAddress;
import org.onosproject.net.DeviceId;
@@ -35,6 +36,7 @@
private static final String MAC = "routerMac";
private static final String SID = "nodeSid";
private static final String EDGE = "isEdgeRouter";
+ private static final String ADJSID = "adjacencySids";
public Optional<String> getName() {
String name = get(NAME, null);
@@ -79,22 +81,44 @@
return (BasicElementConfig) setOrClear(EDGE, isEdgeRouter);
}
- // TODO extract array from JsonNode
public List<AdjacencySid> getAdjacencySids() {
- return new ArrayList<AdjacencySid>();
+ ArrayList<AdjacencySid> adjacencySids = new ArrayList<>();
+
+ if (!object.has(ADJSID)) {
+ return adjacencySids;
+ }
+
+ ArrayNode adjacencySidNodes = (ArrayNode) object.path(ADJSID);
+ adjacencySidNodes.forEach(adjacencySidNode -> {
+ int asid = adjacencySidNode.path(AdjacencySid.ASID).asInt();
+
+ ArrayList<Integer> ports = new ArrayList<Integer>();
+ ArrayNode portsNodes = (ArrayNode) adjacencySidNode.path(AdjacencySid.PORTS);
+ portsNodes.forEach(portNode -> {
+ ports.add(portNode.asInt());
+ });
+
+ AdjacencySid adjacencySid = new AdjacencySid(asid, ports);
+ adjacencySids.add(adjacencySid);
+ });
+
+ return adjacencySids;
}
public class AdjacencySid {
- int sid;
+ private static final String ASID = "adjSid";
+ private static final String PORTS = "ports";
+
+ int asid;
List<Integer> ports;
- public AdjacencySid(int sid, List<Integer> ports) {
- this.sid = sid;
+ public AdjacencySid(int asid, List<Integer> ports) {
+ this.asid = asid;
this.ports = ports;
}
- public int getSid() {
- return sid;
+ public int getAsid() {
+ return asid;
}
public List<Integer> getPorts() {