Ethernet VPN (EVPN_RT5) Enhancement to SNAT_HA 31/53131/5
authorkarthikeyan <karthikeyan.k@altencalsoftlabs.com>
Fri, 10 Mar 2017 11:32:41 +0000 (17:02 +0530)
committerKarthikeyan Krishnan <karthikeyan.k@altencalsoftlabs.com>
Tue, 21 Mar 2017 11:31:07 +0000 (11:31 +0000)
This code review (4th Review) is part of EVPN_RT5 enhancement to NAT
Feature.

This code changes is responsible for SNAT HA during NAPT Switch
down/restart scenario

1) Remove all the SNAT flows from old NAPT switch

2) Install all the SNAT flows on newly elected NAPT switch

Note: This review is dependent on below review
https://git.opendaylight.org/gerrit/#/c/51338/

Change-Id: I4201096772af11b111f7387bb1bfce1535ee0ca5
Signed-off-by: karthikeyan <karthikeyan.k@altencalsoftlabs.com>
vpnservice/natservice/natservice-impl/src/main/java/org/opendaylight/netvirt/natservice/internal/EvpnNaptSwitchHA.java [new file with mode: 0644]
vpnservice/natservice/natservice-impl/src/main/java/org/opendaylight/netvirt/natservice/internal/NaptSwitchHA.java
vpnservice/natservice/natservice-impl/src/main/java/org/opendaylight/netvirt/natservice/internal/NatTunnelInterfaceStateListener.java
vpnservice/natservice/natservice-impl/src/main/resources/org/opendaylight/blueprint/natservice.xml

diff --git a/vpnservice/natservice/natservice-impl/src/main/java/org/opendaylight/netvirt/natservice/internal/EvpnNaptSwitchHA.java b/vpnservice/natservice/natservice-impl/src/main/java/org/opendaylight/netvirt/natservice/internal/EvpnNaptSwitchHA.java
new file mode 100644 (file)
index 0000000..91cf540
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * 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 org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.genius.mdsalutil.FlowEntity;
+import org.opendaylight.genius.mdsalutil.NwConstants;
+import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class EvpnNaptSwitchHA {
+
+    private static final Logger LOG = LoggerFactory.getLogger(EvpnNaptSwitchHA.class);
+    private final DataBroker dataBroker;
+    private final IMdsalApiManager mdsalManager;
+    private final IdManagerService idManager;
+    private final EvpnSnatFlowProgrammer evpnSnatFlowProgrammer;
+
+    public EvpnNaptSwitchHA(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
+                        final EvpnSnatFlowProgrammer evpnSnatFlowProgrammer,
+                        final IdManagerService idManager) {
+        this.dataBroker = dataBroker;
+        this.mdsalManager = mdsalManager;
+        this.evpnSnatFlowProgrammer = evpnSnatFlowProgrammer;
+        this.idManager = idManager;
+    }
+
+    public void evpnRemoveSnatFlowsInOldNaptSwitch(String routerName, long routerId, String vpnName,
+                                                   BigInteger naptSwitch) {
+        //Handling VXLAN Provider type flow removal from old NAPT switch
+        Long vpnId = NatUtil.getVpnId(dataBroker, routerId);
+        if (vpnId == null) {
+            LOG.error("NAT Service: Unable to retrieved vpnId for routerId {}", routerId);
+            return;
+        }
+        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 {} ", 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;
+        }
+        //Remove the L3_GW_MAC_TABLE which forwards the packet to Inbound NAPT Table (table19->44)
+        NatEvpnUtil.removeL3GwMacTableEntry(naptSwitch, vpnId, gwMacAddress, mdsalManager);
+
+        //Remove the PDNAT_TABLE which forwards the packet to Inbound NAPT Table (table25->44)
+        evpnSnatFlowProgrammer.removePreDnatToSnatTableEntry(naptSwitch);
+
+        //Remove the PSNAT_TABLE which forwards the packet to Outbound NAPT Table (table26->46)
+        String flowRef = getFlowRefSnat(naptSwitch, NwConstants.PSNAT_TABLE, routerName);
+        FlowEntity flowEntity = NatUtil.buildFlowEntity(naptSwitch, NwConstants.PSNAT_TABLE, flowRef);
+        LOG.info("NAT Service: Remove the flow (table26->46) in table {} for the old napt switch with the DPN ID "
+                + "{} and router ID {}", NwConstants.PSNAT_TABLE, naptSwitch, routerId);
+        mdsalManager.removeFlow(flowEntity);
+
+        //Remove the Terminating Service table entry which forwards the packet to Inbound NAPT Table (table36->44)
+        LOG.info("NAT Service: Remove the flow (table36->44) in table {} for the old napt switch with the DPN ID "
+                + "{} and router ID {}", NwConstants.INTERNAL_TUNNEL_TABLE, naptSwitch, routerId);
+        evpnSnatFlowProgrammer.removeTunnelTableEntry(naptSwitch, l3Vni);
+
+        //Remove the INTERNAL_TUNNEL_TABLE entry which forwards the packet to Outbound NAPT Table (table36->46)
+        long tunnelId = NatEvpnUtil.getTunnelIdForRouter(idManager, dataBroker, routerName, routerId);
+
+        String tsFlowRef = getFlowRefTs(naptSwitch, NwConstants.INTERNAL_TUNNEL_TABLE, tunnelId);
+        FlowEntity tsNatFlowEntity = NatUtil.buildFlowEntity(naptSwitch, NwConstants.INTERNAL_TUNNEL_TABLE, tsFlowRef);
+        LOG.info("NAT Service : Remove the flow in the {} for the active switch with the DPN ID {} and router ID {}",
+                NwConstants.INTERNAL_TUNNEL_TABLE, naptSwitch, routerId);
+        mdsalManager.removeFlow(tsNatFlowEntity);
+
+    }
+
+    private String getFlowRefTs(BigInteger dpnId, short tableId, long routerID) {
+        return NatConstants.NAPT_FLOWID_PREFIX + dpnId + NatConstants.FLOWID_SEPARATOR + tableId + NatConstants
+                .FLOWID_SEPARATOR + routerID;
+    }
+
+    private String getFlowRefSnat(BigInteger dpnId, short tableId, String routerID) {
+        return NatConstants.SNAT_FLOWID_PREFIX + dpnId + NatConstants.FLOWID_SEPARATOR + tableId + NatConstants
+                .FLOWID_SEPARATOR + routerID;
+    }
+}
index c90bd7227b40a9dbc5cc16b16e4a55318352d28b..7e7609ed30ca513d77e45eb37bfa02014ca322cd 100644 (file)
@@ -59,6 +59,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev15033
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
 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.ext.routers.Routers;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
