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
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
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
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
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
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