6887d6f79ed40195b6701bbf083860b31f987c3b
[groupbasedpolicy.git] / renderers / vpp / src / main / java / org / opendaylight / groupbasedpolicy / renderer / vpp / nat / NatUtil.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.util.ArrayList;\r
12 import java.util.HashMap;\r
13 \r
14 import com.google.common.annotations.VisibleForTesting;\r
15 import com.google.common.base.Optional;\r
16 \r
17 import org.opendaylight.controller.md.sal.binding.api.DataBroker;\r
18 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;\r
19 import java.util.List;\r
20 import java.util.Map;\r
21 import java.util.Map.Entry;\r
22 \r
23 import javax.annotation.Nonnull;\r
24 import javax.annotation.Nullable;\r
25 \r
26 import org.apache.commons.net.util.SubnetUtils;\r
27 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;\r
28 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;\r
29 import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.PolicyContext;\r
30 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.GbpNetconfTransaction;\r
31 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;\r
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;\r
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;\r
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;\r
35 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;\r
36 import org.opendaylight.groupbasedpolicy.util.NetUtils;\r
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;\r
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;\r
39 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
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.parameters.ExternalIpAddressPool;\r
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.parameters.ExternalIpAddressPoolBuilder;\r
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.SubnetAugmentRenderer;\r
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.subnet.AllocationPool;\r
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.forwarding.RendererForwardingByTenant;\r
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererNodes;\r
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.nodes.RendererNode;\r
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.VppInterfaceAugmentation;\r
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.renderers.renderer.renderer.nodes.renderer.node.PhysicalInterface;\r
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.renderers.renderer.renderer.nodes.renderer.node.PhysicalInterfaceKey;\r
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.forwarding.renderer.forwarding.by.tenant.RendererNetworkDomain;\r
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev161214.NatInterfaceAugmentation;\r
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev161214._interface.nat.attributes.Nat;\r
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev161214._interface.nat.attributes.NatBuilder;\r
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev161214._interface.nat.attributes.nat.InboundBuilder;\r
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev161214._interface.nat.attributes.nat.OutboundBuilder;\r
56 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;\r
57 import org.slf4j.Logger;\r
58 import org.slf4j.LoggerFactory;\r
59 \r
60 import java.util.stream.Collectors;\r
61 \r
62 public class NatUtil {\r
63     private static final Logger LOG = LoggerFactory.getLogger(NatUtil.class);\r
64 \r
65     public void setInboundInterface(Interface iface, WriteTransaction wTx) {\r
66         InstanceIdentifier<Nat> natIid = buildNatIid(VppIidFactory.getInterfaceIID(iface.getKey()));\r
67         Nat nat = new NatBuilder().setInbound(new InboundBuilder().build()).build();\r
68         wTx.put(LogicalDatastoreType.CONFIGURATION, natIid, nat);\r
69     }\r
70 \r
71     public static void setOutboundInterface(Interface iface, DataBroker dataBroker) {\r
72         InstanceIdentifier<Nat> natIid = buildNatIid(VppIidFactory.getInterfaceIID(iface.getKey()));\r
73         Nat nat = new NatBuilder().setOutbound(new OutboundBuilder().build()).build();\r
74         GbpNetconfTransaction.netconfSyncedWrite(dataBroker, natIid, nat, GbpNetconfTransaction.RETRY_COUNT);\r
75 \r
76     }\r
77 \r
78     public static void unsetOutboundInterface(Interface iface, DataBroker dataBroker) {\r
79         InstanceIdentifier<Nat> natIid = buildNatIid(VppIidFactory.getInterfaceIID(iface.getKey()));\r
80         GbpNetconfTransaction.netconfSyncedDelete(dataBroker, natIid, GbpNetconfTransaction.RETRY_COUNT);\r
81     }\r
82 \r
83     public static InstanceIdentifier<Nat> buildNatIid(InstanceIdentifier<Interface> ifaceIid) {\r
84         return ifaceIid.builder().augmentation(NatInterfaceAugmentation.class).child(Nat.class).build();\r
85     }\r
86 \r
87     public static Optional<InstanceIdentifier<PhysicalInterface>> resolvePhysicalInterface(IpPrefix extSubnetPrefix,\r
88         ReadOnlyTransaction rTx) {\r
89         Optional<RendererNodes> readFromDs =\r
90             DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, VppIidFactory.getRendererNodesIid(), rTx);\r
91         rTx.close();\r
92         if (!readFromDs.isPresent() || readFromDs.get().getRendererNode() == null) {\r
93             return Optional.absent();\r
94         }\r
95         RendererNodes rendererNodes = readFromDs.get();\r
96         List<RendererNode>\r
97             vppNodes =\r
98             rendererNodes.getRendererNode()\r
99                 .stream()\r
100                 .filter(rn -> rn.getAugmentation(VppInterfaceAugmentation.class) != null)\r
101                 .filter(rn -> rn.getAugmentation(VppInterfaceAugmentation.class).getPhysicalInterface() != null)\r
102                 .collect(Collectors.toList());\r
103         for (RendererNode rn : vppNodes) {\r
104             java.util.Optional<PhysicalInterface>\r
105                 optResolvedIface =\r
106                 rn.getAugmentation(VppInterfaceAugmentation.class)\r
107                     .getPhysicalInterface()\r
108                     .stream()\r
109                     .filter(phIface -> phIface.getAddress() != null)\r
110                     .filter(phIface -> phIface.getAddress()\r
111                         .stream()\r
112                         .anyMatch(ipAddr -> NetUtils.isInRange(extSubnetPrefix, String.valueOf(ipAddr.getValue()))))\r
113                     .findFirst();\r
114             if (optResolvedIface.isPresent()) {\r
115                 return Optional.of(VppIidFactory.getRendererNodeIid(rn)\r
116                     .builder()\r
117                     .augmentation(VppInterfaceAugmentation.class)\r
118                     .child(PhysicalInterface.class, new PhysicalInterfaceKey(optResolvedIface.get().getKey()))\r
119                     .build());\r
120             }\r
121         }\r
122         return Optional.absent();\r
123     }\r
124 \r
125     public static List<ExternalIpAddressPool> resolveDynamicNat(@Nonnull PolicyContext policyCtx,\r
126         List<MappingEntryBuilder> natEntries) {\r
127         List<RendererForwardingByTenant> rendererForwardingByTenant =\r
128                 policyCtx.getPolicy().getConfiguration().getRendererForwarding().getRendererForwardingByTenant();\r
129         Map<Long, Ipv4Prefix> hm = new HashMap<>();\r
130         for (RendererForwardingByTenant rft : rendererForwardingByTenant) {\r
131             for (RendererNetworkDomain rnd : rft.getRendererNetworkDomain()) {\r
132                 SubnetAugmentRenderer subnet = rnd.getAugmentation(SubnetAugmentRenderer.class);\r
133                 if (subnet.getSubnet() != null && !subnet.getSubnet().isIsTenant()\r
134                         && subnet.getSubnet().getAllocationPool() != null) {\r
135                     for (AllocationPool pool : subnet.getSubnet().getAllocationPool()) {\r
136                         if (subnet.getSubnet().getIpPrefix().getIpv4Prefix() != null) {\r
137                             hm.putAll(resolveIpv4Prefix(subnet.getSubnet().getIpPrefix().getIpv4Prefix(),\r
138                                     pool.getFirst(), pool.getLast(), natEntries));\r
139                         }\r
140                     }\r
141                 }\r
142             }\r
143         }\r
144         List<ExternalIpAddressPool> extIps = new ArrayList<>();\r
145         for (Entry<Long, Ipv4Prefix> entry : hm.entrySet()) {\r
146             extIps.add(new ExternalIpAddressPoolBuilder().setPoolId(entry.getKey())\r
147                 .setExternalIpPool(entry.getValue())\r
148                 .build());\r
149         }\r
150         return extIps;\r
151     }\r
152 \r
153     @VisibleForTesting\r
154     private static Map<Long,Ipv4Prefix> resolveIpv4Prefix(@Nonnull Ipv4Prefix prefix, @Nonnull String first,\r
155             @Nullable String last, @Nullable List<MappingEntryBuilder> natEntries) {\r
156         LOG.trace("Resolving Ipv4Prefix. prefix: {}, first: {}, last: {}", prefix.getValue(), first, last);\r
157         SubnetUtils subnet = new SubnetUtils(prefix.getValue());\r
158         Map<Long,Ipv4Prefix> ext = new HashMap<>();\r
159         int min = subnet.getInfo().asInteger(first);\r
160         for (String addr : subnet.getInfo().getAllAddresses()) {\r
161             int asInt = subnet.getInfo().asInteger(addr);\r
162             if (asInt < min) {\r
163                 continue;\r
164             }\r
165             ext.put(Integer.toUnsignedLong(asInt), new Ipv4Prefix(addr + "/32"));\r
166             if (last == null || subnet.getInfo().asInteger(addr) >= subnet.getInfo().asInteger(last)) {\r
167                 break;\r
168             }\r
169         }\r
170         if (natEntries != null) {\r
171             for (MappingEntryBuilder natEntry : natEntries) {\r
172                 Ipv4Address externalSrcAddress = natEntry.getExternalSrcAddress();\r
173                 long id = Integer.toUnsignedLong(subnet.getInfo().asInteger(externalSrcAddress.getValue()));\r
174                 if (ext.get(id) != null) {\r
175                     ext.remove(id);\r
176                 }\r
177             }\r
178         }\r
179         return ext;\r
180     }\r
181 }\r