HC2VPP-197: translation layert for post routing NAT 73/7873/3
authorMarek Gradzki <[email protected]>
Tue, 1 Aug 2017 11:43:14 +0000 (13:43 +0200)
committerJan Srnicek <[email protected]>
Wed, 2 Aug 2017 11:19:25 +0000 (11:19 +0000)
Change-Id: Icef6682fbc7a18a1e52953270ad26f6b3b7676eb
Signed-off-by: Marek Gradzki <[email protected]>
17 files changed:
nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/ifc/AbstractInterfaceNatCustomizer.java
nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/ifc/AbstractSubInterfaceNatCustomizer.java
nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/ifc/IfcNatReaderFactory.java
nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/ifc/InterfaceInboundNatCustomizer.java
nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/ifc/InterfaceOutboundNatCustomizer.java
nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/ifc/SubIfcNatReaderFactory.java
nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/ifc/SubInterfaceInboundNatCustomizer.java
nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/ifc/SubInterfaceOutboundNatCustomizer.java
nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/ifc/AbstractInterfaceNatCustomizer.java
nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/ifc/AbstractSubInterfaceNatCustomizer.java
nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/ifc/IfcNatWriterFactory.java
nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/ifc/SubIfcNatWriterFactory.java
nat/nat2vpp/src/test/java/io/fd/hc2vpp/nat/read/ifc/InterfaceInboundNatCustomizerTest.java
nat/nat2vpp/src/test/java/io/fd/hc2vpp/nat/read/ifc/InterfaceOutboundNatCustomizerTest.java
nat/nat2vpp/src/test/java/io/fd/hc2vpp/nat/write/ifc/AbstractNatCustomizerTest.java
nat/nat2vpp/src/test/java/io/fd/hc2vpp/nat/write/ifc/InterfaceInboundNatCustomizerTest.java
nat/nat2vpp/src/test/java/io/fd/hc2vpp/nat/write/ifc/InterfaceOutboundNatCustomizerTest.java

index 2d48bd5..c3c81ff 100644 (file)
 
 package io.fd.hc2vpp.nat.read.ifc;
 
+import static java.util.Objects.requireNonNull;
+
 import com.google.common.base.Optional;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
 import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.honeycomb.translate.read.ReadContext;
 import io.fd.honeycomb.translate.read.ReadFailedException;
 import io.fd.honeycomb.translate.spi.read.InitializingReaderCustomizer;
 import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager;
-import io.fd.vpp.jvpp.snat.dto.SnatInterfaceDetails;
 import io.fd.vpp.jvpp.snat.dto.SnatInterfaceDetailsReplyDump;
+import io.fd.vpp.jvpp.snat.dto.SnatInterfaceDump;
+import io.fd.vpp.jvpp.snat.dto.SnatInterfaceOutputFeatureDetailsReplyDump;
+import io.fd.vpp.jvpp.snat.dto.SnatInterfaceOutputFeatureDump;
+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.interfaces.rev140508.interfaces.state.Interface;
 import org.opendaylight.yangtools.concepts.Builder;
@@ -32,48 +38,81 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 
 abstract class AbstractInterfaceNatCustomizer<C extends DataObject, B extends Builder<C>>
