Stale MIP FIB/Flow entries present upon deletion of VRRP master 85/88385/2
authorKarthikeyan Krishnan <karthikeyangceb007@gmail.com>
Tue, 10 Mar 2020 09:05:56 +0000 (14:35 +0530)
committerKarthikeyan Krishnan <karthikeyangceb007@gmail.com>
Tue, 10 Mar 2020 10:29:07 +0000 (15:59 +0530)
Issue:
======
This issue is seen when ports are pre-created and VM is booted on that.
In such condition , when VM is deleted , only south bound Interface remove
is received.
When VM which is a VRRP master(holding MIP-IP) was deleted , MIP-IP adj
was not deleted from the config-VpnInterface. Thus leading to issues like
duplicate FIB entry , when VM is booted back.

Solution:
=========
MIP-IP adj delete is handled appropriately when VM is deleted.

Signed-off-by: Karthikeyan Krishnan <karthikeyangceb007@gmail.com>
Change-Id: Ie42ff0eede90433c15b09537b7973842345ab376

fibmanager/api/src/main/java/org/opendaylight/netvirt/fibmanager/api/IFibManager.java
fibmanager/impl/src/main/java/org/opendaylight/netvirt/fibmanager/FibManagerImpl.java
fibmanager/impl/src/main/java/org/opendaylight/netvirt/fibmanager/FibUtil.java
vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/InterfaceStateChangeListener.java
vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnInterfaceManager.java
vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnUtil.java
vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/iplearn/IpMonitorEventListener.java
vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/iplearn/IpMonitorStopTask.java
vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/iplearn/IpMonitoringHandler.java

index 6baba30b54a260e644889d503c85f7855085f76c..0b687463f56f3f172c14e86d08a3f1ee87b4ec5a 100644 (file)
@@ -13,6 +13,7 @@ import com.google.common.util.concurrent.FutureCallback;
 import java.util.List;
 
 import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.genius.infra.Datastore.Configuration;
 import org.opendaylight.genius.infra.TypedWriteTransaction;
@@ -81,6 +82,8 @@ public interface IFibManager {
                                       boolean isVpnFirstEndPoint,
                                       VrfEntry vrfEntry);
 
+    boolean checkFibEntryExist(DataBroker broker, String rd, String prefix, String nextHopIp);
+
     void programDcGwLoadBalancingGroup(Uint64 dpnId,
             String destinationIp, int addRemoveOrUpdate, boolean isTunnelUp,
                                        Class<? extends TunnelTypeBase> tunnelType);
index 9befcc857bd71c86b3bb3dd2a5a59326dc713727..2e668bad84930a40cc5f0833837a267edf5cb800 100755 (executable)
@@ -15,6 +15,7 @@ import java.util.List;
 import java.util.concurrent.TimeUnit;
 import javax.inject.Inject;
 import javax.inject.Singleton;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.genius.infra.Datastore.Configuration;
 import org.opendaylight.genius.infra.TypedWriteTransaction;
@@ -201,6 +202,11 @@ public class FibManagerImpl implements IFibManager {
         vrfEntryListener.removeInterVPNLinkRouteFlows(interVpnLink, vpnName, vrfEntry);
     }
 
+    @Override
+    public boolean checkFibEntryExist(DataBroker broker, String rd, String prefix, String nextHopIp) {
+        return fibUtil.checkFibEntryExist(broker, rd, prefix, nextHopIp);
+    }
+
     @Override
     public void programDcGwLoadBalancingGroup(Uint64 dpnId, String destinationIp,
                                               int addRemoveOrUpdate, boolean isTunnelUp,
index 08a1cb904e46e6d1250a52d0ea4b9b6f62a59343..41ca0e553807d7a75306ea3e23e21fe0ce79737e 100644 (file)
@@ -897,4 +897,20 @@ public class FibUtil {
         }
         return false;
     }
