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 --- .../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 +++++ 8 files changed, 655 insertions(+) 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 (limited to 'nat/nat2vpp/src/main/java/io/fd/hc2vpp/nat/write') 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; + } +} -- cgit 1.2.3-korg