-        implements InitializingReaderCustomizer<C, B> {
+        implements InitializingReaderCustomizer<C, B>, JvppReplyConsumer {
 
-    private final DumpCacheManager<SnatInterfaceDetailsReplyDump, Void> dumpMgr;
+    private final FutureJVppSnatFacade jvppSnat;
+    private final DumpCacheManager<SnatInterfaceDetailsReplyDump, Void> preRoutingDumpMgr;
+    private final DumpCacheManager<SnatInterfaceOutputFeatureDetailsReplyDump, Void> postRoutingDumpMgr;
     private final NamingContext ifcContext;
 
-    AbstractInterfaceNatCustomizer(@Nonnull final DumpCacheManager<SnatInterfaceDetailsReplyDump, Void> dumpMgr,
+    AbstractInterfaceNatCustomizer(@Nonnull final FutureJVppSnatFacade jvppSnat,
                                    @Nonnull final NamingContext ifcContext) {
-        this.dumpMgr = dumpMgr;
-        this.ifcContext = ifcContext;
+        this.jvppSnat = requireNonNull(jvppSnat, "jvppSnat should not be null");
+        this.ifcContext = requireNonNull(ifcContext, "ifcContext should not be null");
+        this.preRoutingDumpMgr = new DumpCacheManager.DumpCacheManagerBuilder<SnatInterfaceDetailsReplyDump, Void>()
+                .withExecutor((id, params) -> getReplyForRead(
+                        jvppSnat.snatInterfaceDump(new SnatInterfaceDump()).toCompletableFuture(), id))
+                .acceptOnly(SnatInterfaceDetailsReplyDump.class)
+                .build();
+        this.postRoutingDumpMgr =
+                new DumpCacheManager.DumpCacheManagerBuilder<SnatInterfaceOutputFeatureDetailsReplyDump, Void>()
+                        .withExecutor((id, params) -> getReplyForRead(
+                                jvppSnat.snatInterfaceOutputFeatureDump(new SnatInterfaceOutputFeatureDump())
+                                        .toCompletableFuture(), id))
+                        .acceptOnly(SnatInterfaceOutputFeatureDetailsReplyDump.class)
+                        .build();
     }
 
     @Override
     public void readCurrentAttributes(@Nonnull final InstanceIdentifier<C> id,
                                       @Nonnull final B builder,
                                       @Nonnull final ReadContext ctx) throws ReadFailedException {
-        // NOOP
+        final String ifcName = getName(id);
+        getLog().debug("Reading NAT features on interface: {}", ifcName);
+        final int index = ifcContext.getIndex(ifcName, ctx.getMappingContext());
+
+        // There are no additional attributes for pre routing NAT, so it is enough to read post routing ifc mapping:
+        final Optional<SnatInterfaceOutputFeatureDetailsReplyDump> postRoutingDump =
+                postRoutingDumpMgr.getDump(id, ctx.getModificationCache(), null);
+
+        postRoutingDump.or(new SnatInterfaceOutputFeatureDetailsReplyDump()).snatInterfaceOutputFeatureDetails.stream()
+                .filter(snatIfcDetail -> snatIfcDetail.swIfIndex == index)
+                .filter(snatIfcDetail -> isExpectedNatType(snatIfcDetail.isInside))
+                .findFirst()
+                .ifPresent(snatIfcDetail -> setPostRouting(builder));
     }
 
     @Override
-    public boolean isPresent(final InstanceIdentifier<C> id, final C built, final ReadContext ctx) throws ReadFailedException {
+    public boolean isPresent(final InstanceIdentifier<C> id, final C built, final ReadContext ctx)
+            throws ReadFailedException {
+        // In the post routing case, we can reuse default implementation:
+        if (InitializingReaderCustomizer.super.isPresent(id, built, ctx)) {
+            // post routing was set
+            return true;
+        }
+        // In the pre routing case, we need to inspect pre routing dump:
         final String ifcName = getName(id);
-        getLog().debug("Reading NAT features on interface: {}", ifcName);
+        getLog().debug("Checking NAT presence for interface: {}", ifcName);
         final int index = ifcContext.getIndex(ifcName, ctx.getMappingContext());
 
-        // Cache dump for each interface under the same key since this is all ifc dump
-        final Optional<SnatInterfaceDetailsReplyDump> dump =
-                dumpMgr.getDump(id, ctx.getModificationCache(), null);
+        // Cache dump for each interface under the same key since this is all ifc dump:
+        final Optional<SnatInterfaceDetailsReplyDump> preRoutingDump =
+                preRoutingDumpMgr.getDump(id, ctx.getModificationCache(), null);
 
-        // Find entries for current ifc and if is marked as inside set the builder to return presence container
-        return dump.or(new SnatInterfaceDetailsReplyDump()).snatInterfaceDetails.stream()
+        // Find entries for current ifc and if is marked as inside set the builder to return presence container:
+        return preRoutingDump.or(new SnatInterfaceDetailsReplyDump()).snatInterfaceDetails.stream()
                 .filter(snatIfcDetail -> snatIfcDetail.swIfIndex == index)
-                .filter(this::isExpectedNatType)
-                .findFirst()
-                .isPresent();
-        // Not setting data, just marking the builder to propagate empty container to indicate presence
+                .anyMatch(snatIfcDetail -> isExpectedNatType(snatIfcDetail.isInside));
+        // Not setting data, just marking the builder to propagate empty container to indicate presence.
     }
 
     protected String getName(final InstanceIdentifier<C> id) {
         return id.firstKeyOf(Interface.class).getName();
     }
 
-    protected abstract Logger getLog();
+    abstract Logger getLog();
+
+    abstract boolean isExpectedNatType(final int isInside);
 
-    abstract boolean isExpectedNatType(final SnatInterfaceDetails snatInterfaceDetails);
+    abstract void setPostRouting(final B builder);
 }
index 6ccadd1..f3872c4 100644 (file)
@@ -19,8 +19,7 @@ package io.fd.hc2vpp.nat.read.ifc;
 import static com.google.common.base.Preconditions.checkNotNull;
 
 import io.fd.hc2vpp.common.translate.util.NamingContext;
-import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager;
-import io.fd.vpp.jvpp.snat.dto.SnatInterfaceDetailsReplyDump;
+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.interfaces.rev140508.interfaces.state.Interface;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.interfaces.state._interface.sub.interfaces.SubInterface;
@@ -29,18 +28,17 @@ import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
 abstract class AbstractSubInterfaceNatCustomizer<C extends DataObject, B extends Builder<C>>
-    extends AbstractInterfaceNatCustomizer<C, B> {
-    AbstractSubInterfaceNatCustomizer(
-        @Nonnull final DumpCacheManager<SnatInterfaceDetailsReplyDump, Void> dumpMgr,
-        @Nonnull final NamingContext ifcContext) {
-        super(dumpMgr, ifcContext);
+        extends AbstractInterfaceNatCustomizer<C, B> {
+    AbstractSubInterfaceNatCustomizer(@Nonnull final FutureJVppSnatFacade jvppSnat,
+                                      @Nonnull final NamingContext ifcContext) {
+        super(jvppSnat, ifcContext);
     }
 
     @Override
     protected String getName(final InstanceIdentifier<C> id) {
         // TODO(HC2VPP-99): use SubInterfaceUtils after it is moved from v3po2vpp
         final String parentInterfaceName =
-            checkNotNull(id.firstKeyOf(Interface.class), "operational Interface identifier expected").getName();
+                checkNotNull(id.firstKeyOf(Interface.class), "operational Interface identifier expected").getName();
         final Long subIfId = id.firstKeyOf(SubInterface.class).getIdentifier();
         return String.format("%s.%d", parentInterfaceName, subIfId.intValue());
     }
index 3a9a39e..83c7278 100644 (file)
@@ -19,16 +19,10 @@ package io.fd.hc2vpp.nat.read.ifc;
 
 import com.google.inject.Inject;
 import com.google.inject.name.Named;
-import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
 import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.honeycomb.translate.impl.read.GenericInitReader;
-import io.fd.honeycomb.translate.read.ReadFailedException;
 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.honeycomb.translate.util.read.cache.EntityDumpExecutor;
-import io.fd.vpp.jvpp.snat.dto.SnatInterfaceDetailsReplyDump;
-import io.fd.vpp.jvpp.snat.dto.SnatInterfaceDump;
 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.interfaces.rev140508.InterfacesState;
@@ -51,17 +45,13 @@ public final class IfcNatReaderFactory implements ReaderFactory {
     private static final InstanceIdentifier<NatInterfaceStateAugmentation> NAT_AUG_ID =
             IFC_ID.augmentation(NatInterfaceStateAugmentation.class);
     private static final InstanceIdentifier<Nat> NAT_AUG_CONTAINER_ID = NAT_AUG_ID.child(Nat.class);
-
-    private final DumpCacheManager<SnatInterfaceDetailsReplyDump, Void> snatIfcDumpMgr;
     private final NamingContext ifcContext;
+    private final FutureJVppSnatFacade jvppSnat;
 
     @Inject
     public IfcNatReaderFactory(final FutureJVppSnatFacade jvppSnat,
                                @Named("interface-context") final NamingContext ifcContext) {
-        this.snatIfcDumpMgr = new DumpCacheManager.DumpCacheManagerBuilder<SnatInterfaceDetailsReplyDump, Void>()
-                .withExecutor(new SnatInterfaceExecutor(jvppSnat))
-                .acceptOnly(SnatInterfaceDetailsReplyDump.class)
-                .build();
+        this.jvppSnat = jvppSnat;
         this.ifcContext = ifcContext;
     }
 
@@ -71,27 +61,8 @@ public final class IfcNatReaderFactory implements ReaderFactory {
         registry.addStructuralReader(NAT_AUG_CONTAINER_ID, NatBuilder.class);
 
         registry.addAfter(new GenericInitReader<>(NAT_AUG_CONTAINER_ID.child(Inbound.class),
-                        new InterfaceInboundNatCustomizer(snatIfcDumpMgr, ifcContext)), IFC_ID);
+                new InterfaceInboundNatCustomizer(jvppSnat, ifcContext)), IFC_ID);
         registry.addAfter(new GenericInitReader<>(NAT_AUG_CONTAINER_ID.child(Outbound.class),
-                        new InterfaceOutboundNatCustomizer(snatIfcDumpMgr, ifcContext)), IFC_ID);
-    }
-
-    private static final class SnatInterfaceExecutor implements
-            EntityDumpExecutor<SnatInterfaceDetailsReplyDump, Void>,
-            JvppReplyConsumer {
-
-        private final FutureJVppSnatFacade jvppSnat;
-
-        SnatInterfaceExecutor(final FutureJVppSnatFacade jvppSnat) {
-            this.jvppSnat = jvppSnat;
-        }
-
-        @Nonnull
-        @Override
-        public SnatInterfaceDetailsReplyDump executeDump(final InstanceIdentifier<?> identifier, final Void params)
-                throws ReadFailedException {
-            return getReplyForRead(
-                    jvppSnat.snatInterfaceDump(new SnatInterfaceDump()).toCompletableFuture(), identifier);
-        }
+                new InterfaceOutboundNatCustomizer(jvppSnat, ifcContext)), IFC_ID);
     }
 }
index 9bd8000..a909969 100644 (file)
@@ -19,9 +19,7 @@ package io.fd.hc2vpp.nat.read.ifc;
 import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.honeycomb.translate.read.ReadContext;
 import io.fd.honeycomb.translate.spi.read.Initialized;
-import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager;
-import io.fd.vpp.jvpp.snat.dto.SnatInterfaceDetails;
-import io.fd.vpp.jvpp.snat.dto.SnatInterfaceDetailsReplyDump;
+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.interfaces.rev140508.Interfaces;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
@@ -41,10 +39,9 @@ final class InterfaceInboundNatCustomizer extends AbstractInterfaceNatCustomizer
 
     private static final Logger LOG = LoggerFactory.getLogger(InterfaceInboundNatCustomizer.class);
 
-    InterfaceInboundNatCustomizer(
-            @Nonnull final DumpCacheManager<SnatInterfaceDetailsReplyDump, Void> dumpMgr,
-            @Nonnull final NamingContext ifcContext) {
-        super(dumpMgr, ifcContext);
+    InterfaceInboundNatCustomizer(@Nonnull final FutureJVppSnatFacade jvppSnat,
+                                  @Nonnull final NamingContext ifcContext) {
+        super(jvppSnat, ifcContext);
     }
 
     @Override
@@ -53,8 +50,13 @@ final class InterfaceInboundNatCustomizer extends AbstractInterfaceNatCustomizer
     }
 
     @Override
-    boolean isExpectedNatType(final SnatInterfaceDetails snatInterfaceDetails) {
-        return snatInterfaceDetails.isInside == 1;
+    boolean isExpectedNatType(final int isInside) {
+        return isInside == 1;
+    }
+
+    @Override
+    void setPostRouting(final InboundBuilder builder) {
+        builder.setPostRouting(true);
     }
 
     @Nonnull
@@ -76,12 +78,13 @@ final class InterfaceInboundNatCustomizer extends AbstractInterfaceNatCustomizer
                                                   @Nonnull final ReadContext ctx) {
         final InstanceIdentifier<Inbound> cfgId =
                 InstanceIdentifier.create(Interfaces.class)
-                .child(Interface.class,
-                        new InterfaceKey(id.firstKeyOf(
-                        org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class).getName()))
-                .augmentation(NatInterfaceAugmentation.class)
-                .child(Nat.class)
-                .child(Inbound.class);
+                        .child(Interface.class,
+                                new InterfaceKey(id.firstKeyOf(
+                                        org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class)
+                                        .getName()))
+                        .augmentation(NatInterfaceAugmentation.class)
+                        .child(Nat.class)
+                        .child(Inbound.class);
         return Initialized.create(cfgId, readValue);
     }
 }
index 80d8d94..8ea9348 100644 (file)
 
 package io.fd.hc2vpp.nat.read.ifc;
 
+import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.honeycomb.translate.read.ReadContext;
 import io.fd.honeycomb.translate.spi.read.Initialized;
-import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager;
-import io.fd.hc2vpp.common.translate.util.NamingContext;
-import io.fd.vpp.jvpp.snat.dto.SnatInterfaceDetails;
-import io.fd.vpp.jvpp.snat.dto.SnatInterfaceDetailsReplyDump;
+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.interfaces.rev140508.Interfaces;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
@@ -41,10 +39,9 @@ final class InterfaceOutboundNatCustomizer extends AbstractInterfaceNatCustomize
 
     private static final Logger LOG = LoggerFactory.getLogger(InterfaceOutboundNatCustomizer.class);
 
-    InterfaceOutboundNatCustomizer(
-            @Nonnull final DumpCacheManager<SnatInterfaceDetailsReplyDump, Void> dumpMgr,
-            @Nonnull final NamingContext ifcContext) {
-        super(dumpMgr, ifcContext);
+    InterfaceOutboundNatCustomizer(@Nonnull final FutureJVppSnatFacade jvppSnat,
+                                   @Nonnull final NamingContext ifcContext) {
+        super(jvppSnat, ifcContext);
     }
 
     @Override
@@ -53,8 +50,13 @@ final class InterfaceOutboundNatCustomizer extends AbstractInterfaceNatCustomize
     }
 
     @Override
-    boolean isExpectedNatType(final SnatInterfaceDetails snatInterfaceDetails) {
-        return snatInterfaceDetails.isInside == 0;
+    boolean isExpectedNatType(final int isInside) {
+        return isInside == 0;
+    }
+
+    @Override
+    void setPostRouting(final OutboundBuilder builder) {
+        builder.setPostRouting(true);
     }
 
     @Nonnull
@@ -77,7 +79,8 @@ final class InterfaceOutboundNatCustomizer extends AbstractInterfaceNatCustomize
                 InstanceIdentifier.create(Interfaces.class)
                         .child(Interface.class,
                                 new InterfaceKey(id.firstKeyOf(
-                                org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class).getName()))
+                                        org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class)
+                                        .getName()))
                         .augmentation(NatInterfaceAugmentation.class)
                         .child(Nat.class)
                         .child(Outbound.class);
