2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
\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
9 package org.opendaylight.groupbasedpolicy.renderer.vpp.nat;
\r
11 import java.util.ArrayList;
\r
12 import java.util.HashMap;
\r
14 import com.google.common.annotations.VisibleForTesting;
\r
15 import com.google.common.base.Optional;
\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
23 import javax.annotation.Nonnull;
\r
24 import javax.annotation.Nullable;
\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
60 import java.util.stream.Collectors;
\r
62 public class NatUtil {
\r
63 private static final Logger LOG = LoggerFactory.getLogger(NatUtil.class);
\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
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
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
83 public static InstanceIdentifier<Nat> buildNatIid(InstanceIdentifier<Interface> ifaceIid) {
\r
84 return ifaceIid.builder().augmentation(NatInterfaceAugmentation.class).child(Nat.class).build();
\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
92 if (!readFromDs.isPresent() || readFromDs.get().getRendererNode() == null) {
\r
93 return Optional.absent();
\r
95 RendererNodes rendererNodes = readFromDs.get();
\r
98 rendererNodes.getRendererNode()
\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
106 rn.getAugmentation(VppInterfaceAugmentation.class)
\r
107 .getPhysicalInterface()
\r
109 .filter(phIface -> phIface.getAddress() != null)
\r
110 .filter(phIface -> phIface.getAddress()
\r
112 .anyMatch(ipAddr -> NetUtils.isInRange(extSubnetPrefix, String.valueOf(ipAddr.getValue()))))
\r
114 if (optResolvedIface.isPresent()) {
\r
115 return Optional.of(VppIidFactory.getRendererNodeIid(rn)
\r
117 .augmentation(VppInterfaceAugmentation.class)
\r
118 .child(PhysicalInterface.class, new PhysicalInterfaceKey(optResolvedIface.get().getKey()))
\r
122 return Optional.absent();
\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
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
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
165 ext.put(Integer.toUnsignedLong(asInt), new Ipv4Prefix(addr + "/32"));
\r
166 if (last == null || subnet.getInfo().asInteger(addr) >= subnet.getInfo().asInteger(last)) {
\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