SNAT implementation for DVR 55/57155/43
authorMichal Cmarada <mcmarada@cisco.com>
Thu, 28 Sep 2017 07:59:44 +0000 (09:59 +0200)
committerTomas Cechvala <tcechval@cisco.com>
Tue, 3 Oct 2017 07:36:18 +0000 (07:36 +0000)
The feature is implemented in VPP renderer.
There are two implementation of SNAT:
 - centralized
 - DVR

In centralized scenario, NAT is configured on one dedicated node.
The node is the one where BVI interface is configured. All static
entries and dynamic entries are on the same node.

In DVR scenario, NAT is configured on every node where endpoints
resode. Static entries on a node are significant only to local
endpoints. There is no support for dynamic NAT yet.

Change-Id: If3c0e80b0fb1c98b85a8c8d7cbd7c25000d33238
Signed-off-by: Tomas Cechvala <tcechval@cisco.com>
Signed-off-by: Michal Cmarada <mcmarada@cisco.com>
21 files changed:
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/util/IidFactory.java
neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronFloatingIpAware.java
neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/rule/NeutronSecurityRuleAware.java
neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/util/Utils.java
neutron-mapper/src/main/resources/startup.cfg
renderers/vpp/src/main/java/org/opendaylight/controller/config/yang/config/vpp_provider/impl/VppRenderer.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/AbstractInterfaceCommand.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/LoopbackCommand.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/NatInstanceCommand.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/VhostUserCommand.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/InterfaceManager.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/flat/overlay/FlatOverlayManager.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/nat/CentralizedNatImpl.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/nat/DvrNatImpl.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/nat/NatManager.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/nat/NatUtil.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/ForwardingManager.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/VppRendererPolicyManager.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/util/VppIidFactory.java
renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/InterfaceManagerTest.java
renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/VppRendererPolicyManagerTest.java

index 531156928daf102460b6a058dccb1ae872ebfc72..df6e3baa5c41a5830e3b71c3b855663279d0d1a7 100644 (file)
@@ -111,6 +111,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.interests.followed.tenants.FollowedTenantKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.interests.followed.tenants.followed.tenant.FollowedEndpointGroup;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.interests.followed.tenants.followed.tenant.FollowedEndpointGroupKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocationKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.statistics.store.rev151215.StatisticsStore;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.statistics.store.rev151215.statistics.store.StatisticRecord;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.statistics.store.rev151215.statistics.store.StatisticRecordKey;
@@ -380,6 +381,12 @@ public class IidFactory {
             .build();
     }
 
+    public static InstanceIdentifier<AddressEndpointLocation> addressEndpointLocationIid(
+            AddressEndpointWithLocationKey key) {
+        return addressEndpointLocationIid(new AddressEndpointLocationKey(key.getAddress(), key.getAddressType(),
+                key.getContextId(), key.getContextType()));
+    }
+
     public static InstanceIdentifier<AddressEndpointLocation> addressEndpointLocationIid(
             AddressEndpointLocationKey addrEndpointLocationKey) {
         return InstanceIdentifier.builder(EndpointLocations.class)
index b63aad634f5893908d76f9499cc526d29e670b9a..2c7b97af2690dab823e0c94d9c6c867e12e43600 100644 (file)
@@ -84,23 +84,14 @@ public class NeutronFloatingIpAware implements NeutronAware<Floatingip> {
         if (oldEpIp != null && oldFloatingIp.getRouterId() != null) {
             L3ContextId routerL3ContextId = new L3ContextId(oldFloatingIp.getRouterId().getValue());
             DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
-                IidFactory.l3EndpointIid(routerL3ContextId, oldEpIp).augmentation(NatAddress.class), rwTx);
+                    IidFactory.l3EndpointIid(routerL3ContextId, oldEpIp).augmentation(NatAddress.class), rwTx);
         }
         if (epNatIp != null && newEpIp != null && newFloatingIp.getRouterId() != null) {
             L3ContextId routerL3ContextId = new L3ContextId(newFloatingIp.getRouterId().getValue());
             NatAddress nat = new NatAddressBuilder().setNatAddress(epNatIp).build();
-            AddressEndpointKey aek =
-                new AddressEndpointKey(newEpIp.getIpv4Address().getValue() + "/32", IpPrefixType.class,
-                    routerL3ContextId, L3Context.class);
-            LOG.info("Adding NAT augmentation {} for base-endpoint {}", epNatIp, aek);
-            rwTx.put(LogicalDatastoreType.OPERATIONAL, IidFactory.addressEndpointIid(aek)
-                    .augmentation(
-                        org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.NatAddress.class),
-                new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.NatAddressBuilder()
-                    .setNatAddress(epNatIp)
-                    .build(), true);
-            rwTx.put(LogicalDatastoreType.OPERATIONAL, IidFactory.l3EndpointIid(routerL3ContextId, newEpIp)
-                .augmentation(NatAddress.class), nat, true);
+            LOG.info("Adding NAT augmentation {} for endpoint (deperecated model) {}", epNatIp, newEpIp.getValue());
+            rwTx.put(LogicalDatastoreType.OPERATIONAL,
+                    IidFactory.l3EndpointIid(routerL3ContextId, newEpIp).augmentation(NatAddress.class), nat, true);
         }
     }
 
index f2626a669dbcc0b6828b07073c20a7262cfa5104..4ada5760619d5e24bc1e487c77e3896ab7be69d9 100644 (file)
@@ -125,7 +125,13 @@ public class NeutronSecurityRuleAware implements NeutronAware<SecurityRule> {
             return;
         }
         ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
-        boolean isNeutronSecurityRuleAdded = addNeutronSecurityRule(secRule, neutron, rwTx);
+        boolean isNeutronSecurityRuleAdded = true;
+        try {
+            isNeutronSecurityRuleAdded = addNeutronSecurityRule(secRule, neutron, rwTx);
+        } catch (NullPointerException e) {
+            LOG.error("Failed to process rule {}", secRule.getUuid());
+            isNeutronSecurityRuleAdded = false;
+        }
         if (isNeutronSecurityRuleAdded) {
             DataStoreHelper.submitToDs(rwTx);
         } else {
index 8ed8e580ce6dd44dacb99e54f592b27469ab7007..9647161466b3d6aabc68a1d14edd90da5c9a8420 100644 (file)
@@ -11,7 +11,6 @@ import static com.google.common.base.Preconditions.checkArgument;
 
 import java.net.Inet4Address;
 import java.net.InetAddress;
-import java.util.concurrent.ExecutionException;
 
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
@@ -27,8 +26,10 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.NatAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.NatAddressBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.UniqueId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.IpPrefixType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.L3Context;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.base.endpoints.by.ports.BaseEndpointByPort;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.floatingips.attributes.floatingips.Floatingip;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -40,6 +41,8 @@ import com.google.common.net.InetAddresses;
 
 public class Utils {
 
+    private static final String MASK_32 = "/32";
+
     private Utils() {
         throw new UnsupportedOperationException("Cannot create an instance.");
     }
@@ -107,18 +110,11 @@ public class Utils {
         IpAddress newEpIp = newFloatingIp.getFixedIpAddress();
         IpAddress epNatIp = newFloatingIp.getFloatingIpAddress();
         if (epNatIp != null && newEpIp != null) {
-            InstanceIdentifier<BaseEndpointByPort> baseEpByPortId =
-                    NeutronGbpIidFactory.baseEndpointByPortIid(new UniqueId(newFloatingIp.getPortId().getValue()));
-            Optional<BaseEndpointByPort> optional =
-                    DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, baseEpByPortId, rwTx);
-            if (!optional.isPresent()) {
-                return;
-            }
-            NatAddress nat = new NatAddressBuilder().setNatAddress(epNatIp).build();
-            AddressEndpointKey addrEpKey = new AddressEndpointKey(optional.get().getAddress(),
-                    optional.get().getAddressType(), optional.get().getContextId(), optional.get().getContextType());
+            NatAddress natAddr = new NatAddressBuilder().setNatAddress(epNatIp).build();
+            AddressEndpointKey addrEpKey = new AddressEndpointKey(newEpIp.getIpv4Address().getValue() + MASK_32,
+                    IpPrefixType.class, new ContextId(newFloatingIp.getRouterId().getValue()), L3Context.class);
             rwTx.put(LogicalDatastoreType.OPERATIONAL,
-                    IidFactory.addressEndpointIid(addrEpKey).augmentation(NatAddress.class), nat, true);
+                    IidFactory.addressEndpointIid(addrEpKey).augmentation(NatAddress.class), natAddr, true);
         }
         if (oldEpIp != null) {
             InstanceIdentifier<BaseEndpointByPort> baseEpByPortId =
@@ -140,15 +136,9 @@ public class Utils {
             // NAT augmentation should have been already removed
             return;
         }
-        InstanceIdentifier<BaseEndpointByPort> baseEpByPortId =
-                NeutronGbpIidFactory.baseEndpointByPortIid(new UniqueId(removedFloatingIp.getPortId().getValue()));
-        Optional<BaseEndpointByPort> optional =
-                DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, baseEpByPortId, rwTx);
-        if (!optional.isPresent()) {
-            return;
-        }
-        AddressEndpointKey addrEpKey = new AddressEndpointKey(optional.get().getAddress(),
-                optional.get().getAddressType(), optional.get().getContextId(), optional.get().getContextType());
+        AddressEndpointKey addrEpKey =
+                new AddressEndpointKey(removedFloatingIp.getFixedIpAddress().getIpv4Address().getValue() + MASK_32,
+                        IpPrefixType.class, new ContextId(removedFloatingIp.getRouterId().getValue()), L3Context.class);
         rwTx.delete(LogicalDatastoreType.OPERATIONAL,
                 IidFactory.addressEndpointIid(addrEpKey).augmentation(NatAddress.class));
     }
