Cleanup of Lisp in VPP renderer
[groupbasedpolicy.git] / renderers / vpp / src / main / java / org / opendaylight / groupbasedpolicy / renderer / vpp / lisp / loopback / LoopbackManager.java
index ad4f91d811ffad175678f5f0a6bd2b64b783bb08..cd412a51e44eb9d90d93a1a5e0b0450dacdaf995 100644 (file)
 
 package org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.loopback;
 
-import javax.annotation.Nonnull;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.HashBasedTable;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Table;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 import org.apache.commons.lang3.tuple.Pair;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.LoopbackCommand;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.LoopbackCommandWrapper;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.ProxyRangeCommand;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.UnnumberedInterfaceCommand;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.lisp.AbstractLispCommand;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.lisp.LispCommandWrapper;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.LispStateCommandExecutor;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.exception.LispConfigCommandFailedException;
-import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.exception.LispHelperArgumentException;
-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.SubnetState;
-import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.states.VrfHolder;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.exception.LispArgumentException;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.flat.overlay.FlatOverlayManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.mappers.NeutronTenantToVniMapper;
-import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.mappers.SubnetUuidToGbpSubnetMapper;
 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.util.GbpNetconfTransaction;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.LispUtil;
-import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
 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.Interface;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder;
 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.lisp.address.types.rev151105.Ipv4PrefixAfi;
-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.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.GbpSubnet;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170801.gpe.entry.table.grouping.gpe.entry.table.GpeEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170801.gpe.entry.table.grouping.gpe.entry.table.gpe.entry.RemoteEid;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.unnumbered.interfaces.rev170510.InterfaceUnnumberedAugmentation;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.unnumbered.interfaces.rev170510.InterfaceUnnumberedAugmentationBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.unnumbered.interfaces.rev170510.unnumbered.config.attributes.UnnumberedBuilder;
 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.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Preconditions;
