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);