HC2VPP-105: add support for nat64 pool configuration 53/8053/4
authorMarek Gradzki <[email protected]>
Tue, 15 Aug 2017 12:04:51 +0000 (14:04 +0200)
committerMarek Gradzki <[email protected]>
Wed, 16 Aug 2017 10:20:16 +0000 (12:20 +0200)
Change-Id: I5e57b7855e081056ad0d675084209fc9cd4add23
Signed-off-by: Marek Gradzki <[email protected]>
nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/ExternalIpPoolCustomizer.java
nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/NatWriterFactory.java
nat/nat2vpp/src/test/java/io/fd/hc2vpp/nat/NatTestSchemaContext.java
nat/nat2vpp/src/test/java/io/fd/hc2vpp/nat/write/ExternalIpPoolCustomizerTest.java
nat/nat2vpp/src/test/resources/nat64/external-ip-pool.json [new file with mode: 0644]

index 61fedbd..6233162 100644 (file)
 package io.fd.hc2vpp.nat.write;
 
 import static com.google.common.base.Preconditions.checkArgument;
+import static org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nat.rev170804.NatPoolType.Nat64;
 
-import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer;
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
 import io.fd.hc2vpp.common.translate.util.Ipv4AddressRange;
 import io.fd.hc2vpp.common.translate.util.Ipv4Translator;
 import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer;
 import io.fd.honeycomb.translate.write.WriteContext;
 import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.snat.dto.Nat64AddDelPoolAddrRange;
 import io.fd.vpp.jvpp.snat.dto.SnatAddAddressRange;
 import io.fd.vpp.jvpp.snat.future.FutureJVppSnatFacade;
 import javax.annotation.Nonnull;
@@ -31,12 +34,13 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.
 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.parameters.ExternalIpAddressPool;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.parameters.ExternalIpAddressPoolKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nat.rev170804.ExternalIpAddressPoolConfigAugmentation;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 final class ExternalIpPoolCustomizer implements ListWriterCustomizer<ExternalIpAddressPool, ExternalIpAddressPoolKey>,
-        JvppReplyConsumer, Ipv4Translator {
+        JvppReplyConsumer, Ipv4Translator, ByteDataTranslator {
 
     private static final Logger LOG = LoggerFactory.getLogger(ExternalIpPoolCustomizer.class);
 
@@ -54,8 +58,7 @@ final class ExternalIpPoolCustomizer implements ListWriterCustomizer<ExternalIpA
                 "External IP pools are only assignable for nat instance(vrf-id) with ID 0");
         LOG.trace("Adding address range:{}, as: {}", id, dataAfter);
         // TODO check overlaps ? VPP-478 maybe no necessary, depending on how VPP handles them
-        getReplyForCreate(jvppSnat.snatAddAddressRange(
-                getRequest(dataAfter.getExternalIpPool(), true)).toCompletableFuture(), id, dataAfter);
+        configureAddressPool(id, dataAfter, true);
         LOG.debug("Address range: {} added successfully", id);
     }
 
@@ -64,20 +67,46 @@ final class ExternalIpPoolCustomizer implements ListWriterCustomizer<ExternalIpA
                                         @Nonnull final ExternalIpAddressPool dataBefore,
                                         @Nonnull final WriteContext writeContext) throws WriteFailedException {
         LOG.trace("Deleting address range:{}, as: {}", id, dataBefore);
-        getReplyForDelete(jvppSnat.snatAddAddressRange(
-                getRequest(dataBefore.getExternalIpPool(), false)).toCompletableFuture(), id);
+        configureAddressPool(id, dataBefore, false);
         LOG.debug("Deleting range: {} added successfully", id);
     }
 