-
 /**
  * Created by Shakib Ahmed on 4/26/17.
  */
 public class LoopbackManager {
     private static final Logger LOG = LoggerFactory.getLogger(LoopbackManager.class);
 
-    private ConfigManagerHelper loopbackManagerHelper;
+    private ConfigManagerHelper configManagerHelper;
+    private Table<NodeKey, String, List<String>> unnumberedCache = HashBasedTable.create();
 
-    private HostRelatedInfoContainer hostRelatedInfoContainer = HostRelatedInfoContainer.getInstance();
-    private SubnetUuidToGbpSubnetMapper subnetUuidToGbpSubnetMapper = SubnetUuidToGbpSubnetMapper.getInstance();
     private NeutronTenantToVniMapper neutronTenantToVniMapper = NeutronTenantToVniMapper.getInstance();
 
-    public LoopbackManager(@Nonnull MountedDataBrokerProvider mountedDataBrokerProvider) {
-        this.loopbackManagerHelper = new ConfigManagerHelper(mountedDataBrokerProvider);
-    }
 
-    public void createBviLoopbackIfNeeded(AddressEndpointWithLocation addressEp,
-                                          String bridgeDomainName) {
-        try {
-            EndpointHost endpointHost = loopbackManagerHelper.getEndpointHostInformation(addressEp);
-            long vni = getVni(addressEp.getTenant().getValue());
-            long vrfId = vni;
-            String subnetUuid = loopbackManagerHelper.getSubnet(addressEp);
+    private Map<String, GbpSubnet> GbpSubnetCache = new HashMap<>();
+    private Map<String, List<LoopBackDetails>> loopBackHostnames = new HashMap<>();
 
-            VrfHolder hostVrfHolder = hostRelatedInfoContainer.getVrfStateOfHost(endpointHost.getHostName());
+    private class LoopBackDetails {
+        private LoopbackCommand loopbackCommand;
+        private String hostName;
 
-            if (!hostVrfHolder.hasVrf(vrfId)) {
-                //dummy init for bridge domain case
-                hostVrfHolder.initializeVrfState(vrfId, Constants.DUMMY_PROTOCOL_BRIDGE_DOMAIN);
-            }
+        LoopbackCommand getLoopbackCommand() {
+            return loopbackCommand;
+        }
 
-            SubnetState subnetState = hostVrfHolder.getVrfState(vni)
-                                                                            .getSubnetHolder()
-                                                                            .getSubnetState(subnetUuid);
+        void setLoopbackCommand(LoopbackCommand loopbackCommand) {
+            this.loopbackCommand = loopbackCommand;
+        }
 
-            if (!subnetState.isGwConfigured()) {
-                return;
-            }
+        String getHostName() {
+            return hostName;
+        }
 
-            GbpSubnet gbpSubnetInfo = Preconditions.checkNotNull(getSubnetInfo(subnetUuid),
-                    "Subnet UUID {} hasn't been created yet!", subnetUuid);
+        void setHostName(String hostName) {
+            this.hostName = hostName;
+        }
+    }
 
-            String gwInterfaceName = loopbackManagerHelper.getGatewayInterfaceName(Constants.GW_NAME_PREFIX, subnetUuid);
 
-            LoopbackCommand bviLoopbackCommand = LoopbackCommandWrapper
-                    .bviLoopbackPutCommand(gwInterfaceName, vni, gbpSubnetInfo.getGatewayIp(), gbpSubnetInfo.getCidr(),
-                            bridgeDomainName);
-            createLoopbackInterface(endpointHost.getHostName(), subnetState, bviLoopbackCommand);
-        } catch (LispConfigCommandFailedException e) {
-            LOG.warn("LISP couldn't be configured: {}", e.getMessage());
-        }
+    public LoopbackManager() {
+        this.configManagerHelper = new ConfigManagerHelper();
     }
 
     public void createSimpleLoopbackIfNeeded(AddressEndpointWithLocation addressEp) {
-        try {
+        if (!addressEp.getAddressType().equals(IpPrefixType.class)) {
+            return;
+        }
+        Map<String, String> intfcsByHostname = FlatOverlayManager.resolveIntfcsByHosts(addressEp);
 
-            if (loopbackManagerHelper.isMetadataPort(addressEp)) {
-                return;
-            }
-            String hostName = loopbackManagerHelper.getHostName(addressEp).get();
-            long vni = getVni(addressEp.getTenant().getValue());
-            long vrfId = vni;
-            String subnetUuid = loopbackManagerHelper.getSubnet(addressEp);
-
-            SubnetState stateOfSubnetUuid = hostRelatedInfoContainer
-                                                            .getVrfStateOfHost(hostName)
-                                                            .getVrfState(vrfId).getSubnetHolder()
-                                                            .getSubnetState(subnetUuid);
-
-            GbpSubnet gbpSubnetInfo = Preconditions.checkNotNull(getSubnetInfo(subnetUuid),
-                    "Subnet UUID {} hasn't been created yet!", subnetUuid);
-
-            if (!stateOfSubnetUuid.isGwConfigured()) {
-                String interfaceName = loopbackManagerHelper.getGatewayInterfaceName(Constants.GW_NAME_PREFIX,
-                        subnetUuid);
-                LoopbackCommand simpleLoopbackCommand = LoopbackCommandWrapper
-                        .simpleLoopbackPutCommand(interfaceName, vrfId, gbpSubnetInfo.getGatewayIp(),
-                                gbpSubnetInfo.getCidr());
-                createLoopbackInterface(hostName, stateOfSubnetUuid, simpleLoopbackCommand);
-                addProxyArpRange(hostName, vrfId, gbpSubnetInfo);
-                addGpeEntry(VppIidFactory.getNetconfNodeIid(new NodeId(hostName)), gbpSubnetInfo, vni);
+        intfcsByHostname.forEach((hostname, interfaceName) -> {
+            try {
+                long vni = getVni(addressEp.getTenant().getValue());
+                long vrfId = vni;
+                String subnetUuid = configManagerHelper.getSubnet(addressEp);
+                GbpSubnet gbpSubnetInfo = GbpSubnetCache.get(subnetUuid);
+                String loopIntfcName = Constants.GW_NAME_PREFIX + subnetUuid;
+
+                if (gbpSubnetInfo != null) {
+                    Optional<Interface> optionalLoopback =
+                        GbpNetconfTransaction.read(VppIidFactory.getNetconfNodeIid(new NodeId(hostname)),
+                            LogicalDatastoreType.CONFIGURATION,
+                            VppIidFactory.getInterfaceIID(new InterfaceKey(loopIntfcName)),
+                            GbpNetconfTransaction.RETRY_COUNT);
+                    if (!optionalLoopback.isPresent()) {
+                        LoopbackCommand simpleLoopbackCommand =
+                            LoopbackCommandWrapper.simpleLoopbackPutCommand(loopIntfcName, vrfId,
+                                gbpSubnetInfo.getGatewayIp(), gbpSubnetInfo.getCidr());
+                        if (createLoopbackInterface(hostname, simpleLoopbackCommand)) {
+                            addGpeEntry(VppIidFactory.getNetconfNodeIid(new NodeId(hostname)), gbpSubnetInfo, vni);
+                            addProxyArpRange(hostname, vrfId, gbpSubnetInfo);
+                            if(loopBackHostnames.get(loopIntfcName) == null) {
+                                LoopBackDetails loopBackDetails = new LoopBackDetails();
+                                loopBackDetails.setHostName(hostname);
+                                loopBackDetails.setLoopbackCommand(simpleLoopbackCommand);
+                                loopBackHostnames.put(loopIntfcName, Lists.newArrayList(loopBackDetails));
+                            } else {
+                                LoopBackDetails loopBackDetails = new LoopBackDetails();
+                                loopBackDetails.setHostName(hostname);
+                                loopBackDetails.setLoopbackCommand(simpleLoopbackCommand);
+                                loopBackHostnames.get(loopIntfcName).add(loopBackDetails);
+                            }
+                        }
+                    } else {
+                        LOG.trace("Loopback already present on host: {} skip update for: {} - {} in vrf: {}", hostname,
+                            loopIntfcName, gbpSubnetInfo.getGatewayIp(), vrfId);
+                    }
+                }
+
+
+                if (!addUnnumberedInterface(hostname, interfaceName, loopIntfcName)){
+                    LOG.warn("Failed to add unnumbered for addressEp : {}", addressEp);
+                }
+            } catch (LispConfigCommandFailedException e) {
+                LOG.warn("LISP couldn't be configured: {}", e.getMessage());
             }
+        });
 
-            String gwInterfaceName = stateOfSubnetUuid.getGwInterfaceName();
-            addUnnumberedInterface(addressEp, gwInterfaceName);
-        } catch (LispConfigCommandFailedException e) {
-            LOG.warn("LISP couldn't be configured: {}", e.getMessage());
-        }
-    }
 
-    private void createLoopbackInterface(String hostName,
-                                         SubnetState subnetState,
-                                         LoopbackCommand loopbackCommand) throws LispConfigCommandFailedException {
 
-        if (GbpNetconfTransaction.netconfSyncedWrite(VppIidFactory.getNetconfNodeIid(new NodeId(hostName)),
-                loopbackCommand, GbpNetconfTransaction.RETRY_COUNT)) {
-            subnetState.setGwInterfaceName(loopbackCommand.getName());
-        } else {
-            throw new LispConfigCommandFailedException("BVI could not be created for "
-                    + hostName + " and bridge domain " + loopbackCommand.getBridgeDomain());
-        }
     }
 
-    public void handleEndpointDelete(AddressEndpointWithLocation addressEp) {
+    private boolean createLoopbackInterface(String hostName, LoopbackCommand loopbackCommand){
 
-        if (loopbackManagerHelper.isMetadataPort(addressEp)) {
-            return;
-        }
-        String hostName = loopbackManagerHelper.getHostName(addressEp).get();
-        String portSubnetUuid = loopbackManagerHelper.getSubnet(addressEp);
-        long vrfId = getVni(addressEp.getTenant().getValue());
-        SubnetState subnetStateForSubnetUuid = hostRelatedInfoContainer
-                                                        .getVrfStateOfHost(hostName)
-                                                        .getVrfState(vrfId)
-                                                        .getSubnetHolder()
-                                                        .getSubnetState(portSubnetUuid);
-
-        if (!subnetStateForSubnetUuid.hasIpsInSubnet()) {
-            String gwInterfaceName = subnetStateForSubnetUuid.getGwInterfaceName();
-            GbpSubnet gbpSubnetInfo = Preconditions.checkNotNull(subnetUuidToGbpSubnetMapper.getSubnetInfo(portSubnetUuid),
-                    "Invalid port!");
-            long vni = getVni(addressEp.getTenant().getValue());
-            try {
-                InstanceIdentifier<Node> iid = VppIidFactory.getNetconfNodeIid(new NodeId(hostName));
-                deleteSpecificLoopback(iid, gwInterfaceName);
-                deleteProxyArpRange(hostName, vni, gbpSubnetInfo);
-                deleteGpeEntry(iid, Constants.GPE_ENTRY_PREFIX + gbpSubnetInfo.getId() + "_1");
-                deleteGpeEntry(iid, Constants.GPE_ENTRY_PREFIX + gbpSubnetInfo.getId() + "_2");
-                hostRelatedInfoContainer.getVrfStateOfHost(hostName)
-                        .getVrfState(vrfId)
-                        .getSubnetHolder()
-                        .removeSubnetState(portSubnetUuid);
-            } catch (LispConfigCommandFailedException e) {
-                LOG.warn("Loopback not deleted properly: {}", e.getMessage());
-            }
-        }
+        return GbpNetconfTransaction.netconfSyncedWrite(VppIidFactory.getNetconfNodeIid(new NodeId(hostName)),
+                loopbackCommand, GbpNetconfTransaction.RETRY_COUNT);
     }
 
-    private void deleteSpecificLoopback(InstanceIdentifier<Node> nodeIid, String interfaceName) throws LispConfigCommandFailedException {
-        if (!GbpNetconfTransaction.netconfSyncedDelete(nodeIid,
-                VppIidFactory.getInterfaceIID(new InterfaceKey(interfaceName)), GbpNetconfTransaction.RETRY_COUNT)) {
-            throw new LispConfigCommandFailedException("Failed to delete Loopback interface!");
-        } else {
-            LOG.debug("Deleted loopback interface!");
+    private boolean deleteSpecificLoopback(InstanceIdentifier<Node> nodeIid, String loopbackName) {
+        LOG.trace("deleteSpecificLoopback -> nodeiid: {}, loopbackInterface: {}", nodeIid, loopbackName);
+        if (unnumberedCache.get(new NodeKey(nodeIid.firstKeyOf(Node.class)), loopbackName) != null) {
+            unnumberedCache.get(new NodeKey(nodeIid.firstKeyOf(Node.class)), loopbackName).forEach(intfc -> {
+                if (GbpNetconfTransaction.netconfSyncedDelete(nodeIid,
+                    VppIidFactory.getUnnumberedIid(new InterfaceKey(intfc)), GbpNetconfTransaction.RETRY_COUNT)) {
+                    unnumberedCache.remove(new NodeKey(nodeIid.firstKeyOf(Node.class)), loopbackName);
+                }
+            });
         }
+        return GbpNetconfTransaction.netconfSyncedDelete(nodeIid,
+                VppIidFactory.getInterfaceIID(new InterfaceKey(loopbackName)), GbpNetconfTransaction.RETRY_COUNT);
     }
 
     private void addProxyArpRange(String hostName,
@@ -212,10 +184,8 @@ public class LoopbackManager {
 
         Pair<Ipv4Address, Ipv4Address> startAndEndAddress = IpAddressUtil.getStartAndEndIp(subnetPrefix);
 
-        if (!putArpRangesCommand(VppIidFactory.getNetconfNodeIid(new NodeId(hostName)),
-                vrf,
-                startAndEndAddress.getLeft(),
-                startAndEndAddress.getRight())) {
+        if (!putArpRangesCommand(VppIidFactory.getNetconfNodeIid(new NodeId(hostName)), vrf,
+            startAndEndAddress.getLeft(), startAndEndAddress.getRight())) {
             throw new LispConfigCommandFailedException("Proxy arp configuration failed for subnet uuid: " +
                     gbpSubnetInfo.getId() + "!");
         } else {
@@ -224,9 +194,7 @@ public class LoopbackManager {
         }
     }
 
-    private void deleteProxyArpRange(String hostName,
-                                     long vrf,
-                                     GbpSubnet gbpSubnetInfo) throws LispConfigCommandFailedException {
+    private boolean deleteProxyArpRange(String hostName, long vrf, GbpSubnet gbpSubnetInfo) {
         Ipv4Prefix subnetPrefix = gbpSubnetInfo.getCidr().getIpv4Prefix();
 
         Preconditions.checkNotNull(subnetPrefix, "Subnet CIDR found to be null for "
@@ -234,16 +202,8 @@ public class LoopbackManager {
 
         Pair<Ipv4Address, Ipv4Address> startAndEndAddress = IpAddressUtil.getStartAndEndIp(subnetPrefix);
 
-        if (!deleteArpRangesCommand(VppIidFactory.getNetconfNodeIid(new NodeId(hostName)),
-                vrf,
-                startAndEndAddress.getLeft(),
-                startAndEndAddress.getRight())) {
-            throw new LispConfigCommandFailedException("Proxy arp configuration failed for subnet uuid: " +
-                    gbpSubnetInfo.getId() + "!");
-        } else {
-            LOG.debug("Removed proxy arp for range {} to {} on node : {}!", startAndEndAddress.getLeft(),
-                    startAndEndAddress.getRight(), hostName);
-        }
+        return (deleteArpRangesCommand(VppIidFactory.getNetconfNodeIid(new NodeId(hostName)), vrf,
+            startAndEndAddress.getLeft(), startAndEndAddress.getRight()));
     }
 
     private boolean putArpRangesCommand(InstanceIdentifier<Node> iid, long vrf, Ipv4Address start, Ipv4Address end) {
@@ -267,50 +227,61 @@ public class LoopbackManager {
         return GbpNetconfTransaction.netconfSyncedDelete(iid, builder.build(), GbpNetconfTransaction.RETRY_COUNT);
     }
 
-    private void addUnnumberedInterface(AddressEndpointWithLocation addressEp, String loopbackName) throws LispConfigCommandFailedException {
-        ExternalLocationCase loc = ConfigManagerHelper.resolveAndValidateLocation(addressEp);
-        InstanceIdentifier<Node> nodeIid = (InstanceIdentifier<Node>) loc.getExternalNodeMountPoint();
-        String neutronInterfaceName = loopbackManagerHelper.getInterfaceName(addressEp).get();
-        if (putUnnumberedInterface(nodeIid, neutronInterfaceName, loopbackName)) {
-            LOG.debug("Added Interface {} as unnumberd for {}", loopbackName, neutronInterfaceName);
-        } else {
-            throw new LispConfigCommandFailedException("Unnumbered configuration failed for " +
-                    neutronInterfaceName + " - " + loopbackName);
+    private boolean addUnnumberedInterface(String hostname, String neutronInterfaceName, String loopbackName) {
+        InstanceIdentifier<Node> nodeIid = VppIidFactory.getNetconfNodeIid(new NodeId(hostname));
+        if (neutronInterfaceName.equalsIgnoreCase(loopbackName)) {
+            LOG.trace("No need to configure unnumbered for loopback: {} on host: {}. skip processing.", loopbackName,
+                neutronInterfaceName);
+            return true;
+        }
+        LOG.trace("Adding unnumbered configuration hostname: {}, interface: {} use : {}", hostname,
+            neutronInterfaceName, loopbackName);
+        boolean unnumberWritten = putUnnumberedInterface(nodeIid, neutronInterfaceName, loopbackName);
+        if (unnumberWritten) {
+            if (unnumberedCache.get(nodeIid.firstKeyOf(Node.class), loopbackName) != null) {
+                unnumberedCache.get(nodeIid.firstKeyOf(Node.class), loopbackName).add(neutronInterfaceName);
+            } else {
+                unnumberedCache.put(nodeIid.firstKeyOf(Node.class), loopbackName,
+                    Lists.newArrayList(neutronInterfaceName));
+            }
+            LOG.debug("Added Interface {} as unnumbered for {}", loopbackName, neutronInterfaceName);
         }
+        return unnumberWritten;
     }
 
-    private boolean putUnnumberedInterface(InstanceIdentifier<Node> iid, String interfaceFor, String interfaceWith) {
-        UnnumberedBuilder unnumberedBuilder = new UnnumberedBuilder();
-        unnumberedBuilder.setUse(interfaceWith);
-        InstanceIdentifier<Interface> interfaceIid = VppIidFactory.getInterfaceIID(new InterfaceKey(interfaceFor));
-        InterfaceUnnumberedAugmentationBuilder augBuilder = new InterfaceUnnumberedAugmentationBuilder();
-        augBuilder.setUnnumbered(unnumberedBuilder.build());
-        InterfaceBuilder interfaceBuilder = new InterfaceBuilder().setKey(new InterfaceKey(interfaceFor));
-        interfaceBuilder.addAugmentation(InterfaceUnnumberedAugmentation.class, augBuilder.build());
-        return GbpNetconfTransaction.netconfSyncedMerge(iid, interfaceIid, interfaceBuilder.build(),
-                GbpNetconfTransaction.RETRY_COUNT);
+    private boolean putUnnumberedInterface(InstanceIdentifier<Node> iid, String interfaceName, String useInterface) {
+        UnnumberedInterfaceCommand unnumberedCommand =
+            UnnumberedInterfaceCommand.builder()
+                .setOperation(General.Operations.MERGE)
+                .setUseInterface(useInterface)
+                .setInterfaceName(interfaceName)
+                .build();
+        return GbpNetconfTransaction.netconfSyncedWrite(iid, unnumberedCommand, GbpNetconfTransaction.RETRY_COUNT);
     }
 
     private void addGpeEntry(InstanceIdentifier<Node> iid, GbpSubnet gbpSubnetInfo, long vni) {
+        LOG.trace("addGpeEntry called. iid: {}, GbpSubnet: {}, vni: {}", iid, gbpSubnetInfo, vni);
         try {
-            Pair<Ipv4Prefix, Ipv4Prefix> delegatingSubnets = IpAddressUtil
-                    .getSmallerSubnet(gbpSubnetInfo.getCidr().getIpv4Prefix());
+            Pair<Ipv4Prefix, Ipv4Prefix> delegatingSubnets =
+                IpAddressUtil.getSmallerSubnet(gbpSubnetInfo.getCidr().getIpv4Prefix());
 
-            RemoteEid firstREid = LispUtil.toRemoteEid(LispUtil.toLispIpv4Prefix(delegatingSubnets.getLeft()),
-                    vni,
-                    Ipv4PrefixAfi.class);
-            putGpeEntry(iid, Constants.GPE_ENTRY_PREFIX + gbpSubnetInfo.getId() + "_1", firstREid, vni, vni);
+            RemoteEid firstREid =
+                LispUtil.toRemoteEid(LispUtil.toLispIpv4Prefix(delegatingSubnets.getLeft()), vni, Ipv4PrefixAfi.class);
+            if (!putGpeEntry(iid, Constants.GPE_ENTRY_PREFIX + gbpSubnetInfo.getId() + "_1", firstREid, vni, vni)) {
+                LOG.warn("Failed to write GPE entry: {}", Constants.GPE_ENTRY_PREFIX + gbpSubnetInfo.getId() + "_1");
+            }
 
             if (delegatingSubnets.getLeft().equals(delegatingSubnets.getRight())) {
                 return;
             }
 
-            RemoteEid secondREid = LispUtil.toRemoteEid(LispUtil.toLispIpv4Prefix(delegatingSubnets.getRight()),
-                    vni,
-                    Ipv4PrefixAfi.class);
+            RemoteEid secondREid =
+                LispUtil.toRemoteEid(LispUtil.toLispIpv4Prefix(delegatingSubnets.getRight()), vni, Ipv4PrefixAfi.class);
 
-            putGpeEntry(iid, Constants.GPE_ENTRY_PREFIX + gbpSubnetInfo.getId() + "_2", secondREid, vni, vni);
-        } catch (LispHelperArgumentException e) {
+            if (!putGpeEntry(iid, Constants.GPE_ENTRY_PREFIX + gbpSubnetInfo.getId() + "_2", secondREid, vni, vni)) {
+                LOG.warn("Failed to write GPE entry: {}", Constants.GPE_ENTRY_PREFIX + gbpSubnetInfo.getId() + "_2");
+            }
+        } catch (LispArgumentException e) {
             e.printStackTrace();
         }
     }
@@ -331,7 +302,51 @@ public class LoopbackManager {
         return neutronTenantToVniMapper.getVni(tenantUuid);
     }
 
-    private GbpSubnet getSubnetInfo(String subnetUuid) {
-        return subnetUuidToGbpSubnetMapper.getSubnetInfo(subnetUuid);
+
+    public void gbpSubnetCreated(String subnetUuid, GbpSubnet subnetInfo) {
+        GbpSubnetCache.put(subnetUuid, subnetInfo);
+    }
+
+    public void gbpSubnetdeleted(String subnetUuid) {
+        LOG.trace("gbpSubnetdeleted -> subnetUuid:{}", subnetUuid);
+        GbpSubnet gbpSubnet = GbpSubnetCache.get(subnetUuid);
+        String loopIntfcName = Constants.GW_NAME_PREFIX + subnetUuid;
+        List<LoopBackDetails> loopBackDetails = loopBackHostnames.get(loopIntfcName);
+        if (loopBackDetails != null) {
+            loopBackDetails.forEach(loopbackDetail -> {
+
+                InstanceIdentifier<Node> iid =
+                    VppIidFactory.getNetconfNodeIid(new NodeId(loopbackDetail.getHostName()));
+
+                if (deleteSpecificLoopback(iid, loopIntfcName)) {
+                    if (!deleteProxyArpRange(loopbackDetail.getHostName(),
+                        loopbackDetail.getLoopbackCommand().getVrfId(), gbpSubnet)) {
+                        LOG.warn("Failed to delete ProxyArpRange: {} on host: {}", gbpSubnet.getAllocationPools(),
+                            loopbackDetail.getHostName());
+                    }
+
+                    if (!deleteGpeEntry(iid, Constants.GPE_ENTRY_PREFIX + gbpSubnet.getId() + "_1")) {
+                        LOG.warn("Failed to delete gpeEntry: {} on host: {}",
+                            Constants.GPE_ENTRY_PREFIX + gbpSubnet.getId() + "_1", loopbackDetail.getHostName());
+                    }
+                    if (!deleteGpeEntry(iid, Constants.GPE_ENTRY_PREFIX + gbpSubnet.getId() + "_2")) {
+                        LOG.warn("Failed to delete gpeEntry: {} on host: {}",
+                            Constants.GPE_ENTRY_PREFIX + gbpSubnet.getId() + "_2", loopbackDetail.getHostName());
+                    }
+                    if (!deleteGpeFeatureData(loopbackDetail.getHostName())) {
+                        LOG.warn("Failed to delete gpe configuration: {} on host: {}", loopbackDetail.getHostName());
+                    }
+
+                } else {
+                    LOG.warn("Failed to delete loopback: {} on host: {}", loopIntfcName, loopbackDetail.getHostName());
+                }
+            });
+        }
+        GbpSubnetCache.remove(subnetUuid);
+    }
+
+    private boolean deleteGpeFeatureData(String hostname) {
+        return GbpNetconfTransaction.netconfSyncedDelete(VppIidFactory.getNetconfNodeIid(new NodeId(hostname)),
+            VppIidFactory.getGpeFeatureDataIid(), GbpNetconfTransaction.RETRY_COUNT);
     }
 }