+
+    public static boolean checkFibEntryExist(DataBroker broker, String rd, String prefix, String nextHopIp) {
+        InstanceIdentifier<VrfEntry> vrfEntryId =
+                InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd))
+                        .child(VrfEntry.class, new VrfEntryKey(prefix)).build();
+        Optional<VrfEntry> entry = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
+        if (entry.isPresent()) {
+            List<RoutePaths> paths = entry.get().getRoutePaths();
+            for (RoutePaths path: paths) {
+                if (path.getNexthopAddress().equals(nextHopIp)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
 }
index eb148a9fb6ba9e2078619008719a7250ab4ba03e..1c017946d6cac4609608f068efb2aae54beab5e2 100644 (file)
@@ -38,7 +38,10 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.re
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.Adjacencies;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.Adjacency;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterface;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.vpn._interface.VpnInstanceNames;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -233,6 +236,7 @@ public class InterfaceStateChangeListener
                                                     + " triggered by northbound agent. ignoring.", ifName, vpnName);
                                                 continue;
                                             }
+                                            handleMipAdjRemoval(cfgVpnInterface, vpnName);
                                             final VpnInterfaceOpDataEntry vpnInterface = optVpnInterface.get();
                                             String gwMac = intrf.getPhysAddress() != null ? intrf.getPhysAddress()
                                                 .getValue() : vpnInterface.getGatewayMacAddress();
@@ -342,6 +346,7 @@ public class InterfaceStateChangeListener
                                                         if (optVpnInterface.isPresent()) {
                                                             VpnInterfaceOpDataEntry vpnOpInterface =
                                                                 optVpnInterface.get();
+                                                            handleMipAdjRemoval(vpnIf, vpnName);
                                                             vpnInterfaceManager.processVpnInterfaceDown(dpnId,
                                                                 vpnIf.getName(), ifIndex, update.getPhysAddress()
                                                                 .getValue(), vpnOpInterface, true,
@@ -371,6 +376,29 @@ public class InterfaceStateChangeListener
         }
     }
 