-    private SnatAddAddressRange getRequest(final Ipv4Prefix externalIpPool, boolean isAdd) {
-        SnatAddAddressRange request = new SnatAddAddressRange();
-        // SNAT supports only IPv4 now, so does the model
+    private void configureAddressPool(@Nonnull final InstanceIdentifier<ExternalIpAddressPool> id,
+                                      @Nonnull final ExternalIpAddressPool addressPool,
+                                      final boolean isAdd) throws WriteFailedException {
+        boolean isNat64 = false;
+        final ExternalIpAddressPoolConfigAugmentation augmentation =
+                addressPool.getAugmentation(ExternalIpAddressPoolConfigAugmentation.class);
+        if (augmentation != null) {
+            isNat64 = Nat64.equals(augmentation.getPoolType());
+        }
+        if (isNat64) {
+            final Nat64AddDelPoolAddrRange request = getNat64Request(addressPool.getExternalIpPool(), isAdd);
+            getReplyForWrite(jvppSnat.nat64AddDelPoolAddrRange(request).toCompletableFuture(), id);
+        } else {
+            final SnatAddAddressRange request = getNat44Request(addressPool.getExternalIpPool(), isAdd);
+            getReplyForWrite(jvppSnat.snatAddAddressRange(request).toCompletableFuture(), id);
+        }
+    }
+
+    private SnatAddAddressRange getNat44Request(final Ipv4Prefix externalIpPool, boolean isAdd) {
+        final SnatAddAddressRange request = new SnatAddAddressRange();
         final Ipv4AddressRange range = Ipv4AddressRange.fromPrefix(externalIpPool);
-        LOG.trace("Handling address range: {}", range);
+        LOG.trace("Handling NAT44 address range: {}", range);
         request.isIp4 = 1;
-        request.isAdd = (byte) (isAdd ? 1 : 0);
+        request.isAdd = booleanToByte(isAdd);
         request.firstIpAddress = ipv4AddressNoZoneToArray(range.getStart());
         request.lastIpAddress = ipv4AddressNoZoneToArray(range.getEnd());
         return request;
     }
+
+    private Nat64AddDelPoolAddrRange getNat64Request(final Ipv4Prefix externalIpPool, boolean isAdd) {
+        final Nat64AddDelPoolAddrRange request = new Nat64AddDelPoolAddrRange();
+        final Ipv4AddressRange range = Ipv4AddressRange.fromPrefix(externalIpPool);
+        LOG.trace("Handling NAT64 address range: {}", range);
+        request.isAdd = booleanToByte(isAdd);
+        request.startAddr = ipv4AddressNoZoneToArray(range.getStart());
+        request.endAddr = ipv4AddressNoZoneToArray(range.getEnd());
+        return request;
+    }
 }
