HC2VPP-105: add support for NAT64 BIB entries read 58/7958/2
authorMarek Gradzki <[email protected]>
Wed, 9 Aug 2017 10:30:21 +0000 (12:30 +0200)
committerMarek Gradzki <[email protected]>
Thu, 17 Aug 2017 08:43:41 +0000 (10:43 +0200)
Change-Id: Ic8e61a13cba8ae8e3e69f16985918451df239430
Signed-off-by: Marek Gradzki <[email protected]>
nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/MappingEntryCustomizer.java
nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/NatInstanceCustomizer.java
nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/NatReaderFactory.java
nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/util/MappingEntryContext.java
nat/nat2vpp/src/test/java/io/fd/hc2vpp/nat/read/MappingEntryCustomizerTest.java
nat/nat2vpp/src/test/java/io/fd/hc2vpp/nat/read/NatInstanceCustomizerTest.java
nat/nat2vpp/src/test/java/io/fd/hc2vpp/nat/util/MappingEntryContextTest.java

index ae4f119..2732c5f 100644 (file)
@@ -17,6 +17,7 @@
 package io.fd.hc2vpp.nat.read;
 
 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.read.ReadContext;
@@ -26,11 +27,15 @@ import io.fd.honeycomb.translate.spi.read.InitializingListReaderCustomizer;
 import io.fd.honeycomb.translate.util.RWUtils;
 import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager;
 import io.fd.honeycomb.translate.util.read.cache.EntityDumpExecutor;
+import io.fd.vpp.jvpp.snat.dto.Nat64BibDetails;
+import io.fd.vpp.jvpp.snat.dto.Nat64BibDetailsReplyDump;
+import io.fd.vpp.jvpp.snat.dto.Nat64BibDump;
 import io.fd.vpp.jvpp.snat.dto.SnatStaticMappingDetails;
 import io.fd.vpp.jvpp.snat.dto.SnatStaticMappingDetailsReplyDump;
 import io.fd.vpp.jvpp.snat.dto.SnatStaticMappingDump;
 import io.fd.vpp.jvpp.snat.future.FutureJVppSnatFacade;
 import java.util.List;
+import java.util.Optional;
 import java.util.stream.Collectors;
 import javax.annotation.Nonnull;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
@@ -50,18 +55,21 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-final class MappingEntryCustomizer implements Ipv4Translator,
+final class MappingEntryCustomizer implements Ipv4Translator, Ipv6Translator,
         InitializingListReaderCustomizer<MappingEntry, MappingEntryKey, MappingEntryBuilder> {
 
     private static final Logger LOG = LoggerFactory.getLogger(MappingEntryCustomizer.class);
 
-    private final DumpCacheManager<SnatStaticMappingDetailsReplyDump, Void> dumpCacheManager;
+    private final DumpCacheManager<SnatStaticMappingDetailsReplyDump, Void> nat44DumpManager;
+    private final DumpCacheManager<Nat64BibDetailsReplyDump, Void> nat64DumpManager;
     private final MappingEntryContext mappingEntryContext;
 
     MappingEntryCustomizer(
-            final DumpCacheManager<SnatStaticMappingDetailsReplyDump, Void> dumpCacheManager,
+            final DumpCacheManager<SnatStaticMappingDetailsReplyDump, Void> nat44DumpManager,
+            final DumpCacheManager<Nat64BibDetailsReplyDump, Void> nat64DumpManager,
             final MappingEntryContext mappingEntryContext) {
-        this.dumpCacheManager = dumpCacheManager;
+        this.nat44DumpManager = nat44DumpManager;
+        this.nat64DumpManager = nat64DumpManager;
         this.mappingEntryContext = mappingEntryContext;
     }
 
@@ -79,34 +87,78 @@ final class MappingEntryCustomizer implements Ipv4Translator,
 
         final int idx = id.firstKeyOf(MappingEntry.class).getIndex().intValue();
         final int natInstanceId = id.firstKeyOf(NatInstance.class).getId().intValue();
-        final List<SnatStaticMappingDetails> details =
-                dumpCacheManager.getDump(id, ctx.getModificationCache(), null)
+        final List<SnatStaticMappingDetails> nat44Details =
+                nat44DumpManager.getDump(id, ctx.getModificationCache(), null)
                         .or(new SnatStaticMappingDetailsReplyDump()).snatStaticMappingDetails;
-        final SnatStaticMappingDetails snatStaticMappingDetails =
-                mappingEntryContext.findDetails(details, natInstanceId, idx, ctx.getMappingContext());
+        final Optional<SnatStaticMappingDetails> snat44StaticMappingDetails =
+                mappingEntryContext.findDetailsNat44(nat44Details, natInstanceId, idx, ctx.getMappingContext());
 
-        builder.setIndex((long) idx);
+        if (snat44StaticMappingDetails.isPresent()) {
+            readNat44Entry(builder, idx, snat44StaticMappingDetails.get());
+        } else {
+            final List<Nat64BibDetails> nat64Details =
+                    nat64DumpManager.getDump(id, ctx.getModificationCache(), null)
+                            .or(new Nat64BibDetailsReplyDump()).nat64BibDetails;
+
+            final Optional<Nat64BibDetails> snat64StaticMappingDetails =
+                    mappingEntryContext.findDetailsNat64(nat64Details, natInstanceId, idx, ctx.getMappingContext());
+
+            if (snat64StaticMappingDetails.isPresent()) {
+                readNat64Entry(builder, idx, snat64StaticMappingDetails.get());
+            }
+        }
+
+
+        LOG.trace("Mapping-entry read as: {}", builder);
+    }
+
+    private void readNat44Entry(@Nonnull final MappingEntryBuilder builder,
+                                final int index, final SnatStaticMappingDetails detail) {
+        builder.setIndex((long) index);
         builder.setType(
                 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.MappingEntry.Type.Static);
-        // Snat only supports ipv4 for now
-        builder.setExternalSrcAddress(arrayToIpv4AddressNoZone(snatStaticMappingDetails.externalIpAddress));
+        builder.setExternalSrcAddress(arrayToIpv4AddressNoZone(detail.externalIpAddress));
         builder.setInternalSrcAddress(
-                new IpAddress(arrayToIpv4AddressNoZone(snatStaticMappingDetails.localIpAddress)));
+                new IpAddress(arrayToIpv4AddressNoZone(detail.localIpAddress)));
 
-        if (snatStaticMappingDetails.addrOnly == 0) {
+        if (detail.addrOnly == 0) {
             builder.setExternalSrcPort(new ExternalSrcPortBuilder()
                     .setPortType(new SinglePortNumberBuilder().setSinglePortNumber(new PortNumber(
-                            (int) snatStaticMappingDetails.externalPort))
+                            (int) detail.externalPort))
                             .build())
                     .build());
             builder.setInternalSrcPort(new InternalSrcPortBuilder()
                     .setPortType(new SinglePortNumberBuilder().setSinglePortNumber(new PortNumber(
-                            (int) snatStaticMappingDetails.localPort))
+                            (int) detail.localPort))
                             .build())
                     .build());
         }