index f9fb1d4..851a3ef 100644 (file)
@@ -19,16 +19,10 @@ package io.fd.hc2vpp.nat.read.ifc;
 
 import com.google.inject.Inject;
 import com.google.inject.name.Named;
-import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
 import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.honeycomb.translate.impl.read.GenericInitReader;
-import io.fd.honeycomb.translate.read.ReadFailedException;
 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.honeycomb.translate.util.read.cache.EntityDumpExecutor;
-import io.fd.vpp.jvpp.snat.dto.SnatInterfaceDetailsReplyDump;
-import io.fd.vpp.jvpp.snat.dto.SnatInterfaceDump;
 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.interfaces.rev140508.InterfacesState;
@@ -51,21 +45,18 @@ public final class SubIfcNatReaderFactory implements ReaderFactory {
 
     private static final InstanceIdentifier<SubInterface>
             SUB_IFC_ID = InstanceIdentifier.create(InterfacesState.class).child(Interface.class).augmentation(
-        SubinterfaceStateAugmentation.class).child(SubInterfaces.class).child(SubInterface.class);
+            SubinterfaceStateAugmentation.class).child(SubInterfaces.class).child(SubInterface.class);
     private static final InstanceIdentifier<NatSubinterfaceStateAugmentation> NAT_SUB_AUG_ID =
-        SUB_IFC_ID.augmentation(NatSubinterfaceStateAugmentation.class);
+            SUB_IFC_ID.augmentation(NatSubinterfaceStateAugmentation.class);
     private static final InstanceIdentifier<Nat> NAT_AUG_CONTAINER_ID = NAT_SUB_AUG_ID.child(Nat.class);
 
-    private final DumpCacheManager<SnatInterfaceDetailsReplyDump, Void> snatIfcDumpMgr;
     private final NamingContext ifcContext;
+    private final FutureJVppSnatFacade jvppSnat;
 
     @Inject
     public SubIfcNatReaderFactory(final FutureJVppSnatFacade jvppSnat,
                                   @Named("interface-context") final NamingContext ifcContext) {
-        this.snatIfcDumpMgr = new DumpCacheManager.DumpCacheManagerBuilder<SnatInterfaceDetailsReplyDump, Void>()
-                .withExecutor(new SnatInterfaceExecutor(jvppSnat))
-                .acceptOnly(SnatInterfaceDetailsReplyDump.class)
-                .build();
+        this.jvppSnat = jvppSnat;
         this.ifcContext = ifcContext;
     }
 
@@ -75,27 +66,8 @@ public final class SubIfcNatReaderFactory implements ReaderFactory {
         registry.addStructuralReader(NAT_AUG_CONTAINER_ID, NatBuilder.class);
 
         registry.addAfter(new GenericInitReader<>(NAT_AUG_CONTAINER_ID.child(Inbound.class),
-                        new SubInterfaceInboundNatCustomizer(snatIfcDumpMgr, ifcContext)), SUB_IFC_ID);
+                new SubInterfaceInboundNatCustomizer(jvppSnat, ifcContext)), SUB_IFC_ID);
         registry.addAfter(new GenericInitReader<>(NAT_AUG_CONTAINER_ID.child(Outbound.class),
-                        new SubInterfaceOutboundNatCustomizer(snatIfcDumpMgr, ifcContext)), SUB_IFC_ID);
-    }
-
-    private static final class SnatInterfaceExecutor implements
-            EntityDumpExecutor<SnatInterfaceDetailsReplyDump, Void>,
-            JvppReplyConsumer {
-
-        private final FutureJVppSnatFacade jvppSnat;
-
-        SnatInterfaceExecutor(final FutureJVppSnatFacade jvppSnat) {
-            this.jvppSnat = jvppSnat;
-        }
-
-        @Nonnull
-        @Override
-        public SnatInterfaceDetailsReplyDump executeDump(final InstanceIdentifier<?> identifier, final Void params)
-                throws ReadFailedException {
-            return getReplyForRead(
-                    jvppSnat.snatInterfaceDump(new SnatInterfaceDump()).toCompletableFuture(), identifier);
-        }
+                new SubInterfaceOutboundNatCustomizer(jvppSnat, ifcContext)), SUB_IFC_ID);
     }
 }
