Added management instance handler and some refactoring
- Added management instance handler to provide management network
connectivity for the management network connected instance, currenly
local managemenet network connectivity provided
- Renamed Dummy service to Default service
- Renamed CordVtnInstanceHandler to AbstractInstanceHandler and moved
default VTN rule populations to DefaultInstanceHandler
- Removed workaround management network access code from OLT agent
instance handler
Change-Id: I990c29b8ae41674d136fbc12f3c4e92167c8c74c
diff --git a/src/main/java/org/opencord/cordvtn/api/CordVtnConfig.java b/src/main/java/org/opencord/cordvtn/api/CordVtnConfig.java
index f4a8cec..10bc6a1 100644
--- a/src/main/java/org/opencord/cordvtn/api/CordVtnConfig.java
+++ b/src/main/java/org/opencord/cordvtn/api/CordVtnConfig.java
@@ -20,7 +20,6 @@
import com.google.common.collect.Sets;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.TpPort;
import org.onosproject.core.ApplicationId;
@@ -42,33 +41,32 @@
protected final Logger log = getLogger(getClass());
- public static final String PRIVATE_GATEWAY_MAC = "privateGatewayMac";
- public static final String PUBLIC_GATEWAYS = "publicGateways";
- public static final String GATEWAY_IP = "gatewayIp";
- public static final String GATEWAY_MAC = "gatewayMac";
- public static final String LOCAL_MANAGEMENT_IP = "localManagementIp";
- public static final String MANAGEMENT_IP = "managementIpRange";
- public static final String OVSDB_PORT = "ovsdbPort";
+ private static final String PRIVATE_GATEWAY_MAC = "privateGatewayMac";
+ private static final String PUBLIC_GATEWAYS = "publicGateways";
+ private static final String GATEWAY_IP = "gatewayIp";
+ private static final String GATEWAY_MAC = "gatewayMac";
+ private static final String LOCAL_MANAGEMENT_IP = "localManagementIp";
+ private static final String OVSDB_PORT = "ovsdbPort";
- public static final String CORDVTN_NODES = "nodes";
- public static final String HOSTNAME = "hostname";
- public static final String HOST_MANAGEMENT_IP = "hostManagementIp";
- public static final String DATA_PLANE_IP = "dataPlaneIp";
- public static final String DATA_PLANE_INTF = "dataPlaneIntf";
- public static final String BRIDGE_ID = "bridgeId";
+ private static final String CORDVTN_NODES = "nodes";
+ private static final String HOSTNAME = "hostname";
+ private static final String HOST_MANAGEMENT_IP = "hostManagementIp";
+ private static final String DATA_PLANE_IP = "dataPlaneIp";
+ private static final String DATA_PLANE_INTF = "dataPlaneIntf";
+ private static final String BRIDGE_ID = "bridgeId";
- public static final String SSH = "ssh";
- public static final String SSH_PORT = "sshPort";
- public static final String SSH_USER = "sshUser";
- public static final String SSH_KEY_FILE = "sshKeyFile";
+ private static final String SSH = "ssh";
+ private static final String SSH_PORT = "sshPort";
+ private static final String SSH_USER = "sshUser";
+ private static final String SSH_KEY_FILE = "sshKeyFile";
- public static final String OPENSTACK = "openstack";
- public static final String XOS = "xos";
+ private static final String OPENSTACK = "openstack";
+ private static final String XOS = "xos";
- public static final String ENDPOINT = "endpoint";
- public static final String TENANT = "tenant";
- public static final String USER = "user";
- public static final String PASSWORD = "password";
+ private static final String ENDPOINT = "endpoint";
+ private static final String TENANT = "tenant";
+ private static final String USER = "user";
+ private static final String PASSWORD = "password";
/**
* Returns the set of nodes read from network config.
@@ -189,25 +187,6 @@
}
/**
- * Returns management IP address range.
- *
- * @return management network ip prefix, or null
- */
- public IpPrefix managementIpRange() {
- JsonNode jsonNode = object.get(MANAGEMENT_IP);
- if (jsonNode == null) {
- return null;
- }
-
- try {
- return IpPrefix.valueOf(jsonNode.asText());
- } catch (IllegalArgumentException e) {
- log.error("{}:{} wrong address format", MANAGEMENT_IP, jsonNode);
- return null;
- }
- }
-
- /**
* Returns XOS access information.
*
* @return XOS access, or null
diff --git a/src/main/java/org/opencord/cordvtn/api/Instance.java b/src/main/java/org/opencord/cordvtn/api/Instance.java
index 3945a9d..23841b6 100644
--- a/src/main/java/org/opencord/cordvtn/api/Instance.java
+++ b/src/main/java/org/opencord/cordvtn/api/Instance.java
@@ -22,7 +22,7 @@
import org.onosproject.net.Host;
import org.onosproject.net.PortNumber;
import org.onosproject.xosclient.api.VtnPortId;
-import org.onosproject.xosclient.api.VtnService;
+import org.onosproject.xosclient.api.VtnServiceApi.ServiceType;
import org.onosproject.xosclient.api.VtnServiceId;
import static com.google.common.base.Preconditions.checkArgument;
@@ -91,9 +91,9 @@
*
* @return vtn service type
*/
- public VtnService.ServiceType serviceType() {
+ public ServiceType serviceType() {
String serviceType = host.annotations().value(SERVICE_TYPE);
- return VtnService.ServiceType.valueOf(serviceType);
+ return ServiceType.valueOf(serviceType);
}
/**
diff --git a/src/main/java/org/opencord/cordvtn/impl/AbstractInstanceHandler.java b/src/main/java/org/opencord/cordvtn/impl/AbstractInstanceHandler.java
new file mode 100644
index 0000000..29868b4
--- /dev/null
+++ b/src/main/java/org/opencord/cordvtn/impl/AbstractInstanceHandler.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * 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.cordvtn.impl;
+
+import org.onlab.osgi.DefaultServiceDirectory;
+import org.onlab.osgi.ServiceDirectory;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.mastership.MastershipService;
+import org.onosproject.net.Host;
+import org.onosproject.net.config.NetworkConfigEvent;
+import org.onosproject.net.config.NetworkConfigListener;
+import org.onosproject.net.config.NetworkConfigRegistry;
+import org.onosproject.net.host.HostEvent;
+import org.onosproject.net.host.HostListener;
+import org.onosproject.net.host.HostService;
+import org.onosproject.xosclient.api.OpenStackAccess;
+import org.onosproject.xosclient.api.VtnPort;
+import org.onosproject.xosclient.api.VtnPortApi;
+import org.onosproject.xosclient.api.VtnPortId;
+import org.onosproject.xosclient.api.VtnService;
+import org.onosproject.xosclient.api.VtnServiceApi;
+import org.onosproject.xosclient.api.VtnServiceApi.ServiceType;
+import org.onosproject.xosclient.api.VtnServiceId;
+import org.onosproject.xosclient.api.XosAccess;
+import org.onosproject.xosclient.api.XosClientService;
+import org.opencord.cordvtn.api.CordVtnConfig;
+import org.opencord.cordvtn.api.CordVtnService;
+import org.opencord.cordvtn.api.Instance;
+import org.opencord.cordvtn.api.InstanceHandler;
+import org.slf4j.Logger;
+
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.stream.Collectors;
+import java.util.stream.StreamSupport;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Provides default virtual network connectivity for service instances.
+ */
+public abstract class AbstractInstanceHandler implements InstanceHandler {
+
+ protected final Logger log = getLogger(getClass());
+
+ protected CoreService coreService;
+ protected MastershipService mastershipService;
+ protected NetworkConfigRegistry configRegistry;
+ protected HostService hostService;
+ protected XosClientService xosClient;
+ protected CordVtnPipeline pipeline;
+ protected CordVtnNodeManager nodeManager;
+
+ protected ApplicationId appId;
+ protected ExecutorService eventExecutor;
+ protected Optional<ServiceType> serviceType = Optional.empty();
+ protected NetworkConfigListener configListener = new InternalConfigListener();
+ protected HostListener hostListener = new InternalHostListener();
+
+ private static final String OPENSTACK_ACCESS_ERROR = "OpenStack access is not configured";
+ private static final String XOS_ACCESS_ERROR = "XOS access is not configured";
+ private XosAccess xosAccess = null;
+ private OpenStackAccess osAccess = null;
+
+ protected void activate() {
+ ServiceDirectory services = new DefaultServiceDirectory();
+ coreService = services.get(CoreService.class);
+ configRegistry = services.get(NetworkConfigRegistry.class);
+ mastershipService = services.get(MastershipService.class);
+ hostService = services.get(HostService.class);
+ xosClient = services.get(XosClientService.class);
+ pipeline = services.get(CordVtnPipeline.class);
+ nodeManager = services.get(CordVtnNodeManager.class);
+
+ appId = coreService.registerApplication(CordVtnService.CORDVTN_APP_ID);
+ hostService.addListener(hostListener);
+ configRegistry.addListener(configListener);
+
+ log.info("Started");
+ }
+
+ protected void deactivate() {
+ hostService.removeListener(hostListener);
+ configRegistry.removeListener(configListener);
+ eventExecutor.shutdown();
+
+ log.info("Stopped");
+ }
+
+ protected VtnService getVtnService(VtnServiceId serviceId) {
+ checkNotNull(osAccess, OPENSTACK_ACCESS_ERROR);
+ checkNotNull(xosAccess, XOS_ACCESS_ERROR);
+
+ // TODO remove openstack access when XOS provides all information
+ VtnServiceApi serviceApi = xosClient.getClient(xosAccess).vtnService();
+ VtnService service = serviceApi.service(serviceId, osAccess);
+ if (service == null) {
+ log.warn("Failed to get VtnService for {}", serviceId);
+ }
+ return service;
+ }
+
+ protected VtnPort getVtnPort(Instance instance) {
+ checkNotNull(osAccess, OPENSTACK_ACCESS_ERROR);
+ checkNotNull(xosAccess, XOS_ACCESS_ERROR);
+
+ VtnPortId vtnPortId = instance.portId();
+ VtnPortApi portApi = xosClient.getClient(xosAccess).vtnPort();
+ VtnPort vtnPort = portApi.vtnPort(vtnPortId, osAccess);
+ if (vtnPort == null) {
+ log.warn("Failed to get port information of {}", instance);
+ return null;
+ }
+ return vtnPort;
+ }
+
+ protected Set<Instance> getInstances(VtnServiceId serviceId) {
+ return StreamSupport.stream(hostService.getHosts().spliterator(), false)
+ .filter(host -> Objects.equals(
+ serviceId.id(),
+ host.annotations().value(Instance.SERVICE_ID)))
+ .map(Instance::of)
+ .collect(Collectors.toSet());
+ }
+
+ protected void readConfiguration() {
+ CordVtnConfig config = configRegistry.getConfig(appId, CordVtnConfig.class);
+ if (config == null) {
+ log.debug("No configuration found");
+ return;
+ }
+ osAccess = config.openstackAccess();
+ xosAccess = config.xosAccess();
+ }
+
+ private class InternalHostListener implements HostListener {
+
+ @Override
+ public void event(HostEvent event) {
+ Host host = event.subject();
+ if (!mastershipService.isLocalMaster(host.location().deviceId())) {
+ // do not allow to proceed without mastership
+ return;
+ }
+
+ Instance instance = Instance.of(host);
+ if (serviceType.isPresent() &&
+ !serviceType.get().equals(instance.serviceType())) {
+ // not my service instance, do nothing
+ return;
+ }
+
+ switch (event.type()) {
+ case HOST_UPDATED:
+ case HOST_ADDED:
+ eventExecutor.execute(() -> instanceDetected(instance));
+ break;
+ case HOST_REMOVED:
+ eventExecutor.execute(() -> instanceRemoved(instance));
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ private class InternalConfigListener implements NetworkConfigListener {
+
+ @Override
+ public void event(NetworkConfigEvent event) {
+ if (!event.configClass().equals(CordVtnConfig.class)) {
+ return;
+ }
+
+ switch (event.type()) {
+ case CONFIG_ADDED:
+ case CONFIG_UPDATED:
+ readConfiguration();
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
diff --git a/src/main/java/org/opencord/cordvtn/impl/CordVtn.java b/src/main/java/org/opencord/cordvtn/impl/CordVtn.java
index f007a36..854bd40 100644
--- a/src/main/java/org/opencord/cordvtn/impl/CordVtn.java
+++ b/src/main/java/org/opencord/cordvtn/impl/CordVtn.java
@@ -33,7 +33,6 @@
import org.onosproject.core.DefaultGroupId;
import org.onosproject.core.GroupId;
import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultFlowRule;
import org.onosproject.net.flow.DefaultTrafficSelector;
@@ -50,8 +49,6 @@
import org.onosproject.net.group.GroupDescription;
import org.onosproject.net.group.GroupKey;
import org.onosproject.net.group.GroupService;
-import org.onosproject.net.host.HostEvent;
-import org.onosproject.net.host.HostListener;
import org.onosproject.xosclient.api.VtnService;
import org.onosproject.xosclient.api.VtnServiceId;
import org.slf4j.Logger;
@@ -73,7 +70,7 @@
*/
@Component(immediate = true)
@Service
-public class CordVtn extends CordVtnInstanceHandler implements CordVtnService {
+public class CordVtn extends AbstractInstanceHandler implements CordVtnService {
protected final Logger log = getLogger(getClass());
@@ -83,7 +80,6 @@
@Activate
protected void activate() {
eventExecutor = newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtn", "event-handler"));
- hostListener = new InternalHostListener();
super.activate();
}
@@ -382,29 +378,4 @@
});
return new GroupBuckets(buckets);
}
-
- private class InternalHostListener implements HostListener {
-
- @Override
- public void event(HostEvent event) {
- Host host = event.subject();
- if (!mastershipService.isLocalMaster(host.location().deviceId())) {
- // do not allow to proceed without mastership
- return;
- }
-
- Instance instance = Instance.of(host);
- switch (event.type()) {
- case HOST_UPDATED:
- case HOST_ADDED:
- eventExecutor.execute(() -> instanceDetected(instance));
- break;
- case HOST_REMOVED:
- eventExecutor.execute(() -> instanceRemoved(instance));
- break;
- default:
- break;
- }
- }
- }
}
diff --git a/src/main/java/org/opencord/cordvtn/impl/CordVtnInstanceHandler.java b/src/main/java/org/opencord/cordvtn/impl/CordVtnInstanceHandler.java
deleted file mode 100644
index 242d94c..0000000
--- a/src/main/java/org/opencord/cordvtn/impl/CordVtnInstanceHandler.java
+++ /dev/null
@@ -1,535 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Laboratory
- *
- * 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.cordvtn.impl;
-
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.Ip4Address;
-import org.onlab.packet.Ip4Prefix;
-import org.opencord.cordvtn.api.CordVtnConfig;
-import org.opencord.cordvtn.api.CordVtnNode;
-import org.opencord.cordvtn.api.CordVtnService;
-import org.opencord.cordvtn.api.Instance;
-import org.opencord.cordvtn.api.InstanceHandler;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.CoreService;
-import org.onosproject.mastership.MastershipService;
-import org.onosproject.net.Host;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.config.NetworkConfigEvent;
-import org.onosproject.net.config.NetworkConfigListener;
-import org.onosproject.net.config.NetworkConfigRegistry;
-import org.onosproject.net.flow.DefaultFlowRule;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flow.instructions.ExtensionTreatment;
-import org.onosproject.net.host.HostEvent;
-import org.onosproject.net.host.HostListener;
-import org.onosproject.net.host.HostService;
-import org.onosproject.xosclient.api.OpenStackAccess;
-import org.onosproject.xosclient.api.VtnService;
-import org.onosproject.xosclient.api.VtnServiceApi;
-import org.onosproject.xosclient.api.VtnServiceId;
-import org.onosproject.xosclient.api.XosAccess;
-import org.onosproject.xosclient.api.XosClientService;
-import org.slf4j.Logger;
-
-import java.util.Objects;
-import java.util.Set;
-import java.util.concurrent.ExecutorService;
-import java.util.stream.Collectors;
-import java.util.stream.StreamSupport;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.onosproject.xosclient.api.VtnService.NetworkType.MANAGEMENT;
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Provides default virtual network connectivity for service instances.
- */
-@Component(immediate = true)
-public abstract class CordVtnInstanceHandler implements InstanceHandler {
-
- protected final Logger log = getLogger(getClass());
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected CoreService coreService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected MastershipService mastershipService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected NetworkConfigRegistry configRegistry;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected HostService hostService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected XosClientService xosClient;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected CordVtnNodeManager nodeManager;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected CordVtnPipeline pipeline;
-
- protected static final String OPENSTACK_ACCESS_ERROR = "OpenStack access is not configured";
- protected static final String XOS_ACCESS_ERROR = "XOS access is not configured";
-
- protected XosAccess xosAccess = null;
- protected OpenStackAccess osAccess = null;
- protected ApplicationId appId;
- protected VtnService.ServiceType serviceType;
- protected ExecutorService eventExecutor;
-
- protected HostListener hostListener = new InternalHostListener();
- protected NetworkConfigListener configListener = new InternalConfigListener();
-
- protected void activate() {
- // sub class should set service type and event executor in its activate method
- appId = coreService.registerApplication(CordVtnService.CORDVTN_APP_ID);
-
- hostService.addListener(hostListener);
- configRegistry.addListener(configListener);
-
- log.info("Started");
- }
-
- protected void deactivate() {
- hostService.removeListener(hostListener);
- configRegistry.removeListener(configListener);
- eventExecutor.shutdown();
-
- log.info("Stopped");
- }
-
- @Override
- public void instanceDetected(Instance instance) {
- log.info("Instance is detected {}", instance);
-
- VtnService service = getVtnService(instance.serviceId());
- if (service == null) {
- log.warn("Failed to get VtnService for {}", instance);
- return;
- }
-
- if (service.networkType().equals(MANAGEMENT)) {
- managementNetworkRules(instance, service, true);
- }
-
- defaultConnectionRules(instance, service, true);
- }
-
- @Override
- public void instanceRemoved(Instance instance) {
- log.info("Instance is removed {}", instance);
-
- VtnService service = getVtnService(instance.serviceId());
- if (service == null) {
- log.warn("Failed to get VtnService for {}", instance);
- return;
- }
-
- if (service.networkType().equals(MANAGEMENT)) {
- managementNetworkRules(instance, service, false);
- }
-
- // TODO check if any stale management network rules are
- defaultConnectionRules(instance, service, false);
- }
-
- protected VtnService getVtnService(VtnServiceId serviceId) {
- checkNotNull(osAccess, OPENSTACK_ACCESS_ERROR);
- checkNotNull(xosAccess, XOS_ACCESS_ERROR);
-
- // TODO remove openstack access when XOS provides all information
- VtnServiceApi serviceApi = xosClient.getClient(xosAccess).vtnService();
- VtnService service = serviceApi.service(serviceId, osAccess);
- if (service == null) {
- log.warn("Failed to get VtnService for {}", serviceId);
- }
- return service;
- }
-
- protected Set<Instance> getInstances(VtnServiceId serviceId) {
- return StreamSupport.stream(hostService.getHosts().spliterator(), false)
- .filter(host -> Objects.equals(
- serviceId.id(),
- host.annotations().value(Instance.SERVICE_ID)))
- .map(Instance::of)
- .collect(Collectors.toSet());
- }
-
- private void defaultConnectionRules(Instance instance, VtnService service, boolean install) {
- long vni = service.vni();
- Ip4Prefix serviceIpRange = service.subnet().getIp4Prefix();
-
- inPortRule(instance, install);
- dstIpRule(instance, vni, install);
- tunnelInRule(instance, vni, install);
-
- if (install) {
- directAccessRule(serviceIpRange, serviceIpRange, true);
- serviceIsolationRule(serviceIpRange, true);
- } else if (getInstances(service.id()).isEmpty()) {
- directAccessRule(serviceIpRange, serviceIpRange, false);
- serviceIsolationRule(serviceIpRange, false);
- }
- }
-
- private void managementNetworkRules(Instance instance, VtnService service, boolean install) {
-
- managementPerInstanceRule(instance, install);
- if (install) {
- managementBaseRule(instance, service, true);
- } else if (!hostService.getConnectedHosts(instance.deviceId()).stream()
- .filter(host -> Instance.of(host).serviceId().equals(service.id()))
- .findAny()
- .isPresent()) {
- managementBaseRule(instance, service, false);
- }
- }
-
- private void managementBaseRule(Instance instance, VtnService service, boolean install) {
- TrafficSelector selector = DefaultTrafficSelector.builder()
- .matchEthType(Ethernet.TYPE_ARP)
- .matchArpTpa(service.serviceIp().getIp4Address())
- .build();
-
- TrafficTreatment treatment = DefaultTrafficTreatment.builder()
- .setOutput(PortNumber.LOCAL)
- .build();
-
- FlowRule flowRule = DefaultFlowRule.builder()
- .fromApp(appId)
- .withSelector(selector)
- .withTreatment(treatment)
- .withPriority(CordVtnPipeline.PRIORITY_MANAGEMENT)
- .forDevice(instance.deviceId())
- .forTable(CordVtnPipeline.TABLE_ZERO)
- .makePermanent()
- .build();
-
- pipeline.processFlowRule(install, flowRule);
-
- selector = DefaultTrafficSelector.builder()
- .matchInPort(PortNumber.LOCAL)
- .matchEthType(Ethernet.TYPE_IPV4)
- .matchIPDst(service.subnet())
- .build();
-
- treatment = DefaultTrafficTreatment.builder()
- .transition(CordVtnPipeline.TABLE_DST_IP)
- .build();
-
- flowRule = DefaultFlowRule.builder()
- .fromApp(appId)
- .withSelector(selector)
- .withTreatment(treatment)
- .withPriority(CordVtnPipeline.PRIORITY_MANAGEMENT)
- .forDevice(instance.deviceId())
- .forTable(CordVtnPipeline.TABLE_ZERO)
- .makePermanent()
- .build();
-
- pipeline.processFlowRule(install, flowRule);
-
- selector = DefaultTrafficSelector.builder()
- .matchEthType(Ethernet.TYPE_IPV4)
- .matchIPDst(service.serviceIp().toIpPrefix())
- .build();
-
- treatment = DefaultTrafficTreatment.builder()
- .setOutput(PortNumber.LOCAL)
- .build();
-
- flowRule = DefaultFlowRule.builder()
- .fromApp(appId)
- .withSelector(selector)
- .withTreatment(treatment)
- .withPriority(CordVtnPipeline.PRIORITY_MANAGEMENT)
- .forDevice(instance.deviceId())
- .forTable(CordVtnPipeline.TABLE_ACCESS_TYPE)
- .makePermanent()
- .build();
-
- pipeline.processFlowRule(install, flowRule);
- }
-
- private void managementPerInstanceRule(Instance instance, boolean install) {
- TrafficSelector selector = DefaultTrafficSelector.builder()
- .matchInPort(PortNumber.LOCAL)
- .matchEthType(Ethernet.TYPE_ARP)
- .matchArpTpa(instance.ipAddress().getIp4Address())
- .build();
-
- TrafficTreatment treatment = DefaultTrafficTreatment.builder()
- .setOutput(instance.portNumber())
- .build();
-
- FlowRule flowRule = DefaultFlowRule.builder()
- .fromApp(appId)
- .withSelector(selector)
- .withTreatment(treatment)
- .withPriority(CordVtnPipeline.PRIORITY_MANAGEMENT)
- .forDevice(instance.deviceId())
- .forTable(CordVtnPipeline.TABLE_ZERO)
- .makePermanent()
- .build();
-
- pipeline.processFlowRule(install, flowRule);
- }
-
- private void inPortRule(Instance instance, boolean install) {
- TrafficSelector selector = DefaultTrafficSelector.builder()
- .matchInPort(instance.portNumber())
- .matchEthType(Ethernet.TYPE_IPV4)
- .matchIPSrc(instance.ipAddress().toIpPrefix())
- .build();
-
- TrafficTreatment treatment = DefaultTrafficTreatment.builder()
- .transition(CordVtnPipeline.TABLE_ACCESS_TYPE)
- .build();
-
-
- FlowRule flowRule = DefaultFlowRule.builder()
- .fromApp(appId)
- .withSelector(selector)
- .withTreatment(treatment)
- .withPriority(CordVtnPipeline.PRIORITY_DEFAULT)
- .forDevice(instance.deviceId())
- .forTable(CordVtnPipeline.TABLE_IN_PORT)
- .makePermanent()
- .build();
-
- pipeline.processFlowRule(install, flowRule);
-
- selector = DefaultTrafficSelector.builder()
- .matchInPort(instance.portNumber())
- .build();
-
- treatment = DefaultTrafficTreatment.builder()
- .transition(CordVtnPipeline.TABLE_IN_SERVICE)
- .build();
-
- flowRule = DefaultFlowRule.builder()
- .fromApp(appId)
- .withSelector(selector)
- .withTreatment(treatment)
- .withPriority(CordVtnPipeline.PRIORITY_LOW)
- .forDevice(instance.deviceId())
- .forTable(CordVtnPipeline.TABLE_IN_PORT)
- .makePermanent()
- .build();
-
- pipeline.processFlowRule(install, flowRule);
- }
-
- private void dstIpRule(Instance instance, long vni, boolean install) {
- Ip4Address tunnelIp = nodeManager.dpIp(instance.deviceId()).getIp4Address();
-
- TrafficSelector selector = DefaultTrafficSelector.builder()
- .matchEthType(Ethernet.TYPE_IPV4)
- .matchIPDst(instance.ipAddress().toIpPrefix())
- .build();
-
- TrafficTreatment treatment = DefaultTrafficTreatment.builder()
- .setEthDst(instance.mac())
- .setOutput(instance.portNumber())
- .build();
-
- FlowRule flowRule = DefaultFlowRule.builder()
- .fromApp(appId)
- .withSelector(selector)
- .withTreatment(treatment)
- .withPriority(CordVtnPipeline.PRIORITY_DEFAULT)
- .forDevice(instance.deviceId())
- .forTable(CordVtnPipeline.TABLE_DST_IP)
- .makePermanent()
- .build();
-
- pipeline.processFlowRule(install, flowRule);
-
- for (CordVtnNode node : nodeManager.completeNodes()) {
- if (node.intBrId().equals(instance.deviceId())) {
- continue;
- }
-
- ExtensionTreatment tunnelDst = pipeline.tunnelDstTreatment(node.intBrId(), tunnelIp);
- if (tunnelDst == null) {
- continue;
- }
-
- treatment = DefaultTrafficTreatment.builder()
- .setEthDst(instance.mac())
- .setTunnelId(vni)
- .extension(tunnelDst, node.intBrId())
- .setOutput(nodeManager.tunnelPort(node.intBrId()))
- .build();
-
- flowRule = DefaultFlowRule.builder()
- .fromApp(appId)
- .withSelector(selector)
- .withTreatment(treatment)
- .withPriority(CordVtnPipeline.PRIORITY_DEFAULT)
- .forDevice(node.intBrId())
- .forTable(CordVtnPipeline.TABLE_DST_IP)
- .makePermanent()
- .build();
-
- pipeline.processFlowRule(install, flowRule);
- }
- }
-
- private void tunnelInRule(Instance instance, long vni, boolean install) {
- TrafficSelector selector = DefaultTrafficSelector.builder()
- .matchTunnelId(vni)
- .matchEthDst(instance.mac())
- .build();
-
- TrafficTreatment treatment = DefaultTrafficTreatment.builder()
- .setOutput(instance.portNumber())
- .build();
-
- FlowRule flowRule = DefaultFlowRule.builder()
- .fromApp(appId)
- .withSelector(selector)
- .withTreatment(treatment)
- .withPriority(CordVtnPipeline.PRIORITY_DEFAULT)
- .forDevice(instance.deviceId())
- .forTable(CordVtnPipeline.TABLE_TUNNEL_IN)
- .makePermanent()
- .build();
-
- pipeline.processFlowRule(install, flowRule);
- }
-
- private void directAccessRule(Ip4Prefix srcRange, Ip4Prefix dstRange, boolean install) {
- TrafficSelector selector = DefaultTrafficSelector.builder()
- .matchEthType(Ethernet.TYPE_IPV4)
- .matchIPSrc(srcRange)
- .matchIPDst(dstRange)
- .build();
-
- TrafficTreatment treatment = DefaultTrafficTreatment.builder()
- .transition(CordVtnPipeline.TABLE_DST_IP)
- .build();
-
-
- nodeManager.completeNodes().stream().forEach(node -> {
- FlowRule flowRuleDirect = DefaultFlowRule.builder()
- .fromApp(appId)
- .withSelector(selector)
- .withTreatment(treatment)
- .withPriority(CordVtnPipeline.PRIORITY_DEFAULT)
- .forDevice(node.intBrId())
- .forTable(CordVtnPipeline.TABLE_ACCESS_TYPE)
- .makePermanent()
- .build();
-
- pipeline.processFlowRule(install, flowRuleDirect);
- });
- }
-
- private void serviceIsolationRule(Ip4Prefix dstRange, boolean install) {
- TrafficSelector selector = DefaultTrafficSelector.builder()
- .matchEthType(Ethernet.TYPE_IPV4)
- .matchIPDst(dstRange)
- .build();
-
- TrafficTreatment treatment = DefaultTrafficTreatment.builder()
- .drop()
- .build();
-
- nodeManager.completeNodes().stream().forEach(node -> {
- FlowRule flowRuleDirect = DefaultFlowRule.builder()
- .fromApp(appId)
- .withSelector(selector)
- .withTreatment(treatment)
- .withPriority(CordVtnPipeline.PRIORITY_LOW)
- .forDevice(node.intBrId())
- .forTable(CordVtnPipeline.TABLE_ACCESS_TYPE)
- .makePermanent()
- .build();
-
- pipeline.processFlowRule(install, flowRuleDirect);
- });
- }
-
- protected void readConfiguration() {
- CordVtnConfig config = configRegistry.getConfig(appId, CordVtnConfig.class);
- if (config == null) {
- log.debug("No configuration found");
- return;
- }
- osAccess = config.openstackAccess();
- xosAccess = config.xosAccess();
- }
-
- public class InternalHostListener implements HostListener {
-
- @Override
- public void event(HostEvent event) {
- Host host = event.subject();
- if (!mastershipService.isLocalMaster(host.location().deviceId())) {
- // do not allow to proceed without mastership
- return;
- }
-
- Instance instance = Instance.of(host);
- if (!Objects.equals(instance.serviceType(), serviceType)) {
- // not my service instance, do nothing
- return;
- }
-
- switch (event.type()) {
- case HOST_UPDATED:
- case HOST_ADDED:
- eventExecutor.execute(() -> instanceDetected(instance));
- break;
- case HOST_REMOVED:
- eventExecutor.execute(() -> instanceRemoved(instance));
- break;
- default:
- break;
- }
- }
- }
-
- public class InternalConfigListener implements NetworkConfigListener {
-
- @Override
- public void event(NetworkConfigEvent event) {
- if (!event.configClass().equals(CordVtnConfig.class)) {
- return;
- }
-
- switch (event.type()) {
- case CONFIG_ADDED:
- case CONFIG_UPDATED:
- readConfiguration();
- break;
- default:
- break;
- }
- }
- }
-}
diff --git a/src/main/java/org/opencord/cordvtn/impl/CordVtnInstanceManager.java b/src/main/java/org/opencord/cordvtn/impl/CordVtnInstanceManager.java
index 6acca13..bb5e067 100644
--- a/src/main/java/org/opencord/cordvtn/impl/CordVtnInstanceManager.java
+++ b/src/main/java/org/opencord/cordvtn/impl/CordVtnInstanceManager.java
@@ -82,9 +82,8 @@
import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
import static org.onlab.util.Tools.groupedThreads;
import static org.onosproject.dhcp.IpAssignment.AssignmentStatus.Option_RangeNotEnforced;
-import static org.onosproject.xosclient.api.VtnService.NetworkType.MANAGEMENT;
-import static org.onosproject.xosclient.api.VtnService.NetworkType.PRIVATE;
-
+import static org.onosproject.xosclient.api.VtnServiceApi.NetworkType.MANAGEMENT;
+import static org.onosproject.xosclient.api.VtnServiceApi.NetworkType.PRIVATE;
import static org.slf4j.LoggerFactory.getLogger;
/**
diff --git a/src/main/java/org/opencord/cordvtn/impl/service/DefaultInstanceHandler.java b/src/main/java/org/opencord/cordvtn/impl/service/DefaultInstanceHandler.java
new file mode 100644
index 0000000..0c19509
--- /dev/null
+++ b/src/main/java/org/opencord/cordvtn/impl/service/DefaultInstanceHandler.java
@@ -0,0 +1,279 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * 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.cordvtn.impl.service;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+
+import org.apache.felix.scr.annotations.Deactivate;
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.Ip4Prefix;
+import org.onosproject.net.flow.DefaultFlowRule;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.instructions.ExtensionTreatment;
+import org.opencord.cordvtn.impl.AbstractInstanceHandler;
+import org.opencord.cordvtn.api.CordVtnNode;
+import org.opencord.cordvtn.api.Instance;
+import org.opencord.cordvtn.api.InstanceHandler;
+import org.onosproject.xosclient.api.VtnService;
+import org.opencord.cordvtn.impl.CordVtnPipeline;
+
+import java.util.Optional;
+
+import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
+import static org.onlab.util.Tools.groupedThreads;
+import static org.onosproject.xosclient.api.VtnServiceApi.ServiceType.DEFAULT;
+
+/**
+ * Provides network connectivity for default service instances.
+ */
+@Component(immediate = true)
+public class DefaultInstanceHandler extends AbstractInstanceHandler implements InstanceHandler {
+
+ @Activate
+ protected void activate() {
+ serviceType = Optional.of(DEFAULT);
+ eventExecutor = newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtn-default", "event-handler"));
+ super.activate();
+ }
+
+ @Deactivate
+ protected void deactivate() {
+ super.deactivate();
+ }
+
+ @Override
+ public void instanceDetected(Instance instance) {
+ log.info("Instance is detected {}", instance);
+
+ VtnService service = getVtnService(instance.serviceId());
+ if (service == null) {
+ log.warn("Failed to get VtnService for {}", instance);
+ return;
+ }
+ defaultConnectionRules(instance, service, true);
+ }
+
+ @Override
+ public void instanceRemoved(Instance instance) {
+ log.info("Instance is removed {}", instance);
+
+ VtnService service = getVtnService(instance.serviceId());
+ if (service == null) {
+ log.warn("Failed to get VtnService for {}", instance);
+ return;
+ }
+ defaultConnectionRules(instance, service, false);
+ }
+
+ private void defaultConnectionRules(Instance instance, VtnService service, boolean install) {
+ long vni = service.vni();
+ Ip4Prefix serviceIpRange = service.subnet().getIp4Prefix();
+
+ inPortRule(instance, install);
+ dstIpRule(instance, vni, install);
+ tunnelInRule(instance, vni, install);
+
+ if (install) {
+ directAccessRule(serviceIpRange, serviceIpRange, true);
+ serviceIsolationRule(serviceIpRange, true);
+ } else if (getInstances(service.id()).isEmpty()) {
+ directAccessRule(serviceIpRange, serviceIpRange, false);
+ serviceIsolationRule(serviceIpRange, false);
+ }
+ }
+
+ private void inPortRule(Instance instance, boolean install) {
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchInPort(instance.portNumber())
+ .matchEthType(Ethernet.TYPE_IPV4)
+ .matchIPSrc(instance.ipAddress().toIpPrefix())
+ .build();
+
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .transition(CordVtnPipeline.TABLE_ACCESS_TYPE)
+ .build();
+
+
+ FlowRule flowRule = DefaultFlowRule.builder()
+ .fromApp(appId)
+ .withSelector(selector)
+ .withTreatment(treatment)
+ .withPriority(CordVtnPipeline.PRIORITY_DEFAULT)
+ .forDevice(instance.deviceId())
+ .forTable(CordVtnPipeline.TABLE_IN_PORT)
+ .makePermanent()
+ .build();
+
+ pipeline.processFlowRule(install, flowRule);
+
+ selector = DefaultTrafficSelector.builder()
+ .matchInPort(instance.portNumber())
+ .build();
+
+ treatment = DefaultTrafficTreatment.builder()
+ .transition(CordVtnPipeline.TABLE_IN_SERVICE)
+ .build();
+
+ flowRule = DefaultFlowRule.builder()
+ .fromApp(appId)
+ .withSelector(selector)
+ .withTreatment(treatment)
+ .withPriority(CordVtnPipeline.PRIORITY_LOW)
+ .forDevice(instance.deviceId())
+ .forTable(CordVtnPipeline.TABLE_IN_PORT)
+ .makePermanent()
+ .build();
+
+ pipeline.processFlowRule(install, flowRule);
+ }
+
+ private void dstIpRule(Instance instance, long vni, boolean install) {
+ Ip4Address tunnelIp = nodeManager.dpIp(instance.deviceId()).getIp4Address();
+
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchEthType(Ethernet.TYPE_IPV4)
+ .matchIPDst(instance.ipAddress().toIpPrefix())
+ .build();
+
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .setEthDst(instance.mac())
+ .setOutput(instance.portNumber())
+ .build();
+
+ FlowRule flowRule = DefaultFlowRule.builder()
+ .fromApp(appId)
+ .withSelector(selector)
+ .withTreatment(treatment)
+ .withPriority(CordVtnPipeline.PRIORITY_DEFAULT)
+ .forDevice(instance.deviceId())
+ .forTable(CordVtnPipeline.TABLE_DST_IP)
+ .makePermanent()
+ .build();
+
+ pipeline.processFlowRule(install, flowRule);
+
+ for (CordVtnNode node : nodeManager.completeNodes()) {
+ if (node.intBrId().equals(instance.deviceId())) {
+ continue;
+ }
+
+ ExtensionTreatment tunnelDst = pipeline.tunnelDstTreatment(node.intBrId(), tunnelIp);
+ if (tunnelDst == null) {
+ continue;
+ }
+
+ treatment = DefaultTrafficTreatment.builder()
+ .setEthDst(instance.mac())
+ .setTunnelId(vni)
+ .extension(tunnelDst, node.intBrId())
+ .setOutput(nodeManager.tunnelPort(node.intBrId()))
+ .build();
+
+ flowRule = DefaultFlowRule.builder()
+ .fromApp(appId)
+ .withSelector(selector)
+ .withTreatment(treatment)
+ .withPriority(CordVtnPipeline.PRIORITY_DEFAULT)
+ .forDevice(node.intBrId())
+ .forTable(CordVtnPipeline.TABLE_DST_IP)
+ .makePermanent()
+ .build();
+
+ pipeline.processFlowRule(install, flowRule);
+ }
+ }
+
+ private void tunnelInRule(Instance instance, long vni, boolean install) {
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchTunnelId(vni)
+ .matchEthDst(instance.mac())
+ .build();
+
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .setOutput(instance.portNumber())
+ .build();
+
+ FlowRule flowRule = DefaultFlowRule.builder()
+ .fromApp(appId)
+ .withSelector(selector)
+ .withTreatment(treatment)
+ .withPriority(CordVtnPipeline.PRIORITY_DEFAULT)
+ .forDevice(instance.deviceId())
+ .forTable(CordVtnPipeline.TABLE_TUNNEL_IN)
+ .makePermanent()
+ .build();
+
+ pipeline.processFlowRule(install, flowRule);
+ }
+
+ private void directAccessRule(Ip4Prefix srcRange, Ip4Prefix dstRange, boolean install) {
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchEthType(Ethernet.TYPE_IPV4)
+ .matchIPSrc(srcRange)
+ .matchIPDst(dstRange)
+ .build();
+
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .transition(CordVtnPipeline.TABLE_DST_IP)
+ .build();
+
+
+ nodeManager.completeNodes().stream().forEach(node -> {
+ FlowRule flowRuleDirect = DefaultFlowRule.builder()
+ .fromApp(appId)
+ .withSelector(selector)
+ .withTreatment(treatment)
+ .withPriority(CordVtnPipeline.PRIORITY_DEFAULT)
+ .forDevice(node.intBrId())
+ .forTable(CordVtnPipeline.TABLE_ACCESS_TYPE)
+ .makePermanent()
+ .build();
+
+ pipeline.processFlowRule(install, flowRuleDirect);
+ });
+ }
+
+ private void serviceIsolationRule(Ip4Prefix dstRange, boolean install) {
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchEthType(Ethernet.TYPE_IPV4)
+ .matchIPDst(dstRange)
+ .build();
+
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .drop()
+ .build();
+
+ nodeManager.completeNodes().stream().forEach(node -> {
+ FlowRule flowRuleDirect = DefaultFlowRule.builder()
+ .fromApp(appId)
+ .withSelector(selector)
+ .withTreatment(treatment)
+ .withPriority(CordVtnPipeline.PRIORITY_LOW)
+ .forDevice(node.intBrId())
+ .forTable(CordVtnPipeline.TABLE_ACCESS_TYPE)
+ .makePermanent()
+ .build();
+
+ pipeline.processFlowRule(install, flowRuleDirect);
+ });
+ }
+}
diff --git a/src/main/java/org/opencord/cordvtn/impl/service/DummyInstanceHandler.java b/src/main/java/org/opencord/cordvtn/impl/service/DummyInstanceHandler.java
deleted file mode 100644
index 86a5f1b..0000000
--- a/src/main/java/org/opencord/cordvtn/impl/service/DummyInstanceHandler.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Laboratory
- *
- * 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.cordvtn.impl.service;
-
-import org.apache.felix.scr.annotations.Activate;
-import org.apache.felix.scr.annotations.Component;
-
-import org.apache.felix.scr.annotations.Deactivate;
-import org.opencord.cordvtn.api.Instance;
-import org.opencord.cordvtn.api.InstanceHandler;
-import org.opencord.cordvtn.impl.CordVtnInstanceHandler;
-import org.onosproject.xosclient.api.VtnService;
-
-import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
-import static org.onlab.util.Tools.groupedThreads;
-
-/**
- * Provides network connectivity for dummy service instances.
- */
-@Component(immediate = true)
-public class DummyInstanceHandler extends CordVtnInstanceHandler implements InstanceHandler {
-
- @Activate
- protected void activate() {
- serviceType = VtnService.ServiceType.DUMMY;
- eventExecutor = newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtn-dummy", "event-handler"));
- super.activate();
- }
-
- @Deactivate
- protected void deactivate() {
- super.deactivate();
- }
-
- @Override
- public void instanceDetected(Instance instance) {
- super.instanceDetected(instance);
- }
-
- @Override
- public void instanceRemoved(Instance instance) {
- super.instanceRemoved(instance);
- }
-}
diff --git a/src/main/java/org/opencord/cordvtn/impl/service/ManagementInstanceHandler.java b/src/main/java/org/opencord/cordvtn/impl/service/ManagementInstanceHandler.java
new file mode 100644
index 0000000..2e49a0b
--- /dev/null
+++ b/src/main/java/org/opencord/cordvtn/impl/service/ManagementInstanceHandler.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * 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.cordvtn.impl.service;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.onlab.packet.Ethernet;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.DefaultFlowRule;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.xosclient.api.VtnService;
+import org.opencord.cordvtn.impl.AbstractInstanceHandler;
+import org.opencord.cordvtn.api.Instance;
+import org.opencord.cordvtn.api.InstanceHandler;
+import org.opencord.cordvtn.impl.CordVtnPipeline;
+
+import java.util.Optional;
+
+import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
+import static org.onlab.util.Tools.groupedThreads;
+import static org.onosproject.xosclient.api.VtnServiceApi.ServiceType.MANAGEMENT;
+
+/**
+ * Provides network connectivity for management network connected instances.
+ */
+@Component(immediate = true)
+public class ManagementInstanceHandler extends AbstractInstanceHandler implements InstanceHandler {
+
+ @Activate
+ protected void activate() {
+ serviceType = Optional.of(MANAGEMENT);
+ eventExecutor = newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtn-mgmt", "event-handler"));
+ super.activate();
+ }
+
+ @Deactivate
+ protected void deactivate() {
+ super.deactivate();
+ }
+
+ @Override
+ public void instanceDetected(Instance instance) {
+ log.info("Instance is detected {}", instance);
+
+ VtnService service = getVtnService(instance.serviceId());
+ if (service == null) {
+ log.warn("Failed to get VtnService for {}", instance);
+ return;
+ }
+ localMgmtNetworkRules(instance, service, true);
+ }
+
+ @Override
+ public void instanceRemoved(Instance instance) {
+ log.info("Instance is removed {}", instance);
+
+ VtnService service = getVtnService(instance.serviceId());
+ if (service == null) {
+ log.warn("Failed to get VtnService for {}", instance);
+ return;
+ }
+
+ // TODO check if any stale management network rules are
+ localMgmtNetworkRules(instance, service, false);
+ }
+
+ private void localMgmtNetworkRules(Instance instance, VtnService service, boolean install) {
+ managementPerInstanceRule(instance, install);
+ if (install) {
+ managementBaseRule(instance, service, true);
+ } else if (!hostService.getConnectedHosts(instance.deviceId()).stream()
+ .filter(host -> Instance.of(host).serviceId().equals(service.id()))
+ .findAny()
+ .isPresent()) {
+ managementBaseRule(instance, service, false);
+ }
+ }
+
+ private void managementBaseRule(Instance instance, VtnService service, boolean install) {
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchEthType(Ethernet.TYPE_ARP)
+ .matchArpTpa(service.serviceIp().getIp4Address())
+ .build();
+
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .setOutput(PortNumber.LOCAL)
+ .build();
+
+ FlowRule flowRule = DefaultFlowRule.builder()
+ .fromApp(appId)
+ .withSelector(selector)
+ .withTreatment(treatment)
+ .withPriority(CordVtnPipeline.PRIORITY_MANAGEMENT)
+ .forDevice(instance.deviceId())
+ .forTable(CordVtnPipeline.TABLE_ZERO)
+ .makePermanent()
+ .build();
+
+ pipeline.processFlowRule(install, flowRule);
+
+ selector = DefaultTrafficSelector.builder()
+ .matchInPort(PortNumber.LOCAL)
+ .matchEthType(Ethernet.TYPE_IPV4)
+ .matchIPDst(service.subnet())
+ .build();
+
+ treatment = DefaultTrafficTreatment.builder()
+ .transition(CordVtnPipeline.TABLE_DST_IP)
+ .build();
+
+ flowRule = DefaultFlowRule.builder()
+ .fromApp(appId)
+ .withSelector(selector)
+ .withTreatment(treatment)
+ .withPriority(CordVtnPipeline.PRIORITY_MANAGEMENT)
+ .forDevice(instance.deviceId())
+ .forTable(CordVtnPipeline.TABLE_ZERO)
+ .makePermanent()
+ .build();
+
+ pipeline.processFlowRule(install, flowRule);
+
+ selector = DefaultTrafficSelector.builder()
+ .matchEthType(Ethernet.TYPE_IPV4)
+ .matchIPDst(service.serviceIp().toIpPrefix())
+ .build();
+
+ treatment = DefaultTrafficTreatment.builder()
+ .setOutput(PortNumber.LOCAL)
+ .build();
+
+ flowRule = DefaultFlowRule.builder()
+ .fromApp(appId)
+ .withSelector(selector)
+ .withTreatment(treatment)
+ .withPriority(CordVtnPipeline.PRIORITY_MANAGEMENT)
+ .forDevice(instance.deviceId())
+ .forTable(CordVtnPipeline.TABLE_ACCESS_TYPE)
+ .makePermanent()
+ .build();
+
+ pipeline.processFlowRule(install, flowRule);
+ }
+
+ private void managementPerInstanceRule(Instance instance, boolean install) {
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchInPort(PortNumber.LOCAL)
+ .matchEthType(Ethernet.TYPE_ARP)
+ .matchArpTpa(instance.ipAddress().getIp4Address())
+ .build();
+
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .setOutput(instance.portNumber())
+ .build();
+
+ FlowRule flowRule = DefaultFlowRule.builder()
+ .fromApp(appId)
+ .withSelector(selector)
+ .withTreatment(treatment)
+ .withPriority(CordVtnPipeline.PRIORITY_MANAGEMENT)
+ .forDevice(instance.deviceId())
+ .forTable(CordVtnPipeline.TABLE_ZERO)
+ .makePermanent()
+ .build();
+
+ pipeline.processFlowRule(install, flowRule);
+ }
+}
diff --git a/src/main/java/org/opencord/cordvtn/impl/service/OltAgentInstanceHandler.java b/src/main/java/org/opencord/cordvtn/impl/service/OltAgentInstanceHandler.java
index 7919c5a..b409e79 100644
--- a/src/main/java/org/opencord/cordvtn/impl/service/OltAgentInstanceHandler.java
+++ b/src/main/java/org/opencord/cordvtn/impl/service/OltAgentInstanceHandler.java
@@ -19,42 +19,33 @@
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.IpPrefix;
+import org.opencord.cordvtn.impl.AbstractInstanceHandler;
import org.opencord.cordvtn.api.CordVtnConfig;
import org.opencord.cordvtn.api.Instance;
import org.opencord.cordvtn.api.InstanceHandler;
-import org.opencord.cordvtn.impl.CordVtnInstanceHandler;
import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
import org.onosproject.net.config.ConfigFactory;
import org.onosproject.net.config.NetworkConfigEvent;
import org.onosproject.net.config.NetworkConfigListener;
import org.onosproject.net.config.basics.SubjectFactories;
-import org.onosproject.net.flow.DefaultFlowRule;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.xosclient.api.VtnService;
import org.opencord.cordconfig.access.AccessAgentConfig;
import org.opencord.cordconfig.access.AccessAgentData;
-import org.opencord.cordvtn.impl.CordVtnPipeline;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
import static org.onlab.util.Tools.groupedThreads;
+import static org.onosproject.xosclient.api.VtnServiceApi.ServiceType.OLT_AGENT;
/**
* Provides network connectivity for OLT agent instances.
*/
@Component(immediate = true)
-public class OltAgentInstanceHandler extends CordVtnInstanceHandler implements InstanceHandler {
+public class OltAgentInstanceHandler extends AbstractInstanceHandler implements InstanceHandler {
private static final Class<AccessAgentConfig> CONFIG_CLASS = AccessAgentConfig.class;
private ConfigFactory<DeviceId, AccessAgentConfig> configFactory =
@@ -67,12 +58,11 @@
};
private Map<DeviceId, AccessAgentData> oltAgentData = Maps.newConcurrentMap();
- private IpPrefix mgmtIpRange = null;
@Activate
protected void activate() {
+ serviceType = Optional.of(OLT_AGENT);
eventExecutor = newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtn-olt", "event-handler"));
- serviceType = VtnService.ServiceType.OLT_AGENT;
configRegistry.registerConfigFactory(configFactory);
configListener = new InternalConfigListener();
@@ -88,49 +78,15 @@
@Override
public void instanceDetected(Instance instance) {
log.info("OLT agent instance detected {}", instance);
-
- managementAccessRule(instance.deviceId(), true);
// TODO implement
}
@Override
public void instanceRemoved(Instance instance) {
log.info("OLT agent instance removed {}", instance);
-
- if (getInstances(instance.serviceId()).isEmpty()) {
- nodeManager.completeNodes().stream().forEach(node ->
- managementAccessRule(node.intBrId(), false));
- }
-
// TODO implement
}
- private void managementAccessRule(DeviceId deviceId, boolean install) {
- // TODO remove this rule after long term management network is done
- if (mgmtIpRange != null) {
- TrafficSelector selector = DefaultTrafficSelector.builder()
- .matchEthType(Ethernet.TYPE_IPV4)
- .matchIPDst(mgmtIpRange)
- .build();
-
- TrafficTreatment treatment = DefaultTrafficTreatment.builder()
- .setOutput(PortNumber.LOCAL)
- .build();
-
- FlowRule flowRule = DefaultFlowRule.builder()
- .fromApp(appId)
- .withSelector(selector)
- .withTreatment(treatment)
- .withPriority(CordVtnPipeline.PRIORITY_MANAGEMENT)
- .forDevice(deviceId)
- .forTable(CordVtnPipeline.TABLE_ACCESS_TYPE)
- .makePermanent()
- .build();
-
- pipeline.processFlowRule(install, flowRule);
- }
- }
-
private void readAccessAgentConfig() {
Set<DeviceId> deviceSubjects = configRegistry.getSubjects(DeviceId.class, CONFIG_CLASS);
@@ -142,20 +98,7 @@
});
}
- @Override
- protected void readConfiguration() {
- CordVtnConfig config = configRegistry.getConfig(appId, CordVtnConfig.class);
- if (config == null) {
- log.debug("No configuration found");
- return;
- }
-
- osAccess = config.openstackAccess();
- xosAccess = config.xosAccess();
- mgmtIpRange = config.managementIpRange();
- }
-
- public class InternalConfigListener implements NetworkConfigListener {
+ private class InternalConfigListener implements NetworkConfigListener {
@Override
public void event(NetworkConfigEvent event) {
diff --git a/src/main/java/org/opencord/cordvtn/impl/service/VsgInstanceHandler.java b/src/main/java/org/opencord/cordvtn/impl/service/VsgInstanceHandler.java
index 46c4a01..e6fd643 100644
--- a/src/main/java/org/opencord/cordvtn/impl/service/VsgInstanceHandler.java
+++ b/src/main/java/org/opencord/cordvtn/impl/service/VsgInstanceHandler.java
@@ -28,9 +28,9 @@
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
+import org.opencord.cordvtn.impl.AbstractInstanceHandler;
import org.opencord.cordvtn.api.Instance;
import org.opencord.cordvtn.api.InstanceHandler;
-import org.opencord.cordvtn.impl.CordVtnInstanceHandler;
import org.opencord.cordvtn.impl.CordVtnInstanceManager;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.HostId;
@@ -50,12 +50,10 @@
import org.onosproject.net.host.DefaultHostDescription;
import org.onosproject.net.host.HostDescription;
import org.onosproject.xosclient.api.VtnPort;
-import org.onosproject.xosclient.api.VtnPortApi;
-import org.onosproject.xosclient.api.VtnPortId;
-import org.onosproject.xosclient.api.VtnService;
import org.opencord.cordvtn.impl.CordVtnPipeline;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -63,13 +61,14 @@
import static org.onlab.util.Tools.groupedThreads;
import static org.onosproject.net.flow.criteria.Criterion.Type.IPV4_DST;
import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.VLAN_PUSH;
+import static org.onosproject.xosclient.api.VtnServiceApi.ServiceType.VSG;
/**
* Provides network connectivity for vSG instances.
*/
@Component(immediate = true)
@Service(value = VsgInstanceHandler.class)
-public final class VsgInstanceHandler extends CordVtnInstanceHandler implements InstanceHandler {
+public final class VsgInstanceHandler extends AbstractInstanceHandler implements InstanceHandler {
private static final String STAG = "stag";
private static final String VSG_VM = "vsgVm";
@@ -82,7 +81,7 @@
@Activate
protected void activate() {
- serviceType = VtnService.ServiceType.VSG;
+ serviceType = Optional.of(VSG);
eventExecutor = newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtn-vsg", "event-handler"));
super.activate();
}
@@ -100,7 +99,7 @@
// find vsg vm for this vsg container
String vsgVmId = instance.getAnnotation(VSG_VM);
if (Strings.isNullOrEmpty(vsgVmId)) {
- log.warn("Failed to find VSG VM for {}", instance);
+ log.warn("Failed to find vSG VM for {}", instance);
return;
}
@@ -121,6 +120,9 @@
return;
}
+ log.info("vSG VM detected {}", instance);
+
+ // insert vSG containers inside the vSG VM as a host
vtnPort.addressPairs().entrySet().stream()
.forEach(pair -> addVsgContainer(
instance,
@@ -128,37 +130,35 @@
pair.getValue(),
getStag(vtnPort).toString()
));
- super.instanceDetected(instance);
}
}
@Override
public void instanceRemoved(Instance instance) {
- if (isVsgContainer(instance)) {
- log.info("vSG container vanished {}", instance);
-
- // find vsg vm for this vsg container
- String vsgVmId = instance.getAnnotation(VSG_VM);
- if (Strings.isNullOrEmpty(vsgVmId)) {
- log.warn("Failed to find VSG VM for {}", instance);
- return;
- }
-
- Instance vsgVm = Instance.of(hostService.getHost(HostId.hostId(vsgVmId)));
- VtnPort vtnPort = getVtnPort(vsgVm);
- if (vtnPort == null || getStag(vtnPort) == null) {
- return;
- }
-
- populateVsgRules(vsgVm, getStag(vtnPort),
- nodeManager.dpPort(vsgVm.deviceId()),
- vtnPort.addressPairs().keySet(),
- false);
-
- } else {
- // TODO remove vsg vm related rules
- super.instanceRemoved(instance);
+ if (!isVsgContainer(instance)) {
+ // nothing to do for the vSG VM itself
+ return;
}
+
+ log.info("vSG container vanished {}", instance);
+
+ // find vsg vm for this vsg container
+ String vsgVmId = instance.getAnnotation(VSG_VM);
+ if (Strings.isNullOrEmpty(vsgVmId)) {
+ log.warn("Failed to find vSG VM for {}", instance);
+ return;
+ }
+
+ Instance vsgVm = Instance.of(hostService.getHost(HostId.hostId(vsgVmId)));
+ VtnPort vtnPort = getVtnPort(vsgVm);
+ if (vtnPort == null || getStag(vtnPort) == null) {
+ return;
+ }
+
+ populateVsgRules(vsgVm, getStag(vtnPort),
+ nodeManager.dpPort(vsgVm.deviceId()),
+ vtnPort.addressPairs().keySet(),
+ false);
}
/**
@@ -320,20 +320,6 @@
}
}
- private VtnPort getVtnPort(Instance instance) {
- checkNotNull(osAccess, OPENSTACK_ACCESS_ERROR);
- checkNotNull(xosAccess, XOS_ACCESS_ERROR);
-
- VtnPortId vtnPortId = instance.portId();
- VtnPortApi portApi = xosClient.getClient(xosAccess).vtnPort();
- VtnPort vtnPort = portApi.vtnPort(vtnPortId, osAccess);
- if (vtnPort == null) {
- log.warn("Failed to get port information of {}", instance);
- return null;
- }
- return vtnPort;
- }
-
// TODO get stag from XOS when XOS provides it, extract if from port name for now
private VlanId getStag(VtnPort vtnPort) {
checkNotNull(vtnPort);