+    }
 
-        LOG.trace("Mapping-entry read as: {}", builder);
+    private void readNat64Entry(@Nonnull final MappingEntryBuilder builder,
+                                final int index, final Nat64BibDetails detail) {
+        builder.setIndex((long) index);
+        if (detail.isStatic == 1) {
+            builder.setType(
+                    org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.MappingEntry.Type.Static);
+        } else {
+            builder.setType(
+                    org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.MappingEntry.Type.Dynamic);
+        }
+        builder.setExternalSrcAddress(arrayToIpv4AddressNoZone(detail.oAddr));
+        builder.setInternalSrcAddress(
+                new IpAddress(arrayToIpv6AddressNoZone(detail.iAddr)));
+
+        builder.setExternalSrcPort(new ExternalSrcPortBuilder()
+                .setPortType(new SinglePortNumberBuilder().setSinglePortNumber(new PortNumber(
+                        (int) detail.oPort))
+                        .build())
+                .build());
+        builder.setInternalSrcPort(new InternalSrcPortBuilder()
+                .setPortType(new SinglePortNumberBuilder().setSinglePortNumber(new PortNumber(
+                        (int) detail.iPort))
+                        .build())
+                .build());
     }
 
     @Nonnull
@@ -117,13 +169,24 @@ final class MappingEntryCustomizer implements Ipv4Translator,
         LOG.trace("Listing IDs for all mapping-entries within nat-instance(vrf):{}", natInstanceId);
 
         final List<MappingEntryKey> entryKeys =
-                dumpCacheManager.getDump(id, context.getModificationCache(), null)
+                nat44DumpManager.getDump(id, context.getModificationCache(), null)
                         .or(new SnatStaticMappingDetailsReplyDump()).snatStaticMappingDetails.stream()
                         .filter(detail -> natInstanceId == detail.vrfId)
                         .map(detail -> mappingEntryContext
                                 .getStoredOrArtificialIndex(natInstanceId, detail, context.getMappingContext()))
                         .map(MappingEntryKey::new)
                         .collect(Collectors.toList());
+
+
+        final List<MappingEntryKey> nat64Keys =
+                nat64DumpManager.getDump(id, context.getModificationCache(), null)
+                        .or(new Nat64BibDetailsReplyDump()).nat64BibDetails.stream()
+                        .filter(detail -> natInstanceId == detail.vrfId)
+                        .map(detail -> mappingEntryContext
+                                .getStoredOrArtificialIndex(natInstanceId, detail, context.getMappingContext()))
+                        .map(MappingEntryKey::new)
+                        .collect(Collectors.toList());
+        entryKeys.addAll(nat64Keys);
         LOG.debug("List of mapping-entry keys within nat-instance(vrf):{} : {}", natInstanceId, entryKeys);
 
         return entryKeys;
@@ -136,27 +199,31 @@ final class MappingEntryCustomizer implements Ipv4Translator,
     }
 
     @Override
-    public Initialized<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry> init(@Nonnull final InstanceIdentifier<MappingEntry> id,
-                                                                                                                                                                          @Nonnull final MappingEntry readValue,
-                                                                                                                                                                          @Nonnull final ReadContext ctx) {
+    public Initialized<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry> init(
+            @Nonnull final InstanceIdentifier<MappingEntry> id,
+            @Nonnull final MappingEntry readValue,
+            @Nonnull final ReadContext ctx) {
         return Initialized.create(getCfgId(id),
-                new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntryBuilder(readValue)
+                new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntryBuilder(
+                        readValue)
                         .build());
     }
 
-    static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry> getCfgId(final @Nonnull InstanceIdentifier<MappingEntry> id) {
+    static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry> getCfgId(
+            final @Nonnull InstanceIdentifier<MappingEntry> id) {
         return NatInstanceCustomizer.getCfgId(RWUtils.cutId(id, NatInstance.class))
                 .child(MappingTable.class)
                 .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry.class,
-                        new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntryKey(id.firstKeyOf(MappingEntry.class).getIndex()));
+                        new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntryKey(
+                                id.firstKeyOf(MappingEntry.class).getIndex()));
     }
 
-    static final class MappingEntryDumpExecutor
+    static final class MappingEntryNat44DumpExecutor
             implements EntityDumpExecutor<SnatStaticMappingDetailsReplyDump, Void>, JvppReplyConsumer {
 
         private final FutureJVppSnatFacade jvppSnat;
 
-        MappingEntryDumpExecutor(final FutureJVppSnatFacade jvppSnat) {
+        MappingEntryNat44DumpExecutor(final FutureJVppSnatFacade jvppSnat) {
             this.jvppSnat = jvppSnat;
         }
 
@@ -168,4 +235,23 @@ final class MappingEntryCustomizer implements Ipv4Translator,
                     identifier);
         }
     }
+
+    static final class MappingEntryNat64DumpExecutor
+            implements EntityDumpExecutor<Nat64BibDetailsReplyDump, Void>, JvppReplyConsumer {
+
+        private final FutureJVppSnatFacade jvppSnat;
+
+        MappingEntryNat64DumpExecutor(final FutureJVppSnatFacade jvppSnat) {
+            this.jvppSnat = jvppSnat;
+        }
+
+        @Nonnull
+        @Override
+        public Nat64BibDetailsReplyDump executeDump(final InstanceIdentifier<?> identifier, final Void params)
+                throws ReadFailedException {
+            final Nat64BibDump dump = new Nat64BibDump();
+            dump.proto = -1; // dump entries for all protocols
+            return getReplyForRead(jvppSnat.nat64BibDump(dump).toCompletableFuture(), identifier);
+        }
+    }
 }
index 9542587..18a9592 100644 (file)
@@ -21,9 +21,11 @@ import io.fd.honeycomb.translate.read.ReadFailedException;
 import io.fd.honeycomb.translate.spi.read.Initialized;
 import io.fd.honeycomb.translate.spi.read.InitializingListReaderCustomizer;
 import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager;
+import io.fd.vpp.jvpp.snat.dto.Nat64BibDetailsReplyDump;
 import io.fd.vpp.jvpp.snat.dto.SnatStaticMappingDetailsReplyDump;
 import java.util.List;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 import javax.annotation.Nonnull;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.NatConfig;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.NatInstancesBuilder;
@@ -39,16 +41,20 @@ import org.slf4j.LoggerFactory;
 /**
  * Nat instance ID is mapped to VRF-ID in VPP.
  */