index 1d6cff9..84e211f 100644 (file)
@@ -19,9 +19,7 @@ package io.fd.hc2vpp.nat.read.ifc;
 import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.honeycomb.translate.read.ReadContext;
 import io.fd.honeycomb.translate.spi.read.Initialized;
-import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager;
-import io.fd.vpp.jvpp.snat.dto.SnatInterfaceDetails;
-import io.fd.vpp.jvpp.snat.dto.SnatInterfaceDetailsReplyDump;
+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.interfaces.rev140508.Interfaces;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
@@ -45,10 +43,9 @@ final class SubInterfaceInboundNatCustomizer extends AbstractSubInterfaceNatCust
 
     private static final Logger LOG = LoggerFactory.getLogger(SubInterfaceInboundNatCustomizer.class);
 
-    SubInterfaceInboundNatCustomizer(
-        @Nonnull final DumpCacheManager<SnatInterfaceDetailsReplyDump, Void> dumpMgr,
-        @Nonnull final NamingContext ifcContext) {
-        super(dumpMgr, ifcContext);
+    SubInterfaceInboundNatCustomizer(@Nonnull final FutureJVppSnatFacade jvppSnat,
+                                     @Nonnull final NamingContext ifcContext) {
+        super(jvppSnat, ifcContext);
     }
 
     @Override
@@ -57,8 +54,13 @@ final class SubInterfaceInboundNatCustomizer extends AbstractSubInterfaceNatCust
     }
 
     @Override
-    boolean isExpectedNatType(final SnatInterfaceDetails snatInterfaceDetails) {
-        return snatInterfaceDetails.isInside == 1;
+    boolean isExpectedNatType(final int isInside) {
+        return isInside == 1;
+    }
+
+    @Override
+    void setPostRouting(final InboundBuilder builder) {
+        builder.setPostRouting(true);
     }
 
     @Nonnull
@@ -79,18 +81,20 @@ final class SubInterfaceInboundNatCustomizer extends AbstractSubInterfaceNatCust
                                                   @Nonnull final Inbound readValue,
                                                   @Nonnull final ReadContext ctx) {
         final InstanceIdentifier<Inbound> cfgId =
-            InstanceIdentifier.create(Interfaces.class)
-                .child(Interface.class,
-                    new InterfaceKey(id.firstKeyOf(
-                        org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class).getName()))
-                .augmentation(SubinterfaceAugmentation.class)
-                .child(SubInterfaces.class)
-                .child(SubInterface.class,
-                    new SubInterfaceKey(id.firstKeyOf(
-                        org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.interfaces.state._interface.sub.interfaces.SubInterface.class).getIdentifier()))
-                .augmentation(NatSubinterfaceAugmentation.class)
-                .child(Nat.class)
-                .child(Inbound.class);
+                InstanceIdentifier.create(Interfaces.class)
+                        .child(Interface.class,
+                                new InterfaceKey(id.firstKeyOf(
+                                        org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class)
+                                        .getName()))
+                        .augmentation(SubinterfaceAugmentation.class)
+                        .child(SubInterfaces.class)
+                        .child(SubInterface.class,
+                                new SubInterfaceKey(id.firstKeyOf(
+                                        org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.interfaces.state._interface.sub.interfaces.SubInterface.class)
+                                        .getIdentifier()))
+                        .augmentation(NatSubinterfaceAugmentation.class)
+                        .child(Nat.class)
+                        .child(Inbound.class);
         return Initialized.create(cfgId, readValue);
     }
 }
index 1179e9f..d450787 100644 (file)
@@ -19,9 +19,7 @@ package io.fd.hc2vpp.nat.read.ifc;
 import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.honeycomb.translate.read.ReadContext;
 import io.fd.honeycomb.translate.spi.read.Initialized;
-import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager;
-import io.fd.vpp.jvpp.snat.dto.SnatInterfaceDetails;
-import io.fd.vpp.jvpp.snat.dto.SnatInterfaceDetailsReplyDump;
+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.interfaces.rev140508.Interfaces;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
@@ -45,10 +43,9 @@ final class SubInterfaceOutboundNatCustomizer extends AbstractSubInterfaceNatCus
 
     private static final Logger LOG = LoggerFactory.getLogger(SubInterfaceOutboundNatCustomizer.class);
 
-    SubInterfaceOutboundNatCustomizer(
-        @Nonnull final DumpCacheManager<SnatInterfaceDetailsReplyDump, Void> dumpMgr,
-        @Nonnull final NamingContext ifcContext) {
-        super(dumpMgr, ifcContext);
+    SubInterfaceOutboundNatCustomizer(@Nonnull final FutureJVppSnatFacade jvppSnat,
+                                      @Nonnull final NamingContext ifcContext) {
+        super(jvppSnat, ifcContext);
     }
 
     @Override
@@ -57,8 +54,13 @@ final class SubInterfaceOutboundNatCustomizer extends AbstractSubInterfaceNatCus
     }
 
     @Override
-    boolean isExpectedNatType(final SnatInterfaceDetails snatInterfaceDetails) {
-        return snatInterfaceDetails.isInside == 0;
+    boolean isExpectedNatType(final int isInside) {
+        return isInside == 0;
+    }
+
+    @Override
+    void setPostRouting(final OutboundBuilder builder) {
+        builder.setPostRouting(true);
     }
 
     @Nonnull
@@ -78,18 +80,20 @@ final class SubInterfaceOutboundNatCustomizer extends AbstractSubInterfaceNatCus
                                                   @Nonnull final Outbound readValue,
                                                   @Nonnull final ReadContext ctx) {
         final InstanceIdentifier<Outbound> cfgId =
-            InstanceIdentifier.create(Interfaces.class)
-                .child(Interface.class,
-                    new InterfaceKey(id.firstKeyOf(
-                        org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class).getName()))
-                .augmentation(SubinterfaceAugmentation.class)
-                .child(SubInterfaces.class)
-                .child(SubInterface.class,
-                    new SubInterfaceKey(id.firstKeyOf(
-                        org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.interfaces.state._interface.sub.interfaces.SubInterface.class).getIdentifier()))
-                .augmentation(NatSubinterfaceAugmentation.class)
-                .child(Nat.class)
-                .child(Outbound.class);
+                InstanceIdentifier.create(Interfaces.class)
+                        .child(Interface.class,
+                                new InterfaceKey(id.firstKeyOf(
+                                        org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class)
+                                        .getName()))
+                        .augmentation(SubinterfaceAugmentation.class)
+                        .child(SubInterfaces.class)
+                        .child(SubInterface.class,
+                                new SubInterfaceKey(id.firstKeyOf(
+                                        org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.interfaces.state._interface.sub.interfaces.SubInterface.class)
+                                        .getIdentifier()))
+                        .augmentation(NatSubinterfaceAugmentation.class)
+                        .child(Nat.class)
+                        .child(Outbound.class);
         return Initialized.create(cfgId, readValue);
     }
 }
index 455b461..82af934 100644 (file)
 
 package io.fd.hc2vpp.nat.write.ifc;
 
