This code review (2nd Review) is part of EVPN_RT5 enhancement to NAT Feature.
This code changes is responsible for below table flow creation and
removal.
1) Install the flow 36->44 (FIP VM on DPN1 is responding back to external fixed IP on DPN2)
{DNAT to SNAT traffic on different Hypervisor}
2) Install the flow 19->44 (FIP VM on DPN1 is responding back to external fixed IP on DPN1 itself)
{DNAT to SNAT traffic on Same Hypervisor}
3) Install the flow 25->44 (If there is no FIP Match on table 25 (PDNAT_TABLE) then default flow to INBOUND_NAPT_TABLE)
Change-Id: Ibb210891fe5dd8d6e18527535a7510dde0eb0273
Signed-off-by: karthikeyan <karthikeyan.k@altencalsoftlabs.com>
--- /dev/null
+/*
+ * Copyright (c) 2017 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.netvirt.natservice.internal;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+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.MatchEthernetType;
+import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId;
+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.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class EvpnSnatFlowProgrammer {
+ private static final Logger LOG = LoggerFactory.getLogger(EvpnSnatFlowProgrammer.class);
+ private final DataBroker dataBroker;
+ private final IMdsalApiManager mdsalManager;
+ private final IBgpManager bgpManager;
+ private final IFibManager fibManager;
+ private static final BigInteger COOKIE_TUNNEL = new BigInteger("9000000", 16);
+
+ public EvpnSnatFlowProgrammer(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
+ final IBgpManager bgpManager,
+ final IFibManager fibManager) {
+ this.dataBroker = dataBroker;
+ this.mdsalManager = mdsalManager;
+ this.bgpManager = bgpManager;
+ this.fibManager = fibManager;
+ }
+
+ 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) {
+ /*
+ * 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
+ * different Hypervisor}
+ *
+ * 2) Install the flow L3_GW_MAC_TABLE (table=19)-> INBOUND_NAPT_TABLE (table=44)
+ * (FIP VM on DPN1 is responding back to external fixed IP on DPN1 itself){DNAT to SNAT traffic on
+ * Same Hypervisor}
+ *
+ * 3) Install the flow PDNAT_TABLE (table=25)-> INBOUND_NAPT_TABLE (table=44)
+ * (If there is no FIP Match on table 25 (PDNAT_TABLE) then default flow to INBOUND_NAPT_TABLE (table=44))
+ *
+ */
+ LOG.info("NAT Service : Handling SNAT Reverse Traffic for External Network {} ", externalIp);
+ // Get the External Gateway MAC Address which is Router gateway MAC address for SNAT
+ String gwMacAddress = NatUtil.getExtGwMacAddFromRouterId(dataBroker, routerId);
+ if (gwMacAddress == null) {
+ LOG.error("NAT Service : Unable to Retrieve External Gateway MAC address from Router ID {}", routerId);
+ return;
+ }
+ //get l3Vni value for external VPN
+ long l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
+ if (l3Vni == NatConstants.DEFAULT_L3VNI_VALUE) {
+ LOG.error("NAT Service : Unable to retrieve L3VNI value for External IP {}", externalIp);
+ return;
+ }
+ /* As of now neither SNAT nor DNAT will use macaddress while advertising to FIB and BGP instead
+ * use only gwMacAddress. Hence default value of macAddress is null
+ */
+ //Inform to BGP
+ NatEvpnUtil.addRoutesForVxLanProvType(dataBroker, bgpManager, fibManager, vpnName, rd, externalIp,
+ nextHopIp, l3Vni, null /*InterfaceName*/, gwMacAddress, writeTx, RouteOrigin.STATIC, dpnId);
+
+ List<Instruction> customInstructions = new ArrayList<>();
+ customInstructions.add(new InstructionGotoTable(tableId).buildInstruction(0));
+ /* 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, l3Vni, customInstructions, tableId);
+ /* 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))
+ */
+ long vpnId = NatUtil.getVpnId(dataBroker, vpnName);
+ if (vpnId == NatConstants.INVALID_ID) {
+ LOG.warn("NAT Service : Invalid Vpn Id is found for Vpn Name {}", vpnName);
+ }
+ NatEvpnUtil.makeL3GwMacTableEntry(dpnId, vpnId, gwMacAddress, customInstructions, mdsalManager);
+
+ /* Install the flow PDNAT_TABLE (table=25)-> INBOUND_NAPT_TABLE (table=44)
+ * If there is no FIP Match on table 25 (PDNAT_TABLE)
+ */
+ List<Instruction> preDnatToSnatInstructions = new ArrayList<>();
+ preDnatToSnatInstructions.add(new InstructionGotoTable(tableId).buildInstruction(0));
+ makePreDnatToSnatTableEntry(dpnId, preDnatToSnatInstructions, tableId);
+
+ }
+
+ public void evpnDelFibTsAndReverseTraffic(final BigInteger dpnId, final long routerId, final String externalIp,
+ final String vpnName) {
+ /*
+ * 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
+ * different Hypervisor}
+ *
+ * 2) Remove the flow L3_GW_MAC_TABLE (table=19)-> INBOUND_NAPT_TABLE (table=44)
+ * (FIP VM on DPN1 is responding back to external fixed IP on DPN1 itself){DNAT to SNAT traffic on
+ * Same Hypervisor}
+ *
+ * 3) Remove the flow PDNAT_TABLE (table=25)-> INBOUND_NAPT_TABLE (table=44)
+ * (If there is no FIP Match on table 25 (PDNAT_TABLE) then default flow to INBOUND_NAPT_TABLE (table=44))
+ *
+ */
+ String rd = NatUtil.getVpnRd(dataBroker, vpnName);
+ if (rd == null) {
+ LOG.error("NAT Service : Could not retrieve RD value from VPN Name {} ", vpnName);
+ return;
+ }
+ long l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
+ if (l3Vni == NatConstants.DEFAULT_L3VNI_VALUE) {
+ LOG.error("NAT Service : Could not retrieve L3VNI value from RD {} in ", rd);
+ return;
+ }
+ String gwMacAddress = NatUtil.getExtGwMacAddFromRouterId(dataBroker, routerId);
+ if (gwMacAddress == null) {
+ LOG.error("NAT Service : Unable to Get External Gateway MAC address for External Router ID {} ", routerId);
+ return;
+ }
+ long vpnId = NatUtil.getVpnId(dataBroker, vpnName);
+ if (vpnId == NatConstants.INVALID_ID) {
+ LOG.warn("NAT Service : Invalid Vpn Id is found for Vpn Name {}", vpnName);
+ }
+ //remove INTERNAL_TUNNEL_TABLE (table=36)-> INBOUND_NAPT_TABLE (table=44) flow
+ removeTunnelTableEntry(dpnId, l3Vni);
+ //remove L3_GW_MAC_TABLE (table=19)-> INBOUND_NAPT_TABLE (table=44) flow
+ removePreDnatToSnatTableEntry(dpnId);
+ //remove PDNAT_TABLE (table=25)-> INBOUND_NAPT_TABLE (table=44) flow
+ NatEvpnUtil.removeL3GwMacTableEntry(dpnId, vpnId, gwMacAddress, mdsalManager);
+ }
+
+ private String getFlowRefPreDnatToSnat(BigInteger dpnId, short tableId, String uniqueId) {
+ return NatConstants.NAPT_FLOWID_PREFIX + dpnId + NwConstants.FLOWID_SEPARATOR + tableId
+ + NwConstants.FLOWID_SEPARATOR + uniqueId;
+ }
+
+ public void makePreDnatToSnatTableEntry(BigInteger naptDpnId, List<Instruction> preDnatToSnatInstructions,
+ short tableId) {
+ LOG.debug("NAT Service : Create Pre-DNAT table {} --> table {} flow on NAPT DpnId {} ", NwConstants.PDNAT_TABLE,
+ tableId, naptDpnId);
+ List<MatchInfo> matches = new ArrayList<>();
+ matches.add(MatchEthernetType.IPV4);
+ String flowRef = getFlowRefPreDnatToSnat(naptDpnId, NwConstants.PDNAT_TABLE, "PreDNATToSNAT");
+ Flow preDnatToSnatTableFlowEntity = MDSALUtil.buildFlowNew(NwConstants.PDNAT_TABLE,flowRef,
+ 5, flowRef, 0, 0, NwConstants.COOKIE_DNAT_TABLE,
+ matches, preDnatToSnatInstructions);
+
+ mdsalManager.installFlow(naptDpnId, preDnatToSnatTableFlowEntity);
+ LOG.debug("NAT Service : Successfully installed Pre-DNAT flow {} on NAPT DpnId {} ",
+ preDnatToSnatTableFlowEntity, naptDpnId);
+ }
+
+ public void removePreDnatToSnatTableEntry(BigInteger naptDpnId) {
+ LOG.debug("NAT Service : Remove Pre-DNAT table {} --> table {} flow on NAPT DpnId {} ", NwConstants.PDNAT_TABLE,
+ NwConstants.INBOUND_NAPT_TABLE, naptDpnId);
+ String flowRef = getFlowRefPreDnatToSnat(naptDpnId, NwConstants.PDNAT_TABLE, "PreDNATToSNAT");
+ Flow preDnatToSnatTableFlowEntity = MDSALUtil.buildFlowNew(NwConstants.PDNAT_TABLE,flowRef,
+ 5, flowRef, 0, 0, NwConstants.COOKIE_DNAT_TABLE, null, null);
+ mdsalManager.removeFlow(naptDpnId, preDnatToSnatTableFlowEntity);
+ LOG.debug("NAT Service : Successfully removed Pre-DNAT flow {} on NAPT DpnId = {}",
+ preDnatToSnatTableFlowEntity, naptDpnId);
+ }
+
+ public void makeTunnelTableEntry(BigInteger dpnId, long l3Vni, List<Instruction> customInstructions,
+ short tableId) {
+ LOG.debug("NAT Service : 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)));
+
+ 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.installFlow(dpnId, terminatingServiceTableFlowEntity);
+ LOG.debug("NAT Service : Successfully installed terminating service table flow {} on DpnId {}",
+ terminatingServiceTableFlowEntity, dpnId);
+ }
+
+ public void removeTunnelTableEntry(BigInteger dpnId, long l3Vni) {
+ LOG.debug("NAT Service : 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)));
+ 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.removeFlow(dpnId, flowEntity);
+ LOG.debug("NAT Service : Successfully removed terminating service table flow {} on DpnId {}", flowEntity,
+ dpnId);
+ }
+}
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.IntextIpPortMap;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.NaptSwitches;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProtocolTypes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.RouterIdName;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.RoutersKey;
private final NaptPacketInHandler naptPacketInHandler;
private final IFibManager fibManager;
private final IVpnManager vpnManager;
+ private final EvpnSnatFlowProgrammer evpnSnatFlowProgrammer;
private static final BigInteger COOKIE_TUNNEL = new BigInteger("9000000", 16);
static final BigInteger COOKIE_VM_LFIB_TABLE = new BigInteger("8000022", 16);
final NaptEventHandler naptEventHandler,
final NaptPacketInHandler naptPacketInHandler,
final IFibManager fibManager,
- final IVpnManager vpnManager) {
+ final IVpnManager vpnManager,
+ final EvpnSnatFlowProgrammer evpnSnatFlowProgrammer) {
super(Routers.class, ExternalRoutersListener.class);
this.dataBroker = dataBroker;
this.mdsalManager = mdsalManager;
this.naptPacketInHandler = naptPacketInHandler;
this.fibManager = fibManager;
this.vpnManager = vpnManager;
+ this.evpnSnatFlowProgrammer = evpnSnatFlowProgrammer;
}
@Override
final IBgpManager bgpManager, final DataBroker dataBroker,
final Logger log) {
LOG.debug("NAT Service : advToBgpAndInstallFibAndTsFlows() entry for DPN ID {}, tableId {}, vpnname {} "
- + "and externalIp {}", dpnId, tableId, vpnName, externalIp);
+ + "and externalIp {}", dpnId, tableId, vpnName, externalIp);
+ String routerName = NatUtil.getRouterName(dataBroker, routerId);
+ if (routerName == null) {
+ LOG.error("NAT Service : Unable to retrieve the Router Name from Router ID {}", routerId);
+ return;
+ }
+ String nextHopIp = NatUtil.getEndpointIpAddressForDPN(dataBroker, dpnId);
+ String rd = NatUtil.getVpnRd(dataBroker, vpnName);
+ if (rd == null || rd.isEmpty()) {
+ LOG.error("NAT Service : Unable to get RD for VPN Name {}", vpnName);
+ return;
+ }
+ ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerName);
+ if (extNwProvType == null) {
+ return;
+ }
+ if (extNwProvType == ProviderTypes.VXLAN) {
+ WriteTransaction writeTx = dataBroker.newWriteOnlyTransaction();
+ evpnSnatFlowProgrammer.evpnAdvToBgpAndInstallFibAndTsFlows(dpnId, tableId, externalIp, vpnName, rd,
+ nextHopIp, writeTx, routerId);
+ return;
+ }
//Generate VPN label for the external IP
GenerateVpnLabelInput labelInput = new GenerateVpnLabelInputBuilder().setVpnName(vpnName)
.setIpPrefix(externalIp).build();
}
} else {
LOG.error("NAT Service : Failed to write label {} for externalIp {} for "
- + "routerId {} in DS",
- label, externalIp, routerId);
+ + "routerId {} in DS", label, externalIp, routerId);
}
-
//Inform BGP
- String rd = NatUtil.getVpnRd(dataBroker, vpnName);
- String nextHopIp = NatUtil.getEndpointIpAddressForDPN(dataBroker, dpnId);
NatUtil.addPrefixToBGP(dataBroker, bgpManager, fibManager, vpnName, rd,
externalIp, nextHopIp, label, log, RouteOrigin.STATIC, dpnId);
protected void delFibTsAndReverseTraffic(final BigInteger dpnId, long routerId, String extIp,
final String vpnName, long tempLabel) {
- LOG.debug("Removing fib entry for externalIp {} in routerId {}", extIp, routerId);
-
+ LOG.debug("NAT Service : Removing fib entry for externalIp {} in routerId {}", extIp, routerId);
+ String routerName = NatUtil.getRouterName(dataBroker,routerId);
+ if (routerName == null) {
+ LOG.error("NAT Service : Could not retrieve Router Name from Router ID {} ", routerId);
+ return;
+ }
+ ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker,routerName);
+ if (extNwProvType == null) {
+ return;
+ }
+ /* Remove the flow table19->44 and table36->44 entries for SNAT reverse traffic flow if the
+ * external network provided type is VxLAN
+ */
+ if (extNwProvType == ProviderTypes.VXLAN) {
+ evpnSnatFlowProgrammer.evpnDelFibTsAndReverseTraffic(dpnId, routerId, extIp, vpnName);
+ return;
+ }
if (tempLabel < 0 || tempLabel == NatConstants.INVALID_ID) {
LOG.error("NAT Service : Label not found for externalIp {} with router id {}", extIp, routerId);
return;
} else {
String errMsg =
String.format("RPC call to remove custom FIB entries on dpn %s for prefix %s "
- + "Failed - %s",
- dpnId, externalIp, result.getErrors());
+ + "Failed - %s", dpnId, externalIp, result.getErrors());
LOG.error(errMsg);
return Futures.immediateFailedFuture(new RuntimeException(errMsg));
}
}
private void delFibTsAndReverseTraffic(final BigInteger dpnId, long routerId, String extIp, final String vpnName) {
- LOG.debug("Removing fib entry for externalIp {} in routerId {}", extIp, routerId);
+ LOG.debug("NAT Service : Removing fib entry for externalIp {} in routerId {}", extIp, routerId);
+ String routerName = NatUtil.getRouterName(dataBroker,routerId);
+ if (routerName == null) {
+ LOG.error("NAT Service : Could not retrieve Router Name from Router ID {} ", routerId);
+ return;
+ }
+ ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker,routerName);
+ if (extNwProvType == null) {
+ return;
+ }
+ /* Remove the flow table19->44 and table36->44 entries for SNAT reverse traffic flow if the
+ * external network provided type is VxLAN
+ */
+ if (extNwProvType == ProviderTypes.VXLAN) {
+ evpnSnatFlowProgrammer.evpnDelFibTsAndReverseTraffic(dpnId, routerId, extIp, vpnName);
+ return;
+ }
//Get IPMaps from the DB for the router ID
List<IpMap> dbIpMaps = NaptManager.getIpMapList(dataBroker, routerId);
if (dbIpMaps == null || dbIpMaps.isEmpty()) {
public static final int DEFAULT_TS_FLOW_PRIORITY = 10;
public static final short DEFAULT_PREFIX = 32;
public static final long DEFAULT_L3VNI_VALUE = 0;
+ public static final int DEFAULT_LABEL_VALUE = 0;
+ public static final String DNAT_FLOW_NAME = "DNAT";
// Flow Actions
public static final int ADD_FLOW = 0;
package org.opendaylight.netvirt.natservice.internal;
import com.google.common.base.Optional;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.genius.interfacemanager.globals.IfmConstants;
+import org.opendaylight.genius.mdsalutil.MDSALUtil;
+import org.opendaylight.genius.mdsalutil.MatchInfo;
+import org.opendaylight.genius.mdsalutil.MetaDataUtil;
+import org.opendaylight.genius.mdsalutil.NwConstants;
+import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.genius.mdsalutil.matches.MatchEthernetDestination;
+import org.opendaylight.genius.mdsalutil.matches.MatchEthernetSource;
+import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
+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.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.AllocateIdInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.slf4j.Logger;
private static boolean isL3VpnOverVxLan(Long l3Vni) {
return (l3Vni != null && l3Vni != 0);
}
+
+ static ProviderTypes getExtNwProvTypeFromRouterName(DataBroker dataBroker, String routerName) {
+ ProviderTypes extNwProviderType = null;
+ Uuid externalNetworkId = NatUtil.getNetworkIdFromRouterName(dataBroker,routerName);
+ if (externalNetworkId == null) {
+ LOG.error("NAT Service : Could not retrieve external network UUID for router {}", routerName);
+ return extNwProviderType;
+ }
+ extNwProviderType = NatUtil.getProviderTypefromNetworkId(dataBroker, externalNetworkId);
+ if (extNwProviderType == null) {
+ LOG.error("NAT Service : Could not retrieve provider type for external network {} ", externalNetworkId);
+ return extNwProviderType;
+ }
+ return extNwProviderType;
+ }
+
+ @SuppressWarnings("checkstyle:IllegalCatch")
+ public static void addRoutesForVxLanProvType(DataBroker broker,
+ IBgpManager bgpManager,
+ IFibManager fibManager,
+ String vpnName,
+ String rd,
+ String prefix,
+ String nextHopIp,
+ long l3Vni,
+ String interfaceName,
+ String gwMacAddress,
+ WriteTransaction writeTx,
+ RouteOrigin origin, BigInteger dpId) {
+ try {
+ LOG.info("NAT Service : ADD: Adding Fib entry rd {} prefix {} nextHop {} l3Vni {}", rd, prefix, nextHopIp,
+ l3Vni);
+ if (nextHopIp == null) {
+ LOG.error("NAT Service : addPrefix failed since nextHopIp cannot be null for prefix {}", prefix);
+ return;
+ }
+ NatUtil.addPrefixToInterface(broker, NatUtil.getVpnId(broker, vpnName), interfaceName, prefix, dpId,
+ /*isNatPrefix*/ true);
+
+ fibManager.addOrUpdateFibEntry(broker, rd, null /*macAddress*/, prefix,
+ Collections.singletonList(nextHopIp), VrfEntry.EncapType.Vxlan, NatConstants.DEFAULT_LABEL_VALUE,
+ l3Vni, gwMacAddress, origin, writeTx);
+ /* Publish to Bgp only if its an INTERNET VPN */
+ if ((rd != null) && (!rd.equalsIgnoreCase(vpnName))) {
+ bgpManager.advertisePrefix(rd, null /*macAddress*/, prefix, Collections.singletonList(nextHopIp),
+ VrfEntry.EncapType.Vxlan, NatConstants.DEFAULT_LABEL_VALUE, l3Vni, gwMacAddress);
+ }
+ LOG.info("NAT Service : ADD: Added Fib entry rd {} prefix {} nextHop {} l3Vni {}", rd, prefix,
+ nextHopIp, l3Vni);
+ } catch (Exception e) {
+ LOG.error("NAT Service : Exception {} in add routes for prefix {}", e, prefix);
+ }
+ }
+
+ static void makeL3GwMacTableEntry(final BigInteger dpnId, final long vpnId, String macAddress,
+ List<Instruction> customInstructions, IMdsalApiManager mdsalManager) {
+ List<MatchInfo> matchInfo = new ArrayList<>();
+ matchInfo.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(vpnId), MetaDataUtil.METADATA_MASK_VRFID));
+ matchInfo.add(new MatchEthernetDestination(new MacAddress(macAddress)));
+ LOG.debug("NAT Service : Create flow table {} -> table {} for External Vpn Id = {} and MacAddress = {} on "
+ + "DpnId = {}", NwConstants.L3_GW_MAC_TABLE, NwConstants.INBOUND_NAPT_TABLE, vpnId, macAddress, dpnId);
+ // Install the flow entry in L3_GW_MAC_TABLE
+ String flowRef = NatUtil.getFlowRef(dpnId, NwConstants.L3_GW_MAC_TABLE, vpnId, macAddress);
+ Flow l3GwMacTableFlowEntity = MDSALUtil.buildFlowNew(NwConstants.L3_GW_MAC_TABLE,
+ flowRef, 21, flowRef, 0, 0, NwConstants.COOKIE_L3_GW_MAC_TABLE, matchInfo, customInstructions);
+
+ mdsalManager.installFlow(dpnId, l3GwMacTableFlowEntity);
+ LOG.debug("NAT Service : Successfully created flow entity {} on DPN = {}", l3GwMacTableFlowEntity, dpnId);
+ }
+
+ static void removeL3GwMacTableEntry(final BigInteger dpnId, final long vpnId, final String macAddress,
+ IMdsalApiManager mdsalManager) {
+ List<MatchInfo> matchInfo = new ArrayList<>();
+ matchInfo.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(vpnId), MetaDataUtil.METADATA_MASK_VRFID));
+ matchInfo.add(new MatchEthernetSource(new MacAddress(macAddress)));
+ LOG.debug("NAT Service : Remove flow table {} -> table {} for External Vpn Id = {} and MacAddress = {} on "
+ + "DpnId = {}", NwConstants.L3_GW_MAC_TABLE, NwConstants.INBOUND_NAPT_TABLE, vpnId, macAddress, dpnId);
+ // Remove the flow entry in L3_GW_MAC_TABLE
+ String flowRef = NatUtil.getFlowRef(dpnId, NwConstants.L3_GW_MAC_TABLE, vpnId, macAddress);
+ Flow l3GwMacTableFlowEntity = MDSALUtil.buildFlowNew(NwConstants.L3_GW_MAC_TABLE,
+ flowRef, 21, flowRef, 0, 0, NwConstants.COOKIE_L3_GW_MAC_TABLE, matchInfo, null);
+
+ mdsalManager.removeFlow(dpnId, l3GwMacTableFlowEntity);
+ LOG.debug("NAT Service : Successfully removed flow entity {} on DPN = {}", l3GwMacTableFlowEntity, dpnId);
+ }
+
+ public static String getFlowRef(BigInteger dpnId, short tableId, long l3Vni, String flowName) {
+ return flowName + NwConstants.FLOWID_SEPARATOR + dpnId + NwConstants.FLOWID_SEPARATOR + tableId + NwConstants
+ .FLOWID_SEPARATOR + l3Vni;
+ }
}
LOG.error("NAT Service : addPrefix prefix {} rd {} failed since nextHopIp cannot be null.", prefix, rd);
return;
}
- addPrefixToInterface(broker, getVpnId(broker, vpnName), prefix, dpId, /*isNatPrefix*/ true);
+ addPrefixToInterface(broker, getVpnId(broker, vpnName), null /*interfaceName*/,prefix, dpId,
+ /*isNatPrefix*/ true);
fibManager.addOrUpdateFibEntry(broker, rd, null /*macAddress*/, prefix,
Collections.singletonList(nextHopIp), VrfEntry.EncapType.Mplsgre, (int)label, 0 /*l3vni*/,
null /*gatewayMacAddress*/, origin, null /*writeTxn*/);
}
}
- static void addPrefixToInterface(DataBroker broker, long vpnId, String ipPrefix, BigInteger dpId,
- boolean isNatPrefix) {
+ static void addPrefixToInterface(DataBroker broker, long vpnId, String interfaceName, String ipPrefix,
+ BigInteger dpId, boolean isNatPrefix) {
InstanceIdentifier<Prefixes> prefixId = InstanceIdentifier.builder(PrefixToInterface.class)
.child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface
.VpnIds.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix
.to._interface.VpnIdsKey(vpnId))
.child(Prefixes.class, new PrefixesKey(ipPrefix)).build();
-
- Prefixes prefix = new PrefixesBuilder().setDpnId(dpId).setIpAddress(ipPrefix).setNatPrefix(isNatPrefix)
- .build();
+ Prefixes prefix = new PrefixesBuilder().setDpnId(dpId).setIpAddress(ipPrefix).setVpnInterfaceName(interfaceName)
+ .setNatPrefix(isNatPrefix).build();
try {
SingleTransactionDataBroker.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, prefixId, prefix);
} catch (TransactionCommitFailedException e) {
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnList;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesList;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalSubnets;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets.Subnets;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets.SubnetsKey;
import org.slf4j.LoggerFactory;
public class RouterDpnChangeListener
- extends AsyncDataTreeChangeListenerBase<DpnVpninterfacesList, RouterDpnChangeListener>
- implements AutoCloseable {
+ extends AsyncDataTreeChangeListenerBase<DpnVpninterfacesList, RouterDpnChangeListener>
+ implements AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(RouterDpnChangeListener.class);
private ListenerRegistration<DataChangeListener> listenerRegistration;
return;
}
externalIpCache = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
- externalIpLabel = NatUtil.getExternalIpsLabelForRouter(dataBroker, routerId);
+ ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerName);
+ if (extNwProvType == null) {
+ return;
+ }
+ //Get the external IP labels other than VXLAN provider type. Since label is not applicable for VXLAN
+ if (extNwProvType == ProviderTypes.VXLAN) {
+ externalIpLabel = null;
+ } else {
+ externalIpLabel = NatUtil.getExternalIpsLabelForRouter(dataBroker, routerId);
+ }
BigInteger naptSwitch = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
if (naptSwitch == null || naptSwitch.equals(BigInteger.ZERO)) {
LOG.debug("No naptSwitch is selected for router {}", routerName);
<argument ref="naptPacketInHandler" />
<argument ref="fibManager" />
<argument ref="vpnManager"/>
+ <argument ref="evpnSnatFlowProgrammer"/>
</bean>
<bean id="externalNetworksChangeListener"
<argument ref="dataBroker"/>
<argument ref="neutronvpnManager" />
</bean>
+
<service ref="natRpcServiceImpl"
interface="org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.OdlNatRpcService"/>
+
+ <bean id="evpnSnatFlowProgrammer" class="org.opendaylight.netvirt.natservice.internal.EvpnSnatFlowProgrammer">
+ <argument ref="dataBroker" />
+ <argument ref="mdsalUtils" />
+ <argument ref="bgpManager" />
+ <argument ref="fibManager" />
+ </bean>
</blueprint>