NETVIRT-1630 migrate to md-sal APIs
[netvirt.git] / natservice / impl / src / main / java / org / opendaylight / netvirt / natservice / internal / EvpnSnatFlowProgrammer.java
index 3ee30f9e899db2de139760ba51e6217575f19550..c65acf3bb688fd2a899128ac6a779ab4cdc41108 100644 (file)
@@ -8,38 +8,48 @@
 
 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;
 
@@ -47,34 +57,35 @@ 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
@@ -100,15 +111,15 @@ public class EvpnSnatFlowProgrammer {
             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);
@@ -119,7 +130,8 @@ public class EvpnSnatFlowProgrammer {
          */
         //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<>();
@@ -134,20 +146,19 @@ public class EvpnSnatFlowProgrammer {
                 + "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 {}",
@@ -156,25 +167,24 @@ public class EvpnSnatFlowProgrammer {
                  /* 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
@@ -196,7 +206,7 @@ public class EvpnSnatFlowProgrammer {
             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;
@@ -206,12 +216,12 @@ public class EvpnSnatFlowProgrammer {
                     + "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);
@@ -222,63 +232,70 @@ public class EvpnSnatFlowProgrammer {
                         + "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);
     }