diff --git a/src/main/java/org/onosproject/cordvtn/impl/CordVtn.java b/src/main/java/org/onosproject/cordvtn/impl/CordVtn.java
index cfcdc4b..efa0e4a 100644
--- a/src/main/java/org/onosproject/cordvtn/impl/CordVtn.java
+++ b/src/main/java/org/onosproject/cordvtn/impl/CordVtn.java
@@ -15,7 +15,6 @@
  */
 package org.onosproject.cordvtn.impl;
 
-import com.google.common.base.Strings;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
@@ -27,210 +26,77 @@
 import org.apache.felix.scr.annotations.Service;
 import org.onlab.packet.Ethernet;
 import org.onlab.packet.Ip4Address;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.cordvtn.api.CordVtnConfig;
+import org.onlab.packet.Ip4Prefix;
 import org.onosproject.cordvtn.api.CordVtnNode;
 import org.onosproject.cordvtn.api.CordVtnService;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.CoreService;
-import org.onosproject.dhcp.DhcpService;
-import org.onosproject.mastership.MastershipService;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.cordvtn.api.Instance;
+import org.onosproject.core.DefaultGroupId;
+import org.onosproject.core.GroupId;
+import org.onosproject.net.DeviceId;
 import org.onosproject.net.Host;
-import org.onosproject.net.HostId;
-import org.onosproject.net.HostLocation;
-import org.onosproject.net.Port;
-import org.onosproject.net.config.ConfigFactory;
-import org.onosproject.net.config.NetworkConfigEvent;
-import org.onosproject.net.config.NetworkConfigListener;
-import org.onosproject.net.config.NetworkConfigRegistry;
-import org.onosproject.net.config.basics.SubjectFactories;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.flow.FlowRuleService;
+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.net.flow.instructions.ExtensionTreatment;
+import org.onosproject.net.group.DefaultGroupDescription;
+import org.onosproject.net.group.DefaultGroupKey;
+import org.onosproject.net.group.Group;
+import org.onosproject.net.group.GroupBucket;
+import org.onosproject.net.group.GroupBuckets;
+import org.onosproject.net.group.GroupDescription;
+import org.onosproject.net.group.GroupKey;
 import org.onosproject.net.group.GroupService;
-import org.onosproject.net.host.DefaultHostDescription;
-import org.onosproject.net.host.HostDescription;
 import org.onosproject.net.host.HostEvent;
 import org.onosproject.net.host.HostListener;
-import org.onosproject.net.host.HostProvider;
-import org.onosproject.net.host.HostProviderRegistry;
-import org.onosproject.net.host.HostProviderService;
-import org.onosproject.net.host.HostService;
-import org.onosproject.net.packet.PacketContext;
-import org.onosproject.net.packet.PacketProcessor;
-import org.onosproject.net.packet.PacketService;
-import org.onosproject.net.provider.AbstractProvider;
-import org.onosproject.net.provider.ProviderId;
-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.VtnServiceId;
-import org.onosproject.xosclient.api.XosAccess;
-import org.onosproject.xosclient.api.XosClientService;
 import org.slf4j.Logger;
 
 import java.util.List;
 import java.util.Map;
 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 java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
 import static org.onlab.util.Tools.groupedThreads;
+import static org.onosproject.cordvtn.impl.CordVtnPipeline.*;
+import static org.onosproject.net.group.DefaultGroupBucket.createSelectGroupBucket;
 import static org.slf4j.LoggerFactory.getLogger;
 
 /**
- * Provisions virtual tenant networks with service chaining capability
- * in OpenStack environment.
+ * Provisions service dependency capabilities between network services.
  */
 @Component(immediate = true)
 @Service
