*/
package org.opendaylight.netvirt.fibmanager;
+import static org.opendaylight.controller.md.sal.binding.api.WriteTransaction.CREATE_MISSING_PARENTS;
+import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
+import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
import static org.opendaylight.genius.mdsalutil.NWUtil.isIpv4Address;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.CheckedFuture;
+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.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
+import org.opendaylight.genius.datastoreutils.listeners.DataTreeEventCallbackRegistrar;
+import org.opendaylight.genius.infra.Datastore.Configuration;
+import org.opendaylight.genius.infra.Datastore.Operational;
import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
+import org.opendaylight.genius.infra.RetryingManagedNewTransactionRunner;
+import org.opendaylight.genius.infra.TransactionAdapter;
+import org.opendaylight.genius.infra.TypedReadWriteTransaction;
+import org.opendaylight.genius.infra.TypedWriteTransaction;
import org.opendaylight.genius.mdsalutil.ActionInfo;
import org.opendaylight.genius.mdsalutil.FlowEntity;
import org.opendaylight.genius.mdsalutil.InstructionInfo;
import org.opendaylight.genius.mdsalutil.MDSALUtil;
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.actions.ActionDrop;
import org.opendaylight.genius.mdsalutil.actions.ActionGroup;
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;
+import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
import org.opendaylight.netvirt.elanmanager.api.IElanService;
import org.opendaylight.netvirt.fibmanager.NexthopManager.AdjacencyResult;
import org.opendaylight.netvirt.fibmanager.api.FibHelper;
import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
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;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentrybase.RoutePaths;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesOp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.PrefixesBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntry;
private static final int IPV4_ADDR_PREFIX_LENGTH = 32;
private static final int LFIB_INTERVPN_PRIORITY = 15;
public static final BigInteger COOKIE_TUNNEL = new BigInteger("9000000", 16);
- private static final int DJC_MAX_RETRIES = 3;
+ private static final int MAX_RETRIES = 3;
private static final BigInteger COOKIE_TABLE_MISS = new BigInteger("8000004", 16);
private final DataBroker dataBroker;
private final ManagedNewTransactionRunner txRunner;
+ private final RetryingManagedNewTransactionRunner retryingTxRunner;
private final IMdsalApiManager mdsalManager;
private final NexthopManager nextHopManager;
private final BgpRouteVrfEntryHandler bgpRouteVrfEntryHandler;
private final FibUtil fibUtil;
private final InterVpnLinkCache interVpnLinkCache;
private final List<AutoCloseable> closeables = new CopyOnWriteArrayList<>();
+ private final UpgradeState upgradeState;
+ private final DataTreeEventCallbackRegistrar eventCallbacks;
@Inject
public VrfEntryListener(final DataBroker dataBroker, final IMdsalApiManager mdsalApiManager,
final RouterInterfaceVrfEntryHandler routerInterfaceVrfEntryHandler,
final JobCoordinator jobCoordinator,
final FibUtil fibUtil,
- final InterVpnLinkCache interVpnLinkCache) {
+ final InterVpnLinkCache interVpnLinkCache,
+ final UpgradeState upgradeState,
+ final DataTreeEventCallbackRegistrar eventCallbacks) {
super(VrfEntry.class, VrfEntryListener.class);
this.dataBroker = dataBroker;
this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
+ this.retryingTxRunner = new RetryingManagedNewTransactionRunner(dataBroker, MAX_RETRIES);
this.mdsalManager = mdsalApiManager;
this.nextHopManager = nexthopManager;
this.elanManager = elanManager;
this.jobCoordinator = jobCoordinator;
this.fibUtil = fibUtil;
this.interVpnLinkCache = interVpnLinkCache;
+ this.upgradeState = upgradeState;
+ this.eventCallbacks = eventCallbacks;
}
@Override
if (VrfEntry.EncapType.Vxlan.equals(vrfEntry.getEncapType())) {
LOG.info("EVPN flows need to be programmed.");
EvpnVrfEntryHandler evpnVrfEntryHandler = new EvpnVrfEntryHandler(dataBroker, this, bgpRouteVrfEntryHandler,
- nextHopManager, jobCoordinator, elanManager, fibUtil);
+ nextHopManager, jobCoordinator, fibUtil, upgradeState, eventCallbacks);
evpnVrfEntryHandler.createFlows(identifier, vrfEntry, rd);
closeables.add(evpnVrfEntryHandler);
return;
}
- RouterInterface routerInt = vrfEntry.getAugmentation(RouterInterface.class);
+ RouterInterface routerInt = vrfEntry.augmentation(RouterInterface.class);
if (routerInt != null) {
// ping responder for router interfaces
- routerInterfaceVrfEntryHandler.createFlows(identifier, vrfEntry, rd);
+ routerInterfaceVrfEntryHandler.createFlows(vrfEntry, rd);
return;
}
if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.BGP) {
if (VrfEntry.EncapType.Vxlan.equals(vrfEntry.getEncapType())) {
LOG.info("EVPN flows to be deleted");
EvpnVrfEntryHandler evpnVrfEntryHandler = new EvpnVrfEntryHandler(dataBroker, this, bgpRouteVrfEntryHandler,
- nextHopManager, jobCoordinator, elanManager, fibUtil);
+ nextHopManager, jobCoordinator, fibUtil, upgradeState, eventCallbacks);
evpnVrfEntryHandler.removeFlows(identifier, vrfEntry, rd);
closeables.add(evpnVrfEntryHandler);
return;
}
- RouterInterface routerInt = vrfEntry.getAugmentation(RouterInterface.class);
+ RouterInterface routerInt = vrfEntry.augmentation(RouterInterface.class);
if (routerInt != null) {
// ping responder for router interfaces
- routerInterfaceVrfEntryHandler.removeFlows(identifier, vrfEntry, rd);
+ routerInterfaceVrfEntryHandler.removeFlows(vrfEntry, rd);
return;
}
if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.BGP) {
//Update the used rds and vpntoextraroute containers only for the deleted nextHops.
List<String> nextHopsRemoved = FibHelper.getNextHopListFromRoutePaths(original);
nextHopsRemoved.removeAll(FibHelper.getNextHopListFromRoutePaths(update));
- WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
- nextHopsRemoved.parallelStream()
- .forEach(nextHopRemoved -> fibUtil.updateUsedRdAndVpnToExtraRoute(
- writeOperTxn, nextHopRemoved, rd, update.getDestPrefix()));
- CheckedFuture<Void, TransactionCommitFailedException> operFuture = writeOperTxn.submit();
- try {
- operFuture.get();
- } catch (InterruptedException | ExecutionException e) {
- LOG.error("Exception encountered while submitting operational future for update vrfentry {}: "
- + "{}", update, e);
- }
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ ListenableFuture<Void> configFuture =
+ txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, configTx ->
+ futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, operTx ->
+ nextHopsRemoved.parallelStream()
+ .forEach(nextHopRemoved -> {
+ try {
+ fibUtil.updateUsedRdAndVpnToExtraRoute(
+ configTx, operTx, nextHopRemoved, rd, update.getDestPrefix());
+ } catch (ExecutionException | InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }))));
+ futures.add(configFuture);
+ Futures.addCallback(configFuture, new FutureCallback<Void>() {
+ @Override
+ public void onSuccess(Void result) {
+ createFibEntries(identifier, update);
+ LOG.info("UPDATE: Updated static Fib Entry with rd {} prefix {} route-paths {}",
+ rd, update.getDestPrefix(), update.getRoutePaths());
+ }
- createFibEntries(identifier, update);
- LOG.info("UPDATE: Updated static Fib Entry with rd {} prefix {} route-paths {}",
- rd, update.getDestPrefix(), update.getRoutePaths());
+ @Override
+ public void onFailure(Throwable throwable) {
+ LOG.error("Exception encountered while submitting operational future for update vrfentry {}",
+ update, throwable);
+ }
+ }, MoreExecutors.directExecutor());
return;
}
}
final Long vpnId = vpnInstance.getVpnId();
final String rd = vrfTableKey.getRouteDistinguisher();
- SubnetRoute subnetRoute = vrfEntry.getAugmentation(SubnetRoute.class);
+ SubnetRoute subnetRoute = vrfEntry.augmentation(SubnetRoute.class);
if (subnetRoute != null) {
final long elanTag = subnetRoute.getElantag();
LOG.trace("SUBNETROUTE: createFibEntries: SubnetRoute augmented vrfentry found for rd {} prefix {}"
+ " with elantag {}", rd, vrfEntry.getDestPrefix(), elanTag);
if (vpnToDpnList != null) {
- jobCoordinator.enqueueJob(FibUtil.getJobKeyForRdPrefix(rd, vrfEntry.getDestPrefix()), () -> {
- WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
- for (final VpnToDpnList curDpn : vpnToDpnList) {
- if (curDpn.getDpnState() == VpnToDpnList.DpnState.Active) {
- installSubnetRouteInFib(curDpn.getDpnId(), elanTag, rd, vpnId, vrfEntry, tx);
- installSubnetBroadcastAddrDropRule(curDpn.getDpnId(), rd, vpnId.longValue(),
- vrfEntry, NwConstants.ADD_FLOW, tx);
- }
- }
- List<ListenableFuture<Void>> futures = new ArrayList<>();
- futures.add(tx.submit());
- return futures;
- });
+ jobCoordinator.enqueueJob(FibUtil.getJobKeyForRdPrefix(rd, vrfEntry.getDestPrefix()),
+ () -> Collections.singletonList(
+ txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
+ for (final VpnToDpnList curDpn : vpnToDpnList) {
+ if (curDpn.getDpnState() == VpnToDpnList.DpnState.Active) {
+ installSubnetRouteInFib(curDpn.getDpnId(), elanTag, rd, vpnId, vrfEntry, tx);
+ installSubnetBroadcastAddrDropRule(curDpn.getDpnId(), rd, vpnId.longValue(),
+ vrfEntry, NwConstants.ADD_FLOW, tx);
+ }
+ }
+ })));
}
return;
}
+ // Get etherType value based on the IpPrefix address family type
+ int etherType;
+ try {
+ etherType = NWUtil.getEtherTypeFromIpPrefix(vrfEntry.getDestPrefix());
+ } catch (IllegalArgumentException ex) {
+ LOG.error("Unable to get etherType for IP Prefix {}", vrfEntry.getDestPrefix());
+ return;
+ }
- final List<BigInteger> localDpnIdList = createLocalFibEntry(vpnInstance.getVpnId(), rd, vrfEntry);
+ final List<BigInteger> localDpnIdList = createLocalFibEntry(vpnInstance.getVpnId(), rd, vrfEntry, etherType);
if (!localDpnIdList.isEmpty() && vpnToDpnList != null) {
- jobCoordinator.enqueueJob(FibUtil.getJobKeyForRdPrefix(rd, vrfEntry.getDestPrefix()), () -> {
- WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
- synchronized (vpnInstance.getVpnInstanceName().intern()) {
- for (VpnToDpnList vpnDpn : vpnToDpnList) {
- if (!localDpnIdList.contains(vpnDpn.getDpnId())) {
- if (vpnDpn.getDpnState() == VpnToDpnList.DpnState.Active) {
- try {
- if (RouteOrigin.BGP.getValue().equals(vrfEntry.getOrigin())) {
- bgpRouteVrfEntryHandler.createRemoteFibEntry(vpnDpn.getDpnId(),
- vpnId, vrfTableKey.getRouteDistinguisher(), vrfEntry, tx, txnObjects);
- } else {
- createRemoteFibEntry(vpnDpn.getDpnId(), vpnInstance.getVpnId(),
- vrfTableKey.getRouteDistinguisher(), vrfEntry, tx);
+ jobCoordinator.enqueueJob(FibUtil.getJobKeyForRdPrefix(rd, vrfEntry.getDestPrefix()),
+ () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
+ final ReentrantLock lock = lockFor(vpnInstance);
+ lock.lock();
+ try {
+ for (VpnToDpnList vpnDpn : vpnToDpnList) {
+ if (!localDpnIdList.contains(vpnDpn.getDpnId())) {
+ if (vpnDpn.getDpnState() == VpnToDpnList.DpnState.Active) {
+ try {
+ if (RouteOrigin.BGP.getValue().equals(vrfEntry.getOrigin())) {
+ bgpRouteVrfEntryHandler.createRemoteFibEntry(vpnDpn.getDpnId(),
+ vpnId, vrfTableKey.getRouteDistinguisher(), vrfEntry,
+ TransactionAdapter.toWriteTransaction(tx),
+ txnObjects);
+ } else {
+ createRemoteFibEntry(vpnDpn.getDpnId(), vpnInstance.getVpnId(),
+ vrfTableKey.getRouteDistinguisher(), vrfEntry, tx);
+ }
+ } catch (NullPointerException e) {
+ LOG.error("Failed to get create remote fib flows for prefix {} ",
+ vrfEntry.getDestPrefix(), e);
}
- } catch (NullPointerException e) {
- LOG.error("Failed to get create remote fib flows for prefix {} ",
- vrfEntry.getDestPrefix(), e);
}
}
}
+ } finally {
+ lock.unlock();
}
- }
- List<ListenableFuture<Void>> futures = new ArrayList<>();
- futures.add(tx.submit());
- return futures;
- }, DJC_MAX_RETRIES);
+ })), MAX_RETRIES);
}
Optional<String> optVpnUuid = fibUtil.getVpnNameFromRd(rd);
// This is an static route that points to the other endpoint of an InterVpnLink
// In that case, we should add another entry in FIB table pointing to LPortDispatcher table.
installIVpnLinkSwitchingFlows(interVpnLink, vpnUuid, vrfEntry, vpnId);
- installInterVpnRouteInLFib(interVpnLink, vpnUuid, vrfEntry);
+ installInterVpnRouteInLFib(interVpnLink, vpnUuid, vrfEntry, etherType);
}
});
}
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());
}
void installSubnetRouteInFib(final BigInteger dpnId, final long elanTag, final String rd,
- final long vpnId, final VrfEntry vrfEntry, WriteTransaction tx) {
- Boolean wrTxPresent = true;
+ final long vpnId, final VrfEntry vrfEntry, TypedWriteTransaction<Configuration> tx) {
if (tx == null) {
- wrTxPresent = false;
- tx = dataBroker.newWriteOnlyTransaction();
+ ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
+ newTx -> installSubnetRouteInFib(dpnId, elanTag, rd, vpnId, vrfEntry, newTx)), LOG,
+ "Error installing subnet route in FIB");
+ return;
+ }
+ int etherType;
+ try {
+ etherType = NWUtil.getEtherTypeFromIpPrefix(vrfEntry.getDestPrefix());
+ } catch (IllegalArgumentException ex) {
+ LOG.error("Unable to get etherType for IP Prefix {}", vrfEntry.getDestPrefix());
+ return;
}
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<>();
instructions.add(new InstructionWriteMetadata(subnetRouteMeta, MetaDataUtil.METADATA_MASK_SUBNET_ROUTE));
instructions.add(new InstructionGotoTable(NwConstants.L3_SUBNET_ROUTE_TABLE));
baseVrfEntryHandler.makeConnectedRoute(dpnId, vpnId, vrfEntry, rd, instructions,
- NwConstants.ADD_FLOW, tx, null);
-
+ NwConstants.ADD_FLOW, TransactionAdapter.toWriteTransaction(tx), null);
if (vrfEntry.getRoutePaths() != null) {
for (RoutePaths routePath : vrfEntry.getRoutePaths()) {
if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.SELF_IMPORTED) {
List<ActionInfo> actionsInfos = new ArrayList<>();
// reinitialize instructions list for LFIB Table
final List<InstructionInfo> LFIBinstructions = new ArrayList<>();
-
- actionsInfos.add(new ActionPopMpls());
+ actionsInfos.add(new ActionPopMpls(etherType));
LFIBinstructions.add(new InstructionApplyActions(actionsInfos));
LFIBinstructions.add(new InstructionWriteMetadata(subnetRouteMeta,
MetaDataUtil.METADATA_MASK_SUBNET_ROUTE));
}
}
}
- if (!wrTxPresent) {
- tx.submit();
- }
}
private void installSubnetBroadcastAddrDropRule(final BigInteger dpnId, final String rd, final long vpnId,
- final VrfEntry vrfEntry, int addOrRemove, WriteTransaction tx) {
+ final VrfEntry vrfEntry, int addOrRemove, TypedWriteTransaction<Configuration> tx) {
List<MatchInfo> matches = new ArrayList<>();
LOG.debug("SUBNETROUTE: installSubnetBroadcastAddrDropRule: destPrefix {} rd {} vpnId {} dpnId {}",
Node nodeDpn = FibUtil.buildDpnNode(dpnId);
InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
- .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
+ .child(Node.class, nodeDpn.key()).augmentation(FlowCapableNode.class)
.child(Table.class, new TableKey(flow.getTableId())).child(Flow.class, flowKey).build();
if (addOrRemove == NwConstants.ADD_FLOW) {
- tx.put(LogicalDatastoreType.CONFIGURATION, flowInstanceId,flow, true);
+ tx.put(flowInstanceId,flow, true);
} else {
- tx.delete(LogicalDatastoreType.CONFIGURATION, flowInstanceId);
+ tx.delete(flowInstanceId);
}
}
* LportDispatcher table (via table 80)
*/
private void installInterVpnRouteInLFib(final InterVpnLinkDataComposite interVpnLink, final String vpnName,
- final VrfEntry vrfEntry) {
+ final VrfEntry vrfEntry, int etherType) {
// INTERVPN routes are routes in a Vpn1 that have been leaked to Vpn2. In DC-GW, this Vpn2 route is pointing
// to a list of DPNs where Vpn2's VpnLink was instantiated. In these DPNs LFIB must be programmed so that the
// packet is commuted from Vpn2 to Vpn1.
return;
}
- List<BigInteger> targetDpns = interVpnLink.getEndpointDpnsByVpnName(vpnName);
Optional<Long> optLportTag = interVpnLink.getEndpointLportTagByVpnName(vpnName);
if (!optLportTag.isPresent()) {
LOG.warn("Could not retrieve lportTag for VPN {} endpoint in InterVpnLink {}", vpnName, interVpnLinkName);
vrfEntry.getDestPrefix(), vrfEntry.getRoutePaths());
return;
}
- List<ActionInfo> actionsInfos = Collections.singletonList(new ActionPopMpls());
+ List<ActionInfo> actionsInfos = Collections.singletonList(new ActionPopMpls(etherType));
List<InstructionInfo> instructions = Arrays.asList(
new InstructionApplyActions(actionsInfos),
new InstructionWriteMetadata(MetaDataUtil.getMetaDataForLPortDispatcher(lportTag.intValue(),
MetaDataUtil.getMetaDataMaskForLPortDispatcher()),
new InstructionGotoTable(NwConstants.L3_INTERFACE_TABLE));
List<String> interVpnNextHopList = FibHelper.getNextHopListFromRoutePaths(vrfEntry);
+ List<BigInteger> targetDpns = interVpnLink.getEndpointDpnsByVpnName(vpnName);
for (BigInteger dpId : targetDpns) {
LOG.debug("Installing flow: VrfEntry=[prefix={} label={} nexthop={}] dpn {} for InterVpnLink {} in LFIB",
}
}
- private List<BigInteger> createLocalFibEntry(Long vpnId, String rd, VrfEntry vrfEntry) {
+ private List<BigInteger> createLocalFibEntry(Long vpnId, String rd, VrfEntry vrfEntry, int etherType) {
List<BigInteger> returnLocalDpnId = new ArrayList<>();
String localNextHopIP = vrfEntry.getDestPrefix();
Prefixes localNextHopInfo = fibUtil.getPrefixToInterface(vpnId, localNextHopIP);
String vpnName = fibUtil.getVpnNameFromId(vpnId);
if (localNextHopInfo == null) {
- List<String> usedRds = VpnExtraRouteHelper.getUsedRds(dataBroker, vpnId, localNextHopIP);
- List<Routes> vpnExtraRoutes = VpnExtraRouteHelper.getAllVpnExtraRoutes(dataBroker,
- vpnName, usedRds, localNextHopIP);
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<Routes> 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<String> 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, vpnId, vpnExtraRoute, vpnExtraRoutes);
- 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<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 {
label, localNextHopInfo.getVpnInterfaceName(), lri.getDpnId());
if (vpnExtraRoutes.isEmpty()) {
BigInteger dpnId = checkCreateLocalFibEntry(localNextHopInfo, localNextHopIP,
- vpnId, rd, vrfEntry, lri.getParentVpnid(), null, vpnExtraRoutes);
+ vpnId, rd, vrfEntry, null, vpnExtraRoutes, etherType);
returnLocalDpnId.add(dpnId);
} else {
for (Routes extraRoutes : vpnExtraRoutes) {
- BigInteger dpnId = checkCreateLocalFibEntry(localNextHopInfo,
- localNextHopIP,
- vpnId, rd, vrfEntry, lri.getParentVpnid(),
- extraRoutes, vpnExtraRoutes);
+ BigInteger dpnId = checkCreateLocalFibEntry(localNextHopInfo, localNextHopIP,
+ vpnId, rd, vrfEntry, extraRoutes, vpnExtraRoutes, etherType);
returnLocalDpnId.add(dpnId);
}
}
}
}
+ } finally {
+ labelLock.unlock();
}
}
}
}
} else {
BigInteger dpnId = checkCreateLocalFibEntry(localNextHopInfo, localNextHopIP, vpnId,
- rd, vrfEntry, vpnId, /*routes*/ null, /*vpnExtraRoutes*/ null);
+ rd, vrfEntry, /*routes*/ null, /*vpnExtraRoutes*/ null, etherType);
if (dpnId != null) {
returnLocalDpnId.add(dpnId);
}
private BigInteger checkCreateLocalFibEntry(Prefixes localNextHopInfo, String localNextHopIP,
final Long vpnId, final String rd,
- final VrfEntry vrfEntry, Long parentVpnId,
- Routes routes, List<Routes> vpnExtraRoutes) {
+ final VrfEntry vrfEntry,
+ @Nullable Routes routes, @Nullable List<Routes> vpnExtraRoutes,
+ int etherType) {
String vpnName = fibUtil.getVpnNameFromId(vpnId);
if (localNextHopInfo != null) {
long groupId;
+ " FIB processing", vrfEntry.getDestPrefix(), vpnId, rd, dpnId);
return dpnId;
}
- String jobKey = FibUtil.getCreateLocalNextHopJobKey(vpnId, dpnId, vrfEntry.getDestPrefix());
+ if (!isVpnPresentInDpn(rd, dpnId)) {
+ LOG.error("checkCreateLocalFibEntry: The VPN with id {} rd {} is not available on dpn {}",
+ vpnId, rd, dpnId.toString());
+ return BigInteger.ZERO;
+ }
String interfaceName = localNextHopInfo.getVpnInterfaceName();
String prefix = vrfEntry.getDestPrefix();
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) {
- if (isIpv4Address(routes.getNexthopIpList().get(0))) {
- localNextHopIP = routes.getNexthopIpList().get(0) + NwConstants.IPV4PREFIX;
- } else {
- localNextHopIP = routes.getNexthopIpList().get(0) + NwConstants.IPV6PREFIX;
- }
+ if (RouteOrigin.STATIC.getValue().equals(vrfEntry.getOrigin()) && vpnExtraRoutes != null
+ && routes != null) {
if (vpnExtraRoutes.size() > 1) {
- groupId = nextHopManager.createNextHopGroups(parentVpnId, rd, dpnId, vrfEntry, routes,
- vpnExtraRoutes);
- localGroupId = nextHopManager.getLocalNextHopGroup(parentVpnId, localNextHopIP);
- } else if (routes.getNexthopIpList().size() > 1) {
- groupId = nextHopManager.createNextHopGroups(parentVpnId, rd, dpnId, vrfEntry, routes,
- vpnExtraRoutes);
- localGroupId = groupId;
+ groupId = nextHopManager.createNextHopGroups(vpnId, rd, dpnId, vrfEntry, routes, vpnExtraRoutes);
+ localGroupId = nextHopManager.getLocalSelectGroup(vpnId, vrfEntry.getDestPrefix());
} else {
- groupId = nextHopManager.getLocalNextHopGroup(parentVpnId, localNextHopIP);
+ groupId = nextHopManager.createNextHopGroups(vpnId, rd, dpnId, vrfEntry, routes, vpnExtraRoutes);
localGroupId = groupId;
}
} else {
- groupId = nextHopManager.createLocalNextHop(parentVpnId, dpnId, interfaceName, localNextHopIP, prefix,
- gwMacAddress, jobKey);
+ groupId = nextHopManager.createLocalNextHop(vpnId, dpnId, interfaceName, localNextHopIP, prefix,
+ gwMacAddress);
localGroupId = groupId;
}
if (groupId == FibConstants.INVALID_GROUP_ID) {
Collections.singletonList(new ActionGroup(groupId))));
final List<InstructionInfo> lfibinstructions = Collections.singletonList(
new InstructionApplyActions(
- Arrays.asList(new ActionPopMpls(), new ActionGroup(groupId))));
+ Arrays.asList(new ActionPopMpls(etherType), new ActionGroup(localGroupId))));
java.util.Optional<Long> optLabel = FibUtil.getLabelFromRoutePaths(vrfEntry);
List<String> nextHopAddressList = FibHelper.getNextHopListFromRoutePaths(vrfEntry);
- jobCoordinator.enqueueJob(jobKey, () -> {
- WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
- baseVrfEntryHandler.makeConnectedRoute(dpnId, vpnId, vrfEntry, rd, instructions,
- NwConstants.ADD_FLOW, tx, null);
- if (!fibUtil.enforceVxlanDatapathSemanticsforInternalRouterVpn(localNextHopInfo.getSubnetId(),
- vpnName, rd)) {
- optLabel.ifPresent(label -> {
- if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.SELF_IMPORTED) {
- LOG.debug("Installing LFIB and tunnel table entry on dpn {} for interface {} with label "
- + "{}, rd {}, prefix {}, nexthop {}", dpnId,
- localNextHopInfo.getVpnInterfaceName(), optLabel, rd, vrfEntry.getDestPrefix(),
- nextHopAddressList);
- makeLFibTableEntry(dpnId, label, lfibinstructions, DEFAULT_FIB_FLOW_PRIORITY,
- NwConstants.ADD_FLOW, tx);
- // If the extra-route is reachable from VMs attached to the same switch,
- // then the tunnel table can point to the load balancing group.
- // If it is reachable from VMs attached to different switches,
- // then it should be pointing to one of the local group in order to avoid looping.
- if (vrfEntry.getRoutePaths().size() == 1) {
- makeTunnelTableEntry(dpnId, label, groupId, tx);
- } else {
+ String jobKey = FibUtil.getCreateLocalNextHopJobKey(vpnId, dpnId, vrfEntry.getDestPrefix());
+ jobCoordinator.enqueueJob(jobKey,
+ () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
+ baseVrfEntryHandler.makeConnectedRoute(dpnId, vpnId, vrfEntry, rd, instructions,
+ NwConstants.ADD_FLOW, TransactionAdapter.toWriteTransaction(tx), null);
+ if (FibUtil.isBgpVpn(vpnName, rd)) {
+ optLabel.ifPresent(label -> {
+ if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.SELF_IMPORTED) {
+ LOG.debug(
+ "Installing LFIB and tunnel table entry on dpn {} for interface {} with label "
+ + "{}, rd {}, prefix {}, nexthop {}", dpnId,
+ localNextHopInfo.getVpnInterfaceName(), optLabel, rd, vrfEntry.getDestPrefix(),
+ nextHopAddressList);
+ makeLFibTableEntry(dpnId, label, lfibinstructions, DEFAULT_FIB_FLOW_PRIORITY,
+ NwConstants.ADD_FLOW, tx);
makeTunnelTableEntry(dpnId, label, localGroupId, tx);
+ } else {
+ LOG.debug("Route with rd {} prefix {} label {} nexthop {} for vpn {} is an imported "
+ + "route. LFib and Terminating table entries will not be created.",
+ rd, vrfEntry.getDestPrefix(), optLabel, nextHopAddressList, vpnId);
}
- } else {
- LOG.debug("Route with rd {} prefix {} label {} nexthop {} for vpn {} is an imported "
- + "route. LFib and Terminating table entries will not be created.",
- rd, vrfEntry.getDestPrefix(), optLabel, nextHopAddressList, vpnId);
- }
- });
- }
- List<ListenableFuture<Void>> futures = new ArrayList<>();
- futures.add(tx.submit());
- return futures;
- });
+ });
+ }
+ })));
return dpnId;
}
LOG.error("localNextHopInfo received is null for prefix {} on rd {} on vpn {}", vrfEntry.getDestPrefix(), rd,
return BigInteger.ZERO;
}
+ private boolean isVpnPresentInDpn(String rd, BigInteger dpnId) {
+ InstanceIdentifier<VpnToDpnList> id = VpnHelper.getVpnToDpnListIdentifier(rd, dpnId);
+ Optional<VpnToDpnList> dpnInVpn = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
+ 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();
return null;
}
- private boolean deleteLabelRouteInfo(LabelRouteInfo lri, String vpnInstanceName, WriteTransaction tx) {
+ private boolean deleteLabelRouteInfo(LabelRouteInfo lri, String vpnInstanceName,
+ @Nullable TypedWriteTransaction<Operational> tx) {
if (lri == null) {
return true;
}
if (vpnInstancesList.isEmpty()) {
LOG.debug("deleting LRI instance object for label {}", lri.getLabel());
if (tx != null) {
- tx.delete(LogicalDatastoreType.OPERATIONAL, lriId);
+ tx.delete(lriId);
} else {
MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, lriId);
}
}
void makeTunnelTableEntry(BigInteger dpId, long label, long groupId/*String egressInterfaceName*/,
- WriteTransaction tx) {
+ TypedWriteTransaction<Configuration> tx) {
List<ActionInfo> actionsInfos = Collections.singletonList(new ActionGroup(groupId));
createTerminatingServiceActions(dpId, (int) label, actionsInfos, tx);
}
public void createTerminatingServiceActions(BigInteger destDpId, int label, List<ActionInfo> actionsInfos,
- WriteTransaction tx) {
+ TypedWriteTransaction<Configuration> tx) {
List<MatchInfo> mkMatches = new ArrayList<>();
LOG.debug("create terminatingServiceAction on DpnId = {} and serviceId = {} and actions = {}",
Node nodeDpn = FibUtil.buildDpnNode(terminatingServiceTableFlowEntity.getDpnId());
InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
- .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
+ .child(Node.class, nodeDpn.key()).augmentation(FlowCapableNode.class)
.child(Table.class, new TableKey(terminatingServiceTableFlowEntity.getTableId()))
.child(Flow.class, flowKey).build();
- tx.put(LogicalDatastoreType.CONFIGURATION, flowInstanceId, flowbld.build(),
- WriteTransaction.CREATE_MISSING_PARENTS);
+ tx.put(flowInstanceId, flowbld.build(), CREATE_MISSING_PARENTS);
}
- private void removeTunnelTableEntry(BigInteger dpId, long label, WriteTransaction tx) {
+ private void removeTunnelTableEntry(BigInteger dpId, long label, TypedWriteTransaction<Configuration> tx) {
FlowEntity flowEntity;
LOG.debug("remove terminatingServiceActions called with DpnId = {} and label = {}", dpId, label);
List<MatchInfo> mkMatches = new ArrayList<>();
Node nodeDpn = FibUtil.buildDpnNode(flowEntity.getDpnId());
FlowKey flowKey = new FlowKey(new FlowId(flowEntity.getFlowId()));
InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
- .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
+ .child(Node.class, nodeDpn.key()).augmentation(FlowCapableNode.class)
.child(Table.class, new TableKey(flowEntity.getTableId())).child(Flow.class, flowKey).build();
- tx.delete(LogicalDatastoreType.CONFIGURATION, flowInstanceId);
+ tx.delete(flowInstanceId);
LOG.debug("Terminating service Entry for dpID {} : label : {} removed successfully", dpId, label);
}
List<BigInteger> returnLocalDpnId = new ArrayList<>();
Prefixes localNextHopInfo = fibUtil.getPrefixToInterface(vpnId, vrfEntry.getDestPrefix());
String vpnName = fibUtil.getVpnNameFromId(vpnId);
- boolean isExtraroute = false;
+ boolean shouldUpdateNonEcmpLocalNextHop = true;
if (localNextHopInfo == null) {
List<String> usedRds = VpnExtraRouteHelper.getUsedRds(dataBroker, vpnId, vrfEntry.getDestPrefix());
if (usedRds.size() > 1) {
vrfEntry.getDestPrefix(), vpnName, rd);
return returnLocalDpnId;
}
+ String vpnRd = !usedRds.isEmpty() ? usedRds.get(0) : rd;
//Is this fib route an extra route? If yes, get the nexthop which would be an adjacency
//in the vpn
Optional<Routes> extraRouteOptional = VpnExtraRouteHelper.getVpnExtraroutes(dataBroker,
- vpnName, rd, vrfEntry.getDestPrefix());
+ vpnName, vpnRd, vrfEntry.getDestPrefix());
if (extraRouteOptional.isPresent()) {
- isExtraroute = true;
Routes extraRoute = extraRouteOptional.get();
String ipPrefix;
if (isIpv4Address(extraRoute.getNexthopIpList().get(0))) {
} else {
ipPrefix = extraRoute.getNexthopIpList().get(0) + NwConstants.IPV6PREFIX;
}
+ if (extraRoute.getNexthopIpList().size() > 1) {
+ shouldUpdateNonEcmpLocalNextHop = false;
+ }
localNextHopInfo = fibUtil.getPrefixToInterface(vpnId, ipPrefix);
if (localNextHopInfo != null) {
String localNextHopIP = localNextHopInfo.getIpAddress();
- BigInteger dpnId = checkDeleteLocalFibEntry(localNextHopInfo, localNextHopIP,
- vpnId, rd, vrfEntry, isExtraroute, vpnId /*parentVpnId*/);
+ BigInteger dpnId = checkDeleteLocalFibEntry(localNextHopInfo, localNextHopIP, vpnName, vpnId, rd,
+ vrfEntry, shouldUpdateNonEcmpLocalNextHop);
if (!dpnId.equals(BigInteger.ZERO)) {
LOG.trace("Deleting ECMP group for prefix {}, dpn {}", vrfEntry.getDestPrefix(), dpnId);
- nextHopManager.setupLoadBalancingNextHop(vpnId, dpnId,
- vrfEntry.getDestPrefix(), /*listBucketInfo*/ Collections.emptyList(),
- /*remove*/ false);
+ nextHopManager.deleteLoadBalancingNextHop(vpnId, dpnId, vrfEntry.getDestPrefix());
returnLocalDpnId.add(dpnId);
}
} else {
PrefixesBuilder prefixBuilder = new PrefixesBuilder();
prefixBuilder.setDpnId(lri.getDpnId());
BigInteger dpnId = checkDeleteLocalFibEntry(prefixBuilder.build(), nextHopAddressList.get(0),
- vpnId, rd, vrfEntry, isExtraroute, lri.getParentVpnid());
+ vpnName, vpnId, rd, vrfEntry, shouldUpdateNonEcmpLocalNextHop);
if (!dpnId.equals(BigInteger.ZERO)) {
returnLocalDpnId.add(dpnId);
}
} else {
LOG.debug("Obtained prefix to interface for rd {} prefix {}", rd, vrfEntry.getDestPrefix());
String localNextHopIP = localNextHopInfo.getIpAddress();
- BigInteger dpnId = checkDeleteLocalFibEntry(localNextHopInfo, localNextHopIP,
- vpnId, rd, vrfEntry, isExtraroute, vpnId /*parentVpnId*/);
+ BigInteger dpnId = checkDeleteLocalFibEntry(localNextHopInfo, localNextHopIP, vpnName, vpnId, rd, vrfEntry,
+ shouldUpdateNonEcmpLocalNextHop);
if (!dpnId.equals(BigInteger.ZERO)) {
returnLocalDpnId.add(dpnId);
}
}
private BigInteger checkDeleteLocalFibEntry(Prefixes localNextHopInfo, final String localNextHopIP,
- final Long vpnId, final String rd, final VrfEntry vrfEntry,
- boolean isExtraroute, final Long parentVpnId) {
+ final String vpnName, final Long vpnId, final String rd, final VrfEntry vrfEntry,
+ boolean shouldUpdateNonEcmpLocalNextHop) {
if (localNextHopInfo != null) {
final BigInteger dpnId = localNextHopInfo.getDpnId();
if (Prefixes.PrefixCue.Nat.equals(localNextHopInfo.getPrefixCue())) {
return dpnId;
}
- jobCoordinator.enqueueJob(FibUtil.getCreateLocalNextHopJobKey(vpnId, dpnId,
- vrfEntry.getDestPrefix()), () -> {
- WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
+ jobCoordinator.enqueueJob(FibUtil.getCreateLocalNextHopJobKey(vpnId, dpnId, vrfEntry.getDestPrefix()),
+ () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
baseVrfEntryHandler.makeConnectedRoute(dpnId, vpnId, vrfEntry, rd, null,
- NwConstants.DEL_FLOW, tx, null);
- if (!fibUtil.enforceVxlanDatapathSemanticsforInternalRouterVpn(localNextHopInfo.getSubnetId(),
- vpnId, rd)) {
+ NwConstants.DEL_FLOW, TransactionAdapter.toWriteTransaction(tx), null);
+ if (FibUtil.isBgpVpn(vpnName, rd)) {
if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.SELF_IMPORTED) {
FibUtil.getLabelFromRoutePaths(vrfEntry).ifPresent(label -> {
makeLFibTableEntry(dpnId, label, null /* instructions */, DEFAULT_FIB_FLOW_PRIORITY,
});
}
}
- List<ListenableFuture<Void>> futures = new ArrayList<>();
- futures.add(tx.submit());
- return futures;
- });
+ })));
//TODO: verify below adjacency call need to be optimized (?)
//In case of the removal of the extra route, the loadbalancing group is updated
- if (!isExtraroute) {
- baseVrfEntryHandler.deleteLocalAdjacency(dpnId, parentVpnId, localNextHopIP, vrfEntry.getDestPrefix());
+ if (shouldUpdateNonEcmpLocalNextHop) {
+ baseVrfEntryHandler.deleteLocalAdjacency(dpnId, vpnId, localNextHopIP, vrfEntry.getDestPrefix());
}
return dpnId;
}
}
private void createRemoteFibEntry(final BigInteger remoteDpnId, final long vpnId, String rd,
- final VrfEntry vrfEntry, WriteTransaction tx) {
- Boolean wrTxPresent = true;
+ final VrfEntry vrfEntry, TypedWriteTransaction<Configuration> tx) {
if (tx == null) {
- wrTxPresent = false;
- tx = dataBroker.newWriteOnlyTransaction();
+ ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
+ newTx -> createRemoteFibEntry(remoteDpnId, vpnId, rd, vrfEntry, newTx)), LOG,
+ "Error creating remote FIB entry");
+ return;
}
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
- if (!vpnExtraRoutes.isEmpty() && (vpnExtraRoutes.size() > 1
- || vpnExtraRoutes.get(0).getNexthopIpList().size() > 1)) {
- 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));
- baseVrfEntryHandler.makeConnectedRoute(remoteDpnId, vpnId, vrfEntry, rd, instructions,
- NwConstants.ADD_FLOW, tx, null);
+ List<Routes> vpnExtraRoutes =
+ VpnExtraRouteHelper.getAllVpnExtraRoutes(dataBroker, vpnName, usedRds, vrfEntry.getDestPrefix());
+ if (!vpnExtraRoutes.isEmpty()) {
+ programRemoteFibWithLoadBalancingGroups(remoteDpnId, vpnId, rd, vrfEntry, vpnExtraRoutes);
} else {
- baseVrfEntryHandler.programRemoteFib(remoteDpnId, vpnId, vrfEntry, tx, rd, adjacencyResults, null);
+ // Program in case of other static VRF entries like floating IPs
+ programRemoteFibEntry(remoteDpnId, vpnId, rd, vrfEntry, tx);
}
+ }
- if (!wrTxPresent) {
- tx.submit();
+ 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 {}",
public List<ListenableFuture<Void>> call() {
// If another renderer(for eg : CSS) needs to be supported, check can be performed here
// to call the respective helpers.
- return Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+ return Collections.singletonList(txRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, tx -> {
//First Cleanup LabelRouteInfo
//TODO(KIRAN) : Move the below block when addressing iRT/eRT for L3VPN Over VxLan
LOG.debug("cleanupVpnInterfaceWorker: rd {} prefix {}", rd, prefixInfo.getIpAddress());
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();
}
});
}
String vpnName = null;
if (Prefixes.PrefixCue.PhysNetFunc.equals(prefixInfo.getPrefixCue())) {
- /*Get vpnId for rd = networkId since op vpnInterface will be pointing to rd = networkId
- * */
+ // Get vpnId for rd = networkId since op vpnInterface will be pointing to rd = networkId
Optional<String> vpnNameOpt = fibUtil.getVpnNameFromRd(vrfEntry.getParentVpnRd());
if (vpnNameOpt.isPresent()) {
vpnId = fibUtil.getVpnId(vpnNameOpt.get());
}
if (optVpnName.isPresent()) {
vpnName = optVpnName.get();
- Optional<VpnInterfaceOpDataEntry> opVpnInterface = MDSALUtil
- .read(dataBroker, LogicalDatastoreType.OPERATIONAL,
- fibUtil.getVpnInterfaceOpDataEntryIdentifier(ifName, vpnName));
+ Optional<VpnInterfaceOpDataEntry> opVpnInterface = tx
+ .read(FibUtil.getVpnInterfaceOpDataEntryIdentifier(ifName, vpnName)).get();
if (opVpnInterface.isPresent()) {
long associatedVpnId = fibUtil.getVpnId(vpnName);
if (vpnId != associatedVpnId) {
//Only one used Rd present in case of removal event
String usedRd = usedRds.get(0);
if (optVpnName.isPresent()) {
- tx.delete(LogicalDatastoreType.OPERATIONAL,
- baseVrfEntryHandler.getVpnToExtrarouteIdentifier(vpnName, usedRd,
+ tx.delete(BaseVrfEntryHandler.getVpnToExtrarouteIdentifier(vpnName, usedRd,
vrfEntry.getDestPrefix()));
- tx.delete(LogicalDatastoreType.CONFIGURATION,
- VpnExtraRouteHelper.getUsedRdsIdentifier(vpnId, vrfEntry.getDestPrefix()));
+ txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, configTx ->
+ configTx.delete(VpnExtraRouteHelper.getUsedRdsIdentifier(vpnId, vrfEntry.getDestPrefix())));
}
}
- Optional<AdjacenciesOp> optAdjacencies =
- MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
- FibUtil.getAdjListPathOp(ifName, vpnName));
- int numAdj = 0;
- if (optAdjacencies.isPresent()) {
- numAdj = optAdjacencies.get().getAdjacency().size();
- }
- //remove adjacency corr to prefix
- if (numAdj > 1) {
- LOG.info("cleanUpOpDataForFib: remove adjacency for prefix: {} {} vpnName {}", vpnId,
- vrfEntry.getDestPrefix(), vpnName);
- tx.delete(LogicalDatastoreType.OPERATIONAL,
- FibUtil.getAdjacencyIdentifierOp(ifName, vpnName, vrfEntry.getDestPrefix()));
- } else {
- //this is last adjacency (or) no more adjacency left for this vpn interface, so
- //clean up the vpn interface from DpnToVpn list
- LOG.info("Clean up vpn interface {} from dpn {} to vpn {} list.",
- ifName, prefixInfo.getDpnId(), rd);
- tx.delete(LogicalDatastoreType.OPERATIONAL,
- FibUtil.getVpnInterfaceOpDataEntryIdentifier(ifName, vpnName));
- }
+ handleAdjacencyAndVpnOpInterfaceDeletion(vrfEntry, ifName, vpnName, tx);
}));
}
}
+ /**
+ * Check all the adjacency in VpnInterfaceOpData and decide whether to delete the entire interface or only adj.
+ * Remove Adjacency from VPNInterfaceOpData.
+ * if Adjacency != primary.
+ * if Adjacency == primary , then mark it for deletion.
+ * Remove entire VPNinterfaceOpData Entry.
+ * if sie of Adjacency <= 2 and all are marked for deletion , delete the entire VPNinterface Op entry.
+ * @param vrfEntry - VrfEntry removed
+ * @param ifName - Interface name from VRFentry
+ * @param vpnName - VPN name of corresponding VRF
+ * @param tx - ReadWrite Tx
+ */
+ private void handleAdjacencyAndVpnOpInterfaceDeletion(VrfEntry vrfEntry, String ifName, String vpnName,
+ TypedReadWriteTransaction<Operational> tx)
+ throws ExecutionException, InterruptedException {
+ InstanceIdentifier<Adjacency> adjacencyIid =
+ FibUtil.getAdjacencyIdentifierOp(ifName, vpnName, vrfEntry.getDestPrefix());
+ Optional<Adjacency> adjacencyOptional = tx.read(adjacencyIid).get();
+ if (adjacencyOptional.isPresent()) {
+ if (adjacencyOptional.get().getAdjacencyType() != Adjacency.AdjacencyType.PrimaryAdjacency) {
+ tx.delete(FibUtil.getAdjacencyIdentifierOp(ifName, vpnName, vrfEntry.getDestPrefix()));
+ } else {
+ tx.merge(adjacencyIid,
+ new AdjacencyBuilder(adjacencyOptional.get()).setMarkedForDeletion(true).build());
+ }
+ }
+
+ Optional<AdjacenciesOp> optAdjacencies = tx.read(FibUtil.getAdjListPathOp(ifName, vpnName)).get();
+
+ if (!optAdjacencies.isPresent() || optAdjacencies.get().getAdjacency() == null) {
+ return;
+ }
+
+ @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()
+ )) {
+ LOG.info("Clean up vpn interface {} to vpn {} list.", ifName, vpnName);
+ tx.delete(FibUtil.getVpnInterfaceOpDataEntryIdentifier(ifName, vpnName));
+ }
+ }
+
private void deleteFibEntries(final InstanceIdentifier<VrfEntry> identifier, final VrfEntry vrfEntry) {
final VrfTablesKey vrfTableKey = identifier.firstKeyOf(VrfTables.class);
final String rd = vrfTableKey.getRouteDistinguisher();
vpnToDpnList = vpnInstance.getVpnToDpnList();
}
- SubnetRoute subnetRoute = vrfEntry.getAugmentation(SubnetRoute.class);
+ SubnetRoute subnetRoute = vrfEntry.augmentation(SubnetRoute.class);
final java.util.Optional<Long> optionalLabel = FibUtil.getLabelFromRoutePaths(vrfEntry);
List<String> nextHopAddressList = FibHelper.getNextHopListFromRoutePaths(vrfEntry);
String vpnName = fibUtil.getVpnNameFromId(vpnInstance.getVpnId());
+ " with elantag {}", rd, vrfEntry.getDestPrefix(), elanTag);
if (vpnToDpnList != null) {
jobCoordinator.enqueueJob(FibUtil.getJobKeyForRdPrefix(rd, vrfEntry.getDestPrefix()),
- () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
- for (final VpnToDpnList curDpn : vpnToDpnList) {
-
- baseVrfEntryHandler.makeConnectedRoute(curDpn.getDpnId(), vpnInstance.getVpnId(), vrfEntry,
- vrfTableKey.getRouteDistinguisher(), null, NwConstants.DEL_FLOW, tx, null);
- if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.SELF_IMPORTED) {
- optionalLabel.ifPresent(label -> makeLFibTableEntry(curDpn.getDpnId(), label, null,
+ () -> Collections.singletonList(
+ txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
+ for (final VpnToDpnList curDpn : vpnToDpnList) {
+
+ baseVrfEntryHandler.makeConnectedRoute(curDpn.getDpnId(), vpnInstance.getVpnId(),
+ vrfEntry, vrfTableKey.getRouteDistinguisher(), null, NwConstants.DEL_FLOW,
+ TransactionAdapter.toWriteTransaction(tx), null);
+ if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.SELF_IMPORTED) {
+ optionalLabel.ifPresent(label -> makeLFibTableEntry(curDpn.getDpnId(), label, null,
DEFAULT_FIB_FLOW_PRIORITY, NwConstants.DEL_FLOW, tx));
- }
+ }
- installSubnetBroadcastAddrDropRule(curDpn.getDpnId(), rd, vpnInstance.getVpnId(),
+ installSubnetBroadcastAddrDropRule(curDpn.getDpnId(), rd, vpnInstance.getVpnId(),
vrfEntry, NwConstants.DEL_FLOW, tx);
- }
- })));
+ }
+ })));
}
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;
Optional<Routes> 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 ;
.getVpnExtraroutes(dataBroker, vpnName, usedRds.get(0), vrfEntry.getDestPrefix());
}
} else {
- jobKey = FibUtil.getJobKeyForRdPrefix(rd, vrfEntry.getDestPrefix());
extraRouteOptional = Optional.absent();
}
- jobCoordinator.enqueueJob(jobKey,
- () -> {
- WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
-
+ jobCoordinator.enqueueJob(FibUtil.getJobKeyForRdPrefix(rd, vrfEntry.getDestPrefix()),
+ () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
if (localDpnIdList.size() <= 0) {
for (VpnToDpnList curDpn : vpnToDpnList) {
baseVrfEntryHandler.deleteRemoteRoute(BigInteger.ZERO, curDpn.getDpnId(),
- vpnInstance.getVpnId(), vrfTableKey, vrfEntry, extraRouteOptional, tx);
+ vpnInstance.getVpnId(), vrfTableKey, vrfEntry, extraRouteOptional,
+ TransactionAdapter.toWriteTransaction(tx));
}
} 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, tx);
+ vpnInstance.getVpnId(), vrfTableKey, vrfEntry, extraRouteOptional,
+ TransactionAdapter.toWriteTransaction(tx));
}
}
}
}
- List<ListenableFuture<Void>> futures = new ArrayList<>();
- futures.add(tx.submit());
- return futures;
- }, DJC_MAX_RETRIES);
+ 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);
}
//The flow/group entry has been deleted from config DS; need to clean up associated operational
}
- private void makeLFibTableEntry(BigInteger dpId, long label, List<InstructionInfo> instructions, int priority,
- int addOrRemove, WriteTransaction tx) {
- Boolean wrTxPresent = true;
+ private void makeLFibTableEntry(BigInteger dpId, long label, @Nullable List<InstructionInfo> instructions,
+ int priority, int addOrRemove, TypedWriteTransaction<Configuration> tx) {
if (tx == null) {
- wrTxPresent = false;
- tx = dataBroker.newWriteOnlyTransaction();
+ ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
+ newTx -> makeLFibTableEntry(dpId, label, instructions, priority, addOrRemove, newTx)), LOG,
+ "Error making LFIB table entry");
+ return;
}
List<MatchInfo> matches = new ArrayList<>();
FlowKey flowKey = new FlowKey(new FlowId(flowId));
Node nodeDpn = FibUtil.buildDpnNode(dpId);
InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
- .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
+ .child(Node.class, nodeDpn.key()).augmentation(FlowCapableNode.class)
.child(Table.class, new TableKey(flow.getTableId())).child(Flow.class, flowKey).build();
if (addOrRemove == NwConstants.ADD_FLOW) {
- tx.put(LogicalDatastoreType.CONFIGURATION, flowInstanceId, flow, WriteTransaction.CREATE_MISSING_PARENTS);
+ tx.put(flowInstanceId, flow, CREATE_MISSING_PARENTS);
} else {
- tx.delete(LogicalDatastoreType.CONFIGURATION, flowInstanceId);
- }
- if (!wrTxPresent) {
- tx.submit();
+ tx.delete(flowInstanceId);
}
LOG.debug("LFIB Entry for dpID {} : label : {} instructions {} : key {} {} successfully",
public void populateFibOnNewDpn(final BigInteger dpnId, final long vpnId, final String rd,
final FutureCallback<List<Void>> callback) {
LOG.trace("New dpn {} for vpn {} : populateFibOnNewDpn", dpnId, rd);
- InstanceIdentifier<VrfTables> id = buildVrfId(rd);
- final VpnInstanceOpDataEntry vpnInstance = fibUtil.getVpnInstance(rd);
- final Optional<VrfTables> vrfTable = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
- List<SubTransaction> txnObjects = new ArrayList<>();
- if (!vrfTable.isPresent()) {
- LOG.info("populateFibOnNewDpn: dpn: {}: VRF Table not yet available for RD {}", dpnId, rd);
- if (callback != null) {
- List<ListenableFuture<Void>> futures = new ArrayList<>();
- ListenableFuture<List<Void>> listenableFuture = Futures.allAsList(futures);
- Futures.addCallback(listenableFuture, callback, MoreExecutors.directExecutor());
- }
- return;
- }
-
jobCoordinator.enqueueJob(FibUtil.getJobKeyForVpnIdDpnId(vpnId, dpnId),
() -> {
+ InstanceIdentifier<VrfTables> id = buildVrfId(rd);
+ final VpnInstanceOpDataEntry vpnInstance = fibUtil.getVpnInstance(rd);
+ final Optional<VrfTables> vrfTable = MDSALUtil.read(dataBroker,
+ LogicalDatastoreType.CONFIGURATION, id);
List<ListenableFuture<Void>> futures = new ArrayList<>();
- synchronized (vpnInstance.getVpnInstanceName().intern()) {
- WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
- for (final VrfEntry vrfEntry : vrfTable.get().getVrfEntry()) {
- SubnetRoute subnetRoute = vrfEntry.getAugmentation(SubnetRoute.class);
- if (subnetRoute != null) {
- long elanTag = subnetRoute.getElantag();
- installSubnetRouteInFib(dpnId, elanTag, rd, vpnId, vrfEntry, tx);
- installSubnetBroadcastAddrDropRule(dpnId, rd, vpnId, vrfEntry, NwConstants.ADD_FLOW, tx);
- continue;
- }
- RouterInterface routerInt = vrfEntry.getAugmentation(RouterInterface.class);
- if (routerInt != null) {
- LOG.trace("Router augmented vrfentry found rd:{}, uuid:{}, ip:{}, mac:{}",
- rd, routerInt.getUuid(), routerInt.getIpAddress(), routerInt.getMacAddress());
- routerInterfaceVrfEntryHandler.installRouterFibEntry(vrfEntry, dpnId, vpnId,
- routerInt.getIpAddress(), new MacAddress(routerInt.getMacAddress()),
- NwConstants.ADD_FLOW);
- continue;
- }
- //Handle local flow creation for imports
- if (RouteOrigin.value(vrfEntry.getOrigin()) == RouteOrigin.SELF_IMPORTED) {
- java.util.Optional<Long> optionalLabel = FibUtil.getLabelFromRoutePaths(vrfEntry);
- if (optionalLabel.isPresent()) {
- List<String> nextHopList = FibHelper.getNextHopListFromRoutePaths(vrfEntry);
- LabelRouteInfo lri = getLabelRouteInfo(optionalLabel.get());
- if (isPrefixAndNextHopPresentInLri(vrfEntry.getDestPrefix(), nextHopList, lri)) {
- if (lri.getDpnId().equals(dpnId)) {
- createLocalFibEntry(vpnId, rd, vrfEntry);
- continue;
+ if (!vrfTable.isPresent()) {
+ LOG.info("populateFibOnNewDpn: dpn: {}: VRF Table not yet available for RD {}", dpnId, rd);
+ if (callback != null) {
+ ListenableFuture<List<Void>> listenableFuture = Futures.allAsList(futures);
+ Futures.addCallback(listenableFuture, callback, MoreExecutors.directExecutor());
+ }
+ return futures;
+ }
+
+ final ReentrantLock lock = lockFor(vpnInstance);
+ lock.lock();
+ try {
+ futures.add(retryingTxRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, tx -> {
+ for (final VrfEntry vrfEntry : vrfTable.get().nonnullVrfEntry()) {
+ SubnetRoute subnetRoute = vrfEntry.augmentation(SubnetRoute.class);
+ if (subnetRoute != null) {
+ long elanTag = subnetRoute.getElantag();
+ installSubnetRouteInFib(dpnId, elanTag, rd, vpnId, vrfEntry, tx);
+ installSubnetBroadcastAddrDropRule(dpnId, rd, vpnId, vrfEntry, NwConstants.ADD_FLOW,
+ tx);
+ continue;
+ }
+ RouterInterface routerInt = vrfEntry.augmentation(RouterInterface.class);
+ if (routerInt != null) {
+ LOG.trace("Router augmented vrfentry found rd:{}, uuid:{}, ip:{}, mac:{}",
+ rd, routerInt.getUuid(), routerInt.getIpAddress(), routerInt.getMacAddress());
+ routerInterfaceVrfEntryHandler.installRouterFibEntry(vrfEntry, dpnId, vpnId,
+ routerInt.getIpAddress(), new MacAddress(routerInt.getMacAddress()),
+ NwConstants.ADD_FLOW);
+ continue;
+ }
+ //Handle local flow creation for imports
+ if (RouteOrigin.value(vrfEntry.getOrigin()) == RouteOrigin.SELF_IMPORTED) {
+ java.util.Optional<Long> optionalLabel = FibUtil.getLabelFromRoutePaths(vrfEntry);
+ if (optionalLabel.isPresent()) {
+ List<String> nextHopList = FibHelper.getNextHopListFromRoutePaths(vrfEntry);
+ LabelRouteInfo lri = getLabelRouteInfo(optionalLabel.get());
+ if (isPrefixAndNextHopPresentInLri(vrfEntry.getDestPrefix(), nextHopList, lri)) {
+ if (Objects.equals(lri.getDpnId(), dpnId)) {
+ try {
+ int etherType = NWUtil.getEtherTypeFromIpPrefix(
+ vrfEntry.getDestPrefix());
+ createLocalFibEntry(vpnId, rd, vrfEntry, etherType);
+ } catch (IllegalArgumentException ex) {
+ LOG.warn("Unable to get etherType for IP Prefix {}",
+ vrfEntry.getDestPrefix());
+ }
+ continue;
+ }
}
}
}
- }
-
- boolean shouldCreateRemoteFibEntry = shouldCreateFibEntryForVrfAndVpnIdOnDpn(vpnId,
- vrfEntry, dpnId);
- if (shouldCreateRemoteFibEntry) {
- LOG.trace("Will create remote FIB entry for vrfEntry {} on DPN {}",
+ boolean shouldCreateRemoteFibEntry = shouldCreateFibEntryForVrfAndVpnIdOnDpn(vpnId,
vrfEntry, dpnId);
- if (RouteOrigin.BGP.getValue().equals(vrfEntry.getOrigin())) {
- bgpRouteVrfEntryHandler.createRemoteFibEntry(dpnId, vpnId,
- vrfTable.get().getRouteDistinguisher(), vrfEntry, tx, txnObjects);
- } else {
- createRemoteFibEntry(dpnId, vpnId, vrfTable.get().getRouteDistinguisher(),
- vrfEntry, tx);
+ if (shouldCreateRemoteFibEntry) {
+ LOG.trace("Will create remote FIB entry for vrfEntry {} on DPN {}", vrfEntry, dpnId);
+ if (RouteOrigin.BGP.getValue().equals(vrfEntry.getOrigin())) {
+ List<SubTransaction> txnObjects = new ArrayList<>();
+ bgpRouteVrfEntryHandler.createRemoteFibEntry(dpnId, vpnId,
+ vrfTable.get().getRouteDistinguisher(), vrfEntry,
+ TransactionAdapter.toWriteTransaction(tx), txnObjects);
+ } else {
+ createRemoteFibEntry(dpnId, vpnId, vrfTable.get().getRouteDistinguisher(),
+ vrfEntry, tx);
+ }
}
}
+ }));
+ if (callback != null) {
+ ListenableFuture<List<Void>> listenableFuture = Futures.allAsList(futures);
+ Futures.addCallback(listenableFuture, callback, MoreExecutors.directExecutor());
}
- //TODO: if we have 100K entries in FIB, can it fit in one Tranasaction (?)
- futures.add(tx.submit());
- }
- if (callback != null) {
- ListenableFuture<List<Void>> listenableFuture = Futures.allAsList(futures);
- Futures.addCallback(listenableFuture, callback, MoreExecutors.directExecutor());
+ } finally {
+ lock.unlock();
}
return futures;
});
final Optional<VrfTables> vrfTable = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
if (vrfTable.isPresent()) {
jobCoordinator.enqueueJob(FibUtil.getJobKeyForVpnIdDpnId(vpnId, dpnId),
- () -> {
- List<ListenableFuture<Void>> futures = new ArrayList<>();
- synchronized (vpnInstance.getVpnInstanceName().intern()) {
- WriteTransaction writeCfgTxn = dataBroker.newWriteOnlyTransaction();
- vrfTable.get().getVrfEntry().stream()
+ () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
+ 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, writeCfgTxn, txnObjects));
- futures.add(writeCfgTxn.submit());
+ rd, remoteNextHopIp, vrfTable, TransactionAdapter.toWriteTransaction(tx), txnObjects));
+ } finally {
+ lock.unlock();
}
- return futures;
- });
+ })));
}
}
}
jobCoordinator.enqueueJob(FibUtil.getJobKeyForVpnIdDpnId(vpnId, localDpnId),
- () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
- synchronized (vpnInstance.getVpnInstanceName().intern()) {
+ () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
+ 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, tx);
+ extraRouteOptional, TransactionAdapter.toWriteTransaction(tx));
}
+ } finally {
+ lock.unlock();
}
})));
}
public void cleanUpDpnForVpn(final BigInteger dpnId, final long vpnId, final String rd,
final FutureCallback<List<Void>> callback) {
LOG.trace("cleanUpDpnForVpn: Remove dpn {} for vpn {} : cleanUpDpnForVpn", dpnId, rd);
- InstanceIdentifier<VrfTables> id = buildVrfId(rd);
- final VpnInstanceOpDataEntry vpnInstance = fibUtil.getVpnInstance(rd);
- List<SubTransaction> txnObjects = new ArrayList<>();
- final Optional<VrfTables> vrfTable = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
jobCoordinator.enqueueJob(FibUtil.getJobKeyForVpnIdDpnId(vpnId, dpnId),
() -> {
+ InstanceIdentifier<VrfTables> id = buildVrfId(rd);
+ final VpnInstanceOpDataEntry vpnInstance = fibUtil.getVpnInstance(rd);
+ List<SubTransaction> txnObjects = new ArrayList<>();
+ final Optional<VrfTables> vrfTable = MDSALUtil.read(dataBroker,
+ LogicalDatastoreType.CONFIGURATION, id);
List<ListenableFuture<Void>> futures = new ArrayList<>();
if (vrfTable.isPresent()) {
- synchronized (vpnInstance.getVpnInstanceName().intern()) {
- WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
- for (final VrfEntry vrfEntry : vrfTable.get().getVrfEntry()) {
+ 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().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.getAugmentation(SubnetRoute.class);
- if (subnetRoute != null) {
- LOG.trace("SUBNETROUTE: cleanUpDpnForVpn: Cleaning subnetroute {} on dpn {}"
- + " for vpn {}", vrfEntry.getDestPrefix(), dpnId, rd);
- baseVrfEntryHandler.makeConnectedRoute(dpnId, vpnId, vrfEntry, rd, null,
- NwConstants.DEL_FLOW, tx, null);
- List<RoutePaths> routePaths = vrfEntry.getRoutePaths();
- if (routePaths != null) {
- for (RoutePaths routePath : routePaths) {
- makeLFibTableEntry(dpnId, routePath.getLabel(), null,
- DEFAULT_FIB_FLOW_PRIORITY,
- NwConstants.DEL_FLOW, tx);
- LOG.trace("SUBNETROUTE: cleanUpDpnForVpn: Released subnetroute label {} for"
- + " rd {} prefix {}", routePath.getLabel(), rd,
- vrfEntry.getDestPrefix());
+ SubnetRoute subnetRoute = vrfEntry.augmentation(SubnetRoute.class);
+ if (subnetRoute != null && !fibUtil
+ .isInterfacePresentInDpn(parentRd, dpnId)) {
+ LOG.trace("SUBNETROUTE: cleanUpDpnForVpn: Cleaning subnetroute {} on dpn {}"
+ + " for vpn {}", vrfEntry.getDestPrefix(), dpnId, rd);
+ baseVrfEntryHandler.makeConnectedRoute(dpnId, vpnId, vrfEntry, rd, null,
+ NwConstants.DEL_FLOW, TransactionAdapter.toWriteTransaction(tx), null);
+ List<RoutePaths> routePaths = vrfEntry.getRoutePaths();
+ if (routePaths != null) {
+ for (RoutePaths routePath : routePaths) {
+ makeLFibTableEntry(dpnId, routePath.getLabel(), null,
+ DEFAULT_FIB_FLOW_PRIORITY,
+ NwConstants.DEL_FLOW, tx);
+ LOG.trace("SUBNETROUTE: cleanUpDpnForVpn: Released subnetroute label {}"
+ + " for rd {} prefix {}", routePath.getLabel(), rd,
+ vrfEntry.getDestPrefix());
+ }
}
+ installSubnetBroadcastAddrDropRule(dpnId, rd, vpnId, vrfEntry,
+ NwConstants.DEL_FLOW, tx);
+ continue;
+ }
+ // ping responder for router interfaces
+ RouterInterface routerInt = vrfEntry.augmentation(RouterInterface.class);
+ if (routerInt != null) {
+ LOG.trace("Router augmented vrfentry found for rd:{}, uuid:{}, ip:{}, mac:{}",
+ rd, routerInt.getUuid(), routerInt.getIpAddress(),
+ routerInt.getMacAddress());
+ routerInterfaceVrfEntryHandler.installRouterFibEntry(vrfEntry, dpnId, vpnId,
+ routerInt.getIpAddress(), new MacAddress(routerInt.getMacAddress()),
+ NwConstants.DEL_FLOW);
+ continue;
}
- installSubnetBroadcastAddrDropRule(dpnId, rd, vpnId, vrfEntry,
- NwConstants.DEL_FLOW, tx);
- continue;
- }
- // ping responder for router interfaces
- RouterInterface routerInt = vrfEntry.getAugmentation(RouterInterface.class);
- if (routerInt != null) {
- LOG.trace("Router augmented vrfentry found for rd:{}, uuid:{}, ip:{}, mac:{}",
- rd, routerInt.getUuid(), routerInt.getIpAddress(), routerInt.getMacAddress());
- routerInterfaceVrfEntryHandler.installRouterFibEntry(vrfEntry, dpnId, vpnId,
- routerInt.getIpAddress(), new MacAddress(routerInt.getMacAddress()),
- NwConstants.DEL_FLOW);
- continue;
- }
- //Handle local flow deletion for imports
- if (RouteOrigin.value(vrfEntry.getOrigin()) == RouteOrigin.SELF_IMPORTED) {
- java.util.Optional<Long> optionalLabel = FibUtil.getLabelFromRoutePaths(vrfEntry);
- if (optionalLabel.isPresent()) {
- List<String> nextHopList = FibHelper.getNextHopListFromRoutePaths(vrfEntry);
- LabelRouteInfo lri = getLabelRouteInfo(optionalLabel.get());
- if (isPrefixAndNextHopPresentInLri(vrfEntry.getDestPrefix(), nextHopList, lri)) {
- if (lri.getDpnId().equals(dpnId)) {
+ //Handle local flow deletion for imports
+ if (RouteOrigin.value(vrfEntry.getOrigin()) == RouteOrigin.SELF_IMPORTED) {
+ java.util.Optional<Long> optionalLabel = FibUtil.getLabelFromRoutePaths(vrfEntry);
+ if (optionalLabel.isPresent()) {
+ List<String> nextHopList = FibHelper.getNextHopListFromRoutePaths(vrfEntry);
+ LabelRouteInfo lri = getLabelRouteInfo(optionalLabel.get());
+ if (isPrefixAndNextHopPresentInLri(vrfEntry.getDestPrefix(), nextHopList,
+ lri) && Objects.equals(lri.getDpnId(), dpnId)) {
deleteLocalFibEntry(vpnId, rd, vrfEntry);
- continue;
}
}
}
- }
- // Passing null as we don't know the dpn
- // to which prefix is attached at this point
- List<String> usedRds = VpnExtraRouteHelper.getUsedRds(dataBroker, vpnInstance.getVpnId(),
- vrfEntry.getDestPrefix());
- String vpnName = fibUtil.getVpnNameFromId(vpnInstance.getVpnId());
- Optional<Routes> 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()) {
- if (usedRds.size() > 1) {
- LOG.error("The extra route prefix is still present in some DPNs");
- return futures;
- } else {
- extraRouteOptional = VpnExtraRouteHelper.getVpnExtraroutes(dataBroker, vpnName,
- usedRds.get(0), vrfEntry.getDestPrefix());
+ // Passing null as we don't know the dpn
+ // to which prefix is attached at this point
+ List<String> usedRds = VpnExtraRouteHelper.getUsedRds(dataBroker,
+ vpnInstance.getVpnId(), vrfEntry.getDestPrefix());
+ Optional<Routes> 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()) {
+ if (usedRds.size() > 1) {
+ LOG.error("The extra route prefix is still present in some DPNs");
+ return;
+ } else {
+ extraRouteOptional = VpnExtraRouteHelper.getVpnExtraroutes(dataBroker, vpnName,
+ usedRds.get(0), vrfEntry.getDestPrefix());
+ }
+ } else {
+ extraRouteOptional = Optional.absent();
+ }
+ if (RouteOrigin.BGP.getValue().equals(vrfEntry.getOrigin())) {
+ bgpRouteVrfEntryHandler.deleteRemoteRoute(null, dpnId, vpnId,
+ vrfTable.get().key(), vrfEntry, extraRouteOptional,
+ TransactionAdapter.toWriteTransaction(tx), txnObjects);
+ } else {
+ if (subnetRoute == null || !fibUtil
+ .isInterfacePresentInDpn(parentRd, dpnId)) {
+ baseVrfEntryHandler.deleteRemoteRoute(null, dpnId, vpnId,
+ vrfTable.get().key(), vrfEntry, extraRouteOptional,
+ TransactionAdapter.toWriteTransaction(tx));
+ }
}
- } else {
- extraRouteOptional = Optional.absent();
- }
- if (RouteOrigin.BGP.getValue().equals(vrfEntry.getOrigin())) {
- bgpRouteVrfEntryHandler.deleteRemoteRoute(null, dpnId, vpnId, vrfTable.get().getKey(),
- vrfEntry, extraRouteOptional, tx, txnObjects);
- } else {
- baseVrfEntryHandler.deleteRemoteRoute(null, dpnId, vpnId, vrfTable.get().getKey(),
- vrfEntry, extraRouteOptional, tx);
}
- }
- futures.add(tx.submit());
+ }));
+ } finally {
+ lock.unlock();
}
if (callback != null) {
ListenableFuture<List<Void>> listenableFuture = Futures.allAsList(futures);
Futures.addCallback(listenableFuture, callback, MoreExecutors.directExecutor());
}
+ } else {
+ LOG.error("cleanUpDpnForVpn: No vrf table found for rd {} vpnId {} dpn {}", rd, vpnId, dpnId);
}
return futures;
});
if (vrfTable.isPresent()) {
jobCoordinator.enqueueJob(FibUtil.getJobKeyForVpnIdDpnId(vpnId, dpnId),
() -> {
- List<ListenableFuture<Void>> futures = new ArrayList<>();
- synchronized (vpnInstance.getVpnInstanceName().intern()) {
- WriteTransaction writeCfgTxn = dataBroker.newWriteOnlyTransaction();
- vrfTable.get().getVrfEntry().stream()
- .filter(vrfEntry -> RouteOrigin.value(vrfEntry.getOrigin()) == RouteOrigin.BGP)
- .forEach(bgpRouteVrfEntryHandler.getConsumerForDeletingRemoteFib(dpnId, vpnId, rd,
- remoteNextHopIp, vrfTable, writeCfgTxn, txnObjects));
- futures.add(writeCfgTxn.submit());
+ final ReentrantLock lock = lockFor(vpnInstance);
+ lock.lock();
+ try {
+ return Collections.singletonList(
+ txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
+ 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();
}
- return futures;
});
}
}
+ 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))
optNextHop.ifPresent(nextHop -> {
String flowRef = getInterVpnFibFlowRef(interVpnLinkName, vrfEntry.getDestPrefix(), nextHop);
FlowKey flowKey = new FlowKey(new FlowId(flowRef));
- Flow flow = new FlowBuilder().setKey(flowKey).setId(new FlowId(flowRef))
+ Flow flow = new FlowBuilder().withKey(flowKey).setId(new FlowId(flowRef))
.setTableId(NwConstants.L3_FIB_TABLE).setFlowName(flowRef).build();
LOG.trace("Removing flow in FIB table for interVpnLink {} key {}", interVpnLinkName, flowRef);
optLabel.ifPresent(label -> {
LOG.trace("Removing flow in FIB table for interVpnLink {}", interVpnLinkName);
- WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
- for (BigInteger dpId : targetDpns) {
- LOG.debug("Removing flow: VrfEntry=[prefix={} label={}] dpn {} for InterVpnLink {} in LFIB",
- vrfEntry.getDestPrefix(), label, dpId, interVpnLinkName);
- makeLFibTableEntry(dpId, label, /*instructions*/null, LFIB_INTERVPN_PRIORITY, NwConstants.DEL_FLOW, tx);
- }
- tx.submit();
+ ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
+ for (BigInteger dpId : targetDpns) {
+ LOG.debug("Removing flow: VrfEntry=[prefix={} label={}] dpn {} for InterVpnLink {} in LFIB",
+ vrfEntry.getDestPrefix(), label, dpId, interVpnLinkName);
+ makeLFibTableEntry(dpId, label, /*instructions*/null, LFIB_INTERVPN_PRIORITY, NwConstants.DEL_FLOW,
+ tx);
+ }
+ }), LOG, "Error removing flows");
});
}
- 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);
+ }
}