index e239721..ef2a2af 100644 (file)
@@ -32,6 +32,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev1509
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.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.parameters.ExternalIpAddressPool;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nat.rev170804.ExternalIpAddressPoolConfigAugmentation;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
 /**
@@ -66,7 +67,10 @@ public final class NatWriterFactory implements WriterFactory {
 
         // External address pool has to be executed before mapping entry. Because adding mapping entries requires to
         //  already have an IP range predefined ... in some cases
-        registry.addBefore(new GenericListWriter<>(NAT_INSTANCE_ID.child(ExternalIpAddressPool.class),
+        registry.subtreeAddBefore(
+                Sets.newHashSet(InstanceIdentifier.create(ExternalIpAddressPool.class)
+                                .augmentation(ExternalIpAddressPoolConfigAugmentation.class)),
+                        new GenericListWriter<>(NAT_INSTANCE_ID.child(ExternalIpAddressPool.class),
                 new ExternalIpPoolCustomizer(jvppSnat)),
                 MAP_ENTRY_ID);
     }
index 8a30df2..041096f 100644 (file)
@@ -34,7 +34,9 @@ public interface NatTestSchemaContext {
                                 .getInstance(),
                         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.$YangModuleInfoImpl
                                 .getInstance(),
-                    org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev170801.$YangModuleInfoImpl
+                        org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nat.rev170804.$YangModuleInfoImpl
+                                .getInstance(),
+                        org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev170801.$YangModuleInfoImpl
                                 .getInstance()));
         return context;
     }
index e2db427..8f25bfa 100644 (file)
@@ -22,10 +22,13 @@ import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
 import io.fd.hc2vpp.nat.NatTestSchemaContext;
 import io.fd.honeycomb.test.tools.HoneycombTestRunner;
 import io.fd.honeycomb.test.tools.annotations.InjectTestData;
 import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.snat.dto.Nat64AddDelPoolAddrRange;
+import io.fd.vpp.jvpp.snat.dto.Nat64AddDelPoolAddrRangeReply;
 import io.fd.vpp.jvpp.snat.dto.SnatAddAddressRange;
 import io.fd.vpp.jvpp.snat.dto.SnatAddAddressRangeReply;
 import io.fd.vpp.jvpp.snat.future.FutureJVppSnatFacade;
@@ -41,7 +44,8 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev1509
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
 @RunWith(HoneycombTestRunner.class)
-public class ExternalIpPoolCustomizerTest extends WriterCustomizerTest implements NatTestSchemaContext {
+public class ExternalIpPoolCustomizerTest extends WriterCustomizerTest implements NatTestSchemaContext,
+        ByteDataTranslator {
 
     private static final long NAT_INSTANCE_ID = 0;
     private static final long POOL_ID = 22;
@@ -59,43 +63,70 @@ public class ExternalIpPoolCustomizerTest extends WriterCustomizerTest implement
     public void setUpTest() {
         customizer = new ExternalIpPoolCustomizer(jvppSnat);
         when(jvppSnat.snatAddAddressRange(any())).thenReturn(future(new SnatAddAddressRangeReply()));
+        when(jvppSnat.nat64AddDelPoolAddrRange(any())).thenReturn(future(new Nat64AddDelPoolAddrRangeReply()));
     }
 
     @Test
-    public void testWrite(
-        @InjectTestData(resourcePath = "/nat44/external-ip-pool.json", id = NAT_INSTANCES_PATH) NatInstances data)
-        throws WriteFailedException {
+    public void testWriteNat44(
+            @InjectTestData(resourcePath = "/nat44/external-ip-pool.json", id = NAT_INSTANCES_PATH) NatInstances data)
+            throws WriteFailedException {
         customizer.writeCurrentAttributes(IID, extractIpPool(data), writeContext);
-        final SnatAddAddressRange expectedRequest = getExpectedRequest();
-        expectedRequest.isAdd = 1;
+        final SnatAddAddressRange expectedRequest = getExpectedRequestNat44(true);
         verify(jvppSnat).snatAddAddressRange(expectedRequest);
     }
 
-    @Test(expected = UnsupportedOperationException.class)
-    public void testUpdate() throws WriteFailedException {
+    @Test
+    public void testWriteNat64(
+            @InjectTestData(resourcePath = "/nat64/external-ip-pool.json", id = NAT_INSTANCES_PATH) NatInstances data)
+            throws WriteFailedException {
+        customizer.writeCurrentAttributes(IID, extractIpPool(data), writeContext);
+        final Nat64AddDelPoolAddrRange expectedRequest = getExpectedRequestNat64(true);
+        verify(jvppSnat).nat64AddDelPoolAddrRange(expectedRequest);
+    }
+
+        @Test(expected = UnsupportedOperationException.class)
+    public void testUpdateNat44() throws WriteFailedException {
         final ExternalIpAddressPool data = mock(ExternalIpAddressPool.class);
         customizer.updateCurrentAttributes(IID, data, data, writeContext);
     }
 
     @Test
-    public void testDelete(
-        @InjectTestData(resourcePath = "/nat44/external-ip-pool.json", id = NAT_INSTANCES_PATH) NatInstances data)
-        throws WriteFailedException {
+    public void testDeleteNat44(
+            @InjectTestData(resourcePath = "/nat44/external-ip-pool.json", id = NAT_INSTANCES_PATH) NatInstances data)
+            throws WriteFailedException {
         customizer.deleteCurrentAttributes(IID, extractIpPool(data), writeContext);
-        final SnatAddAddressRange expectedRequest = getExpectedRequest();
+        final SnatAddAddressRange expectedRequest = getExpectedRequestNat44(false);
         verify(jvppSnat).snatAddAddressRange(expectedRequest);
     }
 
+    @Test
+    public void testDeleteNat64(
+            @InjectTestData(resourcePath = "/nat64/external-ip-pool.json", id = NAT_INSTANCES_PATH) NatInstances data)
+            throws WriteFailedException {
+        customizer.deleteCurrentAttributes(IID, extractIpPool(data), writeContext);
+        final Nat64AddDelPoolAddrRange expectedRequest = getExpectedRequestNat64(false);
+        verify(jvppSnat).nat64AddDelPoolAddrRange(expectedRequest);
+    }
+
     private static ExternalIpAddressPool extractIpPool(NatInstances data) {
         // assumes single nat instance and single ip pool
         return data.getNatInstance().get(0).getExternalIpAddressPool().get(0);
     }
 
-    private static SnatAddAddressRange getExpectedRequest() {
+    private SnatAddAddressRange getExpectedRequestNat44(final boolean isAdd) {
         final SnatAddAddressRange expectedRequest = new SnatAddAddressRange();
+        expectedRequest.isAdd = booleanToByte(isAdd);
         expectedRequest.isIp4 = 1;
         expectedRequest.firstIpAddress = new byte[] {(byte) 192, (byte) 168, 1, 0};
         expectedRequest.lastIpAddress = new byte[] {(byte) 192, (byte) 168, 1, (byte) 255};
         return expectedRequest;
     }
+
+    private Nat64AddDelPoolAddrRange getExpectedRequestNat64(final boolean isAdd) {
+        final Nat64AddDelPoolAddrRange expectedRequest = new Nat64AddDelPoolAddrRange();
+        expectedRequest.isAdd = booleanToByte(isAdd);
+        expectedRequest.startAddr = new byte[] {(byte) 192, (byte) 168, 1, 0};
+        expectedRequest.endAddr = new byte[] {(byte) 192, (byte) 168, 1, (byte) 255};
+        return expectedRequest;
+    }
 }
\ No newline at end of file
diff --git a/nat/nat2vpp/src/test/resources/nat64/external-ip-pool.json b/nat/nat2vpp/src/test/resources/nat64/external-ip-pool.json
new file mode 100644 (file)
index 0000000..3be25d2
--- /dev/null
@@ -0,0 +1,13 @@
+{
+  "nat-instances" : {
+    "nat-instance" : {
+      "id" : 0,
+      "external-ip-address-pool": {
+        "pool-id": 22,
+        "external-ip-pool": "192.168.1.1/24",
+        "vpp-nat:pool-type": "nat64"
+      }
+    }
+  }
+}
+