@@ -90,6 +91,7 @@ public class NaptSwitchHA {
     private final IFibManager fibManager;
     private List<String> externalIpsCache;
     private HashMap<String, Long> externalIpsLabel;
+    private final EvpnNaptSwitchHA evpnNaptSwitchHA;
 
     public NaptSwitchHA(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
                         final ExternalRoutersListener externalRouterListener,
@@ -100,7 +102,8 @@ public class NaptSwitchHA {
                         final IBgpManager bgpManager,
                         final VpnRpcService vpnService,
                         final FibRpcService fibService,
-                        final IFibManager fibManager) {
+                        final IFibManager fibManager,
+                        final EvpnNaptSwitchHA evpnNaptSwitchHA) {
         this.dataBroker = dataBroker;
         this.mdsalManager = mdsalManager;
         this.externalRouterListener = externalRouterListener;
@@ -112,6 +115,7 @@ public class NaptSwitchHA {
         this.vpnService = vpnService;
         this.fibService = fibService;
         this.fibManager = fibManager;
+        this.evpnNaptSwitchHA = evpnNaptSwitchHA;
     }
 
     /* This method checks the switch that gone down is a NaptSwitch for a router.
@@ -159,13 +163,30 @@ public class NaptSwitchHA {
             LOG.error("Invalid routerId returned for routerName {}", routerName);
             return;
         }
-        //Remove the Terminating Service table entry which forwards the packet to Outbound NAPT Table
-        String tsFlowRef = externalRouterListener.getFlowRefTs(naptSwitch, NwConstants.INTERNAL_TUNNEL_TABLE, routerId);
-        FlowEntity tsNatFlowEntity = NatUtil.buildFlowEntity(naptSwitch, NwConstants.INTERNAL_TUNNEL_TABLE, tsFlowRef);
+        String vpnName = getExtNetworkVpnName(routerName);
+        if (vpnName == null) {
+            LOG.error("Vpn is not associated to externalN/w of router {}", routerName);
+            return;
+        }
+        ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerName);
+        if (extNwProvType == null) {
+            LOG.error("NAT Service : Unable to retrieve the External Network Provider Type for Router {}",
+                    routerName);
+            return;
+        }
+        if (extNwProvType == ProviderTypes.VXLAN) {
+            evpnNaptSwitchHA.evpnRemoveSnatFlowsInOldNaptSwitch(routerName, routerId, vpnName, naptSwitch);
+        } else {
+            //Remove the Terminating Service table entry which forwards the packet to Outbound NAPT Table
+            String tsFlowRef = externalRouterListener.getFlowRefTs(naptSwitch, NwConstants.INTERNAL_TUNNEL_TABLE,
+                    routerId);
+            FlowEntity tsNatFlowEntity = NatUtil.buildFlowEntity(naptSwitch, NwConstants.INTERNAL_TUNNEL_TABLE,
+                    tsFlowRef);
 
-        LOG.info("Remove the flow in table {} for the old napt switch with the DPN ID {} and router ID {}",
-                NwConstants.INTERNAL_TUNNEL_TABLE, naptSwitch, routerId);
-        mdsalManager.removeFlow(tsNatFlowEntity);
+            LOG.info("Remove the flow in table {} for the old napt switch with the DPN ID {} and router ID {}",
+                    NwConstants.INTERNAL_TUNNEL_TABLE, naptSwitch, routerId);
+            mdsalManager.removeFlow(tsNatFlowEntity);
+        }
         //Remove the Outbound flow entry which forwards the packet to Outbound NAPT Table
         String outboundNatFlowRef = externalRouterListener.getFlowRefOutbound(naptSwitch,
             NwConstants.OUTBOUND_NAPT_TABLE, routerId);
@@ -221,36 +242,30 @@ public class NaptSwitchHA {
         }
 
         //Remove Fib entries,tables 20->44 ,36-> 44
-        String vpnName = getExtNetworkVpnName(routerName);
-        if (vpnName == null) {
-            LOG.debug("Vpn is not associated to externalN/w of router {}", routerName);
+        if (externalIpsLabel != null && !externalIpsLabel.isEmpty()) {
+            for (String externalIp : externalIpsLabel.keySet()) {
+                Long label = externalIpsLabel.get(externalIp);
+                externalRouterListener.delFibTsAndReverseTraffic(naptSwitch, routerId, externalIp, vpnName, label);
+                LOG.debug("Successfully removed fib entries in old naptswitch {} for router {} and "
+                        + "externalIps {} label {}", naptSwitch, routerId, externalIp, label);
+            }
         } else {
-            if (externalIpsLabel != null && !externalIpsLabel.isEmpty()) {
-                for (String externalIp : externalIpsLabel.keySet()) {
-                    Long label = externalIpsLabel.get(externalIp);
-                    externalRouterListener.delFibTsAndReverseTraffic(naptSwitch, routerId, externalIp, vpnName, label);
-                    LOG.debug("Successfully removed fib entries in old naptswitch {} for router {} and "
-                        + "externalIps {} label {}",
-                        naptSwitch, routerId, externalIp, label);
-                }
-            } else {
-                List<String> externalIps = NatUtil.getExternalIpsFromRouter(dataBroker, routerName);
-                if (externalIps != null) {
-                    Uuid networkId = NatUtil.getNetworkIdFromRouterName(dataBroker, routerName);
-                    if (networkId != null) {
-                        externalRouterListener.clearFibTsAndReverseTraffic(naptSwitch, routerId, networkId,
+            List<String> externalIps = NatUtil.getExternalIpsFromRouter(dataBroker, routerName);
+            if (externalIps != null) {
+                Uuid networkId = NatUtil.getNetworkIdFromRouterName(dataBroker, routerName);
+                if (networkId != null) {
+                    externalRouterListener.clearFibTsAndReverseTraffic(naptSwitch, routerId, networkId,
                             externalIps, null);
-                        LOG.debug("Successfully removed fib entries in old naptswitch {} for "
-                            + "router {} with networkId {} and externalIps {}",
-                            naptSwitch, routerId, networkId, externalIps);
-                    } else {
-                        LOG.debug("External network not associated to router {}", routerId);
-                    }
-                    externalRouterListener.removeNaptFibExternalOutputFlows(routerId, naptSwitch,
-                        extNetworkId, externalIps);
+                    LOG.debug("Successfully removed fib entries in old naptswitch {} for "
+                            + "router {} with networkId {} and externalIps {}", naptSwitch, routerId, networkId,
+                            externalIps);
                 } else {
-                    LOG.debug("ExternalIps not found for router {}", routerName);
+                    LOG.debug("External network not associated to router {}", routerId);
                 }
+                externalRouterListener.removeNaptFibExternalOutputFlows(routerId, naptSwitch, extNetworkId,
+                        externalIps);
+            } else {
+                LOG.debug("ExternalIps not found for router {}", routerName);
             }
         }
 
@@ -884,28 +899,42 @@ public class NaptSwitchHA {
                 LOG.debug("Vpn is not associated to externalN/w of router {}", routerName);
                 return;
             }
-            if (externalIpLabel == null || externalIpLabel.size() == 0) {
-                LOG.debug("ExternalIpLabel map is empty for router {}", routerName);
-                return;
-            }
             BigInteger naptSwitch = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
             if (naptSwitch == null || naptSwitch.equals(BigInteger.ZERO)) {
                 LOG.debug("No naptSwitch is selected for router {}", routerName);
                 return;
             }
-            Long label;
-            for (String externalIp : removedExternalIps) {
-                if (externalIpLabel.containsKey(externalIp)) {
-                    label = externalIpLabel.get(externalIp);
-                    LOG.debug("Label {} for ExternalIp {} for router {}", label, externalIp, routerName);
-                } else {
-                    LOG.debug("Label for ExternalIp {} is not found for router {}", externalIp, routerName);
-                    continue;
+            ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker,routerName);
+            if (extNwProvType == null) {
+                return;
+            }
+            if (extNwProvType == ProviderTypes.VXLAN) {
+                for (String externalIp : removedExternalIps) {
+                    externalRouterListener.clearBgpRoutes(externalIp, vpnName);
+                    externalRouterListener.delFibTsAndReverseTraffic(naptSwitch, routerId, externalIp, vpnName,
+                            NatConstants.DEFAULT_LABEL_VALUE);
+                    LOG.debug("NAT Service: Successfully removed fib entry for externalIp {} for routerId {} "
+                                    + "on NAPT switch {} ", externalIp, routerId, naptSwitch);
+                }
+            } else {
+                if (externalIpLabel == null || externalIpLabel.size() == 0) {
+                    LOG.debug("ExternalIpLabel map is empty for router {}", routerName);
+                    return;
+                }
+                Long label;
+                for (String externalIp : removedExternalIps) {
+                    if (externalIpLabel.containsKey(externalIp)) {
+                        label = externalIpLabel.get(externalIp);
+                        LOG.debug("Label {} for ExternalIp {} for router {}", label, externalIp, routerName);
+                    } else {
+                        LOG.debug("Label for ExternalIp {} is not found for router {}", externalIp, routerName);
+                        continue;
+                    }
+                    externalRouterListener.clearBgpRoutes(externalIp, vpnName);
+                    externalRouterListener.delFibTsAndReverseTraffic(naptSwitch, routerId, externalIp, vpnName, label);
+                    LOG.debug("Successfully removed fib entries in switch {} for router {} and externalIps {}",
+                            naptSwitch, routerId, externalIp);
                 }
-                externalRouterListener.clearBgpRoutes(externalIp, vpnName);
-                externalRouterListener.delFibTsAndReverseTraffic(naptSwitch, routerId, externalIp, vpnName, label);
-                LOG.debug("Successfully removed fib entries in switch {} for router {} and externalIps {}",
-                    naptSwitch, routerId, externalIp);
             }
         } else {
             LOG.debug("No external IP found for router {}", routerId);
index 4dc97bde88a7f7f0041c1cace522ec7f8b86efa9..969e4428ffed89a44159bd6534788b495ef62765 100644 (file)
@@ -19,6 +19,7 @@ import java.util.HashMap;
 import java.util.List;
 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.datastoreutils.AsyncDataTreeChangeListenerBase;
 import org.opendaylight.genius.mdsalutil.BucketInfo;
@@ -48,6 +49,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.R
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.RemoveFibEntryInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpn.routers.DpnRoutersList;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpn.routers.dpn.routers.list.RoutersList;
+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.floating.ip.info.RouterPorts;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.Ports;
@@ -187,7 +189,15 @@ public class NatTunnelInterfaceStateListener
             return;
         }
         externalIpCache = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
-        externalIpLabel = NatUtil.getExternalIpsLabelForRouter(dataBroker, routerId);
+        ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker,routerName);
+        if (extNwProvType == null) {
+            return;
+        }
+        if (extNwProvType == ProviderTypes.VXLAN) {
+            externalIpLabel = null;
+        } else {
+            externalIpLabel = NatUtil.getExternalIpsLabelForRouter(dataBroker, routerId);
+        }
         try {
             final String externalVpnName = NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
             if (externalVpnName == null) {
@@ -591,20 +601,45 @@ public class NatTunnelInterfaceStateListener
         FIB manager.
         */
         String rd = NatUtil.getVpnRd(dataBroker, externalVpnName);
+        ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker,routerName);
+        if (extNwProvType == null) {
+            return false;
+        }
+        String gwMacAddress = null;
+        long l3Vni = 0;
+        WriteTransaction writeTx = null;
+        if (extNwProvType == ProviderTypes.VXLAN) {
+            // Get the External Gateway MAC Address which is Router gateway MAC address for SNAT
+            gwMacAddress = NatUtil.getExtGwMacAddFromRouterId(dataBroker, routerId);
+            //get l3Vni value for external VPN
+            l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
+            //Create writeTx Object
+            writeTx = dataBroker.newWriteOnlyTransaction();
+        }
         if (externalIps != null) {
             for (final String externalIp : externalIps) {
-                Long label = externalRouterListner.checkExternalIpLabel(routerId,
-                    externalIp);
-                if (label == null || label == NatConstants.INVALID_ID) {
-                    LOG.debug("NAT Service : SNAT -> Unable to advertise to the DC GW since label is invalid");
-                    return false;
-                }
-
-                LOG.debug("NAT Service : SNAT -> Advertise the route to the externalIp {} having nextHopIp {}",
-                    externalIp, nextHopIp);
-                NatUtil.addPrefixToBGP(dataBroker, bgpManager, fibManager, externalVpnName, rd, externalIp,
-                    nextHopIp, label, LOG, RouteOrigin.STATIC, srcDpnId);
+                long serviceId = 0;
+                if (extNwProvType == ProviderTypes.VXLAN) {
+                    LOG.debug("NAT Service : SNAT -> Advertise the route to the externalIp {} having nextHopIp {}",
+                            externalIp, nextHopIp);
+                    NatEvpnUtil.addRoutesForVxLanProvType(dataBroker, bgpManager, fibManager, externalVpnName, rd,
+                            externalIp, nextHopIp, l3Vni, tunnelName, gwMacAddress, writeTx, RouteOrigin.STATIC,
+                            srcDpnId);
+                    serviceId = l3Vni;
+                } else {
+                    Long label = externalRouterListner.checkExternalIpLabel(routerId,
+                            externalIp);
+                    if (label == null || label == NatConstants.INVALID_ID) {
+                        LOG.debug("NAT Service : SNAT -> Unable to advertise to the DC GW since label is invalid");
+                        return false;
+                    }
 
+                    LOG.debug("NAT Service : SNAT -> Advertise the route to the externalIp {} having nextHopIp {}",
+                            externalIp, nextHopIp);
+                    NatUtil.addPrefixToBGP(dataBroker, bgpManager, fibManager, externalVpnName, rd, externalIp,
+                            nextHopIp, label, LOG, RouteOrigin.STATIC, srcDpnId);
+                    serviceId = label;
+                }
                 LOG.debug("NAT Service : SNAT -> Install custom FIB routes "
                     + "(Table 21 -> Push MPLS label to Tunnel port");
                 List<Instruction> customInstructions = new ArrayList<>();
@@ -612,7 +647,7 @@ public class NatTunnelInterfaceStateListener
                 CreateFibEntryInput input =
                     new CreateFibEntryInputBuilder().setVpnName(externalVpnName).setSourceDpid(srcDpnId)
                         .setInstruction(customInstructions).setIpAddress(externalIp + "/32")
-                        .setServiceId(label).setInstruction(customInstructions).build();
+                        .setServiceId(serviceId).setInstruction(customInstructions).build();
                 Future<RpcResult<Void>> future = fibRpcService.createFibEntry(input);
                 ListenableFuture<RpcResult<Void>> listenableFuture = JdkFutureAdapters.listenInPoolThread(future);
 
@@ -636,6 +671,9 @@ public class NatTunnelInterfaceStateListener
                     }
                 });
             }
