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;
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;
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;
if (!localDpnIdList.isEmpty() && vpnToDpnList != null) {
jobCoordinator.enqueueJob(FibUtil.getJobKeyForRdPrefix(rd, vrfEntry.getDestPrefix()),
() -> 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) {
}
}
}
+ } finally {
+ lock.unlock();
}
})), MAX_RETRIES);
}
LabelRouteInfoBuilder builder = new LabelRouteInfoBuilder(lri);
if (!isPresentInList) {
LOG.debug("vpnName {} is not present in LRI with label {}..", vpnInstanceName, lri.getLabel());
- List<String> vpnInstanceNames = lri.getVpnInstanceList();
+ List<String> vpnInstanceNames =
+ lri.getVpnInstanceList() != null ? new ArrayList<>(lri.getVpnInstanceList()) : new ArrayList<>();
vpnInstanceNames.add(vpnInstanceName);
builder.setVpnInstanceList(vpnInstanceNames);
MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, lriId, builder.build());
}
FibUtil.getLabelFromRoutePaths(vrfEntry).ifPresent(label -> {
List<String> 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) {
LOG.debug("SUBNETROUTE: installSubnetRouteInFib: Fetched labelRouteInfo for label {} interface {}"
+ " and got dpn {}", label, lri.getVpnInterfaceName(), lri.getDpnId());
}
+ } finally {
+ lock.unlock();
}
});
final List<InstructionInfo> instructions = new ArrayList<>();
if (localNextHopInfo == null) {
boolean localNextHopSeen = false;
List<Routes> vpnExtraRoutes = null;
- String rdPrefixKey = localNextHopIP + FibConstants.SEPARATOR + rd;
//Synchronized to prevent missing bucket action due to race condition between refreshFib and
// add/updateFib threads on missing nexthop in VpnToExtraroutes
- synchronized (rdPrefixKey.intern()) {
+ // FIXME: use an Identifier structure?
+ final ReentrantLock lock = JvmGlobalLocks.getLockForString(localNextHopIP + FibConstants.SEPARATOR + rd);
+ lock.lock();
+ try {
List<String> usedRds = VpnExtraRouteHelper.getUsedRds(dataBroker, vpnId, localNextHopIP);
vpnExtraRoutes = VpnExtraRouteHelper.getAllVpnExtraRoutes(dataBroker,
vpnName, usedRds, localNextHopIP);
returnLocalDpnId.add(dpnId);
}
}
+ } finally {
+ lock.unlock();
}
if (!localNextHopSeen && RouteOrigin.value(vrfEntry.getOrigin()) == RouteOrigin.SELF_IMPORTED) {
java.util.Optional<Long> optionalLabel = FibUtil.getLabelFromRoutePaths(vrfEntry);
if (optionalLabel.isPresent()) {
Long label = optionalLabel.get();
List<String> 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<VpnInstanceOpDataEntry> 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 {
}
}
}
+ } finally {
+ labelLock.unlock();
}
}
}
private BigInteger checkCreateLocalFibEntry(Prefixes localNextHopInfo, String localNextHopIP,
final Long vpnId, final String rd,
final VrfEntry vrfEntry,
- Routes routes, List<Routes> vpnExtraRoutes,
+ @Nullable Routes routes, @Nullable List<Routes> vpnExtraRoutes,
int etherType) {
String vpnName = fibUtil.getVpnNameFromId(vpnId);
if (localNextHopInfo != null) {
String gwMacAddress = vrfEntry.getGatewayMacAddress();
//The loadbalancing group is created only if the extra route has multiple nexthops
//to avoid loadbalancing the discovered routes
- if (vpnExtraRoutes != null && routes != null) {
+ if (RouteOrigin.STATIC.getValue().equals(vrfEntry.getOrigin()) && vpnExtraRoutes != null
+ && routes != null) {
if (vpnExtraRoutes.size() > 1) {
groupId = nextHopManager.createNextHopGroups(vpnId, rd, dpnId, vrfEntry, routes, vpnExtraRoutes);
localGroupId = nextHopManager.getLocalSelectGroup(vpnId, vrfEntry.getDestPrefix());
private boolean isVpnPresentInDpn(String rd, BigInteger dpnId) {
InstanceIdentifier<VpnToDpnList> id = VpnHelper.getVpnToDpnListIdentifier(rd, dpnId);
Optional<VpnToDpnList> 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<LabelRouteInfo> lriIid = InstanceIdentifier.builder(LabelRouteMap.class)
- .child(LabelRouteInfo.class, new LabelRouteInfoKey(label)).build();
+ .child(LabelRouteInfo.class, label).build();
Optional<LabelRouteInfo> opResult = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, lriIid);
if (opResult.isPresent()) {
return opResult.get();
}
private boolean deleteLabelRouteInfo(LabelRouteInfo lri, String vpnInstanceName,
- TypedWriteTransaction<Operational> tx) {
+ @Nullable TypedWriteTransaction<Operational> tx) {
if (lri == null) {
return true;
}
}
String vpnName = fibUtil.getVpnNameFromId(vpnId);
- LOG.debug("createremotefibentry: adding route {} for rd {} on remoteDpnId {}",
- vrfEntry.getDestPrefix(), rd, remoteDpnId);
+ LOG.debug("createremotefibentry: adding route {} for rd {} on remoteDpnId {}", vrfEntry.getDestPrefix(), rd,
+ remoteDpnId);
- List<AdjacencyResult> 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<String> usedRds = VpnExtraRouteHelper.getUsedRds(dataBroker, vpnId, vrfEntry.getDestPrefix());
- List<Routes> 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<Routes> vpnExtraRoutes =
+ VpnExtraRouteHelper.getAllVpnExtraRoutes(dataBroker, vpnName, usedRds, vrfEntry.getDestPrefix());
if (!vpnExtraRoutes.isEmpty()) {
- List<InstructionInfo> instructions = new ArrayList<>();
- // Obtain the local routes for this particular dpn.
- java.util.Optional<Routes> 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<ActionInfo> actionInfos =
- Collections.singletonList(new ActionGroup(groupId));
- instructions.add(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);
- })));
+ 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<Routes> 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> 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<ActionInfo> actionInfos = Collections.singletonList(new ActionGroup(groupId));
+ List<InstructionInfo> 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<Configuration> tx) {
+ List<AdjacencyResult> 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,
List<String> 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) {
}
private void checkCleanUpOpDataForFib(final Prefixes prefixInfo, final Long vpnId, final String rd,
- final VrfEntry vrfEntry, final Routes extraRoute) {
+ final VrfEntry vrfEntry, @Nullable final Routes extraRoute) {
if (prefixInfo == null) {
LOG.error("Cleanup VPN Data Failed as unable to find prefix Info for prefix {} VpnId {} rd {}",
if (VrfEntry.EncapType.Mplsgre.equals(vrfEntry.getEncapType())) {
FibUtil.getLabelFromRoutePaths(vrfEntry).ifPresent(label -> {
List<String> 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<VpnInstanceOpDataEntry> vpnInstanceOpDataEntryOptional =
fibUtil.getVpnInstanceOpData(rd);
fibUtil.releaseId(FibConstants.VPN_IDPOOL_NAME, FibUtil.getNextHopLabelKey(
rd, vrfEntry.getDestPrefix()));
}
+ } finally {
+ lock.unlock();
}
});
}
return;
}
- if (optAdjacencies.get().getAdjacency().stream().count() <= 2
- && optAdjacencies.get().getAdjacency().stream().allMatch(adjacency ->
+ @NonNull List<Adjacency> adjacencies = optAdjacencies.get().nonnullAdjacency();
+ if (adjacencies.size() <= 2
+ && adjacencies.stream().allMatch(adjacency ->
adjacency.getAdjacencyType() == Adjacency.AdjacencyType.PrimaryAdjacency
&& adjacency.isMarkedForDeletion() != null
&& adjacency.isMarkedForDeletion()
})));
}
optionalLabel.ifPresent(label -> {
- 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<VpnInstanceOpDataEntry> vpnInstanceOpDataEntryOptional =
fibUtil.getVpnInstanceOpData(rd);
LOG.trace("SUBNETROUTE: deleteFibEntries: Released subnetroute label {} for rd {} prefix {}",
label, rd, vrfEntry.getDestPrefix());
}
+ } finally {
+ lock.unlock();
}
});
return;
} else {
for (BigInteger localDpnId : localDpnIdList) {
for (VpnToDpnList curDpn : vpnToDpnList) {
- if (!curDpn.getDpnId().equals(localDpnId)) {
+ if (!Objects.equals(curDpn.getDpnId(), localDpnId)) {
baseVrfEntryHandler.deleteRemoteRoute(localDpnId, curDpn.getDpnId(),
vpnInstance.getVpnId(), vrfTableKey, vrfEntry, extraRouteOptional,
TransactionAdapter.toWriteTransaction(tx));
}
}
}
- nextHopManager.removeNextHopPointer(nextHopManager
- .getRemoteSelectGroupKey(vpnInstance.getVpnId(), vrfEntry.getDestPrefix()));
- nextHopManager.removeNextHopPointer(nextHopManager
- .getLocalSelectGroupKey(vpnInstance.getVpnId(), vrfEntry.getDestPrefix()));
+ if (extraRouteOptional.isPresent()) {
+ //Remove select groups only for extra-routes
+ nextHopManager.removeNextHopPointer(nextHopManager
+ .getRemoteSelectGroupKey(vpnInstance.getVpnId(), vrfEntry.getDestPrefix()));
+ nextHopManager.removeNextHopPointer(nextHopManager
+ .getLocalSelectGroupKey(vpnInstance.getVpnId(), vrfEntry.getDestPrefix()));
+ }
})), MAX_RETRIES);
}
}
- private void makeLFibTableEntry(BigInteger dpId, long label, List<InstructionInfo> instructions, int priority,
- int addOrRemove, TypedWriteTransaction<Configuration> tx) {
+ private void makeLFibTableEntry(BigInteger dpId, long label, @Nullable List<InstructionInfo> instructions,
+ int priority, int addOrRemove, TypedWriteTransaction<Configuration> tx) {
if (tx == null) {
ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
newTx -> makeLFibTableEntry(dpId, label, instructions, priority, addOrRemove, newTx)), LOG,
}
return futures;
}
- synchronized (vpnInstance.getVpnInstanceName().intern()) {
+
+ final ReentrantLock lock = lockFor(vpnInstance);
+ lock.lock();
+ try {
futures.add(retryingTxRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, tx -> {
- 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();
List<String> 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());
ListenableFuture<List<Void>> listenableFuture = Futures.allAsList(futures);
Futures.addCallback(listenableFuture, callback, MoreExecutors.directExecutor());
}
+ } finally {
+ lock.unlock();
}
return futures;
});
if (vrfTable.isPresent()) {
jobCoordinator.enqueueJob(FibUtil.getJobKeyForVpnIdDpnId(vpnId, dpnId),
() -> 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();
}
})));
}
jobCoordinator.enqueueJob(FibUtil.getJobKeyForVpnIdDpnId(vpnId, localDpnId),
() -> 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) {
//Is this fib route an extra route? If yes, get the nexthop which would be
//an adjacency in the vpn
Optional<Routes> 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());
baseVrfEntryHandler.deleteRemoteRoute(null, localDpnId, vpnId, vrfTablesKey, modVrfEntry,
extraRouteOptional, TransactionAdapter.toWriteTransaction(tx));
}
+ } finally {
+ lock.unlock();
}
})));
}
LogicalDatastoreType.CONFIGURATION, id);
List<ListenableFuture<Void>> 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,
List<String> 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);
}
}
TransactionAdapter.toWriteTransaction(tx), txnObjects);
} else {
if (subnetRoute == null || !fibUtil
- .isInterfacePresentInDpn(vrfEntry.getParentVpnRd(), dpnId)) {
+ .isInterfacePresentInDpn(parentRd, dpnId)) {
baseVrfEntryHandler.deleteRemoteRoute(null, dpnId, vpnId,
vrfTable.get().key(), vrfEntry, extraRouteOptional,
TransactionAdapter.toWriteTransaction(tx));
}
}
}));
+ } finally {
+ lock.unlock();
}
if (callback != null) {
ListenableFuture<List<Void>> listenableFuture = Futures.allAsList(futures);
if (vrfTable.isPresent()) {
jobCoordinator.enqueueJob(FibUtil.getJobKeyForVpnIdDpnId(vpnId, dpnId),
() -> {
- 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();
}
});
}
+ tableMiss + FLOWID_PREFIX;
}
+ @Nullable
private VrfEntry getVrfEntry(DataBroker broker, String rd, String ipPrefix) {
InstanceIdentifier<VrfEntry> vrfEntryId = InstanceIdentifier.builder(FibEntries.class)
.child(VrfTables.class, new VrfTablesKey(rd))
});
}
- private boolean isPrefixAndNextHopPresentInLri(String prefix,
+ private static boolean isPrefixAndNextHopPresentInLri(String prefix,
List<String> nextHopAddressList, LabelRouteInfo lri) {
- return lri != null && lri.getPrefix().equals(prefix)
+ return lri != null && Objects.equals(lri.getPrefix(), prefix)
&& nextHopAddressList.contains(lri.getNextHopIpList().get(0));
}
}
return true;
}
+
+ private static ReentrantLock lockFor(final VpnInstanceOpDataEntry vpnInstance) {
+ // FIXME: use vpnInstance.key() instead?
+ return JvmGlobalLocks.getLockForString(vpnInstance.getVpnInstanceName());
+ }
+
+ private static ReentrantLock lockFor(LabelRouteInfoKey label) {
+ return JvmGlobalLocks.getLockFor(label);
+ }
}