0b046e2c4a323656ef6700e91661e5a42b411591
[groupbasedpolicy.git] / renderers / vpp / src / main / java / org / opendaylight / groupbasedpolicy / renderer / vpp / nat / NatManager.java
1 /*\r
2  * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.\r
3  *\r
4  * This program and the accompanying materials are made available under the\r
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
6  * and is available at http://www.eclipse.org/legal/epl-v10.html\r
7  */\r
8 \r
9 package org.opendaylight.groupbasedpolicy.renderer.vpp.nat;\r
10 \r
11 import java.net.Inet4Address;\r
12 import java.net.Inet6Address;\r
13 import java.net.InetAddress;\r
14 import java.net.UnknownHostException;\r
15 import java.util.List;\r
16 import java.util.concurrent.atomic.AtomicInteger;\r
17 import java.util.stream.Collectors;\r
18 \r
19 import org.apache.commons.net.util.SubnetUtils;\r
20 import org.opendaylight.controller.md.sal.binding.api.DataBroker;\r
21 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;\r
22 import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.PolicyContext;\r
23 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.GbpNetconfTransaction;\r
24 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider;\r
25 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;\r
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;\r
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;\r
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;\r
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;\r
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;\r
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;\r
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.NatInstance;\r
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.NatInstanceBuilder;\r
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.MappingTable;\r
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.MappingTableBuilder;\r
36 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
37 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
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.parameters.ExternalIpAddressPool;\r
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.nodes.RendererNode;\r
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.renderers.renderer.renderer.nodes.renderer.node.PhysicalInterface;\r
41 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;\r
42 import org.slf4j.Logger;\r
43 import org.slf4j.LoggerFactory;\r
44 \r
45 import com.google.common.base.Optional;\r
46 public class NatManager {\r
47 \r
48     private static final Logger LOG = LoggerFactory.getLogger(NatManager.class);\r
49 \r
50     private final Long id;\r
51     private final DataBroker dataBroker;\r
52     private final MountedDataBrokerProvider mountDataProvider;\r
53 \r
54     public NatManager(DataBroker dataBroker, MountedDataBrokerProvider mountDataProvider) {\r
55         this.id = 0L;\r
56         this.dataBroker = dataBroker;\r
57         this.mountDataProvider = mountDataProvider;\r
58     }\r
59 \r
60     public Optional<MappingEntryBuilder> resolveSnatEntry(String internal, Ipv4Address external) {\r
61         IpAddress internalIp = null;\r
62         LOG.trace("Resolving SNAT entry for internal: {}, external: {}", internal, external);\r
63         try {\r
64             InetAddress inetAddr = InetAddress.getByName(internal);\r
65             if (inetAddr instanceof Inet4Address) {\r
66                 internalIp = new IpAddress(new Ipv4Address(internal));\r
67             } else if (inetAddr instanceof Inet6Address) {\r
68                 internalIp = new IpAddress(new Ipv6Address(internal));\r
69             }\r
70         } catch (UnknownHostException e) {\r
71             LOG.error("Cannot resolve host IP {}. {}", internal, e.getMessage());\r
72             return Optional.absent();\r
73         }\r
74         SubnetUtils subnet = new SubnetUtils(internal + "/32" );\r
75         Long index = Integer.toUnsignedLong(subnet.getInfo().asInteger(internal));\r
76         MappingEntryBuilder mappingEntryBuilder =\r
77             new MappingEntryBuilder().setType(\r
78                 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.MappingEntry.Type.Static)\r
79                 .setIndex(index)\r
80                 .setInternalSrcAddress(internalIp)\r
81                 .setExternalSrcAddress(external);\r
82         LOG.trace("Resolved SNAT mapping: {}", mappingEntryBuilder.build().toString());\r
83         return Optional.of(mappingEntryBuilder);\r
84     }\r
85 \r
86     public void submitNatChanges(List<InstanceIdentifier<PhysicalInterface>> physIfacesIid,\r
87             List<MappingEntryBuilder> natEntries, PolicyContext policyCtx, boolean add) {\r
88         LOG.trace("Preparing to submit NAT changes {} on physical interfaces", natEntries.toArray(), physIfacesIid);\r
89         for (InstanceIdentifier<PhysicalInterface> iidPhysIface : physIfacesIid) {\r
90             InstanceIdentifier<?> nodeIid = iidPhysIface.firstKeyOf(RendererNode.class).getNodePath();\r
91             Optional<DataBroker> mountPointDataBroker = mountDataProvider.getDataBrokerForMountPoint(nodeIid);\r
92             if (!mountPointDataBroker.isPresent()) {\r
93                 throw new IllegalStateException("Cannot find data broker for mount point " + nodeIid);\r
94             }\r
95             String phInterfaceName = iidPhysIface.firstKeyOf(PhysicalInterface.class).getInterfaceName();\r
96             InstanceIdentifier<Interface> interfaceIID =\r
97                 VppIidFactory.getInterfaceIID(new InterfaceKey(phInterfaceName));\r
98 \r
99             Optional<Interface> readIface =\r
100                 GbpNetconfTransaction.read(mountPointDataBroker.get(), LogicalDatastoreType.CONFIGURATION, interfaceIID,\r
101                     GbpNetconfTransaction.RETRY_COUNT);\r
102 \r
103             if (!readIface.isPresent()) {\r
104                 LOG.error("Interface {} not found on mount point {}", phInterfaceName, nodeIid);\r
105                 return;\r
106             }\r
107             if (add) {\r
108                 LOG.trace("Setting outbound NAT on interface {} on node: {}", iidPhysIface.getPathArguments(), nodeIid);\r
109                 NatUtil.setOutboundInterface(readIface.get(), mountPointDataBroker.get());\r
110                 NatInstance natInstance =\r
111                     buildNatInstance(natEntries, NatUtil.resolveDynamicNat(policyCtx, natEntries));\r
112                 GbpNetconfTransaction.netconfSyncedWrite(mountPointDataBroker.get(),\r
113                     VppIidFactory.getNatInstanceIid(id), natInstance, GbpNetconfTransaction.RETRY_COUNT);\r
114             } else {\r
115                 LOG.trace("UNsetting outbound NAT on interface {}.", iidPhysIface.getPathArguments());\r
116                 NatUtil.unsetOutboundInterface(readIface.get(), mountPointDataBroker.get());\r
117                 if (GbpNetconfTransaction.read(mountPointDataBroker.get(), LogicalDatastoreType.CONFIGURATION,\r
118                     VppIidFactory.getNatInstanceIid(id), GbpNetconfTransaction.RETRY_COUNT).isPresent()) {\r
119                     GbpNetconfTransaction.netconfSyncedDelete(mountPointDataBroker.get(),\r
120                         VppIidFactory.getNatInstanceIid(id), GbpNetconfTransaction.RETRY_COUNT);\r
121                 }\r
122             }\r
123             return;\r
124         }\r
125     }\r
126 \r
127     private NatInstance buildNatInstance(List<MappingEntryBuilder> natEntries,\r
128         List<ExternalIpAddressPool> poolEntries) {\r
129         AtomicInteger ai = new AtomicInteger();\r
130          List<MappingEntry> mappingEntries = natEntries.stream().map(me -> {\r
131             int value = ai.get();\r
132             ai.incrementAndGet();\r
133             return me.setIndex((long) value).build();\r
134         }).collect(Collectors.toList());\r
135         MappingTable mappingTable = new MappingTableBuilder().setMappingEntry(mappingEntries).build();\r
136         return new NatInstanceBuilder()\r
137             .setId(id)\r
138             .setExternalIpAddressPool(poolEntries)\r
139             .setMappingTable(mappingTable)\r
140             .build();\r
141     }\r
142 }\r