From 175197da8ea43335df3daeba4c6296fcd83a057c Mon Sep 17 00:00:00 2001 From: Maros Marsalek Date: Thu, 10 Nov 2016 13:31:25 +0100 Subject: Post split cleanup - change groupIds - change packages - update poms Change-Id: I343c5a292a67de1dd50687870ca4ab5b7276e93e Signed-off-by: Maros Marsalek Signed-off-by: Marek Gradzki --- nat/nat2vpp/pom.xml | 12 +- .../src/main/java/io/fd/hc2vpp/nat/NatModule.java | 72 +++++++ .../io/fd/hc2vpp/nat/jvpp/JVppSnatProvider.java | 60 ++++++ .../hc2vpp/nat/read/ExternalIpPoolCustomizer.java | 150 +++++++++++++++ .../fd/hc2vpp/nat/read/MappingEntryCustomizer.java | 171 +++++++++++++++++ .../fd/hc2vpp/nat/read/NatInstanceCustomizer.java | 114 +++++++++++ .../io/fd/hc2vpp/nat/read/NatReaderFactory.java | 90 +++++++++ .../read/ifc/AbstractInterfaceNatCustomizer.java | 75 ++++++++ .../hc2vpp/nat/read/ifc/IfcNatReaderFactory.java | 96 ++++++++++ .../read/ifc/InterfaceInboundNatCustomizer.java | 95 ++++++++++ .../read/ifc/InterfaceOutboundNatCustomizer.java | 86 +++++++++ .../io/fd/hc2vpp/nat/util/MappingEntryContext.java | 210 +++++++++++++++++++++ .../hc2vpp/nat/write/ExternalIpPoolCustomizer.java | 92 +++++++++ .../hc2vpp/nat/write/MappingEntryCustomizer.java | 182 ++++++++++++++++++ .../fd/hc2vpp/nat/write/NatInstaceCustomizer.java | 53 ++++++ .../io/fd/hc2vpp/nat/write/NatWriterFactory.java | 73 +++++++ .../write/ifc/AbstractInterfaceNatCustomizer.java | 105 +++++++++++ .../hc2vpp/nat/write/ifc/IfcNatWriterFactory.java | 62 ++++++ .../write/ifc/InterfaceInboundNatCustomizer.java | 44 +++++ .../write/ifc/InterfaceOutboundNatCustomizer.java | 44 +++++ .../main/java/io/fd/honeycomb/nat/NatModule.java | 72 ------- .../io/fd/honeycomb/nat/jvpp/JVppSnatProvider.java | 60 ------ .../nat/read/ExternalIpPoolCustomizer.java | 150 --------------- .../honeycomb/nat/read/MappingEntryCustomizer.java | 171 ----------------- .../honeycomb/nat/read/NatInstanceCustomizer.java | 114 ----------- .../io/fd/honeycomb/nat/read/NatReaderFactory.java | 90 --------- .../read/ifc/AbstractInterfaceNatCustomizer.java | 75 -------- .../nat/read/ifc/IfcNatReaderFactory.java | 96 ---------- .../read/ifc/InterfaceInboundNatCustomizer.java | 95 ---------- .../read/ifc/InterfaceOutboundNatCustomizer.java | 86 --------- .../fd/honeycomb/nat/util/MappingEntryContext.java | 210 --------------------- .../nat/write/ExternalIpPoolCustomizer.java | 92 --------- .../nat/write/MappingEntryCustomizer.java | 182 ------------------ .../honeycomb/nat/write/NatInstaceCustomizer.java | 53 ------ .../fd/honeycomb/nat/write/NatWriterFactory.java | 73 ------- .../write/ifc/AbstractInterfaceNatCustomizer.java | 105 ----------- .../nat/write/ifc/IfcNatWriterFactory.java | 62 ------ .../write/ifc/InterfaceInboundNatCustomizer.java | 44 ----- .../write/ifc/InterfaceOutboundNatCustomizer.java | 44 ----- .../test/java/io/fd/hc2vpp/nat/NatModuleTest.java | 123 ++++++++++++ .../ifc/InterfaceInboundNatCustomizerTest.java | 107 +++++++++++ .../ifc/InterfaceOutboundNatCustomizerTest.java | 94 +++++++++ .../hc2vpp/nat/util/MappingEntryContextTest.java | 198 +++++++++++++++++++ .../java/io/fd/honeycomb/nat/NatModuleTest.java | 123 ------------ .../ifc/InterfaceInboundNatCustomizerTest.java | 107 ----------- .../ifc/InterfaceOutboundNatCustomizerTest.java | 94 --------- .../nat/util/MappingEntryContextTest.java | 198 ------------------- 47 files changed, 2402 insertions(+), 2402 deletions(-) create mode 100644 nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/NatModule.java create mode 100755 nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/jvpp/JVppSnatProvider.java create mode 100644 nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/ExternalIpPoolCustomizer.java create mode 100644 nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/MappingEntryCustomizer.java create mode 100644 nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/NatInstanceCustomizer.java create mode 100644 nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/NatReaderFactory.java create mode 100644 nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/ifc/AbstractInterfaceNatCustomizer.java create mode 100644 nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/ifc/IfcNatReaderFactory.java create mode 100644 nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/ifc/InterfaceInboundNatCustomizer.java create mode 100644 nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/ifc/InterfaceOutboundNatCustomizer.java create mode 100644 nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/util/MappingEntryContext.java create mode 100644 nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/ExternalIpPoolCustomizer.java create mode 100644 nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/MappingEntryCustomizer.java create mode 100644 nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/NatInstaceCustomizer.java create mode 100644 nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/NatWriterFactory.java create mode 100644 nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/ifc/AbstractInterfaceNatCustomizer.java create mode 100644 nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/ifc/IfcNatWriterFactory.java create mode 100644 nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/ifc/InterfaceInboundNatCustomizer.java create mode 100644 nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/ifc/InterfaceOutboundNatCustomizer.java delete mode 100644 nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/NatModule.java delete mode 100755 nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/jvpp/JVppSnatProvider.java delete mode 100644 nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/ExternalIpPoolCustomizer.java delete mode 100644 nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/MappingEntryCustomizer.java delete mode 100644 nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/NatInstanceCustomizer.java delete mode 100644 nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/NatReaderFactory.java delete mode 100644 nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/ifc/AbstractInterfaceNatCustomizer.java delete mode 100644 nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/ifc/IfcNatReaderFactory.java delete mode 100644 nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/ifc/InterfaceInboundNatCustomizer.java delete mode 100644 nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/ifc/InterfaceOutboundNatCustomizer.java delete mode 100644 nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/util/MappingEntryContext.java delete mode 100644 nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/write/ExternalIpPoolCustomizer.java delete mode 100644 nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/write/MappingEntryCustomizer.java delete mode 100644 nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/write/NatInstaceCustomizer.java delete mode 100644 nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/write/NatWriterFactory.java delete mode 100644 nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/write/ifc/AbstractInterfaceNatCustomizer.java delete mode 100644 nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/write/ifc/IfcNatWriterFactory.java delete mode 100644 nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/write/ifc/InterfaceInboundNatCustomizer.java delete mode 100644 nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/write/ifc/InterfaceOutboundNatCustomizer.java create mode 100644 nat/nat2vpp/src/test/java/io/fd/hc2vpp/nat/NatModuleTest.java create mode 100644 nat/nat2vpp/src/test/java/io/fd/hc2vpp/nat/read/ifc/InterfaceInboundNatCustomizerTest.java create mode 100644 nat/nat2vpp/src/test/java/io/fd/hc2vpp/nat/read/ifc/InterfaceOutboundNatCustomizerTest.java create mode 100644 nat/nat2vpp/src/test/java/io/fd/hc2vpp/nat/util/MappingEntryContextTest.java delete mode 100644 nat/nat2vpp/src/test/java/io/fd/honeycomb/nat/NatModuleTest.java delete mode 100644 nat/nat2vpp/src/test/java/io/fd/honeycomb/nat/read/ifc/InterfaceInboundNatCustomizerTest.java delete mode 100644 nat/nat2vpp/src/test/java/io/fd/honeycomb/nat/read/ifc/InterfaceOutboundNatCustomizerTest.java delete mode 100644 nat/nat2vpp/src/test/java/io/fd/honeycomb/nat/util/MappingEntryContextTest.java (limited to 'nat/nat2vpp') diff --git a/nat/nat2vpp/pom.xml b/nat/nat2vpp/pom.xml index ad81e0662..60eb7d469 100644 --- a/nat/nat2vpp/pom.xml +++ b/nat/nat2vpp/pom.xml @@ -15,14 +15,14 @@ --> - io.fd.honeycomb.vpp + io.fd.hc2vpp.common vpp-impl-parent ../../vpp-common/vpp-impl-parent 1.16.12-SNAPSHOT 4.0.0 - io.fd.honeycomb.nat + io.fd.hc2vpp.nat nat2vpp ${project.artifactId} 1.16.12-SNAPSHOT @@ -30,7 +30,7 @@ 1.16.12-SNAPSHOT - 1.16.12-SNAPSHOT + 1.16.12-SNAPSHOT @@ -42,7 +42,7 @@ - io.fd.honeycomb.vpp + io.fd.hc2vpp.common vpp-translate-utils @@ -102,9 +102,9 @@ test - io.fd.honeycomb.vpp + io.fd.hc2vpp.common vpp-translate-test - ${honeycomb.vpp.common.version} + ${hc2vpp.common.version} test diff --git a/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/NatModule.java b/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/NatModule.java new file mode 100644 index 000000000..53f7560b6 --- /dev/null +++ b/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/NatModule.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.hc2vpp.nat; + +import com.google.common.annotations.VisibleForTesting; +import com.google.inject.AbstractModule; +import com.google.inject.Provider; +import com.google.inject.Singleton; +import com.google.inject.multibindings.Multibinder; +import io.fd.hc2vpp.nat.jvpp.JVppSnatProvider; +import io.fd.hc2vpp.nat.read.NatReaderFactory; +import io.fd.hc2vpp.nat.read.ifc.IfcNatReaderFactory; +import io.fd.hc2vpp.nat.util.MappingEntryContext; +import io.fd.hc2vpp.nat.write.NatWriterFactory; +import io.fd.hc2vpp.nat.write.ifc.IfcNatWriterFactory; +import io.fd.honeycomb.translate.read.ReaderFactory; +import io.fd.honeycomb.translate.write.WriterFactory; +import io.fd.vpp.jvpp.snat.future.FutureJVppSnatFacade; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Module class instantiating nat plugin components. + */ +public final class NatModule extends AbstractModule { + + private static final Logger LOG = LoggerFactory.getLogger(NatModule.class); + private final Class> jvppSnatProviderClass; + + public NatModule() { + this(JVppSnatProvider.class); + } + + @VisibleForTesting + NatModule(Class> jvppSnatProvider) { + this.jvppSnatProviderClass = jvppSnatProvider; + } + + @Override + protected void configure() { + // Mapping entry context util + bind(MappingEntryContext.class).toInstance(new MappingEntryContext()); + + LOG.debug("Installing NAT module"); + + // Bind to Plugin's JVPP + bind(FutureJVppSnatFacade.class).toProvider(jvppSnatProviderClass).in(Singleton.class); + + final Multibinder readBinder = Multibinder.newSetBinder(binder(), ReaderFactory.class); + readBinder.addBinding().to(IfcNatReaderFactory.class).in(Singleton.class); + readBinder.addBinding().to(NatReaderFactory.class).in(Singleton.class); + + final Multibinder writeBinder = Multibinder.newSetBinder(binder(), WriterFactory.class); + writeBinder.addBinding().to(IfcNatWriterFactory.class).in(Singleton.class); + writeBinder.addBinding().to(NatWriterFactory.class).in(Singleton.class); + LOG.info("Module NAT successfully configured"); + } +} diff --git a/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/jvpp/JVppSnatProvider.java b/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/jvpp/JVppSnatProvider.java new file mode 100755 index 000000000..c16bcbaab --- /dev/null +++ b/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/jvpp/JVppSnatProvider.java @@ -0,0 +1,60 @@ +/* + * 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.hc2vpp.nat.jvpp; + +import com.google.inject.Inject; +import io.fd.honeycomb.infra.distro.ProviderTrait; +import io.fd.vpp.jvpp.JVppRegistry; +import io.fd.vpp.jvpp.snat.JVppSnatImpl; +import io.fd.vpp.jvpp.snat.future.FutureJVppSnatFacade; +import java.io.IOException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Provides future API for jvpp-nsh plugin. Must be a singleton due to shutdown hook usage. + * Registers shutdown hook to free plugin's resources on shutdown. + */ +public final class JVppSnatProvider extends ProviderTrait { + + private static final Logger LOG = LoggerFactory.getLogger(JVppSnatProvider.class); + + @Inject + private JVppRegistry registry; + + @Override + protected FutureJVppSnatFacade create() { + try { + final JVppSnatImpl jvppSnat = new JVppSnatImpl(); + // Free jvpp-nsh plugin's resources on shutdown + Runtime.getRuntime().addShutdownHook(new Thread() { + @Override + public void run() { + LOG.info("Unloading jvpp-snat plugin"); + jvppSnat.close(); + LOG.info("Successfully unloaded jvpp-snat plugin"); + } + }); + + LOG.info("Successfully loaded jvpp-snat plugin"); + return new FutureJVppSnatFacade(registry, jvppSnat); + } catch (IOException e) { + throw new IllegalStateException("Unable to open VPP management connection", e); + } + } +} + diff --git a/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/ExternalIpPoolCustomizer.java b/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/ExternalIpPoolCustomizer.java new file mode 100644 index 000000000..615d9c70f --- /dev/null +++ b/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/ExternalIpPoolCustomizer.java @@ -0,0 +1,150 @@ +/* + * 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.hc2vpp.nat.read; + +import io.fd.honeycomb.translate.read.ReadContext; +import io.fd.honeycomb.translate.read.ReadFailedException; +import io.fd.honeycomb.translate.spi.read.Initialized; +import io.fd.honeycomb.translate.spi.read.InitializingListReaderCustomizer; +import io.fd.honeycomb.translate.util.RWUtils; +import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager; +import io.fd.honeycomb.translate.util.read.cache.EntityDumpExecutor; +import io.fd.hc2vpp.common.translate.util.Ipv4Translator; +import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer; +import io.fd.vpp.jvpp.snat.dto.SnatAddressDetails; +import io.fd.vpp.jvpp.snat.dto.SnatAddressDetailsReplyDump; +import io.fd.vpp.jvpp.snat.dto.SnatAddressDump; +import io.fd.vpp.jvpp.snat.future.FutureJVppSnatFacade; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.LongStream; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.parameters.ExternalIpAddressPool; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.parameters.ExternalIpAddressPoolBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.parameters.ExternalIpAddressPoolKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.NatInstance; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.NatInstanceKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.nat.instance.NatCurrentConfigBuilder; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +final class ExternalIpPoolCustomizer implements + InitializingListReaderCustomizer, + JvppReplyConsumer, Ipv4Translator { + + private static final Logger LOG = LoggerFactory.getLogger(ExternalIpPoolCustomizer.class); + + private final DumpCacheManager dumpMgr; + + ExternalIpPoolCustomizer(final DumpCacheManager dumpMgr) { + this.dumpMgr = dumpMgr; + } + + @Nonnull + @Override + public ExternalIpAddressPoolBuilder getBuilder(@Nonnull final InstanceIdentifier id) { + return new ExternalIpAddressPoolBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final ExternalIpAddressPoolBuilder builder, + @Nonnull final ReadContext ctx) throws ReadFailedException { + LOG.trace("Reading current attributes for external IP pool: {}", id); + + final Long poolId = id.firstKeyOf(ExternalIpAddressPool.class).getPoolId(); + final SnatAddressDetails details = + dumpMgr.getDump(id, ctx.getModificationCache(), null) + .or(new SnatAddressDetailsReplyDump()).snatAddressDetails.get(Math.toIntExact(poolId)); + + builder.setExternalIpPool( + new Ipv4Prefix(arrayToIpv4AddressNoZoneReversed(details.ipAddress).getValue() + "/32")); + builder.setPoolId(poolId); + + LOG.trace("External IP pool: {}. Read as: {}", id, builder); + } + + @Nonnull + @Override + public List getAllIds(@Nonnull final InstanceIdentifier id, + @Nonnull final ReadContext ctx) throws ReadFailedException { + final NatInstanceKey natKey = id.firstKeyOf(NatInstance.class); + if (!natKey.equals(NatInstanceCustomizer.DEFAULT_VRF_ID)) { + // IP Pools are not vrf aware ... so they are only visible under default vrf (nat-instance) + return Collections.emptyList(); + } + + LOG.trace("Listing IDs for all external IP pools within nat-instance(vrf):{}", natKey); + + // Since VPP returns every single (unordered) address instead of address range, + // there is no way to determine what the original ranges were when writing the data into VPP. + + // That's why the write and read is not symmetrical in terms of data structure, instead, + // this customizer also returns every single address as a 32 prefix and assigns an artificial key to them + + final long addressCount = dumpMgr.getDump(id, ctx.getModificationCache(), null) + .or(new SnatAddressDetailsReplyDump()).snatAddressDetails.stream() + .count(); + + final List ids = LongStream.range(0, addressCount) + .mapToObj(ExternalIpAddressPoolKey::new) + .collect(Collectors.toList()); + + LOG.trace("List of external IP pool ids: {}", ids); + return ids; + } + + @Override + public void merge(@Nonnull final Builder builder, + @Nonnull final List readData) { + ((NatCurrentConfigBuilder) builder).setExternalIpAddressPool(readData); + } + + @Override + public Initialized init( + @Nonnull final InstanceIdentifier id, + @Nonnull final ExternalIpAddressPool readValue, + @Nonnull final ReadContext ctx) { + return Initialized.create(getCfgId(id), readValue); + } + + static InstanceIdentifier getCfgId(final @Nonnull InstanceIdentifier id) { + return NatInstanceCustomizer.getCfgId(RWUtils.cutId(id, NatInstance.class)) + .child(ExternalIpAddressPool.class, id.firstKeyOf(ExternalIpAddressPool.class)); + } + + static final class AddressRangeDumpExecutor implements EntityDumpExecutor, + JvppReplyConsumer { + private final FutureJVppSnatFacade jvppSnat; + + AddressRangeDumpExecutor(final FutureJVppSnatFacade jvppSnat) { + this.jvppSnat = jvppSnat; + } + + @Nonnull + @Override + public SnatAddressDetailsReplyDump executeDump(final InstanceIdentifier identifier, final Void params) + throws ReadFailedException { + return getReplyForRead(jvppSnat.snatAddressDump(new SnatAddressDump()).toCompletableFuture(), identifier); + } + } +} diff --git a/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/MappingEntryCustomizer.java b/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/MappingEntryCustomizer.java new file mode 100644 index 000000000..75e06c26f --- /dev/null +++ b/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/MappingEntryCustomizer.java @@ -0,0 +1,171 @@ +/* + * 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.hc2vpp.nat.read; + +import io.fd.hc2vpp.nat.util.MappingEntryContext; +import io.fd.honeycomb.translate.read.ReadContext; +import io.fd.honeycomb.translate.read.ReadFailedException; +import io.fd.honeycomb.translate.spi.read.Initialized; +import io.fd.honeycomb.translate.spi.read.InitializingListReaderCustomizer; +import io.fd.honeycomb.translate.util.RWUtils; +import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager; +import io.fd.honeycomb.translate.util.read.cache.EntityDumpExecutor; +import io.fd.hc2vpp.common.translate.util.Ipv4Translator; +import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer; +import io.fd.vpp.jvpp.snat.dto.SnatStaticMappingDetails; +import io.fd.vpp.jvpp.snat.dto.SnatStaticMappingDetailsReplyDump; +import io.fd.vpp.jvpp.snat.dto.SnatStaticMappingDump; +import io.fd.vpp.jvpp.snat.future.FutureJVppSnatFacade; +import java.util.List; +import java.util.stream.Collectors; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.mapping.entry.ExternalSrcPortBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.mapping.entry.InternalSrcPortBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.MappingTable; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.NatInstance; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.nat.instance.MappingTableBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.nat.instance.mapping.table.MappingEntry; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.nat.instance.mapping.table.MappingEntryBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.nat.instance.mapping.table.MappingEntryKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.port.number.port.type.SinglePortNumberBuilder; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +final class MappingEntryCustomizer implements Ipv4Translator, + InitializingListReaderCustomizer { + + private static final Logger LOG = LoggerFactory.getLogger(MappingEntryCustomizer.class); + + private final DumpCacheManager dumpCacheManager; + private final MappingEntryContext mappingEntryContext; + + MappingEntryCustomizer( + final DumpCacheManager dumpCacheManager, + final MappingEntryContext mappingEntryContext) { + this.dumpCacheManager = dumpCacheManager; + this.mappingEntryContext = mappingEntryContext; + } + + @Nonnull + @Override + public MappingEntryBuilder getBuilder(@Nonnull final InstanceIdentifier id) { + return new MappingEntryBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final MappingEntryBuilder builder, @Nonnull final ReadContext ctx) + throws ReadFailedException { + LOG.trace("Reading current attributes for mapping-entry: {}", id); + + final int idx = id.firstKeyOf(MappingEntry.class).getIndex().intValue(); + final int natInstanceId = id.firstKeyOf(NatInstance.class).getId().intValue(); + final List details = + dumpCacheManager.getDump(id, ctx.getModificationCache(), null) + .or(new SnatStaticMappingDetailsReplyDump()).snatStaticMappingDetails; + final SnatStaticMappingDetails snatStaticMappingDetails = + mappingEntryContext.findDetails(details, natInstanceId, idx, ctx.getMappingContext()); + + builder.setIndex((long) idx); + builder.setType( + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.MappingEntry.Type.Static); + // Snat only supports ipv4 for now + builder.setExternalSrcAddress(arrayToIpv4AddressNoZoneReversed(snatStaticMappingDetails.externalIpAddress)); + builder.setInternalSrcAddress( + new IpAddress(arrayToIpv4AddressNoZoneReversed(snatStaticMappingDetails.localIpAddress))); + + if (snatStaticMappingDetails.addrOnly == 0) { + builder.setExternalSrcPort(new ExternalSrcPortBuilder() + .setPortType(new SinglePortNumberBuilder().setSinglePortNumber(new PortNumber( + (int) snatStaticMappingDetails.externalPort)) + .build()) + .build()); + builder.setInternalSrcPort(new InternalSrcPortBuilder() + .setPortType(new SinglePortNumberBuilder().setSinglePortNumber(new PortNumber( + (int) snatStaticMappingDetails.localPort)) + .build()) + .build()); + } + + LOG.trace("Mapping-entry read as: {}", builder); + } + + @Nonnull + @Override + public List getAllIds(@Nonnull final InstanceIdentifier id, + @Nonnull final ReadContext context) throws ReadFailedException { + final Long natInstanceId = id.firstKeyOf(NatInstance.class).getId(); + LOG.trace("Listing IDs for all mapping-entries within nat-instance(vrf):{}", natInstanceId); + + final List entryKeys = + dumpCacheManager.getDump(id, context.getModificationCache(), null) + .or(new SnatStaticMappingDetailsReplyDump()).snatStaticMappingDetails.stream() + .filter(detail -> natInstanceId == detail.vrfId) + .map(detail -> mappingEntryContext + .getStoredOrArtificialIndex(natInstanceId, detail, context.getMappingContext())) + .map(MappingEntryKey::new) + .collect(Collectors.toList()); + LOG.debug("List of mapping-entry keys within nat-instance(vrf):{} : {}", natInstanceId, entryKeys); + + return entryKeys; + } + + @Override + public void merge(@Nonnull final Builder builder, + @Nonnull final List readData) { + ((MappingTableBuilder) builder).setMappingEntry(readData); + } + + @Override + public Initialized init(@Nonnull final InstanceIdentifier id, + @Nonnull final MappingEntry readValue, + @Nonnull final ReadContext ctx) { + return Initialized.create(getCfgId(id), + new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntryBuilder(readValue) + .build()); + } + + static InstanceIdentifier getCfgId(final @Nonnull InstanceIdentifier id) { + return NatInstanceCustomizer.getCfgId(RWUtils.cutId(id, NatInstance.class)) + .child(MappingTable.class) + .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry.class, + new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntryKey(id.firstKeyOf(MappingEntry.class).getIndex())); + } + + static final class MappingEntryDumpExecutor + implements EntityDumpExecutor, JvppReplyConsumer { + + private final FutureJVppSnatFacade jvppSnat; + + MappingEntryDumpExecutor(final FutureJVppSnatFacade jvppSnat) { + this.jvppSnat = jvppSnat; + } + + @Nonnull + @Override + public SnatStaticMappingDetailsReplyDump executeDump(final InstanceIdentifier identifier, final Void params) + throws ReadFailedException { + return getReplyForRead(jvppSnat.snatStaticMappingDump(new SnatStaticMappingDump()).toCompletableFuture(), + identifier); + } + } +} diff --git a/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/NatInstanceCustomizer.java b/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/NatInstanceCustomizer.java new file mode 100644 index 000000000..9542587d0 --- /dev/null +++ b/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/NatInstanceCustomizer.java @@ -0,0 +1,114 @@ +/* + * 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.hc2vpp.nat.read; + +import io.fd.honeycomb.translate.read.ReadContext; +import io.fd.honeycomb.translate.read.ReadFailedException; +import io.fd.honeycomb.translate.spi.read.Initialized; +import io.fd.honeycomb.translate.spi.read.InitializingListReaderCustomizer; +import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager; +import io.fd.vpp.jvpp.snat.dto.SnatStaticMappingDetailsReplyDump; +import java.util.List; +import java.util.stream.Collectors; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.NatConfig; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.NatInstancesBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.NatInstance; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.NatInstanceBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.NatInstanceKey; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Nat instance ID is mapped to VRF-ID in VPP. + */ +final class NatInstanceCustomizer implements InitializingListReaderCustomizer { + + private static final Logger LOG = LoggerFactory.getLogger(NatInstanceCustomizer.class); + static final NatInstanceKey DEFAULT_VRF_ID = new NatInstanceKey(0L); + + private final DumpCacheManager dumpCacheManager; + + NatInstanceCustomizer( + final DumpCacheManager dumpCacheManager) { + this.dumpCacheManager = dumpCacheManager; + } + + @Nonnull + @Override + public NatInstanceBuilder getBuilder(@Nonnull final InstanceIdentifier id) { + return new NatInstanceBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final NatInstanceBuilder builder, @Nonnull final ReadContext ctx) + throws ReadFailedException { + LOG.trace("Reading current attributes for nat-instance: {}", id); + builder.setId(id.firstKeyOf(NatInstance.class).getId()); + } + + @Nonnull + @Override + public List getAllIds(@Nonnull final InstanceIdentifier id, + @Nonnull final ReadContext context) throws ReadFailedException { + LOG.trace("Listing IDs for all nat-instances"); + + // Find the nat instance IDs (vrf-ids) by listing all static mappings and their VRF assignment + final List vrfIds = + dumpCacheManager.getDump(id, context.getModificationCache(), null) + .or(new SnatStaticMappingDetailsReplyDump()).snatStaticMappingDetails.stream() + .map(detail -> detail.vrfId) + .map(vrfId -> new NatInstanceKey((long) vrfId)) + .collect(Collectors.toList()); + + // Add default vrf id if not present + if (!vrfIds.contains(DEFAULT_VRF_ID)) { + vrfIds.add(0, DEFAULT_VRF_ID); + } + + LOG.debug("List of nat-instance keys (vrf-ids): {}", vrfIds); + return vrfIds; + } + + @Override + public void merge(@Nonnull final Builder builder, @Nonnull final List readData) { + ((NatInstancesBuilder) builder).setNatInstance(readData); + } + + @Override + public Initialized init(@Nonnull final InstanceIdentifier id, + @Nonnull final NatInstance readValue, + @Nonnull final ReadContext ctx) { + return Initialized.create(getCfgId(id), + new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.NatInstanceBuilder() + .setId(readValue.getId()) + .build()); + } + + static InstanceIdentifier getCfgId( + @Nonnull final InstanceIdentifier id) { + return InstanceIdentifier.create(NatConfig.class) + .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.NatInstances.class) + .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.NatInstance.class, + new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.NatInstanceKey( + id.firstKeyOf(NatInstance.class).getId())); + } +} diff --git a/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/NatReaderFactory.java b/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/NatReaderFactory.java new file mode 100644 index 000000000..76c478594 --- /dev/null +++ b/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/NatReaderFactory.java @@ -0,0 +1,90 @@ +/* + * 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.hc2vpp.nat.read; + +import com.google.common.collect.Sets; +import com.google.inject.Inject; +import io.fd.hc2vpp.nat.util.MappingEntryContext; +import io.fd.honeycomb.translate.impl.read.GenericInitListReader; +import io.fd.honeycomb.translate.read.ReaderFactory; +import io.fd.honeycomb.translate.read.registry.ModifiableReaderRegistryBuilder; +import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager; +import io.fd.vpp.jvpp.snat.dto.SnatAddressDetailsReplyDump; +import io.fd.vpp.jvpp.snat.dto.SnatStaticMappingDetailsReplyDump; +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.nat.rev150908.NatState; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.NatStateBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.mapping.entry.ExternalSrcPort; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.mapping.entry.InternalSrcPort; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.parameters.ExternalIpAddressPool; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.NatInstances; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.NatInstancesBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.NatInstance; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.nat.instance.MappingTable; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.nat.instance.MappingTableBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.nat.instance.NatCurrentConfig; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.nat.instance.NatCurrentConfigBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.nat.instance.mapping.table.MappingEntry; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class NatReaderFactory implements ReaderFactory { + + private static final InstanceIdentifier NAT_OPER_ID = InstanceIdentifier.create(NatState.class); + private static final InstanceIdentifier NAT_INSTANCES_ID = NAT_OPER_ID.child(NatInstances.class); + private static final InstanceIdentifier NAT_INSTANCE_ID = NAT_INSTANCES_ID.child(NatInstance.class); + private static final InstanceIdentifier CURRENT_CONFIG = + NAT_INSTANCE_ID.child(NatCurrentConfig.class); + private static final InstanceIdentifier MAP_TABLE_ID = NAT_INSTANCE_ID.child(MappingTable.class); + private static final InstanceIdentifier MAP_ENTRY_ID = MAP_TABLE_ID.child(MappingEntry.class); + + private final MappingEntryContext mappingEntryContext; + private final DumpCacheManager mapEntryDumpMgr; + private final DumpCacheManager addressRangeDumpMgr; + + + @Inject + public NatReaderFactory(final FutureJVppSnatFacade jvppSnat, + final MappingEntryContext mappingEntryContext) { + this.mappingEntryContext = mappingEntryContext; + this.mapEntryDumpMgr = + new DumpCacheManager.DumpCacheManagerBuilder() + .withExecutor(new MappingEntryCustomizer.MappingEntryDumpExecutor(jvppSnat)) + .build(); + + this.addressRangeDumpMgr = + new DumpCacheManager.DumpCacheManagerBuilder() + .withExecutor(new ExternalIpPoolCustomizer.AddressRangeDumpExecutor(jvppSnat)) + .build(); + } + + @Override + public void init(@Nonnull final ModifiableReaderRegistryBuilder registry) { + registry.addStructuralReader(NAT_OPER_ID, NatStateBuilder.class); + registry.addStructuralReader(NAT_INSTANCES_ID, NatInstancesBuilder.class); + registry.add(new GenericInitListReader<>(NAT_INSTANCE_ID, new NatInstanceCustomizer(mapEntryDumpMgr))); + registry.addStructuralReader(MAP_TABLE_ID, MappingTableBuilder.class); + registry.subtreeAdd(Sets.newHashSet(InstanceIdentifier.create(MappingEntry.class).child(ExternalSrcPort.class), + InstanceIdentifier.create(MappingEntry.class).child(InternalSrcPort.class)), + new GenericInitListReader<>(MAP_ENTRY_ID, + new MappingEntryCustomizer(mapEntryDumpMgr, mappingEntryContext))); + + registry.addStructuralReader(CURRENT_CONFIG, NatCurrentConfigBuilder.class); + registry.add(new GenericInitListReader<>(CURRENT_CONFIG.child(ExternalIpAddressPool.class), + new ExternalIpPoolCustomizer(addressRangeDumpMgr))); + } +} diff --git a/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/ifc/AbstractInterfaceNatCustomizer.java b/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/ifc/AbstractInterfaceNatCustomizer.java new file mode 100644 index 000000000..d6cc2b144 --- /dev/null +++ b/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/ifc/AbstractInterfaceNatCustomizer.java @@ -0,0 +1,75 @@ +/* + * 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.hc2vpp.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.hc2vpp.common.translate.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> + implements InitializingReaderCustomizer { + + private final DumpCacheManager dumpMgr; + private final NamingContext ifcContext; + + AbstractInterfaceNatCustomizer(@Nonnull final DumpCacheManager dumpMgr, + @Nonnull final NamingContext ifcContext) { + this.dumpMgr = dumpMgr; + this.ifcContext = ifcContext; + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final B builder, + @Nonnull final ReadContext ctx) throws ReadFailedException { + // NOOP + } + + @Override + public boolean isPresent(final InstanceIdentifier id, final C built, 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 dump = + dumpMgr.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() + .filter(snatIfcDetail -> snatIfcDetail.swIfIndex == index) + .filter(this::isExpectedNatType) + .findFirst() + .isPresent(); + // Not setting data, just marking the builder to propagate empty container to indicate presence + } + + protected abstract Logger getLog(); + + abstract boolean isExpectedNatType(final SnatInterfaceDetails snatInterfaceDetails); +} diff --git a/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/ifc/IfcNatReaderFactory.java b/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/ifc/IfcNatReaderFactory.java new file mode 100644 index 000000000..87a70f707 --- /dev/null +++ b/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/ifc/IfcNatReaderFactory.java @@ -0,0 +1,96 @@ +/* + * 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.hc2vpp.nat.read.ifc; + + +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.hc2vpp.common.translate.util.JvppReplyConsumer; +import io.fd.hc2vpp.common.translate.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; +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.NatInterfaceStateAugmentationBuilder; +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.Outbound; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * Factory producing readers for nat plugin's data. + */ +public final class IfcNatReaderFactory implements ReaderFactory { + + private static final InstanceIdentifier + IFC_ID = InstanceIdentifier.create(InterfacesState.class).child(Interface.class); + private static final InstanceIdentifier NAT_AUG_ID = + IFC_ID.augmentation(NatInterfaceStateAugmentation.class); + private static final InstanceIdentifier NAT_AUG_CONTAINER_ID = NAT_AUG_ID.child(Nat.class); + + private final DumpCacheManager snatIfcDumpMgr; + private final NamingContext ifcContext; + + @Inject + public IfcNatReaderFactory(final FutureJVppSnatFacade jvppSnat, + @Named("interface-context") final NamingContext ifcContext) { + this.snatIfcDumpMgr = new DumpCacheManager.DumpCacheManagerBuilder() + .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 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, + 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/hc2vpp/nat/read/ifc/InterfaceInboundNatCustomizer.java b/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/ifc/InterfaceInboundNatCustomizer.java new file mode 100644 index 000000000..ea3d05fd5 --- /dev/null +++ b/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/ifc/InterfaceInboundNatCustomizer.java @@ -0,0 +1,95 @@ +/* + * 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.hc2vpp.nat.read.ifc; + +import io.fd.honeycomb.translate.read.ReadContext; +import io.fd.honeycomb.translate.read.ReadFailedException; +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 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.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +final class InterfaceInboundNatCustomizer extends AbstractInterfaceNatCustomizer { + + private static final Logger LOG = LoggerFactory.getLogger(InterfaceInboundNatCustomizer.class); + + InterfaceInboundNatCustomizer( + @Nonnull final DumpCacheManager dumpMgr, + @Nonnull final NamingContext ifcContext) { + super(dumpMgr, ifcContext); + } + + @Override + protected Logger getLog() { + return LOG; + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final InboundBuilder builder, @Nonnull final ReadContext ctx) + throws ReadFailedException { + super.readCurrentAttributes(id, builder, ctx); + } + + @Override + boolean isExpectedNatType(final SnatInterfaceDetails snatInterfaceDetails) { + return snatInterfaceDetails.isInside == 1; + } + + @Nonnull + @Override + public InboundBuilder getBuilder(@Nonnull final InstanceIdentifier id) { + // Return not present value by default + return new InboundBuilder(); + } + + @Override + public void merge(@Nonnull final Builder parentBuilder, @Nonnull final Inbound readValue) { + ((NatBuilder) parentBuilder).setInbound(readValue); + } + + @Nonnull + @Override + public Initialized init(@Nonnull final InstanceIdentifier id, + @Nonnull final Inbound readValue, + @Nonnull final ReadContext ctx) { + final InstanceIdentifier 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); + } +} diff --git a/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/ifc/InterfaceOutboundNatCustomizer.java b/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/ifc/InterfaceOutboundNatCustomizer.java new file mode 100644 index 000000000..c4974b9fb --- /dev/null +++ b/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/ifc/InterfaceOutboundNatCustomizer.java @@ -0,0 +1,86 @@ +/* + * 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.hc2vpp.nat.read.ifc; + +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 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.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +final class InterfaceOutboundNatCustomizer extends AbstractInterfaceNatCustomizer { + + private static final Logger LOG = LoggerFactory.getLogger(InterfaceOutboundNatCustomizer.class); + + InterfaceOutboundNatCustomizer( + @Nonnull final DumpCacheManager dumpMgr, + @Nonnull final NamingContext ifcContext) { + super(dumpMgr, ifcContext); + } + + @Override + protected Logger getLog() { + return LOG; + } + + @Override + boolean isExpectedNatType(final SnatInterfaceDetails snatInterfaceDetails) { + return snatInterfaceDetails.isInside == 0; + } + + @Nonnull + @Override + public OutboundBuilder getBuilder(@Nonnull final InstanceIdentifier id) { + return new OutboundBuilder(); + } + + @Override + public void merge(@Nonnull final Builder parentBuilder, @Nonnull final Outbound readValue) { + ((NatBuilder) parentBuilder).setOutbound(readValue); + } + + @Nonnull + @Override + public Initialized init(@Nonnull final InstanceIdentifier id, + @Nonnull final Outbound readValue, + @Nonnull final ReadContext ctx) { + final InstanceIdentifier 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); + } +} diff --git a/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/util/MappingEntryContext.java b/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/util/MappingEntryContext.java new file mode 100644 index 000000000..6db8d468c --- /dev/null +++ b/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/util/MappingEntryContext.java @@ -0,0 +1,210 @@ +/* + * 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.hc2vpp.nat.util; + +import static com.google.common.base.Preconditions.checkArgument; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Optional; +import io.fd.honeycomb.translate.MappingContext; +import io.fd.hc2vpp.common.translate.util.Ipv4Translator; +import io.fd.vpp.jvpp.snat.dto.SnatStaticMappingDetails; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import javax.annotation.Nonnull; +import javax.annotation.concurrent.ThreadSafe; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.Contexts; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.nat.context.rev161214.NatMappingEntryCtxAugmentation; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.nat.context.rev161214.mapping.entry.context.attributes.NatMappingEntryContext; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.nat.context.rev161214.mapping.entry.context.attributes.nat.mapping.entry.context.NatInstance; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.nat.context.rev161214.mapping.entry.context.attributes.nat.mapping.entry.context.NatInstanceKey; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.nat.context.rev161214.mapping.entry.context.attributes.nat.mapping.entry.context.nat.instance.MappingTable; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.nat.context.rev161214.mapping.entry.context.attributes.nat.mapping.entry.context.nat.instance.mapping.table.MappingEntry; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.nat.context.rev161214.mapping.entry.context.attributes.nat.mapping.entry.context.nat.instance.mapping.table.MappingEntryBuilder; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.nat.context.rev161214.mapping.entry.context.attributes.nat.mapping.entry.context.nat.instance.mapping.table.MappingEntryKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Context tracker for Nat Mapping entries. + */ +@ThreadSafe +public class MappingEntryContext implements Ipv4Translator { + + private static final Logger LOG = LoggerFactory.getLogger(MappingEntryContext.class); + + /** + * Add mapping entry to index mapping to context. + */ + public synchronized void addEntry(final long natInstanceId, + final long entryId, + @Nonnull final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry entry, + @Nonnull final MappingContext mappingContext) { + final InstanceIdentifier id = getId(natInstanceId, entryToKey(entry)); + checkArgument(!containsEntry(natInstanceId, entry, mappingContext), "Mapping for %s already present", id); + mappingContext.put(id, toCtxMapEntry(entry, entryId)); + } + + /** + * Check whether mapping entry to index mapping already exists in context. + */ + public synchronized boolean containsEntry(final long natInstanceId, + @Nonnull final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry entry, + @Nonnull final MappingContext mappingContext) { + final InstanceIdentifier id = getId(natInstanceId, entryToKey(entry)); + return mappingContext.read(id).isPresent(); + } + + @VisibleForTesting + static InstanceIdentifier getId(final Long natInstanceId, final MappingEntryKey key) { + return getTableId(natInstanceId).child(MappingEntry.class, key); + } + + @VisibleForTesting + static InstanceIdentifier getTableId(final long natInstanceId) { + return InstanceIdentifier.create(Contexts.class) + .augmentation(NatMappingEntryCtxAugmentation.class) + .child(NatMappingEntryContext.class) + .child(NatInstance.class, new NatInstanceKey(natInstanceId)) + .child(MappingTable.class); + } + + @VisibleForTesting + static MappingEntryKey entryToKey( + final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry entry) { + // Only IPv4 + return new MappingEntryKey(new IpAddress(entry.getExternalSrcAddress()), entry.getInternalSrcAddress()); + } + + private MappingEntryKey entryToKey(final SnatStaticMappingDetails entry) { + // Only IPv4 + return new MappingEntryKey( + new IpAddress(new Ipv4Address(arrayToIpv4AddressNoZoneReversed(entry.externalIpAddress))), + new IpAddress(new Ipv4Address(arrayToIpv4AddressNoZoneReversed(entry.localIpAddress)))); + } + + private boolean equalEntries(final SnatStaticMappingDetails detail, final MappingEntry ctxMappingEntry) { + final IpAddress internalAddrFromDetails = + new IpAddress(new Ipv4Address(arrayToIpv4AddressNoZoneReversed(detail.localIpAddress))); + // Only IPv4 + if (!ctxMappingEntry.getInternal().equals(internalAddrFromDetails)) { + return false; + } + // Only IPv4 + final IpAddress externalAddrFromDetails = + new IpAddress(new Ipv4Address(arrayToIpv4AddressNoZoneReversed(detail.externalIpAddress))); + if (!ctxMappingEntry.getExternal().equals(externalAddrFromDetails)) { + return false; + } + return true; + } + + @VisibleForTesting + static MappingEntry toCtxMapEntry( + @Nonnull final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry entry, + final long entryId) { + return new MappingEntryBuilder() + .setKey(entryToKey(entry)) + .setIndex(entryId) + .build(); + } + + private MappingEntry toCtxMapEntry(@Nonnull final SnatStaticMappingDetails details, final long entryId) { + return new MappingEntryBuilder() + .setKey(entryToKey(details)) + .setIndex(entryId) + .build(); + } + + /** + * Delete mapping of mapping entry to index from context. + */ + public synchronized void removeEntry(final long natInstanceId, + @Nonnull final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry entry, + @Nonnull final MappingContext mappingContext) { + mappingContext.delete(getId(natInstanceId, entryToKey(entry))); + } + + /** + * Find specific details in provided collection identified with provided index. + */ + public synchronized SnatStaticMappingDetails findDetails(@Nonnull final List details, + final long natInstanceId, final long idx, + @Nonnull final MappingContext mappingContext) { + // Find mapping entry for Index + final MappingEntry ctxMappingEntry = mappingContext.read(getTableId(natInstanceId)) + .transform(MappingTable::getMappingEntry) + .or(Collections.emptyList()) + .stream() + .filter(entry -> entry.getIndex() == idx) + .findFirst() + .orElseThrow(() -> new IllegalStateException("Unable to find context mapping for nat-instance: " + + natInstanceId + " and ID: " + idx)); + + // Find which details matches the context stored entry under index + return details.stream() + .filter(detail -> equalEntries(detail, ctxMappingEntry)) + .findFirst() + .orElseThrow(() -> new IllegalStateException("Unable to match mapping for nat-instance: " + + natInstanceId + " and match: " + ctxMappingEntry + " in: " + details)); + } + + /** + * Get index for a mapping entry details or create an artificial one. + */ + public synchronized long getStoredOrArtificialIndex(final Long natInstanceId, + @Nonnull final SnatStaticMappingDetails details, + @Nonnull final MappingContext mappingContext) { + return mappingContext.read(getId(natInstanceId, entryToKey(details))) + .transform(MappingEntry::getIndex) + .or(() -> getArtificialId(details, natInstanceId, mappingContext)); + } + + /** + * Get index for a stored mapping entry. + */ + public synchronized Optional getStoredIndex(final long natInstanceId, + @Nonnull final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry entry, + @Nonnull final MappingContext mappingContext) { + return mappingContext.read(getId(natInstanceId, entryToKey(entry))) + .transform(MappingEntry::getIndex); + } + + private long getArtificialId(final SnatStaticMappingDetails details, final Long natInstanceId, + final MappingContext mappingContext) { + LOG.trace("Assigning artificial ID for {}", details); + final long artificialIdx = findFreeIndex(natInstanceId, mappingContext); + LOG.debug("Artificial ID for {} assigned as: {}", details, artificialIdx); + mappingContext.put(getId(natInstanceId, entryToKey(details)), toCtxMapEntry(details, artificialIdx)); + return artificialIdx; + } + + private long findFreeIndex(final long natInstanceId, final MappingContext mappingContext) { + return mappingContext.read(getTableId(natInstanceId)) + .transform(MappingTable::getMappingEntry) + .or(Collections.emptyList()) + .stream() + .map(MappingEntry::getIndex) + .max(Comparator.naturalOrder()) + .map(i -> i + 1) + .orElse(0L); + } +} diff --git a/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/ExternalIpPoolCustomizer.java b/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/ExternalIpPoolCustomizer.java new file mode 100644 index 000000000..505318c22 --- /dev/null +++ b/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/ExternalIpPoolCustomizer.java @@ -0,0 +1,92 @@ +/* + * 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.hc2vpp.nat.write; + +import static com.google.common.base.Preconditions.checkArgument; + +import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer; +import io.fd.hc2vpp.common.translate.util.Ipv4AddressRange; +import io.fd.hc2vpp.common.translate.util.Ipv4Translator; +import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer; +import io.fd.honeycomb.translate.write.WriteContext; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.vpp.jvpp.snat.dto.SnatAddAddressRange; +import io.fd.vpp.jvpp.snat.future.FutureJVppSnatFacade; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.NatInstance; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.parameters.ExternalIpAddressPool; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.parameters.ExternalIpAddressPoolKey; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +final class ExternalIpPoolCustomizer implements ListWriterCustomizer, + JvppReplyConsumer, Ipv4Translator { + + private static final Logger LOG = LoggerFactory.getLogger(ExternalIpPoolCustomizer.class); + + private final FutureJVppSnatFacade jvppSnat; + + ExternalIpPoolCustomizer(@Nonnull final FutureJVppSnatFacade jvppSnat) { + this.jvppSnat = jvppSnat; + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final ExternalIpAddressPool dataAfter, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + checkArgument(id.firstKeyOf(NatInstance.class).getId() == 0, + "External IP pools are only assignable for nat instance(vrf-id) with ID 0"); + LOG.trace("Adding address range:{}, as: {}", id, dataAfter); + // TODO check overlaps ? VPP-478 maybe no necessary, depending on how VPP handles them + getReplyForCreate(jvppSnat.snatAddAddressRange( + getRequest(dataAfter.getExternalIpPool(), true)).toCompletableFuture(), id, dataAfter); + LOG.debug("Address range: {} added successfully", id); + } + + @Override + public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final ExternalIpAddressPool dataBefore, + @Nonnull final ExternalIpAddressPool dataAfter, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, + new UnsupportedOperationException("Address range update is not supported")); + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final ExternalIpAddressPool dataBefore, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + LOG.trace("Deleting address range:{}, as: {}", id, dataBefore); + getReplyForDelete(jvppSnat.snatAddAddressRange( + getRequest(dataBefore.getExternalIpPool(), false)).toCompletableFuture(), id); + LOG.debug("Deleting range: {} added successfully", id); + } + + private SnatAddAddressRange getRequest(final Ipv4Prefix externalIpPool, boolean isAdd) { + SnatAddAddressRange request = new SnatAddAddressRange(); + // SNAT supports only IPv4 now, so does the model + final Ipv4AddressRange range = Ipv4AddressRange.fromPrefix(externalIpPool); + LOG.trace("Handling address range: {}", range); + request.isIp4 = 1; + request.isAdd = (byte) (isAdd ? 1 : 0); + request.firstIpAddress = ipv4AddressNoZoneToArray(range.getStart()); + request.lastIpAddress = ipv4AddressNoZoneToArray(range.getEnd()); + return request; + } +} diff --git a/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/MappingEntryCustomizer.java b/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/MappingEntryCustomizer.java new file mode 100644 index 000000000..c5417d925 --- /dev/null +++ b/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/MappingEntryCustomizer.java @@ -0,0 +1,182 @@ +/* + * 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.hc2vpp.nat.write; + +import static com.google.common.base.Preconditions.checkArgument; + +import com.google.common.base.Optional; +import io.fd.hc2vpp.nat.util.MappingEntryContext; +import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer; +import io.fd.hc2vpp.common.translate.util.Ipv4Translator; +import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer; +import io.fd.honeycomb.translate.write.WriteContext; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.vpp.jvpp.snat.dto.SnatAddStaticMapping; +import io.fd.vpp.jvpp.snat.future.FutureJVppSnatFacade; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.PortNumber; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.NatInstance; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntryKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.port.number.PortType; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.port.number.port.type.SinglePortNumber; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +final class MappingEntryCustomizer implements ListWriterCustomizer, + JvppReplyConsumer, Ipv4Translator { + + private static final Logger LOG = LoggerFactory.getLogger(MappingEntryCustomizer.class); + + private final FutureJVppSnatFacade jvppSnat; + private final MappingEntryContext mappingEntryContext; + + MappingEntryCustomizer(final FutureJVppSnatFacade jvppSnat, final MappingEntryContext mappingEntryContext) { + this.jvppSnat = jvppSnat; + this.mappingEntryContext = mappingEntryContext; + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final MappingEntry dataAfter, + @Nonnull final WriteContext writeContext) + throws WriteFailedException { + // Only static mapping supported by SNAT for now + checkArgument(dataAfter.getType() == + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.MappingEntry.Type.Static, + "Only static NAT entries are supported currently. Trying to write: %s entry", dataAfter.getType()); + final Long natInstanceId = id.firstKeyOf(NatInstance.class).getId(); + final Long mappingEntryId = id.firstKeyOf(MappingEntry.class).getIndex(); + LOG.debug("Writing mapping entry: {} for nat-instance(vrf): {}", natInstanceId, mappingEntryId); + + final SnatAddStaticMapping request = getRequest(id, dataAfter, natInstanceId, true); + getReplyForWrite(jvppSnat.snatAddStaticMapping(request).toCompletableFuture(), id); + + // Store context mapping only if not already present under the same exact mapping + synchronized (mappingEntryContext) { + if (shouldStoreContextMapping(natInstanceId, mappingEntryId, dataAfter, writeContext)) { + mappingEntryContext + .addEntry(natInstanceId, mappingEntryId, dataAfter, writeContext.getMappingContext()); + } + } + LOG.trace("Mapping entry: {} for nat-instance(vrf): {} written successfully", request.vrfId, id); + } + + /** + * Check whether entry is already stored in context under the same index. + * + * @return true if it's not yet stored under same index, false otherwise. + */ + private boolean shouldStoreContextMapping(final long natInstanceId, final long mappingEntryId, + final MappingEntry dataAfter, + final WriteContext writeCtx) { + if (!mappingEntryContext.containsEntry(natInstanceId, dataAfter, writeCtx.getMappingContext())) { + return true; + } + + final Optional storedIndex = + mappingEntryContext.getStoredIndex(natInstanceId, dataAfter, writeCtx.getMappingContext()); + if (!storedIndex.isPresent()) { + return true; + } + + if (storedIndex.get() != mappingEntryId) { + return true; + } + + return false; + } + + @Override + public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final MappingEntry dataBefore, + @Nonnull final MappingEntry dataAfter, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, + new UnsupportedOperationException("Mapping entry update not supported")); + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final MappingEntry dataBefore, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + final long natInstanceId = id.firstKeyOf(NatInstance.class).getId(); + final MappingEntryKey mappingEntryKey = id.firstKeyOf(MappingEntry.class); + LOG.debug("Deleting mapping entry: {} for nat-instance(vrf): {}", natInstanceId, mappingEntryKey); + + final SnatAddStaticMapping request = getRequest(id, dataBefore, natInstanceId, false); + getReplyForWrite(jvppSnat.snatAddStaticMapping(request).toCompletableFuture(), id); + mappingEntryContext.removeEntry(natInstanceId, dataBefore, writeContext.getMappingContext()); + LOG.trace("Mapping entry: {} for nat-instance(vrf): {} deleted successfully", request.vrfId, id); + } + + private SnatAddStaticMapping getRequest(final InstanceIdentifier id, + final MappingEntry dataAfter, + final Long natInstanceId, + final boolean isAdd) + throws WriteFailedException.CreateFailedException { + final SnatAddStaticMapping request = new SnatAddStaticMapping(); + request.isAdd = isAdd + ? (byte) 1 + : 0; + request.isIp4 = 1; + // VPP uses int, model long + request.vrfId = natInstanceId.intValue(); + + // Snat supports only ipv4 now + if (dataAfter.getInternalSrcAddress().getIpv4Address() == null) { + throw new WriteFailedException.CreateFailedException(id, dataAfter, + new UnsupportedOperationException( + String.format("No Ipv4 present for in address %s. Ipv6 not supported", + dataAfter.getInternalSrcAddress()))); + } + + request.addrOnly = 1; + request.localIpAddress = + ipv4AddressNoZoneToArray(dataAfter.getInternalSrcAddress().getIpv4Address().getValue()); + request.externalIpAddress = ipv4AddressNoZoneToArray(dataAfter.getExternalSrcAddress().getValue()); + + Optional internalPortNumber = getPortNumber(id, dataAfter, + (entry) -> Optional.fromNullable(entry.getInternalSrcPort()).transform(PortNumber::getPortType)); + Optional externalPortNumber = getPortNumber(id, dataAfter, + (entry) -> Optional.fromNullable(entry.getExternalSrcPort()).transform(PortNumber::getPortType)); + if (internalPortNumber.isPresent() && externalPortNumber.isPresent()) { + request.addrOnly = 0; + request.localPort = internalPortNumber.get(); + request.externalPort = externalPortNumber.get(); + } + return request; + } + + private Optional getPortNumber(final InstanceIdentifier id, final MappingEntry dataAfter, + final PortGetter portGetter) { + return portGetter.getPortType(dataAfter).transform(port -> { + if (port instanceof SinglePortNumber) { + return ((SinglePortNumber) port).getSinglePortNumber().getValue().shortValue(); + } else { + throw new IllegalArgumentException( + String.format("Only single port number supported. Submitted: %s for entry: %s", + dataAfter.getInternalSrcPort(), id)); + } + }); + } + + interface PortGetter { + Optional getPortType(MappingEntry entry); + } +} diff --git a/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/NatInstaceCustomizer.java b/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/NatInstaceCustomizer.java new file mode 100644 index 000000000..5d1c2b53c --- /dev/null +++ b/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/NatInstaceCustomizer.java @@ -0,0 +1,53 @@ +/* + * 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.hc2vpp.nat.write; + +import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer; +import io.fd.honeycomb.translate.write.WriteContext; +import io.fd.honeycomb.translate.write.WriteFailedException; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.NatInstance; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.NatInstanceKey; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +final class NatInstaceCustomizer implements ListWriterCustomizer { + + private static final Logger LOG = LoggerFactory.getLogger(NatInstaceCustomizer.class); + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final NatInstance dataAfter, @Nonnull final WriteContext writeContext) + throws WriteFailedException { + LOG.trace("Writing nat-instance: {}", id); + } + + @Override + public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final NatInstance dataBefore, @Nonnull final NatInstance dataAfter, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + LOG.trace("Updating nat-instance: {}", id); + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final NatInstance dataBefore, @Nonnull final WriteContext writeContext) + throws WriteFailedException { + LOG.trace("Deleting nat-instance: {}", id); + } +} diff --git a/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/NatWriterFactory.java b/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/NatWriterFactory.java new file mode 100644 index 000000000..e239721d4 --- /dev/null +++ b/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/NatWriterFactory.java @@ -0,0 +1,73 @@ +/* + * 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.hc2vpp.nat.write; + +import com.google.common.collect.Sets; +import com.google.inject.Inject; +import io.fd.hc2vpp.nat.util.MappingEntryContext; +import io.fd.honeycomb.translate.impl.write.GenericListWriter; +import io.fd.honeycomb.translate.write.WriterFactory; +import io.fd.honeycomb.translate.write.registry.ModifiableWriterRegistryBuilder; +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.nat.rev150908.NatConfig; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.mapping.entry.ExternalSrcPort; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.mapping.entry.InternalSrcPort; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.NatInstances; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.NatInstance; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.MappingTable; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.parameters.ExternalIpAddressPool; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * Nat Writers registration. + */ +public final class NatWriterFactory implements WriterFactory { + + private static final InstanceIdentifier NAT_CFG_ID = InstanceIdentifier.create(NatConfig.class); + private static final InstanceIdentifier NAT_INSTANCE_ID = + NAT_CFG_ID.child(NatInstances.class).child(NatInstance.class); + private static final InstanceIdentifier MAP_ENTRY_ID = + NAT_INSTANCE_ID.child(MappingTable.class).child(MappingEntry.class); + + private final FutureJVppSnatFacade jvppSnat; + private final MappingEntryContext mappingEntryContext; + + @Inject + public NatWriterFactory(final FutureJVppSnatFacade jvppSnat, + final MappingEntryContext mappingEntryContext) { + this.jvppSnat = jvppSnat; + this.mappingEntryContext = mappingEntryContext; + } + + @Override + public void init(@Nonnull final ModifiableWriterRegistryBuilder registry) { + // Nat-instance + registry.add(new GenericListWriter<>(NAT_INSTANCE_ID, new NatInstaceCustomizer())); + // Mapping-entry + registry.subtreeAdd(Sets.newHashSet(InstanceIdentifier.create(MappingEntry.class).child(ExternalSrcPort.class), + InstanceIdentifier.create(MappingEntry.class).child(InternalSrcPort.class)), + new GenericListWriter<>(MAP_ENTRY_ID, new MappingEntryCustomizer(jvppSnat, mappingEntryContext))); + + // External address pool has to be executed before mapping entry. Because adding mapping entries requires to + // already have an IP range predefined ... in some cases + registry.addBefore(new GenericListWriter<>(NAT_INSTANCE_ID.child(ExternalIpAddressPool.class), + new ExternalIpPoolCustomizer(jvppSnat)), + MAP_ENTRY_ID); + } +} diff --git a/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/ifc/AbstractInterfaceNatCustomizer.java b/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/ifc/AbstractInterfaceNatCustomizer.java new file mode 100644 index 000000000..6893f0b35 --- /dev/null +++ b/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/ifc/AbstractInterfaceNatCustomizer.java @@ -0,0 +1,105 @@ +/* + * 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.hc2vpp.nat.write.ifc; + +import io.fd.honeycomb.translate.spi.write.WriterCustomizer; +import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer; +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.honeycomb.translate.write.WriteContext; +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.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.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; + +abstract class AbstractInterfaceNatCustomizer implements JvppReplyConsumer, WriterCustomizer { + + private final FutureJVppSnatFacade jvppSnat; + private final NamingContext ifcContext; + + AbstractInterfaceNatCustomizer(@Nonnull final FutureJVppSnatFacade jvppSnat, + @Nonnull final NamingContext ifcContext) { + this.jvppSnat = jvppSnat; + this.ifcContext = ifcContext; + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final D dataAfter, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + final String ifcName = id.firstKeyOf(Interface.class).getName(); + getLog().debug("Enabling " + getType() + " NAT on interface: {}", ifcName); + getLog().debug("Enabling " + getType() + " NAT: {}", id); + + final int ifcIndex = ifcContext.getIndex(ifcName, writeContext.getMappingContext()); + final SnatInterfaceAddDelFeature request = getRequest(ifcIndex, (byte)1); + final CompletionStage future = jvppSnat.snatInterfaceAddDelFeature(request); + + final SnatInterfaceAddDelFeatureReply reply = getReplyForWrite(future.toCompletableFuture(), id); + getLog().debug("NAT " + getType() + " enabled successfully on: {}, reply: {}", ifcName, reply); + } + + @Override + public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final D dataBefore, @Nonnull final D dataAfter, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, + new UnsupportedOperationException("Unable to update NAT feature")); + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final D dataBefore, @Nonnull final WriteContext writeContext) + throws WriteFailedException { + final String ifcName = id.firstKeyOf(Interface.class).getName(); + getLog().debug("Disabling " + getType() + " NAT on interface: {}", ifcName); + getLog().debug("Disabling " + getType() + " NAT: {}", id); + + final int ifcIndex = ifcContext.getIndex(ifcName, writeContext.getMappingContext()); + final SnatInterfaceAddDelFeature request = getRequest(ifcIndex, (byte)0); + final CompletionStage future = jvppSnat.snatInterfaceAddDelFeature(request); + + final SnatInterfaceAddDelFeatureReply reply = getReplyForWrite(future.toCompletableFuture(), id); + getLog().debug("NAT " + getType() + " disabled successfully on: {}, reply: {}", ifcName, reply); + } + + enum NatType { + INBOUND((byte)1), OUTBOUND((byte)0); + + private final byte isInside; + + NatType(final byte isInside) { + this.isInside = isInside; + } + } + + 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; + } + +} diff --git a/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/ifc/IfcNatWriterFactory.java b/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/ifc/IfcNatWriterFactory.java new file mode 100644 index 000000000..5cb10b750 --- /dev/null +++ b/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/ifc/IfcNatWriterFactory.java @@ -0,0 +1,62 @@ +/* + * 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.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.write.WriterFactory; +import io.fd.honeycomb.translate.write.registry.ModifiableWriterRegistryBuilder; +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; +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.nat.Inbound; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev161214._interface.nat.attributes.nat.Outbound; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * Nat Writers registration. + */ +public final class IfcNatWriterFactory implements WriterFactory { + + private static final InstanceIdentifier + IFC_ID = InstanceIdentifier.create(Interfaces.class).child(Interface.class); + private static final InstanceIdentifier NAT_AUG_ID = + IFC_ID .augmentation(NatInterfaceAugmentation.class).child(Nat.class); + + private final FutureJVppSnatFacade jvppSnat; + private final NamingContext ifcContext; + + @Inject + public IfcNatWriterFactory(final FutureJVppSnatFacade jvppSnat, + @Named("interface-context") final NamingContext ifcContext) { + this.jvppSnat = jvppSnat; + this.ifcContext = ifcContext; + } + + @Override + public void init(@Nonnull final ModifiableWriterRegistryBuilder registry) { + registry.addAfter(new GenericWriter<>(NAT_AUG_ID.child(Inbound.class), + new InterfaceInboundNatCustomizer(jvppSnat, ifcContext)), IFC_ID); + registry.addAfter(new GenericWriter<>(NAT_AUG_ID.child(Outbound.class), + new InterfaceOutboundNatCustomizer(jvppSnat, ifcContext)), IFC_ID); + } +} diff --git a/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/ifc/InterfaceInboundNatCustomizer.java b/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/ifc/InterfaceInboundNatCustomizer.java new file mode 100644 index 000000000..3f7c90b57 --- /dev/null +++ b/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/ifc/InterfaceInboundNatCustomizer.java @@ -0,0 +1,44 @@ +/* + * 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.hc2vpp.nat.write.ifc; + +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.opendaylight.params.xml.ns.yang._interface.nat.rev161214._interface.nat.attributes.nat.Inbound; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +final class InterfaceInboundNatCustomizer extends AbstractInterfaceNatCustomizer { + + private static final Logger LOG = LoggerFactory.getLogger(InterfaceInboundNatCustomizer.class); + + InterfaceInboundNatCustomizer(@Nonnull final FutureJVppSnatFacade jvppSnat, + @Nonnull final NamingContext ifcContext) { + super(jvppSnat, ifcContext); + } + + @Override + NatType getType() { + return NatType.INBOUND; + } + + @Override + Logger getLog() { + return LOG; + } +} diff --git a/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/ifc/InterfaceOutboundNatCustomizer.java b/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/ifc/InterfaceOutboundNatCustomizer.java new file mode 100644 index 000000000..970c38baa --- /dev/null +++ b/nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write/ifc/InterfaceOutboundNatCustomizer.java @@ -0,0 +1,44 @@ +/* + * 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.hc2vpp.nat.write.ifc; + +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.opendaylight.params.xml.ns.yang._interface.nat.rev161214._interface.nat.attributes.nat.Outbound; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +final class InterfaceOutboundNatCustomizer extends AbstractInterfaceNatCustomizer { + + private static final Logger LOG = LoggerFactory.getLogger(InterfaceOutboundNatCustomizer.class); + + InterfaceOutboundNatCustomizer(@Nonnull final FutureJVppSnatFacade jvppSnat, + @Nonnull final NamingContext ifcContext) { + super(jvppSnat, ifcContext); + } + + @Override + NatType getType() { + return NatType.OUTBOUND; + } + + @Override + Logger getLog() { + return LOG; + } +} diff --git a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/NatModule.java b/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/NatModule.java deleted file mode 100644 index adaaca9c3..000000000 --- a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/NatModule.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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; - -import com.google.common.annotations.VisibleForTesting; -import com.google.inject.AbstractModule; -import com.google.inject.Provider; -import com.google.inject.Singleton; -import com.google.inject.multibindings.Multibinder; -import io.fd.honeycomb.nat.jvpp.JVppSnatProvider; -import io.fd.honeycomb.nat.read.NatReaderFactory; -import io.fd.honeycomb.nat.read.ifc.IfcNatReaderFactory; -import io.fd.honeycomb.nat.util.MappingEntryContext; -import io.fd.honeycomb.nat.write.NatWriterFactory; -import io.fd.honeycomb.nat.write.ifc.IfcNatWriterFactory; -import io.fd.honeycomb.translate.read.ReaderFactory; -import io.fd.honeycomb.translate.write.WriterFactory; -import io.fd.vpp.jvpp.snat.future.FutureJVppSnatFacade; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Module class instantiating nat plugin components. - */ -public final class NatModule extends AbstractModule { - - private static final Logger LOG = LoggerFactory.getLogger(NatModule.class); - private final Class> jvppSnatProviderClass; - - public NatModule() { - this(JVppSnatProvider.class); - } - - @VisibleForTesting - NatModule(Class> jvppSnatProvider) { - this.jvppSnatProviderClass = jvppSnatProvider; - } - - @Override - protected void configure() { - // Mapping entry context util - bind(MappingEntryContext.class).toInstance(new MappingEntryContext()); - - LOG.debug("Installing NAT module"); - - // Bind to Plugin's JVPP - bind(FutureJVppSnatFacade.class).toProvider(jvppSnatProviderClass).in(Singleton.class); - - final Multibinder readBinder = Multibinder.newSetBinder(binder(), ReaderFactory.class); - readBinder.addBinding().to(IfcNatReaderFactory.class).in(Singleton.class); - readBinder.addBinding().to(NatReaderFactory.class).in(Singleton.class); - - final Multibinder writeBinder = Multibinder.newSetBinder(binder(), WriterFactory.class); - writeBinder.addBinding().to(IfcNatWriterFactory.class).in(Singleton.class); - writeBinder.addBinding().to(NatWriterFactory.class).in(Singleton.class); - LOG.info("Module NAT successfully configured"); - } -} diff --git a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/jvpp/JVppSnatProvider.java b/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/jvpp/JVppSnatProvider.java deleted file mode 100755 index b83665679..000000000 --- a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/jvpp/JVppSnatProvider.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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.jvpp; - -import com.google.inject.Inject; -import io.fd.honeycomb.infra.distro.ProviderTrait; -import io.fd.vpp.jvpp.JVppRegistry; -import io.fd.vpp.jvpp.snat.JVppSnatImpl; -import io.fd.vpp.jvpp.snat.future.FutureJVppSnatFacade; -import java.io.IOException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Provides future API for jvpp-nsh plugin. Must be a singleton due to shutdown hook usage. - * Registers shutdown hook to free plugin's resources on shutdown. - */ -public final class JVppSnatProvider extends ProviderTrait { - - private static final Logger LOG = LoggerFactory.getLogger(JVppSnatProvider.class); - - @Inject - private JVppRegistry registry; - - @Override - protected FutureJVppSnatFacade create() { - try { - final JVppSnatImpl jvppSnat = new JVppSnatImpl(); - // Free jvpp-nsh plugin's resources on shutdown - Runtime.getRuntime().addShutdownHook(new Thread() { - @Override - public void run() { - LOG.info("Unloading jvpp-snat plugin"); - jvppSnat.close(); - LOG.info("Successfully unloaded jvpp-snat plugin"); - } - }); - - LOG.info("Successfully loaded jvpp-snat plugin"); - return new FutureJVppSnatFacade(registry, jvppSnat); - } catch (IOException e) { - throw new IllegalStateException("Unable to open VPP management connection", e); - } - } -} - diff --git a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/ExternalIpPoolCustomizer.java b/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/ExternalIpPoolCustomizer.java deleted file mode 100644 index 0650280f1..000000000 --- a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/ExternalIpPoolCustomizer.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * 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; - -import io.fd.honeycomb.translate.read.ReadContext; -import io.fd.honeycomb.translate.read.ReadFailedException; -import io.fd.honeycomb.translate.spi.read.Initialized; -import io.fd.honeycomb.translate.spi.read.InitializingListReaderCustomizer; -import io.fd.honeycomb.translate.util.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.Ipv4Translator; -import io.fd.honeycomb.translate.vpp.util.JvppReplyConsumer; -import io.fd.vpp.jvpp.snat.dto.SnatAddressDetails; -import io.fd.vpp.jvpp.snat.dto.SnatAddressDetailsReplyDump; -import io.fd.vpp.jvpp.snat.dto.SnatAddressDump; -import io.fd.vpp.jvpp.snat.future.FutureJVppSnatFacade; -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.LongStream; -import javax.annotation.Nonnull; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.parameters.ExternalIpAddressPool; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.parameters.ExternalIpAddressPoolBuilder; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.parameters.ExternalIpAddressPoolKey; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.NatInstance; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.NatInstanceKey; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.nat.instance.NatCurrentConfigBuilder; -import org.opendaylight.yangtools.concepts.Builder; -import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -final class ExternalIpPoolCustomizer implements - InitializingListReaderCustomizer, - JvppReplyConsumer, Ipv4Translator { - - private static final Logger LOG = LoggerFactory.getLogger(ExternalIpPoolCustomizer.class); - - private final DumpCacheManager dumpMgr; - - ExternalIpPoolCustomizer(final DumpCacheManager dumpMgr) { - this.dumpMgr = dumpMgr; - } - - @Nonnull - @Override - public ExternalIpAddressPoolBuilder getBuilder(@Nonnull final InstanceIdentifier id) { - return new ExternalIpAddressPoolBuilder(); - } - - @Override - public void readCurrentAttributes(@Nonnull final InstanceIdentifier id, - @Nonnull final ExternalIpAddressPoolBuilder builder, - @Nonnull final ReadContext ctx) throws ReadFailedException { - LOG.trace("Reading current attributes for external IP pool: {}", id); - - final Long poolId = id.firstKeyOf(ExternalIpAddressPool.class).getPoolId(); - final SnatAddressDetails details = - dumpMgr.getDump(id, ctx.getModificationCache(), null) - .or(new SnatAddressDetailsReplyDump()).snatAddressDetails.get(Math.toIntExact(poolId)); - - builder.setExternalIpPool( - new Ipv4Prefix(arrayToIpv4AddressNoZoneReversed(details.ipAddress).getValue() + "/32")); - builder.setPoolId(poolId); - - LOG.trace("External IP pool: {}. Read as: {}", id, builder); - } - - @Nonnull - @Override - public List getAllIds(@Nonnull final InstanceIdentifier id, - @Nonnull final ReadContext ctx) throws ReadFailedException { - final NatInstanceKey natKey = id.firstKeyOf(NatInstance.class); - if (!natKey.equals(NatInstanceCustomizer.DEFAULT_VRF_ID)) { - // IP Pools are not vrf aware ... so they are only visible under default vrf (nat-instance) - return Collections.emptyList(); - } - - LOG.trace("Listing IDs for all external IP pools within nat-instance(vrf):{}", natKey); - - // Since VPP returns every single (unordered) address instead of address range, - // there is no way to determine what the original ranges were when writing the data into VPP. - - // That's why the write and read is not symmetrical in terms of data structure, instead, - // this customizer also returns every single address as a 32 prefix and assigns an artificial key to them - - final long addressCount = dumpMgr.getDump(id, ctx.getModificationCache(), null) - .or(new SnatAddressDetailsReplyDump()).snatAddressDetails.stream() - .count(); - - final List ids = LongStream.range(0, addressCount) - .mapToObj(ExternalIpAddressPoolKey::new) - .collect(Collectors.toList()); - - LOG.trace("List of external IP pool ids: {}", ids); - return ids; - } - - @Override - public void merge(@Nonnull final Builder builder, - @Nonnull final List readData) { - ((NatCurrentConfigBuilder) builder).setExternalIpAddressPool(readData); - } - - @Override - public Initialized init( - @Nonnull final InstanceIdentifier id, - @Nonnull final ExternalIpAddressPool readValue, - @Nonnull final ReadContext ctx) { - return Initialized.create(getCfgId(id), readValue); - } - - static InstanceIdentifier getCfgId(final @Nonnull InstanceIdentifier id) { - return NatInstanceCustomizer.getCfgId(RWUtils.cutId(id, NatInstance.class)) - .child(ExternalIpAddressPool.class, id.firstKeyOf(ExternalIpAddressPool.class)); - } - - static final class AddressRangeDumpExecutor implements EntityDumpExecutor, - JvppReplyConsumer { - private final FutureJVppSnatFacade jvppSnat; - - AddressRangeDumpExecutor(final FutureJVppSnatFacade jvppSnat) { - this.jvppSnat = jvppSnat; - } - - @Nonnull - @Override - public SnatAddressDetailsReplyDump executeDump(final InstanceIdentifier identifier, final Void params) - throws ReadFailedException { - return getReplyForRead(jvppSnat.snatAddressDump(new SnatAddressDump()).toCompletableFuture(), identifier); - } - } -} diff --git a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/MappingEntryCustomizer.java b/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/MappingEntryCustomizer.java deleted file mode 100644 index df0a8e886..000000000 --- a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/MappingEntryCustomizer.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * 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; - -import io.fd.honeycomb.nat.util.MappingEntryContext; -import io.fd.honeycomb.translate.read.ReadContext; -import io.fd.honeycomb.translate.read.ReadFailedException; -import io.fd.honeycomb.translate.spi.read.Initialized; -import io.fd.honeycomb.translate.spi.read.InitializingListReaderCustomizer; -import io.fd.honeycomb.translate.util.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.Ipv4Translator; -import io.fd.honeycomb.translate.vpp.util.JvppReplyConsumer; -import io.fd.vpp.jvpp.snat.dto.SnatStaticMappingDetails; -import io.fd.vpp.jvpp.snat.dto.SnatStaticMappingDetailsReplyDump; -import io.fd.vpp.jvpp.snat.dto.SnatStaticMappingDump; -import io.fd.vpp.jvpp.snat.future.FutureJVppSnatFacade; -import java.util.List; -import java.util.stream.Collectors; -import javax.annotation.Nonnull; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.mapping.entry.ExternalSrcPortBuilder; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.mapping.entry.InternalSrcPortBuilder; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.MappingTable; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.NatInstance; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.nat.instance.MappingTableBuilder; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.nat.instance.mapping.table.MappingEntry; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.nat.instance.mapping.table.MappingEntryBuilder; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.nat.instance.mapping.table.MappingEntryKey; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.port.number.port.type.SinglePortNumberBuilder; -import org.opendaylight.yangtools.concepts.Builder; -import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -final class MappingEntryCustomizer implements Ipv4Translator, - InitializingListReaderCustomizer { - - private static final Logger LOG = LoggerFactory.getLogger(MappingEntryCustomizer.class); - - private final DumpCacheManager dumpCacheManager; - private final MappingEntryContext mappingEntryContext; - - MappingEntryCustomizer( - final DumpCacheManager dumpCacheManager, - final MappingEntryContext mappingEntryContext) { - this.dumpCacheManager = dumpCacheManager; - this.mappingEntryContext = mappingEntryContext; - } - - @Nonnull - @Override - public MappingEntryBuilder getBuilder(@Nonnull final InstanceIdentifier id) { - return new MappingEntryBuilder(); - } - - @Override - public void readCurrentAttributes(@Nonnull final InstanceIdentifier id, - @Nonnull final MappingEntryBuilder builder, @Nonnull final ReadContext ctx) - throws ReadFailedException { - LOG.trace("Reading current attributes for mapping-entry: {}", id); - - final int idx = id.firstKeyOf(MappingEntry.class).getIndex().intValue(); - final int natInstanceId = id.firstKeyOf(NatInstance.class).getId().intValue(); - final List details = - dumpCacheManager.getDump(id, ctx.getModificationCache(), null) - .or(new SnatStaticMappingDetailsReplyDump()).snatStaticMappingDetails; - final SnatStaticMappingDetails snatStaticMappingDetails = - mappingEntryContext.findDetails(details, natInstanceId, idx, ctx.getMappingContext()); - - builder.setIndex((long) idx); - builder.setType( - org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.MappingEntry.Type.Static); - // Snat only supports ipv4 for now - builder.setExternalSrcAddress(arrayToIpv4AddressNoZoneReversed(snatStaticMappingDetails.externalIpAddress)); - builder.setInternalSrcAddress( - new IpAddress(arrayToIpv4AddressNoZoneReversed(snatStaticMappingDetails.localIpAddress))); - - if (snatStaticMappingDetails.addrOnly == 0) { - builder.setExternalSrcPort(new ExternalSrcPortBuilder() - .setPortType(new SinglePortNumberBuilder().setSinglePortNumber(new PortNumber( - (int) snatStaticMappingDetails.externalPort)) - .build()) - .build()); - builder.setInternalSrcPort(new InternalSrcPortBuilder() - .setPortType(new SinglePortNumberBuilder().setSinglePortNumber(new PortNumber( - (int) snatStaticMappingDetails.localPort)) - .build()) - .build()); - } - - LOG.trace("Mapping-entry read as: {}", builder); - } - - @Nonnull - @Override - public List getAllIds(@Nonnull final InstanceIdentifier id, - @Nonnull final ReadContext context) throws ReadFailedException { - final Long natInstanceId = id.firstKeyOf(NatInstance.class).getId(); - LOG.trace("Listing IDs for all mapping-entries within nat-instance(vrf):{}", natInstanceId); - - final List entryKeys = - dumpCacheManager.getDump(id, context.getModificationCache(), null) - .or(new SnatStaticMappingDetailsReplyDump()).snatStaticMappingDetails.stream() - .filter(detail -> natInstanceId == detail.vrfId) - .map(detail -> mappingEntryContext - .getStoredOrArtificialIndex(natInstanceId, detail, context.getMappingContext())) - .map(MappingEntryKey::new) - .collect(Collectors.toList()); - LOG.debug("List of mapping-entry keys within nat-instance(vrf):{} : {}", natInstanceId, entryKeys); - - return entryKeys; - } - - @Override - public void merge(@Nonnull final Builder builder, - @Nonnull final List readData) { - ((MappingTableBuilder) builder).setMappingEntry(readData); - } - - @Override - public Initialized init(@Nonnull final InstanceIdentifier id, - @Nonnull final MappingEntry readValue, - @Nonnull final ReadContext ctx) { - return Initialized.create(getCfgId(id), - new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntryBuilder(readValue) - .build()); - } - - static InstanceIdentifier getCfgId(final @Nonnull InstanceIdentifier id) { - return NatInstanceCustomizer.getCfgId(RWUtils.cutId(id, NatInstance.class)) - .child(MappingTable.class) - .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry.class, - new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntryKey(id.firstKeyOf(MappingEntry.class).getIndex())); - } - - static final class MappingEntryDumpExecutor - implements EntityDumpExecutor, JvppReplyConsumer { - - private final FutureJVppSnatFacade jvppSnat; - - MappingEntryDumpExecutor(final FutureJVppSnatFacade jvppSnat) { - this.jvppSnat = jvppSnat; - } - - @Nonnull - @Override - public SnatStaticMappingDetailsReplyDump executeDump(final InstanceIdentifier identifier, final Void params) - throws ReadFailedException { - return getReplyForRead(jvppSnat.snatStaticMappingDump(new SnatStaticMappingDump()).toCompletableFuture(), - identifier); - } - } -} diff --git a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/NatInstanceCustomizer.java b/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/NatInstanceCustomizer.java deleted file mode 100644 index 56965f7b4..000000000 --- a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/NatInstanceCustomizer.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * 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; - -import io.fd.honeycomb.translate.read.ReadContext; -import io.fd.honeycomb.translate.read.ReadFailedException; -import io.fd.honeycomb.translate.spi.read.Initialized; -import io.fd.honeycomb.translate.spi.read.InitializingListReaderCustomizer; -import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager; -import io.fd.vpp.jvpp.snat.dto.SnatStaticMappingDetailsReplyDump; -import java.util.List; -import java.util.stream.Collectors; -import javax.annotation.Nonnull; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.NatConfig; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.NatInstancesBuilder; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.NatInstance; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.NatInstanceBuilder; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.NatInstanceKey; -import org.opendaylight.yangtools.concepts.Builder; -import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Nat instance ID is mapped to VRF-ID in VPP. - */ -final class NatInstanceCustomizer implements InitializingListReaderCustomizer { - - private static final Logger LOG = LoggerFactory.getLogger(NatInstanceCustomizer.class); - static final NatInstanceKey DEFAULT_VRF_ID = new NatInstanceKey(0L); - - private final DumpCacheManager dumpCacheManager; - - NatInstanceCustomizer( - final DumpCacheManager dumpCacheManager) { - this.dumpCacheManager = dumpCacheManager; - } - - @Nonnull - @Override - public NatInstanceBuilder getBuilder(@Nonnull final InstanceIdentifier id) { - return new NatInstanceBuilder(); - } - - @Override - public void readCurrentAttributes(@Nonnull final InstanceIdentifier id, - @Nonnull final NatInstanceBuilder builder, @Nonnull final ReadContext ctx) - throws ReadFailedException { - LOG.trace("Reading current attributes for nat-instance: {}", id); - builder.setId(id.firstKeyOf(NatInstance.class).getId()); - } - - @Nonnull - @Override - public List getAllIds(@Nonnull final InstanceIdentifier id, - @Nonnull final ReadContext context) throws ReadFailedException { - LOG.trace("Listing IDs for all nat-instances"); - - // Find the nat instance IDs (vrf-ids) by listing all static mappings and their VRF assignment - final List vrfIds = - dumpCacheManager.getDump(id, context.getModificationCache(), null) - .or(new SnatStaticMappingDetailsReplyDump()).snatStaticMappingDetails.stream() - .map(detail -> detail.vrfId) - .map(vrfId -> new NatInstanceKey((long) vrfId)) - .collect(Collectors.toList()); - - // Add default vrf id if not present - if (!vrfIds.contains(DEFAULT_VRF_ID)) { - vrfIds.add(0, DEFAULT_VRF_ID); - } - - LOG.debug("List of nat-instance keys (vrf-ids): {}", vrfIds); - return vrfIds; - } - - @Override - public void merge(@Nonnull final Builder builder, @Nonnull final List readData) { - ((NatInstancesBuilder) builder).setNatInstance(readData); - } - - @Override - public Initialized init(@Nonnull final InstanceIdentifier id, - @Nonnull final NatInstance readValue, - @Nonnull final ReadContext ctx) { - return Initialized.create(getCfgId(id), - new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.NatInstanceBuilder() - .setId(readValue.getId()) - .build()); - } - - static InstanceIdentifier getCfgId( - @Nonnull final InstanceIdentifier id) { - return InstanceIdentifier.create(NatConfig.class) - .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.NatInstances.class) - .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.NatInstance.class, - new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.NatInstanceKey( - id.firstKeyOf(NatInstance.class).getId())); - } -} diff --git a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/NatReaderFactory.java b/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/NatReaderFactory.java deleted file mode 100644 index ff0d1880c..000000000 --- a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/NatReaderFactory.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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; - -import com.google.common.collect.Sets; -import com.google.inject.Inject; -import io.fd.honeycomb.nat.util.MappingEntryContext; -import io.fd.honeycomb.translate.impl.read.GenericInitListReader; -import io.fd.honeycomb.translate.read.ReaderFactory; -import io.fd.honeycomb.translate.read.registry.ModifiableReaderRegistryBuilder; -import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager; -import io.fd.vpp.jvpp.snat.dto.SnatAddressDetailsReplyDump; -import io.fd.vpp.jvpp.snat.dto.SnatStaticMappingDetailsReplyDump; -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.nat.rev150908.NatState; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.NatStateBuilder; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.mapping.entry.ExternalSrcPort; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.mapping.entry.InternalSrcPort; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.parameters.ExternalIpAddressPool; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.NatInstances; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.NatInstancesBuilder; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.NatInstance; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.nat.instance.MappingTable; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.nat.instance.MappingTableBuilder; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.nat.instance.NatCurrentConfig; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.nat.instance.NatCurrentConfigBuilder; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.nat.instance.mapping.table.MappingEntry; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; - -public class NatReaderFactory implements ReaderFactory { - - private static final InstanceIdentifier NAT_OPER_ID = InstanceIdentifier.create(NatState.class); - private static final InstanceIdentifier NAT_INSTANCES_ID = NAT_OPER_ID.child(NatInstances.class); - private static final InstanceIdentifier NAT_INSTANCE_ID = NAT_INSTANCES_ID.child(NatInstance.class); - private static final InstanceIdentifier CURRENT_CONFIG = - NAT_INSTANCE_ID.child(NatCurrentConfig.class); - private static final InstanceIdentifier MAP_TABLE_ID = NAT_INSTANCE_ID.child(MappingTable.class); - private static final InstanceIdentifier MAP_ENTRY_ID = MAP_TABLE_ID.child(MappingEntry.class); - - private final MappingEntryContext mappingEntryContext; - private final DumpCacheManager mapEntryDumpMgr; - private final DumpCacheManager addressRangeDumpMgr; - - - @Inject - public NatReaderFactory(final FutureJVppSnatFacade jvppSnat, - final MappingEntryContext mappingEntryContext) { - this.mappingEntryContext = mappingEntryContext; - this.mapEntryDumpMgr = - new DumpCacheManager.DumpCacheManagerBuilder() - .withExecutor(new MappingEntryCustomizer.MappingEntryDumpExecutor(jvppSnat)) - .build(); - - this.addressRangeDumpMgr = - new DumpCacheManager.DumpCacheManagerBuilder() - .withExecutor(new ExternalIpPoolCustomizer.AddressRangeDumpExecutor(jvppSnat)) - .build(); - } - - @Override - public void init(@Nonnull final ModifiableReaderRegistryBuilder registry) { - registry.addStructuralReader(NAT_OPER_ID, NatStateBuilder.class); - registry.addStructuralReader(NAT_INSTANCES_ID, NatInstancesBuilder.class); - registry.add(new GenericInitListReader<>(NAT_INSTANCE_ID, new NatInstanceCustomizer(mapEntryDumpMgr))); - registry.addStructuralReader(MAP_TABLE_ID, MappingTableBuilder.class); - registry.subtreeAdd(Sets.newHashSet(InstanceIdentifier.create(MappingEntry.class).child(ExternalSrcPort.class), - InstanceIdentifier.create(MappingEntry.class).child(InternalSrcPort.class)), - new GenericInitListReader<>(MAP_ENTRY_ID, - new MappingEntryCustomizer(mapEntryDumpMgr, mappingEntryContext))); - - registry.addStructuralReader(CURRENT_CONFIG, NatCurrentConfigBuilder.class); - registry.add(new GenericInitListReader<>(CURRENT_CONFIG.child(ExternalIpAddressPool.class), - new ExternalIpPoolCustomizer(addressRangeDumpMgr))); - } -} 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 deleted file mode 100644 index f4d45900c..000000000 --- a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/ifc/AbstractInterfaceNatCustomizer.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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> - implements InitializingReaderCustomizer { - - private final DumpCacheManager dumpMgr; - private final NamingContext ifcContext; - - AbstractInterfaceNatCustomizer(@Nonnull final DumpCacheManager dumpMgr, - @Nonnull final NamingContext ifcContext) { - this.dumpMgr = dumpMgr; - this.ifcContext = ifcContext; - } - - @Override - public void readCurrentAttributes(@Nonnull final InstanceIdentifier id, - @Nonnull final B builder, - @Nonnull final ReadContext ctx) throws ReadFailedException { - // NOOP - } - - @Override - public boolean isPresent(final InstanceIdentifier id, final C built, 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 dump = - dumpMgr.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() - .filter(snatIfcDetail -> snatIfcDetail.swIfIndex == index) - .filter(this::isExpectedNatType) - .findFirst() - .isPresent(); - // Not setting data, just marking the builder to propagate empty container to indicate presence - } - - protected abstract Logger getLog(); - - 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 deleted file mode 100644 index 761986fc1..000000000 --- a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/ifc/IfcNatReaderFactory.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * 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.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; -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.NatInterfaceStateAugmentationBuilder; -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.Outbound; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; - -/** - * Factory producing readers for nat plugin's data. - */ -public final class IfcNatReaderFactory implements ReaderFactory { - - private static final InstanceIdentifier - IFC_ID = InstanceIdentifier.create(InterfacesState.class).child(Interface.class); - private static final InstanceIdentifier NAT_AUG_ID = - IFC_ID.augmentation(NatInterfaceStateAugmentation.class); - private static final InstanceIdentifier NAT_AUG_CONTAINER_ID = NAT_AUG_ID.child(Nat.class); - - private final DumpCacheManager snatIfcDumpMgr; - private final NamingContext ifcContext; - - @Inject - public IfcNatReaderFactory(final FutureJVppSnatFacade jvppSnat, - @Named("interface-context") final NamingContext ifcContext) { - this.snatIfcDumpMgr = new DumpCacheManager.DumpCacheManagerBuilder() - .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 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, - 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 deleted file mode 100644 index 3e4b60fb4..000000000 --- a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/ifc/InterfaceInboundNatCustomizer.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * 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 io.fd.honeycomb.translate.read.ReadContext; -import io.fd.honeycomb.translate.read.ReadFailedException; -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.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -final class InterfaceInboundNatCustomizer extends AbstractInterfaceNatCustomizer { - - private static final Logger LOG = LoggerFactory.getLogger(InterfaceInboundNatCustomizer.class); - - InterfaceInboundNatCustomizer( - @Nonnull final DumpCacheManager dumpMgr, - @Nonnull final NamingContext ifcContext) { - super(dumpMgr, ifcContext); - } - - @Override - protected Logger getLog() { - return LOG; - } - - @Override - public void readCurrentAttributes(@Nonnull final InstanceIdentifier id, - @Nonnull final InboundBuilder builder, @Nonnull final ReadContext ctx) - throws ReadFailedException { - super.readCurrentAttributes(id, builder, ctx); - } - - @Override - boolean isExpectedNatType(final SnatInterfaceDetails snatInterfaceDetails) { - return snatInterfaceDetails.isInside == 1; - } - - @Nonnull - @Override - public InboundBuilder getBuilder(@Nonnull final InstanceIdentifier id) { - // Return not present value by default - return new InboundBuilder(); - } - - @Override - public void merge(@Nonnull final Builder parentBuilder, @Nonnull final Inbound readValue) { - ((NatBuilder) parentBuilder).setInbound(readValue); - } - - @Nonnull - @Override - public Initialized init(@Nonnull final InstanceIdentifier id, - @Nonnull final Inbound readValue, - @Nonnull final ReadContext ctx) { - final InstanceIdentifier 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); - } -} 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 deleted file mode 100644 index da940c835..000000000 --- a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/read/ifc/InterfaceOutboundNatCustomizer.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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 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.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.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -final class InterfaceOutboundNatCustomizer extends AbstractInterfaceNatCustomizer { - - private static final Logger LOG = LoggerFactory.getLogger(InterfaceOutboundNatCustomizer.class); - - InterfaceOutboundNatCustomizer( - @Nonnull final DumpCacheManager dumpMgr, - @Nonnull final NamingContext ifcContext) { - super(dumpMgr, ifcContext); - } - - @Override - protected Logger getLog() { - return LOG; - } - - @Override - boolean isExpectedNatType(final SnatInterfaceDetails snatInterfaceDetails) { - return snatInterfaceDetails.isInside == 0; - } - - @Nonnull - @Override - public OutboundBuilder getBuilder(@Nonnull final InstanceIdentifier id) { - return new OutboundBuilder(); - } - - @Override - public void merge(@Nonnull final Builder parentBuilder, @Nonnull final Outbound readValue) { - ((NatBuilder) parentBuilder).setOutbound(readValue); - } - - @Nonnull - @Override - public Initialized init(@Nonnull final InstanceIdentifier id, - @Nonnull final Outbound readValue, - @Nonnull final ReadContext ctx) { - final InstanceIdentifier 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); - } -} diff --git a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/util/MappingEntryContext.java b/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/util/MappingEntryContext.java deleted file mode 100644 index 0f2df7e1d..000000000 --- a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/util/MappingEntryContext.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * 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.util; - -import static com.google.common.base.Preconditions.checkArgument; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Optional; -import io.fd.honeycomb.translate.MappingContext; -import io.fd.honeycomb.translate.vpp.util.Ipv4Translator; -import io.fd.vpp.jvpp.snat.dto.SnatStaticMappingDetails; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import javax.annotation.Nonnull; -import javax.annotation.concurrent.ThreadSafe; -import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.Contexts; -import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.nat.context.rev161214.NatMappingEntryCtxAugmentation; -import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.nat.context.rev161214.mapping.entry.context.attributes.NatMappingEntryContext; -import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.nat.context.rev161214.mapping.entry.context.attributes.nat.mapping.entry.context.NatInstance; -import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.nat.context.rev161214.mapping.entry.context.attributes.nat.mapping.entry.context.NatInstanceKey; -import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.nat.context.rev161214.mapping.entry.context.attributes.nat.mapping.entry.context.nat.instance.MappingTable; -import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.nat.context.rev161214.mapping.entry.context.attributes.nat.mapping.entry.context.nat.instance.mapping.table.MappingEntry; -import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.nat.context.rev161214.mapping.entry.context.attributes.nat.mapping.entry.context.nat.instance.mapping.table.MappingEntryBuilder; -import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.nat.context.rev161214.mapping.entry.context.attributes.nat.mapping.entry.context.nat.instance.mapping.table.MappingEntryKey; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Context tracker for Nat Mapping entries. - */ -@ThreadSafe -public class MappingEntryContext implements Ipv4Translator { - - private static final Logger LOG = LoggerFactory.getLogger(MappingEntryContext.class); - - /** - * Add mapping entry to index mapping to context. - */ - public synchronized void addEntry(final long natInstanceId, - final long entryId, - @Nonnull final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry entry, - @Nonnull final MappingContext mappingContext) { - final InstanceIdentifier id = getId(natInstanceId, entryToKey(entry)); - checkArgument(!containsEntry(natInstanceId, entry, mappingContext), "Mapping for %s already present", id); - mappingContext.put(id, toCtxMapEntry(entry, entryId)); - } - - /** - * Check whether mapping entry to index mapping already exists in context. - */ - public synchronized boolean containsEntry(final long natInstanceId, - @Nonnull final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry entry, - @Nonnull final MappingContext mappingContext) { - final InstanceIdentifier id = getId(natInstanceId, entryToKey(entry)); - return mappingContext.read(id).isPresent(); - } - - @VisibleForTesting - static InstanceIdentifier getId(final Long natInstanceId, final MappingEntryKey key) { - return getTableId(natInstanceId).child(MappingEntry.class, key); - } - - @VisibleForTesting - static InstanceIdentifier getTableId(final long natInstanceId) { - return InstanceIdentifier.create(Contexts.class) - .augmentation(NatMappingEntryCtxAugmentation.class) - .child(NatMappingEntryContext.class) - .child(NatInstance.class, new NatInstanceKey(natInstanceId)) - .child(MappingTable.class); - } - - @VisibleForTesting - static MappingEntryKey entryToKey( - final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry entry) { - // Only IPv4 - return new MappingEntryKey(new IpAddress(entry.getExternalSrcAddress()), entry.getInternalSrcAddress()); - } - - private MappingEntryKey entryToKey(final SnatStaticMappingDetails entry) { - // Only IPv4 - return new MappingEntryKey( - new IpAddress(new Ipv4Address(arrayToIpv4AddressNoZoneReversed(entry.externalIpAddress))), - new IpAddress(new Ipv4Address(arrayToIpv4AddressNoZoneReversed(entry.localIpAddress)))); - } - - private boolean equalEntries(final SnatStaticMappingDetails detail, final MappingEntry ctxMappingEntry) { - final IpAddress internalAddrFromDetails = - new IpAddress(new Ipv4Address(arrayToIpv4AddressNoZoneReversed(detail.localIpAddress))); - // Only IPv4 - if (!ctxMappingEntry.getInternal().equals(internalAddrFromDetails)) { - return false; - } - // Only IPv4 - final IpAddress externalAddrFromDetails = - new IpAddress(new Ipv4Address(arrayToIpv4AddressNoZoneReversed(detail.externalIpAddress))); - if (!ctxMappingEntry.getExternal().equals(externalAddrFromDetails)) { - return false; - } - return true; - } - - @VisibleForTesting - static MappingEntry toCtxMapEntry( - @Nonnull final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry entry, - final long entryId) { - return new MappingEntryBuilder() - .setKey(entryToKey(entry)) - .setIndex(entryId) - .build(); - } - - private MappingEntry toCtxMapEntry(@Nonnull final SnatStaticMappingDetails details, final long entryId) { - return new MappingEntryBuilder() - .setKey(entryToKey(details)) - .setIndex(entryId) - .build(); - } - - /** - * Delete mapping of mapping entry to index from context. - */ - public synchronized void removeEntry(final long natInstanceId, - @Nonnull final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry entry, - @Nonnull final MappingContext mappingContext) { - mappingContext.delete(getId(natInstanceId, entryToKey(entry))); - } - - /** - * Find specific details in provided collection identified with provided index. - */ - public synchronized SnatStaticMappingDetails findDetails(@Nonnull final List details, - final long natInstanceId, final long idx, - @Nonnull final MappingContext mappingContext) { - // Find mapping entry for Index - final MappingEntry ctxMappingEntry = mappingContext.read(getTableId(natInstanceId)) - .transform(MappingTable::getMappingEntry) - .or(Collections.emptyList()) - .stream() - .filter(entry -> entry.getIndex() == idx) - .findFirst() - .orElseThrow(() -> new IllegalStateException("Unable to find context mapping for nat-instance: " - + natInstanceId + " and ID: " + idx)); - - // Find which details matches the context stored entry under index - return details.stream() - .filter(detail -> equalEntries(detail, ctxMappingEntry)) - .findFirst() - .orElseThrow(() -> new IllegalStateException("Unable to match mapping for nat-instance: " - + natInstanceId + " and match: " + ctxMappingEntry + " in: " + details)); - } - - /** - * Get index for a mapping entry details or create an artificial one. - */ - public synchronized long getStoredOrArtificialIndex(final Long natInstanceId, - @Nonnull final SnatStaticMappingDetails details, - @Nonnull final MappingContext mappingContext) { - return mappingContext.read(getId(natInstanceId, entryToKey(details))) - .transform(MappingEntry::getIndex) - .or(() -> getArtificialId(details, natInstanceId, mappingContext)); - } - - /** - * Get index for a stored mapping entry. - */ - public synchronized Optional getStoredIndex(final long natInstanceId, - @Nonnull final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry entry, - @Nonnull final MappingContext mappingContext) { - return mappingContext.read(getId(natInstanceId, entryToKey(entry))) - .transform(MappingEntry::getIndex); - } - - private long getArtificialId(final SnatStaticMappingDetails details, final Long natInstanceId, - final MappingContext mappingContext) { - LOG.trace("Assigning artificial ID for {}", details); - final long artificialIdx = findFreeIndex(natInstanceId, mappingContext); - LOG.debug("Artificial ID for {} assigned as: {}", details, artificialIdx); - mappingContext.put(getId(natInstanceId, entryToKey(details)), toCtxMapEntry(details, artificialIdx)); - return artificialIdx; - } - - private long findFreeIndex(final long natInstanceId, final MappingContext mappingContext) { - return mappingContext.read(getTableId(natInstanceId)) - .transform(MappingTable::getMappingEntry) - .or(Collections.emptyList()) - .stream() - .map(MappingEntry::getIndex) - .max(Comparator.naturalOrder()) - .map(i -> i + 1) - .orElse(0L); - } -} diff --git a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/write/ExternalIpPoolCustomizer.java b/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/write/ExternalIpPoolCustomizer.java deleted file mode 100644 index 856bc1355..000000000 --- a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/write/ExternalIpPoolCustomizer.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * 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.write; - -import static com.google.common.base.Preconditions.checkArgument; - -import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer; -import io.fd.honeycomb.translate.vpp.util.Ipv4AddressRange; -import io.fd.honeycomb.translate.vpp.util.Ipv4Translator; -import io.fd.honeycomb.translate.vpp.util.JvppReplyConsumer; -import io.fd.honeycomb.translate.write.WriteContext; -import io.fd.honeycomb.translate.write.WriteFailedException; -import io.fd.vpp.jvpp.snat.dto.SnatAddAddressRange; -import io.fd.vpp.jvpp.snat.future.FutureJVppSnatFacade; -import javax.annotation.Nonnull; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.NatInstance; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.parameters.ExternalIpAddressPool; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.parameters.ExternalIpAddressPoolKey; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -final class ExternalIpPoolCustomizer implements ListWriterCustomizer, - JvppReplyConsumer, Ipv4Translator { - - private static final Logger LOG = LoggerFactory.getLogger(ExternalIpPoolCustomizer.class); - - private final FutureJVppSnatFacade jvppSnat; - - ExternalIpPoolCustomizer(@Nonnull final FutureJVppSnatFacade jvppSnat) { - this.jvppSnat = jvppSnat; - } - - @Override - public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, - @Nonnull final ExternalIpAddressPool dataAfter, - @Nonnull final WriteContext writeContext) throws WriteFailedException { - checkArgument(id.firstKeyOf(NatInstance.class).getId() == 0, - "External IP pools are only assignable for nat instance(vrf-id) with ID 0"); - LOG.trace("Adding address range:{}, as: {}", id, dataAfter); - // TODO check overlaps ? VPP-478 maybe no necessary, depending on how VPP handles them - getReplyForCreate(jvppSnat.snatAddAddressRange( - getRequest(dataAfter.getExternalIpPool(), true)).toCompletableFuture(), id, dataAfter); - LOG.debug("Address range: {} added successfully", id); - } - - @Override - public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, - @Nonnull final ExternalIpAddressPool dataBefore, - @Nonnull final ExternalIpAddressPool dataAfter, - @Nonnull final WriteContext writeContext) throws WriteFailedException { - throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, - new UnsupportedOperationException("Address range update is not supported")); - } - - @Override - public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, - @Nonnull final ExternalIpAddressPool dataBefore, - @Nonnull final WriteContext writeContext) throws WriteFailedException { - LOG.trace("Deleting address range:{}, as: {}", id, dataBefore); - getReplyForDelete(jvppSnat.snatAddAddressRange( - getRequest(dataBefore.getExternalIpPool(), false)).toCompletableFuture(), id); - LOG.debug("Deleting range: {} added successfully", id); - } - - private SnatAddAddressRange getRequest(final Ipv4Prefix externalIpPool, boolean isAdd) { - SnatAddAddressRange request = new SnatAddAddressRange(); - // SNAT supports only IPv4 now, so does the model - final Ipv4AddressRange range = Ipv4AddressRange.fromPrefix(externalIpPool); - LOG.trace("Handling address range: {}", range); - request.isIp4 = 1; - request.isAdd = (byte) (isAdd ? 1 : 0); - request.firstIpAddress = ipv4AddressNoZoneToArray(range.getStart()); - request.lastIpAddress = ipv4AddressNoZoneToArray(range.getEnd()); - return request; - } -} diff --git a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/write/MappingEntryCustomizer.java b/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/write/MappingEntryCustomizer.java deleted file mode 100644 index 785606942..000000000 --- a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/write/MappingEntryCustomizer.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * 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.write; - -import static com.google.common.base.Preconditions.checkArgument; - -import com.google.common.base.Optional; -import io.fd.honeycomb.nat.util.MappingEntryContext; -import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer; -import io.fd.honeycomb.translate.vpp.util.Ipv4Translator; -import io.fd.honeycomb.translate.vpp.util.JvppReplyConsumer; -import io.fd.honeycomb.translate.write.WriteContext; -import io.fd.honeycomb.translate.write.WriteFailedException; -import io.fd.vpp.jvpp.snat.dto.SnatAddStaticMapping; -import io.fd.vpp.jvpp.snat.future.FutureJVppSnatFacade; -import javax.annotation.Nonnull; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.PortNumber; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.NatInstance; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntryKey; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.port.number.PortType; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.port.number.port.type.SinglePortNumber; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -final class MappingEntryCustomizer implements ListWriterCustomizer, - JvppReplyConsumer, Ipv4Translator { - - private static final Logger LOG = LoggerFactory.getLogger(MappingEntryCustomizer.class); - - private final FutureJVppSnatFacade jvppSnat; - private final MappingEntryContext mappingEntryContext; - - MappingEntryCustomizer(final FutureJVppSnatFacade jvppSnat, final MappingEntryContext mappingEntryContext) { - this.jvppSnat = jvppSnat; - this.mappingEntryContext = mappingEntryContext; - } - - @Override - public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, - @Nonnull final MappingEntry dataAfter, - @Nonnull final WriteContext writeContext) - throws WriteFailedException { - // Only static mapping supported by SNAT for now - checkArgument(dataAfter.getType() == - org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.MappingEntry.Type.Static, - "Only static NAT entries are supported currently. Trying to write: %s entry", dataAfter.getType()); - final Long natInstanceId = id.firstKeyOf(NatInstance.class).getId(); - final Long mappingEntryId = id.firstKeyOf(MappingEntry.class).getIndex(); - LOG.debug("Writing mapping entry: {} for nat-instance(vrf): {}", natInstanceId, mappingEntryId); - - final SnatAddStaticMapping request = getRequest(id, dataAfter, natInstanceId, true); - getReplyForWrite(jvppSnat.snatAddStaticMapping(request).toCompletableFuture(), id); - - // Store context mapping only if not already present under the same exact mapping - synchronized (mappingEntryContext) { - if (shouldStoreContextMapping(natInstanceId, mappingEntryId, dataAfter, writeContext)) { - mappingEntryContext - .addEntry(natInstanceId, mappingEntryId, dataAfter, writeContext.getMappingContext()); - } - } - LOG.trace("Mapping entry: {} for nat-instance(vrf): {} written successfully", request.vrfId, id); - } - - /** - * Check whether entry is already stored in context under the same index. - * - * @return true if it's not yet stored under same index, false otherwise. - */ - private boolean shouldStoreContextMapping(final long natInstanceId, final long mappingEntryId, - final MappingEntry dataAfter, - final WriteContext writeCtx) { - if (!mappingEntryContext.containsEntry(natInstanceId, dataAfter, writeCtx.getMappingContext())) { - return true; - } - - final Optional storedIndex = - mappingEntryContext.getStoredIndex(natInstanceId, dataAfter, writeCtx.getMappingContext()); - if (!storedIndex.isPresent()) { - return true; - } - - if (storedIndex.get() != mappingEntryId) { - return true; - } - - return false; - } - - @Override - public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, - @Nonnull final MappingEntry dataBefore, - @Nonnull final MappingEntry dataAfter, - @Nonnull final WriteContext writeContext) throws WriteFailedException { - throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, - new UnsupportedOperationException("Mapping entry update not supported")); - } - - @Override - public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, - @Nonnull final MappingEntry dataBefore, - @Nonnull final WriteContext writeContext) throws WriteFailedException { - final long natInstanceId = id.firstKeyOf(NatInstance.class).getId(); - final MappingEntryKey mappingEntryKey = id.firstKeyOf(MappingEntry.class); - LOG.debug("Deleting mapping entry: {} for nat-instance(vrf): {}", natInstanceId, mappingEntryKey); - - final SnatAddStaticMapping request = getRequest(id, dataBefore, natInstanceId, false); - getReplyForWrite(jvppSnat.snatAddStaticMapping(request).toCompletableFuture(), id); - mappingEntryContext.removeEntry(natInstanceId, dataBefore, writeContext.getMappingContext()); - LOG.trace("Mapping entry: {} for nat-instance(vrf): {} deleted successfully", request.vrfId, id); - } - - private SnatAddStaticMapping getRequest(final InstanceIdentifier id, - final MappingEntry dataAfter, - final Long natInstanceId, - final boolean isAdd) - throws WriteFailedException.CreateFailedException { - final SnatAddStaticMapping request = new SnatAddStaticMapping(); - request.isAdd = isAdd - ? (byte) 1 - : 0; - request.isIp4 = 1; - // VPP uses int, model long - request.vrfId = natInstanceId.intValue(); - - // Snat supports only ipv4 now - if (dataAfter.getInternalSrcAddress().getIpv4Address() == null) { - throw new WriteFailedException.CreateFailedException(id, dataAfter, - new UnsupportedOperationException( - String.format("No Ipv4 present for in address %s. Ipv6 not supported", - dataAfter.getInternalSrcAddress()))); - } - - request.addrOnly = 1; - request.localIpAddress = - ipv4AddressNoZoneToArray(dataAfter.getInternalSrcAddress().getIpv4Address().getValue()); - request.externalIpAddress = ipv4AddressNoZoneToArray(dataAfter.getExternalSrcAddress().getValue()); - - Optional internalPortNumber = getPortNumber(id, dataAfter, - (entry) -> Optional.fromNullable(entry.getInternalSrcPort()).transform(PortNumber::getPortType)); - Optional externalPortNumber = getPortNumber(id, dataAfter, - (entry) -> Optional.fromNullable(entry.getExternalSrcPort()).transform(PortNumber::getPortType)); - if (internalPortNumber.isPresent() && externalPortNumber.isPresent()) { - request.addrOnly = 0; - request.localPort = internalPortNumber.get(); - request.externalPort = externalPortNumber.get(); - } - return request; - } - - private Optional getPortNumber(final InstanceIdentifier id, final MappingEntry dataAfter, - final PortGetter portGetter) { - return portGetter.getPortType(dataAfter).transform(port -> { - if (port instanceof SinglePortNumber) { - return ((SinglePortNumber) port).getSinglePortNumber().getValue().shortValue(); - } else { - throw new IllegalArgumentException( - String.format("Only single port number supported. Submitted: %s for entry: %s", - dataAfter.getInternalSrcPort(), id)); - } - }); - } - - interface PortGetter { - Optional getPortType(MappingEntry entry); - } -} diff --git a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/write/NatInstaceCustomizer.java b/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/write/NatInstaceCustomizer.java deleted file mode 100644 index 3cc477dd0..000000000 --- a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/write/NatInstaceCustomizer.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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.write; - -import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer; -import io.fd.honeycomb.translate.write.WriteContext; -import io.fd.honeycomb.translate.write.WriteFailedException; -import javax.annotation.Nonnull; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.NatInstance; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.NatInstanceKey; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -final class NatInstaceCustomizer implements ListWriterCustomizer { - - private static final Logger LOG = LoggerFactory.getLogger(NatInstaceCustomizer.class); - - @Override - public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, - @Nonnull final NatInstance dataAfter, @Nonnull final WriteContext writeContext) - throws WriteFailedException { - LOG.trace("Writing nat-instance: {}", id); - } - - @Override - public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, - @Nonnull final NatInstance dataBefore, @Nonnull final NatInstance dataAfter, - @Nonnull final WriteContext writeContext) throws WriteFailedException { - LOG.trace("Updating nat-instance: {}", id); - } - - @Override - public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, - @Nonnull final NatInstance dataBefore, @Nonnull final WriteContext writeContext) - throws WriteFailedException { - LOG.trace("Deleting nat-instance: {}", id); - } -} diff --git a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/write/NatWriterFactory.java b/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/write/NatWriterFactory.java deleted file mode 100644 index 7887d463a..000000000 --- a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/write/NatWriterFactory.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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.write; - -import com.google.common.collect.Sets; -import com.google.inject.Inject; -import io.fd.honeycomb.nat.util.MappingEntryContext; -import io.fd.honeycomb.translate.impl.write.GenericListWriter; -import io.fd.honeycomb.translate.write.WriterFactory; -import io.fd.honeycomb.translate.write.registry.ModifiableWriterRegistryBuilder; -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.nat.rev150908.NatConfig; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.mapping.entry.ExternalSrcPort; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.mapping.entry.InternalSrcPort; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.NatInstances; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.NatInstance; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.MappingTable; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.parameters.ExternalIpAddressPool; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; - -/** - * Nat Writers registration. - */ -public final class NatWriterFactory implements WriterFactory { - - private static final InstanceIdentifier NAT_CFG_ID = InstanceIdentifier.create(NatConfig.class); - private static final InstanceIdentifier NAT_INSTANCE_ID = - NAT_CFG_ID.child(NatInstances.class).child(NatInstance.class); - private static final InstanceIdentifier MAP_ENTRY_ID = - NAT_INSTANCE_ID.child(MappingTable.class).child(MappingEntry.class); - - private final FutureJVppSnatFacade jvppSnat; - private final MappingEntryContext mappingEntryContext; - - @Inject - public NatWriterFactory(final FutureJVppSnatFacade jvppSnat, - final MappingEntryContext mappingEntryContext) { - this.jvppSnat = jvppSnat; - this.mappingEntryContext = mappingEntryContext; - } - - @Override - public void init(@Nonnull final ModifiableWriterRegistryBuilder registry) { - // Nat-instance - registry.add(new GenericListWriter<>(NAT_INSTANCE_ID, new NatInstaceCustomizer())); - // Mapping-entry - registry.subtreeAdd(Sets.newHashSet(InstanceIdentifier.create(MappingEntry.class).child(ExternalSrcPort.class), - InstanceIdentifier.create(MappingEntry.class).child(InternalSrcPort.class)), - new GenericListWriter<>(MAP_ENTRY_ID, new MappingEntryCustomizer(jvppSnat, mappingEntryContext))); - - // External address pool has to be executed before mapping entry. Because adding mapping entries requires to - // already have an IP range predefined ... in some cases - registry.addBefore(new GenericListWriter<>(NAT_INSTANCE_ID.child(ExternalIpAddressPool.class), - new ExternalIpPoolCustomizer(jvppSnat)), - MAP_ENTRY_ID); - } -} diff --git a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/write/ifc/AbstractInterfaceNatCustomizer.java b/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/write/ifc/AbstractInterfaceNatCustomizer.java deleted file mode 100644 index 64e714241..000000000 --- a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/write/ifc/AbstractInterfaceNatCustomizer.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * 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.write.ifc; - -import io.fd.honeycomb.translate.spi.write.WriterCustomizer; -import io.fd.honeycomb.translate.vpp.util.JvppReplyConsumer; -import io.fd.honeycomb.translate.vpp.util.NamingContext; -import io.fd.honeycomb.translate.write.WriteContext; -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.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.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.slf4j.Logger; - -abstract class AbstractInterfaceNatCustomizer implements JvppReplyConsumer, WriterCustomizer { - - private final FutureJVppSnatFacade jvppSnat; - private final NamingContext ifcContext; - - AbstractInterfaceNatCustomizer(@Nonnull final FutureJVppSnatFacade jvppSnat, - @Nonnull final NamingContext ifcContext) { - this.jvppSnat = jvppSnat; - this.ifcContext = ifcContext; - } - - @Override - public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final D dataAfter, - @Nonnull final WriteContext writeContext) throws WriteFailedException { - final String ifcName = id.firstKeyOf(Interface.class).getName(); - getLog().debug("Enabling " + getType() + " NAT on interface: {}", ifcName); - getLog().debug("Enabling " + getType() + " NAT: {}", id); - - final int ifcIndex = ifcContext.getIndex(ifcName, writeContext.getMappingContext()); - final SnatInterfaceAddDelFeature request = getRequest(ifcIndex, (byte)1); - final CompletionStage future = jvppSnat.snatInterfaceAddDelFeature(request); - - final SnatInterfaceAddDelFeatureReply reply = getReplyForWrite(future.toCompletableFuture(), id); - getLog().debug("NAT " + getType() + " enabled successfully on: {}, reply: {}", ifcName, reply); - } - - @Override - public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, - @Nonnull final D dataBefore, @Nonnull final D dataAfter, - @Nonnull final WriteContext writeContext) throws WriteFailedException { - throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, - new UnsupportedOperationException("Unable to update NAT feature")); - } - - @Override - public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, - @Nonnull final D dataBefore, @Nonnull final WriteContext writeContext) - throws WriteFailedException { - final String ifcName = id.firstKeyOf(Interface.class).getName(); - getLog().debug("Disabling " + getType() + " NAT on interface: {}", ifcName); - getLog().debug("Disabling " + getType() + " NAT: {}", id); - - final int ifcIndex = ifcContext.getIndex(ifcName, writeContext.getMappingContext()); - final SnatInterfaceAddDelFeature request = getRequest(ifcIndex, (byte)0); - final CompletionStage future = jvppSnat.snatInterfaceAddDelFeature(request); - - final SnatInterfaceAddDelFeatureReply reply = getReplyForWrite(future.toCompletableFuture(), id); - getLog().debug("NAT " + getType() + " disabled successfully on: {}, reply: {}", ifcName, reply); - } - - enum NatType { - INBOUND((byte)1), OUTBOUND((byte)0); - - private final byte isInside; - - NatType(final byte isInside) { - this.isInside = isInside; - } - } - - 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; - } - -} diff --git a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/write/ifc/IfcNatWriterFactory.java b/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/write/ifc/IfcNatWriterFactory.java deleted file mode 100644 index bf2c600a2..000000000 --- a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/write/ifc/IfcNatWriterFactory.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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.write.ifc; - -import com.google.inject.Inject; -import com.google.inject.name.Named; -import io.fd.honeycomb.translate.impl.write.GenericWriter; -import io.fd.honeycomb.translate.vpp.util.NamingContext; -import io.fd.honeycomb.translate.write.WriterFactory; -import io.fd.honeycomb.translate.write.registry.ModifiableWriterRegistryBuilder; -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; -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.nat.Inbound; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev161214._interface.nat.attributes.nat.Outbound; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; - -/** - * Nat Writers registration. - */ -public final class IfcNatWriterFactory implements WriterFactory { - - private static final InstanceIdentifier - IFC_ID = InstanceIdentifier.create(Interfaces.class).child(Interface.class); - private static final InstanceIdentifier NAT_AUG_ID = - IFC_ID .augmentation(NatInterfaceAugmentation.class).child(Nat.class); - - private final FutureJVppSnatFacade jvppSnat; - private final NamingContext ifcContext; - - @Inject - public IfcNatWriterFactory(final FutureJVppSnatFacade jvppSnat, - @Named("interface-context") final NamingContext ifcContext) { - this.jvppSnat = jvppSnat; - this.ifcContext = ifcContext; - } - - @Override - public void init(@Nonnull final ModifiableWriterRegistryBuilder registry) { - registry.addAfter(new GenericWriter<>(NAT_AUG_ID.child(Inbound.class), - new InterfaceInboundNatCustomizer(jvppSnat, ifcContext)), IFC_ID); - registry.addAfter(new GenericWriter<>(NAT_AUG_ID.child(Outbound.class), - new InterfaceOutboundNatCustomizer(jvppSnat, ifcContext)), IFC_ID); - } -} diff --git a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/write/ifc/InterfaceInboundNatCustomizer.java b/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/write/ifc/InterfaceInboundNatCustomizer.java deleted file mode 100644 index e72e12ada..000000000 --- a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/write/ifc/InterfaceInboundNatCustomizer.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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.write.ifc; - -import io.fd.honeycomb.translate.vpp.util.NamingContext; -import io.fd.vpp.jvpp.snat.future.FutureJVppSnatFacade; -import javax.annotation.Nonnull; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev161214._interface.nat.attributes.nat.Inbound; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -final class InterfaceInboundNatCustomizer extends AbstractInterfaceNatCustomizer { - - private static final Logger LOG = LoggerFactory.getLogger(InterfaceInboundNatCustomizer.class); - - InterfaceInboundNatCustomizer(@Nonnull final FutureJVppSnatFacade jvppSnat, - @Nonnull final NamingContext ifcContext) { - super(jvppSnat, ifcContext); - } - - @Override - NatType getType() { - return NatType.INBOUND; - } - - @Override - Logger getLog() { - return LOG; - } -} diff --git a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/write/ifc/InterfaceOutboundNatCustomizer.java b/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/write/ifc/InterfaceOutboundNatCustomizer.java deleted file mode 100644 index 488edc73c..000000000 --- a/nat/nat2vpp/src/main/java/io/fd/honeycomb/nat/write/ifc/InterfaceOutboundNatCustomizer.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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.write.ifc; - -import io.fd.honeycomb.translate.vpp.util.NamingContext; -import io.fd.vpp.jvpp.snat.future.FutureJVppSnatFacade; -import javax.annotation.Nonnull; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev161214._interface.nat.attributes.nat.Outbound; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -final class InterfaceOutboundNatCustomizer extends AbstractInterfaceNatCustomizer { - - private static final Logger LOG = LoggerFactory.getLogger(InterfaceOutboundNatCustomizer.class); - - InterfaceOutboundNatCustomizer(@Nonnull final FutureJVppSnatFacade jvppSnat, - @Nonnull final NamingContext ifcContext) { - super(jvppSnat, ifcContext); - } - - @Override - NatType getType() { - return NatType.OUTBOUND; - } - - @Override - Logger getLog() { - return LOG; - } -} diff --git a/nat/nat2vpp/src/test/java/io/fd/hc2vpp/nat/NatModuleTest.java b/nat/nat2vpp/src/test/java/io/fd/hc2vpp/nat/NatModuleTest.java new file mode 100644 index 000000000..6052d7e8c --- /dev/null +++ b/nat/nat2vpp/src/test/java/io/fd/hc2vpp/nat/NatModuleTest.java @@ -0,0 +1,123 @@ +/* + * 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.hc2vpp.nat; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.Matchers.empty; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.MockitoAnnotations.initMocks; + +import com.google.inject.Guice; +import com.google.inject.Inject; +import com.google.inject.Provider; +import com.google.inject.multibindings.Multibinder; +import com.google.inject.name.Named; +import com.google.inject.testing.fieldbinder.Bind; +import com.google.inject.testing.fieldbinder.BoundFieldModule; +import io.fd.honeycomb.translate.read.ReaderFactory; +import io.fd.honeycomb.translate.impl.read.registry.CompositeReaderRegistryBuilder; +import io.fd.honeycomb.translate.impl.write.registry.FlatWriterRegistryBuilder; +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.honeycomb.translate.write.WriterFactory; +import io.fd.vpp.jvpp.snat.future.FutureJVppSnatFacade; +import java.util.HashSet; +import java.util.Set; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +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.InterfacesStateBuilder; +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.InterfaceBuilder; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class NatModuleTest { + + @Named("honeycomb-context") + @Bind + @Mock + private DataBroker honeycombContext; + + @Bind + private ReaderFactory ietfIfcReaderFactory; + + @Named("honeycomb-initializer") + @Bind + @Mock + private DataBroker honeycombInitializer; + + @Named("interface-context") + @Bind + private NamingContext ifcContext; + + @Inject + private Set readerFactories = new HashSet<>(); + + @Inject + private Set writerFactories = new HashSet<>(); + + @Before + public void setUp() throws Exception { + ietfIfcReaderFactory = registry -> { + registry.addStructuralReader(InstanceIdentifier.create(InterfacesState.class), InterfacesStateBuilder.class); + registry.addStructuralReader(InstanceIdentifier.create(InterfacesState.class).child(Interface.class), InterfaceBuilder.class); + }; + initMocks(this); + ifcContext = new NamingContext("interface-", "interface-context"); + // Nat Module adds readers under InterfacesState/Interface and since readers for parents that do nothing need to + // be present, add structural readers (or add V3poModule here, but adding the full Module is not the best solution) + Guice.createInjector(binder -> Multibinder.newSetBinder(binder, ReaderFactory.class) + .addBinding().toInstance(registry -> { + registry.addStructuralReader(InstanceIdentifier.create(InterfacesState.class), + InterfacesStateBuilder.class); + registry.addStructuralReader(InstanceIdentifier.create(InterfacesState.class).child(Interface.class), + InterfaceBuilder.class); + }), new NatModule(MockJVppSnatProvider.class), BoundFieldModule.of(this)).injectMembers(this); + } + + @Test + public void testReaderFactories() throws Exception { + assertThat(readerFactories, is(not(empty()))); + + // Test registration process (all dependencies present, topological order of readers does exist, etc.) + final CompositeReaderRegistryBuilder registryBuilder = new CompositeReaderRegistryBuilder(); + readerFactories.forEach(factory -> factory.init(registryBuilder)); + assertNotNull(registryBuilder.build()); + } + + @Test + public void testWriterFactories() throws Exception { + assertThat(writerFactories, is(not(empty()))); + + // Test registration process (all dependencies present, topological order of writers does exist, etc.) + final FlatWriterRegistryBuilder registryBuilder = new FlatWriterRegistryBuilder(); + writerFactories.forEach(factory -> factory.init(registryBuilder)); + assertNotNull(registryBuilder.build()); + } + + private static final class MockJVppSnatProvider implements Provider { + + @Override + public FutureJVppSnatFacade get() { + return mock(FutureJVppSnatFacade.class); + } + } +} \ No newline at end of file diff --git a/nat/nat2vpp/src/test/java/io/fd/hc2vpp/nat/read/ifc/InterfaceInboundNatCustomizerTest.java b/nat/nat2vpp/src/test/java/io/fd/hc2vpp/nat/read/ifc/InterfaceInboundNatCustomizerTest.java new file mode 100644 index 000000000..b5c0dab53 --- /dev/null +++ b/nat/nat2vpp/src/test/java/io/fd/hc2vpp/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.hc2vpp.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.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.common.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 { + + private static final String IFC_NAME = "a"; + private static final int IFC_IDX = 0; + private static final String CTX_NAME = "ifc"; + + @Mock + private EntityDumpExecutor natExecutor; + private DumpCacheManager dumpMgr; + private NamingContext ifcContext = new NamingContext(CTX_NAME, CTX_NAME); + private InstanceIdentifier 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(natExecutor).executeDump(id, null); + dumpMgr = new DumpCacheManager.DumpCacheManagerBuilder() + .withExecutor(natExecutor) + .build(); + } + + static > InstanceIdentifier getId(Class 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 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(natExecutor).executeDump(id, null); + + assertTrue(getReader().read(id, ctx).isPresent()); + } + + @Override + protected ReaderCustomizer initCustomizer() { + return new InterfaceInboundNatCustomizer(dumpMgr, ifcContext); + } +} \ No newline at end of file diff --git a/nat/nat2vpp/src/test/java/io/fd/hc2vpp/nat/read/ifc/InterfaceOutboundNatCustomizerTest.java b/nat/nat2vpp/src/test/java/io/fd/hc2vpp/nat/read/ifc/InterfaceOutboundNatCustomizerTest.java new file mode 100644 index 000000000..34f5b0949 --- /dev/null +++ b/nat/nat2vpp/src/test/java/io/fd/hc2vpp/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.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 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.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.common.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 { + + private static final String IFC_NAME = "a"; + private static final int IFC_IDX = 0; + private static final String CTX_NAME = "ifc"; + + @Mock + private EntityDumpExecutor abc; + private DumpCacheManager dumpMgr; + private NamingContext ifcContext = new NamingContext(CTX_NAME, CTX_NAME); + private InstanceIdentifier 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() + .withExecutor(abc) + .build(); + } + + @Test + public void testNoPresence() throws Exception { + assertFalse(getReader().read(id, ctx).isPresent()); + } + + private GenericReader 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 initCustomizer() { + return new InterfaceOutboundNatCustomizer(dumpMgr, ifcContext); + } +} \ No newline at end of file diff --git a/nat/nat2vpp/src/test/java/io/fd/hc2vpp/nat/util/MappingEntryContextTest.java b/nat/nat2vpp/src/test/java/io/fd/hc2vpp/nat/util/MappingEntryContextTest.java new file mode 100644 index 000000000..4d8f8074d --- /dev/null +++ b/nat/nat2vpp/src/test/java/io/fd/hc2vpp/nat/util/MappingEntryContextTest.java @@ -0,0 +1,198 @@ +/* + * 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.hc2vpp.nat.util; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.mockito.MockitoAnnotations.initMocks; + +import com.google.common.base.Optional; +import com.google.common.collect.Lists; +import io.fd.honeycomb.translate.MappingContext; +import io.fd.hc2vpp.common.translate.util.Ipv4Translator; +import io.fd.vpp.jvpp.snat.dto.SnatStaticMappingDetails; +import java.util.Collections; +import java.util.List; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.nat.context.rev161214.mapping.entry.context.attributes.nat.mapping.entry.context.nat.instance.MappingTableBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntryBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntryKey; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +@SuppressWarnings("unchecked") +public class MappingEntryContextTest implements Ipv4Translator { + + private MappingEntryContext ctx = new MappingEntryContext(); + @Mock + private MappingContext mappingCtx; + + @Before + public void setUp() throws Exception { + initMocks(this); + } + + @Test + public void testAdd() throws Exception { + when(mappingCtx.read(any(InstanceIdentifier.class))).thenReturn(Optional.absent()); + final long natId = 7; + final long entryId = 99; + final MappingEntry entry = getEntry(natId, "192.168.1.5", "17.14.4.6"); + + ctx.addEntry(natId, entryId, entry, mappingCtx); + + verify(mappingCtx).put(MappingEntryContext.getId(natId, MappingEntryContext.entryToKey(entry)), MappingEntryContext.toCtxMapEntry(entry, entryId)); + } + + @Test + public void testRemove() throws Exception { + final long natId = 0; + final MappingEntry entry = getEntry(natId, "192.168.1.5", "17.14.4.6"); + + ctx.removeEntry(natId, entry, mappingCtx); + + verify(mappingCtx).delete(MappingEntryContext.getId(natId, MappingEntryContext.entryToKey(entry))); + } + + @Test + public void testGetExistingIndex() throws Exception { + final long natId = 0; + final long entryId = 12; + final MappingEntry entry = getEntry(entryId, "192.168.1.5", "17.14.4.6"); + final SnatStaticMappingDetails details = getDetails(entryId, "192.168.1.5", "17.14.4.6"); + + when(mappingCtx.read(MappingEntryContext.getId(natId, MappingEntryContext.entryToKey(entry)))) + .thenReturn(Optional.of(MappingEntryContext.toCtxMapEntry(entry, entryId))); + + assertEquals(12, ctx.getStoredOrArtificialIndex(natId, details, mappingCtx)); + verify(mappingCtx).read(MappingEntryContext.getId(natId, MappingEntryContext.entryToKey(entry))); + } + + @Test + public void testFindDetails() throws Exception { + final long natId = 0; + final MappingEntry entry = getEntry(0, "192.168.1.5", "17.14.4.6"); + final SnatStaticMappingDetails details = getDetails(0, "192.168.1.5", "17.14.4.6"); + final MappingEntry entry2 = getEntry(1, "192.168.1.8", "17.14.4.10"); + final SnatStaticMappingDetails details2 = getDetails(1, "192.168.1.8", "17.14.4.10"); + + final List someDetails = Lists.newArrayList(details, details2); + + when(mappingCtx.read(MappingEntryContext.getTableId(natId))) + .thenReturn(Optional.of(new MappingTableBuilder() + .setMappingEntry(Lists.newArrayList( + MappingEntryContext.toCtxMapEntry(entry, 0), + MappingEntryContext.toCtxMapEntry(entry2, 1))) + .build())); + + assertSame(details, ctx.findDetails(someDetails, natId, 0, mappingCtx)); + } + + @Test(expected = IllegalStateException.class) + public void testFindDetailsNoMappingStored() throws Exception { + final long natId = 0; + final long entryId = 12; + final SnatStaticMappingDetails details = getDetails(entryId, "192.168.1.5", "17.14.4.6"); + final List someDetails = Lists.newArrayList(details); + when(mappingCtx.read(MappingEntryContext.getTableId(natId))).thenReturn(Optional.absent()); + + ctx.findDetails(someDetails, natId, entryId, mappingCtx); + } + + @Test(expected = IllegalStateException.class) + public void testFindDetailsNoMappingStored2() throws Exception { + final long natId = 0; + final long entryId = 12; + final SnatStaticMappingDetails details = getDetails(entryId, "192.168.1.5", "17.14.4.6"); + final List someDetails = Lists.newArrayList(details); + + when(mappingCtx.read(MappingEntryContext.getTableId(natId))) + .thenReturn(Optional.of(new MappingTableBuilder().setMappingEntry(Collections.emptyList()).build())); + + ctx.findDetails(someDetails, natId, entryId, mappingCtx); + } + + @Test + public void testGetArtificialIndex() throws Exception { + final long natId = 0; + final long entryId = 0; + final MappingEntry entry = getEntry(entryId, "192.168.1.5", "17.14.4.6"); + final long entryId2 = 55; + final MappingEntry entry2 = getEntry(entryId2, "192.168.1.6", "17.14.4.7"); + final long entryId3 = 18954; + final MappingEntry entry3 = getEntry(entryId3, "192.168.1.7", "17.14.4.8"); + final long entryId4 = 18955; + final MappingEntry entry4 = getEntry(entryId4, "192.168.1.8", "17.14.4.9"); + + final long newEntryId = 18956; + final MappingEntry newEntry = getEntry(newEntryId, "192.168.1.99", "17.14.4.99"); + final SnatStaticMappingDetails newDetails = getDetails(newEntryId, "192.168.1.99", "17.14.4.99"); + when(mappingCtx.read(MappingEntryContext.getId(natId, MappingEntryContext.entryToKey(newEntry)))) + .thenReturn(Optional.absent()); + + when(mappingCtx.read(MappingEntryContext.getTableId(natId))) + .thenReturn(Optional.of(new MappingTableBuilder() + .setMappingEntry(Lists.newArrayList( + MappingEntryContext.toCtxMapEntry(entry, entryId), + MappingEntryContext.toCtxMapEntry(entry3, entryId3), + MappingEntryContext.toCtxMapEntry(entry4, entryId4), + MappingEntryContext.toCtxMapEntry(entry2, entryId2))) + .build())); + + assertFalse(ctx.getStoredIndex(natId, newEntry, mappingCtx).isPresent()); + assertEquals(newEntryId, ctx.getStoredOrArtificialIndex(natId, newDetails, mappingCtx)); + } + + private SnatStaticMappingDetails getDetails(final long vrfId, final String localIp, final String externIp) { + final SnatStaticMappingDetails snatStaticMappingDetails = new SnatStaticMappingDetails(); + snatStaticMappingDetails.vrfId = (int) vrfId; + snatStaticMappingDetails.addrOnly = 1; + snatStaticMappingDetails.isIp4 = 1; + snatStaticMappingDetails.localIpAddress = ipv4AddressNoZoneToArray(localIp); + snatStaticMappingDetails.externalIpAddress = ipv4AddressNoZoneToArray(externIp); + return snatStaticMappingDetails; + } + + @Test(expected = IllegalArgumentException.class) + public void testAddExisting() throws Exception { + final long natId = 7; + final long entryId = 99; + final MappingEntry entry = getEntry(natId, "192.168.1.5", "17.14.4.6"); + final org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.nat.context.rev161214.mapping.entry.context.attributes.nat.mapping.entry.context.nat.instance.mapping.table.MappingEntry + data = MappingEntryContext.toCtxMapEntry(entry, entryId); + when(mappingCtx.read(any(InstanceIdentifier.class))).thenReturn(Optional.of(data)); + + ctx.addEntry(natId, entryId, entry, mappingCtx); + } + + private static MappingEntry getEntry(final long id, final String longernalIpv4, final String externalIpv4) { + return new MappingEntryBuilder() + .setKey(new MappingEntryKey(id)) + .setType(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.MappingEntry.Type.Static) + .setInternalSrcAddress(new IpAddress(new Ipv4Address(longernalIpv4))) + .setExternalSrcAddress(new Ipv4Address(externalIpv4)) + .build(); + } +} \ No newline at end of file diff --git a/nat/nat2vpp/src/test/java/io/fd/honeycomb/nat/NatModuleTest.java b/nat/nat2vpp/src/test/java/io/fd/honeycomb/nat/NatModuleTest.java deleted file mode 100644 index f69672e15..000000000 --- a/nat/nat2vpp/src/test/java/io/fd/honeycomb/nat/NatModuleTest.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * 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; - -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.not; -import static org.hamcrest.Matchers.empty; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.MockitoAnnotations.initMocks; - -import com.google.inject.Guice; -import com.google.inject.Inject; -import com.google.inject.Provider; -import com.google.inject.multibindings.Multibinder; -import com.google.inject.name.Named; -import com.google.inject.testing.fieldbinder.Bind; -import com.google.inject.testing.fieldbinder.BoundFieldModule; -import io.fd.honeycomb.translate.read.ReaderFactory; -import io.fd.honeycomb.translate.impl.read.registry.CompositeReaderRegistryBuilder; -import io.fd.honeycomb.translate.impl.write.registry.FlatWriterRegistryBuilder; -import io.fd.honeycomb.translate.vpp.util.NamingContext; -import io.fd.honeycomb.translate.write.WriterFactory; -import io.fd.vpp.jvpp.snat.future.FutureJVppSnatFacade; -import java.util.HashSet; -import java.util.Set; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.opendaylight.controller.md.sal.binding.api.DataBroker; -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.InterfacesStateBuilder; -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.InterfaceBuilder; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; - -public class NatModuleTest { - - @Named("honeycomb-context") - @Bind - @Mock - private DataBroker honeycombContext; - - @Bind - private ReaderFactory ietfIfcReaderFactory; - - @Named("honeycomb-initializer") - @Bind - @Mock - private DataBroker honeycombInitializer; - - @Named("interface-context") - @Bind - private NamingContext ifcContext; - - @Inject - private Set readerFactories = new HashSet<>(); - - @Inject - private Set writerFactories = new HashSet<>(); - - @Before - public void setUp() throws Exception { - ietfIfcReaderFactory = registry -> { - registry.addStructuralReader(InstanceIdentifier.create(InterfacesState.class), InterfacesStateBuilder.class); - registry.addStructuralReader(InstanceIdentifier.create(InterfacesState.class).child(Interface.class), InterfaceBuilder.class); - }; - initMocks(this); - ifcContext = new NamingContext("interface-", "interface-context"); - // Nat Module adds readers under InterfacesState/Interface and since readers for parents that do nothing need to - // be present, add structural readers (or add V3poModule here, but adding the full Module is not the best solution) - Guice.createInjector(binder -> Multibinder.newSetBinder(binder, ReaderFactory.class) - .addBinding().toInstance(registry -> { - registry.addStructuralReader(InstanceIdentifier.create(InterfacesState.class), - InterfacesStateBuilder.class); - registry.addStructuralReader(InstanceIdentifier.create(InterfacesState.class).child(Interface.class), - InterfaceBuilder.class); - }), new NatModule(MockJVppSnatProvider.class), BoundFieldModule.of(this)).injectMembers(this); - } - - @Test - public void testReaderFactories() throws Exception { - assertThat(readerFactories, is(not(empty()))); - - // Test registration process (all dependencies present, topological order of readers does exist, etc.) - final CompositeReaderRegistryBuilder registryBuilder = new CompositeReaderRegistryBuilder(); - readerFactories.forEach(factory -> factory.init(registryBuilder)); - assertNotNull(registryBuilder.build()); - } - - @Test - public void testWriterFactories() throws Exception { - assertThat(writerFactories, is(not(empty()))); - - // Test registration process (all dependencies present, topological order of writers does exist, etc.) - final FlatWriterRegistryBuilder registryBuilder = new FlatWriterRegistryBuilder(); - writerFactories.forEach(factory -> factory.init(registryBuilder)); - assertNotNull(registryBuilder.build()); - } - - private static final class MockJVppSnatProvider implements Provider { - - @Override - public FutureJVppSnatFacade get() { - return mock(FutureJVppSnatFacade.class); - } - } -} \ No newline at end of file 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 deleted file mode 100644 index 3cef1880e..000000000 --- a/nat/nat2vpp/src/test/java/io/fd/honeycomb/nat/read/ifc/InterfaceInboundNatCustomizerTest.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * 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 { - - private static final String IFC_NAME = "a"; - private static final int IFC_IDX = 0; - private static final String CTX_NAME = "ifc"; - - @Mock - private EntityDumpExecutor natExecutor; - private DumpCacheManager dumpMgr; - private NamingContext ifcContext = new NamingContext(CTX_NAME, CTX_NAME); - private InstanceIdentifier 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(natExecutor).executeDump(id, null); - dumpMgr = new DumpCacheManager.DumpCacheManagerBuilder() - .withExecutor(natExecutor) - .build(); - } - - static > InstanceIdentifier getId(Class 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 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(natExecutor).executeDump(id, null); - - assertTrue(getReader().read(id, ctx).isPresent()); - } - - @Override - protected ReaderCustomizer 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 deleted file mode 100644 index c33e040bb..000000000 --- a/nat/nat2vpp/src/test/java/io/fd/honeycomb/nat/read/ifc/InterfaceOutboundNatCustomizerTest.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * 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 { - - private static final String IFC_NAME = "a"; - private static final int IFC_IDX = 0; - private static final String CTX_NAME = "ifc"; - - @Mock - private EntityDumpExecutor abc; - private DumpCacheManager dumpMgr; - private NamingContext ifcContext = new NamingContext(CTX_NAME, CTX_NAME); - private InstanceIdentifier 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() - .withExecutor(abc) - .build(); - } - - @Test - public void testNoPresence() throws Exception { - assertFalse(getReader().read(id, ctx).isPresent()); - } - - private GenericReader 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 initCustomizer() { - return new InterfaceOutboundNatCustomizer(dumpMgr, ifcContext); - } -} \ No newline at end of file diff --git a/nat/nat2vpp/src/test/java/io/fd/honeycomb/nat/util/MappingEntryContextTest.java b/nat/nat2vpp/src/test/java/io/fd/honeycomb/nat/util/MappingEntryContextTest.java deleted file mode 100644 index fee8def89..000000000 --- a/nat/nat2vpp/src/test/java/io/fd/honeycomb/nat/util/MappingEntryContextTest.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * 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.util; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertSame; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.initMocks; - -import com.google.common.base.Optional; -import com.google.common.collect.Lists; -import io.fd.honeycomb.translate.MappingContext; -import io.fd.honeycomb.translate.vpp.util.Ipv4Translator; -import io.fd.vpp.jvpp.snat.dto.SnatStaticMappingDetails; -import java.util.Collections; -import java.util.List; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.nat.context.rev161214.mapping.entry.context.attributes.nat.mapping.entry.context.nat.instance.MappingTableBuilder; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntryBuilder; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntryKey; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; - -@SuppressWarnings("unchecked") -public class MappingEntryContextTest implements Ipv4Translator { - - private MappingEntryContext ctx = new MappingEntryContext(); - @Mock - private MappingContext mappingCtx; - - @Before - public void setUp() throws Exception { - initMocks(this); - } - - @Test - public void testAdd() throws Exception { - when(mappingCtx.read(any(InstanceIdentifier.class))).thenReturn(Optional.absent()); - final long natId = 7; - final long entryId = 99; - final MappingEntry entry = getEntry(natId, "192.168.1.5", "17.14.4.6"); - - ctx.addEntry(natId, entryId, entry, mappingCtx); - - verify(mappingCtx).put(MappingEntryContext.getId(natId, MappingEntryContext.entryToKey(entry)), MappingEntryContext.toCtxMapEntry(entry, entryId)); - } - - @Test - public void testRemove() throws Exception { - final long natId = 0; - final MappingEntry entry = getEntry(natId, "192.168.1.5", "17.14.4.6"); - - ctx.removeEntry(natId, entry, mappingCtx); - - verify(mappingCtx).delete(MappingEntryContext.getId(natId, MappingEntryContext.entryToKey(entry))); - } - - @Test - public void testGetExistingIndex() throws Exception { - final long natId = 0; - final long entryId = 12; - final MappingEntry entry = getEntry(entryId, "192.168.1.5", "17.14.4.6"); - final SnatStaticMappingDetails details = getDetails(entryId, "192.168.1.5", "17.14.4.6"); - - when(mappingCtx.read(MappingEntryContext.getId(natId, MappingEntryContext.entryToKey(entry)))) - .thenReturn(Optional.of(MappingEntryContext.toCtxMapEntry(entry, entryId))); - - assertEquals(12, ctx.getStoredOrArtificialIndex(natId, details, mappingCtx)); - verify(mappingCtx).read(MappingEntryContext.getId(natId, MappingEntryContext.entryToKey(entry))); - } - - @Test - public void testFindDetails() throws Exception { - final long natId = 0; - final MappingEntry entry = getEntry(0, "192.168.1.5", "17.14.4.6"); - final SnatStaticMappingDetails details = getDetails(0, "192.168.1.5", "17.14.4.6"); - final MappingEntry entry2 = getEntry(1, "192.168.1.8", "17.14.4.10"); - final SnatStaticMappingDetails details2 = getDetails(1, "192.168.1.8", "17.14.4.10"); - - final List someDetails = Lists.newArrayList(details, details2); - - when(mappingCtx.read(MappingEntryContext.getTableId(natId))) - .thenReturn(Optional.of(new MappingTableBuilder() - .setMappingEntry(Lists.newArrayList( - MappingEntryContext.toCtxMapEntry(entry, 0), - MappingEntryContext.toCtxMapEntry(entry2, 1))) - .build())); - - assertSame(details, ctx.findDetails(someDetails, natId, 0, mappingCtx)); - } - - @Test(expected = IllegalStateException.class) - public void testFindDetailsNoMappingStored() throws Exception { - final long natId = 0; - final long entryId = 12; - final SnatStaticMappingDetails details = getDetails(entryId, "192.168.1.5", "17.14.4.6"); - final List someDetails = Lists.newArrayList(details); - when(mappingCtx.read(MappingEntryContext.getTableId(natId))).thenReturn(Optional.absent()); - - ctx.findDetails(someDetails, natId, entryId, mappingCtx); - } - - @Test(expected = IllegalStateException.class) - public void testFindDetailsNoMappingStored2() throws Exception { - final long natId = 0; - final long entryId = 12; - final SnatStaticMappingDetails details = getDetails(entryId, "192.168.1.5", "17.14.4.6"); - final List someDetails = Lists.newArrayList(details); - - when(mappingCtx.read(MappingEntryContext.getTableId(natId))) - .thenReturn(Optional.of(new MappingTableBuilder().setMappingEntry(Collections.emptyList()).build())); - - ctx.findDetails(someDetails, natId, entryId, mappingCtx); - } - - @Test - public void testGetArtificialIndex() throws Exception { - final long natId = 0; - final long entryId = 0; - final MappingEntry entry = getEntry(entryId, "192.168.1.5", "17.14.4.6"); - final long entryId2 = 55; - final MappingEntry entry2 = getEntry(entryId2, "192.168.1.6", "17.14.4.7"); - final long entryId3 = 18954; - final MappingEntry entry3 = getEntry(entryId3, "192.168.1.7", "17.14.4.8"); - final long entryId4 = 18955; - final MappingEntry entry4 = getEntry(entryId4, "192.168.1.8", "17.14.4.9"); - - final long newEntryId = 18956; - final MappingEntry newEntry = getEntry(newEntryId, "192.168.1.99", "17.14.4.99"); - final SnatStaticMappingDetails newDetails = getDetails(newEntryId, "192.168.1.99", "17.14.4.99"); - when(mappingCtx.read(MappingEntryContext.getId(natId, MappingEntryContext.entryToKey(newEntry)))) - .thenReturn(Optional.absent()); - - when(mappingCtx.read(MappingEntryContext.getTableId(natId))) - .thenReturn(Optional.of(new MappingTableBuilder() - .setMappingEntry(Lists.newArrayList( - MappingEntryContext.toCtxMapEntry(entry, entryId), - MappingEntryContext.toCtxMapEntry(entry3, entryId3), - MappingEntryContext.toCtxMapEntry(entry4, entryId4), - MappingEntryContext.toCtxMapEntry(entry2, entryId2))) - .build())); - - assertFalse(ctx.getStoredIndex(natId, newEntry, mappingCtx).isPresent()); - assertEquals(newEntryId, ctx.getStoredOrArtificialIndex(natId, newDetails, mappingCtx)); - } - - private SnatStaticMappingDetails getDetails(final long vrfId, final String localIp, final String externIp) { - final SnatStaticMappingDetails snatStaticMappingDetails = new SnatStaticMappingDetails(); - snatStaticMappingDetails.vrfId = (int) vrfId; - snatStaticMappingDetails.addrOnly = 1; - snatStaticMappingDetails.isIp4 = 1; - snatStaticMappingDetails.localIpAddress = ipv4AddressNoZoneToArray(localIp); - snatStaticMappingDetails.externalIpAddress = ipv4AddressNoZoneToArray(externIp); - return snatStaticMappingDetails; - } - - @Test(expected = IllegalArgumentException.class) - public void testAddExisting() throws Exception { - final long natId = 7; - final long entryId = 99; - final MappingEntry entry = getEntry(natId, "192.168.1.5", "17.14.4.6"); - final org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.nat.context.rev161214.mapping.entry.context.attributes.nat.mapping.entry.context.nat.instance.mapping.table.MappingEntry - data = MappingEntryContext.toCtxMapEntry(entry, entryId); - when(mappingCtx.read(any(InstanceIdentifier.class))).thenReturn(Optional.of(data)); - - ctx.addEntry(natId, entryId, entry, mappingCtx); - } - - private static MappingEntry getEntry(final long id, final String longernalIpv4, final String externalIpv4) { - return new MappingEntryBuilder() - .setKey(new MappingEntryKey(id)) - .setType(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.MappingEntry.Type.Static) - .setInternalSrcAddress(new IpAddress(new Ipv4Address(longernalIpv4))) - .setExternalSrcAddress(new Ipv4Address(externalIpv4)) - .build(); - } -} \ No newline at end of file -- cgit 1.2.3-korg