+            if (writeTx != null) {
+                writeTx.submit();
+            }
         }
         return true;
     }
@@ -653,8 +691,6 @@ public class NatTunnelInterfaceStateListener
             return;
         }
         RouterPorts routerPorts = optRouterPorts.get();
-        List<Ports> interfaces = routerPorts.getPorts();
-
         Uuid extNwId = routerPorts.getExternalNetworkId();
         final String vpnName = NatUtil.getAssociatedVPN(dataBroker, extNwId, LOG);
         if (vpnName == null) {
@@ -664,6 +700,23 @@ public class NatTunnelInterfaceStateListener
         }
 
         String rd = NatUtil.getVpnRd(dataBroker, vpnName);
+        long routerId = NatUtil.getVpnId(dataBroker, routerName);
+        ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker,routerName);
+        if (extNwProvType == null) {
+            return;
+        }
+        String gwMacAddress = null;
+        long l3Vni = 0;
+        WriteTransaction writeTx = null;
+        if (extNwProvType == ProviderTypes.VXLAN) {
+            // Get the External Gateway MAC Address which is Router gateway MAC address for SNAT
+            gwMacAddress = NatUtil.getExtGwMacAddFromRouterId(dataBroker, routerId);
+            //get l3Vni value for external VPN
+            l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
+            //Create writeTx Object
+            writeTx = dataBroker.newWriteOnlyTransaction();
+        }
+        List<Ports> interfaces = routerPorts.getPorts();
         for (Ports port : interfaces) {
             //Get the DPN on which this interface resides
             final String interfaceName = port.getPortName();
@@ -686,20 +739,33 @@ public class NatTunnelInterfaceStateListener
                 LOG.debug("NAT Service : DNAT -> Advertising the FIB route to the floating IP {} configured "
                     + "for the port: {}",
                     externalIp, interfaceName);
-                long label = floatingIPListener.getOperationalIpMapping(routerName, interfaceName, internalIp);
-                if (label == NatConstants.INVALID_ID) {
-                    LOG.debug("NAT Service : DNAT -> Unable to advertise to the DC GW since label is invalid");
-                    return;
+                long serviceId = 0;
+                if (extNwProvType == ProviderTypes.VXLAN) {
+                    LOG.debug("NAT Service : DNAT -> Advertise the route to the externalIp {} having nextHopIp {}",
+                            externalIp, nextHopIp);
+                    NatEvpnUtil.addRoutesForVxLanProvType(dataBroker, bgpManager, fibManager, vpnName, rd,
+                            externalIp, nextHopIp, l3Vni, interfaceName, gwMacAddress, writeTx, RouteOrigin.STATIC,
+                            fipCfgdDpnId);
+                    serviceId = l3Vni;
+                } else {
+                    long label = floatingIPListener.getOperationalIpMapping(routerName, interfaceName, internalIp);
+                    if (label == NatConstants.INVALID_ID) {
+                        LOG.debug("NAT Service : DNAT -> Unable to advertise to the DC GW since label is invalid");
+                        return;
+                    }
+                    LOG.debug("NAT Service : DNAT -> Advertise the route to the externalIp {} having nextHopIp {}",
+                            externalIp, nextHopIp);
+                    NatUtil.addPrefixToBGP(dataBroker, bgpManager, fibManager, vpnName, rd,
+                            externalIp + "/32", nextHopIp, label, LOG, RouteOrigin.STATIC, fipCfgdDpnId);
+                    serviceId = label;
                 }
-                NatUtil.addPrefixToBGP(dataBroker, bgpManager, fibManager, vpnName, rd,
-                    externalIp + "/32", nextHopIp, label, LOG, RouteOrigin.STATIC, fipCfgdDpnId);
-
                 //Install custom FIB routes (Table 21 -> Push MPLS label to Tunnel port
                 List<Instruction> customInstructions = new ArrayList<>();
                 customInstructions.add(new InstructionGotoTable(NwConstants.PDNAT_TABLE).buildInstruction(0));
                 CreateFibEntryInput input = new CreateFibEntryInputBuilder().setVpnName(vpnName)
                     .setSourceDpid(fipCfgdDpnId).setInstruction(customInstructions)
-                    .setIpAddress(externalIp + "/32").setServiceId(label).setInstruction(customInstructions).build();
+                    .setIpAddress(externalIp + "/32").setServiceId(serviceId).setInstruction(customInstructions)
+                        .build();
                 Future<RpcResult<Void>> future = fibRpcService.createFibEntry(input);
                 ListenableFuture<RpcResult<Void>> listenableFuture = JdkFutureAdapters.listenInPoolThread(future);
 
@@ -722,6 +788,9 @@ public class NatTunnelInterfaceStateListener
                     }
                 });
             }