-import io.fd.honeycomb.translate.spi.write.WriterCustomizer;
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
 import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
 import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.spi.write.WriterCustomizer;
 import io.fd.honeycomb.translate.write.WriteContext;
 import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.dto.JVppReply;
 import io.fd.vpp.jvpp.snat.dto.SnatInterfaceAddDelFeature;
 import io.fd.vpp.jvpp.snat.dto.SnatInterfaceAddDelFeatureReply;
+import io.fd.vpp.jvpp.snat.dto.SnatInterfaceAddDelOutputFeature;
+import io.fd.vpp.jvpp.snat.dto.SnatInterfaceAddDelOutputFeatureReply;
 import io.fd.vpp.jvpp.snat.future.FutureJVppSnatFacade;
 import java.util.concurrent.CompletionStage;
 import javax.annotation.Nonnull;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev170801.InterfaceNatVppFeatureAttributes;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 
-abstract class AbstractInterfaceNatCustomizer<D extends DataObject> implements JvppReplyConsumer, WriterCustomizer<D> {
+abstract class AbstractInterfaceNatCustomizer<D extends InterfaceNatVppFeatureAttributes & DataObject>
+        implements ByteDataTranslator, JvppReplyConsumer, WriterCustomizer<D> {
 
     private final FutureJVppSnatFacade jvppSnat;
     private final NamingContext ifcContext;
@@ -47,14 +53,16 @@ abstract class AbstractInterfaceNatCustomizer<D extends DataObject> implements J
                                        @Nonnull final WriteContext writeContext) throws WriteFailedException {
         final String ifcName = getName(id);
         getLog().debug("Enabling " + getType() + " NAT on interface: {}", ifcName);
-        getLog().debug("Enabling " + getType() + " NAT: {}", id);
+        getLog().debug("Enabling {} NAT: {}", dataAfter, id);
 
         final int ifcIndex = ifcContext.getIndex(ifcName, writeContext.getMappingContext());
-        final SnatInterfaceAddDelFeature request = getRequest(ifcIndex, (byte)1);
-        final CompletionStage<SnatInterfaceAddDelFeatureReply> future = jvppSnat.snatInterfaceAddDelFeature(request);
-
-        final SnatInterfaceAddDelFeatureReply reply = getReplyForWrite(future.toCompletableFuture(), id);
-        getLog().debug("NAT " + getType() + " enabled successfully on: {}, reply: {}", ifcName, reply);
+        final JVppReply reply;
+        if (dataAfter.isPostRouting()) {
+            reply = postRoutingNat(id, ifcIndex, true);
+        } else {
+            reply = preRoutingNat(id, ifcIndex, true);
+        }
+        getLog().debug("NAT {} enabled successfully on: {}, reply: {}", dataAfter, ifcName, reply);
     }
 
     @Override
@@ -71,22 +79,47 @@ abstract class AbstractInterfaceNatCustomizer<D extends DataObject> implements J
             throws WriteFailedException {
         final String ifcName = getName(id);
         getLog().debug("Disabling " + getType() + " NAT on interface: {}", ifcName);
-        getLog().debug("Disabling " + getType() + " NAT: {}", id);
+        getLog().debug("Disabling {} NAT: {}", dataBefore, id);
 
         final int ifcIndex = ifcContext.getIndex(ifcName, writeContext.getMappingContext());
-        final SnatInterfaceAddDelFeature request = getRequest(ifcIndex, (byte)0);
-        final CompletionStage<SnatInterfaceAddDelFeatureReply> future = jvppSnat.snatInterfaceAddDelFeature(request);
-
-        final SnatInterfaceAddDelFeatureReply reply = getReplyForWrite(future.toCompletableFuture(), id);
-        getLog().debug("NAT " + getType() + " disabled successfully on: {}, reply: {}", ifcName, reply);
+        final JVppReply reply;
+        if (dataBefore.isPostRouting()) {
+            reply = postRoutingNat(id, ifcIndex, false);
+        } else {
+            reply = preRoutingNat(id, ifcIndex, false);
+        }
+        getLog().debug("NAT {} disabled successfully on: {}, reply: {}", dataBefore, ifcName, reply);
     }
 
     protected String getName(final InstanceIdentifier<D> id) {
         return id.firstKeyOf(Interface.class).getName();
     }
 
+    private JVppReply postRoutingNat(@Nonnull final InstanceIdentifier<D> id, final int ifcIndex, final boolean enable)
+            throws WriteFailedException {
+        final SnatInterfaceAddDelOutputFeature request = new SnatInterfaceAddDelOutputFeature();
+        request.isAdd = booleanToByte(enable);
+        request.isInside = getType().isInside;
+        request.swIfIndex = ifcIndex;
+
+        final CompletionStage<SnatInterfaceAddDelOutputFeatureReply> future =
+                jvppSnat.snatInterfaceAddDelOutputFeature(request);
+        return getReplyForWrite(future.toCompletableFuture(), id);
+    }
+
+    private JVppReply preRoutingNat(@Nonnull final InstanceIdentifier<D> id, final int ifcIndex, final boolean enable)
+            throws WriteFailedException {
+        final SnatInterfaceAddDelFeature request = new SnatInterfaceAddDelFeature();
+        request.isAdd = booleanToByte(enable);
+        request.isInside = getType().isInside;
+        request.swIfIndex = ifcIndex;
+
+        final CompletionStage<SnatInterfaceAddDelFeatureReply> future = jvppSnat.snatInterfaceAddDelFeature(request);
+        return getReplyForWrite(future.toCompletableFuture(), id);
+    }
+
     enum NatType {
-        INBOUND((byte)1), OUTBOUND((byte)0);
+        INBOUND((byte) 1), OUTBOUND((byte) 0);
 
         private final byte isInside;
 
@@ -96,14 +129,6 @@ abstract class AbstractInterfaceNatCustomizer<D extends DataObject> implements J
     }
 
     abstract NatType getType();
-    abstract Logger getLog();
-
-    private SnatInterfaceAddDelFeature getRequest(final int ifcIdx, final byte isAdd) {
-        final SnatInterfaceAddDelFeature request = new SnatInterfaceAddDelFeature();
-        request.isAdd = isAdd;
-        request.isInside = getType().isInside;
-        request.swIfIndex = ifcIdx;
-        return request;
-    }
 
+    abstract Logger getLog();
 }
index 4e693ec..ca40f8a 100644 (file)
@@ -37,13 +37,15 @@ import io.fd.hc2vpp.common.translate.util.NamingContext;
 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.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev170801.InterfaceNatVppFeatureAttributes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.interfaces._interface.sub.interfaces.SubInterface;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
