diff options
author | Maros Marsalek <mmarsale@cisco.com> | 2016-10-24 16:14:37 +0200 |
---|---|---|
committer | Maros Marsalek <mmarsale@cisco.com> | 2016-11-02 09:22:39 +0000 |
commit | 36d68584f46032b29eb7fc502a8c6fb11a7ee59b (patch) | |
tree | ead9f02fe240e63f90c89ecdec57854bcde682fa | |
parent | b8f86e7069a67031514c43caf8022e8553159fa7 (diff) |
HONEYCOMB-248 Enable in/out NAT feature read
Change-Id: I6fe57b955437d0b0024323bcbac268f0ed4799f6
Signed-off-by: Maros Marsalek <mmarsale@cisco.com>
7 files changed, 526 insertions, 28 deletions
diff --git a/nat/nat2vpp/pom.xml b/nat/nat2vpp/pom.xml index ba8204d6c..ad81e0662 100644 --- a/nat/nat2vpp/pom.xml +++ b/nat/nat2vpp/pom.xml @@ -30,6 +30,7 @@ <properties> <honeycomb.infra.version>1.16.12-SNAPSHOT</honeycomb.infra.version> + <honeycomb.vpp.common.version>1.16.12-SNAPSHOT</honeycomb.vpp.common.version> </properties> <dependencies> @@ -101,6 +102,12 @@ <scope>test</scope> </dependency> <dependency> + <groupId>io.fd.honeycomb.vpp</groupId> + <artifactId>vpp-translate-test</artifactId> + <version>${honeycomb.vpp.common.version}</version> + <scope>test</scope> + </dependency> + <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <scope>test</scope> diff --git a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/ifc/AbstractInterfaceNatCustomizer.java b/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/ifc/AbstractInterfaceNatCustomizer.java new file mode 100644 index 000000000..441218a3f --- /dev/null +++ b/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/ifc/AbstractInterfaceNatCustomizer.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.nat.read.ifc; + +import com.google.common.base.Optional; +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.honeycomb.translate.vpp.util.NamingContext; +import io.fd.vpp.jvpp.snat.dto.SnatInterfaceDetails; +import io.fd.vpp.jvpp.snat.dto.SnatInterfaceDetailsReplyDump; +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; +import org.opendaylight.yangtools.yang.binding.DataObject; +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> { + + private final DumpCacheManager<SnatInterfaceDetailsReplyDump, Void> dumpMgr; + private final NamingContext ifcContext; + + AbstractInterfaceNatCustomizer(@Nonnull final DumpCacheManager<SnatInterfaceDetailsReplyDump, Void> dumpMgr, + @Nonnull final NamingContext ifcContext) { + this.dumpMgr = dumpMgr; + this.ifcContext = ifcContext; + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier<C> id, + @Nonnull final B builder, + @Nonnull final ReadContext ctx) throws ReadFailedException { + final String ifcName = id.firstKeyOf(Interface.class).getName(); + getLog().debug("Reading NAT features on 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, getClass().getName(), ctx.getModificationCache(), null); + + // Find entries for current ifc and if is marked as inside set the builder to return presence container + dump.or(new SnatInterfaceDetailsReplyDump()).snatInterfaceDetails.stream() + .filter(snatIfcDetail -> snatIfcDetail.swIfIndex == index) + .filter(this::isExpectedNatType) + .findFirst() + .ifPresent(snatIfcDetail -> setBuilderPresence(builder)); + // Not setting data, just marking the builder to propagate empty container to indicate presence + } + + protected abstract Logger getLog(); + + abstract void setBuilderPresence(@Nonnull final B builder); + + abstract boolean isExpectedNatType(final SnatInterfaceDetails snatInterfaceDetails); +} diff --git a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/ifc/IfcNatReaderFactory.java b/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/ifc/IfcNatReaderFactory.java index 293a3dfd9..761986fc1 100644 --- a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/ifc/IfcNatReaderFactory.java +++ b/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/ifc/IfcNatReaderFactory.java @@ -17,9 +17,19 @@ package io.fd.honeycomb.nat.read.ifc; -import io.fd.honeycomb.translate.impl.read.GenericReader; +import com.google.inject.Inject; +import com.google.inject.name.Named; +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.honeycomb.translate.vpp.util.JvppReplyConsumer; +import io.fd.honeycomb.translate.vpp.util.NamingContext; +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; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface; @@ -42,14 +52,45 @@ public final class IfcNatReaderFactory implements ReaderFactory { 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; + + @Inject + public IfcNatReaderFactory(final FutureJVppSnatFacade jvppSnat, + @Named("interface-context") final NamingContext ifcContext) { + this.snatIfcDumpMgr = new DumpCacheManager.DumpCacheManagerBuilder<SnatInterfaceDetailsReplyDump, Void>() + .withExecutor(new SnatInterfaceExecutor(jvppSnat)) + .build(); + this.ifcContext = ifcContext; + } + @Override public void init(@Nonnull final ModifiableReaderRegistryBuilder registry) { registry.addStructuralReader(NAT_AUG_ID, NatInterfaceStateAugmentationBuilder.class); registry.addStructuralReader(NAT_AUG_CONTAINER_ID, NatBuilder.class); - registry.addAfter( - new GenericReader<>(NAT_AUG_CONTAINER_ID.child(Inbound.class), new InterfaceInboundNatCustomizer()), IFC_ID); - registry.addAfter( - new GenericReader<>(NAT_AUG_CONTAINER_ID.child(Outbound.class), new InterfaceOutboundNatCustomizer()), IFC_ID); + registry.addAfter(new GenericInitReader<>(NAT_AUG_CONTAINER_ID.child(Inbound.class), + new InterfaceInboundNatCustomizer(snatIfcDumpMgr, 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); + } } } diff --git a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/ifc/InterfaceInboundNatCustomizer.java b/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/ifc/InterfaceInboundNatCustomizer.java index 5be35ce16..52467a19a 100644 --- a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/ifc/InterfaceInboundNatCustomizer.java +++ b/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/ifc/InterfaceInboundNatCustomizer.java @@ -17,39 +17,127 @@ package io.fd.honeycomb.nat.read.ifc; import io.fd.honeycomb.translate.read.ReadContext; -import io.fd.honeycomb.translate.read.ReadFailedException; -import io.fd.honeycomb.translate.spi.read.ReaderCustomizer; +import io.fd.honeycomb.translate.spi.read.Initialized; +import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager; +import io.fd.honeycomb.translate.vpp.util.NamingContext; +import io.fd.vpp.jvpp.snat.dto.SnatInterfaceDetails; +import io.fd.vpp.jvpp.snat.dto.SnatInterfaceDetailsReplyDump; 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; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev161214.NatInterfaceAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev161214._interface.nat.attributes.Nat; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev161214._interface.nat.attributes.NatBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev161214._interface.nat.attributes.nat.Inbound; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev161214._interface.nat.attributes.nat.InboundBuilder; import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.Augmentation; +import org.opendaylight.yangtools.yang.binding.DataContainer; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -final class InterfaceInboundNatCustomizer implements ReaderCustomizer<Inbound, InboundBuilder> { +final class InterfaceInboundNatCustomizer extends AbstractInterfaceNatCustomizer<Inbound, InboundBuilder> { private static final Logger LOG = LoggerFactory.getLogger(InterfaceInboundNatCustomizer.class); - @Nonnull + InterfaceInboundNatCustomizer( + @Nonnull final DumpCacheManager<SnatInterfaceDetailsReplyDump, Void> dumpMgr, + @Nonnull final NamingContext ifcContext) { + super(dumpMgr, ifcContext); + } + @Override - public InboundBuilder getBuilder(@Nonnull final InstanceIdentifier<Inbound> id) { - return new InboundBuilder(); + protected Logger getLog() { + return LOG; } @Override - public void readCurrentAttributes(@Nonnull final InstanceIdentifier<Inbound> id, - @Nonnull final InboundBuilder builder, - @Nonnull final ReadContext ctx) - throws ReadFailedException { - // FIXME HONEYCOMB-248 VPP-459 Implement when read is available in VPP/Snat - LOG.debug("Unable to read Inbound NAT feature state for an interface"); + void setBuilderPresence(@Nonnull final InboundBuilder builder) { + ((PresenceInboundBuilder) builder).setPresent(true); + } + + @Override + boolean isExpectedNatType(final SnatInterfaceDetails snatInterfaceDetails) { + return snatInterfaceDetails.isInside == 1; + } + + @Nonnull + @Override + public InboundBuilder getBuilder(@Nonnull final InstanceIdentifier<Inbound> id) { + // Return not present value by default + return new PresenceInboundBuilder(false); } @Override public void merge(@Nonnull final Builder<? extends DataObject> parentBuilder, @Nonnull final Inbound readValue) { ((NatBuilder) parentBuilder).setInbound(readValue); } + + @Nonnull + @Override + public Initialized<? extends DataObject> init(@Nonnull final InstanceIdentifier<Inbound> id, + @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(NatInterfaceAugmentation.class) + .child(Nat.class) + .child(Inbound.class); + return Initialized.create(cfgId, readValue); + } + + // TODO HONEYCOMB-270, make this better, having to fake a builder + value is just exploitation. + + /** + * Special Builder to also propagate empty container into the resulting data. + */ + private static final class PresenceInboundBuilder extends InboundBuilder { + + private volatile boolean isPresent = false; + + PresenceInboundBuilder(final boolean isPresent) { + this.isPresent = isPresent; + } + + void setPresent(final boolean present) { + this.isPresent = present; + } + + @Override + public Inbound build() { + return isPresent + ? super.build() + : NotPresentInbound.NOT_PRESENT_INBOUND; + } + } + + /** + * Fake container that returns false on equals. + */ + private static final class NotPresentInbound implements Inbound { + + private static final NotPresentInbound NOT_PRESENT_INBOUND = new NotPresentInbound(); + + @Override + public <E extends Augmentation<Inbound>> E getAugmentation(final Class<E> augmentationType) { + throw new UnsupportedOperationException(); + } + + @Override + public Class<? extends DataContainer> getImplementedInterface() { + return Inbound.class; + } + + @Override + public boolean equals(final Object obj) { + // This is necessary to fake this.equals(something) + return obj == NOT_PRESENT_INBOUND; + } + } } diff --git a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/ifc/InterfaceOutboundNatCustomizer.java b/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/ifc/InterfaceOutboundNatCustomizer.java index cb0103111..b08a636ca 100644 --- a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/ifc/InterfaceOutboundNatCustomizer.java +++ b/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/ifc/InterfaceOutboundNatCustomizer.java @@ -17,38 +17,127 @@ package io.fd.honeycomb.nat.read.ifc; import io.fd.honeycomb.translate.read.ReadContext; -import io.fd.honeycomb.translate.read.ReadFailedException; -import io.fd.honeycomb.translate.spi.read.ReaderCustomizer; +import io.fd.honeycomb.translate.spi.read.Initialized; +import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager; +import io.fd.honeycomb.translate.vpp.util.NamingContext; +import io.fd.vpp.jvpp.snat.dto.SnatInterfaceDetails; +import io.fd.vpp.jvpp.snat.dto.SnatInterfaceDetailsReplyDump; 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; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev161214.NatInterfaceAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev161214._interface.nat.attributes.Nat; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev161214._interface.nat.attributes.NatBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev161214._interface.nat.attributes.nat.Outbound; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev161214._interface.nat.attributes.nat.OutboundBuilder; import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.Augmentation; +import org.opendaylight.yangtools.yang.binding.DataContainer; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -final class InterfaceOutboundNatCustomizer implements ReaderCustomizer<Outbound, OutboundBuilder> { +final class InterfaceOutboundNatCustomizer extends AbstractInterfaceNatCustomizer<Outbound, OutboundBuilder> { private static final Logger LOG = LoggerFactory.getLogger(InterfaceOutboundNatCustomizer.class); - @Nonnull + InterfaceOutboundNatCustomizer( + @Nonnull final DumpCacheManager<SnatInterfaceDetailsReplyDump, Void> dumpMgr, + @Nonnull final NamingContext ifcContext) { + super(dumpMgr, ifcContext); + } + @Override - public OutboundBuilder getBuilder(@Nonnull final InstanceIdentifier<Outbound> id) { - return new OutboundBuilder(); + protected Logger getLog() { + return LOG; } @Override - public void readCurrentAttributes(@Nonnull final InstanceIdentifier<Outbound> id, - @Nonnull final OutboundBuilder builder, @Nonnull final ReadContext ctx) - throws ReadFailedException { - // FIXME HONEYCOMB-248 VPP-459 Implement when read is available in VPP/Snat - LOG.debug("Unable to read Outbound NAT feature state for an interface"); + void setBuilderPresence(@Nonnull final OutboundBuilder builder) { + ((PresenceOutboundBuilder) builder).setPresent(true); + } + + @Override + boolean isExpectedNatType(final SnatInterfaceDetails snatInterfaceDetails) { + return snatInterfaceDetails.isInside == 0; + } + + @Nonnull + @Override + public OutboundBuilder getBuilder(@Nonnull final InstanceIdentifier<Outbound> id) { + return new PresenceOutboundBuilder(false); } @Override public void merge(@Nonnull final Builder<? extends DataObject> parentBuilder, @Nonnull final Outbound readValue) { ((NatBuilder) parentBuilder).setOutbound(readValue); } + + @Nonnull + @Override + public Initialized<? extends DataObject> init(@Nonnull final InstanceIdentifier<Outbound> id, + @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(NatInterfaceAugmentation.class) + .child(Nat.class) + .child(Outbound.class); + return Initialized.create(cfgId, readValue); + } + + // TODO HONEYCOMB-270, make this better, having to fake a builder + value is just exploitation. + + /** + * Special Builder to also propagate empty container into the resulting data. + */ + private static final class PresenceOutboundBuilder extends OutboundBuilder { + + private volatile boolean isPresent = false; + + PresenceOutboundBuilder(final boolean isPresent) { + this.isPresent = isPresent; + } + + void setPresent(final boolean present) { + this.isPresent = present; + } + + @Override + public Outbound build() { + final Outbound build = super.build(); + return isPresent + ? build + : NotPresentOutbound.NOT_PRESENT_OUTBOUND; + } + } + + /** + * Fake container that returns false on equals. + */ + private static final class NotPresentOutbound implements Outbound { + + private static final NotPresentOutbound NOT_PRESENT_OUTBOUND = new NotPresentOutbound(); + + @Override + public <E extends Augmentation<Outbound>> E getAugmentation(final Class<E> augmentationType) { + throw new UnsupportedOperationException(); + } + + @Override + public Class<? extends DataContainer> getImplementedInterface() { + return Outbound.class; + } + + @Override + public boolean equals(final Object obj) { + // This is necessary to fake this.equals(something) + return obj == NOT_PRESENT_OUTBOUND; + } + } } diff --git a/nat/nat2vpp/src/test/java/io/fd/honeycomb/nat/read/ifc/InterfaceInboundNatCustomizerTest.java b/nat/nat2vpp/src/test/java/io/fd/honeycomb/nat/read/ifc/InterfaceInboundNatCustomizerTest.java new file mode 100644 index 000000000..140d35fec --- /dev/null +++ b/nat/nat2vpp/src/test/java/io/fd/honeycomb/nat/read/ifc/InterfaceInboundNatCustomizerTest.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.nat.read.ifc; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import com.google.common.collect.Lists; +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.honeycomb.translate.vpp.util.NamingContext; +import io.fd.honeycomb.vpp.test.read.ReaderCustomizerTest; +import io.fd.vpp.jvpp.snat.dto.SnatInterfaceDetails; +import io.fd.vpp.jvpp.snat.dto.SnatInterfaceDetailsReplyDump; +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; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev161214.NatInterfaceStateAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev161214._interface.nat.attributes.Nat; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev161214._interface.nat.attributes.NatBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev161214._interface.nat.attributes.nat.Inbound; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev161214._interface.nat.attributes.nat.InboundBuilder; +import org.opendaylight.yangtools.yang.binding.ChildOf; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class InterfaceInboundNatCustomizerTest + extends ReaderCustomizerTest<Inbound, InboundBuilder> { + + private static final String IFC_NAME = "a"; + private static final int IFC_IDX = 0; + private static final String CTX_NAME = "ifc"; + + @Mock + private EntityDumpExecutor<SnatInterfaceDetailsReplyDump, Void> abc; + private DumpCacheManager<SnatInterfaceDetailsReplyDump, Void> dumpMgr; + private NamingContext ifcContext = new NamingContext(CTX_NAME, CTX_NAME); + private InstanceIdentifier<Inbound> id; + + public InterfaceInboundNatCustomizerTest() { + super(Inbound.class, NatBuilder.class); + } + + @Override + protected void setUp() throws Exception { + id = getId(Inbound.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) + .build(); + } + + static <T extends ChildOf<Nat>> InstanceIdentifier<T> getId(Class<T> boundType) { + return InstanceIdentifier.create(InterfacesState.class) + .child(Interface.class, new InterfaceKey(IFC_NAME)) + .augmentation(NatInterfaceStateAugmentation.class) + .child(Nat.class) + .child(boundType); + } + + @Test + public void testNoPresence() throws Exception { + assertFalse(getReader().read(id, ctx).isPresent()); + } + + private GenericReader<Inbound, InboundBuilder> getReader() { + return new GenericReader<>(RWUtils.makeIidWildcarded(id), customizer); + } + + @Test + public void testPresence() 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(abc).executeDump(id, null); + + assertTrue(getReader().read(id, ctx).isPresent()); + } + + @Override + protected ReaderCustomizer<Inbound, InboundBuilder> initCustomizer() { + return new InterfaceInboundNatCustomizer(dumpMgr, ifcContext); + } +}
\ No newline at end of file diff --git a/nat/nat2vpp/src/test/java/io/fd/honeycomb/nat/read/ifc/InterfaceOutboundNatCustomizerTest.java b/nat/nat2vpp/src/test/java/io/fd/honeycomb/nat/read/ifc/InterfaceOutboundNatCustomizerTest.java new file mode 100644 index 000000000..c33e040bb --- /dev/null +++ b/nat/nat2vpp/src/test/java/io/fd/honeycomb/nat/read/ifc/InterfaceOutboundNatCustomizerTest.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.nat.read.ifc; + +import static io.fd.honeycomb.nat.read.ifc.InterfaceInboundNatCustomizerTest.getId; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import com.google.common.collect.Lists; +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.honeycomb.translate.vpp.util.NamingContext; +import io.fd.honeycomb.vpp.test.read.ReaderCustomizerTest; +import io.fd.vpp.jvpp.snat.dto.SnatInterfaceDetails; +import io.fd.vpp.jvpp.snat.dto.SnatInterfaceDetailsReplyDump; +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.rev161214._interface.nat.attributes.NatBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev161214._interface.nat.attributes.nat.Outbound; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev161214._interface.nat.attributes.nat.OutboundBuilder; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class InterfaceOutboundNatCustomizerTest + extends ReaderCustomizerTest<Outbound, OutboundBuilder> { + + private static final String IFC_NAME = "a"; + private static final int IFC_IDX = 0; + private static final String CTX_NAME = "ifc"; + + @Mock + private EntityDumpExecutor<SnatInterfaceDetailsReplyDump, Void> abc; + private DumpCacheManager<SnatInterfaceDetailsReplyDump, Void> dumpMgr; + private NamingContext ifcContext = new NamingContext(CTX_NAME, CTX_NAME); + private InstanceIdentifier<Outbound> id; + + public InterfaceOutboundNatCustomizerTest() { + super(Outbound.class, NatBuilder.class); + } + + @Override + 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) + .build(); + } + + @Test + public void testNoPresence() throws Exception { + assertFalse(getReader().read(id, ctx).isPresent()); + } + + private GenericReader<Outbound, OutboundBuilder> getReader() { + return new GenericReader<>(RWUtils.makeIidWildcarded(id), customizer); + } + + @Test + public void testPresence() 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); + + assertTrue(getReader().read(id, ctx).isPresent()); + } + + @Override + protected ReaderCustomizer<Outbound, OutboundBuilder> initCustomizer() { + return new InterfaceOutboundNatCustomizer(dumpMgr, ifcContext); + } +}
\ No newline at end of file |