Charles Chan
Committed by Gerrit Code Review

[CORD-200] Improves Segment Routing using Network Configuration Subsystem

The missing part of gerrit #5533

Change-Id: I0830aa80f9be0e9933a99e0c12518aef67008a53
...@@ -19,7 +19,12 @@ import com.google.common.collect.Lists; ...@@ -19,7 +19,12 @@ import com.google.common.collect.Lists;
19 import org.onlab.packet.Ip4Address; 19 import org.onlab.packet.Ip4Address;
20 import org.onlab.packet.Ip4Prefix; 20 import org.onlab.packet.Ip4Prefix;
21 import org.onlab.packet.MacAddress; 21 import org.onlab.packet.MacAddress;
22 +import org.onosproject.incubator.net.config.basics.ConfigException;
23 +import org.onosproject.incubator.net.config.basics.InterfaceConfig;
24 +import org.onosproject.incubator.net.intf.Interface;
25 +import org.onosproject.net.ConnectPoint;
22 import org.onosproject.net.config.NetworkConfigRegistry; 26 import org.onosproject.net.config.NetworkConfigRegistry;
27 +import org.onosproject.net.host.InterfaceIpAddress;
23 import org.onosproject.segmentrouting.config.SegmentRoutingConfig; 28 import org.onosproject.segmentrouting.config.SegmentRoutingConfig;
24 import org.onosproject.segmentrouting.config.SegmentRoutingConfig.AdjacencySid; 29 import org.onosproject.segmentrouting.config.SegmentRoutingConfig.AdjacencySid;
25 import org.onosproject.segmentrouting.grouphandler.DeviceProperties; 30 import org.onosproject.segmentrouting.grouphandler.DeviceProperties;
...@@ -28,8 +33,6 @@ import org.onosproject.net.PortNumber; ...@@ -28,8 +33,6 @@ import org.onosproject.net.PortNumber;
28 import org.slf4j.Logger; 33 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory; 34 import org.slf4j.LoggerFactory;
30 35
31 -import static com.google.common.base.Preconditions.checkNotNull;
32 -
33 import java.util.ArrayList; 36 import java.util.ArrayList;
34 import java.util.HashMap; 37 import java.util.HashMap;
35 import java.util.List; 38 import java.util.List;
...@@ -49,7 +52,6 @@ public class DeviceConfiguration implements DeviceProperties { ...@@ -49,7 +52,6 @@ public class DeviceConfiguration implements DeviceProperties {
49 .getLogger(DeviceConfiguration.class); 52 .getLogger(DeviceConfiguration.class);
50 private final List<Integer> allSegmentIds = new ArrayList<>(); 53 private final List<Integer> allSegmentIds = new ArrayList<>();
51 private final HashMap<DeviceId, SegmentRouterInfo> deviceConfigMap = new HashMap<>(); 54 private final HashMap<DeviceId, SegmentRouterInfo> deviceConfigMap = new HashMap<>();
52 - private final NetworkConfigRegistry configService;
53 55
54 private class SegmentRouterInfo { 56 private class SegmentRouterInfo {
55 int nodeSid; 57 int nodeSid;
...@@ -65,33 +67,54 @@ public class DeviceConfiguration implements DeviceProperties { ...@@ -65,33 +67,54 @@ public class DeviceConfiguration implements DeviceProperties {
65 /** 67 /**
66 * Constructor. Reads all the configuration for all devices of type 68 * Constructor. Reads all the configuration for all devices of type
67 * Segment Router and organizes into various maps for easier access. 69 * Segment Router and organizes into various maps for easier access.
68 - *
69 - * @param cfgService handle to network configuration manager
70 - * component from where the relevant configuration is retrieved.
71 */ 70 */
72 public DeviceConfiguration(NetworkConfigRegistry cfgService) { 71 public DeviceConfiguration(NetworkConfigRegistry cfgService) {
73 - this.configService = checkNotNull(cfgService); 72 + // Read config from device subject, excluding gatewayIps and subnets.
74 - 73 + Set<DeviceId> deviceSubjects =
75 - Set<DeviceId> subjectSet =
76 cfgService.getSubjects(DeviceId.class, SegmentRoutingConfig.class); 74 cfgService.getSubjects(DeviceId.class, SegmentRoutingConfig.class);
77 - 75 + deviceSubjects.forEach(subject -> {
78 - subjectSet.forEach(subject -> {
79 SegmentRoutingConfig config = 76 SegmentRoutingConfig config =
80 cfgService.getConfig(subject, SegmentRoutingConfig.class); 77 cfgService.getConfig(subject, SegmentRoutingConfig.class);
81 SegmentRouterInfo info = new SegmentRouterInfo(); 78 SegmentRouterInfo info = new SegmentRouterInfo();
82 - info.nodeSid = config.getSid();
83 info.deviceId = subject; 79 info.deviceId = subject;
80 + info.nodeSid = config.getSid();
84 info.ip = config.getIp(); 81 info.ip = config.getIp();
85 info.mac = config.getMac(); 82 info.mac = config.getMac();
86 info.isEdge = config.isEdgeRouter(); 83 info.isEdge = config.isEdgeRouter();
87 - // TODO fecth subnet and gateway information via port subject 84 + info.adjacencySids = config.getAdjacencySids();
88 info.gatewayIps = new HashMap<>(); 85 info.gatewayIps = new HashMap<>();
89 info.subnets = new HashMap<>(); 86 info.subnets = new HashMap<>();
90 - info.adjacencySids = config.getAdjacencySids();
91 87
92 this.deviceConfigMap.put(info.deviceId, info); 88 this.deviceConfigMap.put(info.deviceId, info);
93 this.allSegmentIds.add(info.nodeSid); 89 this.allSegmentIds.add(info.nodeSid);
94 }); 90 });
91 +
92 + // Read gatewayIps and subnets from port subject.
93 + Set<ConnectPoint> portSubjects =
94 + cfgService.getSubjects(ConnectPoint.class, InterfaceConfig.class);
95 + portSubjects.forEach(subject -> {
96 + InterfaceConfig config =
97 + cfgService.getConfig(subject, InterfaceConfig.class);
98 + Set<Interface> networkInterfaces;
99 + try {
100 + networkInterfaces = config.getInterfaces();
101 + } catch (ConfigException e) {
102 + log.error("Error loading port configuration");
103 + return;
104 + }
105 + networkInterfaces.forEach(networkInterface -> {
106 + DeviceId dpid = networkInterface.connectPoint().deviceId();
107 + PortNumber port = networkInterface.connectPoint().port();
108 + SegmentRouterInfo info = this.deviceConfigMap.get(dpid);
109 +
110 + Set<InterfaceIpAddress> interfaceAddresses = networkInterface.ipAddresses();
111 + interfaceAddresses.forEach(interfaceAddress -> {
112 + info.gatewayIps.put(port, interfaceAddress.ipAddress().getIp4Address());
113 + info.subnets.put(port, interfaceAddress.subnetAddress().getIp4Prefix());
114 + });
115 + });
116 +
117 + });
95 } 118 }
96 119
97 /** 120 /**
...@@ -370,7 +393,7 @@ public class DeviceConfiguration implements DeviceProperties { ...@@ -370,7 +393,7 @@ public class DeviceConfiguration implements DeviceProperties {
370 public List<Integer> getPortsForAdjacencySid(DeviceId deviceId, int sid) { 393 public List<Integer> getPortsForAdjacencySid(DeviceId deviceId, int sid) {
371 if (deviceConfigMap.get(deviceId) != null) { 394 if (deviceConfigMap.get(deviceId) != null) {
372 for (AdjacencySid asid : deviceConfigMap.get(deviceId).adjacencySids) { 395 for (AdjacencySid asid : deviceConfigMap.get(deviceId).adjacencySids) {
373 - if (asid.getSid() == sid) { 396 + if (asid.getAsid() == sid) {
374 return asid.getPorts(); 397 return asid.getPorts();
375 } 398 }
376 } 399 }
...@@ -394,7 +417,7 @@ public class DeviceConfiguration implements DeviceProperties { ...@@ -394,7 +417,7 @@ public class DeviceConfiguration implements DeviceProperties {
394 } else { 417 } else {
395 for (AdjacencySid asid: 418 for (AdjacencySid asid:
396 deviceConfigMap.get(deviceId).adjacencySids) { 419 deviceConfigMap.get(deviceId).adjacencySids) {
397 - if (asid.getSid() == sid) { 420 + if (asid.getAsid() == sid) {
398 return true; 421 return true;
399 } 422 }
400 } 423 }
......
...@@ -141,7 +141,9 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -141,7 +141,9 @@ public class SegmentRoutingManager implements SegmentRoutingService {
141 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 141 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
142 protected NetworkConfigRegistry cfgService; 142 protected NetworkConfigRegistry cfgService;
143 143
144 - private final InternalConfigListener cfgListener = new InternalConfigListener(); 144 + private final InternalConfigListener cfgListener =
145 + new InternalConfigListener(this);
146 +
145 private final ConfigFactory cfgFactory = 147 private final ConfigFactory cfgFactory =
146 new ConfigFactory(SubjectFactories.DEVICE_SUBJECT_FACTORY, 148 new ConfigFactory(SubjectFactories.DEVICE_SUBJECT_FACTORY,
147 SegmentRoutingConfig.class, 149 SegmentRoutingConfig.class,
...@@ -211,40 +213,8 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -211,40 +213,8 @@ public class SegmentRoutingManager implements SegmentRoutingService {
211 213
212 cfgService.addListener(cfgListener); 214 cfgService.addListener(cfgListener);
213 cfgService.registerConfigFactory(cfgFactory); 215 cfgService.registerConfigFactory(cfgFactory);
214 - deviceConfiguration = new DeviceConfiguration(cfgService);
215 -
216 - arpHandler = new ArpHandler(this);
217 - icmpHandler = new IcmpHandler(this);
218 - ipHandler = new IpHandler(this);
219 - routingRulePopulator = new RoutingRulePopulator(this);
220 - defaultRoutingHandler = new DefaultRoutingHandler(this);
221 - tunnelHandler = new TunnelHandler(linkService, deviceConfiguration,
222 - groupHandlerMap, tunnelStore);
223 - policyHandler = new PolicyHandler(appId, deviceConfiguration,
224 - flowObjectiveService, tunnelHandler, policyStore);
225 -
226 - packetService.addProcessor(processor, PacketProcessor.director(2));
227 - linkService.addListener(new InternalLinkListener());
228 - deviceService.addListener(new InternalDeviceListener());
229 -
230 - for (Device device : deviceService.getDevices()) {
231 - //Irrespective whether the local is a MASTER or not for this device,
232 - //create group handler instance and push default TTP flow rules.
233 - //Because in a multi-instance setup, instances can initiate
234 - //groups for any devices. Also the default TTP rules are needed
235 - //to be pushed before inserting any IP table entries for any device
236 - DefaultGroupHandler groupHandler = DefaultGroupHandler
237 - .createGroupHandler(device.id(), appId,
238 - deviceConfiguration, linkService,
239 - flowObjectiveService,
240 - nsNextObjStore);
241 - groupHandlerMap.put(device.id(), groupHandler);
242 - defaultRoutingHandler.populateTtpRules(device.id());
243 - }
244 216
245 - defaultRoutingHandler.startPopulationProcess();
246 log.info("Started"); 217 log.info("Started");
247 -
248 } 218 }
249 219
250 @Deactivate 220 @Deactivate
...@@ -535,12 +505,56 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -535,12 +505,56 @@ public class SegmentRoutingManager implements SegmentRoutingService {
535 } 505 }
536 506
537 private class InternalConfigListener implements NetworkConfigListener { 507 private class InternalConfigListener implements NetworkConfigListener {
508 + SegmentRoutingManager segmentRoutingManager;
509 +
510 + public InternalConfigListener(SegmentRoutingManager srMgr) {
511 + this.segmentRoutingManager = srMgr;
512 + }
513 +
514 + public void configureNetwork() {
515 + deviceConfiguration = new DeviceConfiguration(segmentRoutingManager.cfgService);
516 +
517 + arpHandler = new ArpHandler(segmentRoutingManager);
518 + icmpHandler = new IcmpHandler(segmentRoutingManager);
519 + ipHandler = new IpHandler(segmentRoutingManager);
520 + routingRulePopulator = new RoutingRulePopulator(segmentRoutingManager);
521 + defaultRoutingHandler = new DefaultRoutingHandler(segmentRoutingManager);
522 +
523 + tunnelHandler = new TunnelHandler(linkService, deviceConfiguration,
524 + groupHandlerMap, tunnelStore);
525 + policyHandler = new PolicyHandler(appId, deviceConfiguration,
526 + flowObjectiveService,
527 + tunnelHandler, policyStore);
528 +
529 + packetService.addProcessor(processor, PacketProcessor.director(2));
530 + linkService.addListener(new InternalLinkListener());
531 + deviceService.addListener(new InternalDeviceListener());
532 +
533 + for (Device device : deviceService.getDevices()) {
534 + //Irrespective whether the local is a MASTER or not for this device,
535 + //create group handler instance and push default TTP flow rules.
536 + //Because in a multi-instance setup, instances can initiate
537 + //groups for any devices. Also the default TTP rules are needed
538 + //to be pushed before inserting any IP table entries for any device
539 + DefaultGroupHandler groupHandler = DefaultGroupHandler
540 + .createGroupHandler(device.id(), appId,
541 + deviceConfiguration, linkService,
542 + flowObjectiveService,
543 + nsNextObjStore);
544 + groupHandlerMap.put(device.id(), groupHandler);
545 + defaultRoutingHandler.populateTtpRules(device.id());
546 + }
547 +
548 + defaultRoutingHandler.startPopulationProcess();
549 + }
550 +
538 @Override 551 @Override
539 public void event(NetworkConfigEvent event) { 552 public void event(NetworkConfigEvent event) {
540 if ((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED || 553 if ((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
541 event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED) && 554 event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED) &&
542 event.configClass().equals(SegmentRoutingConfig.class)) { 555 event.configClass().equals(SegmentRoutingConfig.class)) {
543 - // TODO Support dynamic configuration in the future 556 + log.info("Network configuration change detected. (Re)Configuring...");
557 + configureNetwork();
544 return; 558 return;
545 } 559 }
546 } 560 }
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
16 16
17 package org.onosproject.segmentrouting.config; 17 package org.onosproject.segmentrouting.config;
18 18
19 +import com.fasterxml.jackson.databind.node.ArrayNode;
19 import org.onlab.packet.Ip4Address; 20 import org.onlab.packet.Ip4Address;
20 import org.onlab.packet.MacAddress; 21 import org.onlab.packet.MacAddress;
21 import org.onosproject.net.DeviceId; 22 import org.onosproject.net.DeviceId;
...@@ -35,6 +36,7 @@ public class SegmentRoutingConfig extends Config<DeviceId> { ...@@ -35,6 +36,7 @@ public class SegmentRoutingConfig extends Config<DeviceId> {
35 private static final String MAC = "routerMac"; 36 private static final String MAC = "routerMac";
36 private static final String SID = "nodeSid"; 37 private static final String SID = "nodeSid";
37 private static final String EDGE = "isEdgeRouter"; 38 private static final String EDGE = "isEdgeRouter";
39 + private static final String ADJSID = "adjacencySids";
38 40
39 public Optional<String> getName() { 41 public Optional<String> getName() {
40 String name = get(NAME, null); 42 String name = get(NAME, null);
...@@ -79,22 +81,44 @@ public class SegmentRoutingConfig extends Config<DeviceId> { ...@@ -79,22 +81,44 @@ public class SegmentRoutingConfig extends Config<DeviceId> {
79 return (BasicElementConfig) setOrClear(EDGE, isEdgeRouter); 81 return (BasicElementConfig) setOrClear(EDGE, isEdgeRouter);
80 } 82 }
81 83
82 - // TODO extract array from JsonNode
83 public List<AdjacencySid> getAdjacencySids() { 84 public List<AdjacencySid> getAdjacencySids() {
84 - return new ArrayList<AdjacencySid>(); 85 + ArrayList<AdjacencySid> adjacencySids = new ArrayList<>();
86 +
87 + if (!object.has(ADJSID)) {
88 + return adjacencySids;
89 + }
90 +
91 + ArrayNode adjacencySidNodes = (ArrayNode) object.path(ADJSID);
92 + adjacencySidNodes.forEach(adjacencySidNode -> {
93 + int asid = adjacencySidNode.path(AdjacencySid.ASID).asInt();
94 +
95 + ArrayList<Integer> ports = new ArrayList<Integer>();
96 + ArrayNode portsNodes = (ArrayNode) adjacencySidNode.path(AdjacencySid.PORTS);
97 + portsNodes.forEach(portNode -> {
98 + ports.add(portNode.asInt());
99 + });
100 +
101 + AdjacencySid adjacencySid = new AdjacencySid(asid, ports);
102 + adjacencySids.add(adjacencySid);
103 + });
104 +
105 + return adjacencySids;
85 } 106 }
86 107
87 public class AdjacencySid { 108 public class AdjacencySid {
88 - int sid; 109 + private static final String ASID = "adjSid";
110 + private static final String PORTS = "ports";
111 +
112 + int asid;
89 List<Integer> ports; 113 List<Integer> ports;
90 114
91 - public AdjacencySid(int sid, List<Integer> ports) { 115 + public AdjacencySid(int asid, List<Integer> ports) {
92 - this.sid = sid; 116 + this.asid = asid;
93 this.ports = ports; 117 this.ports = ports;
94 } 118 }
95 119
96 - public int getSid() { 120 + public int getAsid() {
97 - return sid; 121 + return asid;
98 } 122 }
99 123
100 public List<Integer> getPorts() { 124 public List<Integer> getPorts() {
......
...@@ -19,6 +19,30 @@ ...@@ -19,6 +19,30 @@
19 ] 19 ]
20 } 20 }
21 }, 21 },
22 + "devices" : {
23 + "of:0000000000000002" : {
24 + "segmentrouting" : {
25 + "name" : "Leaf-R1",
26 + "nodeSid" : 101,
27 + "routerIp" : "10.0.1.254",
28 + "routerMac" : "00:00:00:00:01:80",
29 + "isEdgeRouter" : true,
30 + "adjacencySids" : [
31 + { "sid" : 100, "port" : [2, 3] },
32 + { "sid" : 200, "port" : [4, 5] }
33 + ]
34 + }
35 + },
36 + "of:0000000000000191" : {
37 + "segmentrouting" : {
38 + "name" : "Spine-R1",
39 + "nodeSid" : 105,
40 + "routerIp" : "192.168.0.11",
41 + "routerMac" : "00:00:01:00:11:80",
42 + "isEdgeRouter" : false
43 + }
44 + }
45 + },
22 "apps" : { 46 "apps" : {
23 "org.onosproject.router" : { 47 "org.onosproject.router" : {
24 "bgp" : { 48 "bgp" : {
......
1 -{
2 - "comment": "Configuration for a 4X4 leaf-spine fabric",
3 - "restrictSwitches": true,
4 - "restrictLinks": true,
5 -
6 - "switchConfig":
7 - [
8 - { "nodeDpid" : "of:0000000000000001", "name": "Leaf-R1", "type": "Router_SR", "allowed": true,
9 - "latitude": 80.80, "longitude": 90.10,
10 - "params": { "routerIp": "10.0.1.254/32",
11 - "routerMac": "00:00:00:00:01:80",
12 - "nodeSid": 101,
13 - "isEdgeRouter" : true,
14 - "subnets": [
15 - { "portNo": 1, "subnetIp": "10.0.1.254/24" }
16 - ]
17 - }
18 - },
19 -
20 - { "nodeDpid": "of:0000000000000002", "name": "Leaf-R2", "type": "Router_SR", "allowed": true,
21 - "latitude": 80.80, "longitude": 90.10,
22 - "params": { "routerIp": "10.0.2.254/32",
23 - "routerMac": "00:00:00:00:02:80",
24 - "nodeSid": 102,
25 - "isEdgeRouter" : true,
26 - "subnets": [
27 - { "portNo": 1, "subnetIp": "10.0.2.254/24" }
28 - ]
29 - }
30 -
31 - },
32 -
33 - { "nodeDpid": "of:0000000000000003", "name": "Leaf-R3", "type": "Router_SR", "allowed": true,
34 - "latitude": 80.80, "longitude": 90.10,
35 - "params": { "routerIp": "10.0.3.101/32",
36 - "routerMac": "00:00:00:00:03:80",
37 - "nodeSid": 103,
38 - "isEdgeRouter" : true,
39 - "subnets": [
40 - { "portNo": 1, "subnetIp": "10.0.3.254/24" }
41 - ]
42 - }
43 -
44 - },
45 -
46 - { "nodeDpid": "of:0000000000000004", "name": "Leaf-R4", "type": "Router_SR", "allowed": true,
47 - "latitude": 80.80, "longitude": 90.10,
48 - "params": { "routerIp": "10.0.4.101/32",
49 - "routerMac": "00:00:00:00:04:80",
50 - "nodeSid": 104,
51 - "isEdgeRouter" : true,
52 - "subnets": [
53 - { "portNo": 1, "subnetIp": "10.0.4.254/24" }
54 - ]
55 - }
56 -
57 - },
58 -
59 - { "nodeDpid": "of:0000000000000191", "name": "Spine-R1", "type": "Router_SR", "allowed": true,
60 - "latitude": 80.80, "longitude": 90.10,
61 - "params": { "routerIp": "192.168.0.11/32",
62 - "routerMac": "00:00:01:00:11:80",
63 - "nodeSid": 105,
64 - "isEdgeRouter" : false
65 - }
66 - },
67 -
68 - { "nodeDpid": "of:0000000000000192", "name": "Spine-R2", "type": "Router_SR", "allowed": true,
69 - "latitude": 80.80, "longitude": 90.10,
70 - "params": { "routerIp": "192.168.0.22/32",
71 - "routerMac": "00:00:01:00:22:80",
72 - "nodeSid": 106,
73 - "isEdgeRouter" : false
74 - }
75 - },
76 -
77 - { "nodeDpid": "of:0000000000000193", "name": "Spine-R3", "type": "Router_SR", "allowed": true,
78 - "latitude": 80.80, "longitude": 90.10,
79 - "params": { "routerIp": "192.168.0.33/32",
80 - "routerMac": "00:00:01:00:33:80",
81 - "nodeSid": 107,
82 - "isEdgeRouter" : false
83 - }
84 - },
85 -
86 - { "nodeDpid": "of:0000000000000194", "name": "Spine-R4", "type": "Router_SR", "allowed": true,
87 - "latitude": 80.80, "longitude": 90.10,
88 - "params": { "routerIp": "192.168.0.44/32",
89 - "routerMac": "00:00:01:00:44:80",
90 - "nodeSid": 108,
91 - "isEdgeRouter" : false
92 - }
93 - }
94 - ]
95 -}