implementing routing for VPP
[groupbasedpolicy.git] / renderers / vpp / src / main / java / org / opendaylight / groupbasedpolicy / renderer / vpp / nat / NatManager.java
index a5821228beda73aa7e1e89f1410cad4f5ebaaeeb..0b046e2c4a323656ef6700e91661e5a42b411591 100644 (file)
@@ -12,24 +12,20 @@ import java.net.Inet4Address;
 import java.net.Inet6Address;\r
 import java.net.InetAddress;\r
 import java.net.UnknownHostException;\r
-import java.util.ArrayList;\r
 import java.util.List;\r
-import java.util.concurrent.ExecutionException;\r
 import java.util.concurrent.atomic.AtomicInteger;\r
 import java.util.stream.Collectors;\r
 \r
+import org.apache.commons.net.util.SubnetUtils;\r
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;\r
-import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;\r
-import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;\r
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;\r
 import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.PolicyContext;\r
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.GbpNetconfTransaction;\r
 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider;\r
 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;\r
-import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;\r
-import org.opendaylight.groupbasedpolicy.util.NetUtils;\r
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;\r
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;\r
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;\r
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;\r
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;\r
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;\r
@@ -40,20 +36,13 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev1509
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry;\r
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntryBuilder;\r
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.parameters.ExternalIpAddressPool;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererNodes;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.nodes.RendererNode;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.VppInterfaceAugmentation;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.renderers.renderer.renderer.nodes.renderer.node.PhysicalInterface;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.renderers.renderer.renderer.nodes.renderer.node.PhysicalInterfaceKey;\r
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;\r
 import org.slf4j.Logger;\r
 import org.slf4j.LoggerFactory;\r
 \r
 import com.google.common.base.Optional;\r