-abstract class AbstractSubInterfaceNatCustomizer<D extends DataObject> extends AbstractInterfaceNatCustomizer<D> {
+abstract class AbstractSubInterfaceNatCustomizer<D extends InterfaceNatVppFeatureAttributes & DataObject>
+        extends AbstractInterfaceNatCustomizer<D> {
     AbstractSubInterfaceNatCustomizer(@Nonnull final FutureJVppSnatFacade jvppSnat,
-                                          @Nonnull final NamingContext ifcContext) {
+                                      @Nonnull final NamingContext ifcContext) {
         super(jvppSnat, ifcContext);
     }
 
@@ -51,7 +53,7 @@ abstract class AbstractSubInterfaceNatCustomizer<D extends DataObject> extends A
     protected String getName(final InstanceIdentifier<D> id) {
         // TODO(HC2VPP-99): use SubInterfaceUtils after it is moved from v3po2vpp
         final String parentInterfaceName =
-            checkNotNull(id.firstKeyOf(Interface.class), "Interface configuration identifier expected").getName();
+                checkNotNull(id.firstKeyOf(Interface.class), "Interface configuration identifier expected").getName();
         final Long subIfId = id.firstKeyOf(SubInterface.class).getIdentifier();
         return String.format("%s.%d", parentInterfaceName, subIfId.intValue());
     }
index 12a12b3..499c9a9 100644 (file)
@@ -18,8 +18,8 @@ package io.fd.hc2vpp.nat.write.ifc;
 
 import com.google.inject.Inject;
 import com.google.inject.name.Named;
-import io.fd.honeycomb.translate.impl.write.GenericWriter;
 import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.impl.write.GenericWriter;
 import io.fd.honeycomb.translate.write.WriterFactory;
 import io.fd.honeycomb.translate.write.registry.ModifiableWriterRegistryBuilder;
 import io.fd.vpp.jvpp.snat.future.FutureJVppSnatFacade;
@@ -40,7 +40,7 @@ public final class IfcNatWriterFactory implements WriterFactory {
     private static final InstanceIdentifier<Interface>
             IFC_ID = InstanceIdentifier.create(Interfaces.class).child(Interface.class);
     private static final InstanceIdentifier<Nat> NAT_AUG_ID =
-            IFC_ID .augmentation(NatInterfaceAugmentation.class).child(Nat.class);
+            IFC_ID.augmentation(NatInterfaceAugmentation.class).child(Nat.class);
 
     private final FutureJVppSnatFacade jvppSnat;
     private final NamingContext ifcContext;
index 86209f6..231d73f 100644 (file)
@@ -41,10 +41,10 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 public final class SubIfcNatWriterFactory implements WriterFactory {
 
     private static final InstanceIdentifier<SubInterface>
-        SUB_IFC_ID = InstanceIdentifier.create(Interfaces.class).child(Interface.class).augmentation(
-        SubinterfaceAugmentation.class).child(SubInterfaces.class).child(SubInterface.class);
+            SUB_IFC_ID = InstanceIdentifier.create(Interfaces.class).child(Interface.class).augmentation(
+            SubinterfaceAugmentation.class).child(SubInterfaces.class).child(SubInterface.class);
     private static final InstanceIdentifier<Nat> NAT_AUG_ID =
-        SUB_IFC_ID.augmentation(NatSubinterfaceAugmentation.class).child(Nat.class);
+            SUB_IFC_ID.augmentation(NatSubinterfaceAugmentation.class).child(Nat.class);
 
     private final FutureJVppSnatFacade jvppSnat;
     private final NamingContext ifcContext;
@@ -59,8 +59,8 @@ public final class SubIfcNatWriterFactory implements WriterFactory {
     @Override
     public void init(@Nonnull final ModifiableWriterRegistryBuilder registry) {
         registry.addAfter(new GenericWriter<>(NAT_AUG_ID.child(Inbound.class),
-            new SubInterfaceInboundNatCustomizer(jvppSnat, ifcContext)), SUB_IFC_ID);
+                new SubInterfaceInboundNatCustomizer(jvppSnat, ifcContext)), SUB_IFC_ID);
         registry.addAfter(new GenericWriter<>(NAT_AUG_ID.child(Outbound.class),
-            new SubInterfaceOutboundNatCustomizer(jvppSnat, ifcContext)), SUB_IFC_ID);
+                new SubInterfaceOutboundNatCustomizer(jvppSnat, ifcContext)), SUB_IFC_ID);
     }
 }
index 859d78f..a71461f 100644 (file)
@@ -18,6 +18,10 @@ package io.fd.hc2vpp.nat.read.ifc;
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import com.google.common.collect.Lists;
 import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest;
@@ -25,13 +29,13 @@ import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.honeycomb.translate.impl.read.GenericReader;
 import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
 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.SnatInterfaceDetails;
 import io.fd.vpp.jvpp.snat.dto.SnatInterfaceDetailsReplyDump;
+import io.fd.vpp.jvpp.snat.dto.SnatInterfaceOutputFeatureDetails;
+import io.fd.vpp.jvpp.snat.dto.SnatInterfaceOutputFeatureDetailsReplyDump;
+import io.fd.vpp.jvpp.snat.future.FutureJVppSnatFacade;
 import org.junit.Test;
 import org.mockito.Mock;
-import org.mockito.Mockito;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
@@ -51,8 +55,8 @@ public class InterfaceInboundNatCustomizerTest
     private static final String CTX_NAME = "ifc";
 
     @Mock
-    private EntityDumpExecutor<SnatInterfaceDetailsReplyDump, Void> natExecutor;
-    private DumpCacheManager<SnatInterfaceDetailsReplyDump, Void> dumpMgr;
+    private FutureJVppSnatFacade jvppSnat;
+
     private NamingContext ifcContext = new NamingContext(CTX_NAME, CTX_NAME);
     private InstanceIdentifier<Inbound> id;
 
@@ -72,12 +76,13 @@ public class InterfaceInboundNatCustomizerTest
     protected void setUp() throws Exception {
         id = getId(Inbound.class);
         defineMapping(mappingContext, IFC_NAME, IFC_IDX, CTX_NAME);
-        // empty dump
-        Mockito.doReturn(new SnatInterfaceDetailsReplyDump()).when(natExecutor).executeDump(id, null);
-        dumpMgr = new DumpCacheManager.DumpCacheManagerBuilder<SnatInterfaceDetailsReplyDump, Void>()
-                .withExecutor(natExecutor)
-                .acceptOnly(SnatInterfaceDetailsReplyDump.class)
-                .build();
+        when(jvppSnat.snatInterfaceDump(any())).thenReturn(future(new SnatInterfaceDetailsReplyDump()));
+        when(jvppSnat.snatInterfaceOutputFeatureDump(any()))
+                .thenReturn(future(new SnatInterfaceOutputFeatureDetailsReplyDump()));
+    }
+
+    private GenericReader<Inbound, InboundBuilder> getReader() {
+        return new GenericReader<>(RWUtils.makeIidWildcarded(id), customizer);
     }
 
     @Test
@@ -85,24 +90,43 @@ public class InterfaceInboundNatCustomizerTest
         assertFalse(getReader().read(id, ctx).isPresent());
     }
 
