*/
package org.opendaylight.netvirt.fibmanager;
+import static java.util.stream.Collectors.toList;
+
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.FutureCallback;
import java.util.concurrent.Callable;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.function.Consumer;
-import java.util.stream.Collectors;
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+import javax.inject.Singleton;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
import org.opendaylight.genius.mdsalutil.actions.ActionPopMpls;
import org.opendaylight.genius.mdsalutil.actions.ActionPushMpls;
+import org.opendaylight.genius.mdsalutil.actions.ActionRegLoad;
import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldEthernetDestination;
import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldEthernetSource;
import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldMplsLabel;
import org.opendaylight.genius.utils.batching.ResourceHandler;
import org.opendaylight.genius.utils.batching.SubTransaction;
import org.opendaylight.genius.utils.batching.SubTransactionImpl;
+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.intervpnlink.IVpnLinkService;
import org.opendaylight.netvirt.vpnmanager.api.intervpnlink.InterVpnLinkCache;
import org.opendaylight.netvirt.vpnmanager.api.intervpnlink.InterVpnLinkDataComposite;
import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeMplsOverGre;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroutes.vpn.ExtraRoutesKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroutes.vpn.extra.routes.Routes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroutes.vpn.extra.routes.RoutesKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.link.states.InterVpnLinkState;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.link.states.InterVpnLinkState.State;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.rev150105.TunnelTypeVxlan;
-import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+@Singleton
public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry, VrfEntryListener>
implements AutoCloseable, ResourceHandler {
private final NexthopManager nextHopManager;
private final OdlInterfaceRpcService interfaceManager;
private final IdManagerService idManager;
- private final IVpnLinkService ivpnLinkService;
List<SubTransaction> transactionObjects;
private static Integer batchSize;
private static BlockingQueue<ActionableResource> vrfEntryBufferQ = new LinkedBlockingQueue<>();
private final ResourceBatchingManager resourceBatchingManager;
+ protected static boolean isOpenStackVniSemanticsEnforced;
+
+ @Inject
public VrfEntryListener(final DataBroker dataBroker, final IMdsalApiManager mdsalApiManager,
final NexthopManager nexthopManager, final OdlInterfaceRpcService interfaceManager,
- final IdManagerService idManager, final IVpnLinkService ivpnLinkService) {
+ final IdManagerService idManager,
+ final IElanService elanManager) {
super(VrfEntry.class, VrfEntryListener.class);
this.dataBroker = dataBroker;
this.mdsalManager = mdsalApiManager;
this.nextHopManager = nexthopManager;
this.interfaceManager = interfaceManager;
this.idManager = idManager;
- this.ivpnLinkService = ivpnLinkService;
+ isOpenStackVniSemanticsEnforced = elanManager.isOpenStackVniSemanticsEnforced();
batchSize = Integer.getInteger("batch.size", BATCH_SIZE);
batchInterval = Integer.getInteger("batch.wait.time", PERIODICITY);
resourceBatchingManager = ResourceBatchingManager.getInstance();
transactionObjects = new ArrayList<>();
}
- public void start() {
- LOG.info("{} start", getClass().getSimpleName());
+ @Override
+ @PostConstruct
+ public void init() {
+ LOG.info("{} init", getClass().getSimpleName());
registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
}
String rd = identifier.firstKeyOf(VrfTables.class).getRouteDistinguisher();
LOG.debug("ADD: Adding Fib Entry rd {} prefix {} route-paths {}",
rd, vrfEntry.getDestPrefix(), vrfEntry.getRoutePaths());
- if (vrfEntry.getEncapType().equals(VrfEntry.EncapType.Vxlan)) {
+ if (VrfEntry.EncapType.Vxlan.equals(vrfEntry.getEncapType())) {
LOG.info("EVPN flows need to be programmed.");
EVPNVrfEntryProcessor evpnVrfEntryProcessor = new EVPNVrfEntryProcessor(identifier,
vrfEntry, dataBroker, this);
vrfEntryBufferQ.add(actResource);
}
}
- leakRouteIfNeeded(identifier, vrfEntry, NwConstants.ADD_FLOW);
LOG.info("ADD: Added Fib Entry rd {} prefix {} route-paths {}",
- rd, vrfEntry.getDestPrefix(), vrfEntry.getRoutePaths());
+ rd, vrfEntry.getDestPrefix(), vrfEntry.getRoutePaths());
}
@Override
vrfEntryBufferQ.add(actResource);
}
}
- leakRouteIfNeeded(identifier, vrfEntry, NwConstants.DEL_FLOW);
LOG.info("REMOVE: Removed Fib Entry rd {} prefix {} route-paths {}",
rd, vrfEntry.getDestPrefix(), vrfEntry.getRoutePaths());
}
Preconditions.checkNotNull(update, "VrfEntry should not be null or empty.");
final String rd = identifier.firstKeyOf(VrfTables.class).getRouteDistinguisher();
- final VrfTablesKey vrfTableKey = identifier.firstKeyOf(VrfTables.class);
LOG.debug("UPDATE: Updating Fib Entries to rd {} prefix {} route-paths {}",
rd, update.getDestPrefix(), update.getRoutePaths());
// Handle BGP Routes first
update.getDestPrefix());
return;
}
+ //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, dataBroker, nextHopRemoved, rd,
+ update.getDestPrefix()));
+ writeOperTxn.submit();
createFibEntries(identifier, update);
LOG.info("UPDATE: Updated Fib Entries to rd {} prefix {} route-paths {}",
rd, update.getDestPrefix(), update.getRoutePaths());
private void createFibEntries(final InstanceIdentifier<VrfEntry> vrfEntryIid, final VrfEntry vrfEntry) {
final VrfTablesKey vrfTableKey = vrfEntryIid.firstKeyOf(VrfTables.class);
-
final VpnInstanceOpDataEntry vpnInstance = getVpnInstance(vrfTableKey.getRouteDistinguisher());
Preconditions.checkNotNull(vpnInstance, "Vpn Instance not available " + vrfTableKey.getRouteDistinguisher());
Preconditions.checkNotNull(vpnInstance.getVpnId(), "Vpn Instance with rd " + vpnInstance.getVrfId()
+ " has null vpnId!");
+ final Collection<VpnToDpnList> vpnToDpnList;
+ if (vrfEntry.getParentVpnRd() != null
+ && FibHelper.isControllerManagedNonSelfImportedRoute(RouteOrigin.value(vrfEntry.getOrigin()))) {
+ VpnInstanceOpDataEntry parentVpnInstance = getVpnInstance(vrfEntry.getParentVpnRd());
+ vpnToDpnList = parentVpnInstance != null ? parentVpnInstance.getVpnToDpnList() :
+ vpnInstance.getVpnToDpnList();
+ } else {
+ vpnToDpnList = vpnInstance.getVpnToDpnList();
+ }
- final Collection<VpnToDpnList> vpnToDpnList = vpnInstance.getVpnToDpnList();
final Long vpnId = vpnInstance.getVpnId();
final String rd = vrfTableKey.getRouteDistinguisher();
SubnetRoute subnetRoute = vrfEntry.getAugmentation(SubnetRoute.class);
}
final List<BigInteger> localDpnIdList = createLocalFibEntry(vpnInstance.getVpnId(), rd, vrfEntry);
-
if (!localDpnIdList.isEmpty()) {
if (vpnToDpnList != null) {
DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
Optional<String> optVpnUuid = FibUtil.getVpnNameFromRd(dataBroker, rd);
if (optVpnUuid.isPresent()) {
- Optional<InterVpnLinkDataComposite> optInterVpnLink =
- InterVpnLinkCache.getInterVpnLinkByVpnId(optVpnUuid.get());
- LOG.debug("InterVpnLink {} found in Cache: {}", optVpnUuid.get(), optInterVpnLink.isPresent());
- if (optInterVpnLink.isPresent()) {
- InterVpnLinkDataComposite interVpnLink = optInterVpnLink.get();
- String vpnUuid = optVpnUuid.get();
+ String vpnUuid = optVpnUuid.get();
+ InterVpnLinkDataComposite interVpnLink = InterVpnLinkCache.getInterVpnLinkByVpnId(vpnUuid).orNull();
+ if (interVpnLink != null) {
+ LOG.debug("InterVpnLink {} found in Cache linking Vpn {}", interVpnLink.getInterVpnLinkName(), vpnUuid);
FibUtil.getFirstNextHopAddress(vrfEntry).ifPresent(routeNexthop -> {
if (interVpnLink.isIpAddrTheOtherVpnEndpoint(routeNexthop, vpnUuid)) {
// 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(rd, vrfEntry);
+ installInterVpnRouteInLFib(interVpnLink, vpnUuid, vrfEntry);
}
});
}
}
}
-
/*
Please note that the following createFibEntries will be invoked only for BGP Imported Routes.
The invocation of the following method is via create() callback from the MDSAL Batching Infrastructure
}
}
- // FIXME: Refactoring needed here.
- // This kind of logic must be taken to an 'upper' layer like BgpManager or VpnManager
- private void leakRouteIfNeeded(final InstanceIdentifier<VrfEntry> vrfEntryIid, final VrfEntry vrfEntry,
- int addOrRemove) {
- Preconditions.checkNotNull(vrfEntry, "VrfEntry cannot be null or empty!");
- final VrfTablesKey vrfTableKey = vrfEntryIid.firstKeyOf(VrfTables.class);
-
- String prefix = vrfEntry.getDestPrefix();
- List<String> nextHopsList = FibUtil.getNextHopListFromRoutePaths(vrfEntry);
- // Label is used only for logging in subsequent method calls.
- //TODO : This label is not needed here. Can be removed. Hence using a default value.
- Long label = FibUtil.getLabelFromRoutePaths(vrfEntry).orElse(0L);
- String rd = vrfTableKey.getRouteDistinguisher();
- LOG.trace("leakRouteIfNeeded: srcVpnRd={} prefix={} nhList={} label={}", rd, prefix, nextHopsList, label);
-
- VpnInstanceOpDataEntry vpnInstance = getVpnInstance(rd);
- if (vpnInstance == null) {
- LOG.error("VPN Instance not available for route with prefix {} label {} nextHop {} RD {}. Returning...",
- prefix, label, nextHopsList, rd);
- return;
- }
- String vpnUuid = vpnInstance.getVpnInstanceName();
- if (vpnUuid == null || vpnUuid.isEmpty()) {
- LOG.warn("Could not find suitable VPN UUID for rd={}. vrfEntry=[prefix={} nhList={} label={}]",
- rd, prefix, nextHopsList, label);
- return;
+ void refreshFibTables(String rd, String prefix) {
+ InstanceIdentifier<VrfEntry> vrfEntryId =
+ InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd))
+ .child(VrfEntry.class, new VrfEntryKey(prefix)).build();
+ Optional<VrfEntry> vrfEntry = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
+ if (vrfEntry.isPresent()) {
+ createFibEntries(vrfEntryId, vrfEntry.get());
}
-
- ivpnLinkService.leakRouteIfNeeded(vpnUuid, prefix, nextHopsList, label.intValue(),
- RouteOrigin.value(vrfEntry.getOrigin()), addOrRemove);
}
private Prefixes updateVpnReferencesInLri(LabelRouteInfo lri, String vpnInstanceName, boolean isPresentInList) {
List<String> vpnInstanceNames = lri.getVpnInstanceList();
vpnInstanceNames.add(vpnInstanceName);
builder.setVpnInstanceList(vpnInstanceNames);
- FibUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, lriId, builder.build(),
- FibUtil.DEFAULT_CALLBACK);
+ MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, lriId, builder.build());
} else {
LOG.debug("vpnName {} is present in LRI with label {}..", vpnInstanceName, lri.getLabel());
}
return prefixBuilder.build();
}
- private void installSubnetRouteInFib(final BigInteger dpnId, final long elanTag, final String rd,
+ void installSubnetRouteInFib(final BigInteger dpnId, final long elanTag, final String rd,
final long vpnId, final VrfEntry vrfEntry, WriteTransaction tx) {
Boolean wrTxPresent = true;
if (tx == null) {
tx = dataBroker.newWriteOnlyTransaction();
}
FibUtil.getLabelFromRoutePaths(vrfEntry).ifPresent(label -> {
- List<String> nextHopAddressList = FibUtil.getNextHopListFromRoutePaths(vrfEntry);
+ List<String> nextHopAddressList = FibHelper.getNextHopListFromRoutePaths(vrfEntry);
synchronized (label.toString().intern()) {
LabelRouteInfo lri = getLabelRouteInfo(label);
if (isPrefixAndNextHopPresentInLri(vrfEntry.getDestPrefix(), nextHopAddressList, lri)) {
}
});
final List<InstructionInfo> instructions = new ArrayList<>();
- BigInteger subnetRouteMeta = ((BigInteger.valueOf(elanTag)).shiftLeft(32))
+ BigInteger subnetRouteMeta = ((BigInteger.valueOf(elanTag)).shiftLeft(24))
.or((BigInteger.valueOf(vpnId).shiftLeft(1)));
instructions.add(new InstructionWriteMetadata(subnetRouteMeta, MetaDataUtil.METADATA_MASK_SUBNET_ROUTE));
instructions.add(new InstructionGotoTable(NwConstants.L3_SUBNET_ROUTE_TABLE));
makeConnectedRoute(dpnId, vpnId, vrfEntry, rd, instructions, NwConstants.ADD_FLOW, tx);
- 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());
- LFIBinstructions.add(new InstructionApplyActions(actionsInfos));
- LFIBinstructions.add(new InstructionWriteMetadata(subnetRouteMeta,
- MetaDataUtil.METADATA_MASK_SUBNET_ROUTE));
- LFIBinstructions.add(new InstructionGotoTable(NwConstants.L3_SUBNET_ROUTE_TABLE));
-
- makeLFibTableEntry(dpnId, routePath.getLabel(), LFIBinstructions, DEFAULT_FIB_FLOW_PRIORITY,
- NwConstants.ADD_FLOW, tx);
+ 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());
+ LFIBinstructions.add(new InstructionApplyActions(actionsInfos));
+ LFIBinstructions.add(new InstructionWriteMetadata(subnetRouteMeta,
+ MetaDataUtil.METADATA_MASK_SUBNET_ROUTE));
+ LFIBinstructions.add(new InstructionGotoTable(NwConstants.L3_SUBNET_ROUTE_TABLE));
+
+ makeLFibTableEntry(dpnId, routePath.getLabel(), LFIBinstructions, DEFAULT_FIB_FLOW_PRIORITY,
+ NwConstants.ADD_FLOW, tx);
+ }
}
}
if (!wrTxPresent) {
* For a given route, it installs a flow in LFIB that sets the lportTag of the other endpoint and sends to
* LportDispatcher table (via table 80)
*/
- private void installInterVpnRouteInLFib(final String rd, final VrfEntry vrfEntry) {
+ private void installInterVpnRouteInLFib(final InterVpnLinkDataComposite interVpnLink, final String vpnName,
+ final VrfEntry vrfEntry) {
// 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.
- Optional<String> vpnNameOpc = FibUtil.getVpnNameFromRd(dataBroker, rd);
- if (!vpnNameOpc.isPresent()) {
- LOG.warn("Could not find VpnInstanceName for Route-Distinguisher {}", rd);
+ String interVpnLinkName = interVpnLink.getInterVpnLinkName();
+ if (!interVpnLink.isActive()) {
+ LOG.warn("InterVpnLink {} is NOT ACTIVE. InterVpnLink flows for prefix={} wont be installed in LFIB",
+ interVpnLinkName, vrfEntry.getDestPrefix());
return;
}
- String vpnName = vpnNameOpc.get();
- List<InterVpnLink> interVpnLinks = FibUtil.getAllInterVpnLinks(dataBroker);
- boolean interVpnLinkFound = false;
- for (InterVpnLink interVpnLink : interVpnLinks) {
- boolean vpnIs1stEndpoint = interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(vpnName);
- boolean vpnIs2ndEndpoint = !vpnIs1stEndpoint
- && interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(vpnName);
- if (vpnIs1stEndpoint || vpnIs2ndEndpoint) {
- interVpnLinkFound = true;
-
- Optional<InterVpnLinkState> vpnLinkState =
- FibUtil.getInterVpnLinkState(dataBroker, interVpnLink.getName());
- if (!vpnLinkState.isPresent()
- || !vpnLinkState.get().getState().equals(InterVpnLinkState.State.Active)) {
- LOG.warn("InterVpnLink {}, linking VPN {} and {}, is not in Active state",
- interVpnLink.getName(), interVpnLink.getFirstEndpoint().getVpnUuid().getValue(),
- interVpnLink.getSecondEndpoint().getVpnUuid().getValue());
- return;
- }
-
- List<BigInteger> targetDpns = vpnIs1stEndpoint ? vpnLinkState.get().getFirstEndpointState().getDpId()
- : vpnLinkState.get().getSecondEndpointState().getDpId();
- Long lportTag = vpnIs1stEndpoint ? vpnLinkState.get().getSecondEndpointState().getLportTag()
- : vpnLinkState.get().getFirstEndpointState().getLportTag();
-
- LOG.trace("Installing flow in LFIB table for interVpnLink {}", interVpnLink.getName());
-
- for (BigInteger dpId : targetDpns) {
- List<ActionInfo> actionsInfos = Collections.singletonList(new ActionPopMpls());
-
- List<InstructionInfo> instructions =
- Arrays.asList(new InstructionApplyActions(actionsInfos),
- new InstructionWriteMetadata(
- MetaDataUtil.getMetaDataForLPortDispatcher(lportTag.intValue(),
- ServiceIndex.getIndex(NwConstants.L3VPN_SERVICE_NAME,
- NwConstants.L3VPN_SERVICE_INDEX)),
- MetaDataUtil.getMetaDataMaskForLPortDispatcher()),
- new InstructionGotoTable(NwConstants.L3_INTERFACE_TABLE));
-
- FibUtil.getLabelFromRoutePaths(vrfEntry).ifPresent(interVpnRoutePathLabel -> {
- List<String> interVpnNextHopList = FibUtil.getNextHopListFromRoutePaths(vrfEntry);
- LOG.debug("Installing flow: VrfEntry=[prefix={} label={} nexthop={}] dpn {} for "
- + "InterVpnLink {} in LFIB",
- vrfEntry.getDestPrefix(), interVpnRoutePathLabel, interVpnNextHopList,
- dpId, interVpnLink.getName());
-
- makeLFibTableEntry(dpId, interVpnRoutePathLabel, instructions, LFIB_INTERVPN_PRIORITY,
- NwConstants.ADD_FLOW, null);
- });
- }
+ 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);
+ return;
+ }
- break;
- }
+ Long lportTag = optLportTag.get();
+ Long label = FibUtil.getLabelFromRoutePaths(vrfEntry).orElse(null);
+ if (label == null) {
+ LOG.error("Could not find label in vrfEntry=[prefix={} routePaths={}]. LFIB entry for InterVpnLink skipped",
+ vrfEntry.getDestPrefix(), vrfEntry.getRoutePaths());
+ return;
}
+ List<ActionInfo> actionsInfos = Collections.singletonList(new ActionPopMpls());
+ List<InstructionInfo> instructions = Arrays.asList(
+ new InstructionApplyActions(actionsInfos),
+ new InstructionWriteMetadata(MetaDataUtil.getMetaDataForLPortDispatcher(lportTag.intValue(),
+ ServiceIndex.getIndex(NwConstants.L3VPN_SERVICE_NAME,
+ NwConstants.L3VPN_SERVICE_INDEX)),
+ MetaDataUtil.getMetaDataMaskForLPortDispatcher()),
+ new InstructionGotoTable(NwConstants.L3_INTERFACE_TABLE));
+ List<String> interVpnNextHopList = FibHelper.getNextHopListFromRoutePaths(vrfEntry);
- if (!interVpnLinkFound) {
- LOG.warn("VrfEntry=[prefix={} route-paths={}] for VPN {} has origin INTERVPN but "
- + "no InterVpnLink could be found",
- vrfEntry.getDestPrefix(), vrfEntry.getRoutePaths(), rd);
+ for (BigInteger dpId : targetDpns) {
+ LOG.debug("Installing flow: VrfEntry=[prefix={} label={} nexthop={}] dpn {} for InterVpnLink {} in LFIB",
+ vrfEntry.getDestPrefix(), label, interVpnNextHopList, dpId, interVpnLink.getInterVpnLinkName());
+
+ makeLFibTableEntry(dpId, label, instructions, LFIB_INTERVPN_PRIORITY, NwConstants.ADD_FLOW,
+ /*writeTx*/null);
}
}
}
}
-
- // TODO Clean up the exception handling
- @SuppressWarnings("checkstyle:IllegalCatch")
- private <T extends DataObject> Optional<T> read(DataBroker broker, LogicalDatastoreType datastoreType,
- InstanceIdentifier<T> path) {
-
- ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
-
- Optional<T> result = Optional.absent();
- try {
- result = tx.read(datastoreType, path).get();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
-
- return result;
- }
-
private List<BigInteger> getDpnIdForPrefix(DataBroker broker, Long vpnId, String rd, VrfEntry vrfEntry) {
List<BigInteger> returnLocalDpnId = new ArrayList<>();
Prefixes localNextHopInfo = FibUtil.getPrefixToInterface(broker, vpnId, vrfEntry.getDestPrefix());
vpnExtraRoutes.stream().forEach(extraRoute -> {
Prefixes localNextHopInfoLocal = FibUtil.getPrefixToInterface(dataBroker,
vpnId, extraRoute.getNexthopIpList().get(0) + NwConstants.IPV4PREFIX);
- BigInteger dpnId = checkCreateLocalFibEntry(localNextHopInfoLocal, vrfEntry.getDestPrefix(),
+ BigInteger dpnId = checkCreateLocalFibEntry(localNextHopInfoLocal, localNextHopInfoLocal.getIpAddress(),
vpnId, rd, vrfEntry, vpnId, extraRoute, vpnExtraRoutes);
returnLocalDpnId.add(dpnId);
});
java.util.Optional<Long> optionalLabel = FibUtil.getLabelFromRoutePaths(vrfEntry);
if (optionalLabel.isPresent()) {
Long label = optionalLabel.get();
- List<String> nextHopAddressList = FibUtil.getNextHopListFromRoutePaths(vrfEntry);
+ List<String> nextHopAddressList = FibHelper.getNextHopListFromRoutePaths(vrfEntry);
synchronized (label.toString().intern()) {
LabelRouteInfo lri = getLabelRouteInfo(label);
if (isPrefixAndNextHopPresentInLri(vrfEntry.getDestPrefix(), nextHopAddressList, lri)) {
return dpnId;
}
String jobKey = FibUtil.getCreateLocalNextHopJobKey(vpnId, dpnId, vrfEntry.getDestPrefix());
- if (routes != null) {
+ 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 (routes != null && (vpnExtraRoutes.size() > 1 || routes.getNexthopIpList().size() > 1)) {
+ localNextHopIP = routes.getNexthopIpList().get(0) + NwConstants.IPV4PREFIX;
groupId = nextHopManager.createNextHopGroups(parentVpnId, rd, dpnId, vrfEntry, routes,
vpnExtraRoutes);
- localGroupId = nextHopManager.getLocalNextHopGroup(parentVpnId,
- routes.getNexthopIpList().get(0) + NwConstants.IPV4PREFIX);
+ localGroupId = nextHopManager.getLocalNextHopGroup(parentVpnId, localNextHopIP);
} else {
- groupId = nextHopManager.createLocalNextHop(parentVpnId, dpnId,
- localNextHopInfo.getVpnInterfaceName(), localNextHopIP, vrfEntry.getDestPrefix(),
- vrfEntry.getGatewayMacAddress(), jobKey);
+ groupId = nextHopManager.createLocalNextHop(parentVpnId, dpnId, interfaceName, localNextHopIP, prefix,
+ gwMacAddress, jobKey);
localGroupId = groupId;
}
if (groupId == FibConstants.INVALID_GROUP_ID) {
LOG.error("Unable to create Group for local prefix {} on rd {} for vpninterface {} on Node {}",
- vrfEntry.getDestPrefix(), rd, localNextHopInfo.getVpnInterfaceName(), dpnId.toString());
+ prefix, rd, interfaceName, dpnId.toString());
return BigInteger.ZERO;
}
final List<InstructionInfo> instructions = Collections.singletonList(
new InstructionApplyActions(
Arrays.asList(new ActionPopMpls(), new ActionGroup(groupId))));
java.util.Optional<Long> optLabel = FibUtil.getLabelFromRoutePaths(vrfEntry);
- List<String> nextHopAddressList = FibUtil.getNextHopListFromRoutePaths(vrfEntry);
- if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.SELF_IMPORTED) {
- LOG.debug("Installing tunnel table entry on dpn {} for interface {} with label {}",
- dpnId, localNextHopInfo.getVpnInterfaceName(), optLabel);
- } 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);
- }
- DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
-
- dataStoreCoordinator.enqueueJob(jobKey,
- () -> {
+ List<String> nextHopAddressList = FibHelper.getNextHopListFromRoutePaths(vrfEntry);
+ if (!FibUtil.enforceVxlanDatapathSemanticsforInternalRouterVpn(dataBroker, localNextHopInfo
+ .getSubnetId(), vpnName, rd)) {
+ DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
+ dataStoreCoordinator.enqueueJob(jobKey, () -> {
WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
makeConnectedRoute(dpnId, vpnId, vrfEntry, rd, instructions, NwConstants.ADD_FLOW, tx);
optLabel.ifPresent(label -> {
if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.SELF_IMPORTED) {
- makeLFibTableEntry(dpnId, label, lfibinstructions,
- DEFAULT_FIB_FLOW_PRIORITY, NwConstants.ADD_FLOW, tx);
+ 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);
}
});
-
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 {}",
private boolean isVpnPresentInDpn(String rd, BigInteger dpnId) {
InstanceIdentifier<VpnToDpnList> id = FibUtil.getVpnToDpnListIdentifier(rd, dpnId);
- return FibUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id).isPresent();
+ return MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id).isPresent();
}
private LabelRouteInfo getLabelRouteInfo(Long label) {
InstanceIdentifier<LabelRouteInfo> lriIid = InstanceIdentifier.builder(LabelRouteMap.class)
.child(LabelRouteInfo.class, new LabelRouteInfoKey(label)).build();
- Optional<LabelRouteInfo> opResult = read(dataBroker, LogicalDatastoreType.OPERATIONAL, lriIid);
+ Optional<LabelRouteInfo> opResult = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, lriIid);
if (opResult.isPresent()) {
return opResult.get();
}
if (tx != null) {
tx.delete(LogicalDatastoreType.OPERATIONAL, lriId);
} else {
- FibUtil.delete(dataBroker, LogicalDatastoreType.OPERATIONAL, lriId);
+ MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, lriId);
}
return true;
} else {
LOG.debug("updating LRI instance object for label {}", lri.getLabel());
LabelRouteInfoBuilder builder = new LabelRouteInfoBuilder(lri).setVpnInstanceList(vpnInstancesList);
- FibUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, lriId, builder.build(),
- FibUtil.DEFAULT_CALLBACK);
+ MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, lriId, builder.build());
}
return false;
}
Routes extraRoute = extraRouteOptional.get();
localNextHopInfo = FibUtil.getPrefixToInterface(dataBroker, vpnId,
extraRoute.getNexthopIpList().get(0) + NwConstants.IPV4PREFIX);
- BigInteger dpnId = localNextHopInfo.getDpnId();
- if (!dpnId.equals(BigInteger.ZERO)) {
- nextHopManager.setupLoadBalancingNextHop(vpnId, dpnId,
- vrfEntry.getDestPrefix(), /*listBucketInfo*/ null, /*remove*/ false);
- returnLocalDpnId.add(dpnId);
+ if (localNextHopInfo != null) {
+ BigInteger dpnId = checkDeleteLocalFibEntry(localNextHopInfo, localNextHopIP,
+ vpnId, rd, vrfEntry);
+ if (!dpnId.equals(BigInteger.ZERO)) {
+ nextHopManager.setupLoadBalancingNextHop(vpnId, dpnId,
+ vrfEntry.getDestPrefix(), /*listBucketInfo*/ null, /*remove*/ false);
+ returnLocalDpnId.add(dpnId);
+ }
+ } else {
+ LOG.error("localNextHopInfo unavailable while deleting prefix {} with rds {}, primary rd {} in "
+ + "vpn {}", vrfEntry.getDestPrefix(), usedRds, rd, vpnName);
}
}
java.util.Optional<Long> optionalLabel = FibUtil.getLabelFromRoutePaths(vrfEntry);
if (optionalLabel.isPresent()) {
Long label = optionalLabel.get();
- List<String> nextHopAddressList = FibUtil.getNextHopListFromRoutePaths(vrfEntry);
+ List<String> nextHopAddressList = FibHelper.getNextHopListFromRoutePaths(vrfEntry);
LabelRouteInfo lri = getLabelRouteInfo(label);
if (isPrefixAndNextHopPresentInLri(vrfEntry.getDestPrefix(), nextHopAddressList, lri)) {
PrefixesBuilder prefixBuilder = new PrefixesBuilder();
prefixBuilder.setDpnId(lri.getDpnId());
BigInteger dpnId = checkDeleteLocalFibEntry(prefixBuilder.build(), localNextHopIP,
- vpnId, rd, vrfEntry, false /*isExtraRoute*/);
+ vpnId, rd, vrfEntry);
if (!dpnId.equals(BigInteger.ZERO)) {
returnLocalDpnId.add(dpnId);
}
} else {
BigInteger dpnId = checkDeleteLocalFibEntry(localNextHopInfo, localNextHopIP,
- vpnId, rd, vrfEntry, false /*isExtraRoute*/);
+ vpnId, rd, vrfEntry);
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, final boolean isExtraRoute) {
+ final VrfEntry vrfEntry) {
if (localNextHopInfo != null) {
final BigInteger dpnId = localNextHopInfo.getDpnId();
- DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
- dataStoreCoordinator.enqueueJob("FIB-" + vpnId.toString() + "-"
- + dpnId.toString() + "-" + vrfEntry.getDestPrefix(),
- () -> {
- WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
- makeConnectedRoute(dpnId, vpnId, vrfEntry, rd, null /* instructions */,
- NwConstants.DEL_FLOW, tx);
- if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.SELF_IMPORTED) {
- FibUtil.getLabelFromRoutePaths(vrfEntry).ifPresent(label -> {
- makeLFibTableEntry(dpnId, label, null /* instructions */,
- DEFAULT_FIB_FLOW_PRIORITY, NwConstants.DEL_FLOW, tx);
- removeTunnelTableEntry(dpnId, label, tx);
- });
- }
- List<ListenableFuture<Void>> futures = new ArrayList<>();
- futures.add(tx.submit());
- return futures;
- });
+ if (!FibUtil.enforceVxlanDatapathSemanticsforInternalRouterVpn(dataBroker, localNextHopInfo
+ .getSubnetId(), vpnId, rd)) {
+ DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
+ dataStoreCoordinator.enqueueJob("FIB-" + vpnId.toString() + "-" + dpnId.toString() + "-" + vrfEntry
+ .getDestPrefix(), () -> {
+ WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
+ makeConnectedRoute(dpnId, vpnId, vrfEntry, rd, null /* instructions */, NwConstants.DEL_FLOW,
+ tx);
+ if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.SELF_IMPORTED) {
+ FibUtil.getLabelFromRoutePaths(vrfEntry).ifPresent(label -> {
+ makeLFibTableEntry(dpnId, label, null /* instructions */, DEFAULT_FIB_FLOW_PRIORITY,
+ NwConstants.DEL_FLOW, tx);
+ removeTunnelTableEntry(dpnId, label, tx);
+ });
+ }
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ futures.add(tx.submit());
+ return futures;
+ });
+ }
//TODO: verify below adjacency call need to be optimized (?)
deleteLocalAdjacency(dpnId, vpnId, localNextHopIP, vrfEntry.getDestPrefix());
return dpnId;
new ExtraRoutesKey(vrfId)).child(Routes.class, new RoutesKey(ipPrefix)).build();
}
- public Routes getVpnToExtraroute(String vpnRd, String destPrefix) {
- Optional<String> optVpnName = FibUtil.getVpnNameFromRd(dataBroker, vpnRd);
- if (optVpnName.isPresent()) {
+ public Routes getVpnToExtraroute(Long vpnId, String vpnRd, String destPrefix) {
+ String optVpnName = FibUtil.getVpnNameFromId(dataBroker, vpnId);
+ if (optVpnName != null) {
InstanceIdentifier<Routes> vpnExtraRoutesId = getVpnToExtrarouteIdentifier(
- optVpnName.get(), vpnRd, destPrefix);
- return FibUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, vpnExtraRoutesId).orNull();
+ optVpnName, vpnRd, destPrefix);
+ return MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, vpnExtraRoutesId).orNull();
}
return null;
}
vrfEntry.getDestPrefix(), rd, remoteDpnId);
List<AdjacencyResult> adjacencyResults = resolveAdjacency(remoteDpnId, vpnId, vrfEntry, rd);
- if (adjacencyResults.isEmpty()) {
- LOG.error("Could not get interface for route-paths: {} in vpn {}",
- vrfEntry.getRoutePaths(), rd);
- LOG.warn("Failed to add Route: {} in vpn: {}",
- vrfEntry.getDestPrefix(), rd);
+ if (adjacencyResults == null || adjacencyResults.isEmpty()) {
+ LOG.error("Could not get interface for route-paths: {} in vpn {}", vrfEntry.getRoutePaths(), rd);
+ LOG.warn("Failed to add Route: {} in vpn: {}", vrfEntry.getDestPrefix(), rd);
return;
}
- List<String> usedRds = VpnExtraRouteHelper.getUsedRds(dataBroker, vpnId, vrfEntry.getDestPrefix());
- List<Routes> vpnExtraRoutes = VpnExtraRouteHelper.getAllVpnExtraRoutes(dataBroker,
- vpnName, usedRds, vrfEntry.getDestPrefix());
- if (!vpnExtraRoutes.isEmpty()) {
- List<InstructionInfo> instructions = new ArrayList<>();
- long groupId = nextHopManager.createNextHopGroups(vpnId, rd, remoteDpnId, vrfEntry,
- 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));
- makeConnectedRoute(remoteDpnId, vpnId, vrfEntry, rd, instructions, NwConstants.ADD_FLOW, tx);
+ if (RouteOrigin.BGP.getValue().equals(vrfEntry.getOrigin())) {
+ programRemoteFibForBgpRoutes(remoteDpnId, vpnId, vrfEntry, tx, rd, adjacencyResults);
} else {
- List<InstructionInfo> instructions = new ArrayList<>();
- for (AdjacencyResult adjacencyResult : adjacencyResults) {
- List<ActionInfo> actionInfos = new ArrayList<>();
- String egressInterface = adjacencyResult.getInterfaceName();
- if (FibUtil.isTunnelInterface(adjacencyResult)) {
- addTunnelInterfaceActions(egressInterface, vpnId, vrfEntry, actionInfos);
- } else {
- addRewriteDstMacAction(vpnId, vrfEntry, actionInfos);
- }
- List<ActionInfo> egressActions = nextHopManager.getEgressActionsForInterface(egressInterface,
- actionInfos.size());
- if (egressActions.isEmpty()) {
- LOG.error(
- "Failed to retrieve egress action for prefix {} route-paths {} interface {}. "
- + "Aborting remote FIB entry creation.",
- vrfEntry.getDestPrefix(), vrfEntry.getRoutePaths(), egressInterface);
+ List<String> usedRds = VpnExtraRouteHelper.getUsedRds(dataBroker, vpnId, vrfEntry.getDestPrefix());
+ List<Routes> vpnExtraRoutes = VpnExtraRouteHelper.getAllVpnExtraRoutes(dataBroker,
+ vpnName, usedRds, vrfEntry.getDestPrefix());
+ if (!vpnExtraRoutes.isEmpty()) {
+ List<InstructionInfo> instructions = new ArrayList<>();
+ long groupId = nextHopManager.createNextHopGroups(vpnId, rd, remoteDpnId, vrfEntry,
+ 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;
}
- actionInfos.addAll(egressActions);
+ List<ActionInfo> actionInfos =
+ Collections.singletonList(new ActionGroup(groupId));
instructions.add(new InstructionApplyActions(actionInfos));
+ makeConnectedRoute(remoteDpnId, vpnId, vrfEntry, rd, instructions, NwConstants.ADD_FLOW, tx);
+ } else {
+ programRemoteFib(remoteDpnId, vpnId, vrfEntry, tx, rd, adjacencyResults);
}
- makeConnectedRoute(remoteDpnId, vpnId, vrfEntry, rd, instructions, NwConstants.ADD_FLOW, tx);
}
if (!wrTxPresent) {
tx.submit();
LOG.debug("Successfully added FIB entry for prefix {} in vpnId {}", vrfEntry.getDestPrefix(), vpnId);
}
+ private void programRemoteFib(final BigInteger remoteDpnId, final long vpnId,
+ final VrfEntry vrfEntry, WriteTransaction tx, String rd, List<AdjacencyResult> adjacencyResults) {
+ List<InstructionInfo> instructions = new ArrayList<>();
+ for (AdjacencyResult adjacencyResult : adjacencyResults) {
+ List<ActionInfo> actionInfos = new ArrayList<>();
+ String egressInterface = adjacencyResult.getInterfaceName();
+ if (FibUtil.isTunnelInterface(adjacencyResult)) {
+ addTunnelInterfaceActions(adjacencyResult, vpnId, vrfEntry, actionInfos, rd);
+ } else {
+ addRewriteDstMacAction(vpnId, vrfEntry, actionInfos);
+ }
+ List<ActionInfo> egressActions = nextHopManager.getEgressActionsForInterface(egressInterface,
+ actionInfos.size());
+ if (egressActions.isEmpty()) {
+ LOG.error(
+ "Failed to retrieve egress action for prefix {} route-paths {} interface {}. "
+ + "Aborting remote FIB entry creation.",
+ vrfEntry.getDestPrefix(), vrfEntry.getRoutePaths(), egressInterface);
+ return;
+ }
+ actionInfos.addAll(egressActions);
+ instructions.add(new InstructionApplyActions(actionInfos));
+ }
+ makeConnectedRoute(remoteDpnId, vpnId, vrfEntry, rd, instructions, NwConstants.ADD_FLOW, tx);
+ }
+
private void addRewriteDstMacAction(long vpnId, VrfEntry vrfEntry, List<ActionInfo> actionInfos) {
+ if (vrfEntry.getMac() != null) {
+ actionInfos.add(new ActionSetFieldEthernetDestination(actionInfos.size(),
+ new MacAddress(vrfEntry.getMac())));
+ return;
+ }
+
String ipPrefix = vrfEntry.getDestPrefix();
Prefixes prefixInfo = FibUtil.getPrefixToInterface(dataBroker, vpnId, ipPrefix);
if (prefixInfo == null) {
String ifName = prefixInfo.getVpnInterfaceName();
if (ifName == null) {
- LOG.debug("Failed to get VPN interface for prefix {}", ipPrefix);
+ LOG.warn("Failed to get VPN interface for prefix {}", ipPrefix);
return;
}
actionInfos.add(new ActionSetFieldEthernetDestination(actionInfos.size(), new MacAddress(macAddress)));
}
- private void addTunnelInterfaceActions(String tunnelInterface, long vpnId, VrfEntry vrfEntry,
- List<ActionInfo> actionInfos) {
+ private void addTunnelInterfaceActions(AdjacencyResult adjacencyResult, long vpnId, VrfEntry vrfEntry,
+ List<ActionInfo> actionInfos, String rd) {
Class<? extends TunnelTypeBase> tunnelType = VpnExtraRouteHelper.getTunnelType(interfaceManager,
- tunnelInterface);
- java.util.Optional<Long> optionalLabel = FibUtil.getLabelFromRoutePaths(vrfEntry);
+ adjacencyResult.getInterfaceName());
+ // TODO - For now have added routePath into adjacencyResult so that we know for which
+ // routePath this result is built for. If this is not possible construct a map which does
+ // the same.
+ String nextHopIp = adjacencyResult.getNextHopIp();
+ java.util.Optional<Long> optionalLabel = FibUtil.getLabelForNextHop(vrfEntry, nextHopIp);
if (!optionalLabel.isPresent()) {
- LOG.warn("RoutePaths not available");
+ LOG.warn("NextHopIp {} not found in vrfEntry {}", nextHopIp, vrfEntry);
return;
}
long label = optionalLabel.get();
actionInfos.add(new ActionSetFieldMplsLabel(label));
actionInfos.add(new ActionNxLoadInPort(BigInteger.ZERO));
} else {
- BigInteger tunnelId;
+ BigInteger tunnelId = null;
// FIXME vxlan vni bit set is not working properly with OVS.need to
// revisit
if (tunnelType.equals(TunnelTypeVxlan.class)) {
- tunnelId = BigInteger.valueOf(label);
+ Prefixes prefixInfo = FibUtil.getPrefixToInterface(dataBroker, vpnId, vrfEntry.getDestPrefix());
+ // Internet VPN VNI will be used as tun_id for NAT use-cases
+ if (prefixInfo.isNatPrefix()) {
+ if (vrfEntry.getL3vni() != null && vrfEntry.getL3vni() != 0) {
+ tunnelId = BigInteger.valueOf(vrfEntry.getL3vni());
+ }
+ } else {
+ if (FibUtil.enforceVxlanDatapathSemanticsforInternalRouterVpn(dataBroker, prefixInfo.getSubnetId(),
+ vpnId, rd)) {
+ java.util.Optional<Long> optionalVni = FibUtil.getVniForVxlanNetwork(dataBroker,
+ prefixInfo.getSubnetId());
+ if (!optionalVni.isPresent()) {
+ LOG.error("VNI not found for nexthop {} vrfEntry {} with subnetId {}", nextHopIp,
+ vrfEntry, prefixInfo.getSubnetId());
+ return;
+ }
+ tunnelId = BigInteger.valueOf(optionalVni.get());
+ } else {
+ tunnelId = BigInteger.valueOf(label);
+ }
+ }
} else {
tunnelId = BigInteger.valueOf(label);
}
-
LOG.debug("adding set tunnel id action for label {}", label);
actionInfos.add(new ActionSetFieldTunnelId(tunnelId));
addRewriteDstMacAction(vpnId, vrfEntry, actionInfos);
private void delIntfFromDpnToVpnList(long vpnId, BigInteger dpnId, String intfName, String rd) {
InstanceIdentifier<VpnToDpnList> id = FibUtil.getVpnToDpnListIdentifier(rd, dpnId);
- Optional<VpnToDpnList> dpnInVpn = FibUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
+ Optional<VpnToDpnList> dpnInVpn = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
if (dpnInVpn.isPresent()) {
List<VpnInterfaces> vpnInterfaces = dpnInVpn.get().getVpnInterfaces();
VpnInterfaces currVpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
if (vpnInterfaces.remove(currVpnInterface)) {
if (vpnInterfaces.isEmpty()) {
LOG.trace("Last vpn interface {} on dpn {} for vpn {}. Clean up fib in dpn", intfName, dpnId, rd);
- FibUtil.delete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
+ MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
cleanUpDpnForVpn(dpnId, vpnId, rd, null);
} else {
LOG.trace("Delete vpn interface {} from dpn {} to vpn {} list.", intfName, dpnId, rd);
- FibUtil.delete(dataBroker, LogicalDatastoreType.OPERATIONAL, id.child(
+ MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id.child(
VpnInterfaces.class,
new VpnInterfacesKey(intfName)));
}
}
}
- void cleanUpOpDataForFib(Long vpnId, String rd, final VrfEntry vrfEntry) {
+ 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,
remove the adjacency corresponding to this fib entry.
Prefixes prefixInfo = FibUtil.getPrefixToInterface(dataBroker, vpnId, vrfEntry.getDestPrefix());
Routes extraRoute = null;
if (prefixInfo == null) {
- extraRoute = getVpnToExtraroute(rd, vrfEntry.getDestPrefix());
+ List<String> usedRds = VpnExtraRouteHelper.getUsedRds(dataBroker, vpnId, vrfEntry.getDestPrefix());
+ String usedRd = usedRds.isEmpty() ? primaryRd : usedRds.get(0);
+ extraRoute = getVpnToExtraroute(vpnId, usedRd, vrfEntry.getDestPrefix());
if (extraRoute != null) {
for (String nextHopIp : extraRoute.getNexthopIpList()) {
LOG.debug("NextHop IP for destination {} is {}", vrfEntry.getDestPrefix(), nextHopIp);
if (nextHopIp != null) {
prefixInfo = FibUtil.getPrefixToInterface(dataBroker, vpnId, nextHopIp
+ NwConstants.IPV4PREFIX);
- checkCleanUpOpDataForFib(prefixInfo, vpnId, rd, vrfEntry, extraRoute);
+ checkCleanUpOpDataForFib(prefixInfo, vpnId, primaryRd, vrfEntry, extraRoute);
}
}
}
java.util.Optional<Long> optionalLabel = FibUtil.getLabelFromRoutePaths(vrfEntry);
if (optionalLabel.isPresent()) {
Long label = optionalLabel.get();
- List<String> nextHopAddressList = FibUtil.getNextHopListFromRoutePaths(vrfEntry);
+ List<String> nextHopAddressList = FibHelper.getNextHopListFromRoutePaths(vrfEntry);
LabelRouteInfo lri = getLabelRouteInfo(label);
if (isPrefixAndNextHopPresentInLri(vrfEntry.getDestPrefix(), nextHopAddressList, lri)) {
PrefixesBuilder prefixBuilder = new PrefixesBuilder();
prefixInfo = prefixBuilder.build();
LOG.debug("Fetched labelRouteInfo for label {} interface {} and got dpn {}",
label, prefixInfo.getVpnInterfaceName(), lri.getDpnId());
- checkCleanUpOpDataForFib(prefixInfo, vpnId, rd, vrfEntry, extraRoute);
+ checkCleanUpOpDataForFib(prefixInfo, vpnId, primaryRd, vrfEntry, extraRoute);
}
}
}
} else {
- checkCleanUpOpDataForFib(prefixInfo, vpnId, rd, vrfEntry, extraRoute);
+ checkCleanUpOpDataForFib(prefixInfo, vpnId, primaryRd, vrfEntry, extraRoute);
}
}
//TODO(KIRAN) : Move the below block when addressing iRT/eRT for L3VPN Over VxLan
if (vrfEntry.getEncapType().equals(VrfEntry.EncapType.Mplsgre)) {
FibUtil.getLabelFromRoutePaths(vrfEntry).ifPresent(label -> {
- List<String> nextHopAddressList = FibUtil.getNextHopListFromRoutePaths(vrfEntry);
+ List<String> nextHopAddressList = FibHelper.getNextHopListFromRoutePaths(vrfEntry);
synchronized (label.toString().intern()) {
LabelRouteInfo lri = getLabelRouteInfo(label);
if (lri != null && lri.getPrefix().equals(vrfEntry.getDestPrefix())
});
}
String ifName = prefixInfo.getVpnInterfaceName();
- Optional<VpnInterface> optvpnInterface = FibUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
+ Optional<VpnInterface> optvpnInterface = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
FibUtil.getVpnInterfaceIdentifier(ifName));
if (optvpnInterface.isPresent()) {
long associatedVpnId = FibUtil.getVpnId(dataBroker, optvpnInterface.get().getVpnInstanceName());
}
if (extraRoute != null) {
Optional<String> optVpnName = FibUtil.getVpnNameFromRd(dataBroker, rd);
+ List<String> usedRds = VpnExtraRouteHelper.getUsedRds(dataBroker, vpnId, vrfEntry.getDestPrefix());
+ //Only one used Rd present in case of removal event
+ String usedRd = usedRds.get(0);
if (optVpnName.isPresent()) {
writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL,
- getVpnToExtrarouteIdentifier(optVpnName.get(), rd, vrfEntry.getDestPrefix()));
+ getVpnToExtrarouteIdentifier(optVpnName.get(), usedRd, vrfEntry.getDestPrefix()));
+ writeOperTxn.delete(LogicalDatastoreType.CONFIGURATION,
+ VpnExtraRouteHelper.getUsedRdsIdentifier(vpnId, vrfEntry.getDestPrefix()));
}
}
- Optional<Adjacencies> optAdjacencies = FibUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
+ Optional<Adjacencies> optAdjacencies = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
FibUtil.getAdjListPath(ifName));
int numAdj = 0;
if (optAdjacencies.isPresent()) {
long elanTag = 0L;
SubnetRoute subnetRoute = vrfEntry.getAugmentation(SubnetRoute.class);
final java.util.Optional<Long> optionalLabel = FibUtil.getLabelFromRoutePaths(vrfEntry);
- List<String> nextHopAddressList = FibUtil.getNextHopListFromRoutePaths(vrfEntry);
+ List<String> nextHopAddressList = FibHelper.getNextHopListFromRoutePaths(vrfEntry);
String vpnName = FibUtil.getVpnNameFromId(dataBroker, vpnInstance.getVpnId());
if (subnetRoute != null) {
elanTag = subnetRoute.getElantag();
vpnInstance.getVpnId(), vrfEntry.getDestPrefix());
String usedRd = null;
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");
} else {
// The first rd is retrieved from usedrds as Only 1 rd would be present as extra route prefix
//is not present in any other DPN
- usedRd = usedRds.get(0);
+ extraRouteOptional = VpnExtraRouteHelper
+ .getVpnExtraroutes(dataBroker, vpnName, usedRds.get(0), vrfEntry.getDestPrefix());
}
+ } else {
+ extraRouteOptional = Optional.absent();
}
- //Is this fib route an extra route? If yes, get the nexthop which would be an adjacency in the vpn
- extraRouteOptional = (usedRds != null && !usedRds.isEmpty()) ? VpnExtraRouteHelper
- .getVpnExtraroutes(dataBroker, vpnName, usedRd, vrfEntry.getDestPrefix()) : Optional.absent();
DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
dataStoreCoordinator.enqueueJob("FIB-" + usedRd + "-" + vrfEntry.getDestPrefix(),
() -> {
if (optVpnUuid.isPresent()) {
String vpnUuid = optVpnUuid.get();
FibUtil.getFirstNextHopAddress(vrfEntry).ifPresent(routeNexthop -> {
- Optional<InterVpnLinkDataComposite> optInterVpnLink =
- InterVpnLinkCache.getInterVpnLinkByVpnId(vpnUuid);
+ Optional<InterVpnLinkDataComposite> optInterVpnLink = InterVpnLinkCache.getInterVpnLinkByVpnId(vpnUuid);
if (optInterVpnLink.isPresent()) {
InterVpnLinkDataComposite interVpnLink = optInterVpnLink.get();
if (interVpnLink.isIpAddrTheOtherVpnEndpoint(routeNexthop, vpnUuid)) {
// This is route that points to the other endpoint of an InterVpnLink
// In that case, we should look for the FIB table pointing to
// LPortDispatcher table and remove it.
- removeInterVPNLinkRouteFlows(interVpnLink.getInterVpnLinkName(),
- interVpnLink.isFirstEndpointVpnName(rd),
- vrfEntry);
+ removeInterVPNLinkRouteFlows(interVpnLink, vpnUuid, vrfEntry);
}
}
});
if (vpnToDpnList != null) {
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 {
- rd = usedRds.get(0);
+ extraRouteOptional = VpnExtraRouteHelper.getVpnExtraroutes(dataBroker, vpnName,
+ usedRds.get(0), vrfEntry.getDestPrefix());
}
+ } else {
+ extraRouteOptional = Optional.absent();
}
- //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());
for (VpnToDpnList curDpn : vpnToDpnList) {
if (curDpn.getDpnState() == VpnToDpnList.DpnState.Active) {
deleteRemoteRoute(BigInteger.ZERO, curDpn.getDpnId(), vpnInstance.getVpnId(), vrfTableKey,
private void deleteFibEntry(BigInteger remoteDpnId, long vpnId, VrfEntry vrfEntry,
String rd, WriteTransaction tx) {
+ // When the tunnel is removed the fib entries should be reprogrammed/deleted depending on
+ // the adjacencyResults.
+ if (RouteOrigin.value(vrfEntry.getOrigin()) == RouteOrigin.BGP) {
+ List<AdjacencyResult> adjacencyResults = resolveAdjacency(remoteDpnId, vpnId, vrfEntry, rd);
+ if (!adjacencyResults.isEmpty()) {
+ programRemoteFibForBgpRoutes(remoteDpnId, vpnId, vrfEntry, tx, rd, adjacencyResults);
+ return;
+ }
+ }
makeConnectedRoute(remoteDpnId, vpnId, vrfEntry, rd, null, NwConstants.DEL_FLOW, tx);
LOG.debug("Successfully delete FIB entry: vrfEntry={}, vpnId={}", vrfEntry.getDestPrefix(), vpnId);
}
FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.L3_FIB_TABLE, flowRef, priority,
flowRef, 0, 0,
COOKIE_VM_FIB_TABLE, matches, instructions);
-
Flow flow = flowEntity.getFlowBuilder().build();
String flowId = flowEntity.getFlowId();
FlowKey flowKey = new FlowKey(new FlowId(flowId));
LOG.trace("New dpn {} for vpn {} : populateFibOnNewDpn", dpnId, rd);
InstanceIdentifier<VrfTables> id = buildVrfId(rd);
final VpnInstanceOpDataEntry vpnInstance = getVpnInstance(rd);
- final Optional<VrfTables> vrfTable = FibUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
+ final Optional<VrfTables> vrfTable = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
if (!vrfTable.isPresent()) {
LOG.warn("VRF Table not yet available for RD {}", rd);
if (callback != null) {
if (RouteOrigin.value(vrfEntry.getOrigin()) == RouteOrigin.SELF_IMPORTED) {
java.util.Optional<Long> optionalLabel = FibUtil.getLabelFromRoutePaths(vrfEntry);
if (optionalLabel.isPresent()) {
- List<String> nextHopList = FibUtil.getNextHopListFromRoutePaths(vrfEntry);
+ List<String> nextHopList = FibHelper.getNextHopListFromRoutePaths(vrfEntry);
LabelRouteInfo lri = getLabelRouteInfo(optionalLabel.get());
if (isPrefixAndNextHopPresentInLri(vrfEntry.getDestPrefix(), nextHopList, lri)) {
if (lri.getDpnId().equals(dpnId)) {
}
}
}
- // Passing null as we don't know the dpn
- // to which prefix is attached at this point
- createRemoteFibEntry(dpnId, vpnId, vrfTable.get().getKey(), vrfEntry, tx);
+
+ boolean shouldCreateRemoteFibEntry = shouldCreateFibEntryForVrfAndVpnIdOnDpn(vpnId,
+ vrfEntry, dpnId);
+ if (shouldCreateRemoteFibEntry) {
+ LOG.trace("Will create remote FIB entry for vrfEntry {} on DPN {}",
+ vrfEntry, dpnId);
+ createRemoteFibEntry(dpnId, vpnId, vrfTable.get().getKey(), vrfEntry, tx);
+ }
}
//TODO: if we have 100K entries in FIB, can it fit in one Tranasaction (?)
futures.add(tx.submit());
dpnId, vpnId, rd, localNextHopIp, remoteNextHopIp);
InstanceIdentifier<VrfTables> id = buildVrfId(rd);
final VpnInstanceOpDataEntry vpnInstance = getVpnInstance(rd);
- final Optional<VrfTables> vrfTable = FibUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
+ final Optional<VrfTables> vrfTable = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
if (vrfTable.isPresent()) {
DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
dataStoreCoordinator.enqueueJob("FIB-" + vpnId + "-" + dpnId.toString(),
dpnId, vpnId, rd, localNextHopIp, remoteNextHopIp);
InstanceIdentifier<VrfTables> id = buildVrfId(rd);
final VpnInstanceOpDataEntry vpnInstance = getVpnInstance(rd);
- final Optional<VrfTables> vrfTable = FibUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
+ final Optional<VrfTables> vrfTable = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
if (vrfTable.isPresent()) {
DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
dataStoreCoordinator.enqueueJob("FIB-" + vpnId + "-" + dpnId.toString(),
if (routePathList == null || (routePathList.isEmpty())) {
modVrfEntry = FibHelper.getVrfEntryBuilder(vrfEntry, label,
Collections.singletonList(destTepIp),
- RouteOrigin.value(vrfEntry.getOrigin()))
- .build();
+ RouteOrigin.value(vrfEntry.getOrigin()), null /* parentVpnRd */).build();
} else {
modVrfEntry = vrfEntry;
}
LOG.trace("cleanUpDpnForVpn: Remove dpn {} for vpn {} : cleanUpDpnForVpn", dpnId, rd);
InstanceIdentifier<VrfTables> id = buildVrfId(rd);
final VpnInstanceOpDataEntry vpnInstance = getVpnInstance(rd);
- final Optional<VrfTables> vrfTable = FibUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
+ final Optional<VrfTables> vrfTable = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
if (vrfTable.isPresent()) {
DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
dataStoreCoordinator.enqueueJob("FIB-" + vpnId + "-" + dpnId.toString(),
// to which prefix is attached at this point
List<String> usedRds = VpnExtraRouteHelper.getUsedRds(dataBroker, vpnInstance.getVpnId(),
vrfEntry.getDestPrefix());
- String usedRd;
+ String vpnName = FibUtil.getVpnNameFromId(dataBroker, 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 {
- usedRd = usedRds.get(0);
+ extraRouteOptional = VpnExtraRouteHelper.getVpnExtraroutes(dataBroker, vpnName,
+ usedRds.get(0), vrfEntry.getDestPrefix());
+
}
+ } else {
+ extraRouteOptional = Optional.absent();
}
- //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,
- FibUtil.getVpnNameFromId(dataBroker, vpnInstance.getVpnId()), usedRds.get(0),
- vrfEntry.getDestPrefix());
-
deleteRemoteRoute(null, dpnId, vpnId, vrfTable.get().getKey(), vrfEntry,
extraRouteOptional, tx);
}
dpnId, vpnId, rd, localNextHopIp, remoteNextHopIp);
InstanceIdentifier<VrfTables> id = buildVrfId(rd);
final VpnInstanceOpDataEntry vpnInstance = getVpnInstance(rd);
- final Optional<VrfTables> vrfTable = FibUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
+ final Optional<VrfTables> vrfTable = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
if (vrfTable.isPresent()) {
DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
dataStoreCoordinator.enqueueJob("FIB-" + vpnId + "-" + dpnId.toString(),
dpnId, vpnId, rd, localNextHopIp, remoteNextHopIp);
InstanceIdentifier<VrfTables> id = buildVrfId(rd);
final VpnInstanceOpDataEntry vpnInstance = getVpnInstance(rd);
- final Optional<VrfTables> vrfTable = FibUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
+ final Optional<VrfTables> vrfTable = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
if (vrfTable.isPresent()) {
DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
dataStoreCoordinator.enqueueJob("FIB-" + vpnId + "-" + dpnId.toString(),
protected List<AdjacencyResult> resolveAdjacency(final BigInteger remoteDpnId, final long vpnId,
final VrfEntry vrfEntry, String rd) {
+ List<RoutePaths> routePaths = vrfEntry.getRoutePaths();
+ FibHelper.sortIpAddress(routePaths);
List<AdjacencyResult> adjacencyList = new ArrayList<>();
List<String> prefixIpList = new ArrayList<>();
LOG.trace("resolveAdjacency called with remotedDpnId {}, vpnId{}, VrfEntry {}",
}
for (String prefixIp : prefixIpList) {
- adjacencyList.addAll(vrfEntry.getRoutePaths().stream()
+ if (routePaths == null || routePaths.isEmpty()) {
+ LOG.trace("Processing Destination IP {} without NextHop IP", prefixIp);
+ AdjacencyResult adjacencyResult = nextHopManager.getRemoteNextHopPointer(remoteDpnId, vpnId,
+ prefixIp, null);
+ addAdjacencyResultToList(adjacencyList, adjacencyResult);
+ continue;
+ }
+ adjacencyList.addAll(routePaths.stream()
.map(routePath -> {
LOG.debug("NextHop IP for destination {} is {}", prefixIp,
routePath.getNexthopAddress());
})
.filter(adjacencyResult -> adjacencyResult != null && !adjacencyList.contains(adjacencyResult))
.distinct()
- .collect(Collectors.toList()));
+ .collect(toList()));
}
} catch (NullPointerException e) {
LOG.trace("", e);
return adjacencyList;
}
+ private void addAdjacencyResultToList(List<AdjacencyResult> adjacencyList, AdjacencyResult adjacencyResult) {
+ if (adjacencyResult != null && !adjacencyList.contains(adjacencyResult)) {
+ adjacencyList.add(adjacencyResult);
+ }
+ }
+
protected VpnInstanceOpDataEntry getVpnInstance(String rd) {
InstanceIdentifier<VpnInstanceOpDataEntry> id =
InstanceIdentifier.create(VpnInstanceOpData.class)
.child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd));
Optional<VpnInstanceOpDataEntry> vpnInstanceOpData =
- FibUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
+ MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
return vpnInstanceOpData.isPresent() ? vpnInstanceOpData.get() : null;
}
result.add(String.format(" %-7s %-20s %-20s %-7s %-7s", "RD", "Prefix", "NextHop", "Label", "Origin"));
result.add("-------------------------------------------------------------------");
InstanceIdentifier<FibEntries> id = InstanceIdentifier.create(FibEntries.class);
- Optional<FibEntries> fibEntries = FibUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
+ Optional<FibEntries> fibEntries = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
if (fibEntries.isPresent()) {
List<VrfTables> vrfTables = fibEntries.get().getVrfTables();
for (VrfTables vrfTable : vrfTables) {
for (VrfEntry vrfEntry : vrfTable.getVrfEntry()) {
List<RoutePaths> routePaths = vrfEntry.getRoutePaths();
+ if (routePaths == null) {
+ result.add(String.format(" %-7s %-20s %-20s %-7s",
+ vrfTable.getRouteDistinguisher(),
+ vrfEntry.getDestPrefix(), "local", vrfEntry.getOrigin()));
+ continue;
+ }
for (RoutePaths routePath : routePaths) {
result.add(String.format(" %-7s %-20s %-20s %-7s %-7s",
vrfTable.getRouteDistinguisher(),
InstanceIdentifier<VrfEntry> vrfEntryId = InstanceIdentifier.builder(FibEntries.class)
.child(VrfTables.class, new VrfTablesKey(rd))
.child(VrfEntry.class, new VrfEntryKey(ipPrefix)).build();
- Optional<VrfEntry> vrfEntry = read(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
+ Optional<VrfEntry> vrfEntry = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
if (vrfEntry.isPresent()) {
return vrfEntry.get();
}
}
}
- public void removeInterVPNLinkRouteFlows(final String interVpnLinkName,
- final boolean isVpnFirstEndPoint,
+ public void removeInterVPNLinkRouteFlows(final InterVpnLinkDataComposite interVpnLink,
+ final String vpnName,
final VrfEntry vrfEntry) {
- Preconditions.checkArgument(vrfEntry.getRoutePaths() != null
- && vrfEntry.getRoutePaths().size() == 1);
- Optional<InterVpnLinkState> interVpnLinkState = FibUtil.getInterVpnLinkState(dataBroker, interVpnLinkName);
+ Preconditions.checkArgument(vrfEntry.getRoutePaths() != null && vrfEntry.getRoutePaths().size() == 1);
+
+ String interVpnLinkName = interVpnLink.getInterVpnLinkName();
+ List<BigInteger> targetDpns = interVpnLink.getEndpointDpnsByVpnName(vpnName);
- if (!interVpnLinkState.isPresent()) {
- LOG.warn("Could not find State for InterVpnLink {}", interVpnLinkName);
+ if (targetDpns.isEmpty()) {
+ LOG.warn("Could not find DPNs for VPN {} in InterVpnLink {}", vpnName, interVpnLinkName);
return;
}
- List<BigInteger> targetDpns =
- isVpnFirstEndPoint ? interVpnLinkState.get().getFirstEndpointState().getDpId()
- : interVpnLinkState.get().getSecondEndpointState().getDpId();
-
- java.util.Optional<String> optionalNextHop = FibUtil.getFirstNextHopAddress(vrfEntry);
- java.util.Optional<Long> optionalLabel = FibUtil.getLabelFromRoutePaths(vrfEntry);
+ java.util.Optional<String> optNextHop = FibUtil.getFirstNextHopAddress(vrfEntry);
+ java.util.Optional<Long> optLabel = FibUtil.getLabelFromRoutePaths(vrfEntry);
// delete from FIB
//
- optionalNextHop.ifPresent(nextHop -> {
+ 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))
.setTableId(NwConstants.L3_FIB_TABLE).setFlowName(flowRef).build();
- LOG.trace("Removing flow in FIB table for interVpnLink {} key {}",
- interVpnLinkName, flowRef);
-
+ LOG.trace("Removing flow in FIB table for interVpnLink {} key {}", interVpnLinkName, flowRef);
for (BigInteger dpId : targetDpns) {
LOG.debug("Removing flow: VrfEntry=[prefix={} nexthop={}] dpn {} for InterVpnLink {} in FIB",
- vrfEntry.getDestPrefix(), nextHop,
- dpId, interVpnLinkName);
+ vrfEntry.getDestPrefix(), nextHop, dpId, interVpnLinkName);
mdsalManager.removeFlow(dpId, flow);
}
// delete from LFIB
//
- optionalLabel.ifPresent(label -> {
+ 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, null /* no instructions */,
- LFIB_INTERVPN_PRIORITY, NwConstants.DEL_FLOW, tx);
+ vrfEntry.getDestPrefix(), label, dpId, interVpnLinkName);
+ makeLFibTableEntry(dpId, label, /*instructions*/null, LFIB_INTERVPN_PRIORITY, NwConstants.DEL_FLOW, tx);
}
tx.submit();
});
}
+
private Consumer<? super VrfEntry> getConsumerForCreatingRemoteFib(
final BigInteger dpnId, final long vpnId, final String rd,
final String remoteNextHopIp, final Optional<VrfTables> vrfTable,
return lri != null && lri.getPrefix().equals(prefix)
&& nextHopAddressList.contains(lri.getNextHopIpList().get(0));
}
+
+ private boolean shouldCreateFibEntryForVrfAndVpnIdOnDpn(Long vpnId, VrfEntry vrfEntry, BigInteger dpnId) {
+ if (RouteOrigin.value(vrfEntry.getOrigin()) == RouteOrigin.BGP) {
+ return true;
+ }
+
+ Prefixes prefix = FibUtil.getPrefixToInterface(dataBroker, vpnId, vrfEntry.getDestPrefix());
+ if (prefix != null) {
+ BigInteger prefixDpnId = prefix.getDpnId();
+ if (prefixDpnId == dpnId) {
+ LOG.trace("Should not create remote FIB entry for vrfEntry {} on DPN {}",
+ vrfEntry, dpnId);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private void programRemoteFibForBgpRoutes(final BigInteger remoteDpnId, final long vpnId,
+ final VrfEntry vrfEntry, WriteTransaction tx, String rd, List<AdjacencyResult> adjacencyResults) {
+ Preconditions.checkArgument(vrfEntry.getRoutePaths().size() <= 2);
+
+ if (adjacencyResults.size() == 1) {
+ programRemoteFib(remoteDpnId, vpnId, vrfEntry, tx, rd, adjacencyResults);
+ return;
+ }
+ // ECMP Use case, point to LB group. Move the mpls label accordingly.
+ List<String> tunnelList =
+ adjacencyResults.stream()
+ .map(adjacencyResult -> adjacencyResult.getNextHopIp())
+ .sorted().collect(toList());
+ String lbGroupKey = FibUtil.getGreLbGroupKey(tunnelList);
+ long groupId = nextHopManager.createNextHopPointer(lbGroupKey);
+ int index = 0;
+ List<ActionInfo> actionInfos = new ArrayList<>();
+ for (AdjacencyResult adjResult : adjacencyResults) {
+ String nextHopIp = adjResult.getNextHopIp();
+ java.util.Optional<Long> optionalLabel = FibUtil.getLabelForNextHop(vrfEntry, nextHopIp);
+ if (!optionalLabel.isPresent()) {
+ LOG.warn("NextHopIp {} not found in vrfEntry {}", nextHopIp, vrfEntry);
+ continue;
+ }
+ long label = optionalLabel.get();
+
+ actionInfos.add(new ActionRegLoad(index, FibConstants.NXM_REG_MAPPING.get(index++), 0,
+ 31, label));
+ }
+ List<InstructionInfo> instructions = new ArrayList<>();
+ actionInfos.add(new ActionGroup(index, groupId));
+ instructions.add(new InstructionApplyActions(actionInfos));
+ makeConnectedRoute(remoteDpnId, vpnId, vrfEntry, rd, instructions, NwConstants.ADD_FLOW, tx);
+ }
}