-import com.google.common.util.concurrent.AsyncFunction;\r
-import com.google.common.util.concurrent.Futures;\r
-import com.google.common.util.concurrent.ListenableFuture;\r
-\r
 public class NatManager {\r
 \r
     private static final Logger LOG = LoggerFactory.getLogger(NatManager.class);\r
@@ -68,42 +57,9 @@ public class NatManager {
         this.mountDataProvider = mountDataProvider;\r
     }\r
 \r
-    public Optional<InstanceIdentifier<PhysicalInterface>> resolvePhysicalInterface(IpPrefix extSubnetPrefix) {\r
-        ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();\r
-        Optional<RendererNodes> readFromDs = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,\r
-                VppIidFactory.getRendererNodesIid(), rTx);\r
-        rTx.close();\r
-        if (!readFromDs.isPresent() || readFromDs.get().getRendererNode() == null) {\r
-            return Optional.absent();\r
-        }\r
-        RendererNodes rendererNodes = readFromDs.get();\r
-        List<RendererNode> vppNodes = rendererNodes.getRendererNode()\r
-            .stream()\r
-            .filter(rn -> rn.getAugmentation(VppInterfaceAugmentation.class) != null)\r
-            .filter(rn -> rn.getAugmentation(VppInterfaceAugmentation.class).getPhysicalInterface() != null)\r
-            .collect(Collectors.toList());\r
-        for (RendererNode rn : vppNodes) {\r
-            java.util.Optional<PhysicalInterface> optResolvedIface = rn.getAugmentation(VppInterfaceAugmentation.class)\r
-                .getPhysicalInterface()\r
-                .stream()\r
-                .filter(phIface -> phIface.getAddress() != null)\r
-                .filter(phIface -> phIface.getAddress()\r
-                    .stream()\r
-                    .anyMatch(ipAddr -> NetUtils.isInRange(extSubnetPrefix, String.valueOf(ipAddr.getValue()))))\r
-                .findFirst();\r
-            if (optResolvedIface.isPresent()) {\r
-                return Optional.of(VppIidFactory.getRendererNodeIid(rn)\r
-                    .builder()\r
-                    .augmentation(VppInterfaceAugmentation.class)\r
-                    .child(PhysicalInterface.class, new PhysicalInterfaceKey(optResolvedIface.get().getKey()))\r
-                    .build());\r
-            }\r
-        }\r
-        return Optional.absent();\r
-    }\r
-\r
     public Optional<MappingEntryBuilder> resolveSnatEntry(String internal, Ipv4Address external) {\r
         IpAddress internalIp = null;\r
+        LOG.trace("Resolving SNAT entry for internal: {}, external: {}", internal, external);\r
         try {\r
             InetAddress inetAddr = InetAddress.getByName(internal);\r
             if (inetAddr instanceof Inet4Address) {\r
@@ -115,12 +71,21 @@ public class NatManager {
             LOG.error("Cannot resolve host IP {}. {}", internal, e.getMessage());\r
             return Optional.absent();\r
         }\r
-        return Optional.of(new MappingEntryBuilder().setInternalSrcAddress(internalIp).setExternalSrcAddress(external));\r
+        SubnetUtils subnet = new SubnetUtils(internal + "/32" );\r
+        Long index = Integer.toUnsignedLong(subnet.getInfo().asInteger(internal));\r
+        MappingEntryBuilder mappingEntryBuilder =\r
+            new MappingEntryBuilder().setType(\r
+                org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.MappingEntry.Type.Static)\r
+                .setIndex(index)\r
+                .setInternalSrcAddress(internalIp)\r
+                .setExternalSrcAddress(external);\r
+        LOG.trace("Resolved SNAT mapping: {}", mappingEntryBuilder.build().toString());\r
+        return Optional.of(mappingEntryBuilder);\r
     }\r
 \r
-    public ListenableFuture<Void> submitNatChanges(List<InstanceIdentifier<PhysicalInterface>> physIfacesIid,\r
+    public void submitNatChanges(List<InstanceIdentifier<PhysicalInterface>> physIfacesIid,\r
             List<MappingEntryBuilder> natEntries, PolicyContext policyCtx, boolean add) {\r
-        List<ListenableFuture<Void>> submitedFutures = new ArrayList<>();\r
+        LOG.trace("Preparing to submit NAT changes {} on physical interfaces", natEntries.toArray(), physIfacesIid);\r
         for (InstanceIdentifier<PhysicalInterface> iidPhysIface : physIfacesIid) {\r
             InstanceIdentifier<?> nodeIid = iidPhysIface.firstKeyOf(RendererNode.class).getNodePath();\r
             Optional<DataBroker> mountPointDataBroker = mountDataProvider.getDataBrokerForMountPoint(nodeIid);\r
@@ -128,45 +93,39 @@ public class NatManager {
                 throw new IllegalStateException("Cannot find data broker for mount point " + nodeIid);\r
             }\r
             String phInterfaceName = iidPhysIface.firstKeyOf(PhysicalInterface.class).getInterfaceName();\r
-            ReadWriteTransaction rwTx = mountPointDataBroker.get().newReadWriteTransaction();\r
-            InstanceIdentifier<Interface> interfaceIID = VppIidFactory.getInterfaceIID(new InterfaceKey(phInterfaceName));\r
-            submitedFutures.add(Futures.transform(rwTx.read(LogicalDatastoreType.CONFIGURATION, interfaceIID),\r
-                    new AsyncFunction<Optional<Interface>, Void>() {\r
+            InstanceIdentifier<Interface> interfaceIID =\r
+                VppIidFactory.getInterfaceIID(new InterfaceKey(phInterfaceName));\r
 \r
-                        @Override\r
-                        public ListenableFuture<Void> apply(Optional<Interface> readIface) throws Exception {\r
-                            if (!readIface.isPresent()) {\r
-                                LOG.error("Interface {} not found on mount point {}", phInterfaceName, nodeIid);\r
-                                return Futures.immediateFuture(null);\r
-                            }\r
-                            if (add) {\r
-                                LOG.trace("Setting outbound NAT on interface {}.", iidPhysIface.getPathArguments());\r
-                                NatUtil.setOutboundInterface(readIface.get(), rwTx); \r
-                                rwTx.put(LogicalDatastoreType.CONFIGURATION, VppIidFactory.getNatInstanceIid(id),\r
-                                        buildNatInstance(natEntries, NatUtil.resolveDynamicNat(policyCtx)));\r
-                            } else {\r
-                                LOG.trace("UNsetting outbound NAT on interface {}.", iidPhysIface.getPathArguments());\r
-                                NatUtil.unsetOutboundInterface(readIface.get(), rwTx);\r
-                                if (rwTx.read(LogicalDatastoreType.CONFIGURATION, VppIidFactory.getNatInstanceIid(id))\r
-                                    .get()\r
-                                    .isPresent()) {\r
-                                    rwTx.delete(LogicalDatastoreType.CONFIGURATION, VppIidFactory.getNatInstanceIid(id));\r
-                                }\r
-                            }\r
-                            return rwTx.submit();\r
-                        }\r
-                    }));\r
-        }\r
-        try {\r
-            Futures.allAsList(submitedFutures).get();\r
-        } catch (InterruptedException | ExecutionException e) {\r
-            LOG.error("Failed to sync NAT. {}", e.getMessage());\r
-            e.printStackTrace();\r
+            Optional<Interface> readIface =\r
+                GbpNetconfTransaction.read(mountPointDataBroker.get(), LogicalDatastoreType.CONFIGURATION, interfaceIID,\r
+                    GbpNetconfTransaction.RETRY_COUNT);\r
+\r
+            if (!readIface.isPresent()) {\r
+                LOG.error("Interface {} not found on mount point {}", phInterfaceName, nodeIid);\r
+                return;\r
+            }\r
+            if (add) {\r
+                LOG.trace("Setting outbound NAT on interface {} on node: {}", iidPhysIface.getPathArguments(), nodeIid);\r
+                NatUtil.setOutboundInterface(readIface.get(), mountPointDataBroker.get());\r
+                NatInstance natInstance =\r
+                    buildNatInstance(natEntries, NatUtil.resolveDynamicNat(policyCtx, natEntries));\r
+                GbpNetconfTransaction.netconfSyncedWrite(mountPointDataBroker.get(),\r
+                    VppIidFactory.getNatInstanceIid(id), natInstance, GbpNetconfTransaction.RETRY_COUNT);\r
+            } else {\r
+                LOG.trace("UNsetting outbound NAT on interface {}.", iidPhysIface.getPathArguments());\r
+                NatUtil.unsetOutboundInterface(readIface.get(), mountPointDataBroker.get());\r
+                if (GbpNetconfTransaction.read(mountPointDataBroker.get(), LogicalDatastoreType.CONFIGURATION,\r
+                    VppIidFactory.getNatInstanceIid(id), GbpNetconfTransaction.RETRY_COUNT).isPresent()) {\r
+                    GbpNetconfTransaction.netconfSyncedDelete(mountPointDataBroker.get(),\r
+                        VppIidFactory.getNatInstanceIid(id), GbpNetconfTransaction.RETRY_COUNT);\r
+                }\r
+            }\r
+            return;\r
         }\r
-        return Futures.immediateFuture(null);\r
     }\r
 \r
-    private NatInstance buildNatInstance(List<MappingEntryBuilder> natEntries, List<ExternalIpAddressPool> poolEntries) {\r
+    private NatInstance buildNatInstance(List<MappingEntryBuilder> natEntries,\r
+        List<ExternalIpAddressPool> poolEntries) {\r
         AtomicInteger ai = new AtomicInteger();\r
          List<MappingEntry> mappingEntries = natEntries.stream().map(me -> {\r
             int value = ai.get();\r
@@ -174,6 +133,10 @@ public class NatManager {
             return me.setIndex((long) value).build();\r
         }).collect(Collectors.toList());\r
         MappingTable mappingTable = new MappingTableBuilder().setMappingEntry(mappingEntries).build();\r
-        return new NatInstanceBuilder().setId(id).setExternalIpAddressPool(poolEntries).setMappingTable(mappingTable).build();\r
+        return new NatInstanceBuilder()\r
+            .setId(id)\r
+            .setExternalIpAddressPool(poolEntries)\r
+            .setMappingTable(mappingTable)\r
+            .build();\r
     }\r
 }\r