Remove NatUtil::read()
[netvirt.git] / vpnservice / natservice / natservice-impl / src / main / java / org / opendaylight / netvirt / natservice / internal / VpnFloatingIpHandler.java
index 19110058b1397d2f1561f9ccb860ee49f349423d..962665d234d20dd7890da2a364041b65bae1d949 100644 (file)
@@ -20,9 +20,12 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.Future;
+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.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
 import org.opendaylight.genius.mdsalutil.ActionInfo;
 import org.opendaylight.genius.mdsalutil.MDSALUtil;
 import org.opendaylight.genius.mdsalutil.MatchInfo;
@@ -75,6 +78,7 @@ import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+@Singleton
 public class VpnFloatingIpHandler implements FloatingIPHandler {
     private static final Logger LOG = LoggerFactory.getLogger(VpnFloatingIpHandler.class);
     private final DataBroker dataBroker;
@@ -82,7 +86,6 @@ public class VpnFloatingIpHandler implements FloatingIPHandler {
     private final VpnRpcService vpnService;
     private final IBgpManager bgpManager;
     private final FibRpcService fibService;
-    private final FloatingIPListener floatingIPListener;
     private final IVpnManager vpnManager;
     private final IFibManager fibManager;
     private final OdlArputilService arpUtilService;
@@ -90,15 +93,14 @@ public class VpnFloatingIpHandler implements FloatingIPHandler {
     private final EvpnDnatFlowProgrammer evpnDnatFlowProgrammer;
     private final INeutronVpnManager nvpnManager;
     private final IdManagerService idManager;
+    private static final BigInteger COOKIE_TUNNEL = new BigInteger("9000000", 16);
+    private static final String FLOWID_PREFIX = "NAT.";
 
-    static final BigInteger COOKIE_TUNNEL = new BigInteger("9000000", 16);
-    static final String FLOWID_PREFIX = "NAT.";
-
+    @Inject
     public VpnFloatingIpHandler(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
                                 final VpnRpcService vpnService,
                                 final IBgpManager bgpManager,
                                 final FibRpcService fibService,
-                                final FloatingIPListener floatingIPListener,
                                 final IFibManager fibManager,
                                 final OdlArputilService arputilService,
                                 final IVpnManager vpnManager,
@@ -111,7 +113,6 @@ public class VpnFloatingIpHandler implements FloatingIPHandler {
         this.vpnService = vpnService;
         this.bgpManager = bgpManager;
         this.fibService = fibService;
-        this.floatingIPListener = floatingIPListener;
         this.fibManager = fibManager;
         this.arpUtilService = arputilService;
         this.vpnManager = vpnManager;
@@ -147,6 +148,8 @@ public class VpnFloatingIpHandler implements FloatingIPHandler {
         if (provType == null) {
             return;
         }
+        NatOverVxlanUtil.validateAndCreateVxlanVniPool(dataBroker, nvpnManager, idManager,
+                NatConstants.ODL_VNI_POOL_NAME);
         if (provType == ProviderTypes.VXLAN) {
             Uuid floatingIpInterface = NatEvpnUtil.getFloatingIpInterfaceIdFromFloatingIpId(dataBroker, floatingIpId);
             evpnDnatFlowProgrammer.onAddFloatingIp(dpnId, routerId, vpnName, internalIp, externalIp, networkId,
@@ -156,30 +159,27 @@ public class VpnFloatingIpHandler implements FloatingIPHandler {
             }
             return;
         }
-
-        if (nvpnManager.getEnforceOpenstackSemanticsConfig()) {
-            NatOverVxlanUtil.validateAndCreateVxlanVniPool(dataBroker, nvpnManager,
-                    idManager, NatConstants.ODL_VNI_POOL_NAME);
-        }
-
         GenerateVpnLabelInput labelInput = new GenerateVpnLabelInputBuilder().setVpnName(vpnName)
             .setIpPrefix(externalIp).build();
         Future<RpcResult<GenerateVpnLabelOutput>> labelFuture = vpnService.generateVpnLabel(labelInput);
 
-        ListenableFuture<RpcResult<Void>> future = Futures.transform(JdkFutureAdapters.listenInPoolThread(labelFuture),
-            (AsyncFunction<RpcResult<GenerateVpnLabelOutput>, RpcResult<Void>>) result -> {
+        ListenableFuture<RpcResult<Void>> future = Futures.transformAsync(
+                JdkFutureAdapters.listenInPoolThread(labelFuture),
+                (AsyncFunction<RpcResult<GenerateVpnLabelOutput>, RpcResult<Void>>) result -> {
                 if (result.isSuccessful()) {
                     GenerateVpnLabelOutput output = result.getResult();
                     long label = output.getLabel();
                     LOG.debug("Generated label {} for prefix {}", label, externalIp);
-                    floatingIPListener.updateOperationalDS(routerId, interfaceName, label, internalIp, externalIp);
+                    FloatingIPListener.updateOperationalDS(dataBroker, routerId, interfaceName, label,
+                        internalIp, externalIp);
                     //Inform BGP
                     long l3vni = 0;
-                    if (nvpnManager.getEnforceOpenstackSemanticsConfig()) {
+                    if (elanService.isOpenStackVniSemanticsEnforced()) {
                         l3vni = NatOverVxlanUtil.getInternetVpnVni(idManager, vpnName, l3vni).longValue();
                     }
+                    String fibExternalIp = NatUtil.validateAndAddNetworkMask(externalIp);
                     NatUtil.addPrefixToBGP(dataBroker, bgpManager, fibManager, vpnName, rd, subnetId,
-                            externalIp + "/32", nextHopIp, networkId.getValue(), floatingIpPortMacAddress,
+                            fibExternalIp, nextHopIp, networkId.getValue(), floatingIpPortMacAddress,
                             label, l3vni, LOG, RouteOrigin.STATIC, dpnId);
 
                     List<Instruction> instructions = new ArrayList<>();
@@ -195,10 +195,11 @@ public class VpnFloatingIpHandler implements FloatingIPHandler {
                     customInstructions.add(new InstructionApplyActions(actionInfoFib).buildInstruction(0));
                     customInstructions.add(new InstructionGotoTable(NwConstants.PDNAT_TABLE).buildInstruction(1));
 
-                    makeLFibTableEntry(dpnId, label, NwConstants.PDNAT_TABLE);
+                    makeLFibTableEntry(dpnId, label, floatingIpPortMacAddress, NwConstants.PDNAT_TABLE);
                     CreateFibEntryInput input = new CreateFibEntryInputBuilder().setVpnName(vpnName)
                         .setSourceDpid(dpnId).setInstruction(customInstructions)
-                        .setIpAddress(externalIp + "/32").setServiceId(label)
+                        .setIpAddress(fibExternalIp).setServiceId(label)
+                        .setIpAddressSource(CreateFibEntryInput.IpAddressSource.FloatingIP)
                         .setInstruction(customInstructions).build();
                     //Future<RpcResult<java.lang.Void>> createFibEntry(CreateFibEntryInput input);
                     Future<RpcResult<Void>> future1 = fibService.createFibEntry(input);
@@ -265,7 +266,8 @@ public class VpnFloatingIpHandler implements FloatingIPHandler {
         String floatingIpPortMacAddress = NatUtil.getFloatingIpPortMacFromFloatingIpId(dataBroker, floatingIpId);
         if (floatingIpPortMacAddress != null) {
             WriteTransaction writeTx = dataBroker.newWriteOnlyTransaction();
-            vpnManager.setupSubnetMacIntoVpnInstance(vpnName, subnetId.getValue(), floatingIpPortMacAddress,
+            String networkVpnName =  NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
+            vpnManager.setupSubnetMacIntoVpnInstance(networkVpnName, subnetId.getValue(), floatingIpPortMacAddress,
                     dpnId, writeTx, NwConstants.DEL_FLOW);
             vpnManager.setupArpResponderFlowsToExternalNetworkIps(routerId, Collections.singletonList(externalIp),
                 floatingIpPortMacAddress, dpnId, networkId, writeTx, NwConstants.DEL_FLOW);
@@ -279,7 +281,7 @@ public class VpnFloatingIpHandler implements FloatingIPHandler {
         if (provType == ProviderTypes.VXLAN) {
             Uuid floatingIpInterface = NatEvpnUtil.getFloatingIpInterfaceIdFromFloatingIpId(dataBroker, floatingIpId);
             evpnDnatFlowProgrammer.onRemoveFloatingIp(dpnId, vpnName, externalIp, floatingIpInterface.getValue(),
-                    floatingIpPortMacAddress);
+                    floatingIpPortMacAddress, routerId);
             return;
         }
         cleanupFibEntries(dpnId, vpnName, externalIp, label);
@@ -290,20 +292,34 @@ public class VpnFloatingIpHandler implements FloatingIPHandler {
                                   final long label) {
         //Remove Prefix from BGP
         String rd = NatUtil.getVpnRd(dataBroker, vpnName);
-        NatUtil.removePrefixFromBGP(dataBroker, bgpManager, fibManager, rd, externalIp + "/32", vpnName, LOG);
+        String fibExternalIp = NatUtil.validateAndAddNetworkMask(externalIp);
+        NatUtil.removePrefixFromBGP(dataBroker, bgpManager, fibManager, rd, fibExternalIp, vpnName, LOG);
 
         //Remove custom FIB routes
 
         //Future<RpcResult<java.lang.Void>> removeFibEntry(RemoveFibEntryInput input);
         RemoveFibEntryInput input = new RemoveFibEntryInputBuilder().setVpnName(vpnName)
-            .setSourceDpid(dpnId).setIpAddress(externalIp + "/32").setServiceId(label).build();
+            .setSourceDpid(dpnId).setIpAddress(fibExternalIp).setServiceId(label)
+            .setIpAddressSource(RemoveFibEntryInput.IpAddressSource.FloatingIP).build();
         Future<RpcResult<Void>> future = fibService.removeFibEntry(input);
 
-        ListenableFuture<RpcResult<Void>> labelFuture = Futures.transform(JdkFutureAdapters.listenInPoolThread(future),
-            (AsyncFunction<RpcResult<Void>, RpcResult<Void>>) result -> {
+        ListenableFuture<RpcResult<Void>> labelFuture = Futures.transformAsync(
+                JdkFutureAdapters.listenInPoolThread(future),
+                (AsyncFunction<RpcResult<Void>, RpcResult<Void>>) result -> {
                 //Release label
                 if (result.isSuccessful()) {
-                    removeTunnelTableEntry(dpnId, label);
+                /*  check if any floating IP information is available in vpn-to-dpn-list for given dpn id. If exist any
+                 *  floating IP then do not remove INTERNAL_TUNNEL_TABLE (table=36) -> PDNAT_TABLE (table=25) flow entry
+                 */
+                    Boolean removeTunnelFlow = Boolean.TRUE;
+                    if (elanService.isOpenStackVniSemanticsEnforced()) {
+                        if (NatUtil.isFloatingIpPresentForDpn(dataBroker, dpnId, rd, vpnName, externalIp, false)) {
+                            removeTunnelFlow = Boolean.FALSE;
+                        }
+                    }
+                    if (removeTunnelFlow) {
+                        removeTunnelTableEntry(dpnId, label);
+                    }
                     removeLFibTableEntry(dpnId, label);
                     RemoveVpnLabelInput labelInput = new RemoveVpnLabelInputBuilder()
                         .setVpnName(vpnName).setIpPrefix(externalIp).build();
@@ -363,7 +379,7 @@ public class VpnFloatingIpHandler implements FloatingIPHandler {
         // Increased the 36->25 flow priority. If SNAT is also configured on the same
         // DPN, then the traffic will be hijacked to DNAT and if there are no DNAT match,
         // then handled back to using using flow 25->44(which will be installed as part of SNAT)
-        if (nvpnManager.getEnforceOpenstackSemanticsConfig()) {
+        if (elanService.isOpenStackVniSemanticsEnforced()) {
             mkMatches.add(new MatchTunnelId(NatOverVxlanUtil.getInternetVpnVni(idManager, vpnName, serviceId)));
             flowPriority = 6;
         } else {
@@ -378,7 +394,7 @@ public class VpnFloatingIpHandler implements FloatingIPHandler {
         mdsalManager.installFlow(dpnId, terminatingServiceTableFlowEntity);
     }
 
-    private void makeLFibTableEntry(BigInteger dpId, long serviceId, short tableId) {
+    private void makeLFibTableEntry(BigInteger dpId, long serviceId, String floatingIpPortMacAddress, short tableId) {
         List<MatchInfo> matches = new ArrayList<>();
         matches.add(MatchEthernetType.MPLS_UNICAST);
         matches.add(new MatchMplsLabel(serviceId));
@@ -386,6 +402,7 @@ public class VpnFloatingIpHandler implements FloatingIPHandler {
         List<Instruction> instructions = new ArrayList<>();
         List<ActionInfo> actionsInfos = new ArrayList<>();
         actionsInfos.add(new ActionPopMpls());
+        actionsInfos.add(new ActionSetFieldEthernetDestination(new MacAddress(floatingIpPortMacAddress)));
         Instruction writeInstruction = new InstructionApplyActions(actionsInfos).buildInstruction(0);
         instructions.add(writeInstruction);
         instructions.add(new InstructionGotoTable(tableId).buildInstruction(1));
@@ -462,7 +479,8 @@ public class VpnFloatingIpHandler implements FloatingIPHandler {
         InstanceIdentifier id = buildfloatingIpIdToPortMappingIdentifier(floatingIpId);
         try {
             Optional<FloatingIpIdToPortMapping> optFloatingIpIdToPortMapping =
-                NatUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
+                    SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
+                            LogicalDatastoreType.CONFIGURATION, id);
             if (optFloatingIpIdToPortMapping.isPresent() && optFloatingIpIdToPortMapping.get().isFloatingIpDeleted()) {
                 LOG.debug("Deleting floating IP UUID {} to Floating IP neutron port mapping from Floating "
                     + "IP Port Info Config DS", floatingIpId.getValue());