-    private GenericReader<Inbound, InboundBuilder> getReader() {
-        return new GenericReader<>(RWUtils.makeIidWildcarded(id), customizer);
+    private void mockPostRoutingDump() {
+        final SnatInterfaceOutputFeatureDetailsReplyDump details = new SnatInterfaceOutputFeatureDetailsReplyDump();
+        final SnatInterfaceOutputFeatureDetails detail = new SnatInterfaceOutputFeatureDetails();
+        detail.isInside = 1;
+        detail.swIfIndex = IFC_IDX;
+        details.snatInterfaceOutputFeatureDetails = Lists.newArrayList(detail);
+        when(jvppSnat.snatInterfaceOutputFeatureDump(any())).thenReturn(future(details));
     }
 
     @Test
-    public void testPresence() throws Exception {
+    public void testPresencePreRouting() throws Exception {
         final SnatInterfaceDetailsReplyDump details = new SnatInterfaceDetailsReplyDump();
         final SnatInterfaceDetails detail = new SnatInterfaceDetails();
         detail.isInside = 1;
         detail.swIfIndex = IFC_IDX;
         details.snatInterfaceDetails = Lists.newArrayList(detail);
-        Mockito.doReturn(details).when(natExecutor).executeDump(id, null);
+        when(jvppSnat.snatInterfaceDump(any())).thenReturn(future(details));
+
+        assertTrue(getReader().read(id, ctx).isPresent());
+    }
 
+    @Test
+    public void testPresencePostRouting() throws Exception {
+        mockPostRoutingDump();
         assertTrue(getReader().read(id, ctx).isPresent());
     }
 
+    @Test
+    public void testReadPostRouting() throws Exception {
+        mockPostRoutingDump();
+        final InboundBuilder builder = mock(InboundBuilder.class);
+        customizer.readCurrentAttributes(id, builder, ctx);
+        verify(builder).setPostRouting(true);
+    }
+
     @Override
     protected ReaderCustomizer<Inbound, InboundBuilder> initCustomizer() {
-        return new InterfaceInboundNatCustomizer(dumpMgr, ifcContext);
+        return new InterfaceInboundNatCustomizer(jvppSnat, ifcContext);
     }
 }
\ No newline at end of file
index b19878b..833a4fa 100644 (file)
@@ -19,6 +19,10 @@ package io.fd.hc2vpp.nat.read.ifc;
 import static io.fd.hc2vpp.nat.read.ifc.InterfaceInboundNatCustomizerTest.getId;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import com.google.common.collect.Lists;
 import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest;
@@ -26,13 +30,13 @@ import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.honeycomb.translate.impl.read.GenericReader;
 import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
 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.SnatInterfaceDetails;
 import io.fd.vpp.jvpp.snat.dto.SnatInterfaceDetailsReplyDump;
+import io.fd.vpp.jvpp.snat.dto.SnatInterfaceOutputFeatureDetails;
+import io.fd.vpp.jvpp.snat.dto.SnatInterfaceOutputFeatureDetailsReplyDump;
+import io.fd.vpp.jvpp.snat.future.FutureJVppSnatFacade;
 import org.junit.Test;
 import org.mockito.Mock;
-import org.mockito.Mockito;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev170801._interface.nat.attributes.NatBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev170801._interface.nat.attributes.nat.Outbound;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev170801._interface.nat.attributes.nat.OutboundBuilder;
@@ -46,8 +50,7 @@ public class InterfaceOutboundNatCustomizerTest
     private static final String CTX_NAME = "ifc";
 
     @Mock
-    private EntityDumpExecutor<SnatInterfaceDetailsReplyDump, Void> abc;
-    private DumpCacheManager<SnatInterfaceDetailsReplyDump, Void> dumpMgr;
+    private FutureJVppSnatFacade jvppSnat;
     private NamingContext ifcContext = new NamingContext(CTX_NAME, CTX_NAME);
     private InstanceIdentifier<Outbound> id;
 
@@ -59,12 +62,13 @@ public class InterfaceOutboundNatCustomizerTest
     protected void setUp() throws Exception {
         id = getId(Outbound.class);
         defineMapping(mappingContext, IFC_NAME, IFC_IDX, CTX_NAME);
-        // empty dump
-        Mockito.doReturn(new SnatInterfaceDetailsReplyDump()).when(abc).executeDump(id, null);
-        dumpMgr = new DumpCacheManager.DumpCacheManagerBuilder<SnatInterfaceDetailsReplyDump, Void>()
-                .withExecutor(abc)
-                .acceptOnly(SnatInterfaceDetailsReplyDump.class)
-                .build();
+        when(jvppSnat.snatInterfaceDump(any())).thenReturn(future(new SnatInterfaceDetailsReplyDump()));
+        when(jvppSnat.snatInterfaceOutputFeatureDump(any()))
+                .thenReturn(future(new SnatInterfaceOutputFeatureDetailsReplyDump()));
+    }
+
+    private GenericReader<Outbound, OutboundBuilder> getReader() {
+        return new GenericReader<>(RWUtils.makeIidWildcarded(id), customizer);
     }
 
     @Test
@@ -72,24 +76,43 @@ public class InterfaceOutboundNatCustomizerTest
         assertFalse(getReader().read(id, ctx).isPresent());
     }
 