-final class NatInstanceCustomizer implements InitializingListReaderCustomizer<NatInstance, NatInstanceKey, NatInstanceBuilder> {
+final class NatInstanceCustomizer
+        implements InitializingListReaderCustomizer<NatInstance, NatInstanceKey, NatInstanceBuilder> {
 
     private static final Logger LOG = LoggerFactory.getLogger(NatInstanceCustomizer.class);
     static final NatInstanceKey DEFAULT_VRF_ID = new NatInstanceKey(0L);
 
-    private final DumpCacheManager<SnatStaticMappingDetailsReplyDump, Void> dumpCacheManager;
+    private final DumpCacheManager<SnatStaticMappingDetailsReplyDump, Void> nat44DumpManager;
+    private final DumpCacheManager<Nat64BibDetailsReplyDump, Void> nat64DumpManager;
 
     NatInstanceCustomizer(
-            final DumpCacheManager<SnatStaticMappingDetailsReplyDump, Void> dumpCacheManager) {
-        this.dumpCacheManager = dumpCacheManager;
+            final DumpCacheManager<SnatStaticMappingDetailsReplyDump, Void> nat44DumpManager,
+            final DumpCacheManager<Nat64BibDetailsReplyDump, Void> nat64DumpManager) {
+        this.nat44DumpManager = nat44DumpManager;
+        this.nat64DumpManager = nat64DumpManager;
     }
 
     @Nonnull
@@ -72,12 +78,18 @@ final class NatInstanceCustomizer implements InitializingListReaderCustomizer<Na
         LOG.trace("Listing IDs for all nat-instances");
 
         // Find the nat instance IDs (vrf-ids) by listing all static mappings and their VRF assignment
-        final List<NatInstanceKey> vrfIds =
-                dumpCacheManager.getDump(id, context.getModificationCache(), null)
+        final List<NatInstanceKey> vrfIds = Stream.concat(
+                nat44DumpManager.getDump(id, context.getModificationCache(), null)
                         .or(new SnatStaticMappingDetailsReplyDump()).snatStaticMappingDetails.stream()
-                        .map(detail -> detail.vrfId)
-                        .map(vrfId -> new NatInstanceKey((long) vrfId))
-                        .collect(Collectors.toList());
+                        .map(detail -> detail.vrfId),
+                nat64DumpManager.getDump(id, context.getModificationCache(), null)
+                        .or(new Nat64BibDetailsReplyDump()).nat64BibDetails.stream()
+                        .map(detail -> detail.vrfId))
+                // V4 (nat44) and V6 (nat64) VRFs in VPP can have the same id. We store them under single nat instance,
+                // because the ietf-nat model does not require separate instances for nat44 and nat64 features.
+                .distinct()
+                .map(vrfId -> new NatInstanceKey((long) vrfId))
+                .collect(Collectors.toList());
 
         // Add default vrf id if not present
         if (!vrfIds.contains(DEFAULT_VRF_ID)) {
@@ -94,9 +106,10 @@ final class NatInstanceCustomizer implements InitializingListReaderCustomizer<Na
     }
 
     @Override
-    public Initialized<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.NatInstance> init(@Nonnull final InstanceIdentifier<NatInstance> id,
-                                                                                                                                              @Nonnull final NatInstance readValue,
-                                                                                                                                              @Nonnull final ReadContext ctx) {
+    public Initialized<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.NatInstance> init(
+            @Nonnull final InstanceIdentifier<NatInstance> id,
+            @Nonnull final NatInstance readValue,
+            @Nonnull final ReadContext ctx) {
         return Initialized.create(getCfgId(id),
                 new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.NatInstanceBuilder()
                         .setId(readValue.getId())
index 791b7bc..d9c7f33 100644 (file)
@@ -23,6 +23,7 @@ import io.fd.honeycomb.translate.impl.read.GenericInitListReader;
 import io.fd.honeycomb.translate.read.ReaderFactory;
 import io.fd.honeycomb.translate.read.registry.ModifiableReaderRegistryBuilder;
 import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager;
+import io.fd.vpp.jvpp.snat.dto.Nat64BibDetailsReplyDump;
 import io.fd.vpp.jvpp.snat.dto.SnatStaticMappingDetailsReplyDump;
 import io.fd.vpp.jvpp.snat.future.FutureJVppSnatFacade;
 import javax.annotation.Nonnull;
@@ -53,7 +54,8 @@ public class NatReaderFactory implements ReaderFactory {
 
     private final FutureJVppSnatFacade jvppSnat;
     private final MappingEntryContext mappingEntryContext;
-    private final DumpCacheManager<SnatStaticMappingDetailsReplyDump, Void> mapEntryDumpMgr;
+    private final DumpCacheManager<SnatStaticMappingDetailsReplyDump, Void> mapEntryNat44DumpMgr;
+    private final DumpCacheManager<Nat64BibDetailsReplyDump, Void> mapEntryNat64DumpMgr;
 
 
     @Inject
@@ -61,23 +63,29 @@ public class NatReaderFactory implements ReaderFactory {
                             final MappingEntryContext mappingEntryContext) {
         this.jvppSnat = jvppSnat;
         this.mappingEntryContext = mappingEntryContext;
-        this.mapEntryDumpMgr =
+        this.mapEntryNat44DumpMgr =
                 new DumpCacheManager.DumpCacheManagerBuilder<SnatStaticMappingDetailsReplyDump, Void>()
-                        .withExecutor(new MappingEntryCustomizer.MappingEntryDumpExecutor(jvppSnat))
+                        .withExecutor(new MappingEntryCustomizer.MappingEntryNat44DumpExecutor(jvppSnat))
                         .acceptOnly(SnatStaticMappingDetailsReplyDump.class)
                         .build();
+        this.mapEntryNat64DumpMgr =
+                new DumpCacheManager.DumpCacheManagerBuilder<Nat64BibDetailsReplyDump, Void>()
+                        .withExecutor(new MappingEntryCustomizer.MappingEntryNat64DumpExecutor(jvppSnat))
+                        .acceptOnly(Nat64BibDetailsReplyDump.class)
+                        .build();
     }
 
     @Override
     public void init(@Nonnull final ModifiableReaderRegistryBuilder registry) {
         registry.addStructuralReader(NAT_OPER_ID, NatStateBuilder.class);
         registry.addStructuralReader(NAT_INSTANCES_ID, NatInstancesBuilder.class);
-        registry.add(new GenericInitListReader<>(NAT_INSTANCE_ID, new NatInstanceCustomizer(mapEntryDumpMgr)));
+        registry.add(new GenericInitListReader<>(NAT_INSTANCE_ID,
+                new NatInstanceCustomizer(mapEntryNat44DumpMgr, mapEntryNat64DumpMgr)));
         registry.addStructuralReader(MAP_TABLE_ID, MappingTableBuilder.class);
         registry.subtreeAdd(Sets.newHashSet(InstanceIdentifier.create(MappingEntry.class).child(ExternalSrcPort.class),
                 InstanceIdentifier.create(MappingEntry.class).child(InternalSrcPort.class)),
                 new GenericInitListReader<>(MAP_ENTRY_ID,
-                        new MappingEntryCustomizer(mapEntryDumpMgr, mappingEntryContext)));
+                        new MappingEntryCustomizer(mapEntryNat44DumpMgr, mapEntryNat64DumpMgr, mappingEntryContext)));
 
         registry.addStructuralReader(CURRENT_CONFIG, NatCurrentConfigBuilder.class);
         registry.add(new GenericInitListReader<>(CURRENT_CONFIG.child(ExternalIpAddressPool.class),
index afdf8ab..292adc3 100644 (file)
@@ -21,7 +21,9 @@ import static com.google.common.base.Preconditions.checkArgument;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Optional;
 import io.fd.hc2vpp.common.translate.util.Ipv4Translator;
+import io.fd.hc2vpp.common.translate.util.Ipv6Translator;
 import io.fd.honeycomb.translate.MappingContext;
+import io.fd.vpp.jvpp.snat.dto.Nat64BibDetails;
 import io.fd.vpp.jvpp.snat.dto.SnatStaticMappingDetails;
 import java.util.Collections;
 import java.util.Comparator;
@@ -39,6 +41,7 @@ import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.nat.context
 import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.nat.context.rev161214.mapping.entry.context.attributes.nat.mapping.entry.context.nat.instance.mapping.table.MappingEntryKey;
 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.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -47,7 +50,7 @@ import org.slf4j.LoggerFactory;
  * Context tracker for Nat Mapping entries.
  */
 @ThreadSafe
-public class MappingEntryContext implements Ipv4Translator {
+public class MappingEntryContext implements Ipv4Translator, Ipv6Translator {
 
     private static final Logger LOG = LoggerFactory.getLogger(MappingEntryContext.class);
 
@@ -101,6 +104,12 @@ public class MappingEntryContext implements Ipv4Translator {
                 new IpAddress(new Ipv4Address(arrayToIpv4AddressNoZone(entry.localIpAddress))));
     }
 
+    private MappingEntryKey entryToKey(final Nat64BibDetails entry) {
+        return new MappingEntryKey(
+                new IpAddress(new Ipv4Address(arrayToIpv4AddressNoZone(entry.oAddr))),
+                new IpAddress(new Ipv6Address(arrayToIpv6AddressNoZone(entry.iAddr))));
+    }
+
     private boolean equalEntries(final SnatStaticMappingDetails detail, final MappingEntry ctxMappingEntry) {
         final IpAddress internalAddrFromDetails =
                 new IpAddress(new Ipv4Address(arrayToIpv4AddressNoZone(detail.localIpAddress)));
@@ -117,6 +126,22 @@ public class MappingEntryContext implements Ipv4Translator {
         return true;
     }
 
+    private boolean equalEntries(final Nat64BibDetails detail, final MappingEntry ctxMappingEntry) {
+        final IpAddress internalAddrFromDetails =
+                new IpAddress(new Ipv6Address(arrayToIpv6AddressNoZone(detail.iAddr)));
+        // Only IPv6
+        if (!ctxMappingEntry.getInternal().equals(internalAddrFromDetails)) {
+            return false;
+        }
+        // Only IPv4
+        final IpAddress externalAddrFromDetails =
+                new IpAddress(new Ipv4Address(arrayToIpv4AddressNoZone(detail.oAddr)));
+        if (!ctxMappingEntry.getExternal().equals(externalAddrFromDetails)) {
+            return false;
+        }
+        return true;
+    }
+
     @VisibleForTesting
     static MappingEntry toCtxMapEntry(
             @Nonnull final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry entry,
@@ -134,6 +159,13 @@ public class MappingEntryContext implements Ipv4Translator {
                 .build();
     }
 
+    private MappingEntry toCtxMapEntry(@Nonnull final Nat64BibDetails details, final long entryId) {
+        return new MappingEntryBuilder()
+                .setKey(entryToKey(details))
+                .setIndex(entryId)
+                .build();
+    }
+
     /**
      * Delete mapping of mapping entry to index from context.
      */
@@ -146,9 +178,9 @@ public class MappingEntryContext implements Ipv4Translator {
     /**
      * Find specific details in provided collection identified with provided index.
      */
-    public synchronized SnatStaticMappingDetails findDetails(@Nonnull final List<SnatStaticMappingDetails> details,
-                                                             final long natInstanceId, final long idx,
-                                                             @Nonnull final MappingContext mappingContext) {
+    public synchronized java.util.Optional<SnatStaticMappingDetails> findDetailsNat44(@Nonnull final List<SnatStaticMappingDetails> details,
+                                                                                      final long natInstanceId, final long idx,
+                                                                                      @Nonnull final MappingContext mappingContext) {
         // Find mapping entry for Index
         final MappingEntry ctxMappingEntry = mappingContext.read(getTableId(natInstanceId))
                 .transform(MappingTable::getMappingEntry)
@@ -162,9 +194,29 @@ public class MappingEntryContext implements Ipv4Translator {
         // Find which details matches the context stored entry under index
         return details.stream()
                 .filter(detail -> equalEntries(detail, ctxMappingEntry))
+                .findFirst();
+    }
+
+    /**
+     * Find specific details in provided collection identified with provided index.
+     */
+    public synchronized java.util.Optional<Nat64BibDetails> findDetailsNat64(@Nonnull final List<Nat64BibDetails> details,
+                                                                             final long natInstanceId, final long idx,
+                                                                             @Nonnull final MappingContext mappingContext) {
+        // Find mapping entry for Index
+        final MappingEntry ctxMappingEntry = mappingContext.read(getTableId(natInstanceId))
+                .transform(MappingTable::getMappingEntry)
+                .or(Collections.emptyList())
+                .stream()
+                .filter(entry -> entry.getIndex() == idx)
                 .findFirst()
-                .orElseThrow(() -> new IllegalStateException("Unable to match mapping for nat-instance: "
-                        + natInstanceId + " and match: " + ctxMappingEntry + " in: " + details));
+                .orElseThrow(() -> new IllegalStateException("Unable to find context mapping for nat-instance: "
+                        + natInstanceId + " and ID: " + idx));
+
+        // Find which details matches the context stored entry under index
+        return details.stream()
+                .filter(detail -> equalEntries(detail, ctxMappingEntry))
+                .findFirst();
     }
 
     /**
@@ -178,6 +230,17 @@ public class MappingEntryContext implements Ipv4Translator {
                 .or(() -> getArtificialId(details, natInstanceId, mappingContext));
     }
 
+    /**
+     * Get index for a mapping entry details or create an artificial one.
+     */
+    public synchronized long getStoredOrArtificialIndex(final Long natInstanceId,
+                                                        @Nonnull final Nat64BibDetails details,
+                                                        @Nonnull final MappingContext mappingContext) {
+        return mappingContext.read(getId(natInstanceId, entryToKey(details)))
+                .transform(MappingEntry::getIndex)
+                .or(() -> getArtificialId(details, natInstanceId, mappingContext));
+    }
+
     /**
      * Get index for a stored mapping entry.
      */
@@ -197,6 +260,15 @@ public class MappingEntryContext implements Ipv4Translator {
         return artificialIdx;
     }
 
+    private long getArtificialId(final Nat64BibDetails details, final Long natInstanceId,
+                                 final MappingContext mappingContext) {
+        LOG.trace("Assigning artificial ID for {}", details);
+        final long artificialIdx = findFreeIndex(natInstanceId, mappingContext);
+        LOG.debug("Artificial ID for {} assigned as: {}", details, artificialIdx);
+        mappingContext.put(getId(natInstanceId, entryToKey(details)), toCtxMapEntry(details, artificialIdx));
+        return artificialIdx;
+    }
+
     private long findFreeIndex(final long natInstanceId, final MappingContext mappingContext) {
         return mappingContext.read(getTableId(natInstanceId))
                 .transform(MappingTable::getMappingEntry)
index 678d67b..05513b6 100644 (file)
@@ -27,10 +27,13 @@ import io.fd.hc2vpp.nat.util.MappingEntryContext;
 import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
 import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager;
 import io.fd.honeycomb.translate.util.read.cache.EntityDumpExecutor;
+import io.fd.vpp.jvpp.snat.dto.Nat64BibDetails;
+import io.fd.vpp.jvpp.snat.dto.Nat64BibDetailsReplyDump;
 import io.fd.vpp.jvpp.snat.dto.SnatStaticMappingDetails;
 import io.fd.vpp.jvpp.snat.dto.SnatStaticMappingDetailsReplyDump;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Optional;
 import org.junit.Test;
 import org.mockito.Mock;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.NatInstances;
@@ -45,18 +48,22 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev1509
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
 public class MappingEntryCustomizerTest
-    extends InitializingListReaderCustomizerTest<MappingEntry, MappingEntryKey, MappingEntryBuilder> {
+        extends InitializingListReaderCustomizerTest<MappingEntry, MappingEntryKey, MappingEntryBuilder> {
 
     private static final long NAT_MAPPING_ID = 2L;
     private InstanceIdentifier<MappingEntry> mappingEntryId;
     private InstanceIdentifier<MappingEntry> mappingEntryWildcarded;
-    private DumpCacheManager<SnatStaticMappingDetailsReplyDump, Void> dumpCacheManager;
+    private DumpCacheManager<SnatStaticMappingDetailsReplyDump, Void> nat44DumpManager;
+    private DumpCacheManager<Nat64BibDetailsReplyDump, Void> nat64DumpManager;
 
     @Mock
     private MappingEntryContext mappingContext;
 
     @Mock
-    private EntityDumpExecutor<SnatStaticMappingDetailsReplyDump, Void> dumpExecutor;
+    private EntityDumpExecutor<SnatStaticMappingDetailsReplyDump, Void> nat44DumpExecutor;
+
+    @Mock
+    private EntityDumpExecutor<Nat64BibDetailsReplyDump, Void> nat64DumpExecutor;
 
     public MappingEntryCustomizerTest() {
         super(MappingEntry.class, MappingTableBuilder.class);
@@ -65,90 +72,199 @@ public class MappingEntryCustomizerTest
     @Override
     protected void setUp() throws Exception {
         mappingEntryId = InstanceIdentifier.create(NatInstances.class)
-            .child(NatInstance.class, new NatInstanceKey(NatInstanceCustomizer.DEFAULT_VRF_ID))
-            .child(MappingTable.class)
-            .child(MappingEntry.class, new MappingEntryKey(NAT_MAPPING_ID));
+                .child(NatInstance.class, new NatInstanceKey(NatInstanceCustomizer.DEFAULT_VRF_ID))
+                .child(MappingTable.class)
+                .child(MappingEntry.class, new MappingEntryKey(NAT_MAPPING_ID));
         mappingEntryWildcarded = InstanceIdentifier.create(NatInstances.class)
-            .child(NatInstance.class, new NatInstanceKey(NatInstanceCustomizer.DEFAULT_VRF_ID))
-            .child(MappingTable.class)
-            .child(MappingEntry.class);
-        dumpCacheManager = new DumpCacheManager.DumpCacheManagerBuilder<SnatStaticMappingDetailsReplyDump, Void>()
-            .withExecutor(dumpExecutor)
-            .acceptOnly(SnatStaticMappingDetailsReplyDump.class)
-            .build();
+                .child(NatInstance.class, new NatInstanceKey(NatInstanceCustomizer.DEFAULT_VRF_ID))
+                .child(MappingTable.class)
+                .child(MappingEntry.class);
+        nat44DumpManager = new DumpCacheManager.DumpCacheManagerBuilder<SnatStaticMappingDetailsReplyDump, Void>()
+                .withExecutor(nat44DumpExecutor)
+                .acceptOnly(SnatStaticMappingDetailsReplyDump.class)
+                .build();
+        nat64DumpManager = new DumpCacheManager.DumpCacheManagerBuilder<Nat64BibDetailsReplyDump, Void>()
+                .withExecutor(nat64DumpExecutor)
+                .acceptOnly(Nat64BibDetailsReplyDump.class)
+                .build();
     }
 
     @Test
-    public void testReadAttributes() throws Exception {
-        final SnatStaticMappingDetailsReplyDump dump = dumpNonEmptyDefaultInstance();
-        when(dumpExecutor.executeDump(mappingEntryId, null)).thenReturn(dump);
+    public void testReadNat44() throws Exception {
+        final SnatStaticMappingDetailsReplyDump dumpNat44 = dumpReplyNat44NonEmpty();
+        when(nat44DumpExecutor.executeDump(mappingEntryId, null)).thenReturn(dumpNat44);
         final MappingEntryBuilder builder = new MappingEntryBuilder();
-        when(mappingContext.findDetails(dump.snatStaticMappingDetails, NatInstanceCustomizer.DEFAULT_VRF_ID.getId(),
-            NAT_MAPPING_ID, ctx.getMappingContext())).thenReturn(dump.snatStaticMappingDetails.get(2));
+        when(mappingContext
+                .findDetailsNat44(dumpNat44.snatStaticMappingDetails, NatInstanceCustomizer.DEFAULT_VRF_ID.getId(),
+                        NAT_MAPPING_ID, ctx.getMappingContext()))
+                .thenReturn(Optional.of(dumpNat44.snatStaticMappingDetails.get(2)));
         getCustomizer().readCurrentAttributes(mappingEntryId, builder, ctx);
 
         assertEquals(NAT_MAPPING_ID, builder.getIndex().longValue());
         assertEquals("192.168.3.8", builder.getExternalSrcAddress().getValue());
         assertEquals(6874,
-            ((SinglePortNumber) builder.getExternalSrcPort().getPortType()).getSinglePortNumber().getValue()
-                .intValue());
+                ((SinglePortNumber) builder.getExternalSrcPort().getPortType()).getSinglePortNumber().getValue()
+                        .intValue());
         assertArrayEquals("192.168.2.2".toCharArray(), builder.getInternalSrcAddress().getValue());
         assertEquals(1274,
-            ((SinglePortNumber) builder.getInternalSrcPort().getPortType()).getSinglePortNumber().getValue()
-                .intValue());
+                ((SinglePortNumber) builder.getInternalSrcPort().getPortType()).getSinglePortNumber().getValue()
+                        .intValue());
+    }
+
+    @Test
+    public void testReadNat64() throws Exception {
+        when(nat44DumpExecutor.executeDump(mappingEntryId, null)).thenReturn(new SnatStaticMappingDetailsReplyDump());
+        final Nat64BibDetailsReplyDump dumpNat64 = dumpReplyNat64NonEmpty();
+        when(nat64DumpExecutor.executeDump(mappingEntryId, null)).thenReturn(dumpNat64);
+        final MappingEntryBuilder builder = new MappingEntryBuilder();
+        when(mappingContext
+                .findDetailsNat64(dumpNat64.nat64BibDetails, NatInstanceCustomizer.DEFAULT_VRF_ID.getId(),
+                        NAT_MAPPING_ID, ctx.getMappingContext()))
+                .thenReturn(Optional.of(dumpNat64.nat64BibDetails.get(2)));
+        getCustomizer().readCurrentAttributes(mappingEntryId, builder, ctx);
+
+        assertEquals(NAT_MAPPING_ID, builder.getIndex().longValue());
+        assertEquals("192.168.64.3", builder.getExternalSrcAddress().getValue());
+        assertEquals(6874,
+                ((SinglePortNumber) builder.getExternalSrcPort().getPortType()).getSinglePortNumber().getValue()
+                        .intValue());
+        assertArrayEquals("2001:db8:85a3::8a2e:370:7303".toCharArray(), builder.getInternalSrcAddress().getValue());
+        assertEquals(1274,
+                ((SinglePortNumber) builder.getInternalSrcPort().getPortType()).getSinglePortNumber().getValue()
+                        .intValue());
     }
 
     @Test
-    public void testGetAll() throws Exception {
-        final SnatStaticMappingDetailsReplyDump dump = dumpNonEmptyDefaultInstance();
-        when(dumpExecutor.executeDump(mappingEntryWildcarded, null)).thenReturn(dump);
+    public void testReadAllNat44() throws Exception {
+        final SnatStaticMappingDetailsReplyDump dumpNat44 = dumpReplyNat44NonEmpty();
+        when(nat44DumpExecutor.executeDump(mappingEntryWildcarded, null)).thenReturn(dumpNat44);
+        when(nat64DumpExecutor.executeDump(mappingEntryWildcarded, null)).thenReturn(new Nat64BibDetailsReplyDump());
         when(mappingContext.getStoredOrArtificialIndex(NatInstanceCustomizer.DEFAULT_VRF_ID.getId(),
-            dump.snatStaticMappingDetails.get(0), ctx.getMappingContext())).thenReturn(0L);
+                dumpNat44.snatStaticMappingDetails.get(0), ctx.getMappingContext())).thenReturn(0L);
         when(mappingContext.getStoredOrArtificialIndex(NatInstanceCustomizer.DEFAULT_VRF_ID.getId(),
-            dump.snatStaticMappingDetails.get(1), ctx.getMappingContext())).thenReturn(1L);
+                dumpNat44.snatStaticMappingDetails.get(1), ctx.getMappingContext())).thenReturn(1L);
         when(mappingContext.getStoredOrArtificialIndex(NatInstanceCustomizer.DEFAULT_VRF_ID.getId(),
-            dump.snatStaticMappingDetails.get(2), ctx.getMappingContext())).thenReturn(2L);
+                dumpNat44.snatStaticMappingDetails.get(2), ctx.getMappingContext())).thenReturn(2L);
 
         final List<MappingEntryKey> allIds = getCustomizer().getAllIds(mappingEntryWildcarded, ctx);
         assertThat(allIds, hasItems(new MappingEntryKey(0L), new MappingEntryKey(2L)));
     }
 
+    @Test
+    public void testReadAllNat64() throws Exception {
+        final Nat64BibDetailsReplyDump dumpNat64 = dumpReplyNat64NonEmpty();
+        when(nat44DumpExecutor.executeDump(mappingEntryWildcarded, null))
+                .thenReturn(new SnatStaticMappingDetailsReplyDump());
+        when(nat64DumpExecutor.executeDump(mappingEntryWildcarded, null)).thenReturn(dumpNat64);
+        when(mappingContext.getStoredOrArtificialIndex(NatInstanceCustomizer.DEFAULT_VRF_ID.getId(),
+                dumpNat64.nat64BibDetails.get(0), ctx.getMappingContext())).thenReturn(0L);
+        when(mappingContext.getStoredOrArtificialIndex(NatInstanceCustomizer.DEFAULT_VRF_ID.getId(),
+                dumpNat64.nat64BibDetails.get(1), ctx.getMappingContext())).thenReturn(1L);
+        when(mappingContext.getStoredOrArtificialIndex(NatInstanceCustomizer.DEFAULT_VRF_ID.getId(),
+                dumpNat64.nat64BibDetails.get(2), ctx.getMappingContext())).thenReturn(2L);
+
+        final List<MappingEntryKey> allIds = getCustomizer().getAllIds(mappingEntryWildcarded, ctx);
+        assertThat(allIds, hasItems(new MappingEntryKey(0L), new MappingEntryKey(2L)));
+    }
+
+    @Test
+    public void testReadAll() throws Exception {
+        final SnatStaticMappingDetailsReplyDump dumpNat44 = dumpReplyNat44NonEmpty();
+        final Nat64BibDetailsReplyDump dumpNat64 = dumpReplyNat64NonEmpty();
+        when(nat44DumpExecutor.executeDump(mappingEntryWildcarded, null))
+                .thenReturn(dumpNat44);
+        when(nat64DumpExecutor.executeDump(mappingEntryWildcarded, null)).thenReturn(dumpNat64);
+        when(mappingContext.getStoredOrArtificialIndex(NatInstanceCustomizer.DEFAULT_VRF_ID.getId(),
+                dumpNat44.snatStaticMappingDetails.get(0), ctx.getMappingContext())).thenReturn(0L);
+        when(mappingContext.getStoredOrArtificialIndex(NatInstanceCustomizer.DEFAULT_VRF_ID.getId(),
+                dumpNat44.snatStaticMappingDetails.get(1), ctx.getMappingContext())).thenReturn(1L);
+        when(mappingContext.getStoredOrArtificialIndex(NatInstanceCustomizer.DEFAULT_VRF_ID.getId(),
+                dumpNat44.snatStaticMappingDetails.get(2), ctx.getMappingContext())).thenReturn(2L);
+        when(mappingContext.getStoredOrArtificialIndex(NatInstanceCustomizer.DEFAULT_VRF_ID.getId(),
+                dumpNat64.nat64BibDetails.get(0), ctx.getMappingContext())).thenReturn(3L);
+        when(mappingContext.getStoredOrArtificialIndex(NatInstanceCustomizer.DEFAULT_VRF_ID.getId(),
+                dumpNat64.nat64BibDetails.get(1), ctx.getMappingContext())).thenReturn(4L);
+        when(mappingContext.getStoredOrArtificialIndex(NatInstanceCustomizer.DEFAULT_VRF_ID.getId(),
+                dumpNat64.nat64BibDetails.get(2), ctx.getMappingContext())).thenReturn(5L);
+
+        final List<MappingEntryKey> allIds = getCustomizer().getAllIds(mappingEntryWildcarded, ctx);
+        assertThat(allIds, hasItems(new MappingEntryKey(0L), new MappingEntryKey(2L), new MappingEntryKey(3L),
+                new MappingEntryKey(5L)));
+    }
+
     @Override
     protected ReaderCustomizer<MappingEntry, MappingEntryBuilder> initCustomizer() {
-        return new MappingEntryCustomizer(dumpCacheManager, mappingContext);
+        return new MappingEntryCustomizer(nat44DumpManager, nat64DumpManager, mappingContext);
     }
 
-    private static SnatStaticMappingDetailsReplyDump dumpNonEmptyDefaultInstance() {
+    private static SnatStaticMappingDetailsReplyDump dumpReplyNat44NonEmpty() {
         SnatStaticMappingDetailsReplyDump replyDump = new SnatStaticMappingDetailsReplyDump();
 
         SnatStaticMappingDetails detailsOne = new SnatStaticMappingDetails();
         detailsOne.isIp4 = 1;
         detailsOne.addrOnly = 1;
-        detailsOne.localIpAddress = new byte[] {-64, -88, 2, 1};
+        detailsOne.localIpAddress = new byte[]{-64, -88, 2, 1};
         detailsOne.localPort = 1234;
-        detailsOne.externalIpAddress = new byte[] {-64, -88, 2, 8};
+        detailsOne.externalIpAddress = new byte[]{-64, -88, 2, 8};
         detailsOne.externalPort = 5874;
         detailsOne.vrfId = NatInstanceCustomizer.DEFAULT_VRF_ID.getId().byteValue();
 
         SnatStaticMappingDetails detailsTwo = new SnatStaticMappingDetails();
         detailsTwo.isIp4 = 1;
         detailsTwo.addrOnly = 1;
-        detailsTwo.localIpAddress = new byte[] {-64, -88, 2, 3};
+        detailsTwo.localIpAddress = new byte[]{-64, -88, 2, 3};
         detailsTwo.localPort = 1235;
-        detailsTwo.externalIpAddress = new byte[] {-64, -88, 2, 5};
+        detailsTwo.externalIpAddress = new byte[]{-64, -88, 2, 5};
         detailsTwo.externalPort = 5874;
         detailsTwo.vrfId = 2;
 
         SnatStaticMappingDetails detailsThree = new SnatStaticMappingDetails();
         detailsThree.isIp4 = 1;
         detailsThree.addrOnly = 0;
-        detailsThree.localIpAddress = new byte[] {-64, -88, 2, 2};
+        detailsThree.localIpAddress = new byte[]{-64, -88, 2, 2};
         detailsThree.localPort = 1274;
-        detailsThree.externalIpAddress = new byte[] {-64, -88, 3, 8};
+        detailsThree.externalIpAddress = new byte[]{-64, -88, 3, 8};
         detailsThree.externalPort = 6874;
         detailsThree.vrfId = NatInstanceCustomizer.DEFAULT_VRF_ID.getId().byteValue();
 
         replyDump.snatStaticMappingDetails = Arrays.asList(detailsOne, detailsTwo, detailsThree);
         return replyDump;
     }
+
+    private static Nat64BibDetailsReplyDump dumpReplyNat64NonEmpty() {
+        Nat64BibDetailsReplyDump replyDump = new Nat64BibDetailsReplyDump();
+
+        Nat64BibDetails detailsOne = new Nat64BibDetails();
+        detailsOne.isStatic = 1;
+        detailsOne.iAddr =
+                new byte[]{0x20, 0x01, 0x0d, (byte) 0xb8, (byte) 0x85, (byte) 0xa3, 0, 0, 0, 0, (byte) 0x8a, 0x2e, 0x03,
+                        0x70, 0x73, 0x01};
+        detailsOne.iPort = 1234;
+        detailsOne.oAddr = new byte[]{-64, -88, 64, 1};
+        detailsOne.oPort = 5874;
+        detailsOne.vrfId = NatInstanceCustomizer.DEFAULT_VRF_ID.getId().byteValue();
+
+        Nat64BibDetails detailsTwo = new Nat64BibDetails();
+        detailsTwo.isStatic = 0;
+        detailsTwo.iAddr =
+                new byte[]{0x20, 0x01, 0x0d, (byte) 0xb8, (byte) 0x85, (byte) 0xa3, 0, 0, 0, 0, (byte) 0x8a, 0x2e, 0x03,
+                        0x70, 0x73, 0x02};
+        detailsTwo.iPort = 1235;
+        detailsTwo.oAddr = new byte[]{-64, -88, 64, 2};
+        detailsTwo.oPort = 5874;
+        detailsTwo.vrfId = 2;
+
+        Nat64BibDetails detailsThree = new Nat64BibDetails();
+        detailsThree.isStatic = 1;
+        detailsThree.iAddr =
+                new byte[]{0x20, 0x01, 0x0d, (byte) 0xb8, (byte) 0x85, (byte) 0xa3, 0, 0, 0, 0, (byte) 0x8a, 0x2e, 0x03,
+                        0x70, 0x73, 0x03};
+        detailsThree.iPort = 1274;
+        detailsThree.oAddr = new byte[]{-64, -88, 64, 3};
+        detailsThree.oPort = 6874;
+        detailsThree.vrfId = NatInstanceCustomizer.DEFAULT_VRF_ID.getId().byteValue();
+
+        replyDump.nat64BibDetails = Arrays.asList(detailsOne, detailsTwo, detailsThree);
+        return replyDump;
+    }
 }
\ No newline at end of file
index 821a592..0fad2ab 100644 (file)
@@ -17,6 +17,7 @@
 package io.fd.hc2vpp.nat.read;
 
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.hasSize;
 import static org.hamcrest.core.IsCollectionContaining.hasItems;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
@@ -26,6 +27,8 @@ import io.fd.hc2vpp.common.test.read.InitializingListReaderCustomizerTest;
 import io.fd.honeycomb.translate.read.ReadFailedException;
 import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager;
 import io.fd.honeycomb.translate.util.read.cache.EntityDumpExecutor;
+import io.fd.vpp.jvpp.snat.dto.Nat64BibDetails;
+import io.fd.vpp.jvpp.snat.dto.Nat64BibDetailsReplyDump;
 import io.fd.vpp.jvpp.snat.dto.SnatStaticMappingDetails;
 import io.fd.vpp.jvpp.snat.dto.SnatStaticMappingDetailsReplyDump;
 import java.util.Arrays;
@@ -41,13 +44,16 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
 
 public class NatInstanceCustomizerTest
-    extends InitializingListReaderCustomizerTest<NatInstance, NatInstanceKey, NatInstanceBuilder> {
+        extends InitializingListReaderCustomizerTest<NatInstance, NatInstanceKey, NatInstanceBuilder> {
     @Mock
-    private EntityDumpExecutor<SnatStaticMappingDetailsReplyDump, Void> dumpExecutor;
+    private EntityDumpExecutor<SnatStaticMappingDetailsReplyDump, Void> nat44DumpExecutor;
+    @Mock
+    private EntityDumpExecutor<Nat64BibDetailsReplyDump, Void> nat64DumpExecutor;
 
     private KeyedInstanceIdentifier<NatInstance, NatInstanceKey> natInstanceId;
     private InstanceIdentifier<NatInstance> natInstanceWildcarded;
-    private DumpCacheManager<SnatStaticMappingDetailsReplyDump, Void> dumpCacheManager;
+    private DumpCacheManager<SnatStaticMappingDetailsReplyDump, Void> mapEntryNat44DumpMgr;
+    private DumpCacheManager<Nat64BibDetailsReplyDump, Void> mapEntryNat64DumpMgr;
 
     public NatInstanceCustomizerTest() {
         super(NatInstance.class, NatInstancesBuilder.class);
@@ -55,19 +61,23 @@ public class NatInstanceCustomizerTest
 
     @Override
     protected NatInstanceCustomizer initCustomizer() {
-        return new NatInstanceCustomizer(dumpCacheManager);
+        return new NatInstanceCustomizer(mapEntryNat44DumpMgr, mapEntryNat64DumpMgr);
     }
 
     @Override
     protected void setUp() throws Exception {
         natInstanceId = InstanceIdentifier.create(NatInstances.class)
-            .child(NatInstance.class, new NatInstanceKey(NatInstanceCustomizer.DEFAULT_VRF_ID));
+                .child(NatInstance.class, new NatInstanceKey(NatInstanceCustomizer.DEFAULT_VRF_ID));
         natInstanceWildcarded = InstanceIdentifier.create(NatInstances.class)
-            .child(NatInstance.class);
-        dumpCacheManager = new DumpCacheManager.DumpCacheManagerBuilder<SnatStaticMappingDetailsReplyDump, Void>()
-            .withExecutor(dumpExecutor)
-            .acceptOnly(SnatStaticMappingDetailsReplyDump.class)
-            .build();
+                .child(NatInstance.class);
+        mapEntryNat44DumpMgr = new DumpCacheManager.DumpCacheManagerBuilder<SnatStaticMappingDetailsReplyDump, Void>()
+                .withExecutor(nat44DumpExecutor)
+                .acceptOnly(SnatStaticMappingDetailsReplyDump.class)
+                .build();
+        mapEntryNat64DumpMgr = new DumpCacheManager.DumpCacheManagerBuilder<Nat64BibDetailsReplyDump, Void>()
+                .withExecutor(nat64DumpExecutor)
+                .acceptOnly(Nat64BibDetailsReplyDump.class)
+                .build();
     }
 
     @Test
@@ -79,14 +89,16 @@ public class NatInstanceCustomizerTest
 
     @Test
     public void testReadAll() throws ReadFailedException {
-        final SnatStaticMappingDetailsReplyDump dump = dumpNonEmptyDefaultInstance();
-        when(dumpExecutor.executeDump(natInstanceWildcarded, null)).thenReturn(dump);
+        when(nat44DumpExecutor.executeDump(natInstanceWildcarded, null)).thenReturn(nat44NonEmptyDump());
+        when(nat64DumpExecutor.executeDump(natInstanceWildcarded, null)).thenReturn(nat64NonEmptyDump());
         final List<NatInstanceKey> allIds = getCustomizer().getAllIds(natInstanceWildcarded, ctx);
+        assertThat(allIds, hasSize(6));
         assertThat(allIds, hasItems(
-            new NatInstanceKey(0L), new NatInstanceKey(1L), new NatInstanceKey(2L), new NatInstanceKey(3L)));
+                new NatInstanceKey(0L), new NatInstanceKey(1L), new NatInstanceKey(2L), new NatInstanceKey(3L),
+                new NatInstanceKey(5L), new NatInstanceKey(6L)));
     }
 
-    private static SnatStaticMappingDetailsReplyDump dumpNonEmptyDefaultInstance() {
+    private static SnatStaticMappingDetailsReplyDump nat44NonEmptyDump() {
         SnatStaticMappingDetailsReplyDump replyDump = new SnatStaticMappingDetailsReplyDump();
         SnatStaticMappingDetails detailsOne = new SnatStaticMappingDetails();
         detailsOne.vrfId = 1;
@@ -100,4 +112,19 @@ public class NatInstanceCustomizerTest
         replyDump.snatStaticMappingDetails = Arrays.asList(detailsOne, detailsTwo, detailsThree);
         return replyDump;
     }
+
+    private static Nat64BibDetailsReplyDump nat64NonEmptyDump() {
+        Nat64BibDetailsReplyDump replyDump = new Nat64BibDetailsReplyDump();
+        Nat64BibDetails detailsOne = new Nat64BibDetails();
+        detailsOne.vrfId = 2;
+
+        Nat64BibDetails detailsTwo = new Nat64BibDetails();
+        detailsTwo.vrfId = 5;
+
+        Nat64BibDetails detailsThree = new Nat64BibDetails();
+        detailsThree.vrfId = 6;
+
+        replyDump.nat64BibDetails = Arrays.asList(detailsOne, detailsTwo, detailsThree);
+        return replyDump;
+    }
 }
\ No newline at end of file
index 4d8f807..a664360 100644 (file)
@@ -107,7 +107,7 @@ public class MappingEntryContextTest implements Ipv4Translator {
                                 MappingEntryContext.toCtxMapEntry(entry2, 1)))
                         .build()));
 
-        assertSame(details, ctx.findDetails(someDetails, natId, 0, mappingCtx));
+        assertSame(details, ctx.findDetailsNat44(someDetails, natId, 0, mappingCtx).get());
     }
 
     @Test(expected = IllegalStateException.class)
@@ -118,7 +118,7 @@ public class MappingEntryContextTest implements Ipv4Translator {
         final List<SnatStaticMappingDetails> someDetails = Lists.newArrayList(details);
         when(mappingCtx.read(MappingEntryContext.getTableId(natId))).thenReturn(Optional.absent());
 
-        ctx.findDetails(someDetails, natId, entryId, mappingCtx);
+        ctx.findDetailsNat44(someDetails, natId, entryId, mappingCtx);
     }
 
     @Test(expected = IllegalStateException.class)
@@ -131,7 +131,7 @@ public class MappingEntryContextTest implements Ipv4Translator {
         when(mappingCtx.read(MappingEntryContext.getTableId(natId)))
                 .thenReturn(Optional.of(new MappingTableBuilder().setMappingEntry(Collections.emptyList()).build()));
 
-        ctx.findDetails(someDetails, natId, entryId, mappingCtx);
+        ctx.findDetailsNat44(someDetails, natId, entryId, mappingCtx);
     }
 
     @Test