From 8ce872b0b929e39d41f94ce2313f789403533b6a Mon Sep 17 00:00:00 2001 From: Karthikeyan Krishnan Date: Tue, 10 Mar 2020 14:35:56 +0530 Subject: [PATCH] Stale MIP FIB/Flow entries present upon deletion of VRRP master 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 Change-Id: Ie42ff0eede90433c15b09537b7973842345ab376 --- .../netvirt/fibmanager/api/IFibManager.java | 3 ++ .../netvirt/fibmanager/FibManagerImpl.java | 6 +++ .../netvirt/fibmanager/FibUtil.java | 16 ++++++ .../InterfaceStateChangeListener.java | 28 ++++++++++ .../vpnmanager/VpnInterfaceManager.java | 54 ++++++++++++++----- .../netvirt/vpnmanager/VpnUtil.java | 26 +++++++-- .../iplearn/IpMonitorEventListener.java | 2 +- .../vpnmanager/iplearn/IpMonitorStopTask.java | 27 ++++++++-- .../iplearn/IpMonitoringHandler.java | 9 +++- 9 files changed, 146 insertions(+), 25 deletions(-) diff --git a/fibmanager/api/src/main/java/org/opendaylight/netvirt/fibmanager/api/IFibManager.java b/fibmanager/api/src/main/java/org/opendaylight/netvirt/fibmanager/api/IFibManager.java index 6baba30b54..0b687463f5 100644 --- a/fibmanager/api/src/main/java/org/opendaylight/netvirt/fibmanager/api/IFibManager.java +++ b/fibmanager/api/src/main/java/org/opendaylight/netvirt/fibmanager/api/IFibManager.java @@ -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 tunnelType); diff --git a/fibmanager/impl/src/main/java/org/opendaylight/netvirt/fibmanager/FibManagerImpl.java b/fibmanager/impl/src/main/java/org/opendaylight/netvirt/fibmanager/FibManagerImpl.java index 9befcc857b..2e668bad84 100755 --- a/fibmanager/impl/src/main/java/org/opendaylight/netvirt/fibmanager/FibManagerImpl.java +++ b/fibmanager/impl/src/main/java/org/opendaylight/netvirt/fibmanager/FibManagerImpl.java @@ -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, diff --git a/fibmanager/impl/src/main/java/org/opendaylight/netvirt/fibmanager/FibUtil.java b/fibmanager/impl/src/main/java/org/opendaylight/netvirt/fibmanager/FibUtil.java index 08a1cb904e..41ca0e5538 100644 --- a/fibmanager/impl/src/main/java/org/opendaylight/netvirt/fibmanager/FibUtil.java +++ b/fibmanager/impl/src/main/java/org/opendaylight/netvirt/fibmanager/FibUtil.java @@ -897,4 +897,20 @@ public class FibUtil { } return false; } + + public static boolean checkFibEntryExist(DataBroker broker, String rd, String prefix, String nextHopIp) { + InstanceIdentifier vrfEntryId = + InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)) + .child(VrfEntry.class, new VrfEntryKey(prefix)).build(); + Optional entry = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId); + if (entry.isPresent()) { + List paths = entry.get().getRoutePaths(); + for (RoutePaths path: paths) { + if (path.getNexthopAddress().equals(nextHopIp)) { + return true; + } + } + } + return false; + } } diff --git a/vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/InterfaceStateChangeListener.java b/vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/InterfaceStateChangeListener.java index eb148a9fb6..1c017946d6 100644 --- a/vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/InterfaceStateChangeListener.java +++ b/vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/InterfaceStateChangeListener.java @@ -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 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 { private final String interfaceName; private final boolean add; diff --git a/vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnInterfaceManager.java b/vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnInterfaceManager.java index 1ce9653b90..50466d2697 100755 --- a/vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnInterfaceManager.java +++ b/vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnInterfaceManager.java @@ -954,7 +954,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase 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 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 vrfEntryOptional = FibHelper.getVrfEntry(dataBroker, primaryRd, prefix); if (!vrfEntryOptional.isPresent()) { @@ -984,12 +985,12 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase 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 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 nhList, String vpnName, String primaryRd, - Uint64 dpnId, String rd, String interfaceName, + Uint64 dpnId, String rd, String interfaceName, boolean isNonPrimaryAdjIp, TypedWriteTransaction writeConfigTxn, TypedWriteTransaction writeOperTx) { List 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 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 writeInvTxn) diff --git a/vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnUtil.java b/vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnUtil.java index 92a2bb6c00..2c47b7e560 100644 --- a/vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnUtil.java +++ b/vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnUtil.java @@ -966,8 +966,8 @@ public final class VpnUtil { new LearntVpnVipToPortKey(fixedIp, vpnName)).build(); } - void removeLearntVpnVipToPort(String vpnName, String fixedIp, - @Nullable TypedWriteTransaction writeOperTxn) { + public void removeLearntVpnVipToPort(String vpnName, String fixedIp, + @Nullable TypedWriteTransaction writeOperTxn) { final InstanceIdentifier 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 writeConfigTxn) { final InstanceIdentifier 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 writeConfigTxn) { + String ip = VpnUtil.getIpPrefix(prefix); + LOG.trace("Removing {} adjacency from Old VPN Interface {} ", ip, vpnInterface); + InstanceIdentifier vpnIfId = VpnUtil.getVpnInterfaceIdentifier(vpnInterface); + InstanceIdentifier path = vpnIfId.augmentation(Adjacencies.class); + //TODO: Remove synchronized? + + Optional adjacencies = read(LogicalDatastoreType.OPERATIONAL, path); + if (adjacencies.isPresent()) { + InstanceIdentifier 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 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); diff --git a/vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/iplearn/IpMonitorEventListener.java b/vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/iplearn/IpMonitorEventListener.java index aef6cab597..0769bdd7f9 100644 --- a/vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/iplearn/IpMonitorEventListener.java +++ b/vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/iplearn/IpMonitorEventListener.java @@ -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)); } diff --git a/vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/iplearn/IpMonitorStopTask.java b/vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/iplearn/IpMonitorStopTask.java index 0c764c80b3..10f8ac882f 100644 --- a/vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/iplearn/IpMonitorStopTask.java +++ b/vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/iplearn/IpMonitorStopTask.java @@ -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>> { 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>> + "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; } - - } diff --git a/vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/iplearn/IpMonitoringHandler.java b/vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/iplearn/IpMonitoringHandler.java index 04cc1471ff..5251528894 100644 --- a/vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/iplearn/IpMonitoringHandler.java +++ b/vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/iplearn/IpMonitoringHandler.java @@ -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); } -- 2.36.6