+    private void handleMipAdjRemoval(VpnInterface cfgVpnInterface, String vpnName) {
+        String interfaceName = cfgVpnInterface.getName();
+        Adjacencies adjacencies = cfgVpnInterface.augmentation(Adjacencies.class);
+        if (adjacencies != null) {
+            List<Adjacency> adjacencyList = adjacencies.getAdjacency();
+            if (!adjacencyList.isEmpty()) {
+                for (Adjacency adj : adjacencyList) {
+                    if (adj.getAdjacencyType() != Adjacency.AdjacencyType.PrimaryAdjacency) {
+                        String ipAddress = adj.getIpAddress();
+                        String prefix = ipAddress.split("/")[0];
+                        LearntVpnVipToPort vpnVipToPort = vpnUtil.getLearntVpnVipToPort(vpnName, prefix);
+                        if (vpnVipToPort != null && vpnVipToPort.getPortName().equals(interfaceName)) {
+                            vpnUtil.removeMipAdjacency(vpnName, interfaceName, ipAddress, null);
+                        } else {
+                            LOG.debug("IP {} could be extra-route or learnt-ip on different interface"
+                                    + "than oper-vpn-interface {}", ipAddress, interfaceName);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
     private class PostVpnInterfaceThreadWorker implements FutureCallback<Void> {
         private final String interfaceName;
         private final boolean add;
index 1ce9653b90e937fb0d0d05bf71b8da2e2fac4e17..50466d2697fbbcc43b227fe463a873aeff4ca84f 100755 (executable)
@@ -954,7 +954,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
         }
         String prefix = null;
         List<Adjacency> value = new ArrayList<>();
-        boolean isNextHopAddReqd = false;
+        boolean isFibNextHopAddReqd = false;
         String vpnName = vpnInterface.getVpnInstanceName();
         Uint32 vpnId = vpnUtil.getVpnId(vpnName);
         String primaryRd = vpnUtil.getPrimaryRd(vpnName);
@@ -970,12 +970,13 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
             List<String> nextHopList = adj.getNextHopIpList();
             // If TEP is added , update the nexthop of primary adjacency.
             // Secondary adj nexthop is already pointing to primary adj IP address.
-            if (nextHopList == null || nextHopList.isEmpty()) {
-                isNextHopAddReqd = true;
-            }
-
             if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
                 value.add(new AdjacencyBuilder(adj).setNextHopIpList(nhList).build());
+                if (nextHopList != null && !nextHopList.isEmpty()) {
+                    /* everything right already */
+                } else {
+                    isFibNextHopAddReqd = true;
+                }
             } else {
                 Optional<VrfEntry> vrfEntryOptional = FibHelper.getVrfEntry(dataBroker, primaryRd, prefix);
                 if (!vrfEntryOptional.isPresent()) {
@@ -984,12 +985,12 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                 nhList = FibHelper.getNextHopListFromRoutePaths(vrfEntryOptional.get());
                 if (!nhList.contains(srcTepIp)) {
                     nhList.add(srcTepIp);
-                    isNextHopAddReqd = true;
+                    isFibNextHopAddReqd = true;
                 }
                 value.add(adj);
             }
 
-            if (isNextHopAddReqd) {
+            if (isFibNextHopAddReqd) {
                 updateLabelMapper(label, nhList);
                 LOG.info("updateVpnInterfaceOnTepAdd: Updated label mapper : label {} dpn {} prefix {} nexthoplist {}"
                         + " vpn {} vpnid {} rd {} interface {}", label, srcDpnId , prefix, nhList,
@@ -1396,7 +1397,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
             Optional<VpnInterfaceOpDataEntry> vpnInterfaceOpDataEnteryOptional =
                     SingleTransactionDataBroker.syncReadOptional(dataBroker,
                             LogicalDatastoreType.OPERATIONAL, identifier);
-            boolean isLearntIP = Boolean.FALSE;
+            boolean isNonPrimaryAdjIp = false;
             String primaryRd = vpnUtil.getVpnRd(vpnName);
             LOG.info("removeAdjacenciesFromVpn: For interface {} on dpn {} RD recovered for vpn {} as rd {}",
                     interfaceName, dpnId, vpnName, primaryRd);
@@ -1422,7 +1423,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                         List<String> nhList;
                         if (nextHop.getAdjacencyType() != AdjacencyType.PrimaryAdjacency) {
                             nhList = getNextHopForNonPrimaryAdjacency(nextHop, vpnName, dpnId, interfaceName);
-                            isLearntIP = nextHop.getAdjacencyType() == AdjacencyType.LearntIp ? true : false;
+                            isNonPrimaryAdjIp = Boolean.TRUE;
                         } else {
                             // This is a primary adjacency
                             nhList = nextHop.getNextHopIpList() != null ? nextHop.getNextHopIpList()
@@ -1430,6 +1431,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                             removeGwMacAndArpResponderFlows(nextHop, vpnId, dpnId, lportTag, gwMac,
                                     vpnInterfaceOpDataEnteryOptional.get().getGatewayIpAddress(),
                                     interfaceName, writeInvTxn);
+                            isNonPrimaryAdjIp = Boolean.FALSE;
                         }
                         if (!nhList.isEmpty()) {
                             if (Objects.equals(primaryRd, vpnName)) {
@@ -1439,7 +1441,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                                         interfaceName, dpnId, writeConfigTxn, writeOperTxn));
                             } else {
                                 removeAdjacencyFromBgpvpn(nextHop, nhList, vpnName, primaryRd, dpnId, rd,
-                                        interfaceName, writeConfigTxn, writeOperTxn);
+                                        interfaceName, isNonPrimaryAdjIp, writeConfigTxn, writeOperTxn);
                             }
                         } else {
                             LOG.error("removeAdjacenciesFromVpn: nextHop empty for ip {} rd {} adjacencyType {}"
@@ -1458,7 +1460,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                                 vpnVipToPort.getPortName(), ip, dpnId, vpnName);
                     }
                     // Remove the MIP-IP from VpnPortIpToPort.
-                    if (isLearntIP) {
+                    if (isNonPrimaryAdjIp) {
                         VpnPortipToPort persistedIp = vpnUtil.getVpnPortipToPort(vpnName, ip);
                         if (persistedIp != null && persistedIp.isLearntIp()
                                 && persistedIp.getPortName().equals(interfaceName)) {
@@ -1522,15 +1524,19 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
     }
 
     private void removeAdjacencyFromBgpvpn(Adjacency nextHop, List<String> nhList, String vpnName, String primaryRd,
-                                           Uint64 dpnId, String rd, String interfaceName,
+                                           Uint64 dpnId, String rd, String interfaceName, boolean isNonPrimaryAdjIp,
                                            TypedWriteTransaction<Configuration> writeConfigTxn,
                                            TypedWriteTransaction<Operational> writeOperTx) {
         List<VpnInstanceOpDataEntry> vpnsToImportRoute =
                 vpnUtil.getVpnsImportingMyRoute(vpnName);
         nhList.forEach((nh) -> {
             //IRT: remove routes from other vpns importing it
-            vpnManager.removePrefixFromBGP(vpnName, primaryRd, rd, interfaceName, nextHop.getIpAddress(),
-                    nextHop.getNextHopIpList().get(0), nh, dpnId, writeConfigTxn, writeOperTx);
+            if (isNonPrimaryAdjIp) {
+                removeLearntPrefixFromBGP(rd, nextHop.getIpAddress(), nh, writeConfigTxn);
+            } else {
+                vpnManager.removePrefixFromBGP(vpnName, primaryRd, rd, interfaceName, nextHop.getIpAddress(),
+                        nextHop.getNextHopIpList().get(0), nh, dpnId, writeConfigTxn, writeOperTx);
+            }
             for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
                 String vpnRd = vpn.getVrfId();
                 if (vpnRd != null) {
@@ -1545,6 +1551,26 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
         });
     }
 
+    @SuppressWarnings("checkstyle:IllegalCatch")
+    private void removeLearntPrefixFromBGP(String rd, String prefix, String nextHop,
+                                           TypedWriteTransaction<Configuration> writeConfigTxn) {
+        try {
+            if (!fibManager.checkFibEntryExist(dataBroker, rd, prefix, nextHop)) {
+                LOG.info("removeLearntPrefixFromBGP: IP {} with nexthop {} rd {} is already removed.Ignoring this"
+                        + " operation", prefix, nextHop, rd);
+                return;
+            }
+            LOG.info("removeLearntPrefixFromBGP: VPN WITHDRAW: Removing Fib Entry rd {} prefix {} nexthop {}",
+                    rd, prefix, nextHop);
+            fibManager.removeOrUpdateFibEntry(rd, prefix, nextHop, writeConfigTxn);
+            bgpManager.withdrawPrefix(rd, prefix); // TODO: Might be needed to include nextHop here
+            LOG.info("removeLearntPrefixFromBGP: VPN WITHDRAW: Removed Fib Entry rd {} prefix {} nexthop {}",
+                    rd, prefix, nextHop);
+        } catch (Exception e) {
+            LOG.error("removeLearntPrefixFromBGP: Delete prefix {} rd {} nextHop {} failed", prefix, rd, nextHop, e);
+        }
+    }
+
     private void removeGwMacAndArpResponderFlows(Adjacency nextHop, Uint32 vpnId, Uint64 dpnId,
                                                  int lportTag, String gwMac, String gwIp, String interfaceName,
                                                  TypedReadWriteTransaction<Configuration> writeInvTxn)
index 92a2bb6c000e6c8a060f3ccb46fce6556639b962..2c47b7e560a68590faf3917f92e92e380dcc6937 100644 (file)
@@ -966,8 +966,8 @@ public final class VpnUtil {
                 new LearntVpnVipToPortKey(fixedIp, vpnName)).build();
     }
 
-    void removeLearntVpnVipToPort(String vpnName, String fixedIp,
-                                  @Nullable TypedWriteTransaction<Operational> writeOperTxn) {
+    public void removeLearntVpnVipToPort(String vpnName, String fixedIp,
+                                         @Nullable TypedWriteTransaction<Operational> writeOperTxn) {
         final InstanceIdentifier<LearntVpnVipToPort> id = buildLearntVpnVipToPortIdentifier(vpnName, fixedIp);
         final ReentrantLock lock = lockFor(vpnName, fixedIp);
         lock.lock();
@@ -984,7 +984,7 @@ public final class VpnUtil {
         }
     }
 
-    protected static void removeVpnPortFixedIpToPort(DataBroker broker, String vpnName, String fixedIp,
+    public static void removeVpnPortFixedIpToPort(DataBroker broker, String vpnName, String fixedIp,
                                                      @Nullable TypedWriteTransaction<Configuration> writeConfigTxn) {
         final InstanceIdentifier<VpnPortipToPort> id = buildVpnPortipToPortIdentifier(vpnName, fixedIp);
         final ReentrantLock lock = lockFor(vpnName, fixedIp);
@@ -1071,11 +1071,29 @@ public final class VpnUtil {
         VpnUtil.removeVpnPortFixedIpToPort(dataBroker, vpnName, prefix, null);
     }
 
+    public void removeMipAdjacency(String vpnName, String vpnInterface, String prefix,
+                                   TypedWriteTransaction<Configuration> writeConfigTxn) {
+        String ip = VpnUtil.getIpPrefix(prefix);
+        LOG.trace("Removing {} adjacency from Old VPN Interface {} ", ip, vpnInterface);
+        InstanceIdentifier<VpnInterface> vpnIfId = VpnUtil.getVpnInterfaceIdentifier(vpnInterface);
+        InstanceIdentifier<Adjacencies> path = vpnIfId.augmentation(Adjacencies.class);
+        //TODO: Remove synchronized?
+
+        Optional<Adjacencies> adjacencies = read(LogicalDatastoreType.OPERATIONAL, path);
+        if (adjacencies.isPresent()) {
+            InstanceIdentifier<Adjacency> adjacencyIdentifier = getAdjacencyIdentifier(vpnInterface, prefix);
+            writeConfigTxn.delete(adjacencyIdentifier);
+            LOG.error("removeMipAdjacency: Successfully Deleted Adjacency {} from interface {} vpn {}", ip,
+                    vpnInterface, vpnName);
+        }
+    }
+
     public void removeMipAdjacency(String vpnInterface, String ipAddress) {
         String prefix = VpnUtil.getIpPrefix(ipAddress);
         InstanceIdentifier<Adjacency> adjacencyIdentifier = getAdjacencyIdentifier(vpnInterface, prefix);
         try {
-            SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
+            SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                    adjacencyIdentifier);
         } catch (TransactionCommitFailedException e) {
             if (e.getCause() instanceof ModifiedNodeDoesNotExistException) {
                 LOG.debug("vpnInterface {} is already deleted. prefix={}", vpnInterface, prefix);
index aef6cab59754fa627934a375ba0739480e34ac8d..0769bdd7f9b4aa3138d4b87299f362cb9c6355e9 100644 (file)
@@ -58,7 +58,7 @@ public class IpMonitorEventListener implements AlivenessMonitorListener {
             if (vpnVipToPort != null && macEntry.getCreatedTime().equals(vpnVipToPort.getCreationTime())) {
                 String jobKey = VpnUtil.buildIpMonitorJobKey(macEntry.getIpAddress().getHostAddress(),
                         macEntry.getVpnName());
-                jobCoordinator.enqueueJob(jobKey, new IpMonitorStopTask(macEntry, Boolean.TRUE, vpnUtil,
+                jobCoordinator.enqueueJob(jobKey, new IpMonitorStopTask(macEntry, dataBroker, Boolean.TRUE, vpnUtil,
                         alivenessMonitorUtils));
             }
 
index 0c764c80b333227f8054d48c7e290547ab717d52..10f8ac882fbf76e71c782c630a33f19631397121 100644 (file)
@@ -12,6 +12,12 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
 import java.util.concurrent.Callable;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.genius.infra.Datastore;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
+import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
 import org.opendaylight.netvirt.vpnmanager.VpnUtil;
 import org.opendaylight.netvirt.vpnmanager.iplearn.model.MacEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
@@ -22,16 +28,20 @@ import org.slf4j.LoggerFactory;
 public class IpMonitorStopTask implements Callable<List<ListenableFuture<Void>>> {
     private static final Logger LOG = LoggerFactory.getLogger(IpMonitorStopTask.class);
     private MacEntry macEntry;
+    private DataBroker dataBroker;
     private final AlivenessMonitorUtils alivenessMonitorUtils;
     private boolean isRemoveMipAdjAndLearntIp;
     private final VpnUtil vpnUtil;
+    private final ManagedNewTransactionRunner txRunner;
 
-    public IpMonitorStopTask(MacEntry macEntry, boolean removeMipAdjAndLearntIp, VpnUtil vpnUtil,
-                              AlivenessMonitorUtils alivenessMonitorUtils) {
+    public IpMonitorStopTask(MacEntry macEntry, DataBroker dataBroker, boolean removeMipAdjAndLearntIp, VpnUtil vpnUtil,
+                             AlivenessMonitorUtils alivenessMonitorUtils) {
         this.macEntry = macEntry;
+        this.dataBroker = dataBroker;
         this.alivenessMonitorUtils = alivenessMonitorUtils;
         this.isRemoveMipAdjAndLearntIp = removeMipAdjAndLearntIp;
         this.vpnUtil = vpnUtil;
+        this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
     }
 
     @Override
@@ -54,13 +64,20 @@ public class IpMonitorStopTask implements Callable<List<ListenableFuture<Void>>>
                         + "Ignoring this remove event.", learntIp, vpnName);
                 return futures;
             }
-            vpnUtil.removeMipAdjAndLearntIp(vpnName, macEntry.getInterfaceName(), learntIp);
+            vpnUtil.removeLearntVpnVipToPort(macEntry.getVpnName(),
+                    macEntry.getIpAddress().getHostAddress(), null);
+            vpnUtil.removeVpnPortFixedIpToPort(dataBroker, macEntry.getVpnName(),
+                    macEntry.getIpAddress().getHostAddress(), null);
+
+            ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
+                    Datastore.CONFIGURATION, tx -> vpnUtil.removeMipAdjacency(macEntry.getVpnName(),
+                            macEntry.getInterfaceName(), macEntry.getIpAddress().getHostAddress(), tx)),
+                    LOG, "ArpMonitorStopTask: Error writing to datastore for Vpn {} IP  {}",
+                    macEntry.getVpnName(), macEntry.getIpAddress().getHostAddress());
         } else {
             // Delete only MIP adjacency
             vpnUtil.removeMipAdjacency(macEntry.getInterfaceName(), learntIp);
         }
         return futures;
     }
-
-
 }
index 04cc1471ffb815b25f76bd07680b9a8d09f8a81d..525152889498e005afc8814dcd09707d4c9b42c5 100644 (file)
@@ -165,13 +165,20 @@ public class IpMonitoringHandler
                     return;
                 }
                 String vpnName =  value.getVpnName();
+                String learntIp = srcInetAddr.getHostAddress();
+                LearntVpnVipToPort vpnVipToPort = vpnUtil.getLearntVpnVipToPort(vpnName, learntIp);
+                if (vpnVipToPort != null && !vpnVipToPort.getCreationTime().equals(value.getCreationTime())) {
+                    LOG.warn("The MIP {} over vpn {} has been learnt again and processed. "
+                            + "Ignoring this remove event.", learntIp, vpnName);
+                    return;
+                }
                 MacAddress srcMacAddress = MacAddress.getDefaultInstance(value.getMacAddress());
                 String interfaceName =  value.getPortName();
                 MacEntry macEntry = new MacEntry(vpnName, srcMacAddress, srcInetAddr, interfaceName,
                         value.getCreationTime());
 
                 jobCoordinator.enqueueJob(VpnUtil.buildIpMonitorJobKey(srcInetAddr.toString(), vpnName),
-                        new IpMonitorStopTask(macEntry, Boolean.FALSE, vpnUtil, alivenessMonitorUtils));
+                        new IpMonitorStopTask(macEntry, dataBroker, Boolean.FALSE, vpnUtil, alivenessMonitorUtils));
             } catch (UnknownHostException e) {
                 LOG.error("Error in deserializing packet {} with exception", value, e);
             }