index fc415ec3c644fee182937f5eef8dcc1173d51cc9..6ba246d09e2f6edfe3c4384a4cb1899f342d7f8f 100644 (file)
@@ -6,8 +6,8 @@
 # To explicitly specify which IP prefix should be used for metadata
 # service in openstack, uncomment and modify following line.
 # Specifying one IP for metadata service is currently supported.
-metadata-ip = 169.254.169.254
+#metadata-ip = 169.254.169.254
 
 # To explicitly specify which port should be used for metadata
 # service in openstack, uncomment and modify following line.
-metadata-port = 80
+#metadata-port = 80
index 31a461d99259dd0b47ead871c29dc5d2d06f1194..47c1cd33e8de385ab63498826a9bc969fb86c426 100644 (file)
@@ -24,6 +24,7 @@ import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFaile
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
 import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.api.BridgeDomainManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.config.ConfigUtil;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.dhcp.DhcpRelayHandler;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.InterfaceManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.LispStateManager;
@@ -35,6 +36,8 @@ import org.opendaylight.groupbasedpolicy.renderer.vpp.listener.RendererPolicyLis
 import org.opendaylight.groupbasedpolicy.renderer.vpp.listener.VppEndpointListener;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.listener.VppNodeListener;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.manager.VppNodeManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.nat.CentralizedNatImpl;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.nat.DvrNatImpl;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.nat.NatManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.BridgeDomainManagerImpl;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.ForwardingManager;
