From f2565a9cbcaec0d11ceda2d123717514d53e4072 Mon Sep 17 00:00:00 2001 From: Charles Chan Date: Wed, 10 Feb 2016 20:46:58 -0800 Subject: [PATCH] CORD-508 SegmentRouting / vRouter integration - Added excludePorts config to SegmentRouting SR does not push VLAN filtering rule to excluded ports SR ignores hosts learned from excluded ports - Use separate default route config Don't need to config 0/0 on the interface anymore Change-Id: Iea75d60c2d5f5368e79652b1bf192a6ced49030d --- .../segmentrouting/RoutingRulePopulator.java | 5 +- .../segmentrouting/SegmentRoutingManager.java | 157 ++++++++++-------- .../config/DeviceConfiguration.java | 39 ++++- .../config/SegmentRoutingAppConfig.java | 81 ++++++++- .../config/SegmentRoutingAppConfigTest.java | 123 +++++++++++--- .../network-cfg-fabric2x2-default-route.json | 15 +- 6 files changed, 321 insertions(+), 99 deletions(-) diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java index 10ac6d637f..271ffa0de2 100644 --- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java +++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java @@ -471,8 +471,9 @@ public class RoutingRulePopulator { } for (Port port : srManager.deviceService.getPorts(deviceId)) { - if (port.number().toLong() > 0 && - port.number().toLong() < SegmentRoutingService.OFPP_MAX && + ConnectPoint cp = new ConnectPoint(deviceId, port.number()); + // TODO: Handles dynamic port events when we are ready for dynamic config + if (!srManager.deviceConfiguration.excludedPorts().contains(cp) && port.isEnabled()) { Ip4Prefix portSubnet = config.getPortSubnet(deviceId, port.number()); VlanId assignedVlan = (portSubnet == null) diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java index 32e03decec..03b4f40e93 100644 --- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java +++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java @@ -814,7 +814,8 @@ public class SegmentRoutingManager implements SegmentRoutingService { * Reads network config and initializes related data structure accordingly. */ public void configureNetwork() { - deviceConfiguration = new DeviceConfiguration(segmentRoutingManager.cfgService); + deviceConfiguration = new DeviceConfiguration(appId, + segmentRoutingManager.cfgService); arpHandler = new ArpHandler(segmentRoutingManager); icmpHandler = new IcmpHandler(segmentRoutingManager); @@ -987,22 +988,25 @@ public class SegmentRoutingManager implements SegmentRoutingService { Set ips = event.subject().ipAddresses(); log.info("Host {}/{} is added at {}:{}", mac, vlanId, deviceId, port); - // Populate bridging table entry - log.debug("Populate L2 table entry for host {} at {}:{}", - mac, deviceId, port); - ForwardingObjective.Builder fob = - getForwardingObjectiveBuilder(deviceId, mac, vlanId, port); - flowObjectiveService.forward(deviceId, fob.add( - new BridgingTableObjectiveContext(mac, vlanId) - )); + if (!deviceConfiguration.excludedPorts() + .contains(new ConnectPoint(deviceId, port))) { + // Populate bridging table entry + log.debug("Populate L2 table entry for host {} at {}:{}", + mac, deviceId, port); + ForwardingObjective.Builder fob = + getForwardingObjectiveBuilder(deviceId, mac, vlanId, port); + flowObjectiveService.forward(deviceId, fob.add( + new BridgingTableObjectiveContext(mac, vlanId) + )); - // Populate IP table entry - ips.forEach(ip -> { - if (ip.isIp4()) { - routingRulePopulator.populateIpRuleForHost( - deviceId, ip.getIp4Address(), mac, port); - } - }); + // Populate IP table entry + ips.forEach(ip -> { + if (ip.isIp4()) { + routingRulePopulator.populateIpRuleForHost( + deviceId, ip.getIp4Address(), mac, port); + } + }); + } } private void processHostRemoveEvent(HostEvent event) { @@ -1013,20 +1017,23 @@ public class SegmentRoutingManager implements SegmentRoutingService { Set ips = event.subject().ipAddresses(); log.debug("Host {}/{} is removed from {}:{}", mac, vlanId, deviceId, port); - // Revoke bridging table entry - ForwardingObjective.Builder fob = - getForwardingObjectiveBuilder(deviceId, mac, vlanId, port); - flowObjectiveService.forward(deviceId, fob.remove( - new BridgingTableObjectiveContext(mac, vlanId) - )); + if (!deviceConfiguration.excludedPorts() + .contains(new ConnectPoint(deviceId, port))) { + // Revoke bridging table entry + ForwardingObjective.Builder fob = + getForwardingObjectiveBuilder(deviceId, mac, vlanId, port); + flowObjectiveService.forward(deviceId, fob.remove( + new BridgingTableObjectiveContext(mac, vlanId) + )); - // Revoke IP table entry - ips.forEach(ip -> { - if (ip.isIp4()) { - routingRulePopulator.revokeIpRuleForHost( - deviceId, ip.getIp4Address(), mac, port); - } - }); + // Revoke IP table entry + ips.forEach(ip -> { + if (ip.isIp4()) { + routingRulePopulator.revokeIpRuleForHost( + deviceId, ip.getIp4Address(), mac, port); + } + }); + } } private void processHostMovedEvent(HostEvent event) { @@ -1041,35 +1048,41 @@ public class SegmentRoutingManager implements SegmentRoutingService { log.debug("Host {}/{} is moved from {}:{} to {}:{}", mac, vlanId, prevDeviceId, prevPort, newDeviceId, newPort); - // Revoke previous bridging table entry - ForwardingObjective.Builder prevFob = - getForwardingObjectiveBuilder(prevDeviceId, mac, vlanId, prevPort); - flowObjectiveService.forward(prevDeviceId, prevFob.remove( - new BridgingTableObjectiveContext(mac, vlanId) - )); + if (!deviceConfiguration.excludedPorts() + .contains(new ConnectPoint(prevDeviceId, prevPort))) { + // Revoke previous bridging table entry + ForwardingObjective.Builder prevFob = + getForwardingObjectiveBuilder(prevDeviceId, mac, vlanId, prevPort); + flowObjectiveService.forward(prevDeviceId, prevFob.remove( + new BridgingTableObjectiveContext(mac, vlanId) + )); - // Revoke previous IP table entry - prevIps.forEach(ip -> { - if (ip.isIp4()) { - routingRulePopulator.revokeIpRuleForHost( - prevDeviceId, ip.getIp4Address(), mac, prevPort); - } - }); + // Revoke previous IP table entry + prevIps.forEach(ip -> { + if (ip.isIp4()) { + routingRulePopulator.revokeIpRuleForHost( + prevDeviceId, ip.getIp4Address(), mac, prevPort); + } + }); + } - // Populate new bridging table entry - ForwardingObjective.Builder newFob = - getForwardingObjectiveBuilder(newDeviceId, mac, vlanId, newPort); - flowObjectiveService.forward(newDeviceId, newFob.add( - new BridgingTableObjectiveContext(mac, vlanId) - )); + if (!deviceConfiguration.excludedPorts() + .contains(new ConnectPoint(newDeviceId, newPort))) { + // Populate new bridging table entry + ForwardingObjective.Builder newFob = + getForwardingObjectiveBuilder(newDeviceId, mac, vlanId, newPort); + flowObjectiveService.forward(newDeviceId, newFob.add( + new BridgingTableObjectiveContext(mac, vlanId) + )); - // Populate new IP table entry - newIps.forEach(ip -> { - if (ip.isIp4()) { - routingRulePopulator.populateIpRuleForHost( - newDeviceId, ip.getIp4Address(), mac, newPort); - } - }); + // Populate new IP table entry + newIps.forEach(ip -> { + if (ip.isIp4()) { + routingRulePopulator.populateIpRuleForHost( + newDeviceId, ip.getIp4Address(), mac, newPort); + } + }); + } } private void processHostUpdatedEvent(HostEvent event) { @@ -1083,21 +1096,27 @@ public class SegmentRoutingManager implements SegmentRoutingService { Set newIps = event.subject().ipAddresses(); log.debug("Host {}/{} is updated", mac, vlanId); - // Revoke previous IP table entry - prevIps.forEach(ip -> { - if (ip.isIp4()) { - routingRulePopulator.revokeIpRuleForHost( - prevDeviceId, ip.getIp4Address(), mac, prevPort); - } - }); + if (!deviceConfiguration.excludedPorts() + .contains(new ConnectPoint(prevDeviceId, prevPort))) { + // Revoke previous IP table entry + prevIps.forEach(ip -> { + if (ip.isIp4()) { + routingRulePopulator.revokeIpRuleForHost( + prevDeviceId, ip.getIp4Address(), mac, prevPort); + } + }); + } - // Populate new IP table entry - newIps.forEach(ip -> { - if (ip.isIp4()) { - routingRulePopulator.populateIpRuleForHost( - newDeviceId, ip.getIp4Address(), mac, newPort); - } - }); + if (!deviceConfiguration.excludedPorts() + .contains(new ConnectPoint(newDeviceId, newPort))) { + // Populate new IP table entry + newIps.forEach(ip -> { + if (ip.isIp4()) { + routingRulePopulator.populateIpRuleForHost( + newDeviceId, ip.getIp4Address(), mac, newPort); + } + }); + } } @Override diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java index db4bc63647..f222bb3592 100644 --- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java +++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java @@ -18,11 +18,13 @@ package org.onosproject.segmentrouting.config; import com.google.common.collect.HashMultimap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.SetMultimap; +import com.google.common.collect.Sets; import org.onlab.packet.Ip4Address; import org.onlab.packet.Ip4Prefix; import org.onlab.packet.IpPrefix; import org.onlab.packet.MacAddress; import org.onlab.packet.VlanId; +import org.onosproject.core.ApplicationId; import org.onosproject.incubator.net.config.basics.ConfigException; import org.onosproject.incubator.net.config.basics.InterfaceConfig; import org.onosproject.incubator.net.intf.Interface; @@ -51,11 +53,12 @@ import java.util.concurrent.ConcurrentHashMap; */ public class DeviceConfiguration implements DeviceProperties { - private static final Logger log = LoggerFactory - .getLogger(DeviceConfiguration.class); + private static final Logger log = LoggerFactory.getLogger(DeviceConfiguration.class); private final List allSegmentIds = new ArrayList<>(); private final Map deviceConfigMap = new ConcurrentHashMap<>(); private final Map> xConnects = new ConcurrentHashMap<>(); + private final Set excludedPorts = Sets.newConcurrentHashSet(); + private SegmentRoutingAppConfig appConfig; private class SegmentRouterInfo { int nodeSid; @@ -77,9 +80,11 @@ public class DeviceConfiguration implements DeviceProperties { * Constructs device configuration for all Segment Router devices, * organizing the data into various maps for easier access. * + * @param appId application id * @param cfgService config service */ - public DeviceConfiguration(NetworkConfigRegistry cfgService) { + public DeviceConfiguration(ApplicationId appId, + NetworkConfigRegistry cfgService) { // Read config from device subject, excluding gatewayIps and subnets. Set deviceSubjects = cfgService.getSubjects(DeviceId.class, SegmentRoutingDeviceConfig.class); @@ -98,6 +103,11 @@ public class DeviceConfiguration implements DeviceProperties { allSegmentIds.add(info.nodeSid); }); + // Read excluded port names from config + appConfig = cfgService.getConfig(appId, SegmentRoutingAppConfig.class); + Set excludePorts = (appConfig != null) ? + appConfig.excludePorts() : ImmutableSet.of(); + // Read gatewayIps and subnets from port subject. Set portSubjects = cfgService.getSubjects(ConnectPoint.class, InterfaceConfig.class); @@ -112,6 +122,12 @@ public class DeviceConfiguration implements DeviceProperties { return; } networkInterfaces.forEach(networkInterface -> { + // Do not process excluded ports + if (excludePorts.contains(networkInterface.name())) { + excludedPorts.add(subject); + return; + } + VlanId vlanId = networkInterface.vlan(); ConnectPoint connectPoint = networkInterface.connectPoint(); DeviceId dpid = connectPoint.deviceId(); @@ -343,7 +359,13 @@ public class DeviceConfiguration implements DeviceProperties { if (srinfo != null) { log.trace("getSubnets for device{} is {}", deviceId, srinfo.subnets.values()); - return ImmutableSet.copyOf(srinfo.subnets.values()); + + ImmutableSet.Builder builder = ImmutableSet.builder(); + builder.addAll(srinfo.subnets.values()); + if (deviceId.equals(appConfig.vRouterId())) { + builder.add(Ip4Prefix.valueOf("0.0.0.0/0")); + } + return builder.build(); } return null; } @@ -464,4 +486,13 @@ public class DeviceConfiguration implements DeviceProperties { SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId); return srinfo != null && srinfo.adjacencySids.containsKey(sid); } + + /** + * Returns a set of excluded ports. + * + * @return excluded ports + */ + public Set excludedPorts() { + return excludedPorts; + } } \ No newline at end of file diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingAppConfig.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingAppConfig.java index e39fb18f86..163cc1c9c1 100644 --- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingAppConfig.java +++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingAppConfig.java @@ -21,6 +21,7 @@ import com.fasterxml.jackson.databind.node.ArrayNode; import com.google.common.collect.ImmutableSet; import org.onlab.packet.MacAddress; import org.onosproject.core.ApplicationId; +import org.onosproject.net.DeviceId; import org.onosproject.net.config.Config; import java.util.Set; @@ -31,10 +32,14 @@ import static com.google.common.base.MoreObjects.toStringHelper; */ public class SegmentRoutingAppConfig extends Config { private static final String VROUTER_MACS = "vRouterMacs"; + private static final String VROUTER_ID = "vRouterId"; + private static final String EXCLUDE_PORTS = "excludePorts"; @Override public boolean isValid() { - return hasOnlyFields(VROUTER_MACS) && vRouterMacs() != null; + return hasOnlyFields(VROUTER_MACS, VROUTER_ID, EXCLUDE_PORTS) && + vRouterMacs() != null && vRouterId() != null && + excludePorts() != null; } /** @@ -88,10 +93,84 @@ public class SegmentRoutingAppConfig extends Config { return this; } + /** + * Gets vRouter device ID. + * + * @return vRouter device ID, or null if not valid + */ + public DeviceId vRouterId() { + if (!object.has(VROUTER_ID)) { + return null; + } + + try { + return DeviceId.deviceId(object.path(VROUTER_ID).asText()); + } catch (IllegalArgumentException e) { + return null; + } + } + + /** + * Sets vRouter device ID. + * + * @param vRouterId vRouter device ID + * @return this {@link SegmentRoutingAppConfig} + */ + public SegmentRoutingAppConfig setVRouterId(DeviceId vRouterId) { + if (vRouterId == null) { + object.remove(VROUTER_ID); + } else { + object.put(VROUTER_ID, vRouterId.toString()); + } + return this; + } + + /** + * Gets names of ports that are ignored by SegmentRouting. + * + * @return set of port names + */ + public Set excludePorts() { + if (!object.has(EXCLUDE_PORTS)) { + return null; + } + + ImmutableSet.Builder builder = ImmutableSet.builder(); + ArrayNode arrayNode = (ArrayNode) object.path(EXCLUDE_PORTS); + for (JsonNode jsonNode : arrayNode) { + String portName = jsonNode.asText(null); + if (portName == null) { + return null; + } + builder.add(portName); + } + return builder.build(); + } + + /** + * Sets names of ports that are ignored by SegmentRouting. + * + * @paran excludePorts names of ports that are ignored by SegmentRouting + * @return this {@link SegmentRoutingAppConfig} + */ + public SegmentRoutingAppConfig setExcludePorts(Set excludePorts) { + if (excludePorts == null) { + object.remove(EXCLUDE_PORTS); + } else { + ArrayNode arrayNode = mapper.createArrayNode(); + excludePorts.forEach(portName -> { + arrayNode.add(portName); + }); + object.set(EXCLUDE_PORTS, arrayNode); + } + return this; + } + @Override public String toString() { return toStringHelper(this) .add("vRouterMacs", vRouterMacs()) + .add("excludePorts", excludePorts()) .toString(); } } diff --git a/apps/segmentrouting/src/test/java/org/onosproject/segmentrouting/config/SegmentRoutingAppConfigTest.java b/apps/segmentrouting/src/test/java/org/onosproject/segmentrouting/config/SegmentRoutingAppConfigTest.java index 775505937b..8acef5cb3a 100644 --- a/apps/segmentrouting/src/test/java/org/onosproject/segmentrouting/config/SegmentRoutingAppConfigTest.java +++ b/apps/segmentrouting/src/test/java/org/onosproject/segmentrouting/config/SegmentRoutingAppConfigTest.java @@ -24,6 +24,7 @@ import org.junit.Test; import org.onlab.packet.MacAddress; import org.onosproject.core.ApplicationId; import org.onosproject.TestApplicationId; +import org.onosproject.net.DeviceId; import org.onosproject.net.config.Config; import org.onosproject.net.config.ConfigApplyDelegate; import org.onosproject.segmentrouting.SegmentRoutingService; @@ -32,6 +33,7 @@ import java.util.Set; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; /** * Tests for class {@link SegmentRoutingAppConfig}. @@ -41,9 +43,34 @@ public class SegmentRoutingAppConfigTest { new TestApplicationId(SegmentRoutingService.SR_APP_ID); private SegmentRoutingAppConfig config; - private MacAddress routerMac1; - private MacAddress routerMac2; - private MacAddress routerMac3; + private SegmentRoutingAppConfig invalidConfig; + private static final String JSON_STRING = "{" + + "\"vRouterMacs\" : [" + + " \"00:00:00:00:00:01\"," + + " \"00:00:00:00:00:02\"" + + "]," + + "\"vRouterId\" : \"of:1\"," + + "\"excludePorts\" : [" + + " \"port1\"," + + " \"port2\"" + + "]}"; + private static final String INVALID_JSON_STRING = "{" + + "\"vRouterMacs\" : [" + + " \"00:00:00:00:00:01\"," + + " \"00:00:00:00:00:02\"" + + "]," + + "\"excludePorts\" : [" + + " \"port1\"," + + " \"port2\"" + + "]}"; + private static final MacAddress ROUTER_MAC_1 = MacAddress.valueOf("00:00:00:00:00:01"); + private static final MacAddress ROUTER_MAC_2 = MacAddress.valueOf("00:00:00:00:00:02"); + private static final MacAddress ROUTER_MAC_3 = MacAddress.valueOf("00:00:00:00:00:03"); + private static final String PORT_NAME_1 = "port1"; + private static final String PORT_NAME_2 = "port2"; + private static final String PORT_NAME_3 = "port3"; + private static final DeviceId VROUTER_ID_1 = DeviceId.deviceId("of:1"); + private static final DeviceId VROUTER_ID_2 = DeviceId.deviceId("of:2"); /** * Initialize test related variables. @@ -52,55 +79,107 @@ public class SegmentRoutingAppConfigTest { */ @Before public void setUp() throws Exception { - String jsonString = "{" + - "\"vRouterMacs\" : [" + - " \"00:00:00:00:00:01\"," + - " \"00:00:00:00:00:02\"" + - "]}"; - - routerMac1 = MacAddress.valueOf("00:00:00:00:00:01"); - routerMac2 = MacAddress.valueOf("00:00:00:00:00:02"); - routerMac3 = MacAddress.valueOf("00:00:00:00:00:03"); - ApplicationId subject = APP_ID; String key = SegmentRoutingService.SR_APP_ID; ObjectMapper mapper = new ObjectMapper(); - JsonNode jsonNode = mapper.readTree(jsonString); + JsonNode jsonNode = mapper.readTree(JSON_STRING); + JsonNode invalidJsonNode = mapper.readTree(INVALID_JSON_STRING); ConfigApplyDelegate delegate = new MockDelegate(); config = new SegmentRoutingAppConfig(); config.init(subject, key, jsonNode, mapper, delegate); + invalidConfig = new SegmentRoutingAppConfig(); + invalidConfig.init(subject, key, invalidJsonNode, mapper, delegate); } /** - * Tests vRouters getter. + * Tests config validity. + * + * @throws Exception + */ + @Test + public void testIsValid() throws Exception { + assertTrue(config.isValid()); + assertFalse(invalidConfig.isValid()); + } + + /** + * Tests vRouterMacs getter. * * @throws Exception */ @Test public void testVRouters() throws Exception { - assertTrue(config.isValid()); - Set vRouters = config.vRouterMacs(); assertThat(vRouters.size(), is(2)); - assertTrue(vRouters.contains(routerMac1)); - assertTrue(vRouters.contains(routerMac2)); + assertTrue(vRouters.contains(ROUTER_MAC_1)); + assertTrue(vRouters.contains(ROUTER_MAC_2)); } /** - * Tests vRouters setter. + * Tests vRouterMacs setter. * * @throws Exception */ @Test public void testSetVRouters() throws Exception { ImmutableSet.Builder builder = ImmutableSet.builder(); - builder.add(routerMac3); + builder.add(ROUTER_MAC_3); config.setVRouterMacs(builder.build()); Set macs = config.vRouterMacs(); assertThat(macs.size(), is(1)); - assertTrue(macs.contains(routerMac3)); + assertTrue(macs.contains(ROUTER_MAC_3)); + } + + /** + * Tests vRouterId getter. + * + * @throws Exception + */ + @Test + public void testVRouterId() throws Exception { + assertThat(config.vRouterId(), is(VROUTER_ID_1)); + } + + /** + * Tests vRouterId setter. + * + * @throws Exception + */ + @Test + public void testSetVRouterId() throws Exception { + config.setVRouterId(VROUTER_ID_2); + assertThat(config.vRouterId(), is(VROUTER_ID_2)); + } + + /** + * Tests excludePort getter. + * + * @throws Exception + */ + @Test + public void testExcludePorts() throws Exception { + Set excludePorts = config.excludePorts(); + assertThat(excludePorts.size(), is(2)); + assertTrue(excludePorts.contains(PORT_NAME_1)); + assertTrue(excludePorts.contains(PORT_NAME_2)); + } + + /** + * Tests excludePort setter. + * + * @throws Exception + */ + @Test + public void testSetExcludePorts() throws Exception { + ImmutableSet.Builder builder = ImmutableSet.builder(); + builder.add(PORT_NAME_3); + config.setExcludePorts(builder.build()); + + Set excludePorts = config.excludePorts(); + assertThat(excludePorts.size(), is(1)); + assertTrue(excludePorts.contains(PORT_NAME_3)); } private class MockDelegate implements ConfigApplyDelegate { diff --git a/tools/package/config/samples/network-cfg-fabric2x2-default-route.json b/tools/package/config/samples/network-cfg-fabric2x2-default-route.json index f9e49cc4b4..46830ce291 100644 --- a/tools/package/config/samples/network-cfg-fabric2x2-default-route.json +++ b/tools/package/config/samples/network-cfg-fabric2x2-default-route.json @@ -27,10 +27,19 @@ "of:0000000000000002/4" : { "interfaces" : [ { - "ips" : [ "10.0.2.254/24", "0.0.0.0/0" ], + "ips" : [ "10.0.2.254/24" ], "vlan" : "-1" } ] + }, + "of:0000000000000002/5" : { + "interfaces" : [ + { + "name" : "2/5/1", + "ips" : [ "100.0.0.0/24" ], + "vlan" : "-1" + } + ] } }, "devices" : { @@ -112,6 +121,10 @@ "segmentrouting" : { "vRouterMacs" : [ "00:00:00:aa:00:02" + ], + "vRouterId" : "of:0000000000000002", + "excludePorts" : [ + "2/5/1" ] } }