summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTibor Král <tibor.kral@pantheon.tech>2018-10-03 17:23:08 +0200
committerMichal Cmarada <mcmarada@cisco.com>2018-10-17 18:11:19 +0200
commite4c6d641269efdff2eb1212a54f06683cb99d3d3 (patch)
treeda49ebf995ee538d04f7bbe5c85d73354fb52c00
parentb3c731b754efc83230ea49cc579f8101b8750190 (diff)
HC2VPP-390: Tap v2 interface implementation
Change-Id: I92fe8adabbb770a45ad47c56f5cd21262c4bd6e1 Signed-off-by: Tibor Král <tibor.kral@pantheon.tech> Signed-off-by: Michal Cmarada <mcmarada@cisco.com>
-rw-r--r--v3po/postman_rest_collection.json97
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/factory/InterfacesStateReaderFactory.java5
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/factory/InterfacesWriterFactory.java8
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/TapV2Customizer.java227
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/InterfaceDataTranslator.java7
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/TapV2Customizer.java212
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/TapV2CustomizerTest.java162
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/InterfaceDataTranslatorTest.java7
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/TapCustomizerTest.java2
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/TapV2CustomizerTest.java142
10 files changed, 848 insertions, 21 deletions
diff --git a/v3po/postman_rest_collection.json b/v3po/postman_rest_collection.json
index cdfa047a1..a65327788 100644
--- a/v3po/postman_rest_collection.json
+++ b/v3po/postman_rest_collection.json
@@ -1,6 +1,6 @@
{
"info": {
- "_postman_id": "8204419d-8019-4b29-b758-4a0693efe2cb",
+ "_postman_id": "b7fd7461-3b63-40ed-9aee-dd9668109865",
"name": "Honeycomb V3PO RESTCONF calls",
"description": "Common mgmt operations on VPP core using Honeycomb REST interface",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
@@ -8,7 +8,6 @@
"item": [
{
"name": "Loopback",
- "description": null,
"item": [
{
"name": "Add loopback ifc - cfg ",
@@ -88,7 +87,6 @@
},
{
"name": "Bridge Domain management",
- "description": null,
"item": [
{
"name": "Create bridge domain - cfg",
@@ -599,7 +597,6 @@
},
{
"name": "Context",
- "description": null,
"item": [
{
"name": "List naming contexts - context",
@@ -710,7 +707,6 @@
},
{
"name": "ETH",
- "description": "Example requests for management of Ethernet type interfaces",
"item": [
{
"name": "Set interface mtu",
@@ -822,11 +818,11 @@
},
"response": []
}
- ]
+ ],
+ "description": "Example requests for management of Ethernet type interfaces"
},
{
"name": "GRE-TUNNEL",
- "description": null,
"item": [
{
"name": "Add gre ifc - cfg",
@@ -904,7 +900,6 @@
},
{
"name": "PBB",
- "description": null,
"item": [
{
"name": "Enable local0 + configure Pbb",
@@ -1055,7 +1050,6 @@
},
{
"name": "IP",
- "description": null,
"item": [
{
"name": "Ip Neighbour Get",
@@ -1489,7 +1483,6 @@
},
{
"name": "SPAN",
- "description": null,
"item": [
{
"name": "Set port mirroring local0 -> GigabiteEthernet0/8/0",
@@ -1608,7 +1601,6 @@
},
{
"name": "TAP",
- "description": null,
"item": [
{
"name": "Add simple tap ifc -cfg",
@@ -1757,8 +1749,85 @@
]
},
{
+ "name": "TAPV2",
+ "item": [
+ {
+ "name": "Add tapV2 ifc -cfg",
+ "request": {
+ "method": "PUT",
+ "header": [
+ {
+ "key": "Authorization",
+ "value": "Basic YWRtaW46YWRtaW4="
+ },
+ {
+ "key": "Content-Type",
+ "value": "application/json"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"interface\": [\n {\n \"name\": \"tap-v2\",\n \"description\": \"for testing purposes\",\n \"type\": \"v3po:tap-v2\",\n \"tap-v2\" :{\n \"mac\" : \"00:ff:ff:ff:ff:ff\",\n \"tx-ring-size\" : 512,\n \"rx-ring-size\" : 512,\n \"host-mac\" : \"00:ee:ee:ee:ee:ee\",\n \"host-interface-name\" : \"vpp-tap-v2\",\n \"host-bridge\" : \"testBridge\",\n \"host-ipv4-address\" : \"192.168.20.100/24\",\n \"host-ipv6-address\" : \"a::100/96\",\n \"host-ipv4-gateway\" : \"192.168.20.1\",\n \"host-ipv6-gateway\" : \"a::1\",\n \"tag\": \"tap-v2_tag\"\n }\n }\n ]\n\n}"
+ },
+ "url": {
+ "raw": "http://localhost:8183/restconf/config/ietf-interfaces:interfaces/interface/tap-v2",
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "8183",
+ "path": [
+ "restconf",
+ "config",
+ "ietf-interfaces:interfaces",
+ "interface",
+ "tap-v2"
+ ]
+ },
+ "description": "When adding Tap to a bridge it is needed that the bridge exists. You can create it with these commands:\n\nsudo brctl addbr testBridge\nsudo brctl stp testBridge off\nsudo ip link set dev testBridge up"
+ },
+ "response": []
+ },
+ {
+ "name": "Delete tapV2 ifc - cfg",
+ "request": {
+ "method": "DELETE",
+ "header": [
+ {
+ "key": "Authorization",
+ "value": "Basic YWRtaW46YWRtaW4="
+ },
+ {
+ "key": "Content-Type",
+ "value": "application/json"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": ""
+ },
+ "url": {
+ "raw": "http://localhost:8183/restconf/config/ietf-interfaces:interfaces/interface/tap-v2",
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "8183",
+ "path": [
+ "restconf",
+ "config",
+ "ietf-interfaces:interfaces",
+ "interface",
+ "tap-v2"
+ ]
+ }
+ },
+ "response": []
+ }
+ ]
+ },
+ {
"name": "VHOST",
- "description": null,
"item": [
{
"name": "Add vhost user ifc - cfg",
@@ -1875,7 +1944,6 @@
},
{
"name": "VLAN",
- "description": null,
"item": [
{
"name": "Add sub interface - cfg",
@@ -2207,7 +2275,6 @@
},
{
"name": "VXLAN-GPE-TUNNEL",
- "description": null,
"item": [
{
"name": "Add vxlan-gpe - cfg",
@@ -2285,7 +2352,6 @@
},
{
"name": "VXLAN-TUNNEL",
- "description": null,
"item": [
{
"name": "Add virtual ifc - cfg",
@@ -2363,7 +2429,6 @@
},
{
"name": "AF_PACKET",
- "description": null,
"item": [
{
"name": "Add af_packet interface",
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/factory/InterfacesStateReaderFactory.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/factory/InterfacesStateReaderFactory.java
index 862bd447f..b8e5a7bc3 100644
--- a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/factory/InterfacesStateReaderFactory.java
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/factory/InterfacesStateReaderFactory.java
@@ -27,6 +27,7 @@ import io.fd.hc2vpp.v3po.interfacesstate.InterfaceCustomizer;
import io.fd.hc2vpp.v3po.interfacesstate.InterfaceRoutingCustomizer;
import io.fd.hc2vpp.v3po.interfacesstate.L2Customizer;
import io.fd.hc2vpp.v3po.interfacesstate.TapCustomizer;
+import io.fd.hc2vpp.v3po.interfacesstate.TapV2Customizer;
import io.fd.hc2vpp.v3po.interfacesstate.VhostUserCustomizer;
import io.fd.hc2vpp.v3po.interfacesstate.AfPacketCustomizer;
import io.fd.hc2vpp.v3po.interfacesstate.VxlanCustomizer;
@@ -52,6 +53,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.interfaces.state._interface.Span;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.interfaces.state._interface.SpanBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.interfaces.state._interface.Tap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.interfaces.state._interface.TapV2;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.interfaces.state._interface.VhostUser;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.interfaces.state._interface.AfPacket;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.interfaces.state._interface.Vxlan;
@@ -118,6 +120,9 @@ public final class InterfacesStateReaderFactory implements ReaderFactory {
// Tap
registry.add(new GenericInitReader<>(vppIfcAugId.child(Tap.class),
new TapCustomizer(jvpp, ifcNamingCtx, ifaceDumpManager)));
+ // TapV2
+ registry.add(new GenericInitReader<>(vppIfcAugId.child(TapV2.class),
+ new TapV2Customizer(jvpp, ifcNamingCtx, ifaceDumpManager)));
// VhostUser
registry.add(new GenericInitReader<>(vppIfcAugId.child(VhostUser.class),
new VhostUserCustomizer(jvpp, ifcNamingCtx, ifaceDumpManager)));
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/factory/InterfacesWriterFactory.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/factory/InterfacesWriterFactory.java
index ea8fd4c81..cf982aabf 100644
--- a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/factory/InterfacesWriterFactory.java
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/factory/InterfacesWriterFactory.java
@@ -29,6 +29,7 @@ import io.fd.hc2vpp.v3po.interfaces.InterfaceUnnumberedCustomizer;
import io.fd.hc2vpp.v3po.interfaces.L2Customizer;
import io.fd.hc2vpp.v3po.interfaces.LoopbackCustomizer;
import io.fd.hc2vpp.v3po.interfaces.TapCustomizer;
+import io.fd.hc2vpp.v3po.interfaces.TapV2Customizer;
import io.fd.hc2vpp.v3po.interfaces.VhostUserCustomizer;
import io.fd.hc2vpp.v3po.interfaces.AfPacketCustomizer;
import io.fd.hc2vpp.v3po.interfaces.VxlanCustomizer;
@@ -53,6 +54,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.interfaces._interface.Routing;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.interfaces._interface.Span;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.interfaces._interface.Tap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.interfaces._interface.TapV2;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.interfaces._interface.VhostUser;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.interfaces._interface.AfPacket;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.interfaces._interface.Vxlan;
@@ -120,6 +122,10 @@ public final class InterfacesWriterFactory implements WriterFactory {
final InstanceIdentifier<Tap> tapId = VPP_IFC_AUG_ID.child(Tap.class);
registry.addBefore(new GenericWriter<>(tapId, new TapCustomizer(jvpp, ifcNamingContext)),
ifcId);
+ // TapV2(Needs to be executed before Interface customizer) =
+ final InstanceIdentifier<TapV2> tapV2Id = VPP_IFC_AUG_ID.child(TapV2.class);
+ registry.addBefore(new GenericWriter<>(tapV2Id, new TapV2Customizer(jvpp, ifcNamingContext)),
+ ifcId);
// Loopback(Needs to be executed before Interface customizer) =
final InstanceIdentifier<Loopback> loopbackId = VPP_IFC_AUG_ID.child(Loopback.class);
registry.addBefore(new GenericWriter<>(loopbackId, new LoopbackCustomizer(jvpp, ifcNamingContext)),
@@ -131,7 +137,7 @@ public final class InterfacesWriterFactory implements WriterFactory {
ifcId);
final Set<InstanceIdentifier<?>> specificIfcTypes =
- Sets.newHashSet(vhostId, afpacketId, vxlanId, vxlanGpeId, tapId, loopbackId);
+ Sets.newHashSet(vhostId, afpacketId, vxlanId, vxlanGpeId, tapId, tapV2Id, loopbackId);
// Ethernet =
registry.add(new GenericWriter<>(VPP_IFC_AUG_ID.child(Ethernet.class),
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/TapV2Customizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/TapV2Customizer.java
new file mode 100644
index 000000000..5f315c876
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/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.interfaces;
+
+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.vpp.jvpp.core.dto.TapCreateV2;
+import io.fd.vpp.jvpp.core.dto.TapCreateV2Reply;
+import io.fd.vpp.jvpp.core.dto.TapDeleteV2;
+import io.fd.vpp.jvpp.core.dto.TapDeleteV2Reply;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import java.nio.charset.StandardCharsets;
+import java.util.concurrent.CompletionStage;
+import javax.annotation.Nonnull;
+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.rev140508.InterfaceType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.interfaces._interface.TapV2;
+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.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.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/interfacesstate/InterfaceDataTranslator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/InterfaceDataTranslator.java
index aa52d0bb3..188f83d0f 100644
--- a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/InterfaceDataTranslator.java
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/InterfaceDataTranslator.java
@@ -38,6 +38,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.GreTunnel;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.Loopback;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.Tap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.TapV2;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.VhostUser;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.VxlanGpeTunnel;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.VxlanTunnel;
@@ -138,10 +139,14 @@ public interface InterfaceDataTranslator extends ByteDataTranslator, JvppReplyCo
*/
@Nonnull
default Class<? extends InterfaceType> getInterfaceType(@Nonnull final String interfaceName) {
- if (interfaceName.startsWith("tap")) {
+ if (interfaceName.startsWith("tapcli-")) {
return Tap.class;
}
+ if (interfaceName.startsWith("tap")) {
+ return TapV2.class;
+ }
+
if (interfaceName.startsWith("vxlan_gpe")) {
return VxlanGpeTunnel.class;
}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/TapV2Customizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/TapV2Customizer.java
new file mode 100644
index 000000000..934a5c595
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/TapV2Customizer.java
@@ -0,0 +1,212 @@
+/*
+ * 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.interfacesstate;
+
+import static com.google.common.base.Preconditions.checkState;
+import static java.lang.String.format;
+
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+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.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager;
+import io.fd.honeycomb.translate.read.ReadContext;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.Initialized;
+import io.fd.honeycomb.translate.spi.read.InitializingReaderCustomizer;
+import io.fd.honeycomb.translate.util.RWUtils;
+import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager;
+import io.fd.honeycomb.translate.util.read.cache.StaticCacheKeyFactory;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceTapV2Details;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceTapV2DetailsReplyDump;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceTapV2Dump;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import java.util.Optional;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.VppInterfaceStateAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.interfaces.state._interface.TapV2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.interfaces.state._interface.TapV2Builder;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class TapV2Customizer extends FutureJVppCustomizer
+ implements InitializingReaderCustomizer<TapV2, TapV2Builder>, InterfaceDataTranslator, JvppReplyConsumer,
+ MacTranslator, Ipv4Translator, Ipv6Translator{
+
+ private static final Logger LOG = LoggerFactory.getLogger(TapV2Customizer.class);
+ private NamingContext interfaceContext;
+ private final InterfaceCacheDumpManager dumpManager;
+ private final DumpCacheManager<SwInterfaceTapV2DetailsReplyDump, Void> tapV2DumpManager;
+
+ public TapV2Customizer(@Nonnull final FutureJVppCore jvpp,
+ @Nonnull final NamingContext interfaceContext,
+ @Nonnull final InterfaceCacheDumpManager dumpManager) {
+ super(jvpp);
+ this.interfaceContext = interfaceContext;
+ this.dumpManager = dumpManager;
+ this.tapV2DumpManager = new DumpCacheManager.DumpCacheManagerBuilder<SwInterfaceTapV2DetailsReplyDump, Void>()
+ .withCacheKeyFactory(new StaticCacheKeyFactory(TapV2Customizer.class.getName() + "_dump",
+ SwInterfaceTapV2DetailsReplyDump.class))
+ .withExecutor((identifier, params) -> {
+ // Full TapV2 dump has to be performed here, no filter or anything is here to help so at least we cache it
+ return getReplyForRead(getFutureJVpp()
+ .swInterfaceTapV2Dump(new SwInterfaceTapV2Dump()).toCompletableFuture(), identifier);
+ }).build();
+ }
+
+ @Override
+ public void merge(@Nonnull Builder<? extends DataObject> parentBuilder, @Nonnull TapV2 readValue) {
+ ((VppInterfaceStateAugmentationBuilder) parentBuilder).setTapV2(readValue);
+ }
+
+ @Nonnull
+ @Override
+ public TapV2Builder getBuilder(@Nonnull InstanceIdentifier<TapV2> id) {
+ return new TapV2Builder();
+ }
+
+ @Override
+ public void readCurrentAttributes(@Nonnull final InstanceIdentifier<TapV2> id,
+ @Nonnull final TapV2Builder builder,
+ @Nonnull final ReadContext ctx) throws ReadFailedException {
+
+ final InterfaceKey key = id.firstKeyOf(Interface.class);
+ final int index = interfaceContext.getIndex(key.getName(), ctx.getMappingContext());
+ if (!isInterfaceOfType(dumpManager, id, ctx,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.TapV2.class)) {
+ return;
+ }
+
+ LOG.debug("Reading attributes for tapV2 interface: {}", key.getName());
+ final SwInterfaceTapV2DetailsReplyDump reply = tapV2DumpManager.getDump(id, ctx.getModificationCache())
+ .or(new SwInterfaceTapV2DetailsReplyDump());
+
+ final Optional<SwInterfaceTapV2Details> detail = reply.swInterfaceTapV2Details.stream()
+ .filter(d -> d.swIfIndex == index)
+ .findAny();
+
+ checkState(detail.isPresent(), "TapV2 interface for index %s not found", index);
+ final SwInterfaceTapV2Details swInterfaceTapV2Details = detail.get();
+
+ LOG.trace("TapV2 interface: {} attributes returned from VPP: {}", key.getName(), swInterfaceTapV2Details);
+ if (swInterfaceTapV2Details.devName != null && swInterfaceTapV2Details.devName[0] != 0) {
+ builder.setDeviceName(toString(swInterfaceTapV2Details.devName));
+ } else {
+ builder.setDeviceName(null);
+ }
+
+ if (swInterfaceTapV2Details.hostBridge != null && swInterfaceTapV2Details.hostBridge[0] != 0) {
+ builder.setHostBridge(toString(swInterfaceTapV2Details.hostBridge));
+ } else {
+ builder.setHostBridge(null);
+ }
+
+ if (swInterfaceTapV2Details.hostMacAddr != null &&
+ !ByteDataTranslator.INSTANCE.isArrayZeroed(swInterfaceTapV2Details.hostMacAddr)) {
+ builder.setHostMac(toPhysAddress(swInterfaceTapV2Details.hostMacAddr));
+ } else {
+ builder.setHostMac(null);
+ }
+
+ if (swInterfaceTapV2Details.hostIfName != null && swInterfaceTapV2Details.hostIfName[0] != 0) {
+ builder.setHostInterfaceName(toString(swInterfaceTapV2Details.hostIfName));
+ } else {
+ builder.setHostInterfaceName(null);
+ }
+
+ if (swInterfaceTapV2Details.hostIp4Addr != null && swInterfaceTapV2Details.hostIp4PrefixLen != 0) {
+ builder.setHostIpv4Address(
+ toIpv4Prefix(swInterfaceTapV2Details.hostIp4Addr, swInterfaceTapV2Details.hostIp4PrefixLen));
+ } else {
+ builder.setHostIpv4Address(null);
+ }
+
+ if (swInterfaceTapV2Details.hostIp6Addr != null && swInterfaceTapV2Details.hostIp6PrefixLen != 0) {
+ builder.setHostIpv6Address(
+ toIpv6Prefix(swInterfaceTapV2Details.hostIp6Addr,
+ Byte.toUnsignedInt(swInterfaceTapV2Details.hostIp6PrefixLen)));
+ } else {
+ builder.setHostIpv6Address(null);
+ }
+
+ if (swInterfaceTapV2Details.hostNamespace != null && swInterfaceTapV2Details.hostNamespace[0] != 0) {
+ builder.setHostNamespace(toString(swInterfaceTapV2Details.hostNamespace));
+ } else {
+ builder.setHostNamespace(null);
+ }
+
+
+ builder.setRxRingSize(Short.toUnsignedInt(swInterfaceTapV2Details.rxRingSz));
+ builder.setTxRingSize(Short.toUnsignedInt(swInterfaceTapV2Details.txRingSz));
+ final SwInterfaceDetails ifcDetails = dumpManager.getInterfaceDetail(id, ctx, key.getName());
+
+ if (ifcDetails.tag[0] != 0) { // tag supplied
+ builder.setTag(toString(ifcDetails.tag));
+ }
+ LOG.debug("TapV2 interface: {}, id: {} attributes read as: {}", key.getName(), index, builder);
+ }
+
+ @Override
+ public Initialized<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.interfaces._interface.TapV2> init(
+ @Nonnull final InstanceIdentifier<TapV2> id, @Nonnull final TapV2 readValue,
+ @Nonnull final ReadContext ctx) {
+ // The MAC address & tag is set from interface details, those details are retrieved from cache
+ final InterfaceKey key = id.firstKeyOf(Interface.class);
+
+ final SwInterfaceDetails ifcDetails;
+ try {
+ ifcDetails = dumpManager.getInterfaceDetail(id, ctx, key.getName());
+ } catch (ReadFailedException e) {
+ throw new IllegalStateException(format("Unable to read interface %s", key.getName()), e);
+ }
+
+ return Initialized.create(getCfgId(id),
+ new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.interfaces._interface.TapV2Builder()
+ .setMac(new PhysAddress(vppPhysAddrToYang(ifcDetails.l2Address)))
+ .setHostInterfaceName(readValue.getHostInterfaceName())
+ .setTag(ifcDetails.tag[0] == 0
+ ? null
+ : toString(ifcDetails.tag))
+ .setHostBridge(readValue.getHostBridge())
+ .setHostIpv4Address(readValue.getHostIpv4Address())
+ .setHostIpv6Address(readValue.getHostIpv6Address())
+ .setRxRingSize(readValue.getRxRingSize())
+ .setTxRingSize(readValue.getTxRingSize())
+ .setHostMac(readValue.getHostMac())
+ .setHostNamespace(readValue.getHostNamespace())
+ .build());
+ }
+
+ private InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.interfaces._interface.TapV2> getCfgId(
+ final InstanceIdentifier<TapV2> id) {
+ return InterfaceCustomizer.getCfgId(RWUtils.cutId(id, Interface.class))
+ .augmentation(VppInterfaceAugmentation.class)
+ .child(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.interfaces._interface.TapV2.class);
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/TapV2CustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/TapV2CustomizerTest.java
new file mode 100644
index 000000000..12dd43452
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/TapV2CustomizerTest.java
@@ -0,0 +1,162 @@
+/*
+ * 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.interfaces;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.hc2vpp.common.translate.util.Ipv4Translator;
+import io.fd.hc2vpp.common.translate.util.Ipv6Translator;
+import io.fd.hc2vpp.common.translate.util.MacTranslator;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.vpp.jvpp.core.dto.TapCreateV2;
+import io.fd.vpp.jvpp.core.dto.TapCreateV2Reply;
+import io.fd.vpp.jvpp.core.dto.TapDeleteV2;
+import io.fd.vpp.jvpp.core.dto.TapDeleteV2Reply;
+import java.util.concurrent.atomic.AtomicInteger;
+import org.junit.Assert;
+import org.junit.Test;
+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.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.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.interfaces._interface.TapV2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.interfaces._interface.TapV2Builder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class TapV2CustomizerTest extends WriterCustomizerTest
+ implements Ipv4Translator, Ipv6Translator, MacTranslator {
+
+ private static final String IFC_TEST_INSTANCE = "ifc-test-instance";
+ private TapV2Customizer tapCustomizer;
+ private static final String HOST_IF_NAME = "tapV21";
+ private static final String HOST_BRIDGE = "TestBridge";
+ private static final String HOST_IPV4_PREFIX = "192.168.255.100";
+ private static final byte HOST_IPV4_PREFIX_LEN = 24;
+ private static final String HOST_IPV4_GW = "192.168.255.1";
+ private static final String HOST_IPV6_PREFIX = "a::100";
+ private static final String HOST_IPV6_GW = "a::1";
+ private static final byte HOST_IPV6_PREFIX_LEN = -128;
+ private static final int HOST_IPV6_PREFIX_LEN_EXP = 128;
+ private static final int RX_TX_RING_SIZE = 512;
+ private static final String HOST_MAC = "00:ee:ee:ee:ee:ee";
+ private static final String HOST_NAMESPACE = "testHostNS";
+
+ @Override
+ public void setUpTest() throws Exception {
+ InterfaceTypeTestUtils.setupWriteContext(writeContext,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.TapV2.class);
+ tapCustomizer = new TapV2Customizer(api, new NamingContext("ifcintest", IFC_TEST_INSTANCE));
+ }
+
+ @Test
+ public void testCreate() throws Exception {
+ final AtomicInteger idx = new AtomicInteger(0);
+ doAnswer((i) -> {
+ final TapCreateV2 tapData = i.getArgument(0);
+ if (tapData == null) {
+ return failedFuture();
+ }
+
+ Assert.assertArrayEquals(tapData.hostBridge, HOST_BRIDGE.getBytes());
+ Assert.assertEquals(tapData.hostBridgeSet, 1);
+ Assert.assertArrayEquals(tapData.hostIfName, HOST_IF_NAME.getBytes());
+ Assert.assertEquals(tapData.hostIfNameSet, 1);
+ Assert.assertArrayEquals(tapData.hostNamespace, HOST_NAMESPACE.getBytes());
+ Assert.assertEquals(tapData.hostNamespaceSet, 1);
+ Assert.assertArrayEquals(tapData.hostIp4Addr, ipv4AddressPrefixToArray(
+ new Ipv4Prefix(String.format("%s/%d", HOST_IPV4_PREFIX, HOST_IPV4_PREFIX_LEN))));
+ Assert.assertEquals(tapData.hostIp4AddrSet, 1);
+ Assert.assertEquals(tapData.hostIp4PrefixLen, HOST_IPV4_PREFIX_LEN);
+ Assert.assertArrayEquals(tapData.hostIp6Addr, ipv6AddressPrefixToArray(
+ new Ipv6Prefix(String.format("%s/%d", HOST_IPV6_PREFIX, HOST_IPV6_PREFIX_LEN_EXP))));
+ Assert.assertEquals(tapData.hostIp6AddrSet, 1);
+ Assert.assertEquals(tapData.hostIp6PrefixLen, HOST_IPV6_PREFIX_LEN);
+ Assert.assertArrayEquals(tapData.hostIp4Gw, ipv4AddressPrefixToArray(
+ new Ipv4Prefix(String.format("%s/%d", HOST_IPV4_GW, 24))));
+ Assert.assertEquals(tapData.hostIp4GwSet, 1);
+ Assert.assertArrayEquals(tapData.hostIp6Gw, ipv6AddressPrefixToArray(
+ new Ipv6Prefix(String.format("%s/%d", HOST_IPV6_GW, 96))));
+ Assert.assertEquals(tapData.hostIp6GwSet, 1);
+ Assert.assertArrayEquals(tapData.hostMacAddr, parseMac(HOST_MAC));
+ Assert.assertEquals(tapData.hostMacAddrSet, 1);
+ Assert.assertEquals(tapData.rxRingSz, RX_TX_RING_SIZE);
+ Assert.assertEquals(tapData.txRingSz, RX_TX_RING_SIZE);
+ final TapCreateV2Reply t = new TapCreateV2Reply();
+ t.swIfIndex = idx.getAndIncrement();
+ return future(t);
+
+ }).when(api).tapCreateV2(any(TapCreateV2.class));
+
+ tapCustomizer.writeCurrentAttributes(getTapId("tap"), getTapData("tap"), writeContext);
+ tapCustomizer.writeCurrentAttributes(getTapId("tap2"), getTapData("tap2"), writeContext);
+
+ verify(api, times(2)).tapCreateV2(any(TapCreateV2.class));
+ verify(mappingContext).put(eq(mappingIid("tap", IFC_TEST_INSTANCE)), eq(
+ mapping("tap", 0).get()));
+ verify(mappingContext).put(eq(mappingIid("tap2", IFC_TEST_INSTANCE)), eq(
+ mapping("tap2", 1).get()));
+ }
+
+ @Test
+ public void testDelete() throws Exception {
+ final TapCreateV2Reply t = new TapCreateV2Reply();
+ t.swIfIndex = 0;
+ doReturn(future(t)).when(api).tapCreateV2(any(TapCreateV2.class));
+
+ doReturn(future(new TapDeleteV2Reply())).when(api).tapDeleteV2(any(TapDeleteV2.class));
+ tapCustomizer.writeCurrentAttributes(getTapId("tap-v2"), getTapData("tap-v2"), writeContext);
+ defineMapping(mappingContext, "tap-v2", 1, IFC_TEST_INSTANCE);
+ tapCustomizer.deleteCurrentAttributes(getTapId("tap-v2"), getTapData("tap-v2"), writeContext);
+
+ verify(api).tapCreateV2(any(TapCreateV2.class));
+ verify(api).tapDeleteV2(any(TapDeleteV2.class));
+ verify(mappingContext).delete(eq(mappingIid("tap-v2", IFC_TEST_INSTANCE)));
+ }
+
+ private InstanceIdentifier<TapV2> getTapId(final String tap) {
+ return InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(tap)).augmentation(
+ VppInterfaceAugmentation.class).child(TapV2.class);
+ }
+
+ private TapV2 getTapData(final String tap) {
+ return new TapV2Builder()
+ .setHostInterfaceName(HOST_IF_NAME)
+ .setMac(new PhysAddress(HOST_MAC))
+ .setTag(tap + "_tag")
+ .setHostBridge(HOST_BRIDGE)
+ .setHostIpv4Address(new Ipv4Prefix(String.format("%s/%s", HOST_IPV4_PREFIX, HOST_IPV4_PREFIX_LEN)))
+ .setHostIpv4Gateway(new Ipv4Address(HOST_IPV4_GW))
+ .setHostIpv6Address(new Ipv6Prefix(String.format("%s/%s", HOST_IPV6_PREFIX, HOST_IPV6_PREFIX_LEN_EXP)))
+ .setHostIpv6Gateway(new Ipv6Address(HOST_IPV6_GW))
+ .setRxRingSize(RX_TX_RING_SIZE)
+ .setTxRingSize(RX_TX_RING_SIZE)
+ .setHostMac(new PhysAddress(HOST_MAC))
+ .setHostNamespace(HOST_NAMESPACE)
+ .build();
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/InterfaceDataTranslatorTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/InterfaceDataTranslatorTest.java
index 17665ee30..a3864e583 100644
--- a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/InterfaceDataTranslatorTest.java
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/InterfaceDataTranslatorTest.java
@@ -34,6 +34,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.AfPacket;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.Tap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.TapV2;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.VhostUser;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.VxlanGpeTunnel;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.VxlanTunnel;
@@ -61,7 +62,8 @@ public class InterfaceDataTranslatorTest implements InterfaceDataTranslator {
@Test
public void testGetInterfaceType() {
- assertEquals(Tap.class, getInterfaceType("tap0"));
+ assertEquals(Tap.class, getInterfaceType("tapcli-0"));
+ assertEquals(TapV2.class, getInterfaceType("tap0"));
assertEquals(VxlanTunnel.class, getInterfaceType("vxlan0"));
assertEquals(VxlanGpeTunnel.class, getInterfaceType("vxlan_gpe0"));
assertEquals(VhostUser.class, getInterfaceType("VirtualEthernet0/0/0"));
@@ -72,7 +74,8 @@ public class InterfaceDataTranslatorTest implements InterfaceDataTranslator {
@Test
public void testIsInterfaceOfType() {
- assertTrue(isInterfaceOfType(Tap.class, interfaceDetails("tap0")));
+ assertTrue(isInterfaceOfType(Tap.class, interfaceDetails("tapcli-0")));
+ assertTrue(isInterfaceOfType(TapV2.class, interfaceDetails("tap0")));
assertTrue(isInterfaceOfType(VxlanTunnel.class, interfaceDetails("vxlan0")));
assertTrue(isInterfaceOfType(VxlanGpeTunnel.class, interfaceDetails("vxlan_gpe0")));
assertTrue(isInterfaceOfType(VhostUser.class, interfaceDetails("VirtualEthernet0/0/0")));
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/TapCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/TapCustomizerTest.java
index aa07eaff5..11d8ab8da 100644
--- a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/TapCustomizerTest.java
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/TapCustomizerTest.java
@@ -44,7 +44,7 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
public class TapCustomizerTest extends ReaderCustomizerTest<Tap, TapBuilder> implements InterfaceDumpHelper {
private static final String IFC_CTX_NAME = "ifc-test-instance";
- private static final String IF_NAME = "tap1";
+ private static final String IF_NAME = "tapcli-1";
private static final String TAP_NAME = "testTapName";
private static final int IF_INDEX = 1;
private static final InstanceIdentifier<Tap> IID =
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/TapV2CustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/TapV2CustomizerTest.java
new file mode 100644
index 000000000..ee77afc82
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/TapV2CustomizerTest.java
@@ -0,0 +1,142 @@
+/*
+ * 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.interfacesstate;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest;
+import io.fd.hc2vpp.common.test.util.InterfaceDumpHelper;
+import io.fd.hc2vpp.common.translate.util.Ipv4Translator;
+import io.fd.hc2vpp.common.translate.util.Ipv6Translator;
+import io.fd.hc2vpp.common.translate.util.MacTranslator;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceTapV2Details;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceTapV2DetailsReplyDump;
+import org.junit.Test;
+import org.mockito.Mock;
+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.Ipv6AddressNoZone;
+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.rev140508.InterfacesState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.VppInterfaceStateAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.VppInterfaceStateAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.interfaces.state._interface.TapV2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181008.interfaces.state._interface.TapV2Builder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class TapV2CustomizerTest extends ReaderCustomizerTest<TapV2, TapV2Builder> implements InterfaceDumpHelper,
+ Ipv4Translator, Ipv6Translator, MacTranslator {
+
+ private static final String IFC_CTX_NAME = "ifc-test-instance";
+ private static final String IF_NAME = "tapV21";
+ private static final String DEVICE_NAME = "testTapV2Device";
+ private static final int IF_INDEX = 1;
+ private static final String HOST_BRIDGE = "TestBridge";
+ private static final String HOST_IPV4_PREFIX = "192.168.255.100";
+ private static final byte HOST_IPV4_PREFIX_LEN = 24;
+ private static final String HOST_IPV6_PREFIX = "a::100";
+ private static final byte HOST_IPV6_PREFIX_LEN = -128;
+ private static final int HOST_IPV6_PREFIX_LEN_EXP = 128;
+ private static final int RX_TX_RING_SIZE = 512;
+ private static final String HOST_MAC = "00:ee:ee:ee:ee:ee";
+ private static final String HOST_NAMESPACE = "testHostNS";
+
+ private static final InstanceIdentifier<TapV2> IID =
+ InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IF_NAME))
+ .augmentation(VppInterfaceStateAugmentation.class).child(TapV2.class);
+ private NamingContext interfaceContext;
+
+ @Mock
+ private InterfaceCacheDumpManager dumpCacheManager;
+
+ public TapV2CustomizerTest() {
+ super(TapV2.class, VppInterfaceStateAugmentationBuilder.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ interfaceContext = new NamingContext("generatedIfaceName", IFC_CTX_NAME);
+ defineMapping(mappingContext, IF_NAME, IF_INDEX, IFC_CTX_NAME);
+ when(dumpCacheManager.getInterfaceDetail(IID, ctx, IF_NAME)).thenReturn(ifaceDetails());
+ }
+
+ private SwInterfaceDetails ifaceDetails() {
+ final SwInterfaceDetails details = new SwInterfaceDetails();
+ details.swIfIndex = IF_INDEX;
+ details.interfaceName = IF_NAME.getBytes();
+ details.tag = new byte[64];
+ return details;
+ }
+
+ @Override
+ protected ReaderCustomizer<TapV2, TapV2Builder> initCustomizer() {
+ return new TapV2Customizer(api, interfaceContext, dumpCacheManager);
+ }
+
+ @Test
+ public void testRead() throws ReadFailedException {
+ final TapV2Builder builder = mock(TapV2Builder.class);
+ when(api.swInterfaceTapV2Dump(any())).thenReturn(future(tapDump()));
+ getCustomizer().readCurrentAttributes(IID, builder, ctx);
+ verify(builder).setHostInterfaceName(IF_NAME);
+ verify(builder).setDeviceName(DEVICE_NAME);
+ verify(builder).setHostBridge(HOST_BRIDGE);
+ verify(builder)
+ .setHostIpv4Address(new Ipv4Prefix(String.format("%s/%d", HOST_IPV4_PREFIX, HOST_IPV4_PREFIX_LEN)));
+ verify(builder)
+ .setHostIpv6Address(new Ipv6Prefix(String.format("%s/%d", HOST_IPV6_PREFIX, HOST_IPV6_PREFIX_LEN_EXP)));
+ verify(builder).setTxRingSize(RX_TX_RING_SIZE);
+ verify(builder).setRxRingSize(RX_TX_RING_SIZE);
+ verify(builder).setHostNamespace(HOST_NAMESPACE);
+ verify(builder).setHostMac(new PhysAddress(HOST_MAC));
+ }
+
+ @Test(expected = ReadFailedException.class)
+ public void testReadFailed() throws ReadFailedException {
+ when(api.swInterfaceTapV2Dump(any())).thenReturn(failedFuture());
+ getCustomizer().readCurrentAttributes(IID, mock(TapV2Builder.class), ctx);
+ }
+
+ private SwInterfaceTapV2DetailsReplyDump tapDump() {
+ final SwInterfaceTapV2DetailsReplyDump reply = new SwInterfaceTapV2DetailsReplyDump();
+ final SwInterfaceTapV2Details details = new SwInterfaceTapV2Details();
+ details.devName = DEVICE_NAME.getBytes(UTF_8);
+ details.swIfIndex = IF_INDEX;
+ details.hostBridge = HOST_BRIDGE.getBytes(UTF_8);
+ details.hostNamespace = HOST_NAMESPACE.getBytes(UTF_8);
+ details.hostIfName = IF_NAME.getBytes(UTF_8);
+ details.hostIp4PrefixLen = HOST_IPV4_PREFIX_LEN;
+ details.hostIp4Addr = ipv4AddressNoZoneToArray(HOST_IPV4_PREFIX);
+ details.hostIp6Addr = ipv6AddressNoZoneToArray(new Ipv6AddressNoZone(HOST_IPV6_PREFIX));
+ details.hostIp6PrefixLen = HOST_IPV6_PREFIX_LEN;
+ details.hostMacAddr = parseMac(HOST_MAC);
+ details.txRingSz = details.rxRingSz = RX_TX_RING_SIZE;
+ reply.swInterfaceTapV2Details.add(details);
+ return reply;
+ }
+}