+            if (writeTx != null) {
+                writeTx.submit();
+            }
         }
     }
 
@@ -836,7 +905,6 @@ public class NatTunnelInterfaceStateListener
             return;
         }
         RouterPorts routerPorts = optRouterPorts.get();
-        List<Ports> interfaces = routerPorts.getPorts();
         Uuid extNwId = routerPorts.getExternalNetworkId();
         final String vpnName = NatUtil.getAssociatedVPN(dataBroker, extNwId, LOG);
         if (vpnName == null) {
@@ -845,6 +913,20 @@ public class NatTunnelInterfaceStateListener
             return;
         }
         String rd = NatUtil.getVpnRd(dataBroker, vpnName);
+        ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerName);
+        if (extNwProvType == null) {
+            return;
+        }
+        long l3Vni = 0;
+        if (extNwProvType == ProviderTypes.VXLAN) {
+            //get l3Vni value for external VPN
+            l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
+            if (l3Vni == NatConstants.DEFAULT_L3VNI_VALUE) {
+                LOG.error("NAT Service : Unable to retrieve L3VNI value for RD {}", rd);
+                return;
+            }
+        }
+        List<Ports> interfaces = routerPorts.getPorts();
         for (Ports port : interfaces) {
             //Get the DPN on which this interface resides
             String interfaceName = port.getPortName();
@@ -868,14 +950,20 @@ public class NatTunnelInterfaceStateListener
                     + "configured for the port: {}",
                     externalIp, interfaceName);
                 NatUtil.removePrefixFromBGP(dataBroker, bgpManager, fibManager, rd, externalIp + "/32", vpnName, LOG);