@@ -153,7 +156,10 @@ public class VppRenderer implements AutoCloseable, BindingAwareProvider {
 
         interfaceManager = new InterfaceManager(mountDataProvider, dataBroker, flatOverlayManager);
         AclManager aclManager = new AclManager(mountDataProvider, interfaceManager);
-        NatManager natManager = new NatManager(dataBroker, mountDataProvider);
+        NatManager natManager =
+            (ConfigUtil.getInstance().isL3FlatEnabled()) ? new DvrNatImpl(dataBroker) : new CentralizedNatImpl(
+                dataBroker);
+        LOG.info("Instantiated NAT manager implementation {}", natManager.getClass());
         subnetEventManager = new GbpSubnetEventManager(loopbackManager);
         dtoEventBus.register(interfaceManager);
         dtoEventBus.register(subnetEventManager);
@@ -163,7 +169,8 @@ public class VppRenderer implements AutoCloseable, BindingAwareProvider {
         ForwardingManager fwManager =
                 new ForwardingManager(interfaceManager, aclManager, natManager, routingManager, bdManager,
                         lispStateManager, loopbackManager, flatOverlayManager, dhcpRelayHandler, dataBroker);
-        VppRendererPolicyManager vppRendererPolicyManager = new VppRendererPolicyManager(fwManager, aclManager, dataBroker);
+        VppRendererPolicyManager vppRendererPolicyManager =
+            new VppRendererPolicyManager(fwManager, aclManager, dataBroker);
         dtoEventBus.register(vppRendererPolicyManager);
 
         vppNodeListener = new VppNodeListener(dataBroker, vppNodeManager, dtoEventBus);
index 593945b9d565f37a245da26e0b87e11f3407c44b..3e83559fef0a91900a30e30f4262224899630e5a 100644 (file)
@@ -16,7 +16,6 @@ import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;
 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.interfaces.rev140508.interfaces.InterfaceBuilder;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.proxy.arp.rev170315.ProxyArpInterfaceAugmentation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.proxy.arp.rev170315.ProxyArpInterfaceAugmentationBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.proxy.arp.rev170315.interfaces._interface.ProxyArpBuilder;
@@ -35,6 +34,8 @@ public abstract class AbstractInterfaceCommand implements ConfigCommand, Interfa
     protected Boolean enabled;
     protected Boolean enableProxyArp;
     protected Long vrfId;
+    protected Boolean snatEnabled;
+
 
     public General.Operations getOperation() {
         return operation;
@@ -61,6 +62,10 @@ public abstract class AbstractInterfaceCommand implements ConfigCommand, Interfa
         return bridgeDomain;
     }
 
+    public boolean isSnatEnabled() {
+        return snatEnabled;
+    }
+
     public void execute(ReadWriteTransaction rwTx) {
         switch (getOperation()) {
             case PUT:
@@ -102,7 +107,7 @@ public abstract class AbstractInterfaceCommand implements ConfigCommand, Interfa
     }
 
     protected void addEnableProxyArpAugmentation(InterfaceBuilder interfaceBuilder) {
-        if (enableProxyArp != null) {
+        if (enableProxyArp != null && enableProxyArp) {
             ProxyArpInterfaceAugmentationBuilder augmentationBuilder = new ProxyArpInterfaceAugmentationBuilder();
             augmentationBuilder.setProxyArp((new ProxyArpBuilder()).build());
             interfaceBuilder.addAugmentation(ProxyArpInterfaceAugmentation.class, augmentationBuilder.build());
index 3208d71144cbc15dfff7c2eecf183643ed633aed..6266ef7d6823438744330b43641d6710842fea31 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.groupbasedpolicy.renderer.vpp.commands;
 
 import java.util.Collections;
 
+import org.opendaylight.groupbasedpolicy.renderer.vpp.config.ConfigUtil;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General.Operations;
 import org.opendaylight.groupbasedpolicy.util.NetUtils;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
@@ -87,8 +88,11 @@ public class LoopbackCommand extends AbstractInterfaceCommand {
                 .setDescription(description)
                 .setType(Loopback.class)
                 .setName(name)
-                .setLinkUpDownTrapEnable(Interface.LinkUpDownTrapEnable.Enabled)
-                .addAugmentation(NatInterfaceAugmentation.class, buildInboundNatAugmentation());
+                .setLinkUpDownTrapEnable(Interface.LinkUpDownTrapEnable.Enabled);
+
+        if (!ConfigUtil.getInstance().isL3FlatEnabled()) {
+            interfaceBuilder.addAugmentation(NatInterfaceAugmentation.class, buildInboundNatAugmentation());
+        }
 
         // Create the Loopback augmentation
         VppInterfaceAugmentationBuilder
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/NatInstanceCommand.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/NatInstanceCommand.java
new file mode 100644 (file)
index 0000000..79ec3a8
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.vpp.commands;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
+
+import javax.annotation.Nonnull;
+
+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.util.General;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;
+import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.NatInstances;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.NatInstancesBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.NatInstance;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.NatInstanceBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.MappingTable;
+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.yangtools.yang.binding.InstanceIdentifier;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+
+public class NatInstanceCommand extends AbstractConfigCommand {
+
+    private final General.Operations operation;
+    private final List<ExternalIpAddressPool> dynamicEntries;
+    private final Map<Long, List<MappingEntryBuilder>> staticEntries;
+    private final Long DEFAULT_FIB = 0L;
+
+    public NatInstanceCommand(NatInstanceCommandBuilder builder) {
+        operation = builder.getOperation();
+        dynamicEntries = builder.getDynamicEntries();
+        staticEntries = builder.getStaticEntries();
+    }
+
+    public General.Operations getOperation() {
+        return operation;
+    }
+
+    public List<ExternalIpAddressPool> getDynamicEntries() {
+        return dynamicEntries;
+    }
+
+    public Map<Long, List<MappingEntryBuilder>> getStaticEntries() {
+        return staticEntries;
+    }
+
+    public List<MappingEntryBuilder> getStaticEntries(long fibId) {
+        if (staticEntries == null) {
+            return Collections.emptyList();
+        }
+        return staticEntries.get(fibId);
+    }
+
+    @Override
+    public InstanceIdentifier<NatInstances> getIid() {
+        return VppIidFactory.getNatInstancesIid();
+    }
+
+    @Override
+    void put(ReadWriteTransaction rwTx) {
+        rwTx.put(LogicalDatastoreType.CONFIGURATION, getIid(), buildNatInstances(), true);
+    }
+
+    @Override
+    void merge(ReadWriteTransaction rwTx) {
+        rwTx.merge(LogicalDatastoreType.CONFIGURATION, getIid(), buildNatInstances(), true);
+    }
+
+    @Override
+    void delete(ReadWriteTransaction rwTx) {
+        DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION, getIid(), rwTx);
+    }
+
+    private NatInstances buildNatInstances() {
+        List<NatInstance> instances = Lists.newArrayList();
+        NatInstanceBuilder builder = new NatInstanceBuilder();
+        builder.setId(DEFAULT_FIB).setExternalIpAddressPool(this.getDynamicEntries());
+        if (getStaticEntries().keySet().contains(DEFAULT_FIB)) {
+            addStaticEntries(builder, getStaticEntries().get(DEFAULT_FIB));
+            getStaticEntries().remove(DEFAULT_FIB);
+        }
+        instances.add(builder.build());
+        builder.setExternalIpAddressPool(null);
+        instances.addAll(getStaticEntries().entrySet().stream().map(entry -> {
+            builder.setId(entry.getKey());
+            addStaticEntries(builder, getStaticEntries().get(entry.getKey()));
+            return builder.build();
+        }).collect(Collectors.toList()));
+        return new NatInstancesBuilder().setNatInstance(instances).build();
+    }
+
+    private void addStaticEntries(@Nonnull NatInstanceBuilder builder,
+            @Nonnull List<MappingEntryBuilder> staticEntries) {
+        builder.setMappingTable(null);
+        AtomicInteger ai = new AtomicInteger();
+        List<MappingEntry> mappingEntries = staticEntries.stream().map(me -> {
+            int value = ai.get();
+            ai.incrementAndGet();
+            return me.setIndex((long) value).build();
+        }).collect(Collectors.toList());
+        MappingTable mappingTable = new MappingTableBuilder().setMappingEntry(mappingEntries).build();
+        builder.setMappingTable(mappingTable);
+    }
+
+    @Override
+    public String toString() {
+        StringBuffer stringBuffer = new StringBuffer();
+        stringBuffer.append("NatInstanceCommand [operations=")
+            .append(operation)
+            .append(", dynamicEntries=")
+            .append(Arrays.toString(dynamicEntries.toArray()))
+            .append(", staticEntries= [");
+
+        staticEntries.forEach((aLong, mappingEntryBuilders) -> {
+            stringBuffer.append("VrfId= ").append(aLong).append(", mappingEntries= [");
+            mappingEntryBuilders.forEach(
+                    mappingEntryBuilder -> stringBuffer.append(mappingEntryBuilder.build().toString()).append(", "));
+            stringBuffer.append("]");
+        });
+        stringBuffer.append("]");
+
+        return stringBuffer.toString();
+    }
+
+    public static class NatInstanceCommandBuilder {
+
+        private General.Operations operation;
+        private List<ExternalIpAddressPool> dynamicEntries;
+        private Map<Long, List<MappingEntryBuilder>> staticEntries;
+
+        public NatInstanceCommandBuilder setOperation(General.Operations operation) {
+            this.operation = operation;
+            return this;
+        }
+
+        public NatInstanceCommandBuilder setDynamicEntries(List<ExternalIpAddressPool> dynamicEntries) {
+            this.dynamicEntries = dynamicEntries;
+            return this;
+        }
+
+        public NatInstanceCommandBuilder setStaticEntries(Map<Long, List<MappingEntryBuilder>> staticEntries) {
+            this.staticEntries = staticEntries;
+            return this;
+        }
+
+        public NatInstanceCommandBuilder setStaticEntries(Long fibId, List<MappingEntryBuilder> staticEntries) {
+            if (staticEntries == null) {
+                this.staticEntries = new HashMap<Long, List<MappingEntryBuilder>>();
+            }
+            this.staticEntries.put(fibId, staticEntries);
+            return this;
+        }
+
+        public General.Operations getOperation() {
+            return operation;
+        }
+
+        public List<ExternalIpAddressPool> getDynamicEntries() {
+            return dynamicEntries;
+        }
+
+        public Map<Long, List<MappingEntryBuilder>> getStaticEntries() {
+            return staticEntries;
+        }
+
+        public List<MappingEntryBuilder> getStaticEntries(long fibId) {
+            if (staticEntries == null) {
+                return Collections.emptyList();
+            }
+            return staticEntries.get(Long.valueOf(fibId));
+        }
+
+        public NatInstanceCommand build() {
+            Preconditions.checkNotNull(operation, "Operation of NAT command not specified.");
+            if (staticEntries == null) {
+                staticEntries = new HashMap<Long, List<MappingEntryBuilder>>();
+            }
+            if (dynamicEntries == null) {
+                dynamicEntries = Lists.newArrayList();
+            }
+            return new NatInstanceCommand(this);
+        }
+
+        @Override
+        public String toString() {
+            return build().toString();
+        }
+    }
+}
index 7ff1648dc12902311eaf527ae5d60dbcb3e2426e..5ec2b6f4c649b5b56c702a2c90551572a4e86429 100644 (file)
@@ -10,11 +10,18 @@ package org.opendaylight.groupbasedpolicy.renderer.vpp.commands;
 
 import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
+
+import org.opendaylight.groupbasedpolicy.renderer.vpp.config.ConfigUtil;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General.Operations;
 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.interfaces.rev140508.interfaces.InterfaceBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev170816.NatInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev170816.NatInterfaceAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev170816._interface.nat.attributes.Nat;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev170816._interface.nat.attributes.NatBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev170816._interface.nat.attributes.nat.InboundBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.VhostUserRole;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.VppInterfaceAugmentation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.VppInterfaceAugmentationBuilder;
@@ -34,6 +41,7 @@ public class VhostUserCommand extends AbstractInterfaceCommand {
         this.socket = builder.getSocket();
         this.role = builder.getRole();
         this.enabled = builder.isEnabled();
+        this.snatEnabled = builder.isSnatEnabled();
         this.description = builder.getDescription();
         this.bridgeDomain = builder.getBridgeDomain();
         this.enableProxyArp = builder.getEnableProxyArp();
@@ -55,13 +63,13 @@ public class VhostUserCommand extends AbstractInterfaceCommand {
     @Override
     public InterfaceBuilder getInterfaceBuilder() {
         InterfaceBuilder interfaceBuilder =
-                new InterfaceBuilder().setKey(new InterfaceKey(name))
-                        .setEnabled(enabled)
-                        .setDescription(description)
-                        .setType(
-                            org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.VhostUser.class)
-                        .setName(name)
-                        .setLinkUpDownTrapEnable(Interface.LinkUpDownTrapEnable.Enabled);
+            new InterfaceBuilder().setKey(new InterfaceKey(name))
+                .setEnabled(enabled)
+                .setDescription(description)
+                .setType(
+                    org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.VhostUser.class)
+                .setName(name)
+                .setLinkUpDownTrapEnable(Interface.LinkUpDownTrapEnable.Enabled);
 
         // Create the vhost augmentation
         VppInterfaceAugmentationBuilder vppAugmentationBuilder = new VppInterfaceAugmentationBuilder()
@@ -75,7 +83,13 @@ public class VhostUserCommand extends AbstractInterfaceCommand {
             vppAugmentationBuilder.setL2(new L2Builder()
                     .setInterconnection(new BridgeBasedBuilder().setBridgeDomain(bridgeDomain).build()).build());
         }
-
+        if (snatEnabled) {
+            Nat nat = new NatBuilder().setInbound(new InboundBuilder()
+                    .setNat44Support(true)
+                    .setPostRouting(ConfigUtil.getInstance().isL3FlatEnabled()).build()).build();
+            interfaceBuilder.addAugmentation(NatInterfaceAugmentation.class,
+                    new NatInterfaceAugmentationBuilder().setNat(nat).build());
+        }
         interfaceBuilder.addAugmentation(VppInterfaceAugmentation.class, vppAugmentationBuilder.build());
         addEnableProxyArpAugmentation(interfaceBuilder);
         return interfaceBuilder;
@@ -85,7 +99,8 @@ public class VhostUserCommand extends AbstractInterfaceCommand {
     public String toString() {
         return "VhostUserCommand [socket=" + socket + ", role=" + role + ", bridgeDomain=" + bridgeDomain
                 + ", operation=" + operation + ", name=" + name + ", description=" + description + ", enabled="
-                + enabled + "]";
+                + enabled + ", enableProxyArp=" + enableProxyArp + ", vrfId=" + vrfId + ", snatEnabled=" + snatEnabled
+            + "]";
     }
 
     public static class VhostUserCommandBuilder {
@@ -99,6 +114,7 @@ public class VhostUserCommand extends AbstractInterfaceCommand {
         private String bridgeDomain;
         private Boolean enableProxyArp;
         private Long vrfId;
+        private boolean snatEnabled;
 
         public String getName() {
             return name;
@@ -145,6 +161,15 @@ public class VhostUserCommand extends AbstractInterfaceCommand {
             return this;
         }
 
+        boolean isSnatEnabled() {
+            return snatEnabled;
+        }
+
+        public VhostUserCommandBuilder setSnatEnabled(boolean snatEnabled) {
+            this.snatEnabled = snatEnabled;
+            return this;
+        }
+
         public String getDescription() {
             return description;
         }
@@ -195,4 +220,4 @@ public class VhostUserCommand extends AbstractInterfaceCommand {
             return new VhostUserCommand(this);
         }
     }
-}
\ No newline at end of file
+}
index 5a0d25cce602d76eedc0acf3be002af48126a79c..14bc6978dbb34cb7ebe1692d82cf47fa70c79694 100644 (file)
@@ -320,11 +320,10 @@ public class InterfaceManager implements AutoCloseable {
             builder.setSocket(socket);
             builder.setRole(VhostUserRole.Client);
         }
-
         if (ConfigUtil.getInstance().isL3FlatEnabled()) {
             builder.setEnableProxyArp(true);
+            builder.setSnatEnabled(true);
         }
-
         VhostUserCommand vhostUserCommand =
                 builder.setOperation(operations).setDescription(vppEp.getDescription()).build();
         return Optional.of(vhostUserCommand);
index b7433c20970676f84bb7b2cf785bff6d4cd8673d..da8181f9dd4daa17b6ed3266b8ded9122c6dec46 100644 (file)
@@ -347,7 +347,9 @@ public class FlatOverlayManager {
         }
     }
 
-    private long getVni(String tenantUuid) {
-        return neutronTenantToVniMapper.getVni(tenantUuid);
+    public long getVni(String tenantUuid) {
+        long vni = neutronTenantToVniMapper.getVni(tenantUuid);
+        LOG.debug("Debugging: getVni {} = {}", tenantUuid, vni);
+        return vni;
     }
 }
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/nat/CentralizedNatImpl.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/nat/CentralizedNatImpl.java
new file mode 100644 (file)
index 0000000..e75e2e5
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.vpp.nat;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.NatInstanceCommand;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.NatInstanceCommand.NatInstanceCommandBuilder;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.PolicyContext;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.GbpNetconfTransaction;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General.Operations;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;
+import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
+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.vpp_renderer.rev160425.Config;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes._interface.type.choice.LoopbackCase;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Table;
+
+public class CentralizedNatImpl extends NatManager {
+
+    private NodeId routingNode = null;
+    private static final Logger LOG = LoggerFactory.getLogger(CentralizedNatImpl.class);
+    private static final long DEFAULT_FIB = 0L;
+
+    public CentralizedNatImpl(DataBroker dataBroker) {
+        super(dataBroker);
+    }
+
+    @Override
+    void submit(NatInstanceCommandBuilder builder, NodeId nodeId) {
+        NatInstanceCommand nat = builder.build();
+        switch (nat.getOperation()) {
+            case MERGE:
+            case PUT:
+                GbpNetconfTransaction.netconfSyncedWrite(VppIidFactory.getNetconfNodeIid(nodeId), nat,
+                        GbpNetconfTransaction.RETRY_COUNT);
+                break;
+            case DELETE:
+                GbpNetconfTransaction.netconfSyncedDelete(VppIidFactory.getNetconfNodeIid(nodeId), nat,
+                        GbpNetconfTransaction.RETRY_COUNT);
+                break;
+        }
+    }
+
+    @Override
+    public List<NodeId> resolveNodesForSnat() {
+        if (routingNode == null) {
+            ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();
+            Optional<Config> cfg = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
+                    VppIidFactory.getVppRendererConfig(), rTx);
+            rTx.close();
+            if (!cfg.isPresent() || cfg.get().getVppEndpoint() == null) {
+                return Collections.emptyList();
+            } ;
+            java.util.Optional<NodeId> nodeId = cfg.get()
+                .getVppEndpoint()
+                .stream()
+                .filter(vppEp -> vppEp.getInterfaceTypeChoice() instanceof LoopbackCase)
+                .filter(vppEp -> ((LoopbackCase) vppEp.getInterfaceTypeChoice()).isBvi() != null)
+                .filter(vppEp -> ((LoopbackCase) vppEp.getInterfaceTypeChoice()).isBvi())
+                .map(vppEp -> vppEp.getVppNodeId())
+                .findFirst();
+            if (!nodeId.isPresent()) {
+                return Collections.emptyList();
+            }
+            routingNode = nodeId.get();
+        }
+        LOG.debug("Resolved node for SNAT: {}", routingNode);
+        return ImmutableList.of(routingNode);
+    }
+
+    @Override public Map<NodeId, NatInstanceCommandBuilder> staticEntries(
+        Table<NodeId, Long, List<MappingEntryBuilder>> staticEntries) {
+        NatInstanceCommandBuilder builder = new NatInstanceCommandBuilder();
+        builder.setOperation(General.Operations.PUT);
+        staticEntries.rowKeySet().forEach(nodeId -> {
+            builder.setStaticEntries(staticEntries.row(nodeId)
+                .entrySet()
+                .stream()
+                .collect(Collectors.toMap(x -> DEFAULT_FIB, y -> y.getValue())));
+        });
+        Map<NodeId, NatInstanceCommandBuilder> result = new HashMap<>();
+        resolveNodesForSnat().forEach(nodeId -> {
+            result.put(nodeId, builder);
+            LOG.debug("Resolved static NAT entries for node {}: {}", nodeId, builder.toString());
+        });
+        return result;
+    }
+
+    @Override
+    public void dynamicEntries(PolicyContext ctx, Map<NodeId, NatInstanceCommandBuilder> nodeBuilders) {
+        List<MappingEntryBuilder> collect = nodeBuilders.values()
+            .stream()
+            .filter(natInstCmdBldr -> natInstCmdBldr.getStaticEntries() != null)
+            .map(natInstCmdBldr -> natInstCmdBldr.getStaticEntries().values())
+            .flatMap(mappingEntryBldr -> mappingEntryBldr.stream())
+            .flatMap(mappingEntryBldr -> mappingEntryBldr.stream())
+            .collect(Collectors.toList());
+        List<ExternalIpAddressPool> dynamicEntries = NatUtil.resolveDynamicNat(ctx, collect);
+        LOG.info("Resolved dynamic NAT entries in cfg version {} for node {}: {}", ctx.getPolicy().getVersion(),
+                routingNode, dynamicEntries);
+        if (routingNode != null && nodeBuilders.get(routingNode) != null) {
+            nodeBuilders.get(routingNode).setDynamicEntries(dynamicEntries);
+            return;
+        } else if (routingNode != null) {
+            nodeBuilders.put(routingNode,
+                    new NatInstanceCommandBuilder().setOperation(Operations.PUT).setDynamicEntries(dynamicEntries));
+        }
+    }
+
+    @Override
+    Logger getLogger() {
+        return LOG;
+    }
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/nat/DvrNatImpl.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/nat/DvrNatImpl.java
new file mode 100644 (file)
index 0000000..71bbd7f
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.vpp.nat;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.NatInstanceCommand;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.NatInstanceCommand.NatInstanceCommandBuilder;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.PolicyContext;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.GbpNetconfTransaction;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;
+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.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.renderers.renderer.renderer.nodes.renderer.node.PhysicalInterface;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Table;
+
+public class DvrNatImpl extends NatManager {
+
+    public DvrNatImpl(DataBroker dataBroker) {
+        super(dataBroker);
+    }
+
+    private static final Logger LOG = LoggerFactory.getLogger(DvrNatImpl.class);
+
+    @Override
+    void submit(NatInstanceCommandBuilder builder, NodeId nodeId) {
+        NatInstanceCommand nat = builder.build();
+        switch (nat.getOperation()) {
+            case MERGE:
+            case PUT:
+                GbpNetconfTransaction.netconfSyncedWrite(VppIidFactory.getNetconfNodeIid(nodeId), nat,
+                        GbpNetconfTransaction.RETRY_COUNT);
+                break;
+            case DELETE:
+                GbpNetconfTransaction.netconfSyncedDelete(VppIidFactory.getNetconfNodeIid(nodeId), nat,
+                        GbpNetconfTransaction.RETRY_COUNT);
+                break;
+        }
+    }
+
+    @Override
+    public List<NodeId> resolveNodesForSnat() {
+        ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();
+        List<InstanceIdentifier<PhysicalInterface>> intfcs = NatUtil.resolvePhysicalInterface(rTx);
+        rTx.close();
+        return intfcs.stream().map(NatUtil.resolveNodeId::apply).collect(Collectors.toList());
+    }
+
+    @Override
+    public Map<NodeId, NatInstanceCommandBuilder> staticEntries(
+            Table<NodeId, Long, List<MappingEntryBuilder>> staticEntries) {
+        Map<NodeId, NatInstanceCommandBuilder> result = new HashMap<>();
+        List<NodeId> nodes = resolveNodesForSnat();
+        staticEntries.rowKeySet().forEach(nodeId -> {
+            NatInstanceCommandBuilder builder = new NatInstanceCommandBuilder()
+                .setOperation(General.Operations.PUT)
+                .setStaticEntries(staticEntries.row(nodeId));
+            if (nodes.contains(nodeId)) {
+                result.put(nodeId, builder);
+                LOG.debug("Resolved static NAT entries for node {}, NatEntries: {}.", nodeId, builder.toString());
+            }
+        });
+        return result;
+    }
+
+    @Override
+    public void dynamicEntries(PolicyContext ctx, Map<NodeId, NatInstanceCommandBuilder> nodeBuilders) {
+        LOG.info("No dynamic SNAT entries resolved, not supported yet.");
+    }
+
+    @Override
+    Logger getLogger() {
+        return LOG;
+    }
+}
index 8b1126b50c42e00698bfaddb4dd763247cf5223c..ef01eb3793d8c3409e9edbfbc23fe750684e26ac 100644 (file)
 \r
 package org.opendaylight.groupbasedpolicy.renderer.vpp.nat;\r
 \r
-import java.net.Inet4Address;\r
-import java.net.Inet6Address;\r
-import java.net.InetAddress;\r
-import java.net.UnknownHostException;\r
+import java.util.Collections;\r
 import java.util.List;\r
-import java.util.concurrent.atomic.AtomicInteger;\r
+import java.util.Map;\r
+import java.util.Set;\r
 import java.util.stream.Collectors;\r
 \r
+import javax.annotation.Nonnull;\r
 import javax.annotation.Nullable;\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.common.api.data.LogicalDatastoreType;\r
+import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.NatInstanceCommand;\r
+import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.NatInstanceCommand.NatInstanceCommandBuilder;\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.General;\r
 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;\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.Ipv4Address;\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.NatInstance;\r
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.NatInstanceBuilder;\r
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.MappingTable;\r
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.MappingTableBuilder;\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.renderer.nodes.RendererNode;\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.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCase;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.NatAddressRenderer;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.Endpoints;\r
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;\r
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;\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.base.Function;\r
+import com.google.common.collect.Sets;\r
+import com.google.common.collect.Table;\r
 \r
-public class NatManager {\r
+public abstract class NatManager {\r
 \r
-    private static final Logger LOG = LoggerFactory.getLogger(NatManager.class);\r
+    protected final DataBroker dataBroker;\r
 \r
-    private final Long id;\r
-    private final DataBroker dataBroker;\r
-    private final MountedDataBrokerProvider mountDataProvider;\r
-\r
-    public NatManager(DataBroker dataBroker, MountedDataBrokerProvider mountDataProvider) {\r
-        this.id = 0L;\r
+    public NatManager(DataBroker dataBroker) {\r
         this.dataBroker = dataBroker;\r
-        this.mountDataProvider = mountDataProvider;\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
-                internalIp = new IpAddress(new Ipv4Address(internal));\r
-            } else if (inetAddr instanceof Inet6Address) {\r
-                internalIp = new IpAddress(new Ipv6Address(internal));\r
-            }\r
-        } catch (UnknownHostException e) {\r
-            LOG.error("Cannot resolve host IP {}. {}", internal, e.getMessage());\r
-            return Optional.absent();\r
-        }\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
+    abstract Logger getLogger();\r
+\r
+    abstract void submit(NatInstanceCommandBuilder nat, NodeId nodeId);\r
+\r
+    public abstract List<NodeId> resolveNodesForSnat();\r
+\r
+    abstract public Map<NodeId, NatInstanceCommandBuilder> staticEntries(\r
+            Table<NodeId, Long, List<MappingEntryBuilder>> staticEntries);\r
+\r
+    public abstract void dynamicEntries(PolicyContext ctx, Map<NodeId, NatInstanceCommandBuilder> nodeBuilders);\r
+\r
+    public void clearNodes(@Nonnull Endpoints before, @Nullable Endpoints after) {\r
+        Function<Endpoints, Set<NodeId>> f = x -> {\r
+            return nullToEmpty(x.getAddressEndpointWithLocation()).stream()\r
+                .filter(ep -> ep.getAugmentation(NatAddressRenderer.class) != null)\r
+                .filter(ep -> ep.getAbsoluteLocation() != null)\r
+                .map(ep -> (ExternalLocationCase) ep.getAbsoluteLocation().getLocationType())\r
+                .filter(loc -> loc.getExternalNodeMountPoint() != null)\r
+                .map(loc -> loc.getExternalNodeMountPoint().firstKeyOf(Node.class).getNodeId())\r
+                .collect(Collectors.toSet());\r
+        };\r
+        Set<NodeId> nodesToClear = (after != null) ? Sets.difference(f.apply(before), f.apply(after)) : f.apply(before);\r
+        NatInstanceCommand natCmd = new NatInstanceCommandBuilder().setOperation(General.Operations.DELETE).build();\r
+        getLogger().info("Clearing NAT from nodes {}", nodesToClear);\r
+        nodesToClear.forEach(nodeId -> GbpNetconfTransaction\r
+            .netconfSyncedDelete(VppIidFactory.getNetconfNodeIid(nodeId), natCmd, GbpNetconfTransaction.RETRY_COUNT));\r
     }\r
 \r
-    public void submitNatChanges(final List<InstanceIdentifier<PhysicalInterface>> physIfacesIid,\r
-                                 final @Nullable List<MappingEntryBuilder> sNatEntries,\r
-                                 final PolicyContext policyCtx,\r
-                                 final boolean add) {\r
-        if (sNatEntries == null) {\r
-            LOG.trace("No static NAT entries to submit");\r
-        } else{\r
-            LOG.trace("Preparing to submit NAT changes {} on physical interfaces", sNatEntries.toArray(), physIfacesIid);\r
-        }\r
-        for (InstanceIdentifier<PhysicalInterface> iidPhysIface : physIfacesIid) {\r
-            InstanceIdentifier<Node> nodeIid = (InstanceIdentifier<Node>) iidPhysIface.firstKeyOf(RendererNode.class).getNodePath();\r
-            String phInterfaceName = iidPhysIface.firstKeyOf(PhysicalInterface.class).getInterfaceName();\r
-            InstanceIdentifier<Interface> interfaceIID =\r
-                VppIidFactory.getInterfaceIID(new InterfaceKey(phInterfaceName));\r
-\r
-            Optional<Interface> readIface =\r
-                GbpNetconfTransaction.read(nodeIid, LogicalDatastoreType.CONFIGURATION, interfaceIID,\r
-                    GbpNetconfTransaction.RETRY_COUNT);\r
-\r
-            if (!readIface.isPresent()) {\r
-                LOG.error("Interface {} not found on mount point {}", phInterfaceName, nodeIid);\r
-                continue;\r
-            }\r
-            if (add) {\r
-                NatInstance natInstance =\r
-                    buildNatInstance(sNatEntries, NatUtil.resolveDynamicNat(policyCtx, sNatEntries));\r
-                GbpNetconfTransaction.netconfSyncedWrite(nodeIid,\r
-                    VppIidFactory.getNatInstanceIid(id), natInstance, GbpNetconfTransaction.RETRY_COUNT);\r
-            } else {\r
-                if (GbpNetconfTransaction.read(nodeIid, LogicalDatastoreType.CONFIGURATION,\r
-                    VppIidFactory.getNatInstanceIid(id), GbpNetconfTransaction.RETRY_COUNT).isPresent()) {\r
-                    GbpNetconfTransaction.netconfSyncedDelete(nodeIid,\r
-                        VppIidFactory.getNatInstanceIid(id), GbpNetconfTransaction.RETRY_COUNT);\r
-                }\r
-            }\r
-        }\r
+    private <T> List<T> nullToEmpty(@Nullable List<T> list) {\r
+        return list == null ? Collections.emptyList() : list;\r
     }\r
 \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
-            ai.incrementAndGet();\r
-            return me.setIndex((long) value).build();\r
-        }).collect(Collectors.toList());\r
-        MappingTable mappingTable = new MappingTableBuilder().setMappingEntry(mappingEntries).build();\r
-        return new NatInstanceBuilder()\r
-            .setId(id)\r
-            .setExternalIpAddressPool(poolEntries)\r
-            .setMappingTable(mappingTable)\r
-            .build();\r
+    public void submitNatChanges(Map<NodeId, NatInstanceCommandBuilder> nat) {\r
+        nat.keySet().forEach(nodeId -> {\r
+            submit(nat.get(nodeId), nodeId);\r
+        });\r
     }\r
 }\r
index 1bc3b7d9fc9d0d13d9f42d7421a78077ce2d7f46..198cfb34c5dc0743d7971e4e5a5b14f52d5158d8 100644 (file)
@@ -8,11 +8,16 @@
 \r
 package org.opendaylight.groupbasedpolicy.renderer.vpp.nat;\r
 \r
+import java.net.Inet4Address;\r
+import java.net.Inet6Address;\r
+import java.net.InetAddress;\r
+import java.net.UnknownHostException;\r
 import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Collections;\r
 import java.util.HashMap;\r
 import java.util.List;\r
 import java.util.Map;\r
-import java.util.Map.Entry;\r
 import java.util.stream.Collectors;\r
 \r
 import javax.annotation.Nonnull;\r
@@ -22,27 +27,28 @@ import org.apache.commons.net.util.SubnetUtils;
 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;\r
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;\r
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;\r
+import org.opendaylight.groupbasedpolicy.renderer.vpp.config.ConfigUtil;\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.VppIidFactory;\r
 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;\r
 import org.opendaylight.groupbasedpolicy.util.NetUtils;\r
 import org.opendaylight.vbd.impl.transaction.VbdNetconfTransaction;\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;\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.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.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.parameters.ExternalIpAddressPoolBuilder;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.SubnetAugmentRenderer;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.has.subnet.Subnet;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.has.subnet.subnet.AllocationPool;\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.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.forwarding.RendererForwardingByTenant;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.forwarding.renderer.forwarding.by.tenant.RendererNetworkDomain;\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
@@ -57,16 +63,37 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;\r
 import org.slf4j.LoggerFactory;\r
 \r
-import com.google.common.annotations.VisibleForTesting;\r
+import com.google.common.base.Function;\r
 import com.google.common.base.Optional;\r
+import com.google.common.base.Preconditions;\r
+import com.google.common.collect.ImmutableList;\r
 \r
 public class NatUtil {\r
     private static final Logger LOG = LoggerFactory.getLogger(NatUtil.class);\r
 \r
+    @SuppressWarnings("unchecked")\r
+    static Function<InstanceIdentifier<PhysicalInterface>, NodeId> resolveNodeId = (intf) -> {\r
+        return Preconditions\r
+            .checkNotNull(checkIid(intf).firstKeyOf(RendererNode.class).getNodePath().firstKeyOf(Node.class))\r
+            .getNodeId();\r
+    };\r
+\r
+    @SuppressWarnings("unchecked")\r
+    static Function<InstanceIdentifier<PhysicalInterface>, InstanceIdentifier<Interface>> resolveInterfaceIid = (intf) -> {\r
+        checkIid(intf);\r
+        return VppIidFactory\r
+            .getInterfaceIID(new InterfaceKey(checkIid(intf).firstKeyOf(PhysicalInterface.class).getInterfaceName()));\r
+    };\r
+\r
+    static private InstanceIdentifier<PhysicalInterface> checkIid(InstanceIdentifier<PhysicalInterface> iid) {\r
+        Preconditions.checkNotNull(iid.firstKeyOf(RendererNode.class).getNodePath().firstKeyOf(Node.class));\r
+        return iid;\r
+    }\r
+\r
     public void setInboundInterface(Interface iface, WriteTransaction wTx) {\r
         InstanceIdentifier<Nat> natIid = buildNatIid(VppIidFactory.getInterfaceIID(iface.getKey()));\r
         Nat nat =\r
-            new NatBuilder().setInbound(new InboundBuilder().setNat44Support(true).setPostRouting(false).build())\r
+            new NatBuilder().setInbound(new InboundBuilder().setNat44Support(true).setPostRouting(ConfigUtil.getInstance().isL3FlatEnabled()).build())\r
                 .build();\r
         wTx.put(LogicalDatastoreType.CONFIGURATION, natIid, nat);\r
     }\r
@@ -74,7 +101,7 @@ public class NatUtil {
     public static void setOutboundInterface(Interface iface, InstanceIdentifier<Node> vppIid) {\r
         InstanceIdentifier<Nat> natIid = buildNatIid(VppIidFactory.getInterfaceIID(iface.getKey()));\r
         Nat nat =\r
-            new NatBuilder().setOutbound(new OutboundBuilder().setNat44Support(true).setPostRouting(false).build())\r
+            new NatBuilder().setOutbound(new OutboundBuilder().setNat44Support(true).setPostRouting(ConfigUtil.getInstance().isL3FlatEnabled()).build())\r
                 .build();\r
         GbpNetconfTransaction.netconfSyncedWrite(vppIid, natIid, nat, GbpNetconfTransaction.RETRY_COUNT);\r
 \r
@@ -89,13 +116,13 @@ public class NatUtil {
         return ifaceIid.builder().augmentation(NatInterfaceAugmentation.class).child(Nat.class).build();\r
     }\r
 \r
-    public static Optional<InstanceIdentifier<PhysicalInterface>> resolvePhysicalInterface(IpPrefix extSubnetPrefix,\r
+    public static @Nonnull List<InstanceIdentifier<PhysicalInterface>> resolvePhysicalInterface(IpPrefix extSubnetPrefix,\r
         ReadOnlyTransaction rTx) {\r
         Optional<RendererNodes> readFromDs =\r
             DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, VppIidFactory.getRendererNodesIid(), rTx);\r
         rTx.close();\r
         if (!readFromDs.isPresent() || readFromDs.get().getRendererNode() == null) {\r
-            return Optional.absent();\r
+            return Collections.emptyList();\r
         }\r
         RendererNodes rendererNodes = readFromDs.get();\r
         List<RendererNode>\r
@@ -105,6 +132,7 @@ public class NatUtil {
                 .filter(rn -> rn.getAugmentation(VppInterfaceAugmentation.class) != null)\r
                 .filter(rn -> rn.getAugmentation(VppInterfaceAugmentation.class).getPhysicalInterface() != null)\r
                 .collect(Collectors.toList());\r
+        List<InstanceIdentifier<PhysicalInterface>> iids = new ArrayList<>();\r
         for (RendererNode rn : vppNodes) {\r
             java.util.Optional<PhysicalInterface>\r
                 optResolvedIface =\r
@@ -117,52 +145,118 @@ public class NatUtil {
                         .anyMatch(ipAddr -> NetUtils.isInRange(extSubnetPrefix, String.valueOf(ipAddr.getValue()))))\r
                     .findFirst();\r
             if (optResolvedIface.isPresent()) {\r
-                return Optional.of(VppIidFactory.getRendererNodeIid(rn)\r
+                iids.add(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
+        return iids;\r
     }\r
 \r
-    static List<ExternalIpAddressPool> resolveDynamicNat(@Nonnull PolicyContext policyCtx,\r
-        @Nullable List<MappingEntryBuilder> sNatEntries) {\r
-        List<RendererForwardingByTenant> forwardingByTenantList =\r
-                policyCtx.getPolicy().getConfiguration().getRendererForwarding().getRendererForwardingByTenant();\r
-        Map<Long, Ipv4Prefix> extCache = new HashMap<>();\r
-        // loop through forwarding by tenant\r
-        for (RendererForwardingByTenant rft : forwardingByTenantList) {\r
-            // loop through renderer network domain\r
-            for (RendererNetworkDomain domain : rft.getRendererNetworkDomain()) {\r
-                final SubnetAugmentRenderer subnetAugmentation = domain.getAugmentation(SubnetAugmentRenderer.class);\r
-                final Subnet subnet = subnetAugmentation.getSubnet();\r
-                if (subnet != null && !subnet.isIsTenant() && subnet.getAllocationPool() != null) {\r
-                    // loop through allocation pool\r
-                    for (AllocationPool pool : subnet.getAllocationPool()) {\r
-                        final IpPrefix subnetIpPrefix = subnet.getIpPrefix();\r
-                        if (subnetIpPrefix.getIpv4Prefix() != null) {\r
-                            final String firstEntry = pool.getFirst();\r
-                            final String lastEntry = pool.getLast();\r
-                            extCache.putAll(resolveDynamicNatPrefix(subnetIpPrefix.getIpv4Prefix(), firstEntry, lastEntry,\r
-                                    sNatEntries));\r
-                        }\r
-                    }\r
+    public static @Nonnull List<InstanceIdentifier<PhysicalInterface>> resolvePhysicalInterface(ReadOnlyTransaction rTx) {\r
+            Optional<RendererNodes> readFromDs =\r
+                DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, VppIidFactory.getRendererNodesIid(), rTx);\r
+            rTx.close();\r
+            if (!readFromDs.isPresent() || readFromDs.get().getRendererNode() == null) {\r
+                return Collections.emptyList();\r
+            }\r
+            RendererNodes rendererNodes = readFromDs.get();\r
+            List<RendererNode>\r
+                vppNodes =\r
+                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
+            List<InstanceIdentifier<PhysicalInterface>> iids = new ArrayList<>();\r
+            for (RendererNode rn : vppNodes) {\r
+                java.util.Optional<PhysicalInterface>\r
+                    optResolvedIface =\r
+                    rn.getAugmentation(VppInterfaceAugmentation.class)\r
+                        .getPhysicalInterface()\r
+                        .stream()\r
+                        .filter(phIface -> phIface.getAddress() != null)\r
+                        .filter(phIface -> phIface.isExternal())\r
+                        .findFirst();\r
+                if (optResolvedIface.isPresent()) {\r
+                    iids.add(VppIidFactory.getRendererNodeIid(rn)\r
+                        .builder()\r
+                        .augmentation(VppInterfaceAugmentation.class)\r
+                        .child(PhysicalInterface.class, new PhysicalInterfaceKey(optResolvedIface.get().getKey()))\r
+                        .build());\r
                 }\r
             }\r
+            return iids;\r
         }\r
-        final List<ExternalIpAddressPool> extIps = new ArrayList<>();\r
-        for (Entry<Long, Ipv4Prefix> entry : extCache.entrySet()) {\r
-            extIps.add(new ExternalIpAddressPoolBuilder().setPoolId(entry.getKey())\r
-                .setExternalIpPool(entry.getValue())\r
-                .build());\r
+\r
+    public static Optional<MappingEntryBuilder> createStaticEntry(String internal, Ipv4Address external) {\r
+        IpAddress internalIp = null;\r
+        try {\r
+            InetAddress inetAddr = InetAddress.getByName(internal);\r
+            if (inetAddr instanceof Inet4Address) {\r
+                internalIp = new IpAddress(new Ipv4Address(internal));\r
+            } else if (inetAddr instanceof Inet6Address) {\r
+                internalIp = new IpAddress(new Ipv6Address(internal));\r
+            }\r
+        } catch (UnknownHostException e) {\r
+            LOG.error("Cannot resolve host IP {}. {}", internal, e.getMessage());\r
+            return Optional.absent();\r
+        }\r
+        SubnetUtils subnet = new SubnetUtils(internal + "/32");\r
+        Long index = Integer.toUnsignedLong(subnet.getInfo().asInteger(internal));\r
+        MappingEntryBuilder mappingEntryBuilder = new MappingEntryBuilder()\r
+            .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
+        return Optional.of(mappingEntryBuilder);\r
+    }\r
+\r
+    public static List<ExternalIpAddressPool> resolveDynamicNat(@Nonnull PolicyContext policyCtx,\r
+            @Nullable List<MappingEntryBuilder> sNatEntries) {\r
+        Optional<List<RendererForwardingByTenant>> forwardingByTenantLists = Optional.of(policyCtx)\r
+            .transform(x -> x.getPolicy())\r
+            .transform(x -> x.getConfiguration())\r
+            .transform(x -> x.getRendererForwarding())\r
+            .transform(x -> x.getRendererForwardingByTenant());\r
+        if (!forwardingByTenantLists.isPresent()) {\r
+            LOG.warn("No dynamic NAT resolved in cfg version {}.", policyCtx.getPolicy().getVersion());\r
+            return ImmutableList.of();\r
         }\r
-        return extIps;\r
+        Map<Long, Ipv4Prefix> extCache = new HashMap<>();\r
+        forwardingByTenantLists.get()\r
+            .stream()\r
+            .map(rft -> rft.getRendererNetworkDomain())\r
+            .flatMap(Collection::stream)\r
+            .filter(domain -> domain.getAugmentation(SubnetAugmentRenderer.class) != null)\r
+            .map(domain -> domain.getAugmentation(SubnetAugmentRenderer.class).getSubnet())\r
+            .filter(subnet -> !subnet.isIsTenant() && subnet.getAllocationPool() != null)\r
+            .forEach(subnet -> {\r
+                final IpPrefix subnetIpPrefix = subnet.getIpPrefix();\r
+                subnet.getAllocationPool().forEach(pool -> {\r
+                    if (subnetIpPrefix.getIpv4Prefix() != null) {\r
+                        final String firstEntry = pool.getFirst();\r
+                        final String lastEntry = pool.getLast();\r
+                        extCache.putAll(resolveDynamicNatPrefix(subnetIpPrefix.getIpv4Prefix(), firstEntry, lastEntry,\r
+                                sNatEntries));\r
+                    }\r
+                });\r
+            });\r
+        List<ExternalIpAddressPool> extPools = extCache.entrySet()\r
+            .stream()\r
+            .map(entry -> new ExternalIpAddressPoolBuilder().setPoolId(entry.getKey())\r
+                .setExternalIpPool(entry.getValue())\r
+                .build())\r
+            .collect(Collectors.toList());\r
+        LOG.trace("Resolved dynamic NAT pools in cfg version {}: {}", policyCtx.getPolicy().getVersion(), extPools);\r
+        return extPools;\r
     }\r
 \r
-    @VisibleForTesting\r
-    private static Map<Long, Ipv4Prefix> resolveDynamicNatPrefix(@Nonnull final Ipv4Prefix prefix,\r
+\r
+    static Map<Long, Ipv4Prefix> resolveDynamicNatPrefix(@Nonnull final Ipv4Prefix prefix,\r
                                                                  @Nonnull final String first,\r
                                                                  @Nullable final String last,\r
                                                                  @Nullable final List<MappingEntryBuilder> natEntries) {\r
index c8100e9ec1ec7f906c4f8bd4d759f051d64a5786..574d9393777b8ab1960a03680f1e78ace7c7de36 100644 (file)
@@ -25,13 +25,14 @@ import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.api.BridgeDomainManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.DhcpRelayCommand;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.NatInstanceCommand.NatInstanceCommandBuilder;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.RoutingCommand;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.config.ConfigUtil;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.dhcp.DhcpRelayHandler;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.InterfaceManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.LispStateManager;
-import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.loopback.LoopbackManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.flat.overlay.FlatOverlayManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.loopback.LoopbackManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.mappers.NeutronTenantToVniMapper;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.nat.NatManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.nat.NatUtil;
@@ -62,6 +63,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.NetworkDomain;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.fields.Parent;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.NatAddressRenderer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererPolicy;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.Configuration;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.Endpoints;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.RendererForwarding;
@@ -92,7 +94,11 @@ import org.slf4j.LoggerFactory;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
 import com.google.common.base.Strings;
+import com.google.common.collect.HashBasedTable;
+import com.google.common.collect.ImmutableTable;
+import com.google.common.collect.Lists;
 import com.google.common.collect.SetMultimap;
 import com.google.common.collect.Table;
 
@@ -389,90 +395,89 @@ public final class ForwardingManager {
         return java.util.Optional.empty();
     }
 
-    void syncNatEntries(PolicyContext policyCtx) {
-        Configuration cfg = policyCtx.getPolicy().getConfiguration();
-        if(cfg != null) {
-            final List<MappingEntryBuilder> sNatEntries = resolveStaticNatTableEntries(cfg.getEndpoints());
-            LOG.trace("Syncing static NAT entries {}", sNatEntries);
-            if (cfg.getRendererForwarding() != null) {
-                for (RendererForwardingByTenant fwd : cfg.getRendererForwarding().getRendererForwardingByTenant()) {
-                    List<InstanceIdentifier<PhysicalInterface>> physIfacesIid =
-                        resolvePhysicalInterfacesForNat(fwd.getRendererNetworkDomain());
-                    natManager.submitNatChanges(physIfacesIid, sNatEntries, policyCtx, true);
+    private static Optional<Endpoints> checkEndpoints(PolicyContext ctx) {
+        Optional<PolicyContext> contextOptional = Optional.fromNullable(ctx);
+        if (contextOptional.isPresent()) {
+            Optional<RendererPolicy> policyOptional = Optional.fromNullable(contextOptional.get().getPolicy());
+            if (policyOptional.isPresent()) {
+                Optional<Configuration> configOptional = Optional.fromNullable(policyOptional.get().getConfiguration());
+                if (configOptional.isPresent()) {
+                    return Optional.fromNullable(configOptional.get().getEndpoints());
                 }
             }
         }
+        return Optional.absent();
     }
 
-    void deleteNatEntries(PolicyContext policyCtx) {
-        Configuration cfg = policyCtx.getPolicy().getConfiguration();
-        if(cfg != null) {
-            List<MappingEntryBuilder> natEntries = resolveStaticNatTableEntries(cfg.getEndpoints());
-            if (natEntries.isEmpty()) {
-                LOG.trace("NAT entries are empty,nothing to delete, skipping processing.");
-                return;
-            }
-            LOG.trace("Deleting NAT entries {}", natEntries);
-            if (cfg.getRendererForwarding() != null) {
-                for (RendererForwardingByTenant fwd : cfg.getRendererForwarding().getRendererForwardingByTenant()) {
-                    List<InstanceIdentifier<PhysicalInterface>> physIfacesIid =
-                        resolvePhysicalInterfacesForNat(fwd.getRendererNetworkDomain());
-                    natManager.submitNatChanges(physIfacesIid, natEntries, policyCtx, false);
-                }
-            }
-        }
+
+    void createNatEntries(@Nonnull PolicyContext after) {
+        LOG.info("Resolving NAT for cfg version {}", after.getPolicy().getVersion());
+        Preconditions.checkArgument(checkEndpoints(after).isPresent());
+        final Table<NodeId, Long, List<MappingEntryBuilder>> staticEntries =
+                resolveStaticNatTableEntries(checkEndpoints(after).get());
+        Map<NodeId, NatInstanceCommandBuilder> natByNode = natManager.staticEntries(staticEntries);
+        natManager.dynamicEntries(after, natByNode);
+        natManager.submitNatChanges(natByNode);
     }
 
-    private List<InstanceIdentifier<PhysicalInterface>> resolvePhysicalInterfacesForNat(
-        List<RendererNetworkDomain> rendNetDomains) {
-        List<InstanceIdentifier<PhysicalInterface>> physIfaces = new ArrayList<>();
-        for (RendererNetworkDomain rendDomain : rendNetDomains) {
-            Optional<IpPrefix> resolvedIpPrefix = resolveIpPrefix(rendDomain);
-            if (resolvedIpPrefix.isPresent()) {
-                Optional<InstanceIdentifier<PhysicalInterface>> resPhIface =
-                    NatUtil.resolvePhysicalInterface(resolvedIpPrefix.get(), dataBroker.newReadOnlyTransaction());
-                if (resPhIface.isPresent()) {
-                    physIfaces.add(resPhIface.get());
-                }
-            }
+    void syncNatEntries(@Nonnull PolicyContext before,@Nonnull PolicyContext after) {
+        LOG.info("Syncing NAT entries for version {}", after.getPolicy().getVersion());
+        Optional<Endpoints> endpointsBeforeOptional = checkEndpoints(before);
+
+        Endpoints endpointsAfter = null;
+        Optional<Endpoints> endpointsAfterOptional = checkEndpoints(after);
+        if (endpointsAfterOptional != null && endpointsAfterOptional.isPresent()) {
+            endpointsAfter = endpointsAfterOptional.get();
+        }
+
+        if (endpointsBeforeOptional.isPresent()) {
+            natManager.clearNodes(endpointsBeforeOptional.get(), endpointsAfter);
+        }
+
+        if (endpointsAfter != null) {
+            createNatEntries(after);
         }
-        return physIfaces;
     }
 
-    private Optional<IpPrefix> resolveIpPrefix(RendererNetworkDomain rendDomain) {
-        SubnetAugmentRenderer subnetAug = rendDomain.getAugmentation(SubnetAugmentRenderer.class);
-        if (subnetAug.getSubnet() != null) {
-            return Optional.of(subnetAug.getSubnet().getIpPrefix());
+    void deleteNatEntries(@Nonnull PolicyContext before) {
+        Optional<Endpoints> endpointsBeforeOptional = checkEndpoints(before);
+        if (endpointsBeforeOptional.isPresent()) {
+            natManager.clearNodes(endpointsBeforeOptional.get(), null);
         }
-        return Optional.absent();
     }
 
-    private List<MappingEntryBuilder> resolveStaticNatTableEntries(Endpoints endpoints) {
-        List<MappingEntryBuilder> sNatEntries = new ArrayList<>();
-        for (AddressEndpointWithLocation addrEp : endpoints.getAddressEndpointWithLocation()) {
-            if (addrEp.getAugmentation(NatAddressRenderer.class) == null) {
-                continue;
+    private ImmutableTable<NodeId, Long, List<MappingEntryBuilder>> resolveStaticNatTableEntries(
+            @Nonnull Endpoints endpoints) {
+        Table<NodeId, Long, List<MappingEntryBuilder>> resultBuilder = HashBasedTable.create();
+        List<Predicate<AddressEndpointWithLocation>> filter = Lists.newArrayList();
+        filter.add(ep -> ep.getAugmentation(NatAddressRenderer.class) != null);
+        filter.add(ep -> resolveEpIpAddressForSnat(ep) != null);
+        filter.add(ep -> ep.getAbsoluteLocation() != null);
+        filter.add(ep -> ep.getAbsoluteLocation().getLocationType() instanceof ExternalLocationCase);
+        filter.add(ep -> ep.getAugmentation(NatAddressRenderer.class) != null);
+        filter.add(ep -> ep.getAugmentation(NatAddressRenderer.class).getNatAddress() != null);
+        filter.add(ep -> ep.getAugmentation(NatAddressRenderer.class).getNatAddress().getIpv4Address() != null);
+
+        endpoints.getAddressEndpointWithLocation().forEach(addrEp -> {
+            if (!filter.stream().allMatch(f -> f.apply(addrEp))) {
+                return;
             }
             String endpointIP = resolveEpIpAddressForSnat(addrEp);
-
-            if (endpointIP == null) {
-                LOG.warn("Endpoints {} IP cannot be null, skipping processing of SNAT", addrEp);
-                continue;
-            }
-
             NatAddressRenderer natAddr = addrEp.getAugmentation(NatAddressRenderer.class);
-            if (natAddr.getNatAddress() == null && natAddr.getNatAddress().getIpv4Address() == null) {
-                LOG.warn("Only Ipv4 SNAT is currently supported. Cannot apply SNAT for [{},{}]", endpointIP,
-                        natAddr.getNatAddress());
-                continue;
-            }
-            Optional<MappingEntryBuilder> entry = natManager.resolveSnatEntry(endpointIP, natAddr.getNatAddress()
-                .getIpv4Address());
+            NodeId nodeId = ((ExternalLocationCase) addrEp.getAbsoluteLocation().getLocationType())
+                .getExternalNodeMountPoint().firstKeyOf(Node.class).getNodeId();
+            Optional<MappingEntryBuilder> entry =
+                    NatUtil.createStaticEntry(endpointIP, natAddr.getNatAddress().getIpv4Address());
             if (entry.isPresent()) {
-                sNatEntries.add(entry.get());
+                long tenantId = flatOverlayManager.getVni(addrEp.getTenant().getValue());
+                if (resultBuilder.get(nodeId, tenantId) != null) {
+                    resultBuilder.get(nodeId, tenantId).add(entry.get());
+                } else {
+                    resultBuilder.put(nodeId, tenantId, Lists.newArrayList(entry.get()));
+                }
             }
-        }
-        return sNatEntries;
+        });
+        return ImmutableTable.copyOf(resultBuilder);
     }
 
     private String resolveEpIpAddressForSnat(AddressEndpointWithLocation addrEp) {
@@ -538,7 +543,6 @@ public final class ForwardingManager {
                 if (fwd == null) {
                     continue;
                 }
-
                 List<InstanceIdentifier<PhysicalInterface>>
                     physIfacesIid = resolvePhysicalInterfacesForNat(fwd.getRendererNetworkDomain());
                 Map<InstanceIdentifier<Node>, RoutingCommand> routingCommandMap =
@@ -552,6 +556,30 @@ public final class ForwardingManager {
         }
     }
 
+    List<InstanceIdentifier<PhysicalInterface>> resolvePhysicalInterfacesForNat(
+            List<RendererNetworkDomain> rendNetDomains) {
+            List<InstanceIdentifier<PhysicalInterface>> physIfaces = new ArrayList<>();
+            for (RendererNetworkDomain rendDomain : rendNetDomains) {
+                Optional<IpPrefix> resolvedIpPrefix = resolveIpPrefix(rendDomain);
+                if (resolvedIpPrefix.isPresent()) {
+                    List<InstanceIdentifier<PhysicalInterface>> resPhIface =
+                        NatUtil.resolvePhysicalInterface(resolvedIpPrefix.get(), dataBroker.newReadOnlyTransaction());
+                    if (!resPhIface.isEmpty()) {
+                        physIfaces.addAll(resPhIface);
+                    }
+                }
+            }
+            return physIfaces;
+        }
+
+    public static Optional<IpPrefix> resolveIpPrefix(RendererNetworkDomain rendDomain) {
+        SubnetAugmentRenderer subnetAug = rendDomain.getAugmentation(SubnetAugmentRenderer.class);
+        if (subnetAug.getSubnet() != null) {
+            return Optional.of(subnetAug.getSubnet().getIpPrefix());
+        }
+        return Optional.absent();
+    }
+
     List<DhcpRelayCommand> createDhcpRelay(RendererForwarding rendererForwarding,
         SetMultimap<String, NodeId> vppNodesByL2Fd) {
         for (RendererForwardingByTenant forwardingByTenant : rendererForwarding.getRendererForwardingByTenant()) {
index b380358c567d634563fb05025c6aaa2ae85eda5e..650cb385f42fb40e940dc135027de4e427fdb989 100644 (file)
@@ -185,8 +185,7 @@ public class VppRendererPolicyManager {
             fwManager.syncDhcpRelay(createdDhcpRelays, deletedDhcpRelays);
         }
 
-        fwManager.syncNatEntries(policyCtxAfter);
-
+        fwManager.syncNatEntries(policyCtxBefore, policyCtxAfter);
         fwManager.deleteRouting(policyCtxBefore);
         fwManager.syncRouting(policyCtxAfter);
 
@@ -258,7 +257,7 @@ public class VppRendererPolicyManager {
         }
 
         rEpKeys.forEach(rEpKey -> fwManager.createForwardingForEndpoint(rEpKey, policyCtx));
-        fwManager.syncNatEntries(policyCtx);
+        fwManager.createNatEntries(policyCtx);
         fwManager.syncRouting(policyCtx);
     }
 
index b43f5e7882185e515bc9b00e93e2398074bdc7ce..5f0ce176a6a9038ab68c08ffecdc86dd4f9308bc 100644 (file)
@@ -25,6 +25,9 @@ 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.NatInstances;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.NatInstance;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.NatInstanceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.MappingTable;
+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.MappingEntryKey;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.Routing;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.RoutingInstance;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.RoutingInstanceKey;
@@ -49,7 +52,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev1
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170801.gpe.entry.table.grouping.gpe.entry.table.GpeEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170801.gpe.entry.table.grouping.gpe.entry.table.GpeEntryKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170801.gpe.feature.data.grouping.GpeFeatureData;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170911.ItrRemoteLocatorSetsGrouping;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170911.Lisp;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170911.dp.subtable.grouping.LocalMappings;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170911.dp.subtable.grouping.local.mappings.LocalMapping;
@@ -169,11 +171,21 @@ public class VppIidFactory {
                 org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214._interface.acl.attributes.Acl.class);
     }
 
-    public static InstanceIdentifier<NatInstance> getNatInstanceIid(Long natInstance) {
+    public static InstanceIdentifier<MappingEntry> getMappingEntryIid(long natInstance, long index) {
         return InstanceIdentifier.builder(NatConfig.class)
-                .child(NatInstances.class)
-                .child(NatInstance.class, new NatInstanceKey(natInstance))
-                .build();
+            .child(NatInstances.class)
+            .child(NatInstance.class, new NatInstanceKey(natInstance))
+            .child(MappingTable.class)
+            .child(MappingEntry.class, new MappingEntryKey(index))
+            .build();
+    }
+
+    public static InstanceIdentifier<NatInstances> getNatInstancesIid() {
+        return InstanceIdentifier.builder(NatConfig.class).child(NatInstances.class).build();
+    }
+
+    public static InstanceIdentifier<NatInstance> getNatInstanceIid(Long natInstance) {
+        return getNatInstancesIid().child(NatInstance.class, new NatInstanceKey(natInstance));
     }
 
     public static InstanceIdentifier<RoutingProtocol> getRoutingInstanceIid(
index 66ce38348e168c43e967e4cc2d2884c7474548bb..6ea71dab92d7180be2f7c849820a02e81a34d2ba 100644 (file)
@@ -57,6 +57,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.VhostUser;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.VhostUserRole;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev170816._interface.nat.attributes.Nat;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
@@ -89,7 +90,7 @@ public class InterfaceManagerTest extends CustomDataBrokerTest {
     @Override
     public Collection<Class<?>> getClassesFromModules() {
         return Arrays.asList(Node.class, VppEndpoint.class, Interfaces.class, BridgeDomains.class,
-                LocationProviders.class, IpPrefixType.class, MacAddressType.class);
+                LocationProviders.class, IpPrefixType.class, MacAddressType.class, Nat.class);
     }
 
     @Before
index 79770adb8fbb10ea6ef6a60c55b93682a65dc070..91314ac0072da3335436dbd089788dbb6d4c2297 100644 (file)
@@ -37,6 +37,7 @@ import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.VppEndpointLocationP
 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.LispStateManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.flat.overlay.FlatOverlayManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.loopback.LoopbackManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.nat.CentralizedNatImpl;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.nat.NatManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.acl.AclManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.routing.RoutingManager;
@@ -87,6 +88,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.topology.rev160129.TopologyVbridgeAugment;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.tunnel.vxlan.rev170327.TunnelTypeVxlan;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.tunnel.vxlan.rev170327.network.topology.topology.tunnel.parameters.VxlanTunnelParameters;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev170615.access.lists.acl.access.list.entries.ace.matches.ace.type.VppAce;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev170816._interface.nat.attributes.Nat;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
@@ -138,9 +141,10 @@ public class VppRendererPolicyManagerTest extends CustomDataBrokerTest {
     public Collection<Class<?>> getClassesFromModules() {
         return Arrays.asList(Node.class, VppEndpoint.class, Interfaces.class, BridgeDomains.class,
                 LocationProviders.class, L2FloodDomain.class, VxlanVni.class, TopologyVbridgeAugment.class,
-                TunnelTypeVxlan.class, PhysicalLocationRef.class, AccessLists.class,
-                VppInterfaceAugmentation.class, VppAclInterfaceAugmentation.class, VxlanTunnelParameters.class);
-    }
+                TunnelTypeVxlan.class, PhysicalLocationRef.class, AccessLists.class, VppAce.class,
+                VppInterfaceAugmentation.class, VppAclInterfaceAugmentation.class, VxlanTunnelParameters.class,
+                PhysicalLocationRef.class, Nat.class);
+        }
 
     @Before
     public void init() throws Exception {
@@ -155,7 +159,7 @@ public class VppRendererPolicyManagerTest extends CustomDataBrokerTest {
         flatOverlayManager = new FlatOverlayManager(dataBroker, mountedDataProviderMock);
         ifaceManager = new InterfaceManager(mountedDataProviderMock, dataBroker, flatOverlayManager);
         aclManager = new AclManager(mountedDataProviderMock, ifaceManager);
-        natManager = new NatManager(dataBroker, mountedDataProviderMock);
+        natManager = new CentralizedNatImpl(dataBroker);
         routingManager = new RoutingManager(dataBroker, mountedDataProviderMock);
         bdManager = new BridgeDomainManagerImpl(mountPointDataBroker);
         dhcpRelayHandler = new DhcpRelayHandler(dataBroker);
@@ -182,7 +186,8 @@ public class VppRendererPolicyManagerTest extends CustomDataBrokerTest {
         storeVppEndpoint(clientEp.getKey(), CLIENT_MAC, CLIENT_1_IFACE_NAME, createVppEndpointIid(clientEp.getKey()));
         storeVppEndpoint(webEp.getKey(), WEB_MAC, WEB_1_IFACE_NAME, createVppEndpointIid(webEp.getKey()));
 
-        Configuration configuration = DtoFactory.createConfiguration(Arrays.asList(clientEp), Arrays.asList(webEp));
+        Configuration configuration = DtoFactory.createConfiguration(Collections.singletonList(clientEp),
+            Collections.singletonList(webEp));
         RendererPolicy rendererPolicy =
                 new RendererPolicyBuilder().setVersion(1L).setConfiguration(configuration).build();
         RendererPolicyConfEvent event = new RendererPolicyConfEvent(RENDERER_POLICY_IID, null, rendererPolicy);
@@ -398,11 +403,9 @@ public class VppRendererPolicyManagerTest extends CustomDataBrokerTest {
             Assert.assertTrue(interconnection instanceof BridgeBased);
             Assert.assertEquals(expectedBridgeDomain, ((BridgeBased) interconnection).getBridgeDomain());
         } else {
-            if (vppIfaceAug != null) {
-                L2 l2 = vppIfaceAug.getL2();
-                if (l2 != null) {
-                    Assert.assertNull(l2.getInterconnection());
-                }
+            L2 l2 = vppIfaceAug.getL2();
+            if (l2 != null) {
+                Assert.assertNull(l2.getInterconnection());
             }
         }
     }