summaryrefslogtreecommitdiffstats
path: root/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write
diff options
context:
space:
mode:
Diffstat (limited to 'v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write')
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/AbstractUnnumberedCustomizer.java80
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/AfPacketCustomizer.java119
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/AfPacketValidator.java79
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/EthernetCustomizer.java90
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/EthernetValidator.java48
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/GreCustomizer.java147
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/GreValidator.java72
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/InterconnectionWriteUtils.java159
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/InterfaceCustomizer.java124
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/InterfaceRoutingCustomizer.java61
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/InterfaceRoutingValidator.java118
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/InterfaceUnnumberedCustomizer.java56
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/InterfaceUnnumberedValidator.java55
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/InterfaceValidator.java74
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/InterfacesStatisticsCustomizer.java67
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/InterfacesStatisticsValidator.java55
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/L2Customizer.java89
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/L2Validator.java58
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/LoopbackCustomizer.java104
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/LoopbackValidator.java55
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/RewriteCustomizer.java135
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/RewriteValidator.java55
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/RoutingCustomizer.java95
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/SubInterfaceCustomizer.java193
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/SubInterfaceL2Customizer.java100
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/SubInterfaceL2Validator.java58
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/SubInterfaceRoutingCustomizer.java57
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/SubInterfaceRoutingValidator.java110
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/SubInterfaceUnnumberedCustomizer.java57
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/SubInterfaceUnnumberedValidator.java55
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/SubInterfaceValidator.java62
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/TapV2Customizer.java227
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/TapV2Validator.java55
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/VhostUserCustomizer.java169
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/VhostUserValidator.java55
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/VxlanCustomizer.java181
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/VxlanGpeCustomizer.java164
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/VxlanGpeValidator.java78
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/VxlanValidator.java79
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/pbb/PbbRewriteCustomizer.java111
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/pbb/PbbRewriteValidator.java82
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/span/MirroredInterfaceCustomizer.java118
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/span/MirroredInterfaceValidator.java79
43 files changed, 4085 insertions, 0 deletions
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/AbstractUnnumberedCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/AbstractUnnumberedCustomizer.java
new file mode 100644
index 000000000..15b4be75b
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/AbstractUnnumberedCustomizer.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2017 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.v3po.write;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.spi.write.WriterCustomizer;
+import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.jvpp.core.dto.SwInterfaceSetUnnumbered;
+import io.fd.jvpp.core.future.FutureJVppCore;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.unnumbered.interfaces.rev180103.unnumbered.config.attributes.Unnumbered;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+abstract class AbstractUnnumberedCustomizer extends FutureJVppCustomizer implements WriterCustomizer<Unnumbered>,
+ JvppReplyConsumer, ByteDataTranslator {
+ private static final Logger LOG = LoggerFactory.getLogger(AbstractUnnumberedCustomizer.class);
+
+ private final NamingContext interfaceContext;
+
+ protected AbstractUnnumberedCustomizer(@Nonnull final FutureJVppCore futureJVppCore,
+ @Nonnull final NamingContext interfaceContext) {
+ super(futureJVppCore);
+ this.interfaceContext = checkNotNull(interfaceContext, "interfaceContext should not be null");
+ }
+
+ protected void setUnnumbered(@Nonnull final InstanceIdentifier<Unnumbered> id,
+ @Nonnull final String unnumberedIfcName,
+ @Nonnull final Unnumbered data,
+ @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ final int unnumberedIfcId = interfaceContext.getIndex(unnumberedIfcName, writeContext.getMappingContext());
+ final int targetId = interfaceContext.getIndex(data.getUse(), writeContext.getMappingContext());
+ final SwInterfaceSetUnnumbered request = getUnnumberedAddDelRequest(targetId, unnumberedIfcId, true);
+ getReplyForWrite(getFutureJVpp().swInterfaceSetUnnumbered(request).toCompletableFuture(), id);
+ LOG.debug("The {}(id={}) interface unnumbered flag was set: {}", unnumberedIfcName, unnumberedIfcId, data);
+ }
+
+ protected void disableUnnumbered(@Nonnull final InstanceIdentifier<Unnumbered> id,
+ @Nonnull final String unnumberedIfcName,
+ @Nonnull final Unnumbered data,
+ @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ final int unnumberedIfcId = interfaceContext.getIndex(unnumberedIfcName, writeContext.getMappingContext());
+ final int targetId = interfaceContext.getIndex(data.getUse(), writeContext.getMappingContext());
+ final SwInterfaceSetUnnumbered request = getUnnumberedAddDelRequest(targetId, unnumberedIfcId, false);
+ getReplyForWrite(getFutureJVpp().swInterfaceSetUnnumbered(request).toCompletableFuture(), id);
+ LOG.debug("The {}(id={}) interface unnumbered flag was unset: {}", unnumberedIfcName, unnumberedIfcId, data);
+ }
+
+ private SwInterfaceSetUnnumbered getUnnumberedAddDelRequest(final int targetId, final int unnumberedIfcId,
+ final Boolean isAdd) {
+ final SwInterfaceSetUnnumbered request = new SwInterfaceSetUnnumbered();
+ request.swIfIndex = targetId;
+ request.unnumberedSwIfIndex = unnumberedIfcId;
+ request.isAdd = booleanToByte(isAdd);
+ return request;
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/AfPacketCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/AfPacketCustomizer.java
new file mode 100644
index 000000000..f8e658216
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/AfPacketCustomizer.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2018 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.v3po.write;
+
+import io.fd.hc2vpp.common.translate.util.AbstractInterfaceTypeCustomizer;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.hc2vpp.common.translate.util.MacTranslator;
+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.jvpp.core.dto.AfPacketCreate;
+import io.fd.jvpp.core.dto.AfPacketCreateReply;
+import io.fd.jvpp.core.dto.AfPacketDelete;
+import io.fd.jvpp.core.dto.AfPacketDeleteReply;
+import io.fd.jvpp.core.future.FutureJVppCore;
+import java.nio.charset.StandardCharsets;
+import java.util.concurrent.CompletionStage;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.AfPacket;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.InterfaceType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class AfPacketCustomizer extends AbstractInterfaceTypeCustomizer<AfPacket>
+ implements MacTranslator, JvppReplyConsumer {
+
+ private static final Logger LOG = LoggerFactory.getLogger(AfPacketCustomizer.class);
+ private final NamingContext interfaceContext;
+
+ public AfPacketCustomizer(@Nonnull final FutureJVppCore vppApi, @Nonnull final NamingContext interfaceContext) {
+ super(vppApi);
+ this.interfaceContext = interfaceContext;
+ }
+
+ @Override
+ protected Class<? extends InterfaceType> getExpectedInterfaceType() {
+ return org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.AfPacket.class;
+ }
+
+ @Override
+ protected final void writeInterface(@Nonnull final InstanceIdentifier<AfPacket> id,
+ @Nonnull final AfPacket dataAfter, @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ final String swIfName = id.firstKeyOf(Interface.class).getName();
+ final int swIfIndex = createAfPacketIfc(id, swIfName, dataAfter);
+
+ // Add new interface to our interface context
+ interfaceContext.addName(swIfIndex, swIfName, writeContext.getMappingContext());
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<AfPacket> id,
+ @Nonnull final AfPacket dataBefore, @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ final String swIfName = id.firstKeyOf(Interface.class).getName();
+ deleteAfPacketIfc(id, swIfName, dataBefore);
+
+ // Remove interface from interface context
+ interfaceContext.removeName(swIfName, writeContext.getMappingContext());
+ }
+
+ private int createAfPacketIfc(final InstanceIdentifier<AfPacket> id, final String swIfName, final AfPacket afPacket)
+ throws WriteFailedException {
+ LOG.debug("Creating af_packet interface {}: {}", swIfName, afPacket);
+ final CompletionStage<AfPacketCreateReply> createAfPacketIfReplyCompletionStage =
+ getFutureJVpp().afPacketCreate(getCreateRequest(afPacket));
+ final AfPacketCreateReply reply =
+ getReplyForCreate(createAfPacketIfReplyCompletionStage.toCompletableFuture(), id, afPacket);
+ LOG.debug("Af_packet interface {} created successfully: {}", swIfName, afPacket);
+ return reply.swIfIndex;
+ }
+
+ private AfPacketCreate getCreateRequest(@Nonnull final AfPacket afPacket) {
+ final AfPacketCreate request = new AfPacketCreate();
+ request.hostIfName = afPacket.getHostInterfaceName().getBytes(StandardCharsets.UTF_8);
+ final PhysAddress mac = afPacket.getMac();
+ if (mac == null) {
+ request.useRandomHwAddr = 1;
+ request.hwAddr = new byte[6];
+ } else {
+ request.useRandomHwAddr = 0;
+ request.hwAddr = parseMac(mac.getValue());
+ }
+ return request;
+ }
+
+ private void deleteAfPacketIfc(final InstanceIdentifier<AfPacket> id, final String swIfName,
+ final AfPacket afPacket) throws WriteFailedException {
+ LOG.debug("Deleting af_packet interface {}: {}", swIfName, afPacket);
+ final CompletionStage<AfPacketDeleteReply> deleteAfPacketIfReplyCompletionStage =
+ getFutureJVpp().afPacketDelete(getDeleteRequest(afPacket));
+
+ getReplyForDelete(deleteAfPacketIfReplyCompletionStage.toCompletableFuture(), id);
+ LOG.debug("Af_packet interface {} deleted successfully: {}", swIfName, afPacket);
+ }
+
+ private AfPacketDelete getDeleteRequest(@Nonnull final AfPacket afPacket) {
+ final AfPacketDelete request = new AfPacketDelete();
+ request.hostIfName = afPacket.getHostInterfaceName().getBytes(StandardCharsets.UTF_8);
+ return request;
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/AfPacketValidator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/AfPacketValidator.java
new file mode 100644
index 000000000..392875190
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/AfPacketValidator.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2019 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.v3po.write;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.CreateValidationFailedException;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.DeleteValidationFailedException;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.UpdateValidationFailedException;
+import io.fd.honeycomb.translate.write.Validator;
+import io.fd.honeycomb.translate.write.WriteContext;
+import java.nio.charset.StandardCharsets;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.AfPacket;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class AfPacketValidator implements Validator<AfPacket> {
+
+ public AfPacketValidator(@Nonnull final NamingContext interfaceContext) {
+ checkNotNull(interfaceContext, "interfaceContext should not be null");
+ }
+
+ @Override
+ public void validateWrite(@Nonnull final InstanceIdentifier<AfPacket> id, @Nonnull final AfPacket dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws CreateValidationFailedException {
+ try {
+ validateAfPacket(dataAfter);
+ } catch (Exception e) {
+ throw new CreateValidationFailedException(id, dataAfter, e);
+ }
+ }
+
+ @Override
+ public void validateUpdate(@Nonnull final InstanceIdentifier<AfPacket> id, @Nonnull final AfPacket dataBefore,
+ @Nonnull final AfPacket dataAfter, @Nonnull final WriteContext writeContext)
+ throws UpdateValidationFailedException {
+ try {
+ validateAfPacket(dataAfter);
+ } catch (Exception e) {
+ throw new UpdateValidationFailedException(id, dataBefore, dataAfter, e);
+ }
+ }
+
+ @Override
+ public void validateDelete(@Nonnull final InstanceIdentifier<AfPacket> id, @Nonnull final AfPacket dataBefore,
+ @Nonnull final WriteContext writeContext)
+ throws DeleteValidationFailedException {
+ try {
+ validateAfPacket(dataBefore);
+ } catch (Exception e) {
+ throw new DeleteValidationFailedException(id, e);
+ }
+ }
+
+ private void validateAfPacket(final AfPacket data) {
+ checkNotNull(data.getHostInterfaceName(), "host-interface-name is mandatory for af-packet interface");
+ byte[] hostIfName = data.getHostInterfaceName().getBytes(StandardCharsets.UTF_8);
+ checkArgument(hostIfName.length <= 64,
+ "Interface name for af_packet interface should not be longer than 64 bytes, but was %s",
+ hostIfName.length);
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/EthernetCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/EthernetCustomizer.java
new file mode 100644
index 000000000..029f6f308
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/EthernetCustomizer.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.v3po.write;
+
+import io.fd.hc2vpp.common.translate.util.AbstractInterfaceTypeCustomizer;
+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.jvpp.core.dto.HwInterfaceSetMtu;
+import io.fd.jvpp.core.future.FutureJVppCore;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Ethernet;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev180703.EthernetCsmacd;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.InterfaceType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class EthernetCustomizer extends AbstractInterfaceTypeCustomizer<Ethernet> implements JvppReplyConsumer {
+
+ private static final Logger LOG = LoggerFactory.getLogger(EthernetCustomizer.class);
+ private final NamingContext interfaceContext;
+
+ public EthernetCustomizer(final FutureJVppCore vppApi, final NamingContext interfaceContext) {
+ super(vppApi);
+ this.interfaceContext = interfaceContext;
+ }
+
+ @Override
+ protected Class<? extends InterfaceType> getExpectedInterfaceType() {
+ return EthernetCsmacd.class;
+ }
+
+ @Override
+ public void writeInterface(@Nonnull final InstanceIdentifier<Ethernet> id,
+ @Nonnull final Ethernet dataAfter, @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ setEthernetAttributes(id, dataAfter, writeContext);
+ }
+
+ @Override
+ public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<Ethernet> id,
+ @Nonnull final Ethernet dataBefore, @Nonnull final Ethernet dataAfter,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ setEthernetAttributes(id, dataAfter, writeContext);
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Ethernet> id,
+ @Nonnull final Ethernet dataBefore, @Nonnull final WriteContext writeContext)
+ throws WriteFailedException.DeleteFailedException {
+ throw new WriteFailedException.DeleteFailedException(id,
+ new UnsupportedOperationException("Removing ethernet container is not supported"));
+ }
+
+ private void setEthernetAttributes(@Nonnull final InstanceIdentifier<Ethernet> id,
+ @Nonnull final Ethernet dataAfter, @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ final String name = id.firstKeyOf(Interface.class).getName();
+ final int index = interfaceContext.getIndex(name, writeContext.getMappingContext());
+ LOG.debug("Setting Ethernet attributes for interface: {}, {}. Ethernet: {}", name, index, dataAfter);
+
+ // Set the physical payload MTU. I.e. not including L2 overhead.
+ // Setting the hardware MTU will program the NIC.
+ // Setting MTU for software interfaces is currently not supported (TODO: HC2VPP-355).
+ // More details:
+ // https://git.fd.io/vpp/tree/src/vnet/MTU.md
+ final HwInterfaceSetMtu request = new HwInterfaceSetMtu();
+ request.swIfIndex = index;
+ request.mtu = dataAfter.getMtu().shortValue();
+ getReplyForWrite(getFutureJVpp().hwInterfaceSetMtu(request).toCompletableFuture(), id);
+ LOG.debug("Ethernet attributes set successfully for: {}, {}. Ethernet: {}", name, index, dataAfter);
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/EthernetValidator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/EthernetValidator.java
new file mode 100644
index 000000000..ebdd17346
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/EthernetValidator.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2019 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.v3po.write;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.DataValidationFailedException;
+import io.fd.honeycomb.translate.write.Validator;
+import io.fd.honeycomb.translate.write.WriteContext;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Ethernet;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class EthernetValidator implements Validator<Ethernet> {
+
+ public EthernetValidator(final NamingContext interfaceContext) {
+ checkNotNull(interfaceContext, "interfaceContext should not be null");
+ }
+
+ @Override
+ public void validateWrite(@Nonnull final InstanceIdentifier<Ethernet> id, @Nonnull final Ethernet dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.CreateValidationFailedException {
+ checkNotNull(dataAfter.getMtu(), "MTU cannot be null");
+ }
+
+ @Override
+ public void validateUpdate(@Nonnull final InstanceIdentifier<Ethernet> id, @Nonnull final Ethernet dataBefore,
+ @Nonnull final Ethernet dataAfter, @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.UpdateValidationFailedException {
+ checkNotNull(dataAfter.getMtu(), "MTU cannot be null");
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/GreCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/GreCustomizer.java
new file mode 100644
index 000000000..adb7e2401
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/GreCustomizer.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2016 Intel 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.v3po.write;
+
+import io.fd.hc2vpp.common.translate.util.AbstractInterfaceTypeCustomizer;
+import io.fd.hc2vpp.common.translate.util.AddressTranslator;
+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.jvpp.core.dto.GreTunnelAddDel;
+import io.fd.jvpp.core.dto.GreTunnelAddDelReply;
+import io.fd.jvpp.core.future.FutureJVppCore;
+import java.util.concurrent.CompletionStage;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.GreTunnel;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Gre;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.InterfaceType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class GreCustomizer extends AbstractInterfaceTypeCustomizer<Gre> implements JvppReplyConsumer {
+
+ private static final Logger LOG = LoggerFactory.getLogger(GreCustomizer.class);
+ private final NamingContext interfaceContext;
+
+ public GreCustomizer(final FutureJVppCore vppApi, final NamingContext interfaceContext) {
+ super(vppApi);
+ this.interfaceContext = interfaceContext;
+ }
+
+ private static GreTunnelAddDel getGreTunnelRequest(final byte isAdd, final IpAddressNoZone srcAddr,
+ final IpAddressNoZone dstAddr, final int outerFibId,
+ final byte isIpv6) {
+ final GreTunnelAddDel greTunnelAddDel = new GreTunnelAddDel();
+ greTunnelAddDel.isAdd = isAdd;
+ greTunnelAddDel.tunnel = new io.fd.jvpp.core.types.GreTunnel();
+ if (isIpv6==0) {
+ greTunnelAddDel.tunnel.src =
+ AddressTranslator.INSTANCE.ipv4AddressNoZoneToAddress(srcAddr.getIpv4AddressNoZone());
+ greTunnelAddDel.tunnel.dst =
+ AddressTranslator.INSTANCE.ipv4AddressNoZoneToAddress(dstAddr.getIpv4AddressNoZone());
+ } else {
+ greTunnelAddDel.tunnel.src =
+ AddressTranslator.INSTANCE.ipv6AddressToAddress(srcAddr.getIpv6AddressNoZone());
+ greTunnelAddDel.tunnel.dst =
+ AddressTranslator.INSTANCE.ipv6AddressToAddress(dstAddr.getIpv6AddressNoZone());
+ }
+ greTunnelAddDel.tunnel.outerFibId = outerFibId;
+ greTunnelAddDel.tunnel.isIpv6 = isIpv6;
+ return greTunnelAddDel;
+ }
+
+ @Override
+ protected Class<? extends InterfaceType> getExpectedInterfaceType() {
+ return GreTunnel.class;
+ }
+
+ @Override
+ protected final void writeInterface(@Nonnull final InstanceIdentifier<Gre> id, @Nonnull final Gre dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ final String swIfName = id.firstKeyOf(Interface.class).getName();
+
+ createGreTunnel(id, swIfName, dataAfter, writeContext);
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Gre> id, @Nonnull final Gre dataBefore,
+ @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ final String swIfName = id.firstKeyOf(Interface.class).getName();
+ deleteGreTunnel(id, swIfName, dataBefore, writeContext);
+ }
+
+ private void createGreTunnel(final InstanceIdentifier<Gre> id, final String swIfName, final Gre gre,
+ final WriteContext writeContext) throws WriteFailedException {
+ final byte isIpv6 = (byte) (isIpv6(gre)
+ ? 1
+ : 0);
+ int outerFibId = gre.getOuterFibId().intValue();
+
+ LOG.debug("Setting gre tunnel for interface: {}. Gre: {}", swIfName, gre);
+ final CompletionStage<GreTunnelAddDelReply> greAddDelTunnelReplyCompletionStage =
+ getFutureJVpp().greTunnelAddDel(getGreTunnelRequest((byte) 1 /* is add */, gre.getSrc(),
+ gre.getDst(), outerFibId, isIpv6));
+
+ final GreTunnelAddDelReply reply =
+ getReplyForCreate(greAddDelTunnelReplyCompletionStage.toCompletableFuture(), id, gre);
+ LOG.debug("Gre tunnel set successfully for: {}, gre: {}", swIfName, gre);
+ if (interfaceContext.containsName(reply.swIfIndex, writeContext.getMappingContext())) {
+ // VPP keeps gre tunnels present even after they are delete(reserving ID for next tunnel)
+ // This may cause inconsistencies in mapping context when configuring tunnels like this:
+ // 1. Add tunnel 2. Delete tunnel 3. Read interfaces (reserved mapping e.g. gre_tunnel0 -> 6
+ // will get into mapping context) 4. Add tunnel (this will add another mapping with the same
+ // reserved ID and context is invalid)
+ // That's why a check has to be performed here removing mapping gre_tunnel0 -> 6 mapping and storing
+ // new name for that ID
+ final String formerName = interfaceContext.getName(reply.swIfIndex, writeContext.getMappingContext());
+ LOG.debug("Removing updated mapping of a gre tunnel, id: {}, former name: {}, new name: {}",
+ reply.swIfIndex, formerName, swIfName);
+ interfaceContext.removeName(formerName, writeContext.getMappingContext());
+ }
+ // Add new interface to our interface context
+ interfaceContext.addName(reply.swIfIndex, swIfName, writeContext.getMappingContext());
+ }
+
+ private boolean isIpv6(final Gre gre) {
+ return gre.getSrc().getIpv4AddressNoZone() == null;
+ }
+
+ private void deleteGreTunnel(final InstanceIdentifier<Gre> id, final String swIfName, final Gre gre,
+ final WriteContext writeContext) throws WriteFailedException {
+ final byte isIpv6 = (byte) (isIpv6(gre)
+ ? 1
+ : 0);
+
+ int outerFibId = gre.getOuterFibId().intValue();
+
+ LOG.debug("Deleting gre tunnel for interface: {}. Gre: {}", swIfName, gre);
+ final CompletionStage<GreTunnelAddDelReply> greAddDelTunnelReplyCompletionStage =
+ getFutureJVpp().greTunnelAddDel(getGreTunnelRequest((byte) 0 /* is add */, gre.getSrc(),
+ gre.getDst(), outerFibId, isIpv6));
+
+ getReplyForDelete(greAddDelTunnelReplyCompletionStage.toCompletableFuture(), id);
+ LOG.debug("Gre tunnel deleted successfully for: {}, gre: {}", swIfName, gre);
+ // Remove interface from our interface context
+ interfaceContext.removeName(swIfName, writeContext.getMappingContext());
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/GreValidator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/GreValidator.java
new file mode 100644
index 000000000..df487fde8
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/GreValidator.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2019 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.v3po.write;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.DataValidationFailedException;
+import io.fd.honeycomb.translate.write.Validator;
+import io.fd.honeycomb.translate.write.WriteContext;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Gre;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class GreValidator implements Validator<Gre> {
+
+ public GreValidator(final NamingContext interfaceContext) {
+ checkNotNull(interfaceContext, "interfaceContext should not be null");
+ }
+
+ @Override
+ public void validateWrite(@Nonnull final InstanceIdentifier<Gre> id, @Nonnull final Gre dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.CreateValidationFailedException {
+ try {
+ validateGre(dataAfter);
+ } catch (Exception e) {
+ throw new DataValidationFailedException.CreateValidationFailedException(id, dataAfter, e);
+ }
+ }
+
+ @Override
+ public void validateDelete(@Nonnull final InstanceIdentifier<Gre> id, @Nonnull final Gre dataBefore,
+ @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.DeleteValidationFailedException {
+ try {
+ validateGre(dataBefore);
+ } catch (Exception e) {
+ throw new DataValidationFailedException.DeleteValidationFailedException(id, e);
+ }
+ }
+
+ private void validateGre(final Gre data) {
+ checkNotNull(data.getOuterFibId(), "Outer Fib ID cannot be null");
+ checkNotNull(data.getSrc(), "Source cannot be null");
+ checkNotNull(data.getDst(), "Destination cannot be null");
+ if (data.getSrc().getIpv4AddressNoZone() == null) {
+ checkArgument(data.getDst().getIpv4AddressNoZone() == null, "Inconsistent ip addresses: %s, %s",
+ data.getSrc(),
+ data.getDst());
+ } else {
+ checkArgument(data.getDst().getIpv6AddressNoZone() == null, "Inconsistent ip addresses: %s, %s",
+ data.getSrc(),
+ data.getDst());
+ }
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/InterconnectionWriteUtils.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/InterconnectionWriteUtils.java
new file mode 100644
index 000000000..b93168496
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/InterconnectionWriteUtils.java
@@ -0,0 +1,159 @@
+/*
+ * 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.v3po.write;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
+
+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.jvpp.core.dto.SwInterfaceSetL2Bridge;
+import io.fd.jvpp.core.dto.SwInterfaceSetL2BridgeReply;
+import io.fd.jvpp.core.dto.SwInterfaceSetL2Xconnect;
+import io.fd.jvpp.core.dto.SwInterfaceSetL2XconnectReply;
+import io.fd.jvpp.core.future.FutureJVppCore;
+import io.fd.jvpp.core.types.L2PortType;
+import java.util.concurrent.CompletionStage;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.l2.config.attributes.Interconnection;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.l2.config.attributes.interconnection.BridgeBased;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.l2.config.attributes.interconnection.XconnectBased;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Utility class providing Interconnection CUD support.
+ */
+final class InterconnectionWriteUtils implements JvppReplyConsumer {
+
+ private static final Logger LOG = LoggerFactory.getLogger(InterconnectionWriteUtils.class);
+
+ private final FutureJVppCore futureJVppCore;
+ private final NamingContext interfaceContext;
+ private final NamingContext bridgeDomainContext;
+
+ InterconnectionWriteUtils(@Nonnull final FutureJVppCore futureJVppCore,
+ @Nonnull final NamingContext interfaceContext,
+ @Nonnull final NamingContext bridgeDomainContext) {
+ this.futureJVppCore = requireNonNull(futureJVppCore, "futureJVppCore should not be null");
+ this.interfaceContext = requireNonNull(interfaceContext, "interfaceContext should not be null");
+ this.bridgeDomainContext = requireNonNull(bridgeDomainContext, "bridgeDomainContext should not be null");
+ }
+
+ void setInterconnection(final InstanceIdentifier<? extends DataObject> id, final int swIfIndex,
+ final String ifcName, final Interconnection ic, final WriteContext writeContext)
+ throws WriteFailedException {
+
+ if (ic == null) { // TODO in case of update we should delete interconnection
+ LOG.trace("Interconnection is not set. Skipping");
+ } else if (ic instanceof XconnectBased) {
+ setXconnectBasedL2(id, swIfIndex, ifcName, (XconnectBased) ic, writeContext, (byte) 1 /*enable*/);
+ } else if (ic instanceof BridgeBased) {
+ setBridgeBasedL2(id, swIfIndex, ifcName, (BridgeBased) ic, writeContext, (byte) 1 /*enable*/);
+ } else {
+ // Choices&cases are not data objects, so they cannot have a dedicated Reader/Writer
+ // This choice is already from augment, so its not possible to augment augmented choice
+ LOG.error("Unable to handle Interconnection of type {}", ic.getClass());
+ throw new WriteFailedException(id, "Unable to handle Interconnection of type " + ic.getClass());
+ }
+ }
+
+ void deleteInterconnection(final InstanceIdentifier<? extends DataObject> id, final int swIfIndex,
+ final String ifcName, final Interconnection ic, final WriteContext writeContext)
+ throws WriteFailedException {
+
+ if (ic == null) { // TODO in case of update we should delete interconnection
+ LOG.trace("Interconnection is not set. Skipping");
+ } else if (ic instanceof XconnectBased) {
+ setXconnectBasedL2(id, swIfIndex, ifcName, (XconnectBased) ic, writeContext, (byte) 0 /*disable*/);
+ } else if (ic instanceof BridgeBased) {
+ setBridgeBasedL2(id, swIfIndex, ifcName, (BridgeBased) ic, writeContext, (byte) 0 /*disable*/);
+ } else {
+ LOG.error("Unable to delete Interconnection of type {}", ic.getClass());
+ throw new WriteFailedException(id, "Unable to delete Interconnection of type " + ic.getClass());
+ }
+ }
+
+ private void setBridgeBasedL2(final InstanceIdentifier<? extends DataObject> id, final int swIfIndex,
+ final String ifcName, final BridgeBased bb,
+ final WriteContext writeContext, final byte enabled) throws WriteFailedException {
+ LOG.debug("Setting bridge based interconnection(bridge-domain={}) for interface: {}", bb.getBridgeDomain(),
+ ifcName);
+
+ String bdName = bb.getBridgeDomain();
+
+ int bdId = bridgeDomainContext.getIndex(bdName, writeContext.getMappingContext());
+ checkArgument(bdId > 0, "Unable to set Interconnection for Interface: %s, bridge domain: %s does not exist",
+ ifcName, bdName);
+
+ byte shg = 0;
+ if (bb.getSplitHorizonGroup() != null) {
+ shg = bb.getSplitHorizonGroup().byteValue();
+ }
+
+ final CompletionStage<SwInterfaceSetL2BridgeReply> swInterfaceSetL2BridgeReplyCompletionStage = futureJVppCore
+ .swInterfaceSetL2Bridge(getL2BridgeRequest(swIfIndex, bdId, shg, bb.isBridgedVirtualInterface(), enabled));
+ getReplyForWrite(swInterfaceSetL2BridgeReplyCompletionStage.toCompletableFuture(), id);
+
+ LOG.debug("Bridge based interconnection updated successfully for: {}, interconnection: {}", ifcName, bb);
+ }
+
+ private SwInterfaceSetL2Bridge getL2BridgeRequest(final int swIfIndex, final int bdId, final byte shg,
+ final Boolean bvi, final byte enabled) {
+ final SwInterfaceSetL2Bridge swInterfaceSetL2Bridge = new SwInterfaceSetL2Bridge();
+ swInterfaceSetL2Bridge.rxSwIfIndex = swIfIndex;
+ swInterfaceSetL2Bridge.bdId = bdId;
+ swInterfaceSetL2Bridge.shg = shg;
+
+ // TODO HC2VPP-389: add support for unknown unicast type
+ swInterfaceSetL2Bridge.portType = bvi ? L2PortType.L2_API_PORT_TYPE_BVI : L2PortType.L2_API_PORT_TYPE_NORMAL;
+ swInterfaceSetL2Bridge.enable = enabled;
+ return swInterfaceSetL2Bridge;
+ }
+
+ private void setXconnectBasedL2(final InstanceIdentifier<? extends DataObject> id, final int swIfIndex,
+ final String ifcName, final XconnectBased ic,
+ final WriteContext writeContext, final byte enabled) throws WriteFailedException {
+ String outSwIfName = ic.getXconnectOutgoingInterface();
+ LOG.debug("Setting xconnect based interconnection(outgoing ifc={}) for interface: {}", outSwIfName, ifcName);
+
+ int outSwIfIndex = interfaceContext.getIndex(outSwIfName, writeContext.getMappingContext());
+ checkArgument(outSwIfIndex > 0,
+ "Unable to set Interconnection for Interface: %s, outgoing interface: %s does not exist",
+ ifcName, outSwIfIndex);
+
+ final CompletionStage<SwInterfaceSetL2XconnectReply> swInterfaceSetL2XconnectReplyCompletionStage =
+ futureJVppCore
+ .swInterfaceSetL2Xconnect(getL2XConnectRequest(swIfIndex, outSwIfIndex, enabled));
+ getReplyForWrite(swInterfaceSetL2XconnectReplyCompletionStage.toCompletableFuture(), id);
+ LOG.debug("Xconnect based interconnection updated successfully for: {}, interconnection: {}", ifcName, ic);
+ }
+
+ private SwInterfaceSetL2Xconnect getL2XConnectRequest(final int rxIfc, final int txIfc,
+ final byte enabled) {
+
+ final SwInterfaceSetL2Xconnect swInterfaceSetL2Xconnect = new SwInterfaceSetL2Xconnect();
+ swInterfaceSetL2Xconnect.enable = enabled;
+ swInterfaceSetL2Xconnect.rxSwIfIndex = rxIfc;
+ swInterfaceSetL2Xconnect.txSwIfIndex = txIfc;
+ return swInterfaceSetL2Xconnect;
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/InterfaceCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/InterfaceCustomizer.java
new file mode 100644
index 000000000..147575bb1
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/InterfaceCustomizer.java
@@ -0,0 +1,124 @@
+/*
+ * 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.v3po.write;
+
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer;
+import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.jvpp.core.dto.SwInterfaceSetFlags;
+import io.fd.jvpp.core.dto.SwInterfaceSetFlagsReply;
+import io.fd.jvpp.core.future.FutureJVppCore;
+import java.util.concurrent.CompletionStage;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Ietf interface write customizer that only caches interface objects for child writers
+ */
+public class InterfaceCustomizer extends FutureJVppCustomizer
+ implements ListWriterCustomizer<Interface, InterfaceKey>, JvppReplyConsumer {
+
+ private static final Logger LOG = LoggerFactory.getLogger(InterfaceCustomizer.class);
+ private static final String LOCAL0_NAME = "local0";
+
+ private final NamingContext interfaceContext;
+
+ public InterfaceCustomizer(final FutureJVppCore vppApi, final NamingContext interfaceContext) {
+ super(vppApi);
+ this.interfaceContext = interfaceContext;
+ }
+
+ @Override
+ public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Interface> id,
+ @Nonnull final Interface dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+
+ setInterface(id, dataAfter, writeContext);
+ }
+
+ @Override
+ public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<Interface> id,
+ @Nonnull final Interface dataBefore,
+ @Nonnull final Interface dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ updateInterface(id, dataAfter, writeContext);
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Interface> id,
+ @Nonnull final Interface dataBefore,
+ @Nonnull final WriteContext writeContext)
+ throws WriteFailedException.DeleteFailedException {
+ // Special handling for local0 interface (HC2VPP-308):
+ if (LOCAL0_NAME.equals(dataBefore.getName())) {
+ throw new WriteFailedException.DeleteFailedException(id,
+ new UnsupportedOperationException("Removing " + LOCAL0_NAME + " interface is not supported"));
+ }
+ // For other interfaces, delegate delete to customizers for specific interface types (e.g. VXLan, Tap).
+ }
+
+ private void setInterface(final InstanceIdentifier<Interface> id, final Interface swIf,
+ final WriteContext writeContext) throws WriteFailedException {
+ LOG.debug("Setting interface: {} to: {}", id, swIf);
+ setInterfaceAttributes(id, swIf, swIf.getName(), writeContext);
+ }
+
+ private void setInterfaceAttributes(final InstanceIdentifier<Interface> id, final Interface swIf,
+ final String swIfName, final WriteContext writeContext)
+ throws WriteFailedException {
+
+ setInterfaceFlags(id, swIfName, interfaceContext.getIndex(swIfName, writeContext.getMappingContext()),
+ swIf.isEnabled()
+ ? (byte) 1
+ : (byte) 0);
+ }
+
+ private void updateInterface(final InstanceIdentifier<Interface> id,
+ final Interface dataAfter, final WriteContext writeContext)
+ throws WriteFailedException {
+ LOG.debug("Updating interface:{} to: {}", id, dataAfter);
+ setInterfaceAttributes(id, dataAfter, dataAfter.getName(), writeContext);
+ }
+
+ private void setInterfaceFlags(final InstanceIdentifier<Interface> id, final String swIfName, final int swIfIndex,
+ final byte enabled) throws WriteFailedException {
+ final CompletionStage<SwInterfaceSetFlagsReply> swInterfaceSetFlagsReplyFuture =
+ getFutureJVpp().swInterfaceSetFlags(getSwInterfaceSetFlagsInput(swIfIndex, enabled));
+
+ LOG.debug("Updating interface flags for: {}, index: {}, enabled: {}", swIfName, swIfIndex, enabled);
+
+ getReplyForWrite(swInterfaceSetFlagsReplyFuture.toCompletableFuture(), id);
+ LOG.debug("Interface flags updated successfully for: {}, index: {}, enabled: {}",
+ swIfName, swIfIndex, enabled);
+ }
+
+ private SwInterfaceSetFlags getSwInterfaceSetFlagsInput(final int swIfIndex, final byte enabled) {
+ final SwInterfaceSetFlags swInterfaceSetFlags = new SwInterfaceSetFlags();
+ swInterfaceSetFlags.swIfIndex = swIfIndex;
+ swInterfaceSetFlags.adminUpDown = enabled;
+ return swInterfaceSetFlags;
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/InterfaceRoutingCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/InterfaceRoutingCustomizer.java
new file mode 100644
index 000000000..51d15e348
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/InterfaceRoutingCustomizer.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017 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.v3po.write;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.spi.write.WriterCustomizer;
+import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.jvpp.core.future.FutureJVppCore;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Routing;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class InterfaceRoutingCustomizer extends RoutingCustomizer
+ implements WriterCustomizer<Routing> {
+
+ public InterfaceRoutingCustomizer(@Nonnull final FutureJVppCore vppApi,
+ @Nonnull final NamingContext interfaceContext) {
+ super(vppApi, interfaceContext);
+ }
+
+ @Override
+ public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Routing> id,
+ @Nonnull final Routing dataAfter, @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ final String ifName = id.firstKeyOf(Interface.class).getName();
+ setRouting(id, ifName, dataAfter, writeContext);
+ }
+
+ @Override
+ public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<Routing> id,
+ @Nonnull final Routing dataBefore, @Nonnull final Routing dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ final String ifName = id.firstKeyOf(Interface.class).getName();
+ setRouting(id, ifName, dataAfter, writeContext);
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Routing> id,
+ @Nonnull final Routing dataBefore, @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ final String ifName = id.firstKeyOf(Interface.class).getName();
+ disableRouting(id, ifName, writeContext);
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/InterfaceRoutingValidator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/InterfaceRoutingValidator.java
new file mode 100644
index 000000000..608bda3fa
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/InterfaceRoutingValidator.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * 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.v3po.write;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.util.RWUtils;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.CreateValidationFailedException;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.DeleteValidationFailedException;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.UpdateValidationFailedException;
+import io.fd.honeycomb.translate.write.Validator;
+import io.fd.honeycomb.translate.write.WriteContext;
+import java.util.List;
+import java.util.Optional;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.RoutingBaseAttributes;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Routing;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev180222.Interface1;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev180222.interfaces._interface.Ipv4;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev180222.interfaces._interface.Ipv6;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class InterfaceRoutingValidator implements Validator<Routing> {
+
+ public InterfaceRoutingValidator(@Nonnull final NamingContext interfaceContext) {
+ checkNotNull(interfaceContext, "interfaceContext should not be null");
+ }
+
+ @Override
+ public void validateWrite(@Nonnull final InstanceIdentifier<Routing> id, @Nonnull final Routing dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws CreateValidationFailedException {
+ try {
+ checkVrfIds(dataAfter);
+ checkInterfaceAddressConf(id, writeContext, true);
+ } catch (Exception e) {
+ throw new CreateValidationFailedException(id, dataAfter, e);
+ }
+ }
+
+ @Override
+ public void validateUpdate(@Nonnull final InstanceIdentifier<Routing> id, @Nonnull final Routing dataBefore,
+ @Nonnull final Routing dataAfter, @Nonnull final WriteContext writeContext)
+ throws UpdateValidationFailedException {
+ try {
+ checkVrfIds(dataAfter);
+ checkInterfaceAddressConf(id, writeContext, true);
+ } catch (Exception e) {
+ throw new UpdateValidationFailedException(id, dataBefore, dataAfter, e);
+ }
+ }
+
+ @Override
+ public void validateDelete(@Nonnull final InstanceIdentifier<Routing> id, @Nonnull final Routing dataBefore,
+ @Nonnull final WriteContext writeContext)
+ throws DeleteValidationFailedException {
+ try {
+ checkVrfIds(dataBefore);
+ checkInterfaceAddressConf(id, writeContext, false);
+ } catch (Exception e) {
+ throw new DeleteValidationFailedException(id, e);
+ }
+ }
+
+ private void checkVrfIds(final RoutingBaseAttributes data) {
+ checkArgument(data.getIpv4VrfId() != null || data.getIpv6VrfId() != null, "No vrf-id given");
+ }
+
+ private void checkInterfaceAddressConf(@Nonnull final InstanceIdentifier<Routing> id,
+ @Nonnull final WriteContext ctx,
+ boolean checkBefore) {
+ checkState(isAddressNotPresentForInterface(id, ctx, checkBefore),
+ "Cannot change routing configuration, if address is present for interface");
+ }
+
+ /**
+ * Returns true if interface does not have v4/v6 addresses configured
+ */
+ private boolean isAddressNotPresentForInterface(@Nonnull final InstanceIdentifier<Routing> id,
+ @Nonnull final WriteContext ctx,
+ boolean checkBefore) {
+ final Optional<Interface> interfaceData = checkBefore
+ ? ctx.readBefore(RWUtils.cutId(id, Interface.class))
+ : ctx.readAfter(RWUtils.cutId(id, Interface.class));
+
+ if (interfaceData.isPresent()) {
+ final java.util.Optional<Interface1> augData = java.util.Optional.of(interfaceData.get())
+ .map(iface -> iface.augmentation(Interface1.class));
+
+ final boolean v4NotPresent =
+ augData.map(Interface1::getIpv4).map(Ipv4::getAddress).map(List::isEmpty).orElse(true);
+
+ final boolean v6NotPresent =
+ augData.map(Interface1::getIpv6).map(Ipv6::getAddress).map(List::isEmpty).orElse(true);
+
+ return v4NotPresent && v6NotPresent;
+ }
+ return true;
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/InterfaceUnnumberedCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/InterfaceUnnumberedCustomizer.java
new file mode 100644
index 000000000..a6eada50a
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/InterfaceUnnumberedCustomizer.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2017 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.v3po.write;
+
+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.jvpp.core.future.FutureJVppCore;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.unnumbered.interfaces.rev180103.unnumbered.config.attributes.Unnumbered;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public final class InterfaceUnnumberedCustomizer extends AbstractUnnumberedCustomizer {
+
+ public InterfaceUnnumberedCustomizer(@Nonnull final FutureJVppCore futureJVppCore,
+ @Nonnull final NamingContext interfaceContext) {
+ super(futureJVppCore, interfaceContext);
+ }
+
+ @Override
+ public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Unnumbered> id,
+ @Nonnull final Unnumbered dataAfter,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ setUnnumbered(id, id.firstKeyOf(Interface.class).getName(), dataAfter, writeContext);
+ }
+
+ @Override
+ public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<Unnumbered> id,
+ @Nonnull final Unnumbered dataBefore, @Nonnull final Unnumbered dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ setUnnumbered(id, id.firstKeyOf(Interface.class).getName(), dataAfter, writeContext);
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Unnumbered> id,
+ @Nonnull final Unnumbered dataBefore,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ disableUnnumbered(id, id.firstKeyOf(Interface.class).getName(), dataBefore, writeContext);
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/InterfaceUnnumberedValidator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/InterfaceUnnumberedValidator.java
new file mode 100644
index 000000000..19f115119
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/InterfaceUnnumberedValidator.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2019 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.v3po.write;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.DataValidationFailedException;
+import io.fd.honeycomb.translate.write.Validator;
+import io.fd.honeycomb.translate.write.WriteContext;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.unnumbered.interfaces.rev180103.unnumbered.config.attributes.Unnumbered;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class InterfaceUnnumberedValidator implements Validator<Unnumbered> {
+
+ public InterfaceUnnumberedValidator(final NamingContext interfaceContext) {
+ checkNotNull(interfaceContext, "interfaceContext should not be null");
+ }
+
+ @Override
+ public void validateWrite(@Nonnull final InstanceIdentifier<Unnumbered> id, @Nonnull final Unnumbered dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.CreateValidationFailedException {
+ checkNotNull(dataAfter.getUse(), "Use cannot be null");
+ }
+
+ @Override
+ public void validateUpdate(@Nonnull final InstanceIdentifier<Unnumbered> id, @Nonnull final Unnumbered dataBefore,
+ @Nonnull final Unnumbered dataAfter, @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.UpdateValidationFailedException {
+ checkNotNull(dataAfter.getUse(), "Use cannot be null");
+ }
+
+ @Override
+ public void validateDelete(@Nonnull final InstanceIdentifier<Unnumbered> id, @Nonnull final Unnumbered dataBefore,
+ @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.DeleteValidationFailedException {
+ checkNotNull(dataBefore.getUse(), "Use cannot be null");
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/InterfaceValidator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/InterfaceValidator.java
new file mode 100644
index 000000000..59acbd7af
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/InterfaceValidator.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2019 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.v3po.write;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.CreateValidationFailedException;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.DeleteValidationFailedException;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.UpdateValidationFailedException;
+import io.fd.honeycomb.translate.write.Validator;
+import io.fd.honeycomb.translate.write.WriteContext;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class InterfaceValidator implements Validator<Interface> {
+
+ public InterfaceValidator(final NamingContext interfaceContext) {
+ checkNotNull(interfaceContext, "interfaceContext should not be null");
+ }
+
+ @Override
+ public void validateWrite(@Nonnull final InstanceIdentifier<Interface> id, @Nonnull final Interface dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws CreateValidationFailedException {
+ try {
+ checkInterface(dataAfter);
+ } catch (Exception e) {
+ throw new CreateValidationFailedException(id, dataAfter, e);
+ }
+ }
+
+ @Override
+ public void validateUpdate(@Nonnull final InstanceIdentifier<Interface> id, @Nonnull final Interface dataBefore,
+ @Nonnull final Interface dataAfter, @Nonnull final WriteContext writeContext)
+ throws UpdateValidationFailedException {
+ try {
+ checkInterface(dataAfter);
+ } catch (Exception e) {
+ throw new UpdateValidationFailedException(id, dataBefore, dataAfter, e);
+ }
+ }
+
+ @Override
+ public void validateDelete(@Nonnull final InstanceIdentifier<Interface> id, @Nonnull final Interface dataBefore,
+ @Nonnull final WriteContext writeContext)
+ throws DeleteValidationFailedException {
+ try {
+ checkInterface(dataBefore);
+ } catch (Exception e) {
+ throw new DeleteValidationFailedException(id, e);
+ }
+ }
+
+ private void checkInterface(final Interface data) {
+ checkNotNull(data.isEnabled(), "Enabled tag cannot be null");
+ checkNotNull(data.getName(), "Name cannot be null");
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/InterfacesStatisticsCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/InterfacesStatisticsCustomizer.java
new file mode 100644
index 000000000..ca22aa5ea
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/InterfacesStatisticsCustomizer.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * 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.v3po.write;
+
+import io.fd.hc2vpp.v3po.read.cache.InterfaceStatisticsManager;
+import io.fd.honeycomb.translate.spi.write.WriterCustomizer;
+import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces.Statistics;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class InterfacesStatisticsCustomizer implements WriterCustomizer<Statistics> {
+
+ private final InterfaceStatisticsManager statisticsManager;
+
+ public InterfacesStatisticsCustomizer(final InterfaceStatisticsManager statisticsManager) {
+ this.statisticsManager = statisticsManager;
+ }
+
+ @Override
+ public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Statistics> instanceIdentifier,
+ @Nonnull final Statistics statisticsCollection,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ enableDisableStatistics(statisticsCollection);
+ }
+
+ @Override
+ public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<Statistics> id,
+ @Nonnull final Statistics dataBefore,
+ @Nonnull final Statistics dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ enableDisableStatistics(dataAfter);
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Statistics> instanceIdentifier,
+ @Nonnull final Statistics statisticsCollection,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ statisticsManager.disableStatistics();
+ }
+
+ private void enableDisableStatistics(final Statistics statsCollect) {
+ if (statsCollect != null) {
+ if (statsCollect.isEnabled()) {
+ statisticsManager.enableStatistics();
+ return;
+ }
+ }
+ statisticsManager.disableStatistics();
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/InterfacesStatisticsValidator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/InterfacesStatisticsValidator.java
new file mode 100644
index 000000000..06c532842
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/InterfacesStatisticsValidator.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * 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.v3po.interfaces;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.hc2vpp.v3po.read.cache.InterfaceStatisticsManager;
+import io.fd.honeycomb.translate.write.DataValidationFailedException;
+import io.fd.honeycomb.translate.write.Validator;
+import io.fd.honeycomb.translate.write.WriteContext;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces.Statistics;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class InterfacesStatisticsValidator implements Validator<Statistics> {
+
+ public InterfacesStatisticsValidator(final InterfaceStatisticsManager statisticsManager) {
+ checkNotNull(statisticsManager, "Statistics Collection Manager should not be null");
+ }
+
+ @Override
+ public void validateWrite(@Nonnull final InstanceIdentifier<Statistics> id, @Nonnull final Statistics dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.CreateValidationFailedException {
+ // there is nothing to validate yet
+ }
+
+ @Override
+ public void validateUpdate(@Nonnull final InstanceIdentifier<Statistics> id, @Nonnull final Statistics dataBefore,
+ @Nonnull final Statistics dataAfter, @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.UpdateValidationFailedException {
+ // there is nothing to validate yet
+ }
+
+ @Override
+ public void validateDelete(@Nonnull final InstanceIdentifier<Statistics> id, @Nonnull final Statistics dataBefore,
+ @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.DeleteValidationFailedException {
+ // there is nothing to validate yet
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/L2Customizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/L2Customizer.java
new file mode 100644
index 000000000..cbceea36f
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/L2Customizer.java
@@ -0,0 +1,89 @@
+/*
+ * 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.v3po.write;
+
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.spi.write.WriterCustomizer;
+import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.jvpp.core.future.FutureJVppCore;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.L2;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class L2Customizer extends FutureJVppCustomizer implements WriterCustomizer<L2> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(L2Customizer.class);
+ private final NamingContext interfaceContext;
+ private final InterconnectionWriteUtils icWriteUtils;
+
+ public L2Customizer(final FutureJVppCore vppApi, final NamingContext interfaceContext,
+ final NamingContext bridgeDomainContext) {
+ super(vppApi);
+ this.interfaceContext = interfaceContext;
+ this.icWriteUtils = new InterconnectionWriteUtils(vppApi, interfaceContext, bridgeDomainContext);
+ }
+
+ @Override
+ public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<L2> id, @Nonnull final L2 dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+
+ final String ifcName = id.firstKeyOf(Interface.class).getName();
+ final int swIfc = interfaceContext.getIndex(ifcName, writeContext.getMappingContext());
+ setL2(id, swIfc, ifcName, dataAfter, writeContext);
+ }
+
+ @Override
+ public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<L2> id, @Nonnull final L2 dataBefore,
+ @Nonnull final L2 dataAfter, @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+
+ final String ifcName = id.firstKeyOf(Interface.class).getName();
+ final int swIfc = interfaceContext.getIndex(ifcName, writeContext.getMappingContext());
+ // No update, again calling set
+ setL2(id, swIfc, ifcName, dataAfter, writeContext);
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<L2> id, @Nonnull final L2 dataBefore,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ final String ifcName = id.firstKeyOf(Interface.class).getName();
+ final int swIfc = interfaceContext.getIndex(ifcName, writeContext.getMappingContext());
+ deleteL2(id, swIfc, ifcName, dataBefore, writeContext);
+ }
+
+ private void setL2(final InstanceIdentifier<L2> id, final int swIfIndex, final String ifcName, final L2 l2,
+ final WriteContext writeContext)
+ throws WriteFailedException {
+ LOG.debug("Setting L2 for interface: {}", ifcName);
+ // Nothing besides interconnection here
+ icWriteUtils.setInterconnection(id, swIfIndex, ifcName, l2.getInterconnection(), writeContext);
+ }
+
+ private void deleteL2(final InstanceIdentifier<L2> id, final int swIfIndex, final String ifcName, final L2 l2Before,
+ final WriteContext writeContext)
+ throws WriteFailedException {
+ LOG.debug("Deleting L2 for interface: {}", ifcName);
+ // Nothing besides interconnection here
+ icWriteUtils.deleteInterconnection(id, swIfIndex, ifcName, l2Before.getInterconnection(), writeContext);
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/L2Validator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/L2Validator.java
new file mode 100644
index 000000000..1dedf3817
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/L2Validator.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2019 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.v3po.write;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.DataValidationFailedException;
+import io.fd.honeycomb.translate.write.Validator;
+import io.fd.honeycomb.translate.write.WriteContext;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.L2;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class L2Validator implements Validator<L2> {
+
+ public L2Validator(final NamingContext interfaceContext,
+ final NamingContext bridgeDomainContext) {
+ checkNotNull(interfaceContext, "interfaceContext should not be null");
+ checkNotNull(bridgeDomainContext, "bridgeDomainContext should not be null");
+ }
+
+ @Override
+ public void validateWrite(@Nonnull final InstanceIdentifier<L2> id, @Nonnull final L2 dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.CreateValidationFailedException {
+ // there is nothing to validate yet
+ }
+
+ @Override
+ public void validateUpdate(@Nonnull final InstanceIdentifier<L2> id, @Nonnull final L2 dataBefore,
+ @Nonnull final L2 dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.UpdateValidationFailedException {
+ // there is nothing to validate yet
+ }
+
+ @Override
+ public void validateDelete(@Nonnull final InstanceIdentifier<L2> id, @Nonnull final L2 dataBefore,
+ @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.DeleteValidationFailedException {
+ // there is nothing to validate yet
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/LoopbackCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/LoopbackCustomizer.java
new file mode 100644
index 000000000..0be934598
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/LoopbackCustomizer.java
@@ -0,0 +1,104 @@
+/*
+ * 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.v3po.write;
+
+import io.fd.hc2vpp.common.translate.util.AbstractInterfaceTypeCustomizer;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.hc2vpp.common.translate.util.MacTranslator;
+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.jvpp.core.dto.CreateLoopback;
+import io.fd.jvpp.core.dto.CreateLoopbackReply;
+import io.fd.jvpp.core.dto.DeleteLoopback;
+import io.fd.jvpp.core.future.FutureJVppCore;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Loopback;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.InterfaceType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class LoopbackCustomizer extends AbstractInterfaceTypeCustomizer<Loopback>
+ implements MacTranslator, JvppReplyConsumer {
+
+ private static final Logger LOG = LoggerFactory.getLogger(LoopbackCustomizer.class);
+ private final NamingContext interfaceContext;
+
+ public LoopbackCustomizer(final FutureJVppCore vppApi, final NamingContext interfaceContext) {
+ super(vppApi);
+ this.interfaceContext = interfaceContext;
+ }
+
+ @Override
+ protected Class<? extends InterfaceType> getExpectedInterfaceType() {
+ return org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.Loopback.class;
+ }
+
+ @Override
+ protected final void writeInterface(@Nonnull final InstanceIdentifier<Loopback> id, @Nonnull final Loopback dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ final String ifcName = id.firstKeyOf(Interface.class).getName();
+ createLoopback(id, ifcName, dataAfter, writeContext);
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Loopback> id, @Nonnull final Loopback dataBefore,
+ @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ final String ifcName = id.firstKeyOf(Interface.class).getName();
+
+ final int index;
+ try {
+ index = interfaceContext.getIndex(ifcName, writeContext.getMappingContext());
+ } catch (IllegalArgumentException e) {
+ throw new WriteFailedException.DeleteFailedException(id, e);
+ }
+
+ deleteLoopback(id, ifcName, index, dataBefore, writeContext);
+ }
+
+ private void createLoopback(final InstanceIdentifier<Loopback> id, final String swIfName, final Loopback loopback,
+ final WriteContext writeContext) throws WriteFailedException {
+ LOG.debug("Setting loopback interface: {}. Loopback: {}", swIfName, loopback);
+
+ final CreateLoopback createLoopback = new CreateLoopback();
+ if (loopback.getMac() != null) {
+ createLoopback.macAddress = parseMac(loopback.getMac().getValue());
+ }
+ final CreateLoopbackReply reply =
+ getReplyForCreate(getFutureJVpp().createLoopback(createLoopback).toCompletableFuture(), id, loopback);
+
+ LOG.debug("Loopback set successfully for: {}, loopback: {}", swIfName, loopback);
+ // Add new interface to our interface context
+ interfaceContext.addName(reply.swIfIndex, swIfName, writeContext.getMappingContext());
+ }
+
+ private void deleteLoopback(final InstanceIdentifier<Loopback> id, final String swIfName, final int index,
+ final Loopback dataBefore, final WriteContext writeContext)
+ throws WriteFailedException {
+ LOG.debug("Deleting loopback interface: {}. Loopback: {}", swIfName, dataBefore);
+ final DeleteLoopback deleteLoopback = new DeleteLoopback();
+ deleteLoopback.swIfIndex = index;
+ getReplyForDelete(getFutureJVpp().deleteLoopback(deleteLoopback).toCompletableFuture(), id);
+ LOG.debug("Loopback deleted successfully for: {}, loopback: {}", swIfName, dataBefore);
+ // Remove deleted interface from interface context
+ interfaceContext.removeName(swIfName, writeContext.getMappingContext());
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/LoopbackValidator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/LoopbackValidator.java
new file mode 100644
index 000000000..af6126bfb
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/LoopbackValidator.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2019 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.v3po.write;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.DataValidationFailedException;
+import io.fd.honeycomb.translate.write.Validator;
+import io.fd.honeycomb.translate.write.WriteContext;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Loopback;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class LoopbackValidator implements Validator<Loopback> {
+
+ public LoopbackValidator(final NamingContext interfaceContext) {
+ checkNotNull(interfaceContext, "interfaceContext should not be null");
+ }
+
+ @Override
+ public void validateWrite(@Nonnull final InstanceIdentifier<Loopback> id, @Nonnull final Loopback dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.CreateValidationFailedException {
+ // there is nothing to validate yet
+ }
+
+ @Override
+ public void validateUpdate(@Nonnull final InstanceIdentifier<Loopback> id, @Nonnull final Loopback dataBefore,
+ @Nonnull final Loopback dataAfter, @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.UpdateValidationFailedException {
+ // there is nothing to validate yet
+ }
+
+ @Override
+ public void validateDelete(@Nonnull final InstanceIdentifier<Loopback> id, @Nonnull final Loopback dataBefore,
+ @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.DeleteValidationFailedException {
+ // there is nothing to validate yet
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/RewriteCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/RewriteCustomizer.java
new file mode 100644
index 000000000..15eb7b0b4
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/RewriteCustomizer.java
@@ -0,0 +1,135 @@
+/*
+ * 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.v3po.write;
+
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.common.translate.util.TagRewriteOperation;
+import io.fd.hc2vpp.v3po.util.SubInterfaceUtils;
+import io.fd.honeycomb.translate.spi.write.WriterCustomizer;
+import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.jvpp.core.dto.L2InterfaceVlanTagRewrite;
+import io.fd.jvpp.core.dto.L2InterfaceVlanTagRewriteReply;
+import io.fd.jvpp.core.future.FutureJVppCore;
+import java.util.List;
+import java.util.concurrent.CompletionStage;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319._802dot1q;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterface;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.rewrite.attributes.Rewrite;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.rewrite.attributes.RewriteBuilder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.tag.rewrite.PushTags;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Writer Customizer responsible for vlan tag rewrite.<br> Sends {@code l2_interface_vlan_tag_rewrite} message to
+ * VPP.<br> Equivalent of invoking {@code vppctl set interface l2 tag-rewrite} command.
+ */
+public class RewriteCustomizer extends FutureJVppCustomizer
+ implements WriterCustomizer<Rewrite>, ByteDataTranslator, JvppReplyConsumer {
+
+ private static final Logger LOG = LoggerFactory.getLogger(RewriteCustomizer.class);
+ private final NamingContext interfaceContext;
+
+ public RewriteCustomizer(@Nonnull final FutureJVppCore futureJVppCore,
+ @Nonnull final NamingContext interfaceContext) {
+ super(futureJVppCore);
+ this.interfaceContext = interfaceContext;
+ }
+
+ @Override
+ public void writeCurrentAttributes(final InstanceIdentifier<Rewrite> id, final Rewrite dataAfter,
+ final WriteContext writeContext)
+ throws WriteFailedException {
+ final String subifName = getSubInterfaceName(id);
+ setTagRewrite(id, subifName, dataAfter, writeContext);
+ }
+
+ private static String getSubInterfaceName(final InstanceIdentifier<Rewrite> id) {
+ return SubInterfaceUtils.getSubInterfaceName(id.firstKeyOf(Interface.class).getName(),
+ Math.toIntExact(id.firstKeyOf(SubInterface.class).getIdentifier()));
+ }
+
+ private void setTagRewrite(final InstanceIdentifier<Rewrite> id, final String ifname, final Rewrite rewrite,
+ final WriteContext writeContext) throws WriteFailedException {
+ final int swIfIndex = interfaceContext.getIndex(ifname, writeContext.getMappingContext());
+ LOG.debug("Setting tag rewrite for interface {}(id=): {}", ifname, swIfIndex, rewrite);
+
+ final CompletionStage<L2InterfaceVlanTagRewriteReply> replyCompletionStage =
+ getFutureJVpp().l2InterfaceVlanTagRewrite(getTagRewriteRequest(swIfIndex, rewrite));
+
+ getReplyForWrite(replyCompletionStage.toCompletableFuture(), id);
+ LOG.debug("Tag rewrite for interface {}(id=) set successfully: {}", ifname, swIfIndex, rewrite);
+ }
+
+ private L2InterfaceVlanTagRewrite getTagRewriteRequest(final int swIfIndex, final Rewrite rewrite) {
+ final L2InterfaceVlanTagRewrite request = new L2InterfaceVlanTagRewrite();
+ request.swIfIndex = swIfIndex;
+ request.pushDot1Q = booleanToByte(_802dot1q.class == rewrite.getVlanType());
+
+ final List<PushTags> pushTags = rewrite.getPushTags();
+ final Short popTags = rewrite.getPopTags();
+
+ final int numberOfTagsToPop = popTags == null
+ ? 0
+ : popTags.intValue();
+ final int numberOfTagsToPush = pushTags == null
+ ? 0
+ : pushTags.size();
+
+ request.vtrOp = TagRewriteOperation.get(numberOfTagsToPop, numberOfTagsToPush).ordinal();
+
+ if (numberOfTagsToPush > 0) {
+ for (final PushTags tag : pushTags) {
+ if (tag.getIndex() == 0) {
+ request.tag1 = tag.getDot1qTag().getVlanId().getValue();
+ } else {
+ request.tag2 = tag.getDot1qTag().getVlanId().getValue();
+ }
+ }
+ }
+
+ LOG.debug("Generated tag rewrite request: {}", request);
+ return request;
+ }
+
+ @Override
+ public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<Rewrite> id,
+ @Nonnull final Rewrite dataBefore,
+ @Nonnull final Rewrite dataAfter, @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ final String subifName = getSubInterfaceName(id);
+ setTagRewrite(id, subifName, dataAfter, writeContext);
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Rewrite> id,
+ @Nonnull final Rewrite dataBefore, @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ final String subifName = getSubInterfaceName(id);
+
+ LOG.debug("Disabling tag rewrite for interface {}", subifName);
+ final Rewrite rewrite = new RewriteBuilder().build(); // rewrite without push and pops will cause delete
+ setTagRewrite(id, subifName, rewrite, writeContext);
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/RewriteValidator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/RewriteValidator.java
new file mode 100644
index 000000000..a16bbafc4
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/RewriteValidator.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2019 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.v3po.write;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.DataValidationFailedException;
+import io.fd.honeycomb.translate.write.Validator;
+import io.fd.honeycomb.translate.write.WriteContext;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.rewrite.attributes.Rewrite;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class RewriteValidator implements Validator<Rewrite> {
+
+ public RewriteValidator(@Nonnull final NamingContext interfaceContext) {
+ checkNotNull(interfaceContext, "interfaceContext should not be null");
+ }
+
+ @Override
+ public void validateWrite(@Nonnull final InstanceIdentifier<Rewrite> id, @Nonnull final Rewrite dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.CreateValidationFailedException {
+ // there is nothing to validate yet
+ }
+
+ @Override
+ public void validateUpdate(@Nonnull final InstanceIdentifier<Rewrite> id, @Nonnull final Rewrite dataBefore,
+ @Nonnull final Rewrite dataAfter, @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.UpdateValidationFailedException {
+ // there is nothing to validate yet
+ }
+
+ @Override
+ public void validateDelete(@Nonnull final InstanceIdentifier<Rewrite> id, @Nonnull final Rewrite dataBefore,
+ @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.DeleteValidationFailedException {
+ // there is nothing to validate yet
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/RoutingCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/RoutingCustomizer.java
new file mode 100644
index 000000000..b28b6e3c9
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/RoutingCustomizer.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2017 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.v3po.write;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+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.jvpp.core.dto.SwInterfaceSetTable;
+import io.fd.jvpp.core.dto.SwInterfaceSetTableReply;
+import io.fd.jvpp.core.future.FutureJVppCore;
+import java.util.concurrent.CompletionStage;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.RoutingBaseAttributes;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.fib.table.management.rev180521.VniReference;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+abstract class RoutingCustomizer extends FutureJVppCustomizer implements JvppReplyConsumer, ByteDataTranslator {
+ private static final Logger LOG = LoggerFactory.getLogger(RoutingCustomizer.class);
+ protected final NamingContext interfaceContext;
+
+ protected RoutingCustomizer(@Nonnull final FutureJVppCore futureJVppCore,
+ @Nonnull final NamingContext interfaceContext) {
+ super(futureJVppCore);
+ this.interfaceContext = interfaceContext;
+ }
+
+ protected void setRouting(@Nonnull final InstanceIdentifier<? extends RoutingBaseAttributes> id,
+ @Nonnull final String name,
+ @Nonnull final RoutingBaseAttributes rt,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ final int swIfc = interfaceContext.getIndex(name, writeContext.getMappingContext());
+ LOG.debug("Setting routing for interface: {}, {}. Routing: {}", name, swIfc, rt);
+ checkArgument(rt.getIpv4VrfId() != null || rt.getIpv6VrfId() != null, "No vrf-id given");
+
+ setVrfId(id, swIfc, rt.getIpv4VrfId(), false);
+ setVrfId(id, swIfc, rt.getIpv6VrfId(), true);
+
+ LOG.debug("Routing set successfully for interface: {}, {}, routing: {}", name, swIfc, rt);
+ }
+
+ private void setVrfId(final InstanceIdentifier<? extends RoutingBaseAttributes> id, final int swIfc,
+ final VniReference vniRef, boolean isIp6)
+ throws WriteFailedException {
+ if (vniRef == null || vniRef.getValue() == null) {
+ return;
+ }
+ final CompletionStage<SwInterfaceSetTableReply> cs = getFutureJVpp().swInterfaceSetTable(
+ getInterfaceSetTableRequest(swIfc, booleanToByte(isIp6), vniRef.getValue().intValue()));
+ getReplyForWrite(cs.toCompletableFuture(), id);
+ }
+
+ /**
+ * In this case, there is no such thing as delete routing,only thing that can be done is to disable it by setting
+ * default value 0
+ */
+ void disableRouting(final InstanceIdentifier<? extends RoutingBaseAttributes> id, final String name,
+ final WriteContext writeContext) throws WriteFailedException {
+ final int swIfc = interfaceContext.getIndex(name, writeContext.getMappingContext());
+ LOG.debug("Disabling routing for interface: {}, {}.", name, swIfc);
+
+ getReplyForDelete(getFutureJVpp()
+ .swInterfaceSetTable(getInterfaceSetTableRequest(swIfc, (byte) 0, 0)).toCompletableFuture(), id);
+ LOG.debug("Routing for interface: {}, {} successfully disabled", name, swIfc);
+
+ }
+
+ private SwInterfaceSetTable getInterfaceSetTableRequest(final int swIfc, final byte isIpv6, final int vrfId) {
+ final SwInterfaceSetTable swInterfaceSetTable = new SwInterfaceSetTable();
+ swInterfaceSetTable.isIpv6 = isIpv6;
+ swInterfaceSetTable.swIfIndex = swIfc;
+ swInterfaceSetTable.vrfId = vrfId;
+ return swInterfaceSetTable;
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/SubInterfaceCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/SubInterfaceCustomizer.java
new file mode 100644
index 000000000..65d7de55e
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/SubInterfaceCustomizer.java
@@ -0,0 +1,193 @@
+/*
+ * 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.v3po.write;
+
+import static com.google.common.base.Preconditions.checkState;
+import static io.fd.hc2vpp.v3po.util.SubInterfaceUtils.getNumberOfTags;
+import static io.fd.hc2vpp.v3po.util.SubInterfaceUtils.getSubInterfaceName;
+
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer;
+import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.jvpp.core.dto.CreateSubif;
+import io.fd.jvpp.core.dto.CreateSubifReply;
+import io.fd.jvpp.core.dto.SwInterfaceSetFlags;
+import io.fd.jvpp.core.dto.SwInterfaceSetFlagsReply;
+import io.fd.jvpp.core.future.FutureJVppCore;
+import java.util.concurrent.CompletionStage;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319._802dot1ad;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterface;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterfaceKey;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.match.attributes.MatchType;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.match.attributes.match.type.Default;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.match.attributes.match.type.VlanTagged;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.base.attributes.tags.Tag;
+import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.CVlan;
+import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.Dot1qVlanId;
+import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.SVlan;
+import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.dot1q.tag.or.any.Dot1qTag;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Writer Customizer responsible for sub interface creation.<br> Sends {@code create_subif} message to VPP.<br>
+ * Equivalent of invoking {@code vppclt create subif} command.
+ */
+public class SubInterfaceCustomizer extends FutureJVppCustomizer
+ implements ListWriterCustomizer<SubInterface, SubInterfaceKey>, ByteDataTranslator, JvppReplyConsumer {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SubInterfaceCustomizer.class);
+ private final NamingContext interfaceContext;
+
+ public SubInterfaceCustomizer(@Nonnull final FutureJVppCore futureJVppCore,
+ @Nonnull final NamingContext interfaceContext) {
+ super(futureJVppCore);
+ this.interfaceContext = interfaceContext;
+ }
+
+ @Override
+ public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<SubInterface> id,
+ @Nonnull final SubInterface dataAfter, @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ final String superIfName = id.firstKeyOf(Interface.class).getName();
+ createSubInterface(id, superIfName, dataAfter, writeContext);
+ }
+
+ private void createSubInterface(final InstanceIdentifier<SubInterface> id, @Nonnull final String superIfName,
+ @Nonnull final SubInterface subInterface, final WriteContext writeContext)
+ throws WriteFailedException {
+ final int superIfIndex = interfaceContext.getIndex(superIfName, writeContext.getMappingContext());
+ final CompletionStage<CreateSubifReply> createSubifReplyCompletionStage =
+ getFutureJVpp().createSubif(getCreateSubifRequest(subInterface, superIfIndex));
+
+ final CreateSubifReply reply =
+ getReplyForCreate(createSubifReplyCompletionStage.toCompletableFuture(), id, subInterface);
+
+ setInterfaceState(id, reply.swIfIndex, booleanToByte(subInterface.isEnabled()));
+ interfaceContext.addName(reply.swIfIndex,
+ getSubInterfaceName(superIfName, Math.toIntExact(subInterface.getIdentifier())),
+ writeContext.getMappingContext());
+ LOG.debug("Sub interface created successfully for: {}, subInterface: {}", superIfName, subInterface);
+ }
+
+ private CreateSubif getCreateSubifRequest(@Nonnull final SubInterface subInterface, final int swIfIndex) {
+ // TODO HONEYCOMB-183 add validation
+ CreateSubif request = new CreateSubif();
+ request.subId = Math.toIntExact(subInterface.getIdentifier().intValue());
+ request.swIfIndex = swIfIndex;
+
+ final int numberOfTags = getNumberOfTags(subInterface.getTags());
+ switch (numberOfTags) {
+ case 0:
+ request.noTags = 1;
+ break;
+ case 1:
+ request.oneTag = 1;
+ break;
+ case 2:
+ request.twoTags = 1;
+ break;
+ }
+ request.dot1Ad = booleanToByte(_802dot1ad.class == subInterface.getVlanType());
+
+ // TODO HONEYCOMB-183 match should be mandatory
+ final MatchType matchType = subInterface.getMatch().getMatchType();
+ request.exactMatch = booleanToByte(
+ matchType instanceof VlanTagged
+ && ((VlanTagged) matchType).getVlanTagged().isMatchExactTags()
+ );
+ request.defaultSub = booleanToByte(matchType instanceof Default);
+ if (numberOfTags > 0) {
+ for (final Tag tag : subInterface.getTags().getTag()) {
+ if (tag.getIndex() == 0) {
+ setOuterTag(request, tag);
+ } else if (tag.getIndex() == 1) {
+ setInnerTag(request, tag);
+ }
+ }
+ }
+ return request;
+ }
+
+ private void setOuterTag(final CreateSubif request, final Tag outerTag) {
+ checkState(SVlan.class == outerTag.getDot1qTag().getTagType(), "Service Tag expected at index 0");
+ final Dot1qTag.VlanId vlanId = outerTag.getDot1qTag().getVlanId();
+
+ request.outerVlanId = dot1qVlanIdToShort(vlanId.getDot1qVlanId());
+ request.outerVlanIdAny = booleanToByte(Dot1qTag.VlanId.Enumeration.Any.equals(vlanId.getEnumeration()));
+ }
+
+ private void setInnerTag(final CreateSubif request, final Tag innerTag) {
+ checkState(CVlan.class == innerTag.getDot1qTag().getTagType(), "Customer Tag expected at index 1");
+ final Dot1qTag.VlanId vlanId = innerTag.getDot1qTag().getVlanId();
+
+ request.innerVlanId = dot1qVlanIdToShort(vlanId.getDot1qVlanId());
+ request.innerVlanIdAny = booleanToByte(Dot1qTag.VlanId.Enumeration.Any.equals(vlanId.getEnumeration()));
+ }
+
+ private static short dot1qVlanIdToShort(@Nullable Dot1qVlanId dot1qVlanId) {
+ if (dot1qVlanId == null) {
+ return 0; // tell VPP that optional argument is missing
+ } else {
+ return dot1qVlanId.getValue().shortValue();
+ }
+ }
+
+ @Override
+ public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<SubInterface> id,
+ @Nonnull final SubInterface dataBefore, @Nonnull final SubInterface dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ final String subIfaceName = getSubInterfaceName(id.firstKeyOf(Interface.class).getName(),
+ Math.toIntExact(dataAfter.getIdentifier()));
+ setInterfaceState(id, interfaceContext.getIndex(subIfaceName, writeContext.getMappingContext()),
+ booleanToByte(dataAfter.isEnabled()));
+ }
+
+ private void setInterfaceState(final InstanceIdentifier<SubInterface> id, final int swIfIndex, final byte enabled)
+ throws WriteFailedException {
+ final SwInterfaceSetFlags swInterfaceSetFlags = new SwInterfaceSetFlags();
+ swInterfaceSetFlags.swIfIndex = swIfIndex;
+ swInterfaceSetFlags.adminUpDown = enabled;
+
+ final CompletionStage<SwInterfaceSetFlagsReply> swInterfaceSetFlagsReplyFuture =
+ getFutureJVpp().swInterfaceSetFlags(swInterfaceSetFlags);
+
+ LOG.debug("Updating interface state for interface if={}, enabled: {}", swIfIndex, enabled);
+
+ SwInterfaceSetFlagsReply reply =
+ getReplyForWrite(swInterfaceSetFlagsReplyFuture.toCompletableFuture(), id);
+ LOG.debug("Interface state updated successfully for interface index: {}, enabled: {}, ctxId: {}",
+ swIfIndex, enabled, reply.context);
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<SubInterface> id,
+ @Nonnull final SubInterface dataBefore,
+ @Nonnull final WriteContext writeContext)
+ throws WriteFailedException.DeleteFailedException {
+ throw new UnsupportedOperationException("Sub interface delete is not supported");
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/SubInterfaceL2Customizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/SubInterfaceL2Customizer.java
new file mode 100644
index 000000000..091713c26
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/SubInterfaceL2Customizer.java
@@ -0,0 +1,100 @@
+/*
+ * 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.v3po.write;
+
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.v3po.util.SubInterfaceUtils;
+import io.fd.honeycomb.translate.spi.write.WriterCustomizer;
+import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.jvpp.core.future.FutureJVppCore;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterface;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterfaceKey;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.l2.config.attributes.L2;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Customizer for writing vlan sub interface l2 configuration
+ */
+public class SubInterfaceL2Customizer extends FutureJVppCustomizer implements WriterCustomizer<L2> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SubInterfaceL2Customizer.class);
+ private final NamingContext interfaceContext;
+ private final InterconnectionWriteUtils icWriterUtils;
+
+ public SubInterfaceL2Customizer(final FutureJVppCore vppApi, final NamingContext interfaceContext,
+ final NamingContext bridgeDomainContext) {
+ super(vppApi);
+ this.interfaceContext = interfaceContext;
+ this.icWriterUtils = new InterconnectionWriteUtils(vppApi, interfaceContext, bridgeDomainContext);
+ }
+
+ @Override
+ public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<L2> id, @Nonnull final L2 dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ final String subInterfaceName = getSubInterfaceName(id);
+ final int subInterfaceIndex = interfaceContext.getIndex(subInterfaceName, writeContext.getMappingContext());
+ setL2(id, subInterfaceIndex, subInterfaceName, dataAfter, writeContext);
+ }
+
+ private String getSubInterfaceName(@Nonnull final InstanceIdentifier<L2> id) {
+ final InterfaceKey parentInterfacekey = id.firstKeyOf(Interface.class);
+ final SubInterfaceKey subInterfacekey = id.firstKeyOf(SubInterface.class);
+ return SubInterfaceUtils
+ .getSubInterfaceName(parentInterfacekey.getName(), subInterfacekey.getIdentifier().intValue());
+ }
+
+ @Override
+ public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<L2> id, @Nonnull final L2 dataBefore,
+ @Nonnull final L2 dataAfter, @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+
+ final String subInterfaceName = getSubInterfaceName(id);
+ final int subInterfaceIndex = interfaceContext.getIndex(subInterfaceName, writeContext.getMappingContext());
+ // Setting L2 to new values
+ setL2(id, subInterfaceIndex, subInterfaceName, dataAfter, writeContext);
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<L2> id, @Nonnull final L2 dataBefore,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ final String subInterfaceName = getSubInterfaceName(id);
+ final int subInterfaceIndex = interfaceContext.getIndex(subInterfaceName, writeContext.getMappingContext());
+ deleteL2(id, subInterfaceIndex, subInterfaceName, dataBefore, writeContext);
+ }
+
+ private void setL2(final InstanceIdentifier<L2> id, final int swIfIndex, final String ifcName, final L2 l2,
+ final WriteContext writeContext)
+ throws WriteFailedException {
+ LOG.debug("Setting L2 for sub-interface: {}", ifcName);
+ icWriterUtils.setInterconnection(id, swIfIndex, ifcName, l2.getInterconnection(), writeContext);
+ }
+
+ private void deleteL2(final InstanceIdentifier<L2> id, final int swIfIndex, final String ifcName, final L2 l2Before,
+ final WriteContext writeContext)
+ throws WriteFailedException {
+ LOG.debug("Deleting L2 for sub-interface: {}", ifcName);
+ icWriterUtils.deleteInterconnection(id, swIfIndex, ifcName, l2Before.getInterconnection(), writeContext);
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/SubInterfaceL2Validator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/SubInterfaceL2Validator.java
new file mode 100644
index 000000000..713a80d30
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/SubInterfaceL2Validator.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2019 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.v3po.write;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.DataValidationFailedException;
+import io.fd.honeycomb.translate.write.Validator;
+import io.fd.honeycomb.translate.write.WriteContext;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.l2.config.attributes.L2;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class SubInterfaceL2Validator implements Validator<L2> {
+
+ public SubInterfaceL2Validator(final NamingContext interfaceContext,
+ final NamingContext bridgeDomainContext) {
+ checkNotNull(interfaceContext, "interfaceContext should not be null");
+ checkNotNull(bridgeDomainContext, "bridgeDomainContext should not be null");
+ }
+
+ @Override
+ public void validateWrite(@Nonnull final InstanceIdentifier<L2> id, @Nonnull final L2 dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.CreateValidationFailedException {
+ // there is nothing to validate yet
+ }
+
+ @Override
+ public void validateUpdate(@Nonnull final InstanceIdentifier<L2> id, @Nonnull final L2 dataBefore,
+ @Nonnull final L2 dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.UpdateValidationFailedException {
+ // there is nothing to validate yet
+ }
+
+ @Override
+ public void validateDelete(@Nonnull final InstanceIdentifier<L2> id, @Nonnull final L2 dataBefore,
+ @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.DeleteValidationFailedException {
+ // there is nothing to validate yet
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/SubInterfaceRoutingCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/SubInterfaceRoutingCustomizer.java
new file mode 100644
index 000000000..6fe3c3c01
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/SubInterfaceRoutingCustomizer.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2017 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.v3po.write;
+
+import static io.fd.hc2vpp.v3po.util.SubInterfaceUtils.subInterfaceFullNameConfig;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.spi.write.WriterCustomizer;
+import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.jvpp.core.future.FutureJVppCore;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.routing.attributes.Routing;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class SubInterfaceRoutingCustomizer extends RoutingCustomizer implements WriterCustomizer<Routing> {
+
+ public SubInterfaceRoutingCustomizer(@Nonnull final FutureJVppCore futureJVppCore,
+ @Nonnull final NamingContext interfaceContext) {
+ super(futureJVppCore, interfaceContext);
+ }
+
+ @Override
+ public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Routing> instanceIdentifier,
+ @Nonnull final Routing routing, @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ setRouting(instanceIdentifier, subInterfaceFullNameConfig(instanceIdentifier), routing, writeContext);
+ }
+
+ @Override
+ public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<Routing> instanceIdentifier,
+ @Nonnull final Routing routing, @Nonnull final Routing d1,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ setRouting(instanceIdentifier, subInterfaceFullNameConfig(instanceIdentifier), routing, writeContext);
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Routing> instanceIdentifier,
+ @Nonnull final Routing routing, @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ disableRouting(instanceIdentifier, subInterfaceFullNameConfig(instanceIdentifier), writeContext);
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/SubInterfaceRoutingValidator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/SubInterfaceRoutingValidator.java
new file mode 100644
index 000000000..e769409bd
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/SubInterfaceRoutingValidator.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2019 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.v3po.write;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.util.RWUtils;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.CreateValidationFailedException;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.DeleteValidationFailedException;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.UpdateValidationFailedException;
+import io.fd.honeycomb.translate.write.Validator;
+import io.fd.honeycomb.translate.write.WriteContext;
+import java.util.List;
+import java.util.Optional;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterface;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.ip4.attributes.Ipv4;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.ip6.attributes.Ipv6;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.routing.attributes.Routing;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class SubInterfaceRoutingValidator implements Validator<Routing> {
+
+ public SubInterfaceRoutingValidator(@Nonnull final NamingContext interfaceContext) {
+ checkNotNull(interfaceContext, "interfaceContext should not be null");
+ }
+
+ @Override
+ public void validateWrite(@Nonnull final InstanceIdentifier<Routing> id, @Nonnull final Routing dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws CreateValidationFailedException {
+ try {
+ checkInterfaceAddressConf(id, writeContext, true);
+ } catch (Exception e) {
+ throw new CreateValidationFailedException(id, dataAfter, e);
+ }
+ }
+
+ @Override
+ public void validateUpdate(@Nonnull final InstanceIdentifier<Routing> id, @Nonnull final Routing dataBefore,
+ @Nonnull final Routing dataAfter, @Nonnull final WriteContext writeContext)
+ throws UpdateValidationFailedException {
+ try {
+ checkInterfaceAddressConf(id, writeContext, true);
+ } catch (Exception e) {
+ throw new UpdateValidationFailedException(id, dataBefore, dataAfter, e);
+ }
+ }
+
+ @Override
+ public void validateDelete(@Nonnull final InstanceIdentifier<Routing> id, @Nonnull final Routing dataBefore,
+ @Nonnull final WriteContext writeContext)
+ throws DeleteValidationFailedException {
+ try {
+ checkInterfaceAddressConf(id, writeContext, false);
+ } catch (Exception e) {
+ throw new DeleteValidationFailedException(id, e);
+ }
+ }
+
+ private void checkInterfaceAddressConf(@Nonnull final InstanceIdentifier<Routing> id,
+ @Nonnull final WriteContext ctx,
+ boolean checkBefore) {
+ checkState(isAddressNotPresentForSubInterface(id, ctx, checkBefore),
+ "Cannot change routing configuration, if address is present for sub-interface");
+ }
+
+ /**
+ * Returns true if interface does not have v4/v6 addresses configured
+ */
+ private boolean isAddressNotPresentForSubInterface(@Nonnull final InstanceIdentifier<Routing> id,
+ @Nonnull final WriteContext ctx,
+ boolean checkBefore) {
+ final Optional<SubInterface> subInterfaceData = checkBefore
+ ?
+ ctx.readBefore(RWUtils.cutId(id, SubInterface.class))
+ :
+ ctx.readAfter(RWUtils.cutId(id, SubInterface.class));
+
+ if (subInterfaceData.isPresent()) {
+ final SubInterface subInterface = subInterfaceData.get();
+
+ final boolean v4NotPresent =
+ java.util.Optional.ofNullable(subInterface.getIpv4()).map(Ipv4::getAddress).map(List::isEmpty)
+ .orElse(true);
+
+ final boolean v6NotPresent =
+ java.util.Optional.ofNullable(subInterface.getIpv6()).map(Ipv6::getAddress).map(List::isEmpty)
+ .orElse(true);
+ return v4NotPresent && v6NotPresent;
+ }
+ return true;
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/SubInterfaceUnnumberedCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/SubInterfaceUnnumberedCustomizer.java
new file mode 100644
index 000000000..314e9a4fe
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/SubInterfaceUnnumberedCustomizer.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2017 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.v3po.write;
+
+import static io.fd.hc2vpp.v3po.util.SubInterfaceUtils.subInterfaceFullNameConfig;
+
+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.jvpp.core.future.FutureJVppCore;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.unnumbered.interfaces.rev180103.unnumbered.config.attributes.Unnumbered;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public final class SubInterfaceUnnumberedCustomizer extends AbstractUnnumberedCustomizer {
+
+ public SubInterfaceUnnumberedCustomizer(@Nonnull final FutureJVppCore futureJVppCore,
+ @Nonnull final NamingContext interfaceContext) {
+ super(futureJVppCore, interfaceContext);
+ }
+
+ @Override
+ public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Unnumbered> id,
+ @Nonnull final Unnumbered dataAfter,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ setUnnumbered(id, subInterfaceFullNameConfig(id), dataAfter, writeContext);
+ }
+
+ @Override
+ public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<Unnumbered> id,
+ @Nonnull final Unnumbered dataBefore, @Nonnull final Unnumbered dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ setUnnumbered(id, subInterfaceFullNameConfig(id), dataAfter, writeContext);
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Unnumbered> id,
+ @Nonnull final Unnumbered dataBefore,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ disableUnnumbered(id, subInterfaceFullNameConfig(id), dataBefore, writeContext);
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/SubInterfaceUnnumberedValidator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/SubInterfaceUnnumberedValidator.java
new file mode 100644
index 000000000..d4224534a
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/SubInterfaceUnnumberedValidator.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2019 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.v3po.write;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.DataValidationFailedException;
+import io.fd.honeycomb.translate.write.Validator;
+import io.fd.honeycomb.translate.write.WriteContext;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.unnumbered.interfaces.rev180103.unnumbered.config.attributes.Unnumbered;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class SubInterfaceUnnumberedValidator implements Validator<Unnumbered> {
+
+ public SubInterfaceUnnumberedValidator(final NamingContext interfaceContext) {
+ checkNotNull(interfaceContext, "interfaceContext should not be null");
+ }
+
+ @Override
+ public void validateWrite(@Nonnull final InstanceIdentifier<Unnumbered> id, @Nonnull final Unnumbered dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.CreateValidationFailedException {
+ checkNotNull(dataAfter.getUse());
+ }
+
+ @Override
+ public void validateUpdate(@Nonnull final InstanceIdentifier<Unnumbered> id, @Nonnull final Unnumbered dataBefore,
+ @Nonnull final Unnumbered dataAfter, @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.UpdateValidationFailedException {
+ checkNotNull(dataAfter.getUse());
+ }
+
+ @Override
+ public void validateDelete(@Nonnull final InstanceIdentifier<Unnumbered> id, @Nonnull final Unnumbered dataBefore,
+ @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.DeleteValidationFailedException {
+ checkNotNull(dataBefore.getUse());
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/SubInterfaceValidator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/SubInterfaceValidator.java
new file mode 100644
index 000000000..92b64bcaa
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/SubInterfaceValidator.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2019 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.v3po.write;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.DataValidationFailedException;
+import io.fd.honeycomb.translate.write.Validator;
+import io.fd.honeycomb.translate.write.WriteContext;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterface;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class SubInterfaceValidator implements Validator<SubInterface> {
+
+ public SubInterfaceValidator(@Nonnull final NamingContext interfaceContext) {
+ checkNotNull(interfaceContext, "interfaceContext should not be null");
+ }
+
+ @Override
+ public void validateWrite(@Nonnull final InstanceIdentifier<SubInterface> id, @Nonnull final SubInterface dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.CreateValidationFailedException {
+ try {
+ checkSubInterface(dataAfter);
+ } catch (Exception e) {
+ throw new DataValidationFailedException.CreateValidationFailedException(id, dataAfter, e);
+ }
+ }
+
+ @Override
+ public void validateUpdate(@Nonnull final InstanceIdentifier<SubInterface> id,
+ @Nonnull final SubInterface dataBefore,
+ @Nonnull final SubInterface dataAfter, @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.UpdateValidationFailedException {
+ try {
+ checkSubInterface(dataAfter);
+ } catch (Exception e) {
+ throw new DataValidationFailedException.UpdateValidationFailedException(id, dataBefore, dataAfter, e);
+ }
+ }
+
+ private void checkSubInterface(final SubInterface data) {
+ checkNotNull(data.getIdentifier(), "Identifier cannot be null");
+ checkNotNull(data.getMatch(), "Match cannot be null");
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/TapV2Customizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/TapV2Customizer.java
new file mode 100644
index 000000000..773a48fa0
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/TapV2Customizer.java
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2018 Pantheon Technologies 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.v3po.write;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import io.fd.hc2vpp.common.translate.util.AbstractInterfaceTypeCustomizer;
+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.common.translate.util.MacTranslator;
+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.jvpp.core.dto.TapCreateV2;
+import io.fd.jvpp.core.dto.TapCreateV2Reply;
+import io.fd.jvpp.core.dto.TapDeleteV2;
+import io.fd.jvpp.core.dto.TapDeleteV2Reply;
+import io.fd.jvpp.core.future.FutureJVppCore;
+import java.nio.charset.StandardCharsets;
+import java.util.concurrent.CompletionStage;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.TapV2;
+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.Ipv4AddressNoZone;
+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.inet.types.rev130715.Ipv6Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.InterfaceType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TapV2Customizer extends AbstractInterfaceTypeCustomizer<TapV2>
+ implements MacTranslator, Ipv4Translator, Ipv6Translator, JvppReplyConsumer {
+
+ private static final Logger LOG = LoggerFactory.getLogger(TapV2Customizer.class);
+ private final NamingContext interfaceContext;
+
+ public TapV2Customizer(final FutureJVppCore vppApi, final NamingContext interfaceContext) {
+ super(vppApi);
+ this.interfaceContext = interfaceContext;
+ }
+
+ @Override
+ protected Class<? extends InterfaceType> getExpectedInterfaceType() {
+ return org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.TapV2.class;
+ }
+
+ @Override
+ protected final void writeInterface(@Nonnull final InstanceIdentifier<TapV2> id, @Nonnull final TapV2 dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ final String ifcName = id.firstKeyOf(Interface.class).getName();
+ createTapV2(id, ifcName, dataAfter, writeContext);
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<TapV2> id, @Nonnull final TapV2 dataBefore,
+ @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ final String ifcName = id.firstKeyOf(Interface.class).getName();
+
+ final int index;
+ try {
+ index = interfaceContext.getIndex(ifcName, writeContext.getMappingContext());
+ } catch (IllegalArgumentException e) {
+ throw new WriteFailedException.DeleteFailedException(id, e);
+ }
+
+ deleteTapV2(id, ifcName, index, dataBefore, writeContext);
+ }
+
+ private void createTapV2(final InstanceIdentifier<TapV2> id, final String swIfName, final TapV2 tapv2,
+ final WriteContext writeContext) throws WriteFailedException {
+ LOG.debug("Setting TapV2 interface: {}. TapV2: {}", swIfName, tapv2);
+ final CompletionStage<TapCreateV2Reply> tapV2CreateFuture = getFutureJVpp()
+ .tapCreateV2(getTapV2CreateRequest(tapv2));
+ final TapCreateV2Reply reply = getReplyForCreate(tapV2CreateFuture.toCompletableFuture(), id, tapv2);
+ LOG.debug("TapV2 set successfully for: {}, TapV2: {}", swIfName, tapv2);
+ // Add new interface to our interface context
+ interfaceContext.addName(reply.swIfIndex, swIfName, writeContext.getMappingContext());
+ }
+
+ private void deleteTapV2(final InstanceIdentifier<TapV2> id, final String swIfName, final int index,
+ final TapV2 dataBefore, final WriteContext writeContext)
+ throws WriteFailedException {
+ LOG.debug("Deleting TapV2 interface: {}. TapV2: {}", swIfName, dataBefore);
+ final CompletionStage<TapDeleteV2Reply> vxlanAddDelTunnelReplyCompletionStage =
+ getFutureJVpp().tapDeleteV2(getTapV2DeleteRequest(index));
+ getReplyForDelete(vxlanAddDelTunnelReplyCompletionStage.toCompletableFuture(), id);
+ LOG.debug("TapV2 deleted successfully for: {}, TapV2: {}", swIfName, dataBefore);
+ // Remove deleted interface from interface context
+ interfaceContext.removeName(swIfName, writeContext.getMappingContext());
+ }
+
+ private TapCreateV2 getTapV2CreateRequest(final TapV2 tapv2) {
+ final TapCreateV2 tapConnect = new TapCreateV2();
+ final PhysAddress mac = tapv2.getMac();
+ if (mac == null) {
+ tapConnect.useRandomMac = 1;
+ tapConnect.macAddress = new byte[6];
+ } else {
+ tapConnect.useRandomMac = 0;
+ tapConnect.macAddress = parseMac(mac.getValue());
+ }
+
+ final Integer rxRingSz = tapv2.getRxRingSize();
+ if (rxRingSz != null) {
+ tapConnect.rxRingSz = rxRingSz.shortValue();
+ }
+
+ final Integer txRingSz = tapv2.getTxRingSize();
+ if (txRingSz != null) {
+ tapConnect.txRingSz = txRingSz.shortValue();
+ }
+
+ final String tag = tapv2.getTag();
+ if (tag != null) {
+ tapConnect.tag = tag.getBytes(StandardCharsets.US_ASCII);
+ }
+
+ setHostProperties(tapConnect, tapv2);
+ return tapConnect;
+ }
+
+ private TapDeleteV2 getTapV2DeleteRequest(final int swIndex) {
+ final TapDeleteV2 tapDeleteV2 = new TapDeleteV2();
+ tapDeleteV2.swIfIndex = swIndex;
+ return tapDeleteV2;
+ }
+
+ private void setHostProperties(TapCreateV2 tapConnect, TapV2 tapv2) {
+
+ final PhysAddress hostMacAddress = tapv2.getHostMac();
+ if (hostMacAddress != null) {
+ tapConnect.hostMacAddr = parseMac(hostMacAddress.getValue());
+ tapConnect.hostMacAddrSet = 1;
+ } else {
+ tapConnect.hostMacAddr = new byte[6];
+ tapConnect.hostMacAddrSet = 0;
+ }
+
+ final String hostIfName = tapv2.getHostInterfaceName();
+ if (hostIfName != null) {
+ tapConnect.hostIfName = hostIfName.getBytes(UTF_8);
+ tapConnect.hostIfNameSet = 1;
+ } else {
+ tapConnect.hostIfNameSet = 0;
+ tapConnect.hostIfName = new byte[64];
+ }
+
+ final String hostBridge = tapv2.getHostBridge();
+ if (hostBridge != null) {
+ tapConnect.hostBridgeSet = 1;
+ tapConnect.hostBridge = hostBridge.getBytes(UTF_8);
+ } else {
+ tapConnect.hostBridgeSet = 0;
+ tapConnect.hostBridge = new byte[64];
+ }
+
+ final String hostNamespace = tapv2.getHostNamespace();
+ if (hostNamespace != null) {
+ tapConnect.hostNamespaceSet = 1;
+ tapConnect.hostNamespace = hostNamespace.getBytes(UTF_8);
+ } else {
+ tapConnect.hostNamespaceSet = 0;
+ tapConnect.hostNamespace = new byte[64];
+ }
+
+ final Ipv4Prefix hostIpv4address = tapv2.getHostIpv4Address();
+ if (hostIpv4address != null) {
+ tapConnect.hostIp4Addr = ipv4AddressPrefixToArray(hostIpv4address);
+ tapConnect.hostIp4AddrSet = 1;
+ tapConnect.hostIp4PrefixLen = extractPrefix(hostIpv4address);
+ } else {
+ tapConnect.hostIp4Addr = new byte[4];
+ tapConnect.hostIp4AddrSet = 0;
+ tapConnect.hostIp4PrefixLen = 0;
+ }
+
+ final Ipv4Address hostIpv4GW = tapv2.getHostIpv4Gateway();
+ if (hostIpv4GW != null) {
+ tapConnect.hostIp4Gw = ipv4AddressNoZoneToArray(new Ipv4AddressNoZone(hostIpv4GW));
+ tapConnect.hostIp4GwSet = 1;
+ } else {
+ tapConnect.hostIp4Gw = new byte[4];
+ tapConnect.hostIp4GwSet = 0;
+ }
+
+ final Ipv6Prefix hostIpv6address = tapv2.getHostIpv6Address();
+ if (hostIpv6address != null) {
+ tapConnect.hostIp6Addr = ipv6AddressPrefixToArray(hostIpv6address);
+ tapConnect.hostIp6AddrSet = 1;
+ tapConnect.hostIp6PrefixLen = extractPrefix(hostIpv6address);
+ } else {
+ tapConnect.hostIp6Addr = new byte[16];
+ tapConnect.hostIp6AddrSet = 0;
+ tapConnect.hostIp6PrefixLen = 0;
+ }
+
+ final Ipv6Address hostIpv6GW = tapv2.getHostIpv6Gateway();
+ if (hostIpv6GW != null) {
+ tapConnect.hostIp6Gw = ipv6AddressNoZoneToArray(hostIpv6GW);
+ tapConnect.hostIp6GwSet = 1;
+ } else {
+ tapConnect.hostIp6Gw = new byte[16];
+ tapConnect.hostIp6GwSet = 0;
+ }
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/TapV2Validator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/TapV2Validator.java
new file mode 100644
index 000000000..83ca218da
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/TapV2Validator.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2019 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.v3po.write;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.DataValidationFailedException;
+import io.fd.honeycomb.translate.write.Validator;
+import io.fd.honeycomb.translate.write.WriteContext;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.TapV2;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class TapV2Validator implements Validator<TapV2> {
+
+ public TapV2Validator(final NamingContext interfaceContext) {
+ checkNotNull(interfaceContext, "interfaceContext should not be null");
+ }
+
+ @Override
+ public void validateWrite(@Nonnull final InstanceIdentifier<TapV2> id, @Nonnull final TapV2 dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.CreateValidationFailedException {
+ // there is nothing to validate yet
+ }
+
+ @Override
+ public void validateUpdate(@Nonnull final InstanceIdentifier<TapV2> id, @Nonnull final TapV2 dataBefore,
+ @Nonnull final TapV2 dataAfter, @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.UpdateValidationFailedException {
+ // there is nothing to validate yet
+ }
+
+ @Override
+ public void validateDelete(@Nonnull final InstanceIdentifier<TapV2> id, @Nonnull final TapV2 dataBefore,
+ @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.DeleteValidationFailedException {
+ // there is nothing to validate yet
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/VhostUserCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/VhostUserCustomizer.java
new file mode 100644
index 000000000..69ade6a75
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/VhostUserCustomizer.java
@@ -0,0 +1,169 @@
+/*
+ * 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.v3po.write;
+
+import io.fd.hc2vpp.common.translate.util.AbstractInterfaceTypeCustomizer;
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+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.jvpp.core.dto.CreateVhostUserIf;
+import io.fd.jvpp.core.dto.CreateVhostUserIfReply;
+import io.fd.jvpp.core.dto.DeleteVhostUserIf;
+import io.fd.jvpp.core.dto.DeleteVhostUserIfReply;
+import io.fd.jvpp.core.dto.ModifyVhostUserIf;
+import io.fd.jvpp.core.dto.ModifyVhostUserIfReply;
+import io.fd.jvpp.core.future.FutureJVppCore;
+import java.nio.charset.StandardCharsets;
+import java.util.concurrent.CompletionStage;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VhostUserRole;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.VhostUser;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.InterfaceType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Writer Customizer responsible for passing vhost user interface CRD operations to VPP
+ */
+public class VhostUserCustomizer extends AbstractInterfaceTypeCustomizer<VhostUser>
+ implements ByteDataTranslator, JvppReplyConsumer {
+
+ private static final Logger LOG = LoggerFactory.getLogger(VhostUserCustomizer.class);
+ private final NamingContext interfaceContext;
+
+ public VhostUserCustomizer(@Nonnull final FutureJVppCore vppApi, @Nonnull final NamingContext interfaceContext) {
+ super(vppApi);
+ this.interfaceContext = interfaceContext;
+ }
+
+ @Override
+ protected Class<? extends InterfaceType> getExpectedInterfaceType() {
+ return org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VhostUser.class;
+ }
+
+ @Override
+ protected final void writeInterface(@Nonnull final InstanceIdentifier<VhostUser> id,
+ @Nonnull final VhostUser dataAfter, @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ final String swIfName = id.firstKeyOf(Interface.class).getName();
+ createVhostUserIf(id, swIfName, dataAfter, writeContext);
+ }
+
+ private void createVhostUserIf(final InstanceIdentifier<VhostUser> id, final String swIfName,
+ final VhostUser vhostUser, final WriteContext writeContext)
+ throws WriteFailedException {
+ LOG.debug("Creating vhost user interface: name={}, vhostUser={}", swIfName, vhostUser);
+
+ final CompletionStage<CreateVhostUserIfReply> createVhostUserIfReplyCompletionStage =
+ getFutureJVpp().createVhostUserIf(getCreateVhostUserIfRequest(vhostUser));
+ final CreateVhostUserIfReply reply =
+ getReplyForCreate(createVhostUserIfReplyCompletionStage.toCompletableFuture(), id, vhostUser);
+ LOG.debug("Vhost user interface created successfully for: {}, vhostUser: {}", swIfName, vhostUser);
+ // Add new interface to our interface context
+ interfaceContext.addName(reply.swIfIndex, swIfName, writeContext.getMappingContext());
+ }
+
+ private CreateVhostUserIf getCreateVhostUserIfRequest(final VhostUser vhostUser) {
+ CreateVhostUserIf request = new CreateVhostUserIf();
+ request.isServer = booleanToByte(VhostUserRole.Server.equals(vhostUser.getRole()));
+ request.sockFilename = vhostUser.getSocket().getBytes();
+ final Long deviceInstance = vhostUser.getDeviceInstance();
+ if (deviceInstance == null) {
+ request.renumber = 0;
+ } else {
+ request.renumber = 1;
+ request.customDevInstance = Math.toIntExact(deviceInstance);
+ }
+ final String tag = vhostUser.getTag();
+ if (tag != null) {
+ request.tag = tag.getBytes(StandardCharsets.US_ASCII);
+ }
+ request.useCustomMac = 0;
+ request.macAddress = new byte[]{};
+ return request;
+ }
+
+ @Override
+ public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<VhostUser> id,
+ @Nonnull final VhostUser dataBefore, @Nonnull final VhostUser dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ final String swIfName = id.firstKeyOf(Interface.class).getName();
+ modifyVhostUserIf(id, swIfName, dataBefore, dataAfter, writeContext);
+ }
+
+ private void modifyVhostUserIf(final InstanceIdentifier<VhostUser> id, final String swIfName,
+ final VhostUser vhostUserBefore, final VhostUser vhostUserAfter,
+ final WriteContext writeContext) throws WriteFailedException {
+ LOG.debug("Updating vhost user interface: name={}, vhostUser={}", swIfName, vhostUserAfter);
+ final CompletionStage<ModifyVhostUserIfReply> modifyVhostUserIfReplyCompletionStage =
+ getFutureJVpp()
+ .modifyVhostUserIf(getModifyVhostUserIfRequest(vhostUserAfter,
+ interfaceContext.getIndex(swIfName, writeContext.getMappingContext())));
+
+ getReplyForUpdate(modifyVhostUserIfReplyCompletionStage.toCompletableFuture(), id, vhostUserBefore,
+ vhostUserAfter);
+ LOG.debug("Vhost user interface updated successfully for: {}, vhostUser: {}", swIfName, vhostUserAfter);
+ }
+
+ private ModifyVhostUserIf getModifyVhostUserIfRequest(final VhostUser vhostUser, final int swIfIndex) {
+ ModifyVhostUserIf request = new ModifyVhostUserIf();
+ request.isServer = booleanToByte(VhostUserRole.Server.equals(vhostUser.getRole()));
+ request.sockFilename = vhostUser.getSocket().getBytes();
+ final Long deviceInstance = vhostUser.getDeviceInstance();
+ if (deviceInstance == null) {
+ request.renumber = 0;
+ } else {
+ request.renumber = 1;
+ request.customDevInstance = Math.toIntExact(deviceInstance);
+ }
+ request.swIfIndex = swIfIndex;
+ return request;
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<VhostUser> id,
+ @Nonnull final VhostUser dataBefore, @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ final String swIfName = id.firstKeyOf(Interface.class).getName();
+ deleteVhostUserIf(id, swIfName, dataBefore, writeContext);
+ }
+
+ private void deleteVhostUserIf(final InstanceIdentifier<VhostUser> id, final String swIfName,
+ final VhostUser vhostUser, final WriteContext writeContext)
+ throws WriteFailedException {
+ LOG.debug("Deleting vhost user interface: name={}, vhostUser={}", swIfName, vhostUser);
+ final CompletionStage<DeleteVhostUserIfReply> deleteVhostUserIfReplyCompletionStage =
+ getFutureJVpp().deleteVhostUserIf(getDeleteVhostUserIfRequest(
+ interfaceContext.getIndex(swIfName, writeContext.getMappingContext())));
+
+ getReplyForDelete(deleteVhostUserIfReplyCompletionStage.toCompletableFuture(), id);
+ LOG.debug("Vhost user interface deleted successfully for: {}, vhostUser: {}", swIfName, vhostUser);
+ // Remove interface from our interface context
+ interfaceContext.removeName(swIfName, writeContext.getMappingContext());
+ }
+
+ private DeleteVhostUserIf getDeleteVhostUserIfRequest(final int swIfIndex) {
+ DeleteVhostUserIf request = new DeleteVhostUserIf();
+ request.swIfIndex = swIfIndex;
+ return request;
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/VhostUserValidator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/VhostUserValidator.java
new file mode 100644
index 000000000..c6b84b2b4
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/VhostUserValidator.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2019 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.v3po.write;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.DataValidationFailedException;
+import io.fd.honeycomb.translate.write.Validator;
+import io.fd.honeycomb.translate.write.WriteContext;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.VhostUser;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class VhostUserValidator implements Validator<VhostUser> {
+
+ public VhostUserValidator(@Nonnull final NamingContext interfaceContext) {
+ checkNotNull(interfaceContext, "interfaceContext should not be null");
+ }
+
+ @Override
+ public void validateWrite(@Nonnull final InstanceIdentifier<VhostUser> id, @Nonnull final VhostUser dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.CreateValidationFailedException {
+ checkNotNull(dataAfter.getSocket(), "Socket cannot be null");
+ }
+
+ @Override
+ public void validateUpdate(@Nonnull final InstanceIdentifier<VhostUser> id, @Nonnull final VhostUser dataBefore,
+ @Nonnull final VhostUser dataAfter, @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.UpdateValidationFailedException {
+ checkNotNull(dataAfter.getSocket(), "Socket cannot be null");
+ }
+
+ @Override
+ public void validateDelete(@Nonnull final InstanceIdentifier<VhostUser> id, @Nonnull final VhostUser dataBefore,
+ @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.DeleteValidationFailedException {
+ // there is nothing to validate yet
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/VxlanCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/VxlanCustomizer.java
new file mode 100644
index 000000000..6cac99c38
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/VxlanCustomizer.java
@@ -0,0 +1,181 @@
+/*
+ * 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.v3po.write;
+
+import io.fd.hc2vpp.common.translate.util.AbstractInterfaceTypeCustomizer;
+import io.fd.hc2vpp.common.translate.util.AddressTranslator;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.v3po.DisabledInterfacesManager;
+import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.jvpp.core.dto.VxlanAddDelTunnel;
+import io.fd.jvpp.core.dto.VxlanAddDelTunnelReply;
+import io.fd.jvpp.core.future.FutureJVppCore;
+import java.util.concurrent.CompletionStage;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.L2Input;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.NshProxy;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VxlanTunnel;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Vxlan;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.InterfaceType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class VxlanCustomizer extends AbstractInterfaceTypeCustomizer<Vxlan> implements JvppReplyConsumer {
+
+ private static final Logger LOG = LoggerFactory.getLogger(VxlanCustomizer.class);
+
+ private final NamingContext interfaceNamingContext;
+ private final DisabledInterfacesManager interfaceDisableContext;
+
+ public VxlanCustomizer(@Nonnull final FutureJVppCore vppApi,
+ @Nonnull final NamingContext interfaceNamingContext,
+ @Nonnull final DisabledInterfacesManager interfaceDisableContext) {
+ super(vppApi);
+ this.interfaceNamingContext = interfaceNamingContext;
+ this.interfaceDisableContext = interfaceDisableContext;
+ }
+
+ @Override
+ protected Class<? extends InterfaceType> getExpectedInterfaceType() {
+ return VxlanTunnel.class;
+ }
+
+ @Override
+ protected final void writeInterface(@Nonnull final InstanceIdentifier<Vxlan> id, @Nonnull final Vxlan dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ final String swIfName = id.firstKeyOf(Interface.class).getName();
+ createVxlanTunnel(id, swIfName, dataAfter, writeContext);
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Vxlan> id, @Nonnull final Vxlan dataBefore,
+ @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ final String swIfName = id.firstKeyOf(Interface.class).getName();
+ deleteVxlanTunnel(id, swIfName, dataBefore, writeContext);
+ }
+
+ private void createVxlanTunnel(final InstanceIdentifier<Vxlan> id, final String swIfName, final Vxlan vxlan,
+ final WriteContext writeContext)
+ throws WriteFailedException {
+ final byte isIpv6 = (byte) (isIpv6(vxlan)
+ ? 1
+ : 0);
+
+ int encapVrfId = vxlan.getEncapVrfId().getValue().intValue();
+ int vni = vxlan.getVni().getValue().intValue();
+
+ int decapNext = -1;
+ if (vxlan.getDecapNext() == L2Input.class) {
+ decapNext = 1;
+ } else if (vxlan.getDecapNext() == NshProxy.class) {
+ decapNext = 2;
+ }
+
+ LOG.debug("Setting vxlan tunnel for interface: {}. Vxlan: {}", swIfName, vxlan);
+ final CompletionStage<VxlanAddDelTunnelReply> vxlanAddDelTunnelReplyCompletionStage =
+ getFutureJVpp().vxlanAddDelTunnel(getVxlanTunnelRequest((byte) 1 /* is add */, vxlan.getSrc(),
+ vxlan.getDst(), encapVrfId, decapNext, vni, isIpv6));
+
+ final VxlanAddDelTunnelReply reply =
+ getReplyForCreate(vxlanAddDelTunnelReplyCompletionStage.toCompletableFuture(), id, vxlan);
+ LOG.debug("Vxlan tunnel set successfully for: {}, vxlan: {}", swIfName, vxlan);
+ if (interfaceNamingContext.containsName(reply.swIfIndex, writeContext.getMappingContext())) {
+ // VPP keeps vxlan tunnels present even after they are delete(reserving ID for next tunnel)
+ // This may cause inconsistencies in mapping context when configuring tunnels like this:
+ // 1. Add tunnel 2. Delete tunnel 3. Read interfaces (reserved mapping e.g. vxlan_tunnel0 -> 6
+ // will get into mapping context) 4. Add tunnel (this will add another mapping with the same
+ // reserved ID and context is invalid)
+ // That's why a check has to be performed here removing mapping vxlan_tunnel0 -> 6 mapping and storing
+ // new name for that ID
+ final String formerName = interfaceNamingContext.getName(reply.swIfIndex, writeContext.getMappingContext());
+ LOG.debug("Removing updated mapping of a vxlan tunnel, id: {}, former name: {}, new name: {}",
+ reply.swIfIndex, formerName, swIfName);
+ interfaceNamingContext.removeName(formerName, writeContext.getMappingContext());
+
+ }
+
+ // Removing disability of an interface in case a vxlan tunnel formerly deleted is being reused in VPP
+ // further details in above comment
+ if (interfaceDisableContext.isInterfaceDisabled(reply.swIfIndex, writeContext.getMappingContext())) {
+ LOG.debug("Removing disability of vxlan tunnel, id: {}, name: {}", reply.swIfIndex, swIfName);
+ interfaceDisableContext.removeDisabledInterface(reply.swIfIndex, writeContext.getMappingContext());
+ }
+
+ // Add new interface to our interface context
+ interfaceNamingContext.addName(reply.swIfIndex, swIfName, writeContext.getMappingContext());
+ }
+
+ private boolean isIpv6(final Vxlan vxlan) {
+ return vxlan.getSrc().getIpv4AddressNoZone() == null;
+
+ }
+
+ private void deleteVxlanTunnel(final InstanceIdentifier<Vxlan> id, final String swIfName, final Vxlan vxlan,
+ final WriteContext writeContext) throws WriteFailedException {
+ final byte isIpv6 = (byte) (isIpv6(vxlan)
+ ? 1
+ : 0);
+
+ int encapVrfId = vxlan.getEncapVrfId().getValue().intValue();
+ int vni = vxlan.getVni().getValue().intValue();
+
+ int decapNext = -1;
+ if (vxlan.getDecapNext() == L2Input.class) {
+ decapNext = 1;
+ } else if (vxlan.getDecapNext() == NshProxy.class) {
+ decapNext = 2;
+ }
+
+ LOG.debug("Deleting vxlan tunnel for interface: {}. Vxlan: {}", swIfName, vxlan);
+ final CompletionStage<VxlanAddDelTunnelReply> vxlanAddDelTunnelReplyCompletionStage =
+ getFutureJVpp().vxlanAddDelTunnel(getVxlanTunnelRequest((byte) 0 /* is add */, vxlan.getSrc(),
+ vxlan.getDst(), encapVrfId, decapNext, vni, isIpv6));
+
+ getReplyForDelete(vxlanAddDelTunnelReplyCompletionStage.toCompletableFuture(), id);
+ LOG.debug("Vxlan tunnel deleted successfully for: {}, vxlan: {}", swIfName, vxlan);
+
+ final int index = interfaceNamingContext.getIndex(swIfName, writeContext.getMappingContext());
+ // Mark this interface as disabled to not include it in operational reads
+ // because VPP will keep the interface there
+ LOG.debug("Marking vxlan tunnel as disabled, id: {}, name: {}", index, swIfName);
+ interfaceDisableContext.disableInterface(index, writeContext.getMappingContext());
+ // Remove interface from our interface naming context
+ interfaceNamingContext.removeName(swIfName, writeContext.getMappingContext());
+ }
+
+ private static VxlanAddDelTunnel getVxlanTunnelRequest(final byte isAdd, final IpAddressNoZone srcAddr,
+ final IpAddressNoZone dstAddr,
+ final int encapVrfId,
+ final int decapNextIndex, final int vni, final byte isIpv6) {
+ final VxlanAddDelTunnel vxlanAddDelTunnel = new VxlanAddDelTunnel();
+ vxlanAddDelTunnel.isAdd = isAdd;
+ vxlanAddDelTunnel.srcAddress = AddressTranslator.INSTANCE.ipAddressToArray(srcAddr);
+ vxlanAddDelTunnel.dstAddress = AddressTranslator.INSTANCE.ipAddressToArray(dstAddr);
+ vxlanAddDelTunnel.encapVrfId = encapVrfId;
+ vxlanAddDelTunnel.vni = vni;
+ vxlanAddDelTunnel.decapNextIndex = decapNextIndex;
+ vxlanAddDelTunnel.isIpv6 = isIpv6;
+ return vxlanAddDelTunnel;
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/VxlanGpeCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/VxlanGpeCustomizer.java
new file mode 100644
index 000000000..b435fa169
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/VxlanGpeCustomizer.java
@@ -0,0 +1,164 @@
+/*
+ * 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.v3po.write;
+
+import io.fd.hc2vpp.common.translate.util.AbstractInterfaceTypeCustomizer;
+import io.fd.hc2vpp.common.translate.util.AddressTranslator;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.v3po.DisabledInterfacesManager;
+import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.jvpp.core.dto.VxlanGpeAddDelTunnel;
+import io.fd.jvpp.core.dto.VxlanGpeAddDelTunnelReply;
+import io.fd.jvpp.core.future.FutureJVppCore;
+import java.util.concurrent.CompletionStage;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VxlanGpeTunnel;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.VxlanGpe;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.InterfaceType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class VxlanGpeCustomizer extends AbstractInterfaceTypeCustomizer<VxlanGpe> implements JvppReplyConsumer {
+
+ private static final Logger LOG = LoggerFactory.getLogger(VxlanGpeCustomizer.class);
+ private final NamingContext interfaceNamingContext;
+ private final DisabledInterfacesManager interfaceDisableContext;
+
+ public VxlanGpeCustomizer(@Nonnull final FutureJVppCore vppApi,
+ @Nonnull final NamingContext interfaceNamingContext,
+ @Nonnull final DisabledInterfacesManager interfaceDisableContext) {
+ super(vppApi);
+ this.interfaceNamingContext = interfaceNamingContext;
+ this.interfaceDisableContext = interfaceDisableContext;
+ }
+
+ @Override
+ protected Class<? extends InterfaceType> getExpectedInterfaceType() {
+ return VxlanGpeTunnel.class;
+ }
+
+ @Override
+ protected final void writeInterface(@Nonnull final InstanceIdentifier<VxlanGpe> id,
+ @Nonnull final VxlanGpe dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ final String swIfName = id.firstKeyOf(Interface.class).getName();
+ createVxlanGpeTunnel(id, swIfName, dataAfter, writeContext);
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<VxlanGpe> id,
+ @Nonnull final VxlanGpe dataBefore,
+ @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ final String swIfName = id.firstKeyOf(Interface.class).getName();
+ deleteVxlanGpeTunnel(id, swIfName, dataBefore, writeContext);
+ }
+
+ private void createVxlanGpeTunnel(final InstanceIdentifier<VxlanGpe> id, final String swIfName,
+ final VxlanGpe vxlanGpe, final WriteContext writeContext)
+ throws WriteFailedException {
+ final byte isIpv6 = (byte) (isIpv6(vxlanGpe)
+ ? 1
+ : 0);
+
+ int vni = vxlanGpe.getVni().getValue().intValue();
+ byte protocol = (byte) vxlanGpe.getNextProtocol().getIntValue();
+ int encapVrfId = vxlanGpe.getEncapVrfId().intValue();
+ int decapVrfId = vxlanGpe.getDecapVrfId().intValue();
+
+ LOG.debug("Setting VxlanGpe tunnel for interface: {}. VxlanGpe: {}", swIfName, vxlanGpe);
+ final CompletionStage<VxlanGpeAddDelTunnelReply> VxlanGpeAddDelTunnelReplyCompletionStage =
+ getFutureJVpp()
+ .vxlanGpeAddDelTunnel(getVxlanGpeTunnelRequest((byte) 1 /* is add */, vxlanGpe.getLocal(),
+ vxlanGpe.getRemote(), vni, protocol, encapVrfId, decapVrfId, isIpv6));
+
+ final VxlanGpeAddDelTunnelReply reply =
+ getReplyForCreate(VxlanGpeAddDelTunnelReplyCompletionStage.toCompletableFuture(), id, vxlanGpe);
+ LOG.debug("VxlanGpe tunnel set successfully for: {}, VxlanGpe: {}", swIfName, vxlanGpe);
+ if (interfaceNamingContext.containsName(reply.swIfIndex, writeContext.getMappingContext())) {
+ final String formerName = interfaceNamingContext.getName(reply.swIfIndex, writeContext.getMappingContext());
+ LOG.debug("Removing updated mapping of a vxlan-gpe tunnel, id: {}, former name: {}, new name: {}",
+ reply.swIfIndex, formerName, swIfName);
+ interfaceNamingContext.removeName(formerName, writeContext.getMappingContext());
+ }
+
+ // Removing disability of an interface in case a vxlan-gpe tunnel formerly deleted is being reused in VPP
+ // further details in above comment
+ if (interfaceDisableContext.isInterfaceDisabled(reply.swIfIndex, writeContext.getMappingContext())) {
+ LOG.debug("Removing disability of vxlan tunnel, id: {}, name: {}", reply.swIfIndex, swIfName);
+ interfaceDisableContext.removeDisabledInterface(reply.swIfIndex, writeContext.getMappingContext());
+ }
+
+ // Add new interface to our interface context
+ interfaceNamingContext.addName(reply.swIfIndex, swIfName, writeContext.getMappingContext());
+ }
+
+ private boolean isIpv6(final VxlanGpe vxlanGpe) {
+ return vxlanGpe.getLocal().getIpv4AddressNoZone() == null;
+
+ }
+
+ private void deleteVxlanGpeTunnel(final InstanceIdentifier<VxlanGpe> id, final String swIfName,
+ final VxlanGpe vxlanGpe, final WriteContext writeContext)
+ throws WriteFailedException {
+ final byte isIpv6 = (byte) (isIpv6(vxlanGpe)
+ ? 1
+ : 0);
+
+ int vni = vxlanGpe.getVni().getValue().intValue();
+ byte protocol = (byte) vxlanGpe.getNextProtocol().getIntValue();
+ int encapVrfId = vxlanGpe.getEncapVrfId().intValue();
+ int decapVrfId = vxlanGpe.getDecapVrfId().intValue();
+
+ LOG.debug("Deleting VxlanGpe tunnel for interface: {}. VxlanGpe: {}", swIfName, vxlanGpe);
+ final CompletionStage<VxlanGpeAddDelTunnelReply> VxlanGpeAddDelTunnelReplyCompletionStage =
+ getFutureJVpp()
+ .vxlanGpeAddDelTunnel(getVxlanGpeTunnelRequest((byte) 0 /* is delete */, vxlanGpe.getLocal(),
+ vxlanGpe.getRemote(), vni, protocol, encapVrfId, decapVrfId, isIpv6));
+ getReplyForDelete(VxlanGpeAddDelTunnelReplyCompletionStage.toCompletableFuture(), id);
+ final int index = interfaceNamingContext.getIndex(swIfName, writeContext.getMappingContext());
+ // Mark this interface as disabled to not include it in operational reads
+ // because VPP will keep the interface there
+ LOG.debug("Marking vxlan tunnel as disabled, id: {}, name: {}", index, swIfName);
+ interfaceDisableContext.disableInterface(index, writeContext.getMappingContext());
+ // Remove interface from our interface naming context
+ interfaceNamingContext.removeName(swIfName, writeContext.getMappingContext());
+ }
+
+ private static VxlanGpeAddDelTunnel getVxlanGpeTunnelRequest(final byte isAdd, final IpAddressNoZone local,
+ final IpAddressNoZone remote,
+ final int vni, final byte protocol,
+ final int encapVrfId, final int decapVrfId,
+ final byte isIpv6) {
+ final VxlanGpeAddDelTunnel VxlanGpeAddDelTunnel = new VxlanGpeAddDelTunnel();
+ VxlanGpeAddDelTunnel.isAdd = isAdd;
+ VxlanGpeAddDelTunnel.local = AddressTranslator.INSTANCE.ipAddressToArray(local);
+ VxlanGpeAddDelTunnel.remote = AddressTranslator.INSTANCE.ipAddressToArray(remote);
+ VxlanGpeAddDelTunnel.vni = vni;
+ VxlanGpeAddDelTunnel.protocol = protocol;
+ VxlanGpeAddDelTunnel.encapVrfId = encapVrfId;
+ VxlanGpeAddDelTunnel.decapVrfId = decapVrfId;
+ VxlanGpeAddDelTunnel.isIpv6 = isIpv6;
+ return VxlanGpeAddDelTunnel;
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/VxlanGpeValidator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/VxlanGpeValidator.java
new file mode 100644
index 000000000..3be51b8df
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/VxlanGpeValidator.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2019 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.v3po.write;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.v3po.DisabledInterfacesManager;
+import io.fd.honeycomb.translate.write.DataValidationFailedException;
+import io.fd.honeycomb.translate.write.Validator;
+import io.fd.honeycomb.translate.write.WriteContext;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.VxlanGpe;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class VxlanGpeValidator implements Validator<VxlanGpe> {
+
+ public VxlanGpeValidator(@Nonnull final NamingContext interfaceNamingContext,
+ @Nonnull final DisabledInterfacesManager interfaceDisableContext) {
+ checkNotNull(interfaceNamingContext, "interfaceContext should not be null");
+ checkNotNull(interfaceDisableContext, "DisabledInterfacesManager should not be null");
+ }
+
+ @Override
+ public void validateWrite(@Nonnull final InstanceIdentifier<VxlanGpe> id, @Nonnull final VxlanGpe dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.CreateValidationFailedException {
+ try {
+ validateVxlanGpe(dataAfter);
+ } catch (Exception e) {
+ throw new DataValidationFailedException.CreateValidationFailedException(id, dataAfter, e);
+ }
+ }
+
+ @Override
+ public void validateDelete(@Nonnull final InstanceIdentifier<VxlanGpe> id, @Nonnull final VxlanGpe dataBefore,
+ @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.DeleteValidationFailedException {
+ try {
+ validateVxlanGpe(dataBefore);
+ } catch (Exception e) {
+ throw new DataValidationFailedException.DeleteValidationFailedException(id, e);
+ }
+ }
+
+ private void validateVxlanGpe(final VxlanGpe data) {
+ checkNotNull(data.getLocal(), "Local address cannot be null");
+ checkNotNull(data.getRemote(), "Remote address cannot be null");
+ if (data.getLocal().getIpv4AddressNoZone() == null) {
+ checkArgument(data.getRemote().getIpv4AddressNoZone() == null, "Inconsistent ip addresses: %s, %s",
+ data.getLocal(),
+ data.getRemote());
+ } else {
+ checkArgument(data.getRemote().getIpv6AddressNoZone() == null, "Inconsistent ip addresses: %s, %s",
+ data.getLocal(),
+ data.getRemote());
+ }
+ checkNotNull(data.getEncapVrfId(), "encap-vrf-id is mandatory but was not given");
+ checkNotNull(data.getDecapVrfId(), "decap-vrf-id is mandatory but was not given");
+ checkNotNull(data.getVni(), "VNI cannot be null");
+ checkNotNull(data.getNextProtocol(), "Next protocol cannot be null");
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/VxlanValidator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/VxlanValidator.java
new file mode 100644
index 000000000..5ca34fdd4
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/VxlanValidator.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2019 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.v3po.write;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.v3po.DisabledInterfacesManager;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.CreateValidationFailedException;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.DeleteValidationFailedException;
+import io.fd.honeycomb.translate.write.Validator;
+import io.fd.honeycomb.translate.write.WriteContext;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Vxlan;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class VxlanValidator implements Validator<Vxlan> {
+
+ public VxlanValidator(@Nonnull final NamingContext interfaceNamingContext,
+ @Nonnull final DisabledInterfacesManager disabledInterfacesManager) {
+ checkNotNull(interfaceNamingContext, "interfaceContext should not be null");
+ checkNotNull(disabledInterfacesManager, "disabledInterfacesManager should not be null");
+ }
+
+ @Override
+ public void validateWrite(@Nonnull final InstanceIdentifier<Vxlan> id, @Nonnull final Vxlan dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws CreateValidationFailedException {
+ try {
+ validateVxlan(dataAfter);
+ } catch (Exception e) {
+ throw new CreateValidationFailedException(id, dataAfter, e);
+ }
+ }
+
+ @Override
+ public void validateDelete(@Nonnull final InstanceIdentifier<Vxlan> id, @Nonnull final Vxlan dataBefore,
+ @Nonnull final WriteContext writeContext)
+ throws DeleteValidationFailedException {
+ try {
+ validateVxlan(dataBefore);
+ } catch (Exception e) {
+ throw new DeleteValidationFailedException(id, e);
+ }
+ }
+
+ private void validateVxlan(final Vxlan data) {
+
+ checkNotNull(data.getSrc(), "Source cannot be null");
+ checkNotNull(data.getDst(), "Destination cannot be null");
+ if (data.getSrc().getIpv4AddressNoZone() == null) {
+ checkArgument(data.getDst().getIpv4AddressNoZone() == null, "Inconsistent ip addresses: %s, %s",
+ data.getSrc(),
+ data.getDst());
+ } else {
+ checkArgument(data.getDst().getIpv6AddressNoZone() == null, "Inconsistent ip addresses: %s, %s",
+ data.getSrc(),
+ data.getDst());
+ }
+ checkArgument(data.getEncapVrfId() != null && data.getEncapVrfId().getValue() != null,
+ "encap-vrf-id is mandatory but was not given");
+ checkNotNull(data.getVni(), "VNI cannot be null");
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/pbb/PbbRewriteCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/pbb/PbbRewriteCustomizer.java
new file mode 100644
index 000000000..42d6b1969
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/pbb/PbbRewriteCustomizer.java
@@ -0,0 +1,111 @@
+/*
+ * 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.v3po.write.pbb;
+
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.hc2vpp.common.translate.util.MacTranslator;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.spi.write.WriterCustomizer;
+import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.jvpp.VppBaseCallException;
+import io.fd.jvpp.core.dto.L2InterfacePbbTagRewrite;
+import io.fd.jvpp.core.future.FutureJVppCore;
+import java.util.concurrent.TimeoutException;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.pbb.rev161214.interfaces._interface.PbbRewrite;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class PbbRewriteCustomizer extends FutureJVppCustomizer
+ implements WriterCustomizer<PbbRewrite>, MacTranslator, JvppReplyConsumer {
+
+ private static final int OPERATION_DISABLE = 0;
+
+ private final NamingContext interfaceNamingContext;
+
+ public PbbRewriteCustomizer(@Nonnull final FutureJVppCore futureJVppCore,
+ @Nonnull final NamingContext interfaceNamingContext) {
+ super(futureJVppCore);
+ this.interfaceNamingContext = interfaceNamingContext;
+ }
+
+ @Override
+ public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<PbbRewrite> id,
+ @Nonnull final PbbRewrite dataAfter, @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ try {
+ setPbbRewrite(id, dataAfter, writeContext, false);
+ } catch (TimeoutException | VppBaseCallException e) {
+ throw new WriteFailedException.CreateFailedException(id, dataAfter, e);
+ }
+ }
+
+ @Override
+ public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<PbbRewrite> id,
+ @Nonnull final PbbRewrite dataBefore, @Nonnull final PbbRewrite dataAfter,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ try {
+ setPbbRewrite(id, dataAfter, writeContext, false);
+ } catch (TimeoutException | VppBaseCallException e) {
+ throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, e);
+ }
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<PbbRewrite> id,
+ @Nonnull final PbbRewrite dataBefore, @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+
+ try {
+ setPbbRewrite(id, dataBefore, writeContext, true);
+ } catch (TimeoutException | VppBaseCallException e) {
+ throw new WriteFailedException.DeleteFailedException(id, e);
+ }
+ }
+
+ private void setPbbRewrite(final InstanceIdentifier<PbbRewrite> id, final PbbRewrite data,
+ final WriteContext writeContext, final boolean disable)
+ throws TimeoutException, VppBaseCallException {
+ final String interfaceName = id.firstKeyOf(Interface.class).getName();
+
+ final L2InterfacePbbTagRewrite request = new L2InterfacePbbTagRewrite();
+
+ //checking all attributes in preconditions(pbb-rewrite is subcontainer, so there can't be mandatory statements)
+ request.swIfIndex = interfaceNamingContext.getIndex(interfaceName, writeContext.getMappingContext());
+ request.bDmac = parseMac(data.getDestinationAddress().getValue());
+ request.bSmac = parseMac(data.getSourceAddress().getValue());
+ request.bVlanid = data.getBVlanTagVlanId().shortValue();
+ request.iSid = data.getITagIsid().intValue();
+ request.vtrOp = verifiedOperation(data, disable);
+
+ //not sure whats gonna happen to this attribute, so its left optional for now
+ if (data.getOuterTag() != null) {
+ request.outerTag = data.getOuterTag().shortValue();
+ }
+
+ getReply(getFutureJVpp().l2InterfacePbbTagRewrite(request).toCompletableFuture());
+ }
+
+ // if disabled ,then uses non-public allowed value 0, which is equal to operation disable
+ private int verifiedOperation(final PbbRewrite data, final boolean disable) {
+ return disable
+ ? OPERATION_DISABLE
+ : data.getInterfaceOperation().getIntValue();
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/pbb/PbbRewriteValidator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/pbb/PbbRewriteValidator.java
new file mode 100644
index 000000000..90ea236a0
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/pbb/PbbRewriteValidator.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2019 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.v3po.write.pbb;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.DataValidationFailedException;
+import io.fd.honeycomb.translate.write.Validator;
+import io.fd.honeycomb.translate.write.WriteContext;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.pbb.rev161214.interfaces._interface.PbbRewrite;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class PbbRewriteValidator implements Validator<PbbRewrite> {
+
+
+ public PbbRewriteValidator(@Nonnull final NamingContext interfaceNamingContext) {
+ checkNotNull(interfaceNamingContext, "Interface naming context cannot be null");
+ }
+
+ @Override
+ public void validateWrite(@Nonnull final InstanceIdentifier<PbbRewrite> id, @Nonnull final PbbRewrite dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.CreateValidationFailedException {
+ try {
+ validatePbbRewrite(id, dataAfter, false);
+ } catch(Exception e) {
+ throw new DataValidationFailedException.CreateValidationFailedException(id, dataAfter, e);
+ }
+ }
+
+ @Override
+ public void validateUpdate(@Nonnull final InstanceIdentifier<PbbRewrite> id, @Nonnull final PbbRewrite dataBefore,
+ @Nonnull final PbbRewrite dataAfter, @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.UpdateValidationFailedException {
+
+ try {
+ validatePbbRewrite(id, dataAfter, false);
+ } catch(Exception e) {
+ throw new DataValidationFailedException.UpdateValidationFailedException(id, dataBefore, dataAfter, e);
+ }
+ }
+
+ @Override
+ public void validateDelete(@Nonnull final InstanceIdentifier<PbbRewrite> id, @Nonnull final PbbRewrite dataBefore,
+ @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.DeleteValidationFailedException {
+ try {
+ validatePbbRewrite(id, dataBefore, true);
+ } catch(Exception e) {
+ throw new DataValidationFailedException.DeleteValidationFailedException(id, e);
+ }
+ }
+
+ private void validatePbbRewrite(final InstanceIdentifier<PbbRewrite> id, @Nonnull final PbbRewrite data,
+ final boolean disable) {
+ checkNotNull(id.firstKeyOf(Interface.class), "Interface key not found");
+ checkNotNull(data.getDestinationAddress(), "Destination address cannot be null");
+ checkNotNull(data.getSourceAddress(), "Source address cannot be null");
+ checkNotNull(data.getBVlanTagVlanId(), "BVlan id cannot be null");
+ checkNotNull(data.getITagIsid(), "ISid cannot be null");
+ if (disable) {
+ checkNotNull(data.getInterfaceOperation(), "Operation cannot be null");
+ }
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/span/MirroredInterfaceCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/span/MirroredInterfaceCustomizer.java
new file mode 100644
index 000000000..31b129537
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/span/MirroredInterfaceCustomizer.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2017 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.v3po.write.span;
+
+import static io.fd.honeycomb.translate.util.RWUtils.cutId;
+
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer;
+import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.jvpp.core.dto.SwInterfaceSpanEnableDisable;
+import io.fd.jvpp.core.future.FutureJVppCore;
+import java.util.function.Function;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.SpanState;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.span.attributes.MirroredInterfaces;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.span.attributes.mirrored.interfaces.MirroredInterface;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.span.attributes.mirrored.interfaces.MirroredInterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class MirroredInterfaceCustomizer extends FutureJVppCustomizer
+ implements ListWriterCustomizer<MirroredInterface, MirroredInterfaceKey>, JvppReplyConsumer {
+
+ private static final Logger LOG = LoggerFactory.getLogger(MirroredInterfaceCustomizer.class);
+
+ private final NamingContext ifcContext;
+ private final Function<InstanceIdentifier<MirroredInterfaces>, String> destinationInterfaceNameExtractor;
+
+ public MirroredInterfaceCustomizer(@Nonnull final FutureJVppCore futureJVppCore,
+ @Nonnull final NamingContext ifcContext,
+ @Nonnull final Function<InstanceIdentifier<MirroredInterfaces>, String> destinationInterfaceNameExtractor) {
+ super(futureJVppCore);
+ this.ifcContext = ifcContext;
+ this.destinationInterfaceNameExtractor = destinationInterfaceNameExtractor;
+ }
+
+
+ @Override
+ public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<MirroredInterface> id,
+ @Nonnull final MirroredInterface mirroredInterface,
+ @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ final String destinationInterfaceName =
+ destinationInterfaceNameExtractor.apply(cutId(id, MirroredInterfaces.class));
+ final String sourceInterfaceName = mirroredInterface.getIfaceRef();
+ final SpanState spanState = mirroredInterface.getState();
+
+ LOG.debug("Enabling span for source interface {} | destination interface {} | state {}", sourceInterfaceName,
+ destinationInterfaceName, spanState);
+
+ getReplyForWrite(getFutureJVpp().swInterfaceSpanEnableDisable(
+ getSpanAddDelRequest(
+ interfaceId(writeContext, ifcContext, destinationInterfaceName),
+ interfaceId(writeContext, ifcContext, sourceInterfaceName),
+ true,
+ spanState))
+ .toCompletableFuture(), id);
+ LOG.debug("Span for source interface {} | destination interface {} | state {} successfully enabled",
+ sourceInterfaceName, destinationInterfaceName, spanState);
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<MirroredInterface> id,
+ @Nonnull final MirroredInterface mirroredInterface,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ final String destinationInterfaceName =
+ destinationInterfaceNameExtractor.apply(cutId(id, MirroredInterfaces.class));
+ final String sourceInterfaceName = mirroredInterface.getIfaceRef();
+ LOG.debug("Disabling span for source interface {} | destination interface {} ", sourceInterfaceName,
+ destinationInterfaceName);
+
+ getReplyForWrite(getFutureJVpp().swInterfaceSpanEnableDisable(
+ getSpanAddDelRequest(
+ interfaceId(writeContext, ifcContext, destinationInterfaceName),
+ interfaceId(writeContext, ifcContext, sourceInterfaceName),
+ false,
+ null))
+ .toCompletableFuture(), id);
+ LOG.debug("Span for source interface {} | destination interface {} successfully disabled",
+ sourceInterfaceName, destinationInterfaceName);
+ }
+
+ private SwInterfaceSpanEnableDisable getSpanAddDelRequest(final int dstId, final Integer srcId, final boolean isAdd,
+ @Nullable final SpanState state) {
+ final SwInterfaceSpanEnableDisable spanAddDel = new SwInterfaceSpanEnableDisable();
+ spanAddDel.state = (byte) (isAdd
+ ? state != null
+ ? state.getIntValue()
+ : 0
+ : 0);// either one of 1(rx),2(tx),3(both) or 0 for disable/delete
+ spanAddDel.swIfIndexFrom = srcId;
+ spanAddDel.swIfIndexTo = dstId;
+ return spanAddDel;
+ }
+
+ private static int interfaceId(final WriteContext writeContext, final NamingContext ifcContext, final String name) {
+ return ifcContext.getIndex(name, writeContext.getMappingContext());
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/span/MirroredInterfaceValidator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/span/MirroredInterfaceValidator.java
new file mode 100644
index 000000000..90c740be8
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/write/span/MirroredInterfaceValidator.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2019 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.v3po.write.span;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.DataValidationFailedException;
+import io.fd.honeycomb.translate.write.Validator;
+import io.fd.honeycomb.translate.write.WriteContext;
+import java.util.function.Function;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.span.attributes.MirroredInterfaces;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.span.attributes.mirrored.interfaces.MirroredInterface;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class MirroredInterfaceValidator implements Validator<MirroredInterface> {
+
+ public MirroredInterfaceValidator(@Nonnull final NamingContext ifcContext,
+ @Nonnull final Function<InstanceIdentifier<MirroredInterfaces>, String> destinationInterfaceNameExtractor) {
+ checkNotNull(ifcContext, "Interface naming context cannot be null");
+ checkNotNull(destinationInterfaceNameExtractor, "Destination Interface Name extractor cannot be null");
+ }
+
+ @Override
+ public void validateWrite(@Nonnull final InstanceIdentifier<MirroredInterface> id,
+ @Nonnull final MirroredInterface dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.CreateValidationFailedException {
+ try {
+ checkMirroredInterfaceData(dataAfter);
+ } catch (Exception e) {
+ throw new DataValidationFailedException.CreateValidationFailedException(id, dataAfter, e);
+ }
+ }
+
+ @Override
+ public void validateUpdate(@Nonnull final InstanceIdentifier<MirroredInterface> id,
+ @Nonnull final MirroredInterface dataBefore,
+ @Nonnull final MirroredInterface dataAfter, @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.UpdateValidationFailedException {
+ try {
+ checkMirroredInterfaceData(dataAfter);
+ } catch (Exception e) {
+ throw new DataValidationFailedException.UpdateValidationFailedException(id, dataBefore, dataAfter, e);
+ }
+ }
+
+ @Override
+ public void validateDelete(@Nonnull final InstanceIdentifier<MirroredInterface> id,
+ @Nonnull final MirroredInterface dataBefore,
+ @Nonnull final WriteContext writeContext)
+ throws DataValidationFailedException.DeleteValidationFailedException {
+ try {
+ checkMirroredInterfaceData(dataBefore);
+ } catch (Exception e) {
+ throw new DataValidationFailedException.DeleteValidationFailedException(id, e);
+ }
+ }
+
+ private void checkMirroredInterfaceData(final MirroredInterface data) {
+ checkNotNull(data.getIfaceRef(), "IfaceRef cannot be null");
+ checkNotNull(data.getState(), "State cannot be null");
+ }
+}