Fixes for DVR
[groupbasedpolicy.git] / renderers / vpp / src / main / java / org / opendaylight / groupbasedpolicy / renderer / vpp / lisp / flat / overlay / FlatOverlayManager.java
index 997513fa7777139130707c728e3616a9c49cad31..0ed93636db71742edde7d6317b57f5567541a550 100644 (file)
@@ -8,26 +8,27 @@
 
 package org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.flat.overlay;
 
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 import javax.annotation.Nonnull;
 
+import org.apache.commons.net.util.SubnetUtils;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.StaticArpCommand;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.VppPathMapper;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.EndpointHost;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.HostRelatedInfoContainer;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.states.PhysicalInterfaces;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.states.PortInterfaces;
-import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.states.PortRouteState;
-import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.states.SubnetState;
-import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.states.VrfHolder;
-import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.states.VrfState;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.mappers.NeutronTenantToVniMapper;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.util.ConfigManagerHelper;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.util.Constants;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.util.IpAddressUtil;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.listener.VppEndpointListener;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.routing.RoutingManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.GbpNetconfTransaction;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General;
@@ -39,18 +40,28 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.routing.protocols.RoutingProtocol;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.vpp.routing.rev170917.VniReference;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.child.endpoints.ChildEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.IpPrefixType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.Config;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes._interface.type.choice.TapCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpointKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.Routing;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.RoutingBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
 public class FlatOverlayManager {
     private static final Logger LOG = LoggerFactory.getLogger(FlatOverlayManager.class);
 
@@ -59,107 +70,24 @@ public class FlatOverlayManager {
 
     private NeutronTenantToVniMapper neutronTenantToVniMapper = NeutronTenantToVniMapper.getInstance();
     private HostRelatedInfoContainer hostRelatedInfoContainer = HostRelatedInfoContainer.getInstance();
+    // Node ID, VRF ID, route count
+    private Map<String, Map<Long, Long>> vrfsByHostname = new HashMap<>();
 
     private StaticRoutingHelper staticRoutingHelper;
+    private VppEndpointListener vppEndpointListener;
 
     public FlatOverlayManager(@Nonnull DataBroker dataBroker,
-                              @Nonnull MountedDataBrokerProvider mountedDataBrokerProvider) {
+                              @Nonnull MountedDataBrokerProvider mountedDataBrokerProvider,
+                              @Nonnull VppEndpointListener vppEndpointListener) {
         this.overlayHelper = new ConfigManagerHelper(mountedDataBrokerProvider);
         staticRoutingHelper = new StaticRoutingHelper();
         this.dataBroker = dataBroker;
+        this.vppEndpointListener = vppEndpointListener;
     }
 
     public void configureEndpointForFlatOverlay(AddressEndpointWithLocation addressEp) {
-        if (!overlayHelper.hasRelativeLocations(addressEp)) {
-            configureInterfaceForFlatOverlay(addressEp);
-            addStaticArp(addressEp);
-            addStaticRoute(addressEp);
-        } else {
-            Ipv4Address metadataIp = overlayHelper.getInterfaceIp(addressEp);
-            Ipv4Prefix metadataIpPrefix = overlayHelper.getInterfaceIpAsPrefix(addressEp);
-            addressEp.getRelativeLocations().getExternalLocation().forEach(externalLocation -> {
-                String hostName = overlayHelper.getHostName(externalLocation).get();
-                String metadataInterfaceName = overlayHelper.getInterfaceName(externalLocation).get();
-
-                long vrf = getVni(addressEp.getTenant().getValue());
-
-                String metadataSubnetUuid = Constants.METADATA_SUBNET_UUID;
-
-                PortInterfaces portInterfacesOfHost = hostRelatedInfoContainer.getPortInterfaceStateOfHost(hostName);
-
-                if (!portInterfacesOfHost.isInterfaceConfiguredForMetadata(metadataInterfaceName)) {
-                    addInterfaceInVrf(hostName, metadataInterfaceName, vrf);
-                    String physicalAddress = resolvePhysicalAddress(hostName, metadataInterfaceName);
-                    addStaticArp(hostName, metadataInterfaceName, physicalAddress, metadataIp);
-                    addStaticRoute(hostName, vrf, metadataSubnetUuid, metadataIp, metadataIpPrefix,
-                            metadataInterfaceName);
-                    portInterfacesOfHost.addInterfaceInMetadataInterfaceSet(metadataInterfaceName);
-                }
-            });
-        }
-    }
-
-    private String resolvePhysicalAddress(String hostName, String metadataInterfaceName) {
-        String physAddress = null;
-        Optional<Config> configOptional =
-            DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, VppIidFactory.getVppRendererConfig(),
-                dataBroker.newReadOnlyTransaction());
-        if (configOptional.isPresent() && configOptional.get().getVppEndpoint() != null) {
-            java.util.Optional<VppEndpoint> vppEndpointOptional = configOptional.get().getVppEndpoint().stream()
-                    .filter(vppEndpoint -> vppEndpoint.getVppNodeId().getValue().equals(hostName))
-                    .filter(vppEndpoint -> vppEndpoint.getVppInterfaceName().equals(metadataInterfaceName))
-                    .findFirst();
-            if (vppEndpointOptional.isPresent() && vppEndpointOptional.get()
-                .getInterfaceTypeChoice() instanceof TapCase) {
-                TapCase tapCase = (TapCase) vppEndpointOptional.get().getInterfaceTypeChoice();
-                physAddress = tapCase.getPhysicalAddress().getValue();
-                LOG.trace("Resolved PhysicalAddress : {} for metadataInterfaceName: {}, on node: {}", physAddress
-                    , metadataInterfaceName, hostName);
-            } else {
-                LOG.warn("PhysicalAddress was not resolved for metadataInterfaceName: {}, on node: {}",
-                    metadataInterfaceName, hostName);
-            }
-        }
-
-        return physAddress;
-    }
-
-    public void handleEndpointDeleteForFlatOverlay(AddressEndpointWithLocation addressEp) {
-        if (overlayHelper.hasRelativeLocations(addressEp)) {
-            // okay to ignore
-            // routes will be deleted on interface delete
-            return;
-        }
-        deleteStaticRoute(addressEp);
-    }
-
-    public void handleInterfaceDeleteForFlatOverlay(VppEndpoint vppEndpoint) {
-        String hostName = vppEndpoint.getVppNodeId().getValue();
-        String interfaceName = vppEndpoint.getVppInterfaceName();
-        LOG.trace("handleInterfaceDeleteForFlatOverlay: hostname: {}, interfaceName: {}", hostName,interfaceName);
-
-        Preconditions.checkNotNull(hostName, "Hostname cannot be null when deleting Interface");
-        Preconditions.checkNotNull(interfaceName, "InterfaceName cannot be null when deleting Interface");
-
-        staticRoutingHelper.deleteAllRoutesThroughInterface(hostName, interfaceName);
-
-        PortInterfaces portInterfaces = hostRelatedInfoContainer.getPortInterfaceStateOfHost(hostName);
-        portInterfaces.removePortInterface(interfaceName);
-    }
-
-    private void configureInterfaceForFlatOverlay(AddressEndpointWithLocation addressEp) {
-        addInterfaceInVrf(addressEp);
-    }
-
-    private void addInterfaceInVrf(AddressEndpointWithLocation addressEp) {
-        EndpointHost endpointHost = overlayHelper.getEndpointHostInformation(addressEp);
-        long vni = getVni(addressEp.getTenant().getValue());
-        long vrf = vni;
-        Optional<String> interfaceNameOptional = overlayHelper.getInterfaceName(addressEp);
-
-        Preconditions.checkArgument(interfaceNameOptional.isPresent());
-
-        addInterfaceInVrf(endpointHost.getHostName(), interfaceNameOptional.get(), vrf);
+        addStaticRoute(addressEp);
+        addStaticArpAndInfcsToVrf(addressEp);
     }
 
     private void addInterfaceInVrf(String hostName, String interfaceName, long vrf) {
@@ -178,9 +106,7 @@ public class FlatOverlayManager {
         }
     }
 
-    private boolean putVrfInInterface(String hostName,
-                                  String interfaceName,
-                                  Long vrf) {
+    private boolean putVrfInInterface(String hostName, String interfaceName, Long vrf) {
         InstanceIdentifier<Routing> iid = VppIidFactory.getRoutingIid(new InterfaceKey(interfaceName));
         RoutingBuilder builder = new RoutingBuilder();
         builder.setIpv4VrfId(vrf);
@@ -188,45 +114,36 @@ public class FlatOverlayManager {
                 builder.build(), GbpNetconfTransaction.RETRY_COUNT);
     }
 
-    private void addStaticArp(AddressEndpointWithLocation addressEp) {
-        String hostName = overlayHelper.getHostName(addressEp).get();
-        String physicalAddress = overlayHelper.getPhysicalAddress(addressEp);
-        Optional<String> interfaceNameOptional = overlayHelper.getInterfaceName(addressEp);
-
-        Preconditions.checkArgument(interfaceNameOptional.isPresent());
-
-        String interfaceName = interfaceNameOptional.get();
-
-        addStaticArp(hostName, interfaceName, physicalAddress, overlayHelper.getInterfaceIp(addressEp));
-    }
-
-    private void addStaticArp(String hostName,
-                              String interfaceName,
-                              String physicalAddress,
-                              Ipv4Address ipv4Address) {
-        Ipv4AddressNoZone ip = new Ipv4AddressNoZone(ipv4Address);
-        if (physicalAddress == null || physicalAddress.isEmpty()) {
-            LOG.warn("Cannot add static arp for interface {}, ip={}, because physical address is null or empty",
-                interfaceName, ip, physicalAddress);
+    private void addStaticArpAndInfcsToVrf(AddressEndpointWithLocation addressEp) {
+        if (!addressEp.getAddressType().equals(IpPrefixType.class)) {
             return;
         }
-        InterfaceKey interfaceKey = new InterfaceKey(interfaceName);
-        if (!putStaticArp(hostName,
-                             interfaceKey,
-                             new PhysAddress(physicalAddress),
-                             ip)) {
-            LOG.warn("Failed to put static arp with interface {} for ip={} and physical-address={}",
-                    interfaceName, ip, physicalAddress);
-        } else {
-            LOG.debug("Added Static arp ({} {}) in host {} for interface {}", ip, physicalAddress, hostName,
-                    interfaceName);
-        }
+        Map<String, String> intfcsByHostname = resolveIntfcsByHosts(addressEp);
+        ReadOnlyTransaction readTx = dataBroker.newReadOnlyTransaction();
+        Optional<Config> cfg = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
+                VppIidFactory.getVppRendererConfig(), readTx);
+        readTx.close();
+        intfcsByHostname.entrySet().forEach(intfcByHost -> {
+            if (cfg.isPresent() && !cfg.get().getVppEndpoint().isEmpty()) {
+                java.util.Optional<VppEndpoint> foundVpp = cfg.get()
+                    .getVppEndpoint()
+                    .stream()
+                    .filter(vpp -> vpp.getVppInterfaceName().equals(intfcByHost.getValue()))
+                    .findFirst();
+                if (!foundVpp.isPresent()) {
+                    return;
+                }
+                Ipv4Address ipv4 = ConfigManagerHelper.getInterfaceIp(addressEp);
+                putStaticArp(intfcByHost.getKey(), new InterfaceKey(intfcByHost.getValue()),
+                        new PhysAddress(foundVpp.get().getAddress()), new Ipv4AddressNoZone(ipv4));
+                addInterfaceInVrf(intfcByHost.getKey(), intfcByHost.getValue(),
+                        getVni(addressEp.getTenant().getValue()));
+            }
+        });
     }
 
-    private boolean putStaticArp(String hostName,
-                                 InterfaceKey interfaceKey,
-                                 PhysAddress physAddress,
-                                 Ipv4AddressNoZone ip) {
+    private boolean putStaticArp(String hostName, InterfaceKey interfaceKey, PhysAddress physAddress,
+        Ipv4AddressNoZone ip) {
         StaticArpCommand.StaticArpCommandBuilder staticArpCommandBuilder =
             new StaticArpCommand.StaticArpCommandBuilder();
 
@@ -240,128 +157,193 @@ public class FlatOverlayManager {
     }
 
     private void addStaticRoute(AddressEndpointWithLocation addressEp) {
-        String hostName = overlayHelper.getHostName(addressEp).get();
+        //TODO caller method
+        Optional<Long> routeId = routeId(addressEp);
+        if(!routeId.isPresent()) {
+            return;
+        }
+
+        //TODO workaround for interfaces that do not exist anymore
+        List<ChildEndpoint> childs = addressEp.getChildEndpoint();
+        if (childs != null) {
+            for (ChildEndpoint child : childs) {
+                child.getAddress();
+                child.getContextId();
+                VppEndpointKey vppEndpointKey = new VppEndpointKey(child.getAddress(), child.getAddressType(),
+                        child.getContextId(), child.getContextType());
+                ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();
+                Optional<VppEndpoint> vppEp = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
+                        VppIidFactory.getVppRendererConfig().child(VppEndpoint.class, vppEndpointKey), rTx);
+                rTx.close();
+                if (!vppEp.isPresent()) {
+                    LOG.error("Failed to add route for endpoint {}. Interface not created yet.", addressEp);
+                    return;
+                }
+            }
+        }
+        
+        Map<String, String> hostnamesAndIntfcs = resolveIntfcsByHosts(addressEp);
         long vni = getVni(addressEp.getTenant().getValue());
         long vrf = vni;
 
-        String portSubnetUuid = overlayHelper.getSubnet(addressEp);
+        hostnamesAndIntfcs.forEach((hostname, outgoingInterfaceName) -> {
 
-        String outgoingInterfaceName = overlayHelper.getInterfaceName(addressEp).get();
-        Ipv4Address ipWithoutPrefix = overlayHelper.getInterfaceIp(addressEp);
+            Ipv4Address ipWithoutPrefix = ConfigManagerHelper.getInterfaceIp(addressEp);
 
-        if (overlayHelper.isMetadataPort(addressEp)) {
-            //override original port subnet to handle the Absolute location case of address endpoint
-            portSubnetUuid = Constants.METADATA_SUBNET_UUID;
-        }
-
-        Ipv4Prefix ipv4Prefix = overlayHelper.getInterfaceIpAsPrefix(addressEp);
-
-        addStaticRoute(hostName, vrf, portSubnetUuid, ipWithoutPrefix, ipv4Prefix, outgoingInterfaceName);
+            Ipv4Prefix ipv4Prefix = overlayHelper.getInterfaceIpAsPrefix(addressEp);
+            LOG.trace("Adding static route for addressEp: {}", addressEp);
+            addStaticRoute(routeId.get(), hostname, vrf, ipWithoutPrefix, ipv4Prefix, outgoingInterfaceName);
+        });
     }
 
-    private void addStaticRoute(String hostName, long vrfId, String hostIpSubnetUuid,
-                                Ipv4Address ipWithoutPrefix, Ipv4Prefix ipv4Prefix, String outgoingInterfaceName) {
-
-        VrfHolder vrfHolderOfHost = hostRelatedInfoContainer.getVrfStateOfHost(hostName);
-
-        if (!vrfHolderOfHost.hasVrf(vrfId)) {
-            if (!staticRoutingHelper.addRoutingProtocolForVrf(LispUtil.HOSTNAME_TO_IID.apply(hostName), vrfId,
-                    vrfHolderOfHost)) {
-                LOG.warn("Failed to add Routing protocol for host {} and vrf {}!", hostName, vrfId);
+    public static Map<String,String> resolveIntfcsByHosts(AddressEndpointWithLocation addressEp) {
+        Map<String, String> hostnamesAndIntfcs = new HashMap<>();
+        if (addressEp.getRelativeLocations() != null
+            && addressEp.getRelativeLocations().getExternalLocation() != null) {
+            LOG.trace("deleteStaticRoutingEntry -> addresEp locations: {}", addressEp.getRelativeLocations().getExternalLocation());
+            addressEp.getRelativeLocations().getExternalLocation().forEach(externalLocation -> {
+                Optional<String> interfaceOptional =
+                    VppPathMapper.interfacePathToInterfaceName(externalLocation.getExternalNodeConnector());
+                if (interfaceOptional.isPresent()) {
+                    hostnamesAndIntfcs.put(
+                        externalLocation.getExternalNodeMountPoint().firstKeyOf(Node.class).getNodeId().getValue(),
+                        interfaceOptional.get());
+                } else {
+                    LOG.warn("Couldn't resolve interface name for addrEP: {}", addressEp);
+                }
+            });
+        } else if (addressEp.getAbsoluteLocation() != null && addressEp.getAbsoluteLocation().getLocationType() != null
+            && addressEp.getAbsoluteLocation().getLocationType() instanceof ExternalLocationCase) {
+            ExternalLocationCase externalLocationCase =
+                (ExternalLocationCase) addressEp.getAbsoluteLocation().getLocationType();
+            LOG.trace("deleteStaticRoutingEntry -> addresEp location: {}", externalLocationCase);
+            Optional<String> interfaceOptional =
+                VppPathMapper.interfacePathToInterfaceName(externalLocationCase.getExternalNodeConnector());
+            if (interfaceOptional.isPresent()) {
+                hostnamesAndIntfcs.put(
+                    externalLocationCase.getExternalNodeMountPoint().firstKeyOf(Node.class).getNodeId().getValue(),
+                    interfaceOptional.get());
             } else {
+                LOG.warn("Couldn't resolve interface name for addrEP: {}", addressEp);
+            }
+        }
+        return hostnamesAndIntfcs;
+    }
+
+    private boolean addStaticRoute(Long routeId, String hostName, long vrfId, Ipv4Address ipWithoutPrefix,
+            Ipv4Prefix ipv4Prefix, String outgoingInterfaceName) {
+        if (vrfsByHostname.get(hostName) == null || !vrfsByHostname.get(hostName).keySet().contains(vrfId)) {
+            if (staticRoutingHelper.addRoutingProtocolForVrf(LispUtil.HOSTNAME_TO_IID.apply(hostName), vrfId)) {
                 addStaticRouteToPublicInterface(hostName, vrfId);
+                countPlusPlus(hostName, vrfId);
             }
         }
+        if (staticRoutingHelper.addSingleStaticRouteInRoutingProtocol(routeId, hostName, vrfId, ipWithoutPrefix,
+                ipv4Prefix, outgoingInterfaceName, null)) {
+            countPlusPlus(hostName, vrfId);
+            return true;
+        }
+        return false;
+    }
 
-        VrfState vrfStateOfVrfId = vrfHolderOfHost.getVrfState(vrfId);
+    private void countPlusPlus(String hostName, Long vrfId) {
+        if (vrfsByHostname.get(hostName) == null || vrfsByHostname.get(hostName).get(vrfId) == null) {
+            HashMap<Long, Long> newEntry = new HashMap<>();
+            newEntry.put(vrfId, 1L);
+            vrfsByHostname.put(hostName, newEntry);
+        } else {
+            Long count = vrfsByHostname.get(hostName).get(vrfId);
+            HashMap<Long, Long> newEntry = new HashMap<>();
+            newEntry.put(vrfId, count + 1);
+            vrfsByHostname.put(hostName, newEntry);
+        }
+    }
 
-        if (vrfStateOfVrfId.getSubnetHolder().getSubnetState(hostIpSubnetUuid).isIpPresent(ipWithoutPrefix)) {
-            LOG.info("Ip already exists in host {} vrf {} ip {}", hostName, vrfId, ipWithoutPrefix);
-            return;
+    private void countMinusMinus(String hostName, Long vrfId) {
+        if (vrfsByHostname.get(hostName) != null && vrfsByHostname.get(hostName).get(vrfId) != null) {
+            Long count = vrfsByHostname.get(hostName).get(vrfId);
+            HashMap<Long, Long> newEntry = new HashMap<>();
+            newEntry.put(vrfId, count - 1);
+            vrfsByHostname.put(hostName, newEntry);
         }
+    }
 
-        if (!staticRoutingHelper.addSingleStaticRouteInRoutingProtocol(hostName, vrfId, hostIpSubnetUuid,
-                ipWithoutPrefix, ipv4Prefix, outgoingInterfaceName, null)) {
-            LOG.warn("Failed to add routing ({} via {}) in vrf {} in compute host {}!",
-                    ipv4Prefix, outgoingInterfaceName, vrfId, hostName);
-        } else {
-            LOG.debug("Added route ({} via {}) in vrf {} in compute host {}",
-                    ipv4Prefix, outgoingInterfaceName, vrfId, hostName);
+    private Long getRouteCount(String hostName, Long vrfId) {
+        if (vrfsByHostname.get(hostName) != null && vrfsByHostname.get(hostName).get(vrfId) != null) {
+            return vrfsByHostname.get(hostName).get(vrfId);
         }
+        return 0L;
     }
 
     private void addStaticRouteToPublicInterface(String hostName, long vrfId) {
         LOG.trace("addStaticRouteToPublicInterface, hostname: {}, vrfId: {}", hostName, vrfId);
-        Ipv4Address physicalInterfaceIp = hostRelatedInfoContainer
-                .getPhysicalInterfaceState(hostName)
-                .getIp(PhysicalInterfaces.PhysicalInterfaceType.PUBLIC).getIpv4Address();
-        String interfaceName = hostRelatedInfoContainer
-                .getPhysicalInterfaceState(hostName)
-                .getName(PhysicalInterfaces.PhysicalInterfaceType.PUBLIC);
-
+        Ipv4Address physicalInterfaceIp = hostRelatedInfoContainer.getPhysicalInterfaceState(hostName)
+            .getIp(PhysicalInterfaces.PhysicalInterfaceType.PUBLIC)
+            .getIpv4Address();
+        String interfaceName = hostRelatedInfoContainer.getPhysicalInterfaceState(hostName)
+            .getName(PhysicalInterfaces.PhysicalInterfaceType.PUBLIC);
         if (interfaceName != null && !interfaceName.isEmpty()) {
             LOG.trace("Adding Public interface route. hostname: {}, VrfId: {}, Ip: {}, Gw: {}, InterfaceName: {}.",
-                hostName, vrfId, physicalInterfaceIp, null, interfaceName);
-            if (!staticRoutingHelper.addSingleStaticRouteInRoutingProtocol(hostName, vrfId,
-                Constants.PUBLIC_SUBNET_UUID, null, IpAddressUtil.toIpV4Prefix(physicalInterfaceIp),
-                interfaceName, new VniReference(RoutingManager.DEFAULT_TABLE))) {
+                    hostName, vrfId, physicalInterfaceIp, null, interfaceName);
+            if (!staticRoutingHelper.addSingleStaticRouteInRoutingProtocol(0L, hostName, vrfId, physicalInterfaceIp,
+                    IpAddressUtil.toIpV4Prefix(physicalInterfaceIp), interfaceName,
+                    new VniReference(RoutingManager.DEFAULT_TABLE))) {
                 LOG.warn("Failed to add route for physical interface in vrf {} compute host {}", vrfId, hostName);
             } else {
-                LOG.debug("Added route for physical interface {} in vrf {}", interfaceName, vrfId);
+                LOG.debug("addStaticRouteToPublicInterface -> Added route to public intf ({} via {}) in vrf {} in compute host {}",
+                        IpAddressUtil.toIpV4Prefix(physicalInterfaceIp), interfaceName, vrfId, hostName);
             }
         }
     }
 
-    private void deleteStaticRoute(AddressEndpointWithLocation addressEp) {
-        String hostName = overlayHelper.getHostName(addressEp).get();
-        String interfaceName = overlayHelper.getInterfaceName(addressEp).get();
-
-        long vni = getVni(addressEp.getTenant().getValue());
-        long vrfId = vni;
-
-        String ipSubnetUuid = overlayHelper.getSubnet(addressEp);
-
-        if (overlayHelper.isMetadataPort(addressEp)) {
-            //override original port subnet to handle the Absolute location case of address endpoint
-            ipSubnetUuid = Constants.METADATA_SUBNET_UUID;
-        }
-
-        Ipv4Address ipWithoutPrefix = overlayHelper.getInterfaceIp(addressEp);
-
-        PortRouteState portRouteState = hostRelatedInfoContainer
-                                            .getPortInterfaceStateOfHost(hostName)
-                                            .getPortRouteState(interfaceName);
-        if (portRouteState == null) {
-            LOG.warn("Port route state is null, it has been deleted already. Skip delete for addresEp: {}.", addressEp);
-            return;
+    private Optional<Long> routeId(AddressEndpointWithLocation addressEp) {
+        if (!addressEp.getAddressType().equals(IpPrefixType.class) || !addressEp.getAddress().contains("/")) {
+            return Optional.absent();
         }
+        String ipAddress = addressEp.getAddress().split("/")[0];
+        SubnetUtils subnet = new SubnetUtils(addressEp.getAddress());
+        Long routeId = Integer.toUnsignedLong(subnet.getInfo().asInteger(ipAddress));
+        return Optional.of(routeId);
+    }
 
-        SubnetState subnetState = hostRelatedInfoContainer
-                                    .getVrfStateOfHost(hostName)
-                                    .getVrfState(vrfId)
-                                    .getSubnetHolder()
-                                    .getSubnetState(ipSubnetUuid);
-
-        if (!subnetState.isIpPresent(ipWithoutPrefix)) {
-            LOG.debug("Route {} already deleted from vrf {} of host {}", ipWithoutPrefix, vrfId, hostName);
+    public void deleteStaticRoutingEntry(AddressEndpointWithLocation addressEp) {
+        //TODO create
+        Optional<Long> routeId = routeId(addressEp);
+        if(!routeId.isPresent()) {
             return;
         }
+        long vni = getVni(addressEp.getTenant().getValue());
+        long vrfId = vni;
+        Map<String, String> hostnamesAndIntfcs = resolveIntfcsByHosts(addressEp);
+        LOG.trace("deleteStaticRoutingEntry -> addresEp locations: {}", addressEp);
+        hostnamesAndIntfcs.entrySet().forEach(intfcsByHost -> {
+            LOG.trace("deleteStaticRoutingEntry -> Deleting addresEp: {} for interface: {}, on node: {}", addressEp.getKey(), intfcsByHost.getValue(), intfcsByHost.getKey());
+            Ipv4Address ipWithoutPrefix = ConfigManagerHelper.getInterfaceIp(addressEp);
+            if (!staticRoutingHelper.deleteSingleStaticRouteFromRoutingProtocol(intfcsByHost.getKey(), vrfId, routeId.get())) {
+                LOG.warn("Failed to delete route ({} via {}) from vrf {} from host{}", ipWithoutPrefix,
+                    intfcsByHost.getValue(), vrfId, intfcsByHost);
+            } else {
+                LOG.trace("deletedStaticRoutingEntry -> Deleted addresEp: {} for interface: {}, on node: {}", addressEp.getKey(), intfcsByHost.getValue(), intfcsByHost.getKey());
+                countMinusMinus(intfcsByHost.getKey(), vrfId);
+                if (getRouteCount(intfcsByHost.getKey(), vrfId) <= 1) {
+                    LOG.info("deletedStaticRoutingEntry -> Removing route to public int from VRF {}", vrfId);
+                    staticRoutingHelper.deleteSingleStaticRouteFromRoutingProtocol(intfcsByHost.getKey(), vrfId, 0L);
+                    InstanceIdentifier<RoutingProtocol> protocol =
+                            VppIidFactory.getRoutingInstanceIid(StaticRoutingHelper.getRoutingProtocolName(vrfId));
+                    if(GbpNetconfTransaction.netconfSyncedDelete(
+                            VppIidFactory.getNetconfNodeIid(new NodeId(intfcsByHost.getKey())), protocol,
+                            GbpNetconfTransaction.RETRY_COUNT)) {
+                        vrfsByHostname.get(intfcsByHost.getKey()).remove(vrfId);
+                    }
+                }
+                LOG.trace("deleteStaticRoutingEntry -> flushPendingVppEndpoint for addresEp: {}", addressEp);
+                hostRelatedInfoContainer.deleteRouteFromIntfc(intfcsByHost.getKey(), intfcsByHost.getValue(), routeId.get());
+                vppEndpointListener.flushPendingVppEndpoint(intfcsByHost.getKey(), intfcsByHost.getValue());
+                LOG.debug("Delete Static Route ({} via {}) from vrf {} from host {}", ipWithoutPrefix,
+                        intfcsByHost.getValue(), vrfId, intfcsByHost);
+            }
+        });
 
-        long targetRouteId = portRouteState.getRouteIdOfIp(ipWithoutPrefix);
-
-        if (!staticRoutingHelper.deleteSingleStaticRouteFromRoutingProtocol(hostName,
-                                                                            vrfId,
-                                                                            interfaceName,
-                                                                            targetRouteId)) {
-            LOG.warn("Failed to delete route ({} via {}) from vrf {} from host{}",
-                    ipWithoutPrefix, interfaceName, vrfId, hostName);
-
-        } else {
-            portRouteState.removeIp(ipWithoutPrefix);
-            subnetState.removeIp(ipWithoutPrefix);
-            LOG.debug("Delete Static Route ({} via {}) from vrf {} from host {}",
-                    ipWithoutPrefix, interfaceName, vrfId, hostName);
-        }
     }
 
     public long getVni(String tenantUuid) {