diff options
author | Marek Gradzki <mgradzki@cisco.com> | 2017-08-09 12:30:21 +0200 |
---|---|---|
committer | Marek Gradzki <mgradzki@cisco.com> | 2017-08-17 10:43:41 +0200 |
commit | 78aca8c336e69a049fd5e340b194bf7c66f61da1 (patch) | |
tree | 8fe8e1a46f5cf42e79c821eba1aa34fd8bca2360 /nat/nat2vpp/src/main | |
parent | 6c133f78a35c93e23da8347fe31e1b716d135dfe (diff) |
HC2VPP-105: add support for NAT64 BIB entries read
Change-Id: Ic8e61a13cba8ae8e3e69f16985918451df239430
Signed-off-by: Marek Gradzki <mgradzki@cisco.com>
Diffstat (limited to 'nat/nat2vpp/src/main')
4 files changed, 227 insertions, 48 deletions
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 index ae4f11917..2732c5fcc 100644 --- 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 @@ -17,6 +17,7 @@ package io.fd.hc2vpp.nat.read; import io.fd.hc2vpp.common.translate.util.Ipv4Translator; +import io.fd.hc2vpp.common.translate.util.Ipv6Translator; import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer; import io.fd.hc2vpp.nat.util.MappingEntryContext; import io.fd.honeycomb.translate.read.ReadContext; @@ -26,11 +27,15 @@ import io.fd.honeycomb.translate.spi.read.InitializingListReaderCustomizer; import io.fd.honeycomb.translate.util.RWUtils; import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager; import io.fd.honeycomb.translate.util.read.cache.EntityDumpExecutor; +import io.fd.vpp.jvpp.snat.dto.Nat64BibDetails; +import io.fd.vpp.jvpp.snat.dto.Nat64BibDetailsReplyDump; +import io.fd.vpp.jvpp.snat.dto.Nat64BibDump; import io.fd.vpp.jvpp.snat.dto.SnatStaticMappingDetails; import io.fd.vpp.jvpp.snat.dto.SnatStaticMappingDetailsReplyDump; import io.fd.vpp.jvpp.snat.dto.SnatStaticMappingDump; import io.fd.vpp.jvpp.snat.future.FutureJVppSnatFacade; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; import javax.annotation.Nonnull; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress; @@ -50,18 +55,21 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -final class MappingEntryCustomizer implements Ipv4Translator, +final class MappingEntryCustomizer implements Ipv4Translator, Ipv6Translator, InitializingListReaderCustomizer<MappingEntry, MappingEntryKey, MappingEntryBuilder> { private static final Logger LOG = LoggerFactory.getLogger(MappingEntryCustomizer.class); - private final DumpCacheManager<SnatStaticMappingDetailsReplyDump, Void> dumpCacheManager; + private final DumpCacheManager<SnatStaticMappingDetailsReplyDump, Void> nat44DumpManager; + private final DumpCacheManager<Nat64BibDetailsReplyDump, Void> nat64DumpManager; private final MappingEntryContext mappingEntryContext; MappingEntryCustomizer( - final DumpCacheManager<SnatStaticMappingDetailsReplyDump, Void> dumpCacheManager, + final DumpCacheManager<SnatStaticMappingDetailsReplyDump, Void> nat44DumpManager, + final DumpCacheManager<Nat64BibDetailsReplyDump, Void> nat64DumpManager, final MappingEntryContext mappingEntryContext) { - this.dumpCacheManager = dumpCacheManager; + this.nat44DumpManager = nat44DumpManager; + this.nat64DumpManager = nat64DumpManager; this.mappingEntryContext = mappingEntryContext; } @@ -79,34 +87,78 @@ final class MappingEntryCustomizer implements Ipv4Translator, final int idx = id.firstKeyOf(MappingEntry.class).getIndex().intValue(); final int natInstanceId = id.firstKeyOf(NatInstance.class).getId().intValue(); - final List<SnatStaticMappingDetails> details = - dumpCacheManager.getDump(id, ctx.getModificationCache(), null) + final List<SnatStaticMappingDetails> nat44Details = + nat44DumpManager.getDump(id, ctx.getModificationCache(), null) .or(new SnatStaticMappingDetailsReplyDump()).snatStaticMappingDetails; - final SnatStaticMappingDetails snatStaticMappingDetails = - mappingEntryContext.findDetails(details, natInstanceId, idx, ctx.getMappingContext()); + final Optional<SnatStaticMappingDetails> snat44StaticMappingDetails = + mappingEntryContext.findDetailsNat44(nat44Details, natInstanceId, idx, ctx.getMappingContext()); - builder.setIndex((long) idx); + if (snat44StaticMappingDetails.isPresent()) { + readNat44Entry(builder, idx, snat44StaticMappingDetails.get()); + } else { + final List<Nat64BibDetails> nat64Details = + nat64DumpManager.getDump(id, ctx.getModificationCache(), null) + .or(new Nat64BibDetailsReplyDump()).nat64BibDetails; + + final Optional<Nat64BibDetails> snat64StaticMappingDetails = + mappingEntryContext.findDetailsNat64(nat64Details, natInstanceId, idx, ctx.getMappingContext()); + + if (snat64StaticMappingDetails.isPresent()) { + readNat64Entry(builder, idx, snat64StaticMappingDetails.get()); + } + } + + + LOG.trace("Mapping-entry read as: {}", builder); + } + + private void readNat44Entry(@Nonnull final MappingEntryBuilder builder, + final int index, final SnatStaticMappingDetails detail) { + builder.setIndex((long) index); builder.setType( org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.MappingEntry.Type.Static); - // Snat only supports ipv4 for now - builder.setExternalSrcAddress(arrayToIpv4AddressNoZone(snatStaticMappingDetails.externalIpAddress)); + builder.setExternalSrcAddress(arrayToIpv4AddressNoZone(detail.externalIpAddress)); builder.setInternalSrcAddress( - new IpAddress(arrayToIpv4AddressNoZone(snatStaticMappingDetails.localIpAddress))); + new IpAddress(arrayToIpv4AddressNoZone(detail.localIpAddress))); - if (snatStaticMappingDetails.addrOnly == 0) { + if (detail.addrOnly == 0) { builder.setExternalSrcPort(new ExternalSrcPortBuilder() .setPortType(new SinglePortNumberBuilder().setSinglePortNumber(new PortNumber( - (int) snatStaticMappingDetails.externalPort)) + (int) detail.externalPort)) .build()) .build()); builder.setInternalSrcPort(new InternalSrcPortBuilder() .setPortType(new SinglePortNumberBuilder().setSinglePortNumber(new PortNumber( - (int) snatStaticMappingDetails.localPort)) + (int) detail.localPort)) .build()) .build()); } + } - LOG.trace("Mapping-entry read as: {}", builder); + private void readNat64Entry(@Nonnull final MappingEntryBuilder builder, + final int index, final Nat64BibDetails detail) { + builder.setIndex((long) index); + if (detail.isStatic == 1) { + builder.setType( + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.MappingEntry.Type.Static); + } else { + builder.setType( + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.MappingEntry.Type.Dynamic); + } + builder.setExternalSrcAddress(arrayToIpv4AddressNoZone(detail.oAddr)); + builder.setInternalSrcAddress( + new IpAddress(arrayToIpv6AddressNoZone(detail.iAddr))); + + builder.setExternalSrcPort(new ExternalSrcPortBuilder() + .setPortType(new SinglePortNumberBuilder().setSinglePortNumber(new PortNumber( + (int) detail.oPort)) + .build()) + .build()); + builder.setInternalSrcPort(new InternalSrcPortBuilder() + .setPortType(new SinglePortNumberBuilder().setSinglePortNumber(new PortNumber( + (int) detail.iPort)) + .build()) + .build()); } @Nonnull @@ -117,13 +169,24 @@ final class MappingEntryCustomizer implements Ipv4Translator, LOG.trace("Listing IDs for all mapping-entries within nat-instance(vrf):{}", natInstanceId); final List<MappingEntryKey> entryKeys = - dumpCacheManager.getDump(id, context.getModificationCache(), null) + nat44DumpManager.getDump(id, context.getModificationCache(), null) .or(new SnatStaticMappingDetailsReplyDump()).snatStaticMappingDetails.stream() .filter(detail -> natInstanceId == detail.vrfId) .map(detail -> mappingEntryContext .getStoredOrArtificialIndex(natInstanceId, detail, context.getMappingContext())) .map(MappingEntryKey::new) .collect(Collectors.toList()); + + + final List<MappingEntryKey> nat64Keys = + nat64DumpManager.getDump(id, context.getModificationCache(), null) + .or(new Nat64BibDetailsReplyDump()).nat64BibDetails.stream() + .filter(detail -> natInstanceId == detail.vrfId) + .map(detail -> mappingEntryContext + .getStoredOrArtificialIndex(natInstanceId, detail, context.getMappingContext())) + .map(MappingEntryKey::new) + .collect(Collectors.toList()); + entryKeys.addAll(nat64Keys); LOG.debug("List of mapping-entry keys within nat-instance(vrf):{} : {}", natInstanceId, entryKeys); return entryKeys; @@ -136,27 +199,31 @@ final class MappingEntryCustomizer implements Ipv4Translator, } @Override - public Initialized<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry> init(@Nonnull final InstanceIdentifier<MappingEntry> id, - @Nonnull final MappingEntry readValue, - @Nonnull final ReadContext ctx) { + public Initialized<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry> init( + @Nonnull final InstanceIdentifier<MappingEntry> id, + @Nonnull final MappingEntry readValue, + @Nonnull final ReadContext ctx) { return Initialized.create(getCfgId(id), - new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntryBuilder(readValue) + new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntryBuilder( + readValue) .build()); } - static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry> getCfgId(final @Nonnull InstanceIdentifier<MappingEntry> id) { + static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry> getCfgId( + final @Nonnull InstanceIdentifier<MappingEntry> id) { return NatInstanceCustomizer.getCfgId(RWUtils.cutId(id, NatInstance.class)) .child(MappingTable.class) .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry.class, - new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntryKey(id.firstKeyOf(MappingEntry.class).getIndex())); + new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntryKey( + id.firstKeyOf(MappingEntry.class).getIndex())); } - static final class MappingEntryDumpExecutor + static final class MappingEntryNat44DumpExecutor implements EntityDumpExecutor<SnatStaticMappingDetailsReplyDump, Void>, JvppReplyConsumer { private final FutureJVppSnatFacade jvppSnat; - MappingEntryDumpExecutor(final FutureJVppSnatFacade jvppSnat) { + MappingEntryNat44DumpExecutor(final FutureJVppSnatFacade jvppSnat) { this.jvppSnat = jvppSnat; } @@ -168,4 +235,23 @@ final class MappingEntryCustomizer implements Ipv4Translator, identifier); } } + + static final class MappingEntryNat64DumpExecutor + implements EntityDumpExecutor<Nat64BibDetailsReplyDump, Void>, JvppReplyConsumer { + + private final FutureJVppSnatFacade jvppSnat; + + MappingEntryNat64DumpExecutor(final FutureJVppSnatFacade jvppSnat) { + this.jvppSnat = jvppSnat; + } + + @Nonnull + @Override + public Nat64BibDetailsReplyDump executeDump(final InstanceIdentifier<?> identifier, final Void params) + throws ReadFailedException { + final Nat64BibDump dump = new Nat64BibDump(); + dump.proto = -1; // dump entries for all protocols + return getReplyForRead(jvppSnat.nat64BibDump(dump).toCompletableFuture(), identifier); + } + } } 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 index 9542587d0..18a959274 100644 --- 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 @@ -21,9 +21,11 @@ import io.fd.honeycomb.translate.read.ReadFailedException; import io.fd.honeycomb.translate.spi.read.Initialized; import io.fd.honeycomb.translate.spi.read.InitializingListReaderCustomizer; import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager; +import io.fd.vpp.jvpp.snat.dto.Nat64BibDetailsReplyDump; import io.fd.vpp.jvpp.snat.dto.SnatStaticMappingDetailsReplyDump; import java.util.List; import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.annotation.Nonnull; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.NatConfig; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.NatInstancesBuilder; @@ -39,16 +41,20 @@ import org.slf4j.LoggerFactory; /** * Nat instance ID is mapped to VRF-ID in VPP. */ -final class NatInstanceCustomizer implements InitializingListReaderCustomizer<NatInstance, NatInstanceKey, NatInstanceBuilder> { +final class NatInstanceCustomizer + implements InitializingListReaderCustomizer<NatInstance, NatInstanceKey, NatInstanceBuilder> { private static final Logger LOG = LoggerFactory.getLogger(NatInstanceCustomizer.class); static final NatInstanceKey DEFAULT_VRF_ID = new NatInstanceKey(0L); - private final DumpCacheManager<SnatStaticMappingDetailsReplyDump, Void> dumpCacheManager; + private final DumpCacheManager<SnatStaticMappingDetailsReplyDump, Void> nat44DumpManager; + private final DumpCacheManager<Nat64BibDetailsReplyDump, Void> nat64DumpManager; NatInstanceCustomizer( - final DumpCacheManager<SnatStaticMappingDetailsReplyDump, Void> dumpCacheManager) { - this.dumpCacheManager = dumpCacheManager; + final DumpCacheManager<SnatStaticMappingDetailsReplyDump, Void> nat44DumpManager, + final DumpCacheManager<Nat64BibDetailsReplyDump, Void> nat64DumpManager) { + this.nat44DumpManager = nat44DumpManager; + this.nat64DumpManager = nat64DumpManager; } @Nonnull @@ -72,12 +78,18 @@ final class NatInstanceCustomizer implements InitializingListReaderCustomizer<Na LOG.trace("Listing IDs for all nat-instances"); // Find the nat instance IDs (vrf-ids) by listing all static mappings and their VRF assignment - final List<NatInstanceKey> vrfIds = - dumpCacheManager.getDump(id, context.getModificationCache(), null) + final List<NatInstanceKey> vrfIds = Stream.concat( + nat44DumpManager.getDump(id, context.getModificationCache(), null) .or(new SnatStaticMappingDetailsReplyDump()).snatStaticMappingDetails.stream() - .map(detail -> detail.vrfId) - .map(vrfId -> new NatInstanceKey((long) vrfId)) - .collect(Collectors.toList()); + .map(detail -> detail.vrfId), + nat64DumpManager.getDump(id, context.getModificationCache(), null) + .or(new Nat64BibDetailsReplyDump()).nat64BibDetails.stream() + .map(detail -> detail.vrfId)) + // V4 (nat44) and V6 (nat64) VRFs in VPP can have the same id. We store them under single nat instance, + // because the ietf-nat model does not require separate instances for nat44 and nat64 features. + .distinct() + .map(vrfId -> new NatInstanceKey((long) vrfId)) + .collect(Collectors.toList()); // Add default vrf id if not present if (!vrfIds.contains(DEFAULT_VRF_ID)) { @@ -94,9 +106,10 @@ final class NatInstanceCustomizer implements InitializingListReaderCustomizer<Na } @Override - public Initialized<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.NatInstance> init(@Nonnull final InstanceIdentifier<NatInstance> id, - @Nonnull final NatInstance readValue, - @Nonnull final ReadContext ctx) { + public Initialized<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.NatInstance> init( + @Nonnull final InstanceIdentifier<NatInstance> id, + @Nonnull final NatInstance readValue, + @Nonnull final ReadContext ctx) { return Initialized.create(getCfgId(id), new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.NatInstanceBuilder() .setId(readValue.getId()) 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 index 791b7bc0b..d9c7f3380 100644 --- 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 @@ -23,6 +23,7 @@ import io.fd.honeycomb.translate.impl.read.GenericInitListReader; import io.fd.honeycomb.translate.read.ReaderFactory; import io.fd.honeycomb.translate.read.registry.ModifiableReaderRegistryBuilder; import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager; +import io.fd.vpp.jvpp.snat.dto.Nat64BibDetailsReplyDump; import io.fd.vpp.jvpp.snat.dto.SnatStaticMappingDetailsReplyDump; import io.fd.vpp.jvpp.snat.future.FutureJVppSnatFacade; import javax.annotation.Nonnull; @@ -53,7 +54,8 @@ public class NatReaderFactory implements ReaderFactory { private final FutureJVppSnatFacade jvppSnat; private final MappingEntryContext mappingEntryContext; - private final DumpCacheManager<SnatStaticMappingDetailsReplyDump, Void> mapEntryDumpMgr; + private final DumpCacheManager<SnatStaticMappingDetailsReplyDump, Void> mapEntryNat44DumpMgr; + private final DumpCacheManager<Nat64BibDetailsReplyDump, Void> mapEntryNat64DumpMgr; @Inject @@ -61,23 +63,29 @@ public class NatReaderFactory implements ReaderFactory { final MappingEntryContext mappingEntryContext) { this.jvppSnat = jvppSnat; this.mappingEntryContext = mappingEntryContext; - this.mapEntryDumpMgr = + this.mapEntryNat44DumpMgr = new DumpCacheManager.DumpCacheManagerBuilder<SnatStaticMappingDetailsReplyDump, Void>() - .withExecutor(new MappingEntryCustomizer.MappingEntryDumpExecutor(jvppSnat)) + .withExecutor(new MappingEntryCustomizer.MappingEntryNat44DumpExecutor(jvppSnat)) .acceptOnly(SnatStaticMappingDetailsReplyDump.class) .build(); + this.mapEntryNat64DumpMgr = + new DumpCacheManager.DumpCacheManagerBuilder<Nat64BibDetailsReplyDump, Void>() + .withExecutor(new MappingEntryCustomizer.MappingEntryNat64DumpExecutor(jvppSnat)) + .acceptOnly(Nat64BibDetailsReplyDump.class) + .build(); } @Override public void init(@Nonnull final ModifiableReaderRegistryBuilder registry) { registry.addStructuralReader(NAT_OPER_ID, NatStateBuilder.class); registry.addStructuralReader(NAT_INSTANCES_ID, NatInstancesBuilder.class); - registry.add(new GenericInitListReader<>(NAT_INSTANCE_ID, new NatInstanceCustomizer(mapEntryDumpMgr))); + registry.add(new GenericInitListReader<>(NAT_INSTANCE_ID, + new NatInstanceCustomizer(mapEntryNat44DumpMgr, mapEntryNat64DumpMgr))); registry.addStructuralReader(MAP_TABLE_ID, MappingTableBuilder.class); registry.subtreeAdd(Sets.newHashSet(InstanceIdentifier.create(MappingEntry.class).child(ExternalSrcPort.class), InstanceIdentifier.create(MappingEntry.class).child(InternalSrcPort.class)), new GenericInitListReader<>(MAP_ENTRY_ID, - new MappingEntryCustomizer(mapEntryDumpMgr, mappingEntryContext))); + new MappingEntryCustomizer(mapEntryNat44DumpMgr, mapEntryNat64DumpMgr, mappingEntryContext))); registry.addStructuralReader(CURRENT_CONFIG, NatCurrentConfigBuilder.class); registry.add(new GenericInitListReader<>(CURRENT_CONFIG.child(ExternalIpAddressPool.class), 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 index afdf8abae..292adc3aa 100644 --- 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 @@ -21,7 +21,9 @@ import static com.google.common.base.Preconditions.checkArgument; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Optional; import io.fd.hc2vpp.common.translate.util.Ipv4Translator; +import io.fd.hc2vpp.common.translate.util.Ipv6Translator; import io.fd.honeycomb.translate.MappingContext; +import io.fd.vpp.jvpp.snat.dto.Nat64BibDetails; import io.fd.vpp.jvpp.snat.dto.SnatStaticMappingDetails; import java.util.Collections; import java.util.Comparator; @@ -39,6 +41,7 @@ import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.nat.context import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.nat.context.rev161214.mapping.entry.context.attributes.nat.mapping.entry.context.nat.instance.mapping.table.MappingEntryKey; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -47,7 +50,7 @@ import org.slf4j.LoggerFactory; * Context tracker for Nat Mapping entries. */ @ThreadSafe -public class MappingEntryContext implements Ipv4Translator { +public class MappingEntryContext implements Ipv4Translator, Ipv6Translator { private static final Logger LOG = LoggerFactory.getLogger(MappingEntryContext.class); @@ -101,6 +104,12 @@ public class MappingEntryContext implements Ipv4Translator { new IpAddress(new Ipv4Address(arrayToIpv4AddressNoZone(entry.localIpAddress)))); } + private MappingEntryKey entryToKey(final Nat64BibDetails entry) { + return new MappingEntryKey( + new IpAddress(new Ipv4Address(arrayToIpv4AddressNoZone(entry.oAddr))), + new IpAddress(new Ipv6Address(arrayToIpv6AddressNoZone(entry.iAddr)))); + } + private boolean equalEntries(final SnatStaticMappingDetails detail, final MappingEntry ctxMappingEntry) { final IpAddress internalAddrFromDetails = new IpAddress(new Ipv4Address(arrayToIpv4AddressNoZone(detail.localIpAddress))); @@ -117,6 +126,22 @@ public class MappingEntryContext implements Ipv4Translator { return true; } + private boolean equalEntries(final Nat64BibDetails detail, final MappingEntry ctxMappingEntry) { + final IpAddress internalAddrFromDetails = + new IpAddress(new Ipv6Address(arrayToIpv6AddressNoZone(detail.iAddr))); + // Only IPv6 + if (!ctxMappingEntry.getInternal().equals(internalAddrFromDetails)) { + return false; + } + // Only IPv4 + final IpAddress externalAddrFromDetails = + new IpAddress(new Ipv4Address(arrayToIpv4AddressNoZone(detail.oAddr))); + if (!ctxMappingEntry.getExternal().equals(externalAddrFromDetails)) { + return false; + } + return true; + } + @VisibleForTesting static MappingEntry toCtxMapEntry( @Nonnull final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry entry, @@ -134,6 +159,13 @@ public class MappingEntryContext implements Ipv4Translator { .build(); } + private MappingEntry toCtxMapEntry(@Nonnull final Nat64BibDetails details, final long entryId) { + return new MappingEntryBuilder() + .setKey(entryToKey(details)) + .setIndex(entryId) + .build(); + } + /** * Delete mapping of mapping entry to index from context. */ @@ -146,9 +178,9 @@ public class MappingEntryContext implements Ipv4Translator { /** * Find specific details in provided collection identified with provided index. */ - public synchronized SnatStaticMappingDetails findDetails(@Nonnull final List<SnatStaticMappingDetails> details, - final long natInstanceId, final long idx, - @Nonnull final MappingContext mappingContext) { + public synchronized java.util.Optional<SnatStaticMappingDetails> findDetailsNat44(@Nonnull final List<SnatStaticMappingDetails> details, + final long natInstanceId, final long idx, + @Nonnull final MappingContext mappingContext) { // Find mapping entry for Index final MappingEntry ctxMappingEntry = mappingContext.read(getTableId(natInstanceId)) .transform(MappingTable::getMappingEntry) @@ -162,9 +194,29 @@ public class MappingEntryContext implements Ipv4Translator { // Find which details matches the context stored entry under index return details.stream() .filter(detail -> equalEntries(detail, ctxMappingEntry)) + .findFirst(); + } + + /** + * Find specific details in provided collection identified with provided index. + */ + public synchronized java.util.Optional<Nat64BibDetails> findDetailsNat64(@Nonnull final List<Nat64BibDetails> details, + final long natInstanceId, final long idx, + @Nonnull final MappingContext mappingContext) { + // Find mapping entry for Index + final MappingEntry ctxMappingEntry = mappingContext.read(getTableId(natInstanceId)) + .transform(MappingTable::getMappingEntry) + .or(Collections.emptyList()) + .stream() + .filter(entry -> entry.getIndex() == idx) .findFirst() - .orElseThrow(() -> new IllegalStateException("Unable to match mapping for nat-instance: " - + natInstanceId + " and match: " + ctxMappingEntry + " in: " + details)); + .orElseThrow(() -> new IllegalStateException("Unable to find context mapping for nat-instance: " + + natInstanceId + " and ID: " + idx)); + + // Find which details matches the context stored entry under index + return details.stream() + .filter(detail -> equalEntries(detail, ctxMappingEntry)) + .findFirst(); } /** @@ -179,6 +231,17 @@ public class MappingEntryContext implements Ipv4Translator { } /** + * Get index for a mapping entry details or create an artificial one. + */ + public synchronized long getStoredOrArtificialIndex(final Long natInstanceId, + @Nonnull final Nat64BibDetails details, + @Nonnull final MappingContext mappingContext) { + return mappingContext.read(getId(natInstanceId, entryToKey(details))) + .transform(MappingEntry::getIndex) + .or(() -> getArtificialId(details, natInstanceId, mappingContext)); + } + + /** * Get index for a stored mapping entry. */ public synchronized Optional<Long> getStoredIndex(final long natInstanceId, @@ -197,6 +260,15 @@ public class MappingEntryContext implements Ipv4Translator { return artificialIdx; } + private long getArtificialId(final Nat64BibDetails details, final Long natInstanceId, + final MappingContext mappingContext) { + LOG.trace("Assigning artificial ID for {}", details); + final long artificialIdx = findFreeIndex(natInstanceId, mappingContext); + LOG.debug("Artificial ID for {} assigned as: {}", details, artificialIdx); + mappingContext.put(getId(natInstanceId, entryToKey(details)), toCtxMapEntry(details, artificialIdx)); + return artificialIdx; + } + private long findFreeIndex(final long natInstanceId, final MappingContext mappingContext) { return mappingContext.read(getTableId(natInstanceId)) .transform(MappingTable::getMappingEntry) |