-public class CordVtn extends AbstractProvider implements CordVtnService, HostProvider {
+public class CordVtn extends CordVtnInstanceHandler implements CordVtnService {
 
     protected final Logger log = getLogger(getClass());
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected CoreService coreService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected NetworkConfigRegistry configRegistry;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected HostProviderRegistry hostProviderRegistry;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected DeviceService deviceService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected HostService hostService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected FlowRuleService flowRuleService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected PacketService packetService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected MastershipService mastershipService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected GroupService groupService;
 
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected DhcpService dhcpService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected XosClientService xosClient;
-
-    private final ConfigFactory configFactory =
-            new ConfigFactory(SubjectFactories.APP_SUBJECT_FACTORY, CordVtnConfig.class, "cordvtn") {
-                @Override
-                public CordVtnConfig createConfig() {
-                    return new CordVtnConfig();
-                }
-            };
-
-    private static final String XOS_ACCESS_ERROR = "XOS access is not configured";
-    private static final String OPENSTACK_ACCESS_ERROR = "OpenStack access is not configured";
-
-    private static final String DEFAULT_TUNNEL = "vxlan";
-    private static final String SERVICE_ID = "serviceId";
-    private static final String PORT_ID = "vtnPortId";
-    private static final String DATA_PLANE_IP = "dataPlaneIp";
-    private static final String DATA_PLANE_INTF = "dataPlaneIntf";
-    private static final String S_TAG = "stag";
-    private static final String VSG_HOST_ID = "vsgHostId";
-    private static final String CREATE_TIME = "createTime";
-
-    private static final Ip4Address DEFAULT_DNS = Ip4Address.valueOf("8.8.8.8");
-
-    private final ExecutorService eventExecutor =
-            newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtn", "event-handler"));
-
-    private final PacketProcessor packetProcessor = new InternalPacketProcessor();
-    private final HostListener hostListener = new InternalHostListener();
-    private final NetworkConfigListener configListener = new InternalConfigListener();
-
-    private ApplicationId appId;
-    private HostProviderService hostProvider;
-    private CordVtnRuleInstaller ruleInstaller;
-    private CordVtnArpProxy arpProxy;
-
-    private volatile XosAccess xosAccess = null;
-    private volatile OpenStackAccess osAccess = null;
-    private volatile MacAddress privateGatewayMac = MacAddress.NONE;
-
-    /**
-     * Creates an cordvtn host location provider.
-     */
-    public CordVtn() {
-        super(new ProviderId("host", CORDVTN_APP_ID));
-    }
-
     @Activate
     protected void activate() {
-        appId = coreService.registerApplication(CordVtnService.CORDVTN_APP_ID);
-        ruleInstaller = new CordVtnRuleInstaller(appId, flowRuleService,
-                                                 deviceService,
-                                                 groupService,
-                                                 hostService,
-                                                 configRegistry,
-                                                 DEFAULT_TUNNEL);
-
-        arpProxy = new CordVtnArpProxy(appId, packetService, hostService);
-        packetService.addProcessor(packetProcessor, PacketProcessor.director(0));
-        arpProxy.requestPacket();
-
-        hostService.addListener(hostListener);
-        hostProvider = hostProviderRegistry.register(this);
-
-        configRegistry.registerConfigFactory(configFactory);
-        configRegistry.addListener(configListener);
-
-        log.info("Started");
+        eventExecutor = newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtn", "event-handler"));
+        hostListener = new InternalHostListener();
+        super.activate();
     }
 
     @Deactivate
     protected void deactivate() {
-        hostProviderRegistry.unregister(this);
-        hostService.removeListener(hostListener);
-
-        packetService.removeProcessor(packetProcessor);
-
-        configRegistry.unregisterConfigFactory(configFactory);
-        configRegistry.removeListener(configListener);
-
-        eventExecutor.shutdown();
-        log.info("Stopped");
-    }
-
-    @Override
-    public void triggerProbe(Host host) {
-        /*
-         * Note: In CORD deployment, we assume that all hosts are configured.
-         * Therefore no probe is required.
-         */
+        super.deactivate();
     }
 
     @Override
     public void createServiceDependency(VtnServiceId tServiceId, VtnServiceId pServiceId,
                                         boolean isBidirectional) {
-        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 tService = serviceApi.service(tServiceId, osAccess);
-        VtnService pService = serviceApi.service(pServiceId, osAccess);
+        VtnService tService = getVtnService(tServiceId);
+        VtnService pService = getVtnService(pServiceId);
 
         if (tService == null || pService == null) {
             log.error("Failed to create dependency between {} and {}",
@@ -239,18 +105,13 @@
         }
 
         log.info("Created dependency between {} and {}", tService.name(), pService.name());
-        ruleInstaller.populateServiceDependencyRules(tService, pService, isBidirectional, true);
+        serviceDependencyRules(tService, pService, isBidirectional, true);
     }
 
     @Override
     public void removeServiceDependency(VtnServiceId tServiceId, VtnServiceId pServiceId) {
-        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 tService = serviceApi.service(tServiceId, osAccess);
-        VtnService pService = serviceApi.service(pServiceId, osAccess);
+        VtnService tService = getVtnService(tServiceId);
+        VtnService pService = getVtnService(pServiceId);
 
         if (tService == null || pService == null) {
             log.error("Failed to remove dependency between {} and {}",
@@ -259,427 +120,267 @@
         }
 
         log.info("Removed dependency between {} and {}", tService.name(), pService.name());
-        ruleInstaller.populateServiceDependencyRules(tService, pService, true, false);
+        serviceDependencyRules(tService, pService, true, false);
     }
 
     @Override
-    public void addServiceVm(CordVtnNode node, ConnectPoint connectPoint) {
-        checkNotNull(osAccess, OPENSTACK_ACCESS_ERROR);
-        checkNotNull(xosAccess, XOS_ACCESS_ERROR);
-
-        Port port = deviceService.getPort(connectPoint.deviceId(), connectPoint.port());
-        String portName = port.annotations().value("portName");
-
-        // TODO remove openstack access when XOS provides all information
-        VtnPortApi portApi = xosClient.getClient(xosAccess).vtnPort();
-        VtnPort vtnPort = portApi.vtnPort(portName, osAccess);
-        if (vtnPort == null) {
-            log.warn("Failed to get port information of {}", portName);
+    public void instanceDetected(Instance instance) {
+        VtnService service = getVtnService(instance.serviceId());
+        if (service == null) {
             return;
         }
 
-        // Added CREATE_TIME intentionally to trigger HOST_UPDATED event for the
-        // existing instances.
-        DefaultAnnotations.Builder annotations = DefaultAnnotations.builder()
-                .set(SERVICE_ID, vtnPort.serviceId().id())
-                .set(PORT_ID, vtnPort.id().id())
-                .set(DATA_PLANE_IP, node.dpIp().ip().toString())
-                .set(DATA_PLANE_INTF, node.dpIntf())
-                .set(CREATE_TIME, String.valueOf(System.currentTimeMillis()));
+        // TODO get bidirectional information from XOS once XOS supports
+        service.tenantServices().stream().forEach(
+                tServiceId -> createServiceDependency(tServiceId, service.id(), true));
+        service.providerServices().stream().forEach(
+                pServiceId -> createServiceDependency(service.id(), pServiceId, true));
 
-        // TODO address service specific task in a separate package
-        String serviceVlan = getServiceVlan(vtnPort);
-        if (!Strings.isNullOrEmpty(serviceVlan)) {
-            annotations.set(S_TAG, serviceVlan);
-        }
-
-        HostDescription hostDesc = new DefaultHostDescription(
-                vtnPort.mac(),
-                VlanId.NONE,
-                new HostLocation(connectPoint, System.currentTimeMillis()),
-                Sets.newHashSet(vtnPort.ip()),
-                annotations.build());
-
-        HostId hostId = HostId.hostId(vtnPort.mac());
-        hostProvider.hostDetected(hostId, hostDesc, false);
+        updateProviderServiceInstances(service);
     }
 
     @Override
-    public void removeServiceVm(ConnectPoint connectPoint) {
-        hostService.getConnectedHosts(connectPoint)
-                .stream()
-                .forEach(host -> hostProvider.hostVanished(host.id()));
-    }
-
-    @Override
-    // TODO address service specific task in a separate package
-    public void updateVirtualSubscriberGateways(HostId vSgHostId, String serviceVlan,
-                                                Map<IpAddress, MacAddress> vSgs) {
-        Host vSgHost = hostService.getHost(vSgHostId);
-        if (vSgHost == null || !vSgHost.annotations().value(S_TAG).equals(serviceVlan)) {
-            log.debug("Invalid vSG updates for {}", serviceVlan);
+    public void instanceRemoved(Instance instance) {
+        VtnService service = getVtnService(instance.serviceId());
+        if (service == null) {
             return;
         }
 
-        log.info("Updates vSGs in {} with {}", vSgHost.id(), vSgs.toString());
-        vSgs.entrySet().stream()
-                .filter(entry -> hostService.getHostsByMac(entry.getValue()).isEmpty())
-                .forEach(entry -> addVirtualSubscriberGateway(
-                        vSgHost,
-                        entry.getKey(),
-                        entry.getValue(),
-                        serviceVlan));
-
-        hostService.getConnectedHosts(vSgHost.location()).stream()
-                .filter(host -> !host.mac().equals(vSgHost.mac()))
-                .filter(host -> !vSgs.values().contains(host.mac()))
-                .forEach(host -> {
-                    log.info("Removed vSG {}", host.toString());
-                    hostProvider.hostVanished(host.id());
-                });
-    }
-
-    /**
-     * Adds virtual subscriber gateway to the system.
-     *
-     * @param vSgHost host virtual machine of this vSG
-     * @param vSgIp vSG ip address
-     * @param vSgMac vSG mac address
-     * @param serviceVlan service vlan
-     */
-    // TODO address service specific task in a separate package
-    private void addVirtualSubscriberGateway(Host vSgHost, IpAddress vSgIp, MacAddress vSgMac,
-                                             String serviceVlan) {
-        log.info("vSG with IP({}) MAC({}) added", vSgIp.toString(), vSgMac.toString());
-
-        HostId hostId = HostId.hostId(vSgMac);
-        DefaultAnnotations.Builder annotations = DefaultAnnotations.builder()
-                .set(S_TAG, serviceVlan)
-                .set(VSG_HOST_ID, vSgHost.id().toString())
-                .set(CREATE_TIME, String.valueOf(System.currentTimeMillis()));
-
-        HostDescription hostDesc = new DefaultHostDescription(
-                vSgMac,
-                VlanId.NONE,
-                vSgHost.location(),
-                Sets.newHashSet(vSgIp),
-                annotations.build());
-
-        hostProvider.hostDetected(hostId, hostDesc, false);
-    }
-
-    /**
-     * Returns public ip addresses of vSGs running inside a give vSG host.
-     *
-     * @param vSgHost vSG host
-     * @return map of ip and mac address, or empty map
-     */
-    // TODO address service specific task in a separate package
-    private Map<IpAddress, MacAddress> getSubscriberGateways(Host vSgHost) {
-        checkNotNull(osAccess, OPENSTACK_ACCESS_ERROR);
-        checkNotNull(xosAccess, XOS_ACCESS_ERROR);
-
-        String vtnPortId = vSgHost.annotations().value(PORT_ID);
-        String sTag = vSgHost.annotations().value(S_TAG);
-
-        if (Strings.isNullOrEmpty(vtnPortId) || Strings.isNullOrEmpty(sTag)) {
-            log.warn("PORT_ID and S_TAG is not set, ignore {}", vSgHost);
-            return Maps.newHashMap();
+        if (!service.providerServices().isEmpty()) {
+            removeInstanceFromTenantService(instance, service);
         }
-
-        // TODO remove openstack access when XOS provides all information
-        VtnPortApi portApi = xosClient.getClient(xosAccess).vtnPort();
-        VtnPort vtnPort = portApi.vtnPort(VtnPortId.of(vtnPortId), osAccess);
-        if (vtnPort == null) {
-            log.warn("Failed to get port information of {}", vSgHost);
-            return Maps.newHashMap();
-        }
-
-        if (!sTag.equals(getServiceVlan(vtnPort))) {
-            log.error("Host({}) s-tag does not match with VTN port s-tag", vSgHost);
-            return Maps.newHashMap();
-        }
-        return vtnPort.addressPairs();
-    }
-
-    /**
-     * Returns s-tag from a given VTN port.
-     *
-     * @param vtnPort vtn port
-     * @return s-tag string
-     */
-    // TODO address service specific task in a separate package
-    private String getServiceVlan(VtnPort vtnPort) {
-        checkNotNull(vtnPort);
-
-        String portName = vtnPort.name();
-        if (portName != null && portName.startsWith(S_TAG)) {
-            return portName.split("-")[1];
-        } else {
-            return null;
+        if (!service.tenantServices().isEmpty()) {
+            updateProviderServiceInstances(service);
         }
     }
 
-    /**
-     * Returns instances with a given network service.
-     *
-     * @param serviceId service id
-     * @return set of hosts
-     */
-    private Set<Host> getInstances(VtnServiceId serviceId) {
-        return StreamSupport.stream(hostService.getHosts().spliterator(), false)
-                .filter(host -> Objects.equals(
-                        serviceId.id(),
-                        host.annotations().value(SERVICE_ID)))
+    private void updateProviderServiceInstances(VtnService service) {
+        GroupKey groupKey = getGroupKey(service.id());
+
+        Set<DeviceId> devices = nodeManager.completeNodes().stream()
+                .map(CordVtnNode::intBrId)
                 .collect(Collectors.toSet());
-    }
 
-    /**
-     * Registers static DHCP lease for a given host.
-     *
-     * @param host host
-     * @param service cord service
-     */
-    private void registerDhcpLease(Host host, VtnService service) {
-        List<Ip4Address> options = Lists.newArrayList();
-        options.add(Ip4Address.makeMaskPrefix(service.subnet().prefixLength()));
-        options.add(service.serviceIp().getIp4Address());
-        options.add(service.serviceIp().getIp4Address());
-        options.add(DEFAULT_DNS);
-
-        log.debug("Set static DHCP mapping for {}", host.mac());
-        dhcpService.setStaticMapping(host.mac(),
-                                     host.ipAddresses().stream().findFirst().get().getIp4Address(),
-                                     true,
-                                     options);
-    }
-
-    /**
-     * Handles VM detected situation.
-     *
-     * @param host host
-     */
-    private void serviceVmAdded(Host host) {
-        checkNotNull(osAccess, OPENSTACK_ACCESS_ERROR);
-        checkNotNull(xosAccess, XOS_ACCESS_ERROR);
-
-        // TODO address service specific task in a separate package
-        String serviceVlan = host.annotations().value(S_TAG);
-        if (serviceVlan != null) {
-            virtualSubscriberGatewayAdded(host, serviceVlan);
-        }
-
-        String serviceId = host.annotations().value(SERVICE_ID);
-        if (Strings.isNullOrEmpty(serviceId)) {
-            // ignore this host, it is not a service instance
-            return;
-        }
-
-        log.info("Instance is detected {}", host);
-
-        // TODO remove openstack access when XOS provides all information
-        VtnServiceApi serviceApi = xosClient.getClient(xosAccess).vtnService();
-        VtnService service = serviceApi.service(VtnServiceId.of(serviceId), osAccess);
-        if (service == null) {
-            log.warn("Failed to get VtnService for {}", serviceId);
-            return;
-        }
-
-        switch (service.networkType()) {
-            case MANAGEMENT:
-                ruleInstaller.populateManagementNetworkRules(host, service);
-                break;
-            case PRIVATE:
-                arpProxy.addGateway(service.serviceIp(), privateGatewayMac);
-            case PUBLIC:
-            default:
-                // TODO get bidirectional information from XOS once XOS supports
-                service.tenantServices().stream().forEach(
-                        tServiceId -> createServiceDependency(tServiceId, service.id(), true));
-                service.providerServices().stream().forEach(
-                        pServiceId -> createServiceDependency(service.id(), pServiceId, true));
-
-                ruleInstaller.updateProviderServiceGroup(service);
-                // sends gratuitous ARP here for the case of adding existing VMs
-                // when ONOS or cordvtn app is restarted
-                arpProxy.sendGratuitousArpForGateway(service.serviceIp(), Sets.newHashSet(host));
-                break;
-        }
-
-        registerDhcpLease(host, service);
-        ruleInstaller.populateBasicConnectionRules(host, service, true);
-    }
-
-    /**
-     * Handles VM removed situation.
-     *
-     * @param host host
-     */
-    private void serviceVmRemoved(Host host) {
-        checkNotNull(osAccess, OPENSTACK_ACCESS_ERROR);
-        checkNotNull(xosAccess, XOS_ACCESS_ERROR);
-
-        // TODO address service specific task in a separate package
-        if (host.annotations().value(S_TAG) != null) {
-            virtualSubscriberGatewayRemoved(host);
-        }
-
-        String serviceId = host.annotations().value(SERVICE_ID);
-        if (Strings.isNullOrEmpty(serviceId)) {
-            // ignore this host, it is not a service instance
-            return;
-        }
-
-        log.info("Instance is vanished {}", host);
-
-        // TODO remove openstack access when XOS provides all information
-        VtnServiceApi vtnServiceApi = xosClient.getClient(xosAccess).vtnService();
-        VtnService service = vtnServiceApi.service(VtnServiceId.of(serviceId), osAccess);
-        if (service == null) {
-            log.warn("Failed to get VtnService for {}", serviceId);
-            return;
-        }
-
-        // TODO need to consider the case that the service is removed also
-        switch (service.networkType()) {
-            case MANAGEMENT:
-                break;
-            case PRIVATE:
-                if (getInstances(VtnServiceId.of(serviceId)).isEmpty()) {
-                    arpProxy.removeGateway(service.serviceIp());
-                }
-            case PUBLIC:
-            default:
-                if (!service.tenantServices().isEmpty()) {
-                    ruleInstaller.updateProviderServiceGroup(service);
-                }
-                if (!service.providerServices().isEmpty()) {
-                    ruleInstaller.updateTenantServiceVm(host, service);
-                }
-                break;
-        }
-
-        dhcpService.removeStaticMapping(host.mac());
-        ruleInstaller.populateBasicConnectionRules(host, service, false);
-    }
-
-
-    /**
-     * Handles virtual subscriber gateway VM or container.
-     *
-     * @param host new host with stag, it can be vsg VM or vsg
-     * @param serviceVlan service vlan
-     */
-    // TODO address service specific task in a separate package
-    private void virtualSubscriberGatewayAdded(Host host, String serviceVlan) {
-        Map<IpAddress, MacAddress> vSgs;
-        Host vSgHost;
-
-        String vSgHostId = host.annotations().value(VSG_HOST_ID);
-        if (vSgHostId == null) {
-            log.info("vSG VM detected {}", host.id());
-
-            vSgHost = host;
-            vSgs = getSubscriberGateways(vSgHost);
-            vSgs.entrySet().stream().forEach(entry -> addVirtualSubscriberGateway(
-                    vSgHost,
-                    entry.getKey(),
-                    entry.getValue(),
-                    serviceVlan));
-        } else {
-            vSgHost = hostService.getHost(HostId.hostId(vSgHostId));
-            if (vSgHost == null) {
-                return;
+        for (DeviceId deviceId : devices) {
+            Group group = groupService.getGroup(deviceId, groupKey);
+            if (group == null) {
+                log.trace("No group exists for service {} in {}", service.id(), deviceId);
+                continue;
             }
 
-            log.info("vSG detected {}", host.id());
-            vSgs = getSubscriberGateways(vSgHost);
-        }
+            List<GroupBucket> oldBuckets = group.buckets().buckets();
+            List<GroupBucket> newBuckets = getServiceGroupBuckets(
+                    deviceId, service.vni(), getInstances(service.id())).buckets();
 
-        ruleInstaller.populateSubscriberGatewayRules(vSgHost, vSgs.keySet());
-    }
-
-    /**
-     * Handles virtual subscriber gateway removed.
-     *
-     * @param vSg vsg host to remove
-     */
-    // TODO address service specific task in a separate package
-    private void virtualSubscriberGatewayRemoved(Host vSg) {
-        String vSgHostId = vSg.annotations().value(VSG_HOST_ID);
-        if (vSgHostId == null) {
-            return;
-        }
-
-        Host vSgHost = hostService.getHost(HostId.hostId(vSgHostId));
-        if (vSgHost == null) {
-            return;
-        }
-
-        log.info("vSG removed {}", vSg.id());
-        Map<IpAddress, MacAddress> vSgs = getSubscriberGateways(vSgHost);
-        ruleInstaller.populateSubscriberGatewayRules(vSgHost, vSgs.keySet());
-    }
-
-    /**
-     * Sets service network gateway MAC address and sends out gratuitous ARP to all
-     * VMs to update the gateway MAC address.
-     *
-     * @param newMac mac address to update
-     */
-    private void setPrivateGatewayMac(MacAddress newMac) {
-        checkNotNull(osAccess, OPENSTACK_ACCESS_ERROR);
-        checkNotNull(xosAccess, XOS_ACCESS_ERROR);
-
-        if (newMac == null || newMac.equals(privateGatewayMac)) {
-            // no updates, do nothing
-            return;
-        }
-
-        privateGatewayMac = newMac;
-        log.debug("Set service gateway MAC address to {}", privateGatewayMac.toString());
-
-        VtnServiceApi vtnServiceApi = xosClient.getClient(xosAccess).vtnService();
-        vtnServiceApi.services().stream().forEach(serviceId -> {
-            VtnService service = vtnServiceApi.service(serviceId, osAccess);
-            if (service != null) {
-                arpProxy.addGateway(service.serviceIp(), privateGatewayMac);
-                arpProxy.sendGratuitousArpForGateway(service.serviceIp(), getInstances(serviceId));
+            if (oldBuckets.equals(newBuckets)) {
+                continue;
             }
+
+            List<GroupBucket> bucketsToRemove = Lists.newArrayList(oldBuckets);
+            bucketsToRemove.removeAll(newBuckets);
+            if (!bucketsToRemove.isEmpty()) {
+                groupService.removeBucketsFromGroup(
+                        deviceId,
+                        groupKey,
+                        new GroupBuckets(bucketsToRemove),
+                        groupKey, appId);
+            }
+
+            List<GroupBucket> bucketsToAdd = Lists.newArrayList(newBuckets);
+            bucketsToAdd.removeAll(oldBuckets);
+            if (!bucketsToAdd.isEmpty()) {
+                groupService.addBucketsToGroup(
+                        deviceId,
+                        groupKey,
+                        new GroupBuckets(bucketsToAdd),
+                        groupKey, appId);
+            }
+        }
+    }
+
+    private void removeInstanceFromTenantService(Instance instance, VtnService service) {
+        service.providerServices().stream().forEach(pServiceId -> {
+            Map<DeviceId, Set<PortNumber>> inPorts = Maps.newHashMap();
+            Map<DeviceId, GroupId> outGroups = Maps.newHashMap();
+
+            inPorts.put(instance.deviceId(), Sets.newHashSet(instance.portNumber()));
+            outGroups.put(instance.deviceId(), getGroupId(pServiceId, instance.deviceId()));
+
+            inServiceRule(inPorts, outGroups, false);
         });
     }
 
-    /**
-     * Sets public gateway MAC address.
-     *
-     * @param publicGateways gateway ip and mac address pairs
-     */
-    private void setPublicGatewayMac(Map<IpAddress, MacAddress> publicGateways) {
-        publicGateways.entrySet()
-                .stream()
-                .forEach(entry -> {
-                    arpProxy.addGateway(entry.getKey(), entry.getValue());
-                    log.debug("Added public gateway IP {}, MAC {}",
-                              entry.getKey().toString(), entry.getValue().toString());
-                });
-        // TODO notice gateway MAC change to VMs holds this gateway IP
+    private void serviceDependencyRules(VtnService tService, VtnService pService,
+                                       boolean isBidirectional, boolean install) {
+        Map<DeviceId, GroupId> outGroups = Maps.newHashMap();
+        Map<DeviceId, Set<PortNumber>> inPorts = Maps.newHashMap();
+
+        nodeManager.completeNodes().stream().forEach(node -> {
+            DeviceId deviceId = node.intBrId();
+            GroupId groupId = createServiceGroup(deviceId, pService);
+            outGroups.put(deviceId, groupId);
+
+            Set<PortNumber> tServiceInstances = getInstances(tService.id())
+                    .stream()
+                    .filter(instance -> instance.deviceId().equals(deviceId))
+                    .map(Instance::portNumber)
+                    .collect(Collectors.toSet());
+            inPorts.put(deviceId, tServiceInstances);
+        });
+
+        Ip4Prefix srcRange = tService.subnet().getIp4Prefix();
+        Ip4Prefix dstRange = pService.subnet().getIp4Prefix();
+
+        indirectAccessRule(srcRange, pService.serviceIp().getIp4Address(), outGroups, install);
+        directAccessRule(srcRange, dstRange, install);
+        if (isBidirectional) {
+            directAccessRule(dstRange, srcRange, install);
+        }
+        inServiceRule(inPorts, outGroups, install);
     }
 
-    /**
-     * Updates configurations.
-     */
-    private void readConfiguration() {
-        CordVtnConfig config = configRegistry.getConfig(appId, CordVtnConfig.class);
-        if (config == null) {
-            log.debug("No configuration found");
-            return;
+    private void indirectAccessRule(Ip4Prefix srcRange, Ip4Address serviceIp,
+                                    Map<DeviceId, GroupId> outGroups, boolean install) {
+        TrafficSelector selector = DefaultTrafficSelector.builder()
+                .matchEthType(Ethernet.TYPE_IPV4)
+                .matchIPSrc(srcRange)
+                .matchIPDst(serviceIp.toIpPrefix())
+                .build();
+
+        for (Map.Entry<DeviceId, GroupId> outGroup : outGroups.entrySet()) {
+            TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+                    .group(outGroup.getValue())
+                    .build();
+
+            FlowRule flowRule = DefaultFlowRule.builder()
+                    .fromApp(appId)
+                    .withSelector(selector)
+                    .withTreatment(treatment)
+                    .withPriority(PRIORITY_HIGH)
+                    .forDevice(outGroup.getKey())
+                    .forTable(TABLE_ACCESS_TYPE)
+                    .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(TABLE_DST_IP)
+                .build();
+
+        nodeManager.completeNodes().stream().forEach(node -> {
+            DeviceId deviceId = node.intBrId();
+            FlowRule flowRuleDirect = DefaultFlowRule.builder()
+                    .fromApp(appId)
+                    .withSelector(selector)
+                    .withTreatment(treatment)
+                    .withPriority(PRIORITY_DEFAULT)
+                    .forDevice(deviceId)
+                    .forTable(TABLE_ACCESS_TYPE)
+                    .makePermanent()
+                    .build();
+
+            pipeline.processFlowRule(install, flowRuleDirect);
+        });
+    }
+
+    private void inServiceRule(Map<DeviceId, Set<PortNumber>> inPorts,
+                               Map<DeviceId, GroupId> outGroups, boolean install) {
+        for (Map.Entry<DeviceId, Set<PortNumber>> entry : inPorts.entrySet()) {
+            Set<PortNumber> ports = entry.getValue();
+            DeviceId deviceId = entry.getKey();
+
+            GroupId groupId = outGroups.get(deviceId);
+            if (groupId == null) {
+                continue;
+            }
+
+            ports.stream().forEach(port -> {
+                TrafficSelector selector = DefaultTrafficSelector.builder()
+                        .matchInPort(port)
+                        .build();
+
+                TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+                        .group(groupId)
+                        .build();
+
+                FlowRule flowRule = DefaultFlowRule.builder()
+                        .fromApp(appId)
+                        .withSelector(selector)
+                        .withTreatment(treatment)
+                        .withPriority(PRIORITY_DEFAULT)
+                        .forDevice(deviceId)
+                        .forTable(TABLE_IN_SERVICE)
+                        .makePermanent()
+                        .build();
+
+                pipeline.processFlowRule(install, flowRule);
+            });
+        }
+    }
+
+    private GroupId getGroupId(VtnServiceId serviceId, DeviceId deviceId) {
+        return new DefaultGroupId(Objects.hash(serviceId, deviceId));
+    }
+
+    private GroupKey getGroupKey(VtnServiceId serviceId) {
+        return new DefaultGroupKey(serviceId.id().getBytes());
+    }
+
+    private GroupId createServiceGroup(DeviceId deviceId, VtnService service) {
+        GroupKey groupKey = getGroupKey(service.id());
+        Group group = groupService.getGroup(deviceId, groupKey);
+        GroupId groupId = getGroupId(service.id(), deviceId);
+
+        if (group != null) {
+            log.debug("Group {} is already exist in {}", service.id(), deviceId);
+            return groupId;
         }
 
-        xosAccess = config.xosAccess();
-        osAccess = config.openstackAccess();
+        GroupBuckets buckets = getServiceGroupBuckets(
+                deviceId, service.vni(), getInstances(service.id()));
+        GroupDescription groupDescription = new DefaultGroupDescription(
+                deviceId,
+                GroupDescription.Type.SELECT,
+                buckets,
+                groupKey,
+                groupId.id(),
+                appId);
 
-        setPrivateGatewayMac(config.privateGatewayMac());
-        setPublicGatewayMac(config.publicGateways());
+        groupService.addGroup(groupDescription);
+        return groupId;
+    }
+
+    private GroupBuckets getServiceGroupBuckets(DeviceId deviceId, long tunnelId,
+                                                Set<Instance> instances) {
+        List<GroupBucket> buckets = Lists.newArrayList();
+        instances.stream().forEach(instance -> {
+            Ip4Address tunnelIp = nodeManager.dpIp(instance.deviceId()).getIp4Address();
+            TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
+
+            if (deviceId.equals(instance.deviceId())) {
+                tBuilder.setEthDst(instance.mac())
+                        .setOutput(instance.portNumber());
+            } else {
+                ExtensionTreatment tunnelDst =
+                        pipeline.tunnelDstTreatment(deviceId, tunnelIp);
+                tBuilder.setEthDst(instance.mac())
+                        .extension(tunnelDst, deviceId)
+                        .setTunnelId(tunnelId)
+                        .setOutput(nodeManager.tunnelPort(instance.deviceId()));
+            }
+            buckets.add(createSelectGroupBucket(tBuilder.build()));
+        });
+        return new GroupBuckets(buckets);
     }
 
     private class InternalHostListener implements HostListener {
@@ -692,50 +393,14 @@
                 return;
             }
 
+            Instance instance = Instance.of(host);
             switch (event.type()) {
                 case HOST_UPDATED:
                 case HOST_ADDED:
-                    eventExecutor.execute(() -> serviceVmAdded(host));
+                    eventExecutor.execute(() -> instanceDetected(instance));
                     break;
                 case HOST_REMOVED:
-                    eventExecutor.execute(() -> serviceVmRemoved(host));
-                    break;
-                default:
-                    break;
-            }
-        }
-    }
-
-    private class InternalPacketProcessor implements PacketProcessor {
-
-        @Override
-        public void process(PacketContext context) {
-            if (context.isHandled()) {
-                return;
-            }
-
-            Ethernet ethPacket = context.inPacket().parsed();
-            if (ethPacket == null || ethPacket.getEtherType() != Ethernet.TYPE_ARP) {
-                return;
-            }
-
-            arpProxy.processArpPacket(context, ethPacket);
-        }
-    }
-
-    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:
-                    log.info("Network configuration changed");
-                    eventExecutor.execute(CordVtn.this::readConfiguration);
+                    eventExecutor.execute(() -> instanceRemoved(instance));
                     break;
                 default:
                     break;