-                long label = floatingIPListener.getOperationalIpMapping(routerName, interfaceName, internalIp);
-                if (label == NatConstants.INVALID_ID) {
-                    LOG.debug("NAT Service : DNAT -> Unable to remove the table 21 entry pushing the "
-                        + "MPLS label to the tunnel since label is invalid");
-                    return;
+                long serviceId = 0;
+                if (extNwProvType == ProviderTypes.VXLAN) {
+                    serviceId = l3Vni;
+                } else {
+                    long label = floatingIPListener.getOperationalIpMapping(routerName, interfaceName, internalIp);
+                    if (label == NatConstants.INVALID_ID) {
+                        LOG.debug("NAT Service : DNAT -> Unable to remove the table 21 entry pushing the "
+                                + "MPLS label to the tunnel since label is invalid");
+                        return;
+                    }
+                    serviceId = label;
                 }
                 RemoveFibEntryInput input = new RemoveFibEntryInputBuilder().setVpnName(vpnName)
-                    .setSourceDpid(fipCfgdDpnId).setIpAddress(externalIp + "/32").setServiceId(label).build();
+                    .setSourceDpid(fipCfgdDpnId).setIpAddress(externalIp + "/32").setServiceId(serviceId).build();
                 Future<RpcResult<Void>> future = fibRpcService.removeFibEntry(input);
                 ListenableFuture<RpcResult<Void>> listenableFuture = JdkFutureAdapters.listenInPoolThread(future);
 
index 24a3cfece674db4c5c5dd96a045b3349053b21d4..690b94f847fa6ef4b73897403766394ca8d9d013 100644 (file)
     <argument ref="vpnRpcService" />
     <argument ref="fibRpcService" />
     <argument ref="fibManager" />
+    <argument ref="evpnNaptSwitchHA" />
   </bean>
 
   <bean id="natNodeEventListener"
     <argument ref="bgpManager" />
     <argument ref="fibManager" />
   </bean>
+
+  <bean id="evpnNaptSwitchHA" class="org.opendaylight.netvirt.natservice.internal.EvpnNaptSwitchHA">
+    <argument ref="dataBroker" />
+    <argument ref="mdsalUtils" />
+    <argument ref="evpnSnatFlowProgrammer" />
+    <argument ref="idManagerService" />
+  </bean>
 </blueprint>