package org.opendaylight.netvirt.natservice.internal;
+import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
+
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.JdkFutureAdapters;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
-import java.util.concurrent.Future;
-import javax.annotation.Nonnull;
+import java.util.concurrent.ExecutionException;
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.WriteTransaction;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.genius.infra.Datastore.Configuration;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
+import org.opendaylight.genius.infra.TypedReadWriteTransaction;
+import org.opendaylight.genius.infra.TypedWriteTransaction;
import org.opendaylight.genius.mdsalutil.MDSALUtil;
import org.opendaylight.genius.mdsalutil.MatchInfo;
import org.opendaylight.genius.mdsalutil.NwConstants;
import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId;
+import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
+import org.opendaylight.mdsal.binding.api.DataBroker;
import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
import org.opendaylight.netvirt.fibmanager.api.IFibManager;
import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.FibRpcService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.RemoveFibEntryInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.RemoveFibEntryInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.RemoveFibEntryOutput;
import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.Uint32;
+import org.opendaylight.yangtools.yang.common.Uint64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class EvpnSnatFlowProgrammer {
private static final Logger LOG = LoggerFactory.getLogger(EvpnSnatFlowProgrammer.class);
- private static final BigInteger COOKIE_TUNNEL = new BigInteger("9000000", 16);
+ private static final Uint64 COOKIE_TUNNEL = Uint64.valueOf("9000000", 16).intern();
private final DataBroker dataBroker;
+ private final ManagedNewTransactionRunner txRunner;
private final IMdsalApiManager mdsalManager;
private final IBgpManager bgpManager;
private final IFibManager fibManager;
private final FibRpcService fibService;
- private final IdManagerService idManager;
+ private final NatOverVxlanUtil natOverVxlanUtil;
@Inject
public EvpnSnatFlowProgrammer(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
final IBgpManager bgpManager,
final IFibManager fibManager,
final FibRpcService fibService,
- final IdManagerService idManager) {
+ final NatOverVxlanUtil natOverVxlanUtil) {
this.dataBroker = dataBroker;
+ this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
this.mdsalManager = mdsalManager;
this.bgpManager = bgpManager;
this.fibManager = fibManager;
this.fibService = fibService;
- this.idManager = idManager;
+ this.natOverVxlanUtil = natOverVxlanUtil;
}
- public void evpnAdvToBgpAndInstallFibAndTsFlows(final BigInteger dpnId, final short tableId,
- final String externalIp, final String vpnName, final String rd,
- final String nextHopIp, final WriteTransaction writeTx,
- final long routerId, final String routerName,
- WriteTransaction writeFlowInvTx) {
+ public void evpnAdvToBgpAndInstallFibAndTsFlows(final Uint64 dpnId, final short tableId,
+ final String externalIp, final String vpnName, final String rd, final String nextHopIp,
+ final Uint32 routerId, final String routerName, final Uuid extNetworkId,
+ TypedWriteTransaction<Configuration> confTx) {
/*
* 1) Install the flow INTERNAL_TUNNEL_TABLE (table=36)-> INBOUND_NAPT_TABLE (table=44)
* (FIP VM on DPN1 is responding back to external fixed IP on DPN2) {DNAT to SNAT traffic on
return;
}
//get l3Vni value for external VPN
- long l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
+ Uint32 l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
if (l3Vni == NatConstants.DEFAULT_L3VNI_VALUE) {
LOG.debug("evpnAdvToBgpAndInstallFibAndTsFlows : L3VNI value is not configured in Internet VPN {}"
+ " and RD {} Carve-out L3VNI value from OpenDaylight VXLAN VNI Pool and continue with "
+ "installing SNAT flows for External Fixed IP {}", vpnName, rd, externalIp);
- l3Vni = NatOverVxlanUtil.getInternetVpnVni(idManager, vpnName, routerId).longValue();
+ l3Vni = natOverVxlanUtil.getInternetVpnVni(vpnName, routerId);
}
- long vpnId = NatUtil.getVpnId(dataBroker, vpnName);
+ Uint32 vpnId = NatUtil.getVpnId(dataBroker, vpnName);
if (vpnId == NatConstants.INVALID_ID) {
LOG.error("evpnAdvToBgpAndInstallFibAndTsFlows : Invalid Vpn Id is found for Vpn Name {}",
vpnName);
*/
//Inform to BGP
NatEvpnUtil.addRoutesForVxLanProvType(dataBroker, bgpManager, fibManager, vpnName, rd, externalIp,
- nextHopIp, l3Vni, null /*InterfaceName*/, gwMacAddress, writeTx, RouteOrigin.STATIC, dpnId);
+ nextHopIp, l3Vni, null /*InterfaceName*/, gwMacAddress, confTx, RouteOrigin.STATIC,
+ dpnId, extNetworkId);
//Install custom FIB routes - FIB table.
List<Instruction> customInstructions = new ArrayList<>();
+ "NAPT Switch {} with l3Vni {}, ExternalFixedIp {}, ExternalVpnName {} for RouterId {}",
NwConstants.L3_FIB_TABLE, tableId, dpnId, l3Vni, externalIp, vpnName, routerId);
- Future<RpcResult<Void>> future1 = fibService.createFibEntry(input);
- ListenableFuture<RpcResult<Void>> futureVxlan = JdkFutureAdapters.listenInPoolThread(future1);
+ ListenableFuture<RpcResult<CreateFibEntryOutput>> futureVxlan = fibService.createFibEntry(input);
- final long finalL3Vni = l3Vni;
- Futures.addCallback(futureVxlan, new FutureCallback<RpcResult<Void>>() {
+ final Uint32 finalL3Vni = l3Vni;
+ Futures.addCallback(futureVxlan, new FutureCallback<RpcResult<CreateFibEntryOutput>>() {
@Override
- public void onFailure(@Nonnull Throwable error) {
+ public void onFailure(@NonNull Throwable error) {
LOG.error("evpnAdvToBgpAndInstallFibAndTsFlows : Error in custom fib routes install process for "
+ "External Fixed IP {} on DPN {} with l3Vni {}, ExternalVpnName {} for RouterId {}",
externalIp, dpnId, finalL3Vni, vpnName, routerId, error);
}
@Override
- public void onSuccess(@Nonnull RpcResult<Void> result) {
+ public void onSuccess(@NonNull RpcResult<CreateFibEntryOutput> result) {
if (result.isSuccessful()) {
LOG.info("evpnAdvToBgpAndInstallFibAndTsFlows : Successfully installed custom FIB routes for "
+ "External Fixed IP {} on DPN {} with l3Vni {}, ExternalVpnName {} for RouterId {}",
/* Install the flow INTERNAL_TUNNEL_TABLE (table=36)-> INBOUND_NAPT_TABLE (table=44)
* (SNAT to DNAT reverse Traffic: If traffic is Initiated from NAPT to FIP VM on different Hypervisor)
*/
- makeTunnelTableEntry(dpnId, finalL3Vni, customInstructions, tableId, writeFlowInvTx);
+ makeTunnelTableEntry(dpnId, finalL3Vni, customInstructions, tableId, confTx);
/* Install the flow L3_GW_MAC_TABLE (table=19)-> INBOUND_NAPT_TABLE (table=44)
* (SNAT reverse traffic: If the traffic is Initiated from DC-GW to VM (SNAT Reverse traffic))
*/
NatEvpnUtil.makeL3GwMacTableEntry(dpnId, vpnId, gwMacAddress, customInstructions, mdsalManager,
- writeFlowInvTx);
+ confTx);
/* Install the flow PDNAT_TABLE (table=25)-> INBOUND_NAPT_TABLE (table=44)
* If there is no FIP Match on table 25 (PDNAT_TABLE)
*/
- NatUtil.makePreDnatToSnatTableEntry(mdsalManager, dpnId, tableId, writeFlowInvTx);
+ NatUtil.makePreDnatToSnatTableEntry(mdsalManager, dpnId, tableId, confTx);
}
}
}, MoreExecutors.directExecutor());
}
- public void evpnDelFibTsAndReverseTraffic(final BigInteger dpnId, final long routerId, final String externalIp,
- final String vpnName, String extGwMacAddress,
- WriteTransaction removeFlowInvTx) {
+ public void evpnDelFibTsAndReverseTraffic(final Uint64 dpnId, final Uint32 routerId, final String externalIp,
+ final String vpnName, String extGwMacAddress) {
/*
* 1) Remove the flow INTERNAL_TUNNEL_TABLE (table=36)-> INBOUND_NAPT_TABLE (table=44)
* (FIP VM on DPN1 is responding back to external fixed IP on DPN2) {DNAT to SNAT traffic on
LOG.error("evpnDelFibTsAndReverseTraffic : Could not retrieve RD value from VPN Name {}", vpnName);
return;
}
- long vpnId = NatUtil.getVpnId(dataBroker, vpnName);
+ Uint32 vpnId = NatUtil.getVpnId(dataBroker, vpnName);
if (vpnId == NatConstants.INVALID_ID) {
LOG.error("evpnDelFibTsAndReverseTraffic : Invalid Vpn Id is found for Vpn Name {}", vpnName);
return;
+ "External Router ID {} ", routerId);
return;
}
- long l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
+ Uint32 l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
if (l3Vni == NatConstants.DEFAULT_L3VNI_VALUE) {
LOG.debug("evpnDelFibTsAndReverseTraffic : L3VNI value is not configured in Internet VPN {} and RD {} "
+ "Carve-out L3VNI value from OpenDaylight VXLAN VNI Pool and continue with installing "
+ "SNAT flows for External Fixed IP {}", vpnName, rd, externalIp);
- l3Vni = NatOverVxlanUtil.getInternetVpnVni(idManager, vpnName, routerId).longValue();
+ l3Vni = natOverVxlanUtil.getInternetVpnVni(vpnName, routerId);
}
final String externalFixedIp = NatUtil.validateAndAddNetworkMask(externalIp);
+ "NAPT Switch {} with l3Vni {}, ExternalFixedIp {}, ExternalVpnName {} for RouterId {}",
NwConstants.L3_FIB_TABLE, NwConstants.INBOUND_NAPT_TABLE, dpnId, l3Vni, externalIp, vpnName, routerId);
- Future<RpcResult<Void>> future = fibService.removeFibEntry(input);
- ListenableFuture<RpcResult<Void>> futureVxlan = JdkFutureAdapters.listenInPoolThread(future);
- final long finalL3Vni = l3Vni;
- Futures.addCallback(futureVxlan, new FutureCallback<RpcResult<Void>>() {
+ ListenableFuture<RpcResult<RemoveFibEntryOutput>> futureVxlan = fibService.removeFibEntry(input);
+ final Uint32 finalL3Vni = l3Vni;
+ Futures.addCallback(futureVxlan, new FutureCallback<RpcResult<RemoveFibEntryOutput>>() {
@Override
- public void onFailure(@Nonnull Throwable error) {
+ public void onFailure(@NonNull Throwable error) {
LOG.error("evpnDelFibTsAndReverseTraffic : Error in custom fib routes remove process for "
+ "External Fixed IP {} on DPN {} with l3Vni {}, ExternalVpnName {} for RouterId {}",
externalIp, dpnId, finalL3Vni, vpnName, routerId, error);
}
@Override
- public void onSuccess(@Nonnull RpcResult<Void> result) {
+ public void onSuccess(@NonNull RpcResult<RemoveFibEntryOutput> result) {
if (result.isSuccessful()) {
- LOG.info("evpnDelFibTsAndReverseTraffic : Successfully removed custom FIB routes for "
- + "External Fixed IP {} on DPN {} with l3Vni {}, ExternalVpnName {} for "
- + "RouterId {}", externalIp, dpnId, finalL3Vni, vpnName, routerId);
+ ListenableFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
+ innerConfTx -> {
+ LOG.info("evpnDelFibTsAndReverseTraffic : Successfully removed custom FIB routes for "
+ + "External Fixed IP {} on DPN {} with l3Vni {}, ExternalVpnName {} for "
+ + "RouterId {}", externalIp, dpnId, finalL3Vni, vpnName, routerId);
- //remove INTERNAL_TUNNEL_TABLE (table=36)-> INBOUND_NAPT_TABLE (table=44) flow
- removeTunnelTableEntry(dpnId, finalL3Vni, removeFlowInvTx);
- //remove L3_GW_MAC_TABLE (table=19)-> INBOUND_NAPT_TABLE (table=44) flow
- NatUtil.removePreDnatToSnatTableEntry(mdsalManager, dpnId, removeFlowInvTx);
- //remove PDNAT_TABLE (table=25)-> INBOUND_NAPT_TABLE (table=44) flow
- NatEvpnUtil.removeL3GwMacTableEntry(dpnId, vpnId, extGwMacAddress, mdsalManager, removeFlowInvTx);
+ //remove INTERNAL_TUNNEL_TABLE (table=36)-> INBOUND_NAPT_TABLE (table=44) flow
+ removeTunnelTableEntry(dpnId, finalL3Vni, innerConfTx);
+ //remove L3_GW_MAC_TABLE (table=19)-> INBOUND_NAPT_TABLE (table=44) flow
+ NatUtil.removePreDnatToSnatTableEntry(innerConfTx, mdsalManager, dpnId);
+ //remove PDNAT_TABLE (table=25)-> INBOUND_NAPT_TABLE (table=44) flow
+ NatEvpnUtil.removeL3GwMacTableEntry(dpnId, vpnId, extGwMacAddress, mdsalManager,
+ innerConfTx);
+ }), LOG, "Error removing EVPN SNAT table entries");
}
}
}, MoreExecutors.directExecutor());
}
- public void makeTunnelTableEntry(BigInteger dpnId, long l3Vni, List<Instruction> customInstructions,
- short tableId, WriteTransaction writeFlowTx) {
+ public void makeTunnelTableEntry(Uint64 dpnId, Uint32 l3Vni, List<Instruction> customInstructions,
+ short tableId, TypedWriteTransaction<Configuration> confTx) {
LOG.debug("makeTunnelTableEntry : Create terminating service table {} --> table {} flow on NAPT DpnId {} "
+ "with l3Vni {} as matching parameter", NwConstants.INTERNAL_TUNNEL_TABLE, tableId, dpnId, l3Vni);
List<MatchInfo> mkMatches = new ArrayList<>();
- mkMatches.add(new MatchTunnelId(BigInteger.valueOf(l3Vni)));
+ mkMatches.add(new MatchTunnelId(Uint64.valueOf(l3Vni)));
Flow terminatingServiceTableFlowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
- NatEvpnUtil.getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, l3Vni, NatConstants.SNAT_FLOW_NAME), 5,
- String.format("%s:%d", "TST Flow Entry ", l3Vni),
- 0, 0, COOKIE_TUNNEL.add(BigInteger.valueOf(l3Vni)), mkMatches, customInstructions);
- mdsalManager.addFlowToTx(dpnId, terminatingServiceTableFlowEntity, writeFlowTx);
+ NatEvpnUtil.getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, l3Vni, NatConstants.SNAT_FLOW_NAME),
+ NatConstants.DEFAULT_VPN_INTERNAL_TUNNEL_TABLE_PRIORITY,
+ String.format("%s:%s", "TST Flow Entry ", l3Vni),
+ 0, 0, Uint64.valueOf(COOKIE_TUNNEL.toJava().add(BigInteger.valueOf(l3Vni.longValue()))),
+ mkMatches, customInstructions);
+ mdsalManager.addFlow(confTx, dpnId, terminatingServiceTableFlowEntity);
LOG.debug("makeTunnelTableEntry : Successfully installed terminating service table flow {} on DpnId {}",
terminatingServiceTableFlowEntity, dpnId);
}
- public void removeTunnelTableEntry(BigInteger dpnId, long l3Vni, WriteTransaction removeFlowInvTx) {
+ public void removeTunnelTableEntry(Uint64 dpnId, Uint32 l3Vni, TypedReadWriteTransaction<Configuration> confTx)
+ throws ExecutionException, InterruptedException {
LOG.debug("removeTunnelTableEntry : Remove terminating service table {} --> table {} flow on NAPT DpnId {} "
+ "with l3Vni {} as matching parameter", NwConstants.INTERNAL_TUNNEL_TABLE,
NwConstants.INBOUND_NAPT_TABLE, dpnId, l3Vni);
List<MatchInfo> mkMatches = new ArrayList<>();
// Matching metadata
- mkMatches.add(new MatchTunnelId(BigInteger.valueOf(l3Vni)));
+ mkMatches.add(new MatchTunnelId(Uint64.valueOf(l3Vni)));
Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
NatEvpnUtil.getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, l3Vni, NatConstants.SNAT_FLOW_NAME),
- 5, String.format("%s:%d", "TST Flow Entry ", l3Vni), 0, 0,
- COOKIE_TUNNEL.add(BigInteger.valueOf(l3Vni)), mkMatches, null);
- mdsalManager.removeFlowToTx(dpnId, flowEntity, removeFlowInvTx);
+ NatConstants.DEFAULT_VPN_INTERNAL_TUNNEL_TABLE_PRIORITY,
+ String.format("%s:%s", "TST Flow Entry ", l3Vni), 0, 0,
+ Uint64.valueOf(COOKIE_TUNNEL.toJava().add(BigInteger.valueOf(l3Vni.longValue()))), mkMatches, null);
+ mdsalManager.removeFlow(confTx, dpnId, flowEntity);
LOG.debug("removeTunnelTableEntry : Successfully removed terminating service table flow {} on DpnId {}",
flowEntity, dpnId);
}