Add VLAN cross connect config for single switch fabric
Change-Id: Ib01f6cd0325225c9573343e1cd3a2c0f52df5b7c
diff --git a/local/ce-fabric/features.xml b/local/ce-fabric/features.xml
new file mode 100644
index 0000000..83ba135
--- /dev/null
+++ b/local/ce-fabric/features.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+ ~ Copyright 2017-present Open Networking Foundation
+ ~
+ ~ 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.
+ -->
+<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="${project.artifactId}-${project.version}">
+ <feature name="${project.artifactId}" version="${project.version}"
+ description="${project.description}">
+ <bundle>mvn:com.google.code.gson/gson/2.6.2</bundle>
+ </feature>
+</features>
diff --git a/local/ce-central-office/pom.xml b/local/ce-fabric/pom.xml
similarity index 67%
rename from local/ce-central-office/pom.xml
rename to local/ce-fabric/pom.xml
index 1ad4a4a..0e3bb75 100644
--- a/local/ce-central-office/pom.xml
+++ b/local/ce-fabric/pom.xml
@@ -25,16 +25,18 @@
<version>1.0.0-SNAPSHOT</version>
</parent>
- <artifactId>co</artifactId>
+ <artifactId>fabric</artifactId>
<packaging>bundle</packaging>
<description>CORD application for Carrier Ethernet Service</description>
<properties>
- <onos.app.name>org.opencord.ce.local.co</onos.app.name>
+ <onos.app.name>org.opencord.ce.local.fabric</onos.app.name>
<onos.version>1.10.6</onos.version>
- <onos.app.title>ECORD Central-Office Fabric config</onos.app.title>
+ <onos.app.title>E-CORD Central Office fabric config</onos.app.title>
<onos.app.url>http://opencord.org</onos.app.url>
+ <onos.app.requires>org.opencord.ce.local.bigswitch</onos.app.requires>
+ <onos.app.requires>org.opencord.ce.local.channel.http</onos.app.requires>
</properties>
<build>
@@ -56,10 +58,38 @@
<dependencies>
<dependency>
+ <groupId>org.opencord.ce</groupId>
+ <artifactId>bigswitch</artifactId>
+ <version>${parent.version}</version>
+ </dependency>
+
+ <dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.6.2</version>
</dependency>
+
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-api</artifactId>
+ <version>${onos.version}</version>
+ <classifier>tests</classifier>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onlab-osgi</artifactId>
+ <version>${onos.version}</version>
+ <classifier>tests</classifier>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-json-jackson</artifactId>
+ <version>2.25.1</version>
+ </dependency>
</dependencies>
<repositories>
diff --git a/local/ce-fabric/src/main/java/org/opencord/ce/local/fabric/CarrierEthernetFabricConfig.java b/local/ce-fabric/src/main/java/org/opencord/ce/local/fabric/CarrierEthernetFabricConfig.java
new file mode 100644
index 0000000..2d8a9c1
--- /dev/null
+++ b/local/ce-fabric/src/main/java/org/opencord/ce/local/fabric/CarrierEthernetFabricConfig.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.opencord.ce.local.fabric;
+
+import org.onlab.packet.IpAddress;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.config.Config;
+
+/**
+ * Configuration for single switch CORD fabric manager for Carrier Ethernet services.
+ */
+public class CarrierEthernetFabricConfig extends Config<ApplicationId> {
+ private static final int DEFAULT_PORT = 8181;
+ private static final String DEFAULT_USERNAME = "onos";
+ private static final String DEFAULT_PASSWORD = "rocks";
+
+ private static final String PUBLIC_IP = "publicIp";
+ private static final String PORT = "port";
+ private static final String USERNAME = "username";
+ private static final String PASSWORD = "password";
+ private static final String DEVICE_ID = "deviceId";
+
+ @Override
+ public boolean isValid() {
+ return hasOnlyFields(PUBLIC_IP, PORT, USERNAME, PASSWORD, DEVICE_ID) &&
+ publicIp() != null &&
+ deviceId() != null;
+ }
+
+ public IpAddress publicIp() {
+ String ip = get(PUBLIC_IP, null);
+ try {
+ return IpAddress.valueOf(ip);
+ } catch (IllegalArgumentException e) {
+ return null;
+ }
+ }
+
+ public Integer port() {
+ String port = get(PORT, String.valueOf(DEFAULT_PORT));
+ try {
+ return Integer.valueOf(port);
+ } catch (NumberFormatException e) {
+ return DEFAULT_PORT;
+ }
+ }
+
+ public String username() {
+ return get(USERNAME, String.valueOf(DEFAULT_USERNAME));
+ }
+
+ public String password() {
+ return get(PASSWORD, String.valueOf(DEFAULT_PASSWORD));
+ }
+
+ public DeviceId deviceId() {
+ String did = get(DEVICE_ID, null);
+ try {
+ return DeviceId.deviceId(did);
+ } catch (IllegalArgumentException e) {
+ return null;
+ }
+ }
+}
diff --git a/local/ce-fabric/src/main/java/org/opencord/ce/local/fabric/CarrierEthernetFabricManager.java b/local/ce-fabric/src/main/java/org/opencord/ce/local/fabric/CarrierEthernetFabricManager.java
new file mode 100644
index 0000000..249031b
--- /dev/null
+++ b/local/ce-fabric/src/main/java/org/opencord/ce/local/fabric/CarrierEthernetFabricManager.java
@@ -0,0 +1,312 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.opencord.ce.local.fabric;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Service;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
+import org.onlab.packet.IpAddress;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.config.ConfigFactory;
+import org.onosproject.net.config.NetworkConfigEvent;
+import org.onosproject.net.config.NetworkConfigListener;
+import org.onosproject.net.config.NetworkConfigRegistry;
+import org.opencord.ce.api.models.CarrierEthernetForwardingConstruct;
+import org.opencord.ce.api.models.CarrierEthernetNetworkInterface;
+import org.opencord.ce.api.models.CarrierEthernetUni;
+import org.opencord.ce.api.models.EvcConnId;
+import org.opencord.ce.api.services.MetroNetworkVirtualNodeService;
+import org.opencord.ce.local.bigswitch.BigSwitchService;
+import org.slf4j.Logger;
+
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+
+import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Manages a single switch CORD fabric for Carrier Ethernet services.
+ *
+ * Receives forwarding constructs from global orchestrator,
+ * and generates VLAN cross connect configuration for the
+ * ONOS fabric controller.
+ *
+ * No resources are allocated so only the node forwarding API is implemented.
+ */
+@Component(immediate = true)
+@Service
+public class CarrierEthernetFabricManager implements MetroNetworkVirtualNodeService {
+ private static final Logger log = getLogger(CarrierEthernetFabricManager.class);
+ private static final String APP_NAME = "org.opencord.ce.local.fabric";
+ private static final String APPS = "apps";
+ private static final String SEGMENT_ROUTING = "org.onosproject.segmentrouting";
+ private static final String XCONNECT = "xconnect";
+ private static final String VLAN = "vlan";
+ private static final String PORTS = "ports";
+ private static final String NAME = "name";
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected BigSwitchService bigSwitchService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CoreService coreService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected NetworkConfigRegistry cfgService;
+
+ private final InternalConfigListener cfgListener = new InternalConfigListener();
+
+ private final ConfigFactory<ApplicationId, CarrierEthernetFabricConfig> configFactory =
+ new ConfigFactory<ApplicationId, CarrierEthernetFabricConfig>(APP_SUBJECT_FACTORY,
+ CarrierEthernetFabricConfig.class, "segmentrouting_ctl", false) {
+ @Override
+ public CarrierEthernetFabricConfig createConfig() {
+ return new CarrierEthernetFabricConfig();
+ }
+ };
+
+ private ApplicationId appId;
+ // TODO: use distributed maps via storage service
+ private Set<CarrierEthernetForwardingConstruct> forwardingConstructs = new LinkedHashSet<>();
+ private Map<EvcConnId, ConnectPoint> eePorts = new HashMap<>();
+ private Map<EvcConnId, ConnectPoint> upstreamPorts = new HashMap<>();
+ private IpAddress publicIp;
+ private Integer port;
+ private String username;
+ private String password;
+ private DeviceId deviceId;
+
+ @Activate
+ protected void activate() {
+ appId = coreService.registerApplication(APP_NAME);
+ cfgService.addListener(cfgListener);
+ cfgService.registerConfigFactory(configFactory);
+ cfgListener.doUpdate(cfgService.getConfig(appId, CarrierEthernetFabricConfig.class));
+ log.info("Started");
+ }
+
+ @Deactivate
+ protected void deactivate() {
+ cfgService.removeListener(cfgListener);
+ cfgService.unregisterConfigFactory(configFactory);
+ log.info("Stopped");
+ }
+
+ @Override
+ public void setNodeForwarding(CarrierEthernetForwardingConstruct fc,
+ CarrierEthernetNetworkInterface srcNi,
+ Set<CarrierEthernetNetworkInterface> dstNiSet) {
+ addCrossconnect(fc, srcNi, dstNiSet);
+ postToSegmentRouting(buildConfig());
+ }
+
+ @Override
+ public void createBandwidthProfileResources(CarrierEthernetForwardingConstruct fc, CarrierEthernetUni uni) {
+ // No resources are allocated on the fabric
+ return;
+ }
+
+ @Override
+ public void applyBandwidthProfileResources(CarrierEthernetForwardingConstruct fc, CarrierEthernetUni uni) {
+ // No resources are allocated on the fabric
+ return;
+ }
+
+ @Override
+ public void removeBandwidthProfileResources(CarrierEthernetForwardingConstruct fc, CarrierEthernetUni uni) {
+ // No resources are allocated on the fabric
+ return;
+ }
+
+ @Override
+ public void removeAllForwardingResources(EvcConnId fcId) {
+ removeCrossconnect(fcId);
+ postToSegmentRouting(buildConfig());
+ }
+
+ /**
+ * Adds a fabric cross connect based on given Carrier Ethernet service.
+ *
+ * @param fc forwarding construct
+ * @param srcNi source network interface
+ * @param dstNiSet set of destination network interfaces
+ */
+ public void addCrossconnect(CarrierEthernetForwardingConstruct fc,
+ CarrierEthernetNetworkInterface srcNi,
+ Set<CarrierEthernetNetworkInterface> dstNiSet) {
+ // Store fc and extract physical fabric ports
+ Optional<ConnectPoint> eePort = bigSwitchService.connectPointFromVirtPort(srcNi.cp().port());
+ // Assume only a single upstream port is used, so we select randomly from set
+ CarrierEthernetNetworkInterface dstNi = dstNiSet.iterator().next();
+ Optional<ConnectPoint> upstreamPort = (dstNi == null) ? Optional.empty() :
+ bigSwitchService.connectPointFromVirtPort(dstNi.cp().port());
+ if (!eePort.isPresent() || !upstreamPort.isPresent()) {
+ log.error("Failed to install node forwarding, missing fabric ports: EE {} - upstream {}",
+ eePort, upstreamPort);
+ return;
+ } else {
+ forwardingConstructs.add(fc);
+ eePorts.put(fc.id(), eePort.get());
+ upstreamPorts.put(fc.id(), upstreamPort.get());
+ }
+ }
+
+ /**
+ * Removes a fabric cross connect based on given forwarding construct.
+ *
+ * @param fcId forwarding construct id
+ */
+ public void removeCrossconnect(EvcConnId fcId) {
+ for (Iterator<CarrierEthernetForwardingConstruct> i = forwardingConstructs.iterator(); i.hasNext();) {
+ CarrierEthernetForwardingConstruct fc = i.next();
+ if (fcId.equals(fc.id())) {
+ forwardingConstructs.remove(fc);
+ break;
+ }
+ }
+ eePorts.remove(fcId);
+ upstreamPorts.remove(fcId);
+ }
+
+
+ /**
+ * All VLAN cross connects are rebuilt and pushed out since ONOS network config does not support updates.
+ *
+ * @return JSON with cross connect configuration for segment routing app
+ */
+ public JsonObject buildConfig() {
+ JsonArray xconnects = new JsonArray();
+ forwardingConstructs.stream()
+ .map(fc -> json(fc))
+ .forEach(fc -> xconnects.add(fc));
+
+ JsonObject dpid = new JsonObject();
+ dpid.add(deviceId.toString(), xconnects);
+
+ JsonObject xconnect = new JsonObject();
+ xconnect.add(XCONNECT, dpid);
+
+ JsonObject appName = new JsonObject();
+ appName.add(SEGMENT_ROUTING, xconnect);
+
+ JsonObject config = new JsonObject();
+ config.add(APPS, appName);
+
+ return config;
+ }
+
+ /**
+ * Execute REST POST to segment routing app with given VLAN cross connect config.
+ *
+ * @param json fabric VLAN cross connect configuration in json form
+ */
+ public void postToSegmentRouting(JsonObject json) {
+ // Setup credentials
+ HttpAuthenticationFeature feature = HttpAuthenticationFeature.basicBuilder()
+ .nonPreemptive()
+ .credentials(username, password)
+ .build();
+ ClientConfig cfg = new ClientConfig();
+ cfg.register(feature);
+ Client client = ClientBuilder.newClient(cfg);
+
+ // Build URL and perform post
+ WebTarget target = client.target("http://" + publicIp + ":" + port + "/onos/v1/network/configuration/");
+ Response response = target.request().post(Entity.entity(json, MediaType.APPLICATION_JSON_TYPE));
+ response.close();
+ }
+
+ /**
+ * Build fabric config json from forwarding construct.
+ *
+ * Example VLAN cross connect configuration for fabric
+ * "apps": {
+ * "org.onosproject.segmentrouting": {
+ * "xconnect": {
+ * "of:0000000000000001": [{
+ * "vlan": 10,
+ * "ports": [5, 73],
+ * "name": "OLT1"
+ * }]
+ * }
+ * }
+ * }
+ */
+ private JsonObject json(CarrierEthernetForwardingConstruct fc) {
+ JsonObject jo = new JsonObject();
+ jo.addProperty(VLAN, fc.vlanId().toShort());
+
+ // First port is EE -> fabric, second is fabric -> upstream / CO egress
+ JsonArray ports = new JsonArray();
+ // FIXME: need to be more careful of nulls here
+ ports.add(eePorts.get(fc.id()).port().toLong());
+ ports.add(upstreamPorts.get(fc.id()).port().toLong());
+ jo.add(PORTS, ports);
+
+ jo.addProperty(NAME, fc.id().id());
+
+ return jo;
+ }
+
+ private class InternalConfigListener implements NetworkConfigListener {
+ private void doUpdate(CarrierEthernetFabricConfig cfg) {
+ if (cfg == null) {
+ log.error("Fabric config for VLAN xconnect missing");
+ return;
+ }
+
+ publicIp = cfg.publicIp();
+ port = cfg.port();
+ username = cfg.username();
+ password = cfg.password();
+ deviceId = cfg.deviceId();
+ log.info("Reconfigured");
+ }
+
+ @Override
+ public void event(NetworkConfigEvent event) {
+ if ((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
+ event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED) &&
+ event.configClass().equals(CarrierEthernetFabricConfig.class)) {
+
+ if (event.config().isPresent()) {
+ doUpdate((CarrierEthernetFabricConfig) event.config().get());
+ }
+ }
+ }
+ }
+}
diff --git a/local/ce-central-office/src/main/java/org/opencord/ce/local/co/package-info.java b/local/ce-fabric/src/main/java/org/opencord/ce/local/fabric/package-info.java
similarity index 85%
rename from local/ce-central-office/src/main/java/org/opencord/ce/local/co/package-info.java
rename to local/ce-fabric/src/main/java/org/opencord/ce/local/fabric/package-info.java
index c54876d..0b030a4 100644
--- a/local/ce-central-office/src/main/java/org/opencord/ce/local/co/package-info.java
+++ b/local/ce-fabric/src/main/java/org/opencord/ce/local/fabric/package-info.java
@@ -15,6 +15,6 @@
*/
/**
- * Central Office CE app.
+ * Single switch CORD fabric support for Carrier Ethernet services.
*/
-package org.opencord.ce.local.co;
\ No newline at end of file
+package org.opencord.ce.local.fabric;
\ No newline at end of file
diff --git a/local/ce-fabric/src/test/java/org.opencord.ce.local.fabric/CarrierEthernetFabricManagerTest.java b/local/ce-fabric/src/test/java/org.opencord.ce.local.fabric/CarrierEthernetFabricManagerTest.java
new file mode 100644
index 0000000..cabcb77
--- /dev/null
+++ b/local/ce-fabric/src/test/java/org.opencord.ce.local.fabric/CarrierEthernetFabricManagerTest.java
@@ -0,0 +1,243 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.opencord.ce.local.fabric;
+
+import com.google.common.collect.Sets;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.onlab.junit.TestUtils;
+import org.onlab.osgi.ServiceDirectory;
+import org.onlab.osgi.TestServiceDirectory;
+import org.onlab.packet.VlanId;
+import org.onosproject.core.CoreServiceAdapter;
+import org.onosproject.event.AbstractListenerManager;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.config.NetworkConfigRegistryAdapter;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.device.DeviceServiceAdapter;
+import org.onosproject.net.device.PortDescription;
+import org.onosproject.net.domain.DomainId;
+import org.opencord.ce.api.models.CarrierEthernetConnection;
+import org.opencord.ce.api.models.CarrierEthernetEnni;
+import org.opencord.ce.api.models.CarrierEthernetForwardingConstruct;
+import org.opencord.ce.api.models.CarrierEthernetInni;
+import org.opencord.ce.api.models.CarrierEthernetLogicalTerminationPoint;
+import org.opencord.ce.api.models.CarrierEthernetNetworkInterface;
+import org.opencord.ce.api.models.CarrierEthernetUni;
+import org.opencord.ce.api.models.EvcConnId;
+import org.opencord.ce.local.bigswitch.BigSwitchEvent;
+import org.opencord.ce.local.bigswitch.BigSwitchListener;
+import org.opencord.ce.local.bigswitch.BigSwitchService;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Unit tests for {@link CarrierEthernetFabricManager}.
+ */
+public class CarrierEthernetFabricManagerTest {
+
+ private CarrierEthernetFabricManager target;
+ private static ServiceDirectory original;
+ private static TestServiceDirectory directory;
+
+ private CarrierEthernetLogicalTerminationPoint ltpSrc;
+ private CarrierEthernetLogicalTerminationPoint ltpDst;
+ // Physical connect points
+ private static ConnectPoint srcUniCp = ConnectPoint.deviceConnectPoint("netconf:10.0.0.10/1");
+ private ConnectPoint dstUniCp = ConnectPoint.deviceConnectPoint("netconf:10.0.0.20/1");
+ private ConnectPoint inniPhyCp = ConnectPoint.deviceConnectPoint("of:0000000000000001/1");
+ private ConnectPoint enni1PhyCp = ConnectPoint.deviceConnectPoint("of:0000000000000001/2");
+ private ConnectPoint enni2PhyCp = ConnectPoint.deviceConnectPoint("of:0000000000000001/3");
+ // Bigswitch (logical) connect points
+ private ConnectPoint inniBsCp = ConnectPoint.deviceConnectPoint("domain:0000000000000001/1");
+ private ConnectPoint enni1BsCp = ConnectPoint.deviceConnectPoint("domain:0000000000000001/2");
+ private ConnectPoint enni2BsCp = ConnectPoint.deviceConnectPoint("domain:0000000000000001/3");
+ // Carrier Ethernet models
+ private CarrierEthernetForwardingConstruct fc1;
+ private CarrierEthernetForwardingConstruct fc2;
+ private CarrierEthernetNetworkInterface srcUni;
+ private CarrierEthernetNetworkInterface dstUni;
+ private CarrierEthernetNetworkInterface inni;
+ private CarrierEthernetNetworkInterface enni1;
+ private CarrierEthernetNetworkInterface enni2;
+
+ private DeviceId deviceId = DeviceId.deviceId("of:0000000000000001");
+ private static VlanId vlan1 = VlanId.vlanId((short) 100);
+ private static VlanId vlan2 = VlanId.vlanId((short) 200);
+
+ @BeforeClass
+ public static void setUpBaseConfigClass() throws TestUtils.TestUtilsException {
+ directory = new TestServiceDirectory();
+ directory.add(DeviceService.class, new DeviceServiceAdapter(Collections.emptyList()));
+ original = TestUtils.getField(CarrierEthernetNetworkInterface.class, "serviceDirectory");
+ TestUtils.setField(CarrierEthernetNetworkInterface.class, "serviceDirectory", directory);
+ }
+
+ @AfterClass
+ public static void tearDownBaseConfigClass() throws TestUtils.TestUtilsException {
+ TestUtils.setField(CarrierEthernetNetworkInterface.class, "serviceDirectory", original);
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ // Initialize the fabric manager
+ target = new CarrierEthernetFabricManager();
+ target.bigSwitchService = new TestBigSwitchService();
+ target.cfgService = new NetworkConfigRegistryAdapter();
+ target.coreService = new CoreServiceAdapter();
+
+ // Build UNIs
+ srcUni = CarrierEthernetUni.builder()
+ .cp(srcUniCp)
+ .build();
+ dstUni = CarrierEthernetUni.builder()
+ .cp(dstUniCp)
+ .build();
+ ltpSrc = new CarrierEthernetLogicalTerminationPoint("srcUni", srcUni);
+ ltpDst = new CarrierEthernetLogicalTerminationPoint("dstUni", dstUni);
+
+ // Build FC connecting UNIs
+ fc1 = CarrierEthernetForwardingConstruct.builder()
+ .cfgId("test1")
+ .id(EvcConnId.of("test1"))
+ .type(CarrierEthernetConnection.Type.POINT_TO_POINT)
+ .ltpSet(Sets.newHashSet(ltpSrc, ltpDst))
+ .build();
+ fc1.setVlanId(vlan1);
+ fc2 = CarrierEthernetForwardingConstruct.builder()
+ .cfgId("test2")
+ .id(EvcConnId.of("test2"))
+ .type(CarrierEthernetConnection.Type.POINT_TO_POINT)
+ .ltpSet(Sets.newHashSet(ltpSrc, ltpDst))
+ .build();
+ fc2.setVlanId(vlan2);
+ inni = CarrierEthernetInni.builder()
+ .cp(inniBsCp)
+ .build();
+ enni1 = CarrierEthernetEnni.builder()
+ .cp(enni1BsCp)
+ .build();
+ enni2 = CarrierEthernetEnni.builder()
+ .cp(enni2BsCp)
+ .build();
+
+ target.activate();
+ }
+
+ @After
+ public void tearDown() {
+ target.deactivate();
+ }
+
+ @Test
+ public void testBuildConfig() {
+ TestUtils.setField(target, "deviceId", deviceId);
+ JsonParser parser = new JsonParser();
+ JsonObject json;
+ String expected;
+
+ // Add first fc
+ target.addCrossconnect(fc1, inni, Sets.newHashSet(enni1));
+ json = target.buildConfig();
+ expected =
+ "{\"apps\":{" +
+ "\"org.onosproject.segmentrouting\":{" +
+ "\"xconnect\":{" +
+ "\"of:0000000000000001\":[{" +
+ "\"vlan\":" + vlan1.toString() + "," +
+ "\"ports\":[1, 2]," +
+ "\"name\": \"" + fc1.id().id() + "\"}" +
+ "]}}}}";
+ assertEquals(json, parser.parse(expected).getAsJsonObject());
+
+ // Add second fc
+ target.addCrossconnect(fc2, inni, Sets.newHashSet(enni2));
+ json = target.buildConfig();
+ expected =
+ "{\"apps\":{" +
+ "\"org.onosproject.segmentrouting\":{" +
+ "\"xconnect\":{" +
+ "\"of:0000000000000001\":[{" +
+ "\"vlan\":" + vlan1.toString() + "," +
+ "\"ports\":[1, 2]," +
+ "\"name\": \"" + fc1.id().id() + "\"}," +
+ "{\"vlan\":" + vlan2.toString() + "," +
+ "\"ports\":[1, 3]," +
+ "\"name\": \"" + fc2.id().id() + "\"}" +
+ "]}}}}";
+ assertEquals(json, parser.parse(expected).getAsJsonObject());
+
+ // Remove first fc
+ target.removeCrossconnect(fc1.id());
+ json = target.buildConfig();
+ expected =
+ "{\"apps\":{" +
+ "\"org.onosproject.segmentrouting\":{" +
+ "\"xconnect\":{" +
+ "\"of:0000000000000001\":[{" +
+ "\"vlan\":" + vlan2.toString() + "," +
+ "\"ports\":[1, 3]," +
+ "\"name\": \"" + fc2.id().id() + "\"}" +
+ "]}}}}";
+ assertEquals(json, parser.parse(expected).getAsJsonObject());
+ }
+
+ private class TestBigSwitchService
+ extends AbstractListenerManager<BigSwitchEvent, BigSwitchListener>
+ implements BigSwitchService {
+
+ @Override
+ public List<PortDescription> getPorts() {
+ return null;
+ }
+
+ @Override
+ public PortNumber getPort(ConnectPoint port) {
+ return null;
+ }
+
+ @Override
+ public Optional<ConnectPoint> connectPointFromVirtPort(PortNumber portNumber) {
+ if (portNumber.toLong() == 1) {
+ return Optional.of(inniPhyCp);
+ }
+ if (portNumber.toLong() == 2) {
+ return Optional.of(enni1PhyCp);
+ }
+ if (portNumber.toLong() == 3) {
+ return Optional.of(enni2PhyCp);
+ }
+
+ return Optional.empty();
+ }
+
+ @Override
+ public DomainId domainId() {
+ return null;
+ }
+ }
+}
diff --git a/local/ce-vee/pom.xml b/local/ce-vee/pom.xml
index 7d7ec38..5ac2ee6 100644
--- a/local/ce-vee/pom.xml
+++ b/local/ce-vee/pom.xml
@@ -35,7 +35,10 @@
<onos.app.name>org.opencord.ce.local.vee</onos.app.name>
<onos.app.title>E-CORD Ethernet Edge app</onos.app.title>
<onos.app.url>http://opencord.org</onos.app.url>
+ <onos.app.requires>org.opencord.ce.local.bigswitch</onos.app.requires>
+ <onos.app.requires>org.opencord.ce.local.channel.http</onos.app.requires>
</properties>
+
<dependencies>
<dependency>
<groupId>org.opencord.ce</groupId>
diff --git a/local/config-samples/co1-config.json b/local/config-samples/co1-onos-cord-cfg.json
similarity index 89%
rename from local/config-samples/co1-config.json
rename to local/config-samples/co1-onos-cord-cfg.json
index 222832d..a908151 100644
--- a/local/config-samples/co1-config.json
+++ b/local/config-samples/co1-onos-cord-cfg.json
@@ -8,7 +8,7 @@
"connectPoint" : "netconf:10.0.0.10:830/1"
},
{
- "mefPortType" : "UNI",
+ "mefPortType" : "INNI",
"connectPoint" : "netconf:10.0.0.10:830/0",
"interlinkId" : "cm-1"
}
@@ -17,7 +17,7 @@
"org.opencord.ce.local.channel.http" : {
"global" : {
"publicIp" : "10.128.14.1",
- "port" : "8181",
+ "port" : "8182",
"username" : "sdn",
"password" : "rocks",
"topic" : "ecord-domains-topic-one"
diff --git a/local/config-samples/co1-withEE-config.json b/local/config-samples/co1-withEE-onos-cord-cfg.json
similarity index 96%
rename from local/config-samples/co1-withEE-config.json
rename to local/config-samples/co1-withEE-onos-cord-cfg.json
index 6c1ef4c..e54cf63 100644
--- a/local/config-samples/co1-withEE-config.json
+++ b/local/config-samples/co1-withEE-onos-cord-cfg.json
@@ -29,7 +29,7 @@
"org.opencord.ce.local.channel.http" : {
"global" : {
"publicIp" : "10.128.14.1",
- "port" : "8181",
+ "port" : "8182",
"username" : "sdn",
"password" : "rocks",
"topic" : "ecord-domains-topic-one"
diff --git a/local/config-samples/co2-config.json b/local/config-samples/co2-onos-cord-cfg.json
similarity index 89%
rename from local/config-samples/co2-config.json
rename to local/config-samples/co2-onos-cord-cfg.json
index 2b6f525..210c7c5 100644
--- a/local/config-samples/co2-config.json
+++ b/local/config-samples/co2-onos-cord-cfg.json
@@ -8,7 +8,7 @@
"connectPoint" : "netconf:10.0.0.20:830/1"
},
{
- "mefPortType" : "UNI",
+ "mefPortType" : "INNI",
"connectPoint" : "netconf:10.0.0.20:830/0",
"interlinkId" : "cm-1"
}
@@ -17,7 +17,7 @@
"org.opencord.ce.local.channel.http" : {
"global" : {
"publicIp" : "10.128.14.1",
- "port" : "8181",
+ "port" : "8182",
"username" : "sdn",
"password" : "rocks",
"topic" : "ecord-domains-topic-one"
diff --git a/local/config-samples/co2-withEE-config.json b/local/config-samples/co2-withEE-onos-cord-cfg.json
similarity index 96%
rename from local/config-samples/co2-withEE-config.json
rename to local/config-samples/co2-withEE-onos-cord-cfg.json
index 1140d7c..78b14b5 100644
--- a/local/config-samples/co2-withEE-config.json
+++ b/local/config-samples/co2-withEE-onos-cord-cfg.json
@@ -29,7 +29,7 @@
"org.opencord.ce.local.channel.http" : {
"global" : {
"publicIp" : "10.128.14.1",
- "port" : "8181",
+ "port" : "8182",
"username" : "sdn",
"password" : "rocks",
"topic" : "ecord-domains-topic-one"
diff --git a/local/config-samples/onos-fabric-cfg.json b/local/config-samples/onos-fabric-cfg.json
new file mode 100644
index 0000000..a9a6f6f
--- /dev/null
+++ b/local/config-samples/onos-fabric-cfg.json
@@ -0,0 +1,38 @@
+{
+ "apps" : {
+ "org.opencord.ce.local.fabric" : {
+ "segmentrouting_ctl": {
+ "publicIp": "127.0.0.1",
+ "port": "8181",
+ "username": "sdn",
+ "password": "rocks",
+ "deviceId": "of:0000001e08095936"
+ }
+ },
+ "org.opencord.ce.local.bigswitch" : {
+ "mefPorts" :
+ [
+ {
+ "mefPortType" : "INNI",
+ "connectPoint" : "of:0000001e08095936/1",
+ "interlinkId" : "EE-2-fabric"
+ },
+ {
+ "mefPortType" : "ENNI",
+ "connectPoint" : "of:0000001e08095936/49",
+ "interlinkId" : "fabric-upstream"
+ }
+ ]
+ },
+ "org.opencord.ce.local.channel.http" : {
+ "global" : {
+ "publicIp" : "10.128.14.1",
+ "port" : "8182",
+ "username" : "sdn",
+ "password" : "rocks",
+ "topic" : "ecord-domains-topic-one"
+ }
+ }
+
+ }
+}
diff --git a/local/pom.xml b/local/pom.xml
index 199412e..ed76a1c 100644
--- a/local/pom.xml
+++ b/local/pom.xml
@@ -43,7 +43,7 @@
<module>http-channel</module>
<module>ce-transport</module>
<module>ce-vee</module>
- <module>ce-central-office</module>
+ <module>ce-fabric</module>
<module>common-component</module>
</modules>
@@ -53,6 +53,19 @@
<artifactId>ce-api</artifactId>
<version>${project.version}</version>
</dependency>
+
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onlab-junit</artifactId>
+ <version>${onos.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>