summaryrefslogtreecommitdiffstats
path: root/nat/nat2vpp/src/main
diff options
context:
space:
mode:
authorMarek Gradzki <mgradzki@cisco.com>2017-08-09 12:30:21 +0200
committerMarek Gradzki <mgradzki@cisco.com>2017-08-17 10:43:41 +0200
commit78aca8c336e69a049fd5e340b194bf7c66f61da1 (patch)
tree8fe8e1a46f5cf42e79c821eba1aa34fd8bca2360 /nat/nat2vpp/src/main
parent6c133f78a35c93e23da8347fe31e1b716d135dfe (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')
-rw-r--r--nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/MappingEntryCustomizer.java136
-rw-r--r--nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/NatInstanceCustomizer.java37
-rw-r--r--nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/read/NatReaderFactory.java18
-rw-r--r--nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/util/MappingEntryContext.java84
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)