diff --git a/apps/openstacknetworking/routing/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingManager.java b/apps/openstacknetworking/routing/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingManager.java
index c8ce876..f7989bd 100644
--- a/apps/openstacknetworking/routing/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingManager.java
+++ b/apps/openstacknetworking/routing/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingManager.java
@@ -15,7 +15,6 @@
  */
 package org.onosproject.openstacknetworking.routing;
 
-import com.google.common.collect.ImmutableSet;
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Deactivate;
@@ -25,10 +24,11 @@
 import org.onlab.packet.Ethernet;
 import org.onlab.packet.IPv4;
 import org.onlab.packet.Ip4Address;
+import org.onlab.packet.IpAddress;
 import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
 import org.onlab.util.Tools;
 import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
 import org.onosproject.core.GroupId;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.Host;
@@ -38,12 +38,10 @@
 import org.onosproject.net.flow.DefaultTrafficTreatment;
 import org.onosproject.net.flow.TrafficSelector;
 import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flowobjective.DefaultForwardingObjective;
 import org.onosproject.net.flowobjective.FlowObjectiveService;
 import org.onosproject.net.flowobjective.ForwardingObjective;
 import org.onosproject.openstackinterface.OpenstackInterfaceService;
 import org.onosproject.openstackinterface.OpenstackNetwork;
-import org.onosproject.openstackinterface.OpenstackPort;
 import org.onosproject.openstackinterface.OpenstackRouter;
 import org.onosproject.openstackinterface.OpenstackRouterInterface;
 import org.onosproject.openstackinterface.OpenstackSubnet;
@@ -62,7 +60,6 @@
 
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.ExecutorService;
@@ -85,9 +82,6 @@
     protected FlowObjectiveService flowObjectiveService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected DeviceService deviceService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected OpenstackInterfaceService openstackService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -96,6 +90,12 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected ScalableGatewayService gatewayService;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected CoreService coreService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected DeviceService deviceService;
+
     private final ExecutorService eventExecutor = newSingleThreadScheduledExecutor(
             groupedThreads(this.getClass().getSimpleName(), "event-handler", log));
     private final InternalNodeListener nodeListener = new InternalNodeListener();
@@ -111,37 +111,56 @@
 
     @Deactivate
     protected void deactivate() {
+        super.deactivate();
         nodeService.removeListener(nodeListener);
         log.info("stopped");
     }
 
     @Override
+    protected void hostDetected(Host host) {
+        // Installs forwarding flow rules to VMs in different nodes and different subnets
+        // that are connected via a router
+        Optional<OpenstackRouter> routerOfTheHost = getRouter(host);
+
+        if (!routerOfTheHost.isPresent()) {
+            return;
+        }
+
+        routableSubNets(routerOfTheHost.get().id()).stream()
+                .filter(subnet -> !subnet.id().equals(host.annotations().value(SUBNET_ID)))
+                .forEach(subnet -> setForwardingRulesAmongHostsInDifferentCnodes(host, getHosts(subnet), true));
+    }
+
+    @Override
+    protected void hostRemoved(Host host) {
+        // Removes forwarding flow rules to VMs in different nodes and different subnets
+        // that are connected via a router
+        Optional<OpenstackRouter> routerOfTheHost = getRouter(host);
+        if (!routerOfTheHost.isPresent()) {
+            return;
+        }
+
+        routableSubNets(routerOfTheHost.get().id()).stream()
+                .filter(subnet -> !subnet.id().equals(host.annotations().value(SUBNET_ID)))
+                .forEach(subnet -> setForwardingRulesAmongHostsInDifferentCnodes(host, getHosts(subnet), false));
+    }
+
+    @Override
     public void createRouter(OpenstackRouter osRouter) {
     }
 
     @Override
     public void updateRouter(OpenstackRouter osRouter) {
         if (osRouter.gatewayExternalInfo().externalFixedIps().size() > 0) {
-            openstackService.ports().stream()
-                    .filter(osPort -> osPort.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE) &&
-                            osPort.deviceId().equals(osRouter.id()))
-                    .forEach(osPort -> {
-                        String subnetId = osPort.fixedIps().keySet().stream().findFirst().get();
-                        setExternalConnection(osRouter, subnetId);
-                    });
+            routableSubNets(osRouter.id()).stream()
+                    .forEach(subnet -> setExternalConnection(osRouter, subnet, true));
 
             log.info("Connected external gateway {} to router {}",
                      osRouter.gatewayExternalInfo().externalFixedIps(),
                      osRouter.name());
         } else {
-            openstackService.ports().stream()
-                    .filter(osPort -> osPort.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE) &&
-                            osPort.deviceId().equals(osRouter.id()))
-                    .forEach(osPort -> {
-                        String subnetId = osPort.fixedIps().keySet().stream().findFirst().get();
-                        OpenstackSubnet osSubNet = openstackService.subnet(subnetId);
-                        unsetExternalConnection(osRouter, osPort.networkId(), osSubNet.cidr());
-                    });
+            routableSubNets(osRouter.id()).stream()
+                    .forEach(subnet -> setExternalConnection(osRouter, subnet, false));
 
             log.info("Disconnected external gateway from router {}",
                      osRouter.name());
