package org.opendaylight.netvirt.natservice.internal;
-import static org.opendaylight.controller.md.sal.binding.api.WriteTransaction.CREATE_MISSING_PARENTS;
import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
-import static org.opendaylight.netvirt.natservice.internal.NatUtil.requireNonNullElse;
-import com.google.common.base.Optional;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.ExecutionException;
-import javax.annotation.Nonnull;
import javax.inject.Inject;
import javax.inject.Singleton;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
import org.opendaylight.genius.infra.Datastore.Configuration;
import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
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.mdsal.common.api.LogicalDatastoreType;
import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
import org.opendaylight.netvirt.fibmanager.api.IFibManager;
import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
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.flow.types.rev131026.instruction.list.InstructionKey;
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.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.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesOp;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesOpBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntryBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.Adjacencies;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.Adjacency;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.AdjacencyKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.vpn._interface.VpnInstanceNames;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
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 EvpnDnatFlowProgrammer {
private static final Logger LOG = LoggerFactory.getLogger(EvpnDnatFlowProgrammer.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 IFibManager fibManager;
private final FibRpcService fibService;
private final IVpnManager vpnManager;
- private final IdManagerService idManager;
+ private final NatOverVxlanUtil natOverVxlanUtil;
@Inject
public EvpnDnatFlowProgrammer(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
final IFibManager fibManager,
final FibRpcService fibService,
final IVpnManager vpnManager,
- final IdManagerService idManager) {
+ final NatOverVxlanUtil natOverVxlanUtil) {
this.dataBroker = dataBroker;
this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
this.mdsalManager = mdsalManager;
this.fibManager = fibManager;
this.fibService = fibService;
this.vpnManager = vpnManager;
- this.idManager = idManager;
+ this.natOverVxlanUtil = natOverVxlanUtil;
}
- public void onAddFloatingIp(final BigInteger dpnId, final String routerName, final long routerId,
+ public void onAddFloatingIp(final Uint64 dpnId, final String routerName, final Uint32 routerId,
final String vpnName,
final String internalIp, final String externalIp, final Uuid networkId,
final String interfaceName,
* (DC-GW is responding back to FIP VM) {DNAT Reverse traffic})
*
*/
- long vpnId = NatUtil.getVpnId(dataBroker, vpnName);
+ Uint32 vpnId = NatUtil.getVpnId(dataBroker, vpnName);
if (vpnId == NatConstants.INVALID_ID) {
LOG.error("onAddFloatingIp : Invalid Vpn Id is found for Vpn Name {}", vpnName);
return;
}
- long l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
+ Uint32 l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
if (l3Vni == NatConstants.DEFAULT_L3VNI_VALUE) {
LOG.debug("onAddFloatingIp : L3VNI value is not configured in Internet VPN {} and RD {} "
+ "Carve-out L3VNI value from OpenDaylight VXLAN VNI Pool and continue with installing "
+ "DNAT flows for FloatingIp {}", vpnName, rd, externalIp);
- l3Vni = NatOverVxlanUtil.getInternetVpnVni(idManager, vpnName, routerId).longValue();
+ l3Vni = natOverVxlanUtil.getInternetVpnVni(vpnName, routerId);
}
FloatingIPListener.updateOperationalDS(dataBroker, routerName, interfaceName, NatConstants.DEFAULT_LABEL_VALUE,
internalIp, externalIp);
floatingIpPortMacAddress, dpnId, networkId);
}), LOG, "Error processing floating IP port with MAC address {}", floatingIpPortMacAddress);
}
- final long finalL3Vni = l3Vni;
+ 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("onAddFloatingIp : Error {} in custom fib routes install process for Floating "
+ "IP Prefix {} on DPN {}", error, externalIp, dpnId);
}
@Override
- public void onSuccess(@Nonnull RpcResult<CreateFibEntryOutput> result) {
+ public void onSuccess(@NonNull RpcResult<CreateFibEntryOutput> result) {
if (result.isSuccessful()) {
ListenableFutures.addErrorLogging(
txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, innerConfTx -> {
LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
if (optionalVpnInterface.isPresent()) {
ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, tx -> {
- for (VpnInstanceNames vpnInstance : requireNonNullElse(optionalVpnInterface.get().getVpnInstanceNames(),
- Collections.<VpnInstanceNames>emptyList())) {
+ for (VpnInstanceNames vpnInstance : optionalVpnInterface.get().nonnullVpnInstanceNames().values()) {
if (!vpnName.equals(vpnInstance.getVpnName())) {
continue;
}
VpnInterfaceOpDataEntryBuilder vpnIfOpDataEntryBuilder = new VpnInterfaceOpDataEntryBuilder();
vpnIfOpDataEntryBuilder.withKey(new VpnInterfaceOpDataEntryKey(interfaceName, vpnName));
- List<Adjacency> adjacencyList =
- adjs != null && adjs.getAdjacency() != null ? adjs.getAdjacency() : new ArrayList<>();
+ Map<AdjacencyKey, Adjacency> keyAdjacencyMap =
+ adjs != null && adjs.getAdjacency() != null ? adjs.getAdjacency()
+ : new HashMap<AdjacencyKey, Adjacency>();
List<Adjacency> adjacencyListToImport = new ArrayList<>();
- for (Adjacency adj : adjacencyList) {
+ for (Adjacency adj : keyAdjacencyMap.values()) {
Subnetmap sn = VpnHelper.getSubnetmapFromItsUuid(dataBroker, adj.getSubnetId());
if (!VpnHelper.isSubnetPartOfVpn(sn, vpnName)) {
continue;
floatingIpInterface);
InstanceIdentifier<VpnInterfaceOpDataEntry> vpnIfIdentifierOpDataEntry =
NatUtil.getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
- tx.put(vpnIfIdentifierOpDataEntry, vpnIfOpDataEntryBuilder.build(), CREATE_MISSING_PARENTS);
+ tx.mergeParentStructurePut(vpnIfIdentifierOpDataEntry, vpnIfOpDataEntryBuilder.build());
break;
}
}), LOG, "onAddFloatingIp : Could not write Interface {}, vpnName {}", interfaceName, vpnName);
}
}
- public void onRemoveFloatingIp(final BigInteger dpnId, final String vpnName, final String externalIp,
+ public void onRemoveFloatingIp(final Uint64 dpnId, final String vpnName, final String externalIp,
final String floatingIpInterface, final String floatingIpPortMacAddress,
- final long routerId, TypedReadWriteTransaction<Configuration> confTx) {
+ final Uint32 routerId) {
/*
* 1) Remove the flow INTERNAL_TUNNEL_TABLE (table=36)-> PDNAT_TABLE (table=25) (SNAT VM on DPN1 is
* responding back to FIP VM on DPN2) {SNAT to DNAT traffic on different Hypervisor}
LOG.error("onRemoveFloatingIp : 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("onRemoveFloatingIp : Invalid Vpn Id is found for Vpn Name {}", vpnName);
return;
}
- long l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
+ Uint32 l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
if (l3Vni == NatConstants.DEFAULT_L3VNI_VALUE) {
LOG.debug("onRemoveFloatingIp : L3VNI value is not configured in Internet VPN {} and RD {} "
+ "Carve-out L3VNI value from OpenDaylight VXLAN VNI Pool and continue with installing "
+ "DNAT flows for FloatingIp {}", vpnName, rd, externalIp);
- l3Vni = NatOverVxlanUtil.getInternetVpnVni(idManager, vpnName, routerId).longValue();
+ l3Vni = natOverVxlanUtil.getInternetVpnVni(vpnName, routerId);
}
String fibExternalIp = NatUtil.validateAndAddNetworkMask(externalIp);
//Remove Prefix from BGP
- NatUtil.removePrefixFromBGP(bgpManager, fibManager, rd, fibExternalIp, vpnName, LOG);
+ NatUtil.removePrefixFromBGP(bgpManager, fibManager, rd, fibExternalIp, vpnName);
//Remove custom FIB routes flow for L3_FIB_TABLE (table=21)-> PDNAT_TABLE (table=25)
RemoveFibEntryInput input = new RemoveFibEntryInputBuilder().setVpnName(vpnName)
.setSourceDpid(dpnId).setIpAddress(fibExternalIp).setServiceId(l3Vni)
.setIpAddressSource(RemoveFibEntryInput.IpAddressSource.FloatingIP).build();
ListenableFuture<RpcResult<RemoveFibEntryOutput>> futureVxlan = fibService.removeFibEntry(input);
- final long finalL3Vni = l3Vni;
+ 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("onRemoveFloatingIp : Error {} in custom fib routes remove process for Floating "
+ "IP Prefix {} on DPN {}", error, externalIp, dpnId);
}
@Override
- public void onSuccess(@Nonnull RpcResult<RemoveFibEntryOutput> result) {
+ public void onSuccess(@NonNull RpcResult<RemoveFibEntryOutput> result) {
if (result.isSuccessful()) {
ListenableFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
innerConfTx -> {
LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
if (optionalVpnInterface.isPresent()) {
ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, tx -> {
- for (VpnInstanceNames vpnInstance : requireNonNullElse(optionalVpnInterface.get().getVpnInstanceNames(),
- Collections.<VpnInstanceNames>emptyList())) {
+ for (VpnInstanceNames vpnInstance : optionalVpnInterface.get().nonnullVpnInstanceNames().values()) {
if (!vpnName.equals(vpnInstance.getVpnName())) {
continue;
}
}
}
- private void makeTunnelTableEntry(BigInteger dpnId, long l3Vni, List<Instruction> customInstructions,
+ @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
+ justification = "https://github.com/spotbugs/spotbugs/issues/811")
+ private void makeTunnelTableEntry(Uint64 dpnId, Uint32 l3Vni, List<Instruction> customInstructions,
TypedWriteTransaction<Configuration> confTx) {
LOG.debug("makeTunnelTableEntry : Create terminating service table {} --> table {} flow on DpnId {} "
+ "with l3Vni {} as matching parameter", NwConstants.INTERNAL_TUNNEL_TABLE, NwConstants.PDNAT_TABLE,
dpnId, l3Vni);
List<MatchInfo> mkMatches = new ArrayList<>();
- mkMatches.add(new MatchTunnelId(BigInteger.valueOf(l3Vni)));
+ mkMatches.add(new MatchTunnelId(Uint64.valueOf(l3Vni)));
+ Map<InstructionKey, Instruction> customInstructionsMap = new HashMap<InstructionKey, Instruction>();
+ int instructionKey = 0;
+ for (Instruction instructionObj : customInstructions) {
+ customInstructionsMap.put(new InstructionKey(++instructionKey), instructionObj);
+ }
Flow terminatingServiceTableFlowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
- NatEvpnUtil.getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, l3Vni, NatConstants.DNAT_FLOW_NAME), 6,
- String.format("%s:%d", "TST Flow Entry ", l3Vni),
- 0, 0, COOKIE_TUNNEL.add(BigInteger.valueOf(l3Vni)), mkMatches, customInstructions);
+ NatEvpnUtil.getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, l3Vni, NatConstants.DNAT_FLOW_NAME),
+ NatConstants.DEFAULT_VPN_INTERNAL_TUNNEL_TABLE_PRIORITY + 1,
+ String.format("%s:%s", "TST Flow Entry ", l3Vni),
+ 0, 0,
+ Uint64.valueOf(COOKIE_TUNNEL.toJava().add(BigInteger.valueOf(l3Vni.longValue()))),
+ mkMatches, customInstructionsMap);
mdsalManager.addFlow(confTx, dpnId, terminatingServiceTableFlowEntity);
LOG.debug("makeTunnelTableEntry : Successfully installed terminating service table flow {} on DpnId {}",
terminatingServiceTableFlowEntity, dpnId);
}
- private void removeTunnelTableEntry(BigInteger dpnId, long l3Vni, TypedReadWriteTransaction<Configuration> confTx)
+ @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
+ justification = "https://github.com/spotbugs/spotbugs/issues/811")
+ private void removeTunnelTableEntry(Uint64 dpnId, Uint32 l3Vni, TypedReadWriteTransaction<Configuration> confTx)
throws ExecutionException, InterruptedException {
LOG.debug("removeTunnelTableEntry : Remove terminating service table {} --> table {} flow on DpnId {} "
+ "with l3Vni {} as matching parameter", NwConstants.INTERNAL_TUNNEL_TABLE, NwConstants.PDNAT_TABLE,
dpnId, l3Vni);
List<MatchInfo> mkMatches = new ArrayList<>();
- 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.DNAT_FLOW_NAME),
- 6, String.format("%s:%d", "TST Flow Entry ", l3Vni), 0, 0,
- COOKIE_TUNNEL.add(BigInteger.valueOf(l3Vni)), mkMatches, null);
+ NatConstants.DEFAULT_VPN_INTERNAL_TUNNEL_TABLE_PRIORITY + 1,
+ 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);