HC2VPP-105: add support for NAT64 BIB entries configuration 56/7956/3
authorMarek Gradzki <[email protected]>
Wed, 9 Aug 2017 10:30:05 +0000 (12:30 +0200)
committerJan Srnicek <[email protected]>
Mon, 14 Aug 2017 07:59:38 +0000 (07:59 +0000)
No read support due to issues with nat64_bib_dump

Change-Id: I851c4fc5084d6e29d622df2855cf8d47ba147015
Signed-off-by: Marek Gradzki <[email protected]>
nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/MappingEntryCustomizer.java
nat/nat2vpp/src/test/java/io/fd/hc2vpp/nat/write/ExternalIpPoolCustomizerTest.java
nat/nat2vpp/src/test/java/io/fd/hc2vpp/nat/write/MappingEntryCustomizerTest.java
nat/nat2vpp/src/test/resources/nat44/external-ip-pool.json [moved from nat/nat2vpp/src/test/resources/nat/external-ip-pool.json with 100% similarity]
nat/nat2vpp/src/test/resources/nat44/static-mapping-address-update.json [moved from nat/nat2vpp/src/test/resources/nat/static-mapping-address-update.json with 100% similarity]
nat/nat2vpp/src/test/resources/nat44/static-mapping-unsupported-proto.json [moved from nat/nat2vpp/src/test/resources/nat/static-mapping-unsupported-proto.json with 100% similarity]
nat/nat2vpp/src/test/resources/nat44/static-mapping.json [moved from nat/nat2vpp/src/test/resources/nat/static-mapping.json with 100% similarity]
nat/nat2vpp/src/test/resources/nat64/static-mapping-address-update.json [new file with mode: 0644]
nat/nat2vpp/src/test/resources/nat64/static-mapping-unsupported-proto.json [new file with mode: 0644]
nat/nat2vpp/src/test/resources/nat64/static-mapping.json [new file with mode: 0644]

index 999b811..0d08a55 100644 (file)
 package io.fd.hc2vpp.nat.write;
 
 import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
 
 import com.google.common.base.Optional;
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
 import io.fd.hc2vpp.common.translate.util.Ipv4Translator;
+import io.fd.hc2vpp.common.translate.util.Ipv6Translator;
 import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
 import io.fd.hc2vpp.nat.util.MappingEntryContext;
 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.Nat64AddDelStaticBib;
 import io.fd.vpp.jvpp.snat.dto.SnatAddStaticMapping;
 import io.fd.vpp.jvpp.snat.future.FutureJVppSnatFacade;
 import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.PortNumber;
 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.nat.instance.mapping.table.MappingEntry;