-    private GenericReader<Outbound, OutboundBuilder> getReader() {
-        return new GenericReader<>(RWUtils.makeIidWildcarded(id), customizer);
+    private void mockPostRoutingDump() {
+        final SnatInterfaceOutputFeatureDetailsReplyDump details = new SnatInterfaceOutputFeatureDetailsReplyDump();
+        final SnatInterfaceOutputFeatureDetails detail = new SnatInterfaceOutputFeatureDetails();
+        detail.isInside = 0;
+        detail.swIfIndex = IFC_IDX;
+        details.snatInterfaceOutputFeatureDetails = Lists.newArrayList(detail);
+        when(jvppSnat.snatInterfaceOutputFeatureDump(any())).thenReturn(future(details));
     }
 
     @Test
-    public void testPresence() throws Exception {
+    public void testPresencePreRouting() throws Exception {
         final SnatInterfaceDetailsReplyDump details = new SnatInterfaceDetailsReplyDump();
         final SnatInterfaceDetails detail = new SnatInterfaceDetails();
         detail.isInside = 0;
         detail.swIfIndex = IFC_IDX;
         details.snatInterfaceDetails = Lists.newArrayList(detail);
-        Mockito.doReturn(details).when(abc).executeDump(id, null);
+        when(jvppSnat.snatInterfaceDump(any())).thenReturn(future(details));
 
         assertTrue(getReader().read(id, ctx).isPresent());
     }
 
+    @Test
+    public void testPresencePostRouting() throws Exception {
+        mockPostRoutingDump();
+        assertTrue(getReader().read(id, ctx).isPresent());
+    }
+
+    @Test
+    public void testReadPostRouting() throws Exception {
+        mockPostRoutingDump();
+        final OutboundBuilder builder = mock(OutboundBuilder.class);
+        customizer.readCurrentAttributes(id, builder, ctx);
+        verify(builder).setPostRouting(true);
+    }
+
     @Override
     protected ReaderCustomizer<Outbound, OutboundBuilder> initCustomizer() {
-        return new InterfaceOutboundNatCustomizer(dumpMgr, ifcContext);
+        return new InterfaceOutboundNatCustomizer(jvppSnat, ifcContext);
     }
 }
\ No newline at end of file
index c4886a4..273d376 100644 (file)
@@ -26,15 +26,18 @@ import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.honeycomb.translate.write.WriteFailedException;
 import io.fd.vpp.jvpp.snat.dto.SnatInterfaceAddDelFeature;
 import io.fd.vpp.jvpp.snat.dto.SnatInterfaceAddDelFeatureReply;
+import io.fd.vpp.jvpp.snat.dto.SnatInterfaceAddDelOutputFeature;
+import io.fd.vpp.jvpp.snat.dto.SnatInterfaceAddDelOutputFeatureReply;
 import io.fd.vpp.jvpp.snat.future.FutureJVppSnatFacade;
 import org.junit.Test;
 import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev170801.InterfaceNatVppFeatureAttributes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev170801._interface.nat.attributes.nat.Inbound;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
-abstract class AbstractNatCustomizerTest<D extends DataObject, T extends AbstractInterfaceNatCustomizer<D>>
-    extends WriterCustomizerTest implements ByteDataTranslator {
+abstract class AbstractNatCustomizerTest<D extends InterfaceNatVppFeatureAttributes & DataObject, T extends AbstractInterfaceNatCustomizer<D>>
+        extends WriterCustomizerTest implements ByteDataTranslator {
 
     private static final String IFC_CTX_NAME = "ifc-test-instance";
     private static final String IFACE_NAME = "eth0";
@@ -48,40 +51,75 @@ abstract class AbstractNatCustomizerTest<D extends DataObject, T extends Abstrac
     @Override
     public void setUpTest() {
         customizer = getCustomizer(snatApi, ifcNamingCtx);
+        defineMapping(mappingContext, IFACE_NAME, IFACE_ID, IFC_CTX_NAME);
+        when(snatApi.snatInterfaceAddDelFeature(any())).thenReturn(future(new SnatInterfaceAddDelFeatureReply()));
+        when(snatApi.snatInterfaceAddDelOutputFeature(any()))
+                .thenReturn(future(new SnatInterfaceAddDelOutputFeatureReply()));
     }
 
     @Test
-    public void testWrite() throws Exception {
-        defineMapping(mappingContext, IFACE_NAME, IFACE_ID, IFC_CTX_NAME);
-        when(snatApi.snatInterfaceAddDelFeature(any())).thenReturn(future(new SnatInterfaceAddDelFeatureReply()));
-        final D data = getData();
+    public void testWritePreRouting() throws Exception {
+        final D data = getPreRoutingConfig();
+        customizer.writeCurrentAttributes(getIId(IFACE_NAME), data, writeContext);
+        verify(snatApi).snatInterfaceAddDelFeature(expectedPreRoutingRequest(data, true));
+    }
+
+    @Test
+    public void testWritePostRouting() throws Exception {
+        final D data = getPostRoutingConfig();
         customizer.writeCurrentAttributes(getIId(IFACE_NAME), data, writeContext);
-        verify(snatApi).snatInterfaceAddDelFeature(expectedRequest(data, true));
+        verify(snatApi).snatInterfaceAddDelOutputFeature(expectedPostRoutingRequest(data, true));
+    }
+
+    @Test(expected = WriteFailedException.UpdateFailedException.class)
+    public void testUpdatePreRouting() throws Exception {
+        customizer.updateCurrentAttributes(getIId(IFACE_NAME), getPreRoutingConfig(), getPreRoutingConfig(),
+                writeContext);
     }
 
     @Test(expected = WriteFailedException.UpdateFailedException.class)
-    public void testUpdate() throws Exception {
-        customizer.updateCurrentAttributes(getIId(IFACE_NAME), getData(), getData(), writeContext);
+    public void testUpdatePostRouting() throws Exception {
+        customizer.updateCurrentAttributes(getIId(IFACE_NAME), getPostRoutingConfig(), getPostRoutingConfig(),
+                writeContext);
     }
 
     @Test
-    public void testDelete() throws Exception {
-        defineMapping(mappingContext, IFACE_NAME, IFACE_ID, IFC_CTX_NAME);
-        when(snatApi.snatInterfaceAddDelFeature(any())).thenReturn(future(new SnatInterfaceAddDelFeatureReply()));
-        final D data = getData();
+    public void testDeletePreRouting() throws Exception {
+        final D data = getPreRoutingConfig();
+        customizer.deleteCurrentAttributes(getIId(IFACE_NAME), data, writeContext);
+        verify(snatApi).snatInterfaceAddDelFeature(expectedPreRoutingRequest(data, false));
+    }
+
+    @Test
+    public void testDeletePostRouting() throws Exception {
+        final D data = getPostRoutingConfig();
         customizer.deleteCurrentAttributes(getIId(IFACE_NAME), data, writeContext);
-        verify(snatApi).snatInterfaceAddDelFeature(expectedRequest(data, false));
+        verify(snatApi).snatInterfaceAddDelOutputFeature(expectedPostRoutingRequest(data, false));
     }
 
-    private SnatInterfaceAddDelFeature expectedRequest(final D data, boolean isAdd) {
+    private SnatInterfaceAddDelFeature expectedPreRoutingRequest(final D data, boolean isAdd) {
         SnatInterfaceAddDelFeature request = new SnatInterfaceAddDelFeature();
-        request.isInside = (byte) ((data instanceof Inbound) ? 1 : 0);
+        request.isInside = (byte) ((data instanceof Inbound)
+                ? 1
+                : 0);
         request.swIfIndex = IFACE_ID;
         request.isAdd = booleanToByte(isAdd);
         return request;
     }
 
-    protected abstract D getData();
+    private SnatInterfaceAddDelOutputFeature expectedPostRoutingRequest(final D data, boolean isAdd) {
+        SnatInterfaceAddDelOutputFeature request = new SnatInterfaceAddDelOutputFeature();
+        request.isInside = (byte) ((data instanceof Inbound)
+                ? 1
+                : 0);
+        request.swIfIndex = IFACE_ID;
+        request.isAdd = booleanToByte(isAdd);
+        return request;
+    }
+
+    protected abstract D getPreRoutingConfig();
+
+    protected abstract D getPostRoutingConfig();
 
     protected abstract InstanceIdentifier<D> getIId(final String ifaceName);
 
index 8c16b1c..17efc40 100644 (file)
@@ -27,22 +27,29 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interfa
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev170801._interface.nat.attributes.nat.InboundBuilder;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
-public class InterfaceInboundNatCustomizerTest extends AbstractNatCustomizerTest<Inbound, InterfaceInboundNatCustomizer> {
+public class InterfaceInboundNatCustomizerTest
+        extends AbstractNatCustomizerTest<Inbound, InterfaceInboundNatCustomizer> {
 
     @Override
-    protected Inbound getData() {
-        return new InboundBuilder().build();
+    protected Inbound getPreRoutingConfig() {
+        return new InboundBuilder().setPostRouting(false).build();
+    }
+
+    @Override
+    protected Inbound getPostRoutingConfig() {
+        return new InboundBuilder().setPostRouting(true).build();
     }
 
     @Override
     protected InstanceIdentifier<Inbound> getIId(final String ifaceName) {
         return InstanceIdentifier.create(Interfaces.class)
-            .child(Interface.class, new InterfaceKey(ifaceName)).augmentation(NatInterfaceAugmentation.class)
-            .child(Nat.class).child(Inbound.class);
+                .child(Interface.class, new InterfaceKey(ifaceName)).augmentation(NatInterfaceAugmentation.class)
+                .child(Nat.class).child(Inbound.class);
     }
 
     @Override
-    protected InterfaceInboundNatCustomizer getCustomizer(final FutureJVppSnatFacade snatApi, final NamingContext ifcNamingCtx) {
+    protected InterfaceInboundNatCustomizer getCustomizer(final FutureJVppSnatFacade snatApi,
+                                                          final NamingContext ifcNamingCtx) {
         return new InterfaceInboundNatCustomizer(snatApi, ifcNamingCtx);
     }
 }
\ No newline at end of file
index 1daa053..fcc9d37 100644 (file)
@@ -27,22 +27,29 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interfa
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev170801._interface.nat.attributes.nat.OutboundBuilder;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
-public class InterfaceOutboundNatCustomizerTest extends AbstractNatCustomizerTest<Outbound, InterfaceOutboundNatCustomizer> {
+public class InterfaceOutboundNatCustomizerTest
+        extends AbstractNatCustomizerTest<Outbound, InterfaceOutboundNatCustomizer> {
 
     @Override
-    protected Outbound getData() {
-        return new OutboundBuilder().build();
+    protected Outbound getPreRoutingConfig() {
+        return new OutboundBuilder().setPostRouting(false).build();
+    }
+
+    @Override
+    protected Outbound getPostRoutingConfig() {
+        return new OutboundBuilder().setPostRouting(true).build();
     }
 
     @Override
     protected InstanceIdentifier<Outbound> getIId(final String ifaceName) {
         return InstanceIdentifier.create(Interfaces.class)
-            .child(Interface.class, new InterfaceKey(ifaceName)).augmentation(NatInterfaceAugmentation.class)
-            .child(Nat.class).child(Outbound.class);
+                .child(Interface.class, new InterfaceKey(ifaceName)).augmentation(NatInterfaceAugmentation.class)
+                .child(Nat.class).child(Outbound.class);
     }
 
     @Override
-    protected InterfaceOutboundNatCustomizer getCustomizer(final FutureJVppSnatFacade snatApi, final NamingContext ifcNamingCtx) {
+    protected InterfaceOutboundNatCustomizer getCustomizer(final FutureJVppSnatFacade snatApi,
+                                                           final NamingContext ifcNamingCtx) {
         return new InterfaceOutboundNatCustomizer(snatApi, ifcNamingCtx);
     }
 }
\ No newline at end of file