From df29f6896818404391aa3fcfdeba789b4c43bebd Mon Sep 17 00:00:00 2001 From: Tomas Cechvala Date: Tue, 28 Feb 2017 10:25:53 +0100 Subject: [PATCH] Initial implementation for dynamic SNAT allocation pools is needed in an external network -> VPP renderer will use external subnet as a pool for dynamic SNAT. - isTenant = false - allocationPool is specified -> traffic passing through an interface set to 'outside NAT' will be automatically translated Change-Id: I18077d0fa31ae1ae3b2fde13aa12c2d41c3fdecb Signed-off-by: Tomas Cechvala --- .../l2-l3/src/main/yang/l2-l3-forwarding.yang | 15 +++++ .../mapper/mapping/NeutronPortAware.java | 4 +- .../mapper/mapping/NeutronSubnetAware.java | 62 ++++++++++++++++--- .../neutron/mapper/util/NetworkUtils.java | 4 ++ .../NeutronPortAwareDataStoreTest.java | 9 +-- .../NeutronSubnetAwareDataStoreTest.java | 22 +++---- .../mapper/test/NeutronMapperAssert.java | 21 ++++--- .../renderer/vpp/nat/NatManager.java | 12 ++-- .../renderer/vpp/nat/NatUtil.java | 61 ++++++++++++++++++ .../vpp/policy/ForwardingManager.java | 4 +- 10 files changed, 173 insertions(+), 41 deletions(-) diff --git a/domain-extensions/l2-l3/src/main/yang/l2-l3-forwarding.yang b/domain-extensions/l2-l3/src/main/yang/l2-l3-forwarding.yang index 5d8f3a61f..b0b82af4e 100644 --- a/domain-extensions/l2-l3/src/main/yang/l2-l3-forwarding.yang +++ b/domain-extensions/l2-l3/src/main/yang/l2-l3-forwarding.yang @@ -78,6 +78,21 @@ module l2-l3-forwarding { } } } + list allocation-pool { + description "Allocation pool of assignable addresses."; + key "first last"; + leaf first { + type string; + } + leaf last { + type string; + } + } + leaf is-tenant { + description "Subnet is used as tenant network."; + type boolean; + default "true"; + } } } diff --git a/neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronPortAware.java b/neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronPortAware.java index cb177af8f..c46cf2d30 100644 --- a/neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronPortAware.java +++ b/neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronPortAware.java @@ -175,7 +175,7 @@ public class NeutronPortAware implements NeutronAware { rwTx.merge(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.l2BridgeDomainIid(tenantId, l2BdId), l2Bd, true); // set virtual router IP for subnet NetworkDomain subnetDomain = NeutronSubnetAware.createSubnet( - routerPortSubnet, portIpWithSubnet.getIpAddress()); + routerPortSubnet, neutron); rwTx.merge(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.subnetIid(tenantId, subnetDomain.getNetworkDomainId()), subnetDomain); // does the same for tenant forwarding domains @@ -589,7 +589,7 @@ public class NeutronPortAware implements NeutronAware { .build(); rwTx.merge(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.l2BridgeDomainIid(tenantId, fwdCtx.getContextId()), fwdCtx); - NetworkDomain subnet = NeutronSubnetAware.createSubnet(routerPortSubnet, null); + NetworkDomain subnet = NeutronSubnetAware.createSubnet(routerPortSubnet, newNeutron); rwTx.put(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.subnetIid(tenantId, subnet.getNetworkDomainId()), subnet); unregisterEndpointAndRemoveMapping(createUnregisterEndpointInput(port, oldNeutron), port, rwTx); diff --git a/neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronSubnetAware.java b/neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronSubnetAware.java index fc7c1675c..6d70dcd2f 100644 --- a/neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronSubnetAware.java +++ b/neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronSubnetAware.java @@ -9,6 +9,9 @@ package org.opendaylight.groupbasedpolicy.neutron.mapper.mapping; import static com.google.common.base.Preconditions.checkNotNull; +import java.util.List; +import java.util.stream.Collectors; + import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; @@ -29,10 +32,14 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.SubnetAugmentForwarding; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.SubnetAugmentForwardingBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.SubnetBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.subnet.AllocationPool; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.subnet.AllocationPoolBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.NetworkDomain; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.NetworkDomainBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network; +import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port; +import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.NetworkProviderExtension; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; @@ -80,8 +87,7 @@ public class NeutronSubnetAware implements NetworkDomain subnetDomain = null; if (NetworkUtils.isProviderPhysicalNetwork(networkOfSubnet)) { - // add virtual router IP only in case it is provider physical network - subnetDomain = createSubnet(neutronSubnet, neutronSubnet.getGatewayIp()); + subnetDomain = createSubnet(neutronSubnet, neutron); IpAddress gatewayIp = neutronSubnet.getGatewayIp(); boolean registeredDefaultRoute = epRegistrator.registerExternalL3PrefixEndpoint(MappingUtils.DEFAULT_ROUTE, new L3ContextId(neutronSubnet.getNetworkId().getValue()), gatewayIp, tenantId); @@ -92,9 +98,7 @@ public class NeutronSubnetAware implements return; } } else { - // virtual router IP is not set and it will be set when router gateway port is set - // or when a router port is attached to a network - subnetDomain = createSubnet(neutronSubnet, null); + subnetDomain = createSubnet(neutronSubnet, neutron); } processTenantSubnet(neutronSubnet, networkOfSubnet, tenantId, rwTx); rwTx.put(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.subnetIid(tenantId, subnetDomain.getNetworkDomainId()), subnetDomain, true); @@ -103,10 +107,54 @@ public class NeutronSubnetAware implements public static NetworkDomain createSubnet( org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet subnet, - IpAddress virtualRouterIp) { + Neutron neutron) { SubnetBuilder sb = new SubnetBuilder(); sb.setIpPrefix(subnet.getCidr()); - sb.setVirtualRouterIp(virtualRouterIp); + if (neutron.getPorts() != null && neutron.getPorts().getPort() != null) { + for (Port port : neutron.getPorts().getPort()) { + if (port.getFixedIps() == null || !port.getFixedIps() + .stream() + .filter(fi -> fi.getSubnetId().equals(subnet.getUuid())) + .findFirst() + .isPresent()) { + continue; + } + if (neutron.getRouters() != null && neutron.getRouters().getRouter() != null && neutron.getRouters() + .getRouter() + .stream() + .filter(r -> !r.getUuid().getValue().equals(port.getDeviceOwner())) + .findFirst() + .isPresent()) { + // virtual router IP is set when a router port is attached to a network + sb.setVirtualRouterIp(subnet.getGatewayIp()); + } else if (neutron.getNetworks() != null && neutron.getNetworks().getNetwork() != null && neutron + .getNetworks() + .getNetwork() + .stream() + .filter(net -> net.getUuid().equals(port.getNetworkId())) + .filter(net -> net.getAugmentation(NetworkProviderExtension.class) != null) + .filter(net -> net.getAugmentation(NetworkProviderExtension.class).getPhysicalNetwork() != null) + .findFirst() + .isPresent()) { + // add virtual router IP only in case it is provider physical network + sb.setVirtualRouterIp(subnet.getGatewayIp()); + } + } + } + Optional potentialNetwork = + NetworkUtils.findNetwork(subnet.getNetworkId(), neutron.getNetworks()); + if (potentialNetwork.isPresent()) { + sb.setIsTenant(NetworkUtils.isTenantNetwork(potentialNetwork.get())); + } + if (subnet.getAllocationPools() != null) { + List pools = subnet.getAllocationPools() + .stream() + .map(s -> new AllocationPoolBuilder().setFirst(s.getStart().getIpv4Address().getValue()) + .setLast(s.getEnd().getIpv4Address().getValue()) + .build()) + .collect(Collectors.toList()); + sb.setAllocationPool(pools); + } NetworkDomainBuilder ndb = new NetworkDomainBuilder(); if (!Strings.isNullOrEmpty(subnet.getName())) { try { diff --git a/neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/util/NetworkUtils.java b/neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/util/NetworkUtils.java index 237f105d0..eff8541e5 100644 --- a/neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/util/NetworkUtils.java +++ b/neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/util/NetworkUtils.java @@ -51,6 +51,10 @@ public class NetworkUtils { return Optional.absent(); } + public static boolean isTenantNetwork(Network network) { + return getPhysicalNetwork(network).isEmpty(); + } + public static boolean isProviderPhysicalNetwork(Network network) { return (!isRouterExternal(network) && !getPhysicalNetwork(network).isEmpty()); } diff --git a/neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronPortAwareDataStoreTest.java b/neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronPortAwareDataStoreTest.java index d5f7c6b16..cd5f3099e 100644 --- a/neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronPortAwareDataStoreTest.java +++ b/neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronPortAwareDataStoreTest.java @@ -14,7 +14,6 @@ import static org.mockito.Mockito.when; import java.util.List; -import com.google.common.collect.ImmutableList; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -43,6 +42,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.s import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.SubnetBuilder; +import com.google.common.collect.ImmutableList; + public class NeutronPortAwareDataStoreTest extends NeutronMapperDataBrokerTest { private final Uuid tenantUuid = new Uuid("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"); @@ -188,10 +189,10 @@ public class NeutronPortAwareDataStoreTest extends NeutronMapperDataBrokerTest { .setFixedIps(ImmutableList.of(portIpWithSubnet)) .build(); portAware.onCreated(port, neutron); - NeutronMapperAssert.assertNetworkDomainExists(dataBroker, port, subnet, ipAddress); + NeutronMapperAssert.assertNetworkDomainExists(dataBroker, port, subnet, neutron); portAware.onDeleted(port, neutron, neutron); - NeutronMapperAssert.assertNetworkDomainExists(dataBroker, port, subnet, ipAddress); + NeutronMapperAssert.assertNetworkDomainExists(dataBroker, port, subnet, neutron); NeutronMapperAssert.assertPortNotExists(dataBroker, port.getUuid()); } @@ -204,7 +205,7 @@ public class NeutronPortAwareDataStoreTest extends NeutronMapperDataBrokerTest { Subnet subnet = subnets.getSubnet().get(0); Port port = newBasePort().setDeviceOwner(PortUtils.DEVICE_OWNER_ROUTER_IFACE).build(); portAware.onCreated(port, neutron); - NeutronMapperAssert.assertNetworkDomainNotExists(dataBroker, port, subnet, ipAddress); + NeutronMapperAssert.assertNetworkDomainNotExists(dataBroker, port, subnet, neutron); } @Test diff --git a/neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronSubnetAwareDataStoreTest.java b/neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronSubnetAwareDataStoreTest.java index 0712d5496..e9b63dc74 100644 --- a/neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronSubnetAwareDataStoreTest.java +++ b/neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronSubnetAwareDataStoreTest.java @@ -15,7 +15,6 @@ import static org.mockito.Mockito.when; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; -import com.google.common.collect.ImmutableList; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -42,6 +41,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.s import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.SubnetBuilder; import org.opendaylight.yangtools.yang.common.RpcResult; +import com.google.common.collect.ImmutableList; + public class NeutronSubnetAwareDataStoreTest extends NeutronMapperDataBrokerTest { private static final Uuid tenantUuid = new Uuid("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"); @@ -122,7 +123,7 @@ public class NeutronSubnetAwareDataStoreTest extends NeutronMapperDataBrokerTest subnetAware.onCreated(subnet, neutron); - NeutronMapperAssert.assertNetworkDomainExists(dataBroker, tenantUuid, subnet, ipAddress); + NeutronMapperAssert.assertNetworkDomainExists(dataBroker, tenantUuid, subnet, neutron); } @Test @@ -133,7 +134,7 @@ public class NeutronSubnetAwareDataStoreTest extends NeutronMapperDataBrokerTest subnetAware.onCreated(subnet, neutron); - NeutronMapperAssert.assertNetworkDomainNotExists(dataBroker, tenantUuid, subnet, ipAddress); + NeutronMapperAssert.assertNetworkDomainNotExists(dataBroker, tenantUuid, subnet, neutron); } @Test @@ -145,12 +146,12 @@ public class NeutronSubnetAwareDataStoreTest extends NeutronMapperDataBrokerTest subnetAware.onCreated(subnet, neutron); - NeutronMapperAssert.assertNetworkDomainExists(dataBroker, tenantUuid, subnet, ipAddress); - NeutronMapperAssert.assertNetworkDomainNotExists(dataBroker, tenantUuid, subnet2, ipAddress); + NeutronMapperAssert.assertNetworkDomainExists(dataBroker, tenantUuid, subnet, neutron); + NeutronMapperAssert.assertNetworkDomainNotExists(dataBroker, tenantUuid, subnet2, neutron); subnetAware.onUpdated(subnet, subnet2, neutron, neutron); - NeutronMapperAssert.assertNetworkDomainExists(dataBroker, tenantUuid, subnet2, ipAddress); + NeutronMapperAssert.assertNetworkDomainExists(dataBroker, tenantUuid, subnet2, neutron); } @Test @@ -162,13 +163,12 @@ public class NeutronSubnetAwareDataStoreTest extends NeutronMapperDataBrokerTest subnetAware.onCreated(subnet, neutron); - NeutronMapperAssert.assertNetworkDomainExists(dataBroker, tenantUuid, subnet, ipAddress); + NeutronMapperAssert.assertNetworkDomainExists(dataBroker, tenantUuid, subnet, neutron); subnetAware.onDeleted(subnet, neutron, neutron); - NeutronMapperAssert.assertNetworkDomainNotExists(dataBroker, tenantUuid, subnet, ipAddress); + NeutronMapperAssert.assertNetworkDomainNotExists(dataBroker, tenantUuid, subnet, neutron); } - @Test public void testOnDeleted_wrongSubnet() { @@ -178,11 +178,11 @@ public class NeutronSubnetAwareDataStoreTest extends NeutronMapperDataBrokerTest subnetAware.onCreated(subnet, neutron); - NeutronMapperAssert.assertNetworkDomainExists(dataBroker, tenantUuid, subnet, ipAddress); + NeutronMapperAssert.assertNetworkDomainExists(dataBroker, tenantUuid, subnet, neutron); subnetAware.onDeleted(subnet2, neutron, neutron); - NeutronMapperAssert.assertNetworkDomainExists(dataBroker, tenantUuid, subnet, ipAddress); + NeutronMapperAssert.assertNetworkDomainExists(dataBroker, tenantUuid, subnet, neutron); } } diff --git a/neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/test/NeutronMapperAssert.java b/neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/test/NeutronMapperAssert.java index d3b774ed0..5098cb3f3 100644 --- a/neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/test/NeutronMapperAssert.java +++ b/neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/test/NeutronMapperAssert.java @@ -27,6 +27,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.endpoints.by.ports.EndpointByPort; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port; +import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.SubnetBuilder; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; @@ -55,35 +56,35 @@ public class NeutronMapperAssert { return portOptional; } - public static void assertNetworkDomainExists(DataBroker dataBroker, Port port, Subnet subnet, IpAddress ipAddress) { + public static void assertNetworkDomainExists(DataBroker dataBroker, Port port, Subnet subnet, Neutron neutron) { Optional opt = - getNetworkDomainOptional(dataBroker, port.getTenantId(), ipAddress, subnet); + getNetworkDomainOptional(dataBroker, port.getTenantId(), neutron, subnet); assertTrue(opt.isPresent()); } public static void assertNetworkDomainNotExists(DataBroker dataBroker, Port port, Subnet subnet, - IpAddress ipAddress) { + Neutron neutron) { Optional opt = - getNetworkDomainOptional(dataBroker, port.getTenantId(), ipAddress, subnet); + getNetworkDomainOptional(dataBroker, port.getTenantId(), neutron, subnet); assertFalse(opt.isPresent()); } public static void assertNetworkDomainExists(DataBroker dataBroker, Uuid tenantUuid, Subnet subnet, - IpAddress ipAddress) { - Optional opt = getNetworkDomainOptional(dataBroker, tenantUuid, ipAddress, subnet); + Neutron neutron) { + Optional opt = getNetworkDomainOptional(dataBroker, tenantUuid, neutron, subnet); assertTrue(opt.isPresent()); } public static void assertNetworkDomainNotExists(DataBroker dataBroker, Uuid tenantUuid, Subnet subnet, - IpAddress ipAddress) { - Optional opt = getNetworkDomainOptional(dataBroker, tenantUuid, ipAddress, subnet); + Neutron neutron) { + Optional opt = getNetworkDomainOptional(dataBroker, tenantUuid, neutron, subnet); assertFalse(opt.isPresent()); } private static Optional getNetworkDomainOptional(DataBroker dataBroker, Uuid tenantUuid, - IpAddress ipAddress, Subnet subnet) { + Neutron neutron, Subnet subnet) { InstanceIdentifier iid; - NetworkDomain subnetDomain = NeutronSubnetAware.createSubnet(subnet, ipAddress); + NetworkDomain subnetDomain = NeutronSubnetAware.createSubnet(subnet, neutron); TenantId tenantId = new TenantId(tenantUuid.getValue()); iid = L2L3IidFactory.subnetIid(tenantId, subnetDomain.getNetworkDomainId()); Optional optional; diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/nat/NatManager.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/nat/NatManager.java index 1564a560e..a5821228b 100644 --- a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/nat/NatManager.java +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/nat/NatManager.java @@ -22,6 +22,7 @@ import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.PolicyContext; import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider; import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory; import org.opendaylight.groupbasedpolicy.util.DataStoreHelper; @@ -38,6 +39,7 @@ 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.MappingTableBuilder; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntryBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.parameters.ExternalIpAddressPool; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererNodes; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.nodes.RendererNode; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.VppInterfaceAugmentation; @@ -117,7 +119,7 @@ public class NatManager { } public ListenableFuture submitNatChanges(List> physIfacesIid, - List natEntries, boolean add) { + List natEntries, PolicyContext policyCtx, boolean add) { List> submitedFutures = new ArrayList<>(); for (InstanceIdentifier iidPhysIface : physIfacesIid) { InstanceIdentifier nodeIid = iidPhysIface.firstKeyOf(RendererNode.class).getNodePath(); @@ -139,9 +141,9 @@ public class NatManager { } if (add) { LOG.trace("Setting outbound NAT on interface {}.", iidPhysIface.getPathArguments()); - NatUtil.setOutboundInterface(readIface.get(), rwTx); + NatUtil.setOutboundInterface(readIface.get(), rwTx); rwTx.put(LogicalDatastoreType.CONFIGURATION, VppIidFactory.getNatInstanceIid(id), - buildNatInstance(natEntries)); + buildNatInstance(natEntries, NatUtil.resolveDynamicNat(policyCtx))); } else { LOG.trace("UNsetting outbound NAT on interface {}.", iidPhysIface.getPathArguments()); NatUtil.unsetOutboundInterface(readIface.get(), rwTx); @@ -164,7 +166,7 @@ public class NatManager { return Futures.immediateFuture(null); } - private NatInstance buildNatInstance(List natEntries) { + private NatInstance buildNatInstance(List natEntries, List poolEntries) { AtomicInteger ai = new AtomicInteger(); List mappingEntries = natEntries.stream().map(me -> { int value = ai.get(); @@ -172,6 +174,6 @@ public class NatManager { return me.setIndex((long) value).build(); }).collect(Collectors.toList()); MappingTable mappingTable = new MappingTableBuilder().setMappingEntry(mappingEntries).build(); - return new NatInstanceBuilder().setId(id).setMappingTable(mappingTable).build(); + return new NatInstanceBuilder().setId(id).setExternalIpAddressPool(poolEntries).setMappingTable(mappingTable).build(); } } diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/nat/NatUtil.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/nat/NatUtil.java index de4f83cd0..c2fff1cae 100644 --- a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/nat/NatUtil.java +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/nat/NatUtil.java @@ -8,10 +8,28 @@ package org.opendaylight.groupbasedpolicy.renderer.vpp.nat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import org.apache.commons.net.util.SubnetUtils; import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.PolicyContext; import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.parameters.ExternalIpAddressPool; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.parameters.ExternalIpAddressPoolBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.SubnetAugmentRenderer; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.subnet.AllocationPool; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.forwarding.RendererForwardingByTenant; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.forwarding.renderer.forwarding.by.tenant.RendererNetworkDomain; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev161214.NatInterfaceAugmentation; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev161214._interface.nat.attributes.Nat; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev161214._interface.nat.attributes.NatBuilder; @@ -41,4 +59,47 @@ public class NatUtil { public static InstanceIdentifier buildNatIid(InstanceIdentifier ifaceIid) { return ifaceIid.builder().augmentation(NatInterfaceAugmentation.class).child(Nat.class).build(); } + + public static List resolveDynamicNat(@Nonnull PolicyContext policyCtx) { + List rendererForwardingByTenant = + policyCtx.getPolicy().getConfiguration().getRendererForwarding().getRendererForwardingByTenant(); + Map hm = new HashMap<>(); + for (RendererForwardingByTenant rft : rendererForwardingByTenant) { + for (RendererNetworkDomain rnd : rft.getRendererNetworkDomain()) { + SubnetAugmentRenderer subnet = rnd.getAugmentation(SubnetAugmentRenderer.class); + if (subnet.getSubnet() != null && !subnet.getSubnet().isIsTenant() + && subnet.getSubnet().getAllocationPool() != null) { + for (AllocationPool pool : subnet.getSubnet().getAllocationPool()) { + if (subnet.getSubnet().getIpPrefix().getIpv4Prefix() != null) { + hm.putAll(resolveIpv4Prefix(subnet.getSubnet().getIpPrefix().getIpv4Prefix(), + pool.getFirst(), pool.getLast())); + } + } + } + } + } + List extIps = new ArrayList<>(); + for (Entry entry : hm.entrySet()) { + new ExternalIpAddressPoolBuilder().setPoolId(entry.getKey()).setExternalIpPool(entry.getValue()).build(); + } + return extIps; + } + + private static Map resolveIpv4Prefix(@Nonnull Ipv4Prefix prefix, @Nonnull String first, + @Nullable String last) { + SubnetUtils subnet = new SubnetUtils(prefix.getValue()); + Map ext = new HashMap<>(); + int min = subnet.getInfo().asInteger(first); + for (String addr : subnet.getInfo().getAllAddresses()) { + int asInt = subnet.getInfo().asInteger(addr); + if (asInt < min) { + continue; + } + ext.put(Long.valueOf(asInt), new Ipv4Prefix(addr + "/32")); + if (last == null || subnet.getInfo().asInteger(addr) > subnet.getInfo().asInteger(last)) { + break; + } + } + return ext; + } } diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/ForwardingManager.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/ForwardingManager.java index c69b82179..2120b5c0d 100644 --- a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/ForwardingManager.java +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/ForwardingManager.java @@ -333,7 +333,7 @@ public final class ForwardingManager { for (RendererForwardingByTenant fwd : cfg.getRendererForwarding().getRendererForwardingByTenant()) { List> physIfacesIid = resolvePhysicalInterfacesForNat(fwd.getRendererNetworkDomain()); - natManager.submitNatChanges(physIfacesIid, natEntries, true); + natManager.submitNatChanges(physIfacesIid, natEntries, policyCtx, true); } } } @@ -352,7 +352,7 @@ public final class ForwardingManager { for (RendererForwardingByTenant fwd : cfg.getRendererForwarding().getRendererForwardingByTenant()) { List> physIfacesIid = resolvePhysicalInterfacesForNat(fwd.getRendererNetworkDomain()); - natManager.submitNatChanges(physIfacesIid, natEntries, false); + natManager.submitNatChanges(physIfacesIid, natEntries, policyCtx, false); } } } -- 2.36.6