@@ -150,309 +169,163 @@
 
     @Override
     public void removeRouter(String osRouterId) {
-        // TODO implement this
+        // Nothing to do
+        // All interfaces need to be removed before the router is removed,
+        // and all related flow rues are removed when the interfaces are removed.
     }
 
     @Override
-    public void addRouterInterface(OpenstackRouterInterface routerIface) {
-        OpenstackRouter osRouter = openstackRouter(routerIface.id());
-        OpenstackPort osPort = openstackService.port(routerIface.portId());
-        if (osRouter == null || osPort == null) {
-            log.warn("Failed to add router interface {}", routerIface);
+    public void addRouterInterface(OpenstackRouterInterface routerIfaceAdded) {
+        OpenstackRouter osRouter = openstackRouter(routerIfaceAdded.id());
+        OpenstackSubnet osSubnetAdded = openstackService.subnet(routerIfaceAdded.subnetId());
+        if (osRouter == null || osSubnetAdded == null) {
+            log.warn("Failed to add router interface {}", routerIfaceAdded);
             return;
         }
-
-        setGatewayIcmp(Ip4Address.valueOf(openstackService.subnet(routerIface.subnetId()).gatewayIp()));
-
-        setRoutes(osRouter, Optional.empty());
-        if (osRouter.gatewayExternalInfo().externalFixedIps().size() > 0) {
-            String subnetId = osPort.fixedIps().keySet().stream().findFirst().get();
-            setExternalConnection(osRouter, subnetId);
-        }
-        log.info("Connected {} to router {}", osPort.fixedIps(), osRouter.name());
+        handleRouterInterfaces(osRouter, osSubnetAdded);
     }
 
     @Override
     public void removeRouterInterface(OpenstackRouterInterface routerIface) {
         OpenstackRouter osRouter = openstackService.router(routerIface.id());
+        OpenstackSubnet osSubnetRemoved = openstackService.subnet(routerIface.subnetId());
         if (osRouter == null) {
             log.warn("Failed to remove router interface {}", routerIface);
             return;
         }
+        handleRouterInterfacesRemoved(osRouter, osSubnetRemoved);
 
-        OpenstackSubnet osSubnet = openstackService.subnet(routerIface.subnetId());
-        OpenstackNetwork osNet = openstackService.network(osSubnet.networkId());
+        log.info("Disconnected {} from router {}", osSubnetRemoved.cidr(), osRouter.name());
+    }
 
-        unsetGatewayIcmp(Ip4Address.valueOf(openstackService.subnet(routerIface.subnetId()).gatewayIp()));
+    private void handleRouterInterfaces(OpenstackRouter osRouter, OpenstackSubnet osSubnetAdded) {
+        OpenstackNetwork osNetworkAdded = openstackService.network(osSubnetAdded.networkId());
+        if (osNetworkAdded == null) {  // in case of external network subnet
+            return;
+        }
 
-        unsetRoutes(osRouter, osSubnet);
+        // Sets flow rules for routing among subnets connected to a router.
+        setRoutesAmongSubnets(osRouter, osSubnetAdded, true);
 
+        // Sets flow rules for forwarding "packets going to external networks" to gateway nodes.
         if (osRouter.gatewayExternalInfo().externalFixedIps().size() > 0) {
-            unsetExternalConnection(osRouter, osNet.id(), osSubnet.cidr());
-        }
-        log.info("Disconnected {} from router {}", osSubnet.cidr(), osRouter.name());
-    }
-
-    private void setGatewayIcmp(Ip4Address gatewayIp) {
-        if (gatewayIp == null) {
-            return;
-        }
-        gatewayService.getGatewayDeviceIds().forEach(deviceId -> populateGatewayIcmpRule(gatewayIp, deviceId));
-    }
-
-    private void populateGatewayIcmpRule(Ip4Address gatewayIp, DeviceId deviceId) {
-        TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
-        TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
-
-        sBuilder.matchEthType(Ethernet.TYPE_IPV4)
-                .matchIPProtocol(IPv4.PROTOCOL_ICMP)
-                .matchIPDst(gatewayIp.toIpPrefix());
-
-        tBuilder.setOutput(PortNumber.CONTROLLER);
-
-        ForwardingObjective fo = DefaultForwardingObjective.builder()
-                .withSelector(sBuilder.build())
-                .withTreatment(tBuilder.build())
-                .withPriority(GATEWAY_ICMP_PRIORITY)
-                .withFlag(ForwardingObjective.Flag.VERSATILE)
-                .fromApp(appId)
-                .add();
-
-        flowObjectiveService.forward(deviceId, fo);
-    }
-
-    private void unsetGatewayIcmp(Ip4Address gatewayIp) {
-        if (gatewayIp == null) {
-            return;
-        }
-        gatewayService.getGatewayDeviceIds().forEach(deviceId -> {
-            removeGatewayIcmpRule(gatewayIp, deviceId);
-        });
-    }
-
-    private void removeGatewayIcmpRule(Ip4Address gatewayIp, DeviceId deviceId) {
-        TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
-
-        sBuilder.matchEthType(Ethernet.TYPE_IPV4)
-                .matchIPProtocol(IPv4.PROTOCOL_ICMP)
-                .matchIPDst(gatewayIp.toIpPrefix());
-
-        RulePopulatorUtil.removeRule(flowObjectiveService, appId, deviceId, sBuilder.build(),
-                ForwardingObjective.Flag.VERSATILE, GATEWAY_ICMP_PRIORITY);
-
-    }
-    private void setExternalConnection(OpenstackRouter osRouter, String osSubNetId) {
-        if (!osRouter.gatewayExternalInfo().isEnablePnat()) {
-            log.debug("Source NAT is disabled");
-            return;
+            setExternalConnection(osRouter, osSubnetAdded, true);
         }
 
-        OpenstackSubnet osSubNet = openstackService.subnet(osSubNetId);
-        OpenstackNetwork osNet = openstackService.network(osSubNet.networkId());
-        populateExternalRules(osNet, osSubNet);
+        // Sets flow rules to handle ping to the virtual gateway.
+        Ip4Address vGatewayIp = Ip4Address.valueOf(osSubnetAdded.gatewayIp());
+        gatewayService.getGatewayDeviceIds()
+                .forEach(deviceId -> setGatewayIcmpRule(vGatewayIp, deviceId, true));
+
+        // Sets east-west routing rules for VMs in different Cnode to Switching Table.
+        setForwardingRulesForEastWestRouting(osRouter, osSubnetAdded, true);
+
     }
 
-    private void unsetExternalConnection(OpenstackRouter osRouter, String osNetId, String subNetCidr) {
-        if (!osRouter.gatewayExternalInfo().isEnablePnat()) {
-            log.debug("Source NAT is disabled");
-            return;
+    private void handleRouterInterfacesRemoved(OpenstackRouter osRouter, OpenstackSubnet osSubnetRemoved) {
+
+        // Removes flow rules for routing among subnets connected to a router.
+        setRoutesAmongSubnets(osRouter, osSubnetRemoved, false);
+
+        // Removes flow rules for forwarding "packets going to external networks" to gateway nodes.
+        if (osRouter.gatewayExternalInfo().externalFixedIps().size() > 0) {
+            setExternalConnection(osRouter, osSubnetRemoved, false);
         }
 
-        // FIXME router interface is subnet specific, not network
-        OpenstackNetwork osNet = openstackService.network(osNetId);
-        removeExternalRules(osNet, subNetCidr);
+        // Removes flow rules to handle ping to the virtual gateway.
+        Ip4Address vGatewayIp = Ip4Address.valueOf(osSubnetRemoved.gatewayIp());
+        gatewayService.getGatewayDeviceIds()
+                .forEach(deviceId -> setGatewayIcmpRule(vGatewayIp, deviceId, false));
+
+        // Removes east-west routing rules for VMs in different Cnode to Switching Table.
+        setForwardingRulesForEastWestRouting(osRouter, osSubnetRemoved, false);
+
+        // Resets east-west routing rules for VMs in different Cnode to Switching Table.
+        routableSubNets(osRouter.id()).stream()
+                .forEach(subnet -> setForwardingRulesForEastWestRouting(osRouter, subnet, true));
     }
 
-    private void setRoutes(OpenstackRouter osRouter, Optional<Host> host) {
+    private void setRoutesAmongSubnets(OpenstackRouter osRouter, OpenstackSubnet osSubnetAdded, boolean install) {
         Set<OpenstackSubnet> routableSubNets = routableSubNets(osRouter.id());
         if (routableSubNets.size() < 2) {
             // no other subnet interface is connected to this router, do nothing
             return;
         }
 
-        Set<String> routableSubNetIds = routableSubNets.stream()
-                .map(OpenstackSubnet::id)
-                .collect(Collectors.toSet());
-
-        if (host.isPresent()) {
-            if (!routableSubNetIds.contains(host.get().annotations().value(SUBNET_ID))) {
-                // subnet of host is not connected to this router, do nothing.
-                return;
-            }
-        }
-
-        Set<Host> hosts = host.isPresent() ? ImmutableSet.of(host.get()) :
-                Tools.stream(hostService.getHosts())
-                        .filter(h -> routableSubNetIds.contains(h.annotations().value(SUBNET_ID)))
-                        .collect(Collectors.toSet());
-
-        hosts.forEach(h -> populateRoutingRules(h, routableSubNets));
-    }
-
-    private void unsetRoutes(OpenstackRouter osRouter, OpenstackSubnet osSubNet) {
-        Set<OpenstackSubnet> routableSubNets = routableSubNets(osRouter.id());
-        Tools.stream(hostService.getHosts())
-                .filter(h -> Objects.equals(
-                        h.annotations().value(NETWORK_ID), osSubNet.id()))
-                .forEach(h -> removeRoutingRules(h, routableSubNets));
-
-        routableSubNets.forEach(n -> {
-            Tools.stream(hostService.getHosts())
-                    .filter(h -> Objects.equals(
-                            h.annotations().value(SUBNET_ID),
-                            n.id()))
-                    .forEach(h -> removeRoutingRules(h, ImmutableSet.of(osSubNet)));
-            log.debug("Removed between {} to {}", n.name(), osSubNet.name());
-        });
-    }
-
-    private OpenstackRouter openstackRouter(String routerId) {
-        return openstackService.routers().stream().filter(r ->
-                r.id().equals(routerId)).iterator().next();
-    }
-
-    private Optional<OpenstackPort> routerIfacePort(String osNetId, String osSubNetId) {
-        // FIXME router interface is subnet specific, not network
-        return openstackService.ports().stream()
-                .filter(p -> p.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE) &&
-                        p.networkId().equals(osNetId) &&
-                        p.fixedIps().containsKey(osSubNetId))
-                .findAny();
-    }
-
-    private Set<OpenstackSubnet> routableSubNets(String osRouterId) {
-        return openstackService.ports().stream()
-                .filter(p -> p.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE) &&
-                        p.deviceId().equals(osRouterId))
-                .map(p -> openstackService.subnet(p.fixedIps().keySet().stream().findFirst().get()))
-                .collect(Collectors.toSet());
-    }
-
-    private void populateExternalRules(OpenstackNetwork osNet, OpenstackSubnet osSubNet) {
-        populateCnodeToGateway(Long.valueOf(osNet.segmentId()), osSubNet.cidr());
-        populateGatewayToController(Long.valueOf(osNet.segmentId()), osSubNet.cidr());
-    }
-
-    private void removeExternalRules(OpenstackNetwork osNet, String subNetCidr) {
-        TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
-        sBuilder.matchEthType(Ethernet.TYPE_IPV4)
-                .matchTunnelId(Long.valueOf(osNet.segmentId()))
-                .matchIPSrc(IpPrefix.valueOf(subNetCidr))
-                .matchEthDst(Constants.DEFAULT_GATEWAY_MAC);
-
-        nodeService.completeNodes().forEach(node -> {
-            ForwardingObjective.Flag flag = node.type().equals(GATEWAY) ?
-                    ForwardingObjective.Flag.VERSATILE :
-                    ForwardingObjective.Flag.SPECIFIC;
-
-            RulePopulatorUtil.removeRule(
-                    flowObjectiveService,
-                    appId,
-                    node.intBridge(),
-                    sBuilder.build(),
-                    flag,
-                    ROUTING_RULE_PRIORITY);
-        });
-    }
-
-    private void populateRoutingRules(Host host, Set<OpenstackSubnet> osSubNets) {
-        String osSubNetId = host.annotations().value(SUBNET_ID);
-        if (osSubNetId == null) {
-            return;
-        }
-
-        DeviceId localDevice = host.location().deviceId();
-        PortNumber localPort = host.location().port();
-        if (!nodeService.dataIp(localDevice).isPresent()) {
-            log.warn("Failed to populate L3 rules");
-            return;
-        }
-
         Map<String, String> vniMap = new HashMap<>();
         openstackService.networks().forEach(n -> vniMap.put(n.id(), n.segmentId()));
 
-        // TODO improve pipeline, do we have to install access rules between networks
-        // for every single VMs?
-        osSubNets.stream().filter(osSubNet -> !osSubNet.id().equals(osSubNetId)).forEach(osSubNet -> {
-            populateRoutingRulestoSameNode(
-                    host.ipAddresses().stream().findFirst().get().getIp4Address(),
-                    host.mac(),
-                    localPort, localDevice,
-                    Long.valueOf(vniMap.get(osSubNet.networkId())),
-                    osSubNet.cidr());
-
-            nodeService.completeNodes().stream()
-                    .filter(node -> node.type().equals(COMPUTE))
-                    .filter(node -> !node.intBridge().equals(localDevice))
-                    .forEach(node -> populateRoutingRulestoDifferentNode(
-                            host.ipAddresses().stream().findFirst().get().getIp4Address(),
-                            Long.valueOf(vniMap.get(osSubNet.networkId())),
-                            node.intBridge(),
-                            nodeService.dataIp(localDevice).get().getIp4Address(),
-                            osSubNet.cidr()));
-        });
+        routableSubNets.stream()
+                .filter(subnet -> !subnet.id().equals(osSubnetAdded.id()))
+                .filter(subnet -> vniMap.get(subnet.networkId()) != null)
+                .forEach(subnet -> nodeService.completeNodes().stream()
+                        .filter(node -> node.type().equals(COMPUTE))
+                        .forEach(node -> {
+                                setRoutingRules(node.intBridge(),
+                                        Integer.parseInt(vniMap.get(subnet.networkId())),
+                                        Integer.parseInt(vniMap.get(osSubnetAdded.networkId())),
+                                        subnet, osSubnetAdded, install);
+                                setRoutingRules(node.intBridge(),
+                                        Integer.parseInt(vniMap.get(osSubnetAdded.networkId())),
+                                        Integer.parseInt(vniMap.get(subnet.networkId())),
+                                        osSubnetAdded, subnet, install);
+                                }
+                        ));
     }
 
-    private void removeRoutingRules(Host host, Set<OpenstackSubnet> osSubNets) {
-        String osSubNetId = host.annotations().value(SUBNET_ID);
-        if (osSubNetId == null) {
-            return;
-        }
+    private void setRoutingRules(DeviceId deviceId, int srcVni, int dstVni,
+                                 OpenstackSubnet subnetSrc, OpenstackSubnet subnetDst, boolean install) {
 
-        Map<String, String> vniMap = new HashMap<>();
-        openstackService.networks().forEach(n -> vniMap.put(n.id(), n.segmentId()));
-
-        osSubNets.stream().filter(osSubNet -> !osSubNet.id().equals(osSubNetId)).forEach(osSubNet -> {
-            TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
-            sBuilder.matchEthType(Ethernet.TYPE_IPV4)
-                    .matchIPDst(host.ipAddresses().stream().findFirst().get().toIpPrefix())
-                    .matchIPSrc(IpPrefix.valueOf(osSubNet.cidr()))
-                    .matchTunnelId(Long.valueOf(vniMap.get(osSubNet.networkId())));
-
-            nodeService.completeNodes().stream()
-                    .filter(node -> node.type().equals(COMPUTE))
-                    .forEach(node -> RulePopulatorUtil.removeRule(
-                            flowObjectiveService,
-                            appId,
-                            node.intBridge(),
-                            sBuilder.build(),
-                            ForwardingObjective.Flag.SPECIFIC,
-                            EW_ROUTING_RULE_PRIORITY));
-        });
-        log.debug("Removed routing rule from {} to {}", host, osSubNets);
-    }
-
-    private void populateGatewayToController(long vni, String subNetCidr) {
         TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
         TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
 
         sBuilder.matchEthType(Ethernet.TYPE_IPV4)
-                .matchTunnelId(vni)
-                .matchIPSrc(IpPrefix.valueOf(subNetCidr))
-                .matchEthDst(Constants.DEFAULT_GATEWAY_MAC);
-        tBuilder.setOutput(PortNumber.CONTROLLER);
+                .matchTunnelId(srcVni)
+                .matchIPSrc(IpPrefix.valueOf(subnetSrc.cidr()))
+                .matchIPDst(IpPrefix.valueOf(subnetDst.cidr()));
 
-        ForwardingObjective fo = DefaultForwardingObjective.builder()
-                .withSelector(sBuilder.build())
-                .withTreatment(tBuilder.build())
-                .withFlag(ForwardingObjective.Flag.VERSATILE)
-                .withPriority(ROUTING_RULE_PRIORITY)
-                .fromApp(appId)
-                .add();
+        tBuilder.setTunnelId(dstVni);
 
-        gatewayService.getGatewayDeviceIds().forEach(deviceId -> flowObjectiveService.forward(deviceId, fo));
+        RulePopulatorUtil.setRule(flowObjectiveService, appId, deviceId, sBuilder.build(),
+                tBuilder.build(), ForwardingObjective.Flag.SPECIFIC, EW_ROUTING_RULE_PRIORITY, install);
+
+        // Flow rules for destination is in different subnet and different node,
+        // because VNI is converted to destination VNI in the source VM node.
+        sBuilder = DefaultTrafficSelector.builder();
+        tBuilder = DefaultTrafficTreatment.builder();
+
+        sBuilder.matchEthType(Ethernet.TYPE_IPV4)
+                .matchTunnelId(dstVni)
+                .matchIPSrc(IpPrefix.valueOf(subnetSrc.cidr()))
+                .matchIPDst(IpPrefix.valueOf(subnetDst.cidr()));
+
+        tBuilder.setTunnelId(dstVni);
+
+        RulePopulatorUtil.setRule(flowObjectiveService, appId, deviceId, sBuilder.build(),
+                tBuilder.build(), ForwardingObjective.Flag.SPECIFIC, EW_ROUTING_RULE_PRIORITY, install);
     }
 
-    private void populateCnodeToGateway(long vni, String subnetCidr) {
+    private void setExternalConnection(OpenstackRouter osRouter, OpenstackSubnet osSubNet, boolean install) {
+        if (!osRouter.gatewayExternalInfo().isEnablePnat()) {
+            log.debug("Source NAT is disabled");
+            return;
+        }
+
+        //OpenstackSubnet osSubNet = openstackService.subnet(osSubNetId);
+        OpenstackNetwork osNet = openstackService.network(osSubNet.networkId());
+
         nodeService.completeNodes().stream()
                 .filter(node -> node.type().equals(COMPUTE))
-                .forEach(node -> populateRuleToGateway(
+                .forEach(node -> setRulesToGateway(
                         node.intBridge(),
                         gatewayService.getGatewayGroupId(node.intBridge()),
-                        vni, subnetCidr));
+                        Long.valueOf(osNet.segmentId()), osSubNet.cidr(), install));
+
+        // Is this for PNAT ??
+        setRulesForGatewayToController(Long.valueOf(osNet.segmentId()), osSubNet.cidr(), install);
     }
 
-    private void populateRuleToGateway(DeviceId deviceId, GroupId groupId, long vni, String cidr) {
+    private void setRulesToGateway(DeviceId deviceId, GroupId groupId, long vni, String cidr, boolean install) {
         TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
         TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
 
@@ -462,133 +335,119 @@
                 .matchEthDst(Constants.DEFAULT_GATEWAY_MAC);
 
         tBuilder.group(groupId);
-        ForwardingObjective fo = DefaultForwardingObjective.builder()
-                .withSelector(sBuilder.build())
-                .withTreatment(tBuilder.build())
-                .withFlag(ForwardingObjective.Flag.SPECIFIC)
-                .withPriority(ROUTING_RULE_PRIORITY)
-                .fromApp(appId)
-                .add();
 
-        flowObjectiveService.forward(deviceId, fo);
+        RulePopulatorUtil.setRule(flowObjectiveService, appId, deviceId, sBuilder.build(),
+                tBuilder.build(), ForwardingObjective.Flag.SPECIFIC, ROUTING_RULE_PRIORITY, install);
     }
 
-    private void populateRoutingRulestoDifferentNode(Ip4Address vmIp, long vni,
-                                                     DeviceId deviceId, Ip4Address hostIp,
-                                                     String cidr) {
+    private void setRulesForGatewayToController(long vni, String subNetCidr, boolean install) {
         TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
         TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
 
         sBuilder.matchEthType(Ethernet.TYPE_IPV4)
                 .matchTunnelId(vni)
-                .matchIPSrc(IpPrefix.valueOf(cidr))
-                .matchIPDst(vmIp.toIpPrefix());
-        tBuilder.extension(buildExtension(deviceService, deviceId, hostIp), deviceId)
-                .setOutput(nodeService.tunnelPort(deviceId).get());
+                .matchIPSrc(IpPrefix.valueOf(subNetCidr))
+                .matchEthDst(Constants.DEFAULT_GATEWAY_MAC);
+        tBuilder.setOutput(PortNumber.CONTROLLER);
 
-        ForwardingObjective fo = DefaultForwardingObjective.builder()
-                .withSelector(sBuilder.build())
-                .withTreatment(tBuilder.build())
-                .withPriority(EW_ROUTING_RULE_PRIORITY)
-                .withFlag(ForwardingObjective.Flag.SPECIFIC)
-                .fromApp(appId)
-                .add();
-
-        flowObjectiveService.forward(deviceId, fo);
+        gatewayService.getGatewayDeviceIds().forEach(deviceId ->
+                RulePopulatorUtil.setRule(flowObjectiveService, appId, deviceId, sBuilder.build(),
+                        tBuilder.build(), ForwardingObjective.Flag.VERSATILE, ROUTING_RULE_PRIORITY, install));
     }
 
-    private void populateRoutingRulestoSameNode(Ip4Address vmIp, MacAddress vmMac,
-                                                PortNumber port, DeviceId deviceId, long vni,
-                                                String cidr) {
+    private void setGatewayIcmpRule(Ip4Address gatewayIp, DeviceId deviceId, boolean install) {
         TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
         TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
 
-        // FIXME: we need to check the VNI of the dest IP also just in case...
         sBuilder.matchEthType(Ethernet.TYPE_IPV4)
-                .matchIPDst(vmIp.toIpPrefix())
-                .matchIPSrc(IpPrefix.valueOf(cidr))
-                .matchTunnelId(vni);
+                .matchIPProtocol(IPv4.PROTOCOL_ICMP)
+                .matchIPDst(gatewayIp.toIpPrefix());
 
-        tBuilder.setEthDst(vmMac)
-                .setOutput(port);
+        tBuilder.setOutput(PortNumber.CONTROLLER);
 
-        ForwardingObjective fo = DefaultForwardingObjective.builder()
-                .withSelector(sBuilder.build())
-                .withTreatment(tBuilder.build())
-                .withPriority(EW_ROUTING_RULE_PRIORITY)
-                .withFlag(ForwardingObjective.Flag.SPECIFIC)
-                .fromApp(appId)
-                .add();
-
-        flowObjectiveService.forward(deviceId, fo);
+        RulePopulatorUtil.setRule(flowObjectiveService, appId, deviceId, sBuilder.build(),
+                tBuilder.build(), ForwardingObjective.Flag.VERSATILE, GATEWAY_ICMP_PRIORITY, install);
     }
 
-    private void reloadRoutingRules() {
-        eventExecutor.execute(() -> openstackService.ports().stream()
-                .filter(osPort -> osPort.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE))
-                .forEach(osPort -> {
-                    OpenstackRouter osRouter = openstackRouter(osPort.deviceId());
+    private void setForwardingRulesForEastWestRouting(OpenstackRouter router, OpenstackSubnet subnetAdded,
+                                                      boolean install) {
 
-                    setGatewayIcmp(Ip4Address.valueOf(openstackService
-                            .subnet(osPort.fixedIps().keySet().stream().findAny().get()).gatewayIp()));
+        Set<OpenstackSubnet> subnets = routableSubNets(router.id());
 
-                    setRoutes(osRouter, Optional.empty());
-                    if (osRouter.gatewayExternalInfo().externalFixedIps().size() > 0) {
-                        String subnetId = osPort.fixedIps().keySet().stream().findFirst().get();
-                        setExternalConnection(osRouter, subnetId);
+        Set<Host> hosts = Tools.stream(hostService.getHosts())
+                .filter(h -> getVni(h).equals(openstackService.network(subnetAdded.networkId()).segmentId()))
+                .collect(Collectors.toSet());
+
+        subnets.stream()
+                .filter(subnet -> !subnet.id().equals(subnetAdded.id()))
+                .forEach(subnet -> getHosts(subnet)
+                        .forEach(h -> setForwardingRulesAmongHostsInDifferentCnodes(h, hosts, install)));
+    }
+
+    private void setForwardingRulesAmongHostsInDifferentCnodes(Host host, Set<Host> remoteHosts, boolean install) {
+        Ip4Address localVmIp = getIp(host);
+        DeviceId localDeviceId = host.location().deviceId();
+        Optional<IpAddress> localDataIp = nodeService.dataIp(localDeviceId);
+
+        if (!localDataIp.isPresent()) {
+            log.debug("Failed to get data IP for device {}",
+                    host.location().deviceId());
+            return;
+        }
+
+        remoteHosts.stream()
+                .filter(remoteHost -> !host.location().deviceId().equals(remoteHost.location().deviceId()))
+                .forEach(remoteVm -> {
+                    Optional<IpAddress> remoteDataIp = nodeService.dataIp(remoteVm.location().deviceId());
+                    if (remoteDataIp.isPresent()) {
+                        setVxLanFlowRule(getVni(remoteVm),
+                                localDeviceId,
+                                remoteDataIp.get().getIp4Address(),
+                                getIp(remoteVm), install);
+
+                        setVxLanFlowRule(getVni(host),
+                                remoteVm.location().deviceId(),
+                                localDataIp.get().getIp4Address(),
+                                localVmIp, install);
                     }
-                }));
+                });
     }
 
-    @Override
-    protected void hostDetected(Host host) {
-        String osNetId = host.annotations().value(NETWORK_ID);
-        String osSubNetId = host.annotations().value(SUBNET_ID);
-        Optional<OpenstackPort> routerIface = routerIfacePort(osNetId, osSubNetId);
-        if (!routerIface.isPresent()) {
+    private void setVxLanFlowRule(String vni, DeviceId deviceId, Ip4Address remoteIp,
+                                  Ip4Address vmIp, boolean install) {
+        Optional<PortNumber> tunnelPort = nodeService.tunnelPort(deviceId);
+        if (!tunnelPort.isPresent()) {
+            log.warn("Failed to get tunnel port from {}", deviceId);
             return;
         }
-        eventExecutor.execute(() -> setRoutes(
-                openstackRouter(routerIface.get().deviceId()),
-                Optional.of(host)));
+
+        TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
+        TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
+
+        sBuilder.matchEthType(Ethernet.TYPE_IPV4)
+                .matchTunnelId(Long.parseLong(vni))
+                .matchIPDst(vmIp.toIpPrefix());
+        tBuilder.extension(buildExtension(deviceService, deviceId, remoteIp), deviceId)
+                .setOutput(tunnelPort.get());
+
+        RulePopulatorUtil.setRule(flowObjectiveService, appId, deviceId, sBuilder.build(),
+                tBuilder.build(), ForwardingObjective.Flag.SPECIFIC, SWITCHING_RULE_PRIORITY, install);
     }
 
-    @Override
-    protected void hostRemoved(Host host) {
-        String osNetId = host.annotations().value(NETWORK_ID);
-        String osSubNetId = host.annotations().value(SUBNET_ID);
-        Optional<OpenstackPort> routerIface = routerIfacePort(osNetId, osSubNetId);
-        if (!routerIface.isPresent()) {
-            return;
-        }
-        Set<OpenstackSubnet> routableSubNets = routableSubNets(routerIface.get().deviceId());
-        eventExecutor.execute(() -> removeRoutingRules(host, routableSubNets));
+
+    private OpenstackRouter openstackRouter(String routerId) {
+        return openstackService.routers().stream().filter(r ->
+                r.id().equals(routerId)).iterator().next();
     }
 
     @Override
     public void reinstallVmFlow(Host host) {
-        if (host == null) {
-            hostService.getHosts().forEach(h -> {
-                hostDetected(h);
-                log.info("Re-Install data plane flow of virtual machine {}", h);
-            });
-        } else {
-            hostDetected(host);
-            log.info("Re-Install data plane flow of virtual machine {}", host);
-        }
+        // TODO: implements later
     }
 
     @Override
     public void purgeVmFlow(Host host) {
-        if (host == null) {
-            hostService.getHosts().forEach(h -> {
-                hostRemoved(h);
-                log.info("Purge data plane flow of virtual machine {}", h);
-            });
-        } else {
-            hostRemoved(host);
-            log.info("Purge data plane flow of virtual machine {}", host);
-        }
+        // TODO: implements later
     }
 
     private class InternalNodeListener implements OpenstackNodeListener {
@@ -599,6 +458,7 @@
 
             switch (event.type()) {
                 case COMPLETE:
+                case INCOMPLETE:
                     log.info("COMPLETE node {} detected", node.hostname());
                     eventExecutor.execute(() -> {
                         if (node.type() == GATEWAY) {
@@ -609,23 +469,13 @@
                                     .build();
                             gatewayService.addGatewayNode(gnode);
                         }
-                        reloadRoutingRules();
                     });
+                    openstackService.routers().stream()
+                            .forEach(router -> routableSubNets(router.id()).stream()
+                                        .forEach(subnet -> handleRouterInterfaces(router, subnet)));
                     break;
                 case INIT:
                 case DEVICE_CREATED:
-                case INCOMPLETE:
-                    eventExecutor.execute(() -> {
-                        if (node.type() == GATEWAY) {
-                            GatewayNode gnode = GatewayNode.builder()
-                                    .gatewayDeviceId(node.intBridge())
-                                    .dataIpAddress(node.dataIp().getIp4Address())
-                                    .uplinkIntf(node.externalPortName().get())
-                                    .build();
-                            gatewayService.deleteGatewayNode(gnode);
-                        }
-                        reloadRoutingRules();
-                    });
                 default:
                     break;
             }
