X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=fibmanager%2Fimpl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fnetvirt%2Ffibmanager%2FVrfEntryListener.java;h=540e06aaf55e551cd6bfc4fefd449829333c1181;hb=bf9dcb80a0dfd9c5f83a9d8fd8044e7d74f606cf;hp=62acf7f1f077adc4c05b0464b10a1401a94c6df1;hpb=3815cbb67c115265ac0624219f3dbbb3f80f75f1;p=netvirt.git diff --git a/fibmanager/impl/src/main/java/org/opendaylight/netvirt/fibmanager/VrfEntryListener.java b/fibmanager/impl/src/main/java/org/opendaylight/netvirt/fibmanager/VrfEntryListener.java old mode 100755 new mode 100644 index 62acf7f1f0..540e06aaf5 --- a/fibmanager/impl/src/main/java/org/opendaylight/netvirt/fibmanager/VrfEntryListener.java +++ b/fibmanager/impl/src/main/java/org/opendaylight/netvirt/fibmanager/VrfEntryListener.java @@ -14,6 +14,7 @@ import static org.opendaylight.genius.mdsalutil.NWUtil.isIpv4Address; import com.google.common.base.Optional; import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; @@ -27,12 +28,16 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Objects; import java.util.concurrent.Callable; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.ExecutionException; +import java.util.concurrent.locks.ReentrantLock; +import javax.annotation.Nullable; import javax.annotation.PostConstruct; import javax.inject.Inject; import javax.inject.Singleton; +import org.eclipse.jdt.annotation.NonNull; import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase; @@ -53,7 +58,6 @@ import org.opendaylight.genius.mdsalutil.MatchInfo; import org.opendaylight.genius.mdsalutil.MetaDataUtil; import org.opendaylight.genius.mdsalutil.NWUtil; import org.opendaylight.genius.mdsalutil.NwConstants; -import org.opendaylight.genius.mdsalutil.UpgradeState; import org.opendaylight.genius.mdsalutil.actions.ActionDrop; import org.opendaylight.genius.mdsalutil.actions.ActionGroup; import org.opendaylight.genius.mdsalutil.actions.ActionPopMpls; @@ -66,6 +70,7 @@ import org.opendaylight.genius.mdsalutil.matches.MatchIpv4Destination; import org.opendaylight.genius.mdsalutil.matches.MatchMetadata; import org.opendaylight.genius.mdsalutil.matches.MatchMplsLabel; import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId; +import org.opendaylight.genius.utils.JvmGlobalLocks; import org.opendaylight.genius.utils.ServiceIndex; import org.opendaylight.genius.utils.batching.SubTransaction; import org.opendaylight.infrautils.jobcoordinator.JobCoordinator; @@ -78,6 +83,7 @@ import org.opendaylight.netvirt.vpnmanager.api.VpnExtraRouteHelper; import org.opendaylight.netvirt.vpnmanager.api.VpnHelper; import org.opendaylight.netvirt.vpnmanager.api.intervpnlink.InterVpnLinkCache; import org.opendaylight.netvirt.vpnmanager.api.intervpnlink.InterVpnLinkDataComposite; +import org.opendaylight.serviceutils.upgrade.UpgradeState; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId; @@ -225,7 +231,7 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> { - synchronized (vpnInstance.getVpnInstanceName().intern()) { + final ReentrantLock lock = lockFor(vpnInstance); + lock.lock(); + try { for (VpnToDpnList vpnDpn : vpnToDpnList) { if (!localDpnIdList.contains(vpnDpn.getDpnId())) { if (vpnDpn.getDpnState() == VpnToDpnList.DpnState.Active) { @@ -452,6 +460,8 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase vpnInstanceNames = lri.getVpnInstanceList(); + List vpnInstanceNames = + lri.getVpnInstanceList() != null ? new ArrayList<>(lri.getVpnInstanceList()) : new ArrayList<>(); vpnInstanceNames.add(vpnInstanceName); builder.setVpnInstanceList(vpnInstanceNames); MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, lriId, builder.build()); @@ -523,8 +534,11 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase { List nextHopAddressList = FibHelper.getNextHopListFromRoutePaths(vrfEntry); - synchronized (label.toString().intern()) { - LabelRouteInfo lri = getLabelRouteInfo(label); + final LabelRouteInfoKey lriKey = new LabelRouteInfoKey(label); + final ReentrantLock lock = lockFor(lriKey); + lock.lock(); + try { + LabelRouteInfo lri = getLabelRouteInfo(lriKey); if (isPrefixAndNextHopPresentInLri(vrfEntry.getDestPrefix(), nextHopAddressList, lri)) { if (RouteOrigin.value(vrfEntry.getOrigin()) == RouteOrigin.SELF_IMPORTED) { @@ -540,6 +554,8 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase instructions = new ArrayList<>(); @@ -751,45 +767,60 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase usedRds = VpnExtraRouteHelper.getUsedRds(dataBroker, vpnId, localNextHopIP); - List vpnExtraRoutes = VpnExtraRouteHelper.getAllVpnExtraRoutes(dataBroker, - vpnName, usedRds, localNextHopIP); - if (LOG.isDebugEnabled()) { - LOG.debug("Creating Local fib entry with vpnName {} usedRds {} localNextHopIP {} vpnExtraRoutes {}", - vpnName, usedRds, localNextHopIP, vpnExtraRoutes); - } boolean localNextHopSeen = false; - //Is this fib route an extra route? If yes, get the nexthop which would be an adjacency in the vpn - for (Routes vpnExtraRoute : vpnExtraRoutes) { - String ipPrefix; - if (isIpv4Address(vpnExtraRoute.getNexthopIpList().get(0))) { - ipPrefix = vpnExtraRoute.getNexthopIpList().get(0) + NwConstants.IPV4PREFIX; - } else { - ipPrefix = vpnExtraRoute.getNexthopIpList().get(0) + NwConstants.IPV6PREFIX; + List vpnExtraRoutes = null; + //Synchronized to prevent missing bucket action due to race condition between refreshFib and + // add/updateFib threads on missing nexthop in VpnToExtraroutes + // FIXME: use an Identifier structure? + final ReentrantLock lock = JvmGlobalLocks.getLockForString(localNextHopIP + FibConstants.SEPARATOR + rd); + lock.lock(); + try { + List usedRds = VpnExtraRouteHelper.getUsedRds(dataBroker, vpnId, localNextHopIP); + vpnExtraRoutes = VpnExtraRouteHelper.getAllVpnExtraRoutes(dataBroker, + vpnName, usedRds, localNextHopIP); + if (LOG.isDebugEnabled()) { + LOG.debug("Creating Local fib entry with vpnName {} usedRds {} localNextHopIP {} vpnExtraRoutes {}", + vpnName, usedRds, localNextHopIP, vpnExtraRoutes); } - Prefixes localNextHopInfoLocal = fibUtil.getPrefixToInterface(vpnId, - ipPrefix); - if (localNextHopInfoLocal != null) { - localNextHopSeen = true; - BigInteger dpnId = - checkCreateLocalFibEntry(localNextHopInfoLocal, localNextHopInfoLocal.getIpAddress(), - vpnId, rd, vrfEntry, vpnExtraRoute, vpnExtraRoutes, etherType); - returnLocalDpnId.add(dpnId); + + //Is this fib route an extra route? If yes, get the nexthop which would be an adjacency in the vpn + for (Routes vpnExtraRoute : vpnExtraRoutes) { + String ipPrefix; + if (isIpv4Address(vpnExtraRoute.getNexthopIpList().get(0))) { + ipPrefix = vpnExtraRoute.getNexthopIpList().get(0) + NwConstants.IPV4PREFIX; + } else { + ipPrefix = vpnExtraRoute.getNexthopIpList().get(0) + NwConstants.IPV6PREFIX; + } + Prefixes localNextHopInfoLocal = fibUtil.getPrefixToInterface(vpnId, + ipPrefix); + if (localNextHopInfoLocal != null) { + localNextHopSeen = true; + BigInteger dpnId = + checkCreateLocalFibEntry(localNextHopInfoLocal, localNextHopInfoLocal.getIpAddress(), + vpnId, rd, vrfEntry, vpnExtraRoute, vpnExtraRoutes, etherType); + returnLocalDpnId.add(dpnId); + } } + } finally { + lock.unlock(); } if (!localNextHopSeen && RouteOrigin.value(vrfEntry.getOrigin()) == RouteOrigin.SELF_IMPORTED) { java.util.Optional optionalLabel = FibUtil.getLabelFromRoutePaths(vrfEntry); if (optionalLabel.isPresent()) { Long label = optionalLabel.get(); List nextHopAddressList = FibHelper.getNextHopListFromRoutePaths(vrfEntry); - synchronized (label.toString().intern()) { - LabelRouteInfo lri = getLabelRouteInfo(label); + final LabelRouteInfoKey lriKey = new LabelRouteInfoKey(label); + final ReentrantLock labelLock = lockFor(lriKey); + labelLock.lock(); + try { + LabelRouteInfo lri = getLabelRouteInfo(lriKey); if (isPrefixAndNextHopPresentInLri(localNextHopIP, nextHopAddressList, lri)) { Optional vpnInstanceOpDataEntryOptional = fibUtil.getVpnInstanceOpData(rd); if (vpnInstanceOpDataEntryOptional.isPresent()) { String vpnInstanceName = vpnInstanceOpDataEntryOptional.get().getVpnInstanceName(); - if (lri.getVpnInstanceList().contains(vpnInstanceName)) { + if (lri.getVpnInstanceList() != null && lri.getVpnInstanceList().contains( + vpnInstanceName)) { localNextHopInfo = updateVpnReferencesInLri(lri, vpnInstanceName, true); localNextHopIP = lri.getPrefix(); } else { @@ -813,6 +844,8 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase vpnExtraRoutes, + @Nullable Routes routes, @Nullable List vpnExtraRoutes, int etherType) { String vpnName = fibUtil.getVpnNameFromId(vpnId); if (localNextHopInfo != null) { @@ -859,7 +892,8 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase 1) { groupId = nextHopManager.createNextHopGroups(vpnId, rd, dpnId, vrfEntry, routes, vpnExtraRoutes); localGroupId = nextHopManager.getLocalSelectGroup(vpnId, vrfEntry.getDestPrefix()); @@ -919,15 +953,18 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase id = VpnHelper.getVpnToDpnListIdentifier(rd, dpnId); Optional dpnInVpn = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id); - if (dpnInVpn.isPresent()) { - return true; - } - return false; + return dpnInVpn.isPresent(); } + @Nullable private LabelRouteInfo getLabelRouteInfo(Long label) { + return getLabelRouteInfo(new LabelRouteInfoKey(label)); + } + + @Nullable + private LabelRouteInfo getLabelRouteInfo(LabelRouteInfoKey label) { InstanceIdentifier lriIid = InstanceIdentifier.builder(LabelRouteMap.class) - .child(LabelRouteInfo.class, new LabelRouteInfoKey(label)).build(); + .child(LabelRouteInfo.class, label).build(); Optional opResult = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, lriIid); if (opResult.isPresent()) { return opResult.get(); @@ -936,7 +973,7 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase tx) { + @Nullable TypedWriteTransaction tx) { if (lri == null) { return true; } @@ -1156,55 +1193,71 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase adjacencyResults = baseVrfEntryHandler.resolveAdjacency(remoteDpnId, vpnId, vrfEntry, rd); - if (adjacencyResults.isEmpty()) { - LOG.error("Could not get interface for route-paths: {} in vpn {} on DPN {}", - vrfEntry.getRoutePaths(), rd, remoteDpnId); - LOG.error("Failed to add Route: {} in vpn: {}", vrfEntry.getDestPrefix(), rd); + if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.STATIC) { + programRemoteFibEntry(remoteDpnId, vpnId, rd, vrfEntry, tx); return; } - + // Handling static VRF entries List usedRds = VpnExtraRouteHelper.getUsedRds(dataBroker, vpnId, vrfEntry.getDestPrefix()); - List vpnExtraRoutes = VpnExtraRouteHelper.getAllVpnExtraRoutes(dataBroker, - vpnName, usedRds, vrfEntry.getDestPrefix()); - // create loadbalancing groups for extra routes only when the extra route is present behind - // multiple VMs + List vpnExtraRoutes = + VpnExtraRouteHelper.getAllVpnExtraRoutes(dataBroker, vpnName, usedRds, vrfEntry.getDestPrefix()); if (!vpnExtraRoutes.isEmpty()) { - List instructions = new ArrayList<>(); - // Obtain the local routes for this particular dpn. - java.util.Optional routes = vpnExtraRoutes - .stream() - .filter(route -> { - Prefixes prefixToInterface = fibUtil.getPrefixToInterface(vpnId, - fibUtil.getIpPrefix(route.getNexthopIpList().get(0))); - if (prefixToInterface == null) { - return false; - } - return remoteDpnId.equals(prefixToInterface.getDpnId()); - }).findFirst(); - long groupId = nextHopManager.createNextHopGroups(vpnId, rd, remoteDpnId, vrfEntry, - routes.isPresent() ? routes.get() : null, vpnExtraRoutes); - if (groupId == FibConstants.INVALID_GROUP_ID) { - LOG.error("Unable to create Group for local prefix {} on rd {} on Node {}", - vrfEntry.getDestPrefix(), rd, remoteDpnId.toString()); - return; - } - List actionInfos = - Collections.singletonList(new ActionGroup(groupId)); - instructions.add(new InstructionApplyActions(actionInfos)); - baseVrfEntryHandler.makeConnectedRoute(remoteDpnId, vpnId, vrfEntry, rd, instructions, - NwConstants.ADD_FLOW, TransactionAdapter.toWriteTransaction(tx), null); + programRemoteFibWithLoadBalancingGroups(remoteDpnId, vpnId, rd, vrfEntry, vpnExtraRoutes); } else { - baseVrfEntryHandler.programRemoteFib(remoteDpnId, vpnId, vrfEntry, - TransactionAdapter.toWriteTransaction(tx), rd, adjacencyResults, null); + // Program in case of other static VRF entries like floating IPs + programRemoteFibEntry(remoteDpnId, vpnId, rd, vrfEntry, tx); + } + } + + private void programRemoteFibWithLoadBalancingGroups(final BigInteger remoteDpnId, final long vpnId, String rd, + final VrfEntry vrfEntry, List vpnExtraRoutes) { + // create loadbalancing groups for extra routes only when the extra route is + // present behind multiple VMs + // Obtain the local routes for this particular dpn. + java.util.Optional routes = vpnExtraRoutes.stream().filter(route -> { + Prefixes prefixToInterface = + fibUtil.getPrefixToInterface(vpnId, FibUtil.getIpPrefix(route.getNexthopIpList().get(0))); + if (prefixToInterface == null) { + return false; + } + return remoteDpnId.equals(prefixToInterface.getDpnId()); + }).findFirst(); + long groupId = nextHopManager.createNextHopGroups(vpnId, rd, remoteDpnId, vrfEntry, + routes.isPresent() ? routes.get() : null, vpnExtraRoutes); + if (groupId == FibConstants.INVALID_GROUP_ID) { + LOG.error("Unable to create Group for local prefix {} on rd {} on Node {}", vrfEntry.getDestPrefix(), rd, + remoteDpnId); + return; } + List actionInfos = Collections.singletonList(new ActionGroup(groupId)); + List instructions = Lists.newArrayList(new InstructionApplyActions(actionInfos)); + String jobKey = FibUtil.getCreateRemoteNextHopJobKey(vpnId, remoteDpnId, vrfEntry.getDestPrefix()); + jobCoordinator.enqueueJob(jobKey, + () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(txn -> { + baseVrfEntryHandler.makeConnectedRoute(remoteDpnId, vpnId, vrfEntry, rd, instructions, + NwConstants.ADD_FLOW, txn, null); + }))); LOG.debug("Successfully added FIB entry for prefix {} in vpnId {}", vrfEntry.getDestPrefix(), vpnId); } + private void programRemoteFibEntry(final BigInteger remoteDpnId, final long vpnId, String rd, + final VrfEntry vrfEntry, TypedWriteTransaction tx) { + List adjacencyResults = baseVrfEntryHandler.resolveAdjacency(remoteDpnId, vpnId, vrfEntry, rd); + if (adjacencyResults.isEmpty()) { + LOG.error("Could not get interface for route-paths: {} in vpn {} on DPN {}", vrfEntry.getRoutePaths(), rd, + remoteDpnId); + LOG.error("Failed to add Route: {} in vpn: {}", vrfEntry.getDestPrefix(), rd); + return; + } + baseVrfEntryHandler.programRemoteFib(remoteDpnId, vpnId, vrfEntry, TransactionAdapter.toWriteTransaction(tx), + rd, adjacencyResults, null); + LOG.debug("Successfully programmed FIB entry for prefix {} in vpnId {}", vrfEntry.getDestPrefix(), vpnId); + } + protected void cleanUpOpDataForFib(Long vpnId, String primaryRd, final VrfEntry vrfEntry) { /* Get interface info from prefix to interface mapping; Use the interface info to get the corresponding vpn interface op DS entry, @@ -1220,7 +1273,7 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase usedRds = VpnExtraRouteHelper.getUsedRds(dataBroker, vpnId, vrfEntry.getDestPrefix()); String usedRd = usedRds.isEmpty() ? primaryRd : usedRds.get(0); Routes extraRoute = baseVrfEntryHandler.getVpnToExtraroute(vpnId, usedRd, vrfEntry.getDestPrefix()); - if (extraRoute != null) { + if (extraRoute != null && extraRoute.getNexthopIpList() != null) { for (String nextHopIp : extraRoute.getNexthopIpList()) { LOG.debug("NextHop IP for destination {} is {}", vrfEntry.getDestPrefix(), nextHopIp); if (nextHopIp != null) { @@ -1259,7 +1312,7 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase { List nextHopAddressList = FibHelper.getNextHopListFromRoutePaths(vrfEntry); - synchronized (label.toString().intern()) { - LabelRouteInfo lri = getLabelRouteInfo(label); - if (lri != null && lri.getPrefix().equals(vrfEntry.getDestPrefix()) + final LabelRouteInfoKey lriKey = new LabelRouteInfoKey(label); + final ReentrantLock lock = lockFor(lriKey); + lock.lock(); + try { + LabelRouteInfo lri = getLabelRouteInfo(lriKey); + if (lri != null && Objects.equals(lri.getPrefix(), vrfEntry.getDestPrefix()) && nextHopAddressList.contains(lri.getNextHopIpList().get(0))) { Optional vpnInstanceOpDataEntryOptional = fibUtil.getVpnInstanceOpData(rd); @@ -1325,6 +1381,8 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase configTx.delete(VpnExtraRouteHelper.getUsedRdsIdentifier(vpnId, vrfEntry.getDestPrefix()))); - nextHopManager.removeNextHopPointer(nextHopManager - .getRemoteSelectGroupKey(vpnId, vrfEntry.getDestPrefix())); - nextHopManager.removeNextHopPointer(nextHopManager - .getLocalSelectGroupKey(vpnId, vrfEntry.getDestPrefix())); } } handleAdjacencyAndVpnOpInterfaceDeletion(vrfEntry, ifName, vpnName, tx); @@ -1409,8 +1463,9 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase + @NonNull List adjacencies = optAdjacencies.get().nonnullAdjacency(); + if (adjacencies.size() <= 2 + && adjacencies.stream().allMatch(adjacency -> adjacency.getAdjacencyType() == Adjacency.AdjacencyType.PrimaryAdjacency && adjacency.isMarkedForDeletion() != null && adjacency.isMarkedForDeletion() @@ -1469,8 +1524,11 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase { - synchronized (label.toString().intern()) { - LabelRouteInfo lri = getLabelRouteInfo(label); + final LabelRouteInfoKey lriKey = new LabelRouteInfoKey(label); + final ReentrantLock lock = lockFor(lriKey); + lock.lock(); + try { + LabelRouteInfo lri = getLabelRouteInfo(lriKey); if (isPrefixAndNextHopPresentInLri(vrfEntry.getDestPrefix(), nextHopAddressList, lri)) { Optional vpnInstanceOpDataEntryOptional = fibUtil.getVpnInstanceOpData(rd); @@ -1492,6 +1550,8 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase extraRouteOptional; //Is this fib route an extra route? If yes, get the nexthop which would be an adjacency in the vpn if (usedRds != null && !usedRds.isEmpty()) { - jobKey = FibUtil.getJobKeyForRdPrefix(usedRds.get(0), vrfEntry.getDestPrefix()); if (usedRds.size() > 1) { LOG.error("The extra route prefix is still present in some DPNs"); return ; @@ -1517,11 +1576,10 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> { if (localDpnIdList.size() <= 0) { for (VpnToDpnList curDpn : vpnToDpnList) { @@ -1532,7 +1590,7 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase instructions, int priority, - int addOrRemove, TypedWriteTransaction tx) { + private void makeLFibTableEntry(BigInteger dpId, long label, @Nullable List instructions, + int priority, int addOrRemove, TypedWriteTransaction tx) { if (tx == null) { ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, newTx -> makeLFibTableEntry(dpId, label, instructions, priority, addOrRemove, newTx)), LOG, @@ -1623,9 +1688,12 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase { - for (final VrfEntry vrfEntry : vrfTable.get().getVrfEntry()) { + for (final VrfEntry vrfEntry : vrfTable.get().nonnullVrfEntry()) { SubnetRoute subnetRoute = vrfEntry.augmentation(SubnetRoute.class); if (subnetRoute != null) { long elanTag = subnetRoute.getElantag(); @@ -1650,7 +1718,7 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase nextHopList = FibHelper.getNextHopListFromRoutePaths(vrfEntry); LabelRouteInfo lri = getLabelRouteInfo(optionalLabel.get()); if (isPrefixAndNextHopPresentInLri(vrfEntry.getDestPrefix(), nextHopList, lri)) { - if (lri.getDpnId().equals(dpnId)) { + if (Objects.equals(lri.getDpnId(), dpnId)) { try { int etherType = NWUtil.getEtherTypeFromIpPrefix( vrfEntry.getDestPrefix()); @@ -1684,6 +1752,8 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase> listenableFuture = Futures.allAsList(futures); Futures.addCallback(listenableFuture, callback, MoreExecutors.directExecutor()); } + } finally { + lock.unlock(); } return futures; }); @@ -1700,11 +1770,15 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> { - synchronized (vpnInstance.getVpnInstanceName().intern()) { - vrfTable.get().getVrfEntry().stream() + final ReentrantLock lock = lockFor(vpnInstance); + lock.lock(); + try { + vrfTable.get().nonnullVrfEntry().stream() .filter(vrfEntry -> RouteOrigin.BGP == RouteOrigin.value(vrfEntry.getOrigin())) .forEach(bgpRouteVrfEntryHandler.getConsumerForCreatingRemoteFib(dpnId, vpnId, rd, remoteNextHopIp, vrfTable, TransactionAdapter.toWriteTransaction(tx), txnObjects)); + } finally { + lock.unlock(); } }))); } @@ -1726,7 +1800,9 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> { - synchronized (vpnInstance.getVpnInstanceName().intern()) { + final ReentrantLock lock = lockFor(vpnInstance); + lock.lock(); + try { VrfTablesKey vrfTablesKey = new VrfTablesKey(rd); VrfEntry vrfEntry = getVrfEntry(dataBroker, rd, destPrefix); if (vrfEntry == null) { @@ -1759,7 +1835,7 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase extraRouteOptional = Optional.absent(); - if (usedRds.size() != 0) { + if (RouteOrigin.value(vrfEntry.getOrigin()) == RouteOrigin.STATIC && usedRds.size() != 0) { extraRouteOptional = VpnExtraRouteHelper.getVpnExtraroutes(dataBroker, fibUtil.getVpnNameFromId(vpnInstance.getVpnId()), usedRds.get(0), vrfEntry.getDestPrefix()); @@ -1767,6 +1843,8 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase> futures = new ArrayList<>(); if (vrfTable.isPresent()) { - synchronized (vpnInstance.getVpnInstanceName().intern()) { + final ReentrantLock lock = lockFor(vpnInstance); + lock.lock(); + try { futures.add(retryingTxRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> { String vpnName = fibUtil.getVpnNameFromId(vpnInstance.getVpnId()); - for (final VrfEntry vrfEntry : vrfTable.get().getVrfEntry()) { + for (final VrfEntry vrfEntry : vrfTable.get().nonnullVrfEntry()) { + /* parentRd is only filled for external PNF cases where the interface on the external + * network VPN are used to cleanup the flows. For all other cases, use "rd" for + * #fibUtil.isInterfacePresentInDpn(). + * */ + String parentRd = vrfEntry.getParentVpnRd() != null ? vrfEntry.getParentVpnRd() + : rd; /* Handle subnet routes here */ SubnetRoute subnetRoute = vrfEntry.augmentation(SubnetRoute.class); if (subnetRoute != null && !fibUtil - .isInterfacePresentInDpn(vrfEntry.getParentVpnRd(), dpnId)) { + .isInterfacePresentInDpn(parentRd, dpnId)) { LOG.trace("SUBNETROUTE: cleanUpDpnForVpn: Cleaning subnetroute {} on dpn {}" + " for vpn {}", vrfEntry.getDestPrefix(), dpnId, rd); baseVrfEntryHandler.makeConnectedRoute(dpnId, vpnId, vrfEntry, rd, null, @@ -1829,7 +1915,7 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase nextHopList = FibHelper.getNextHopListFromRoutePaths(vrfEntry); LabelRouteInfo lri = getLabelRouteInfo(optionalLabel.get()); if (isPrefixAndNextHopPresentInLri(vrfEntry.getDestPrefix(), nextHopList, - lri) && lri.getDpnId().equals(dpnId)) { + lri) && Objects.equals(lri.getDpnId(), dpnId)) { deleteLocalFibEntry(vpnId, rd, vrfEntry); } } @@ -1860,7 +1946,7 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase> listenableFuture = Futures.allAsList(futures); @@ -1893,14 +1981,18 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase { - synchronized (vpnInstance.getVpnInstanceName().intern()) { + final ReentrantLock lock = lockFor(vpnInstance); + lock.lock(); + try { return Collections.singletonList( txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, - tx -> vrfTable.get().getVrfEntry().stream() + tx -> vrfTable.get().nonnullVrfEntry().stream() .filter(vrfEntry -> RouteOrigin.value(vrfEntry.getOrigin()) == RouteOrigin.BGP) .forEach(bgpRouteVrfEntryHandler.getConsumerForDeletingRemoteFib(dpnId, vpnId, remoteNextHopIp, vrfTable, TransactionAdapter.toWriteTransaction(tx), txnObjects)))); + } finally { + lock.unlock(); } }); } @@ -1922,6 +2014,7 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase vrfEntryId = InstanceIdentifier.builder(FibEntries.class) .child(VrfTables.class, new VrfTablesKey(rd)) @@ -1982,9 +2075,9 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase nextHopAddressList, LabelRouteInfo lri) { - return lri != null && lri.getPrefix().equals(prefix) + return lri != null && Objects.equals(lri.getPrefix(), prefix) && nextHopAddressList.contains(lri.getNextHopIpList().get(0)); } @@ -2004,4 +2097,13 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase