*/
package org.opendaylight.netvirt.fibmanager;
+import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
+
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.ListenableFuture;
-import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Objects;
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.ReadFailedException;
+import org.opendaylight.genius.datastoreutils.listeners.DataTreeEventCallbackRegistrar;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
import org.opendaylight.genius.mdsalutil.ActionInfo;
import org.opendaylight.genius.mdsalutil.InstructionInfo;
import org.opendaylight.genius.mdsalutil.NwConstants;
import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
import org.opendaylight.genius.utils.batching.SubTransaction;
import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
-import org.opendaylight.netvirt.elanmanager.api.IElanService;
import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+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.genius.itm.op.rev160406.TunnelOperStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.SubnetRoute;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroutes.vpn.extra.routes.Routes;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.Uint32;
+import org.opendaylight.yangtools.yang.common.Uint64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class EvpnVrfEntryHandler extends BaseVrfEntryHandler implements IVrfEntryHandler {
+public class EvpnVrfEntryHandler extends BaseVrfEntryHandler {
private static final Logger LOG = LoggerFactory.getLogger(EvpnVrfEntryHandler.class);
- private final DataBroker dataBroker;
+ private final ManagedNewTransactionRunner txRunner;
private final VrfEntryListener vrfEntryListener;
private final BgpRouteVrfEntryHandler bgpRouteVrfEntryHandler;
private final NexthopManager nexthopManager;
private final JobCoordinator jobCoordinator;
- private final IElanService elanManager;
EvpnVrfEntryHandler(DataBroker broker, VrfEntryListener vrfEntryListener,
BgpRouteVrfEntryHandler bgpRouteVrfEntryHandler, NexthopManager nexthopManager,
- JobCoordinator jobCoordinator, IElanService elanManager, FibUtil fibUtil) {
- super(broker, nexthopManager, null, fibUtil);
- this.dataBroker = broker;
+ JobCoordinator jobCoordinator, FibUtil fibUtil,
+ final UpgradeState upgradeState, final DataTreeEventCallbackRegistrar eventCallbacks) {
+ super(broker, nexthopManager, null, fibUtil, upgradeState, eventCallbacks);
+ this.txRunner = new ManagedNewTransactionRunnerImpl(broker);
this.vrfEntryListener = vrfEntryListener;
this.bgpRouteVrfEntryHandler = bgpRouteVrfEntryHandler;
this.nexthopManager = nexthopManager;
this.jobCoordinator = jobCoordinator;
- this.elanManager = elanManager;
}
- @Override
- public void createFlows(InstanceIdentifier<VrfEntry> identifier, VrfEntry vrfEntry, String rd) {
+ void createFlows(InstanceIdentifier<VrfEntry> identifier, VrfEntry vrfEntry, String rd) {
LOG.info("Initiating creation of Evpn Flows");
final VrfTablesKey vrfTableKey = identifier.firstKeyOf(VrfTables.class);
final VpnInstanceOpDataEntry vpnInstance = getFibUtil().getVpnInstanceOpData(
vrfTableKey.getRouteDistinguisher()).get();
- Long vpnId = vpnInstance.getVpnId();
+ Uint32 vpnId = vpnInstance.getVpnId();
Preconditions.checkNotNull(vpnInstance, "Vpn Instance not available " + vrfTableKey.getRouteDistinguisher());
Preconditions.checkNotNull(vpnId, "Vpn Instance with rd " + vpnInstance.getVrfId()
+ " has null vpnId!");
if (RouteOrigin.value(vrfEntry.getOrigin()) == RouteOrigin.CONNECTED) {
- SubnetRoute subnetRoute = vrfEntry.getAugmentation(SubnetRoute.class);
+ SubnetRoute subnetRoute = vrfEntry.augmentation(SubnetRoute.class);
final List<VpnToDpnList> vpnToDpnList = vpnInstance.getVpnToDpnList();
- final long elanTag = subnetRoute.getElantag();
+ final long elanTag = subnetRoute.getElantag().toJava();
LOG.trace("SubnetRoute augmented vrfentry found for rd {} prefix {} with elantag {}",
rd, vrfEntry.getDestPrefix(), elanTag);
if (vpnToDpnList != null) {
jobCoordinator.enqueueJob("FIB-" + rd + "-" + vrfEntry.getDestPrefix(),
- () -> {
- WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
- for (final VpnToDpnList curDpn : vpnToDpnList) {
- if (curDpn.getDpnState() == VpnToDpnList.DpnState.Active) {
- vrfEntryListener.installSubnetRouteInFib(curDpn.getDpnId(), elanTag, rd,
+ () -> Collections.singletonList(
+ txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
+ for (final VpnToDpnList curDpn : vpnToDpnList) {
+ if (curDpn.getDpnState() == VpnToDpnList.DpnState.Active) {
+ vrfEntryListener.installSubnetRouteInFib(curDpn.getDpnId(), elanTag, rd,
vpnId, vrfEntry, tx);
+ }
}
- }
- List<ListenableFuture<Void>> futures = new ArrayList<>();
- futures.add(tx.submit());
- return futures;
- });
+ })));
}
return;
}
- Prefixes localNextHopInfo = getFibUtil().getPrefixToInterface(vpnInstance.getVpnId(), vrfEntry.getDestPrefix());
- List<BigInteger> localDpnId = new ArrayList<>();
+ Prefixes localNextHopInfo = getFibUtil().getPrefixToInterface(vpnInstance.getVpnId(),
+ vrfEntry.getDestPrefix());
+ List<Uint64> localDpnId = new ArrayList<>();
boolean isNatPrefix = false;
if (Prefixes.PrefixCue.Nat.equals(localNextHopInfo.getPrefixCue())) {
LOG.info("NAT Prefix {} with vpnId {} rd {}. Skip local dpn {} FIB processing",
createRemoteEvpnFlows(rd, vrfEntry, vpnInstance, localDpnId, vrfTableKey, isNatPrefix);
}
- @Override
- public void removeFlows(InstanceIdentifier<VrfEntry> identifier, VrfEntry vrfEntry, String rd) {
+ void removeFlows(InstanceIdentifier<VrfEntry> identifier, VrfEntry vrfEntry, String rd) {
final VrfTablesKey vrfTableKey = identifier.firstKeyOf(VrfTables.class);
final VpnInstanceOpDataEntry vpnInstance = getFibUtil().getVpnInstanceOpData(
vrfTableKey.getRouteDistinguisher()).get();
}
VpnNexthop localNextHopInfo = nexthopManager.getVpnNexthop(vpnInstance.getVpnId(),
vrfEntry.getDestPrefix());
- List<BigInteger> localDpnId = checkDeleteLocalEvpnFLows(vpnInstance.getVpnId(), rd, vrfEntry, localNextHopInfo);
+ List<Uint64> localDpnId = checkDeleteLocalEvpnFLows(vpnInstance.getVpnId(),
+ rd, vrfEntry, localNextHopInfo);
deleteRemoteEvpnFlows(rd, vrfEntry, vpnInstance, vrfTableKey, localDpnId);
vrfEntryListener.cleanUpOpDataForFib(vpnInstance.getVpnId(), rd, vrfEntry);
}
- @Override
- public void updateFlows(InstanceIdentifier<VrfEntry> identifier, VrfEntry original, VrfEntry update, String rd) {
- //Not used
- }
-
- private List<BigInteger> createLocalEvpnFlows(long vpnId, String rd, VrfEntry vrfEntry,
+ private List<Uint64> createLocalEvpnFlows(Uint32 vpnId, String rd, VrfEntry vrfEntry,
Prefixes localNextHopInfo) {
- List<BigInteger> returnLocalDpnId = new ArrayList<>();
+ List<Uint64> returnLocalDpnId = new ArrayList<>();
String localNextHopIP = vrfEntry.getDestPrefix();
if (localNextHopInfo == null) {
//Handle extra routes and imported routes
Routes extraRoute = getVpnToExtraroute(vpnId, rd, vrfEntry.getDestPrefix());
- if (extraRoute != null) {
+ if (extraRoute != null && extraRoute.getNexthopIpList() != null) {
for (String nextHopIp : extraRoute.getNexthopIpList()) {
LOG.info("NextHop IP for destination {} is {}", vrfEntry.getDestPrefix(), nextHopIp);
if (nextHopIp != null) {
localNextHopInfo = getFibUtil().getPrefixToInterface(vpnId, nextHopIp + "/32");
if (localNextHopInfo != null) {
localNextHopIP = nextHopIp + "/32";
- BigInteger dpnId = checkCreateLocalEvpnFlows(localNextHopInfo, localNextHopIP, vpnId,
+ Uint64 dpnId = checkCreateLocalEvpnFlows(localNextHopInfo, localNextHopIP, vpnId,
rd, vrfEntry);
returnLocalDpnId.add(dpnId);
}
} else {
LOG.info("Creating local EVPN flows for prefix {} rd {} route-paths {} evi {}.",
vrfEntry.getDestPrefix(), rd, vrfEntry.getRoutePaths(), vrfEntry.getL3vni());
- BigInteger dpnId = checkCreateLocalEvpnFlows(localNextHopInfo, localNextHopIP, vpnId,
+ Uint64 dpnId = checkCreateLocalEvpnFlows(localNextHopInfo, localNextHopIP, vpnId,
rd, vrfEntry);
returnLocalDpnId.add(dpnId);
}
return returnLocalDpnId;
}
- private BigInteger checkCreateLocalEvpnFlows(Prefixes localNextHopInfo, String localNextHopIP,
- final Long vpnId, final String rd,
+ // Allow deprecated TransactionRunner calls for now
+ @SuppressWarnings("ForbidCertainMethod")
+ private Uint64 checkCreateLocalEvpnFlows(Prefixes localNextHopInfo, String localNextHopIP,
+ final Uint32 vpnId, final String rd,
final VrfEntry vrfEntry) {
- final BigInteger dpnId = localNextHopInfo.getDpnId();
- String jobKey = "FIB-" + vpnId.toString() + "-" + dpnId.toString() + "-" + vrfEntry.getDestPrefix();
+ final Uint64 dpnId = localNextHopInfo.getDpnId();
+ String jobKey = FibUtil.getCreateLocalNextHopJobKey(vpnId, dpnId, vrfEntry.getDestPrefix());
final long groupId = nexthopManager.createLocalNextHop(vpnId, dpnId,
localNextHopInfo.getVpnInterfaceName(), localNextHopIP, vrfEntry.getDestPrefix(),
- vrfEntry.getGatewayMacAddress(), jobKey);
+ vrfEntry.getGatewayMacAddress(), /*parentVpnId*/ null);
LOG.debug("LocalNextHopGroup {} created/reused for prefix {} rd {} evi {} route-paths {}", groupId,
vrfEntry.getDestPrefix(), rd, vrfEntry.getL3vni(), vrfEntry.getRoutePaths());
final List<InstructionInfo> instructions = Collections.singletonList(
new InstructionApplyActions(
Collections.singletonList(new ActionGroup(groupId))));
- jobCoordinator.enqueueJob("FIB-" + vpnId.toString() + "-" + dpnId.toString()
- + "-" + vrfEntry.getDestPrefix(),
- () -> {
- WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
- makeConnectedRoute(dpnId, vpnId, vrfEntry, rd, instructions, NwConstants.ADD_FLOW, tx, null);
- List<ListenableFuture<Void>> futures = new ArrayList<>();
- futures.add(tx.submit());
- return futures;
- });
+ jobCoordinator.enqueueJob(jobKey,
+ () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
+ tx -> makeConnectedRoute(dpnId, vpnId, vrfEntry, rd, instructions, NwConstants.ADD_FLOW, tx,
+ null))));
return dpnId;
}
+ // Allow deprecated TransactionRunner calls for now
+ @SuppressWarnings("ForbidCertainMethod")
private void createRemoteEvpnFlows(String rd, VrfEntry vrfEntry, VpnInstanceOpDataEntry vpnInstance,
- List<BigInteger> localDpnId, VrfTablesKey vrfTableKey, boolean isNatPrefix) {
+ List<Uint64> localDpnId, VrfTablesKey vrfTableKey, boolean isNatPrefix) {
LOG.info("Creating remote EVPN flows for prefix {} rd {} route-paths {} evi {}",
vrfEntry.getDestPrefix(), rd, vrfEntry.getRoutePaths(), vrfEntry.getL3vni());
List<VpnToDpnList> vpnToDpnList = vpnInstance.getVpnToDpnList();
if (vpnToDpnList != null) {
jobCoordinator.enqueueJob("FIB" + rd + vrfEntry.getDestPrefix(),
- () -> {
- WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
- List<ListenableFuture<Void>> futures = new ArrayList<>();
+ () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
for (VpnToDpnList vpnDpn : vpnToDpnList) {
if (!localDpnId.contains(vpnDpn.getDpnId())) {
if (vpnDpn.getDpnState() == VpnToDpnList.DpnState.Active) {
createRemoteFibEntry(vpnDpn.getDpnId(), vpnInstance.getVpnId(),
- vrfTableKey, vrfEntry, isNatPrefix, tx);
+ vrfTableKey, vrfEntry, isNatPrefix, tx);
}
}
}
- futures.add(tx.submit());
- return futures;
- });
+ })));
}
}
- private void createRemoteFibEntry(final BigInteger remoteDpnId, final long vpnId, final VrfTablesKey vrfTableKey,
+ private void createRemoteFibEntry(final Uint64 remoteDpnId, final Uint32 vpnId, final VrfTablesKey vrfTableKey,
final VrfEntry vrfEntry, boolean isNatPrefix, WriteTransaction tx) {
String rd = vrfTableKey.getRouteDistinguisher();
for (NexthopManager.AdjacencyResult adjacencyResult : tunnelInterfaceList) {
List<ActionInfo> actionInfos = new ArrayList<>();
- BigInteger tunnelId;
+ Uint64 tunnelId = Uint64.ZERO;
String prefix = adjacencyResult.getPrefix();
Prefixes prefixInfo = getFibUtil().getPrefixToInterface(vpnId, prefix);
String interfaceName = prefixInfo.getVpnInterfaceName();
- if (vrfEntry.getOrigin().equals(RouteOrigin.BGP.getValue()) || isNatPrefix) {
- tunnelId = BigInteger.valueOf(vrfEntry.getL3vni());
- } else if (elanManager.isOpenStackVniSemanticsEnforced()) {
- tunnelId = BigInteger.valueOf(getFibUtil().getVniForVxlanNetwork(prefixInfo.getSubnetId()).get());
+ if (RouteOrigin.BGP.getValue().equals(vrfEntry.getOrigin()) || isNatPrefix) {
+ tunnelId = Uint64.valueOf(vrfEntry.getL3vni().longValue());
+ } else if (FibUtil.isVxlanNetwork(prefixInfo.getNetworkType())) {
+ tunnelId = Uint64.valueOf(prefixInfo.getSegmentationId().longValue());
} else {
- Interface interfaceState = getFibUtil().getInterfaceStateFromOperDS(interfaceName);
- tunnelId = BigInteger.valueOf(interfaceState.getIfIndex());
+ try {
+ StateTunnelList stateTunnelList = getFibUtil().getTunnelState(interfaceName);
+ if (stateTunnelList == null || stateTunnelList.getOperState() != TunnelOperStatus.Up) {
+ LOG.trace("Tunnel is not up for interface {}", interfaceName);
+ return;
+ }
+ tunnelId = Uint64.valueOf(stateTunnelList.getIfIndex().intValue());
+ } catch (ReadFailedException e) {
+ LOG.error("createRemoteFibEntry: error in fetching tunnel state for interface {}",
+ interfaceName, e);
+ continue;
+ }
}
LOG.debug("adding set tunnel id action for label {}", tunnelId);
String macAddress = null;
actionInfos.add(new ActionSetFieldTunnelId(tunnelId));
List<ActionInfo> egressActions =
nexthopManager.getEgressActionsForInterface(adjacencyResult.getInterfaceName(), actionInfos.size(),
- true);
+ true, vpnId, vrfEntry.getDestPrefix());
if (egressActions.isEmpty()) {
LOG.error("Failed to retrieve egress action for prefix {} route-paths {} interface {}."
+ " Aborting remote FIB entry creation..", vrfEntry.getDestPrefix(),
LOG.debug("Successfully added FIB entry for prefix {} in rd {}", vrfEntry.getDestPrefix(), rd);
}
+ // Allow deprecated TransactionRunner calls for now
+ @SuppressWarnings("ForbidCertainMethod")
private void deleteRemoteEvpnFlows(String rd, VrfEntry vrfEntry, VpnInstanceOpDataEntry vpnInstance,
- VrfTablesKey vrfTableKey, List<BigInteger> localDpnIdList) {
+ VrfTablesKey vrfTableKey, List<Uint64> localDpnIdList) {
List<VpnToDpnList> vpnToDpnList = vpnInstance.getVpnToDpnList();
List<SubTransaction> subTxns = new ArrayList<>();
if (vpnToDpnList != null) {
jobCoordinator.enqueueJob("FIB" + rd + vrfEntry.getDestPrefix(),
- () -> {
- WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
+ () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
final Optional<Routes> extraRouteOptional = Optional.absent();
if (localDpnIdList.size() <= 0) {
for (VpnToDpnList curDpn1 : vpnToDpnList) {
if (RouteOrigin.value(vrfEntry.getOrigin()) == RouteOrigin.BGP) {
if (curDpn1.getDpnState() == VpnToDpnList.DpnState.Active) {
- bgpRouteVrfEntryHandler.deleteRemoteRoute(BigInteger.ZERO, curDpn1.getDpnId(),
- vpnInstance.getVpnId(), vrfTableKey, vrfEntry,
- extraRouteOptional, tx, subTxns);
+ bgpRouteVrfEntryHandler.deleteRemoteRoute(Uint64.ZERO,
+ curDpn1.getDpnId(),
+ vpnInstance.getVpnId(), vrfTableKey, vrfEntry,
+ extraRouteOptional, tx, subTxns);
}
} else {
- deleteRemoteRoute(BigInteger.ZERO, curDpn1.getDpnId(),
- vpnInstance.getVpnId(), vrfTableKey, vrfEntry,
- extraRouteOptional, tx);
+ deleteRemoteRoute(Uint64.ZERO, curDpn1.getDpnId(),
+ vpnInstance.getVpnId(), vrfTableKey, vrfEntry,
+ extraRouteOptional, tx);
}
}
} else {
- for (BigInteger localDpnId : localDpnIdList) {
+ for (Uint64 localDpnId : localDpnIdList) {
for (VpnToDpnList curDpn2 : vpnToDpnList) {
- if (!curDpn2.getDpnId().equals(localDpnId)) {
+ if (!Objects.equals(curDpn2.getDpnId(), localDpnId)) {
if (RouteOrigin.value(vrfEntry.getOrigin()) == RouteOrigin.BGP) {
if (curDpn2.getDpnState() == VpnToDpnList.DpnState.Active) {
- bgpRouteVrfEntryHandler.deleteRemoteRoute(localDpnId, curDpn2.getDpnId(),
- vpnInstance.getVpnId(), vrfTableKey, vrfEntry,
- extraRouteOptional, tx, subTxns);
+ bgpRouteVrfEntryHandler.deleteRemoteRoute(localDpnId,
+ curDpn2.getDpnId(),
+ vpnInstance.getVpnId(), vrfTableKey, vrfEntry,
+ extraRouteOptional, tx, subTxns);
}
} else {
deleteRemoteRoute(localDpnId, curDpn2.getDpnId(),
- vpnInstance.getVpnId(), vrfTableKey, vrfEntry,
- extraRouteOptional, tx);
+ vpnInstance.getVpnId(), vrfTableKey, vrfEntry,
+ extraRouteOptional, tx);
}
}
}
}
}
- List<ListenableFuture<Void>> futures = new ArrayList<>();
- futures.add(tx.submit());
- return futures;
- });
+ })));
}
}
- private List<BigInteger> checkDeleteLocalEvpnFLows(long vpnId, String rd, VrfEntry vrfEntry,
+ // Allow deprecated TransactionRunner calls for now
+ @SuppressWarnings("ForbidCertainMethod")
+ private List<Uint64> checkDeleteLocalEvpnFLows(Uint32 vpnId, String rd, VrfEntry vrfEntry,
VpnNexthop localNextHopInfo) {
- List<BigInteger> returnLocalDpnId = new ArrayList<>();
+ List<Uint64> returnLocalDpnId = new ArrayList<>();
if (localNextHopInfo == null) {
//Handle extra routes and imported routes
} else {
- final BigInteger dpnId = localNextHopInfo.getDpnId();
+ final Uint64 dpnId = localNextHopInfo.getDpnId();
jobCoordinator.enqueueJob("FIB-" + rd + "-" + vrfEntry.getDestPrefix(),
- () -> {
- WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
- makeConnectedRoute(dpnId, vpnId, vrfEntry, rd, null, NwConstants.DEL_FLOW, tx, null);
- List<ListenableFuture<Void>> futures = new ArrayList<>();
- futures.add(tx.submit());
- return futures;
- });
+ () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
+ tx -> makeConnectedRoute(dpnId, vpnId, vrfEntry, rd, null, NwConstants.DEL_FLOW, tx,
+ null))));
//TODO: verify below adjacency call need to be optimized (?)
deleteLocalAdjacency(dpnId, vpnId, vrfEntry.getDestPrefix(), vrfEntry.getDestPrefix());
returnLocalDpnId.add(dpnId);