@@ -39,7 +46,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 final class MappingEntryCustomizer implements ListWriterCustomizer<MappingEntry, MappingEntryKey>,
-        JvppReplyConsumer, Ipv4Translator {
+        JvppReplyConsumer, Ipv4Translator, Ipv6Translator, ByteDataTranslator {
 
     private static final Logger LOG = LoggerFactory.getLogger(MappingEntryCustomizer.class);
 
@@ -64,8 +71,7 @@ final class MappingEntryCustomizer implements ListWriterCustomizer<MappingEntry,
         final Long mappingEntryId = id.firstKeyOf(MappingEntry.class).getIndex();
         LOG.debug("Writing mapping entry: {} for nat-instance(vrf): {}", natInstanceId, mappingEntryId);
 
-        final SnatAddStaticMapping request = getRequest(id, dataAfter, natInstanceId, true);
-        getReplyForWrite(jvppSnat.snatAddStaticMapping(request).toCompletableFuture(), id);
+        configureMapping(id, dataAfter, natInstanceId, true);
 
         // Store context mapping only if not already present under the same exact mapping
         synchronized (mappingEntryContext) {
@@ -74,7 +80,25 @@ final class MappingEntryCustomizer implements ListWriterCustomizer<MappingEntry,
                         .addEntry(natInstanceId, mappingEntryId, dataAfter, writeContext.getMappingContext());
             }
         }
-        LOG.trace("Mapping entry: {} for nat-instance(vrf): {} written successfully", request.vrfId, id);
+        LOG.trace("Mapping entry: {} for nat-instance(vrf): {} written successfully", natInstanceId, id);
+    }
+
+    private void configureMapping(@Nonnull final InstanceIdentifier<MappingEntry> id,
+                                  @Nonnull final MappingEntry entry,
+                                  @Nonnull final Long natInstanceId,
+                                  final boolean isAdd) throws WriteFailedException {
+        final IpAddress internalSrcAddress = entry.getInternalSrcAddress();
+        final Ipv4Address internalV4SrcAddress = internalSrcAddress.getIpv4Address();
+        final Ipv6Address internalV6SrcAddress = internalSrcAddress.getIpv6Address();
+        if (internalV4SrcAddress != null) {
+            final SnatAddStaticMapping request = getNat44Request(id, entry, natInstanceId, isAdd);
+            getReplyForWrite(jvppSnat.snatAddStaticMapping(request).toCompletableFuture(), id);
+        } else {
+            checkState(internalV6SrcAddress != null,
+                    "internalSrcAddress.getIpv6Address() should not return null if v4 address is not given");
+            final Nat64AddDelStaticBib request = getNat64Request(id, entry, natInstanceId, isAdd);
+            getReplyForWrite(jvppSnat.nat64AddDelStaticBib(request).toCompletableFuture(), id);
+        }
     }
 
     /**
@@ -119,49 +143,43 @@ final class MappingEntryCustomizer implements ListWriterCustomizer<MappingEntry,
         final MappingEntryKey mappingEntryKey = id.firstKeyOf(MappingEntry.class);
         LOG.debug("Deleting mapping entry: {} for nat-instance(vrf): {}", natInstanceId, mappingEntryKey);
 
-        final SnatAddStaticMapping request = getRequest(id, dataBefore, natInstanceId, false);
-        getReplyForWrite(jvppSnat.snatAddStaticMapping(request).toCompletableFuture(), id);
+        configureMapping(id, dataBefore, natInstanceId, false);
         mappingEntryContext.removeEntry(natInstanceId, dataBefore, writeContext.getMappingContext());
-        LOG.trace("Mapping entry: {} for nat-instance(vrf): {} deleted successfully", request.vrfId, id);
+        LOG.trace("Mapping entry: {} for nat-instance(vrf): {} deleted successfully", natInstanceId, id);
     }
 
-    private SnatAddStaticMapping getRequest(final InstanceIdentifier<MappingEntry> id,
-                                            final MappingEntry dataAfter,
-                                            final Long natInstanceId,
-                                            final boolean isAdd)
+    private SnatAddStaticMapping getNat44Request(final InstanceIdentifier<MappingEntry> id,
+                                                 final MappingEntry mappingEntry,
+                                                 final Long natInstanceId,
+                                                 final boolean isAdd)
             throws WriteFailedException.CreateFailedException {
         final SnatAddStaticMapping request = new SnatAddStaticMapping();
-        request.isAdd = isAdd
-                ? (byte) 1
-                : 0;
+        request.isAdd = booleanToByte(isAdd);
         request.isIp4 = 1;
         // VPP uses int, model long
         request.vrfId = natInstanceId.intValue();
 
-        // Snat supports only ipv4 now
-        if (dataAfter.getInternalSrcAddress().getIpv4Address() == null) {
-            throw new WriteFailedException.CreateFailedException(id, dataAfter,
-                    new UnsupportedOperationException(
-                            String.format("No Ipv4 present for in address %s. Ipv6 not supported",
-                                    dataAfter.getInternalSrcAddress())));
-        }
+        final Ipv4Address internalAddress = mappingEntry.getInternalSrcAddress().getIpv4Address();
+        checkArgument(internalAddress != null, "No Ipv4 present in internal-src-address %s",
+                mappingEntry.getInternalSrcAddress());
 
         request.addrOnly = 1;
         request.localIpAddress =
-                ipv4AddressNoZoneToArray(dataAfter.getInternalSrcAddress().getIpv4Address().getValue());
-        request.externalIpAddress = ipv4AddressNoZoneToArray(dataAfter.getExternalSrcAddress().getValue());
+                ipv4AddressNoZoneToArray(mappingEntry.getInternalSrcAddress().getIpv4Address().getValue());
+        request.externalIpAddress = ipv4AddressNoZoneToArray(mappingEntry.getExternalSrcAddress().getValue());
         request.externalSwIfIndex = -1; // external ip address is ignored if externalSwIfIndex is given
         request.protocol = -1;
-        final Short protocol = dataAfter.getTransportProtocol();
+        final Short protocol = mappingEntry.getTransportProtocol();
         if (protocol != null) {
             checkArgument(protocol == 1 || protocol == 6 || protocol == 17,
-                "Unsupported protocol %s only ICMP, TCP and UDP are currently supported", protocol);
+                    "Unsupported protocol %s only ICMP(1), TCP(6) and UDP(17) are currently supported for Nat44",
+                    protocol);
             request.protocol = protocol.byteValue();
         }
 
-        Optional<Short> internalPortNumber = getPortNumber(id, dataAfter,
+        Optional<Short> internalPortNumber = getPortNumber(id, mappingEntry,
                 (entry) -> Optional.fromNullable(entry.getInternalSrcPort()).transform(PortNumber::getPortType));
-        Optional<Short> externalPortNumber = getPortNumber(id, dataAfter,
+        Optional<Short> externalPortNumber = getPortNumber(id, mappingEntry,
                 (entry) -> Optional.fromNullable(entry.getExternalSrcPort()).transform(PortNumber::getPortType));
         if (internalPortNumber.isPresent() && externalPortNumber.isPresent()) {
             request.addrOnly = 0;
@@ -171,6 +189,44 @@ final class MappingEntryCustomizer implements ListWriterCustomizer<MappingEntry,
         return request;
     }
 
+    private Nat64AddDelStaticBib getNat64Request(final InstanceIdentifier<MappingEntry> id,
+                                                 final MappingEntry mappingEntry,
+                                                 final Long natInstanceId,
+                                                 final boolean isAdd)
+            throws WriteFailedException.CreateFailedException {
+        final Nat64AddDelStaticBib request = new Nat64AddDelStaticBib();
+        request.isAdd = booleanToByte(isAdd);
+        // VPP uses int, model long
+        request.vrfId = natInstanceId.intValue();
+
+        final Ipv6Address internalAddress = mappingEntry.getInternalSrcAddress().getIpv6Address();
+        checkArgument(internalAddress != null, "No Ipv6 present in internal-src-address %s",
+                mappingEntry.getInternalSrcAddress());
+
+
+        request.iAddr = ipv6AddressNoZoneToArray(internalAddress);
+        request.oAddr = ipv4AddressNoZoneToArray(mappingEntry.getExternalSrcAddress().getValue());
+        request.proto = -1;
+        final Short protocol = mappingEntry.getTransportProtocol();
+        if (protocol != null) {
+            checkArgument(protocol == 1 || protocol == 6 || protocol == 17 || protocol == 58,
+                    "Unsupported protocol %s only ICMP(1), IPv6-ICMP(58), TCP(6) and UDP(17) are currently supported for Nat64",
+                    protocol);
+            request.proto = protocol.byteValue();
+        }
+
+        Optional<Short> internalPortNumber = getPortNumber(id, mappingEntry,
+                (entry) -> Optional.fromNullable(entry.getInternalSrcPort()).transform(PortNumber::getPortType));
+        Optional<Short> externalPortNumber = getPortNumber(id, mappingEntry,
+                (entry) -> Optional.fromNullable(entry.getExternalSrcPort()).transform(PortNumber::getPortType));
+        if (internalPortNumber.isPresent() && externalPortNumber.isPresent()) {
+            request.iPort = internalPortNumber.get();
+            request.oPort = externalPortNumber.get();
+        }
+        return request;
+    }
+
+
     private Optional<Short> getPortNumber(final InstanceIdentifier<MappingEntry> id, final MappingEntry dataAfter,
                                           final PortGetter portGetter) {
         return portGetter.getPortType(dataAfter).transform(port -> {
index 917b9a9..c414c2b 100644 (file)
@@ -63,7 +63,7 @@ public class ExternalIpPoolCustomizerTest extends WriterCustomizerTest implement
 
     @Test
     public void testWrite(
-        @InjectTestData(resourcePath = "/nat/external-ip-pool.json", id = NAT_INSTANCES_PATH) NatInstances data)
+        @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();
@@ -79,7 +79,7 @@ public class ExternalIpPoolCustomizerTest extends WriterCustomizerTest implement
 
     @Test
     public void testDelete(
-        @InjectTestData(resourcePath = "/nat/external-ip-pool.json", id = NAT_INSTANCES_PATH) NatInstances data)
+        @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();
index 1d5eff7..008ac08 100644 (file)
@@ -26,6 +26,8 @@ import io.fd.hc2vpp.nat.util.MappingEntryContext;
 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.Nat64AddDelStaticBib;
+import io.fd.vpp.jvpp.snat.dto.Nat64AddDelStaticBibReply;
 import io.fd.vpp.jvpp.snat.dto.SnatAddStaticMapping;
 import io.fd.vpp.jvpp.snat.dto.SnatAddStaticMappingReply;
 import io.fd.vpp.jvpp.snat.future.FutureJVppSnatFacade;
@@ -63,44 +65,83 @@ public class MappingEntryCustomizerTest extends WriterCustomizerTest implements
     public void setUpTest() {
         customizer = new MappingEntryCustomizer(jvppSnat, mappingContext);
         when(jvppSnat.snatAddStaticMapping(any())).thenReturn(future(new SnatAddStaticMappingReply()));
+        when(jvppSnat.nat64AddDelStaticBib(any())).thenReturn(future(new Nat64AddDelStaticBibReply()));
     }
 
     @Test
-    public void testWrite(
-        @InjectTestData(resourcePath = "/nat/static-mapping.json", id = MAPPING_TABLE_PATH) MappingTable data)
-        throws WriteFailedException {
+    public void testWriteNat44(
+            @InjectTestData(resourcePath = "/nat44/static-mapping.json", id = MAPPING_TABLE_PATH) MappingTable data)
+            throws WriteFailedException {
         customizer.writeCurrentAttributes(IID, extractMappingEntry(data), writeContext);
-        final SnatAddStaticMapping expectedRequest = getExpectedRequest();
+        final SnatAddStaticMapping expectedRequest = getExpectedNat44Request();
         expectedRequest.isAdd = 1;
         verify(jvppSnat).snatAddStaticMapping(expectedRequest);
     }
 
+    @Test
+    public void testWriteNat64(
+            @InjectTestData(resourcePath = "/nat64/static-mapping.json", id = MAPPING_TABLE_PATH) MappingTable data)
+            throws WriteFailedException {
+        customizer.writeCurrentAttributes(IID, extractMappingEntry(data), writeContext);
+        final Nat64AddDelStaticBib expectedRequest = getExpectedNat64Request();
+        expectedRequest.isAdd = 1;
+        verify(jvppSnat).nat64AddDelStaticBib(expectedRequest);
+    }
+
     @Test(expected = IllegalArgumentException.class)
-    public void testWriteUnsupportedProtocol(
-        @InjectTestData(resourcePath = "/nat/static-mapping-unsupported-proto.json", id = MAPPING_TABLE_PATH) MappingTable data)
-        throws WriteFailedException {
+    public void testWriteNat44UnsupportedProtocol(
+            @InjectTestData(resourcePath = "/nat44/static-mapping-unsupported-proto.json", id = MAPPING_TABLE_PATH) MappingTable data)
+            throws WriteFailedException {
+        customizer.writeCurrentAttributes(IID, extractMappingEntry(data), writeContext);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testWriteNat64UnsupportedProtocol(
+            @InjectTestData(resourcePath = "/nat64/static-mapping-unsupported-proto.json", id = MAPPING_TABLE_PATH) MappingTable data)
+            throws WriteFailedException {
         customizer.writeCurrentAttributes(IID, extractMappingEntry(data), writeContext);
     }
 
     @Test
-    public void testUpdate(
-        @InjectTestData(resourcePath = "/nat/static-mapping.json", id = MAPPING_TABLE_PATH) MappingTable before,
-        @InjectTestData(resourcePath = "/nat/static-mapping-address-update.json", id = MAPPING_TABLE_PATH) MappingTable after)
-        throws WriteFailedException {
+    public void testUpdateNat44(
+            @InjectTestData(resourcePath = "/nat44/static-mapping.json", id = MAPPING_TABLE_PATH) MappingTable before,
+            @InjectTestData(resourcePath = "/nat44/static-mapping-address-update.json", id = MAPPING_TABLE_PATH) MappingTable after)
+            throws WriteFailedException {
         customizer.updateCurrentAttributes(IID, extractMappingEntry(before), extractMappingEntry(after), writeContext);
-        final SnatAddStaticMapping expectedDeleteRequest = getExpectedRequest();
+        final SnatAddStaticMapping expectedDeleteRequest = getExpectedNat44Request();
         verify(jvppSnat).snatAddStaticMapping(expectedDeleteRequest);
-        final SnatAddStaticMapping expectedUpdateRequest = getExpectedUpdateRequest();
+        final SnatAddStaticMapping expectedUpdateRequest = getExpectedNat44UpdateRequest();
         expectedUpdateRequest.isAdd = 1;
         verify(jvppSnat).snatAddStaticMapping(expectedUpdateRequest);
     }
 
     @Test
-    public void testDelete(
-        @InjectTestData(resourcePath = "/nat/static-mapping.json", id = MAPPING_TABLE_PATH) MappingTable data)
-        throws WriteFailedException {
+    public void testUpdateNat64(
+            @InjectTestData(resourcePath = "/nat64/static-mapping.json", id = MAPPING_TABLE_PATH) MappingTable before,
+            @InjectTestData(resourcePath = "/nat64/static-mapping-address-update.json", id = MAPPING_TABLE_PATH) MappingTable after)
+            throws WriteFailedException {
+        customizer.updateCurrentAttributes(IID, extractMappingEntry(before), extractMappingEntry(after), writeContext);
+        final Nat64AddDelStaticBib expectedDeleteRequest = getExpectedNat64Request();
+        verify(jvppSnat).nat64AddDelStaticBib(expectedDeleteRequest);
+        final Nat64AddDelStaticBib expectedUpdateRequest = getExpectedNat64UpdateRequest();
+        expectedUpdateRequest.isAdd = 1;
+        verify(jvppSnat).nat64AddDelStaticBib(expectedUpdateRequest);
+    }
+
+    @Test
+    public void testDeleteNat44(
+            @InjectTestData(resourcePath = "/nat44/static-mapping.json", id = MAPPING_TABLE_PATH) MappingTable data)
+            throws WriteFailedException {
         customizer.deleteCurrentAttributes(IID, extractMappingEntry(data), writeContext);
-        verify(jvppSnat).snatAddStaticMapping(getExpectedRequest());
+        verify(jvppSnat).snatAddStaticMapping(getExpectedNat44Request());
+    }
+
+    @Test
+    public void testDeleteNat64(
+            @InjectTestData(resourcePath = "/nat64/static-mapping.json", id = MAPPING_TABLE_PATH) MappingTable data)
+            throws WriteFailedException {
+        customizer.deleteCurrentAttributes(IID, extractMappingEntry(data), writeContext);
+        verify(jvppSnat).nat64AddDelStaticBib(getExpectedNat64Request());
     }
 
     private static MappingEntry extractMappingEntry(MappingTable data) {
@@ -108,7 +149,7 @@ public class MappingEntryCustomizerTest extends WriterCustomizerTest implements
         return data.getMappingEntry().get(0);
     }
 
-    private static SnatAddStaticMapping getExpectedRequest() {
+    private static SnatAddStaticMapping getExpectedNat44Request() {
         final SnatAddStaticMapping expectedRequest = new SnatAddStaticMapping();
         expectedRequest.isIp4 = 1;
         expectedRequest.addrOnly = 1;
@@ -120,7 +161,16 @@ public class MappingEntryCustomizerTest extends WriterCustomizerTest implements
         return expectedRequest;
     }
 
-    private static SnatAddStaticMapping getExpectedUpdateRequest() {
+    private static Nat64AddDelStaticBib getExpectedNat64Request() {
+        final Nat64AddDelStaticBib expectedRequest = new Nat64AddDelStaticBib();
+        expectedRequest.proto = 58; // icmp v6
+        expectedRequest.vrfId = (int) NAT_INSTANCE_ID;
+        expectedRequest.iAddr = new byte[] {0x20, 0x01, 0x0d, (byte) 0xb8, (byte) 0x85, (byte) 0xa3, 0, 0, 0, 0, (byte) 0x8a, 0x2e, 0x03, 0x70, 0x73, 0x33};
+        expectedRequest.oAddr = new byte[] {10, 1, 1, 3};
+        return expectedRequest;
+    }
+
+    private static SnatAddStaticMapping getExpectedNat44UpdateRequest() {
         final SnatAddStaticMapping expectedRequest = new SnatAddStaticMapping();
         expectedRequest.isIp4 = 1;
         expectedRequest.addrOnly = 1;
@@ -131,4 +181,15 @@ public class MappingEntryCustomizerTest extends WriterCustomizerTest implements
         expectedRequest.externalIpAddress = new byte[] {45, 1, 5, 6};
         return expectedRequest;
     }
+
+    private static Nat64AddDelStaticBib getExpectedNat64UpdateRequest() {
+        final Nat64AddDelStaticBib expectedRequest = new Nat64AddDelStaticBib();
+        expectedRequest.proto = 58; // icmp v6
+        expectedRequest.vrfId = (int) NAT_INSTANCE_ID;
+        expectedRequest.iAddr = new byte[] {0x20, 0x01, 0x0d, (byte) 0xb8, (byte) 0x85, (byte) 0xa3, 0, 0, 0, 0, (byte) 0x8a, 0x2e, 0x03, 0x70, 0x73, 0x34};
+        expectedRequest.oAddr = new byte[] {10, 1, 1, 4};
+        expectedRequest.iPort = 1234;
+        expectedRequest.oPort = 5678;
+        return expectedRequest;
+    }
 }
\ No newline at end of file
diff --git a/nat/nat2vpp/src/test/resources/nat64/static-mapping-address-update.json b/nat/nat2vpp/src/test/resources/nat64/static-mapping-address-update.json
new file mode 100644 (file)
index 0000000..73f2c0e
--- /dev/null
@@ -0,0 +1,17 @@
+{
+  "mapping-table" : {
+    "mapping-entry": {
+      "index": 58,
+      "type": "static",
+      "transport-protocol": 58,
+      "internal-src-address": "2001:db8:85a3::8a2e:370:7334",
+      "external-src-address": "10.1.1.4",
+      "internal-src-port" : {
+        "single-port-number" : 1234
+      },
+      "external-src-port" : {
+        "single-port-number" : 5678
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/nat/nat2vpp/src/test/resources/nat64/static-mapping-unsupported-proto.json b/nat/nat2vpp/src/test/resources/nat64/static-mapping-unsupported-proto.json
new file mode 100644 (file)
index 0000000..bbe8a20
--- /dev/null
@@ -0,0 +1,12 @@
+{
+  "mapping-table" : {
+    "mapping-entry": {
+      "index": 58,
+      "type": "static",
+      "transport-protocol": 123,
+      "internal-src-address": "2001:db8:85a3::8a2e:370:7333",
+      "external-src-address": "10.1.1.3"
+    }
+  }
+}
+
diff --git a/nat/nat2vpp/src/test/resources/nat64/static-mapping.json b/nat/nat2vpp/src/test/resources/nat64/static-mapping.json
new file mode 100644 (file)
index 0000000..d3a1c40
--- /dev/null
@@ -0,0 +1,12 @@
+{
+  "mapping-table" : {
+    "mapping-entry": {
+      "index": 58,
+      "type": "static",
+      "transport-protocol": 58,
+      "internal-src-address": "2001:db8:85a3::8a2e:370:7333",
+      "external-src-address": "10.1.1.3"
+    }
+  }
+}
+