diff options
author | Maros Marsalek <mmarsale@cisco.com> | 2016-11-10 13:31:25 +0100 |
---|---|---|
committer | Marek Gradzki <mgradzki@cisco.com> | 2016-11-19 21:29:39 +0100 |
commit | 175197da8ea43335df3daeba4c6296fcd83a057c (patch) | |
tree | 110298a990c6191933c2ad65d1a06333bab76cee /nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/util | |
parent | 1813bf59fa53e8eb913d34b212d45b227dead799 (diff) |
Post split cleanup
- change groupIds
- change packages
- update poms
Change-Id: I343c5a292a67de1dd50687870ca4ab5b7276e93e
Signed-off-by: Maros Marsalek <mmarsale@cisco.com>
Signed-off-by: Marek Gradzki <mgradzki@cisco.com>
Diffstat (limited to 'nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/util')
-rw-r--r-- | nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/util/MappingEntryContext.java | 210 |
1 files changed, 210 insertions, 0 deletions
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<MappingEntry> 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<MappingEntry> id = getId(natInstanceId, entryToKey(entry)); + return mappingContext.read(id).isPresent(); + } + + @VisibleForTesting + static InstanceIdentifier<MappingEntry> getId(final Long natInstanceId, final MappingEntryKey key) { + return getTableId(natInstanceId).child(MappingEntry.class, key); + } + + @VisibleForTesting + static InstanceIdentifier<MappingTable> 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<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) + .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<Long> 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); + } +} |