HC2VPP-144 - Sub-interface span 32/6632/6
authorJan Srnicek <[email protected]>
Fri, 12 May 2017 11:15:50 +0000 (13:15 +0200)
committerMarek Gradzki <[email protected]>
Mon, 15 May 2017 05:24:48 +0000 (05:24 +0000)
Provides option to define port mirroring from
interface to subinterface

Change-Id: I8c04e8eb6b980c830e77e1ef2b75ddff3d59364c
Signed-off-by: Jan Srnicek <[email protected]>
Signed-off-by: jsrnicek <[email protected]>
Signed-off-by: Jan Srnicek <[email protected]>
13 files changed:
v3po/api/src/main/yang/subinterface-span.yang [new file with mode: 0644]
v3po/span_postman_collection.json [new file with mode: 0644]
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/factory/InterfacesStateReaderFactory.java
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/factory/InterfacesWriterFactory.java
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/factory/SubinterfaceAugmentationWriterFactory.java
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/factory/SubinterfaceStateAugmentationReaderFactory.java
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/span/MirroredInterfaceCustomizer.java
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/span/AbstractMirroredInterfacesCustomizer.java [moved from v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/span/MirroredInterfacesCustomizer.java with 69% similarity]
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/span/InterfaceMirroredInterfacesCustomizer.java [new file with mode: 0644]
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/span/SubInterfaceMirroredInterfacesCustomizer.java [new file with mode: 0644]
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/util/SubInterfaceUtils.java
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/span/MirroredInterfacesCustomizerTest.java [moved from v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/span/MirroredInterfaceCustomizerTest.java with 96% similarity]
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/span/MirroredInterfacesCustomizerTest.java

diff --git a/v3po/api/src/main/yang/subinterface-span.yang b/v3po/api/src/main/yang/subinterface-span.yang
new file mode 100644 (file)
index 0000000..74d33f5
--- /dev/null
@@ -0,0 +1,40 @@
+module subinterface-span {
+  yang-version 1;
+  namespace "urn:opendaylight:params:xml:ns:yang:subinterface-span";
+  prefix "subif-span";
+
+  revision "2017-05-10" {
+    description
+      "Initialial revision that adds support for mirroring interfaces on subinterfaces.
+       Vpp implementation allows/implements only two cases:
+        - Src: interface |Dst: interface - covered in v3po.yang
+        - Src: interface |Dst: subinterface - covered by this model";
+  }
+
+  import v3po {
+    prefix "v3po";
+  }
+
+  import vpp-vlan {
+    prefix "vpp-vlan";
+  }
+
+  import yang-ext {
+    prefix "ext";
+  }
+
+  augment /if:interfaces/if:interface/vpp-vlan:sub-interfaces/vpp-vlan:sub-interface {
+      ext:augment-identifier "vpp-subinterface-span-augmentation";
+
+      container span {
+        uses v3po:span-attributes;
+      }
+  }
+
+  augment /if:interfaces-state/if:interface/vpp-vlan:sub-interfaces/vpp-vlan:sub-interface {
+      ext:augment-identifier "vpp-subinterface-span-state-augmentation";
+      container span-state {
+        uses v3po:span-attributes;
+      }
+  }
+}
\ No newline at end of file
diff --git a/v3po/span_postman_collection.json b/v3po/span_postman_collection.json
new file mode 100644 (file)
index 0000000..412b449
--- /dev/null
@@ -0,0 +1,160 @@
+{
+       "id": "b30b26ab-fd5f-368f-713a-4c72315cf663",
+       "name": "Span interface/subinterface collection",
+       "description": "Provides model request to define pot mirroring for interfaces and sub-interfaces",
+       "order": [],
+       "folders": [
+               {
+                       "id": "cc874576-92fd-fa49-20fe-482333b895c0",
+                       "name": "Interface <==> Interface",
+                       "description": "",
+                       "order": [
+                               "b2342499-fbb3-02d1-bc7d-3c7d515b8cfa",
+                               "67359961-1edf-d25f-63d2-ff84552da924",
+                               "67a1966d-ec28-c131-7fdf-0d8e24ac2b42"
+                       ],
+                       "owner": 0
+               },
+               {
+                       "id": "d26fa438-e4f6-ad96-b92a-ebb509d4ca66",
+                       "name": "Interface <==> SubInterface",
+                       "description": "",
+                       "order": [
+                               "ffd3adcd-345f-d8fb-0393-22ad78528083",
+                               "03a5c3d7-e3c1-0862-4a4c-806ac7282cb5",
+                               "59ae66fd-bd64-e0bd-924c-b9469db447af"
+                       ],
+                       "owner": 0
+               }
+       ],
+       "timestamp": 1494480653049,
+       "owner": 0,
+       "public": false,
+       "requests": [
+               {
+                       "id": "03a5c3d7-e3c1-0862-4a4c-806ac7282cb5",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\n",
+                       "url": "http://localhost:8183/restconf/operational/ietf-interfaces:interfaces-state/interface/GigabitEthernet0%2F8%2F0/vpp-vlan:sub-interfaces/sub-interface/1/span-state",
+                       "preRequestScript": "",
+                       "pathVariables": {},
+                       "method": "GET",
+                       "data": [],
+                       "dataMode": "raw",
+                       "version": 2,
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1494481976252,
+                       "name": "Read port mirroring",
+                       "description": "set span src local0 dst GigabiteEthernet0/8/0",
+                       "collectionId": "b30b26ab-fd5f-368f-713a-4c72315cf663",
+                       "responses": [],
+                       "rawModeData": "{\r\n    \r\n    \"span\": {\r\n    \t\"mirrored-interfaces\": {\r\n    \t\t\"mirrored-interface\": [{\"iface-ref\":\"GigabitEthernet0/8/0\",\"state\":\"receive\"}]\r\n    \t}\r\n    }\r\n    \r\n}"
+               },
+               {
+                       "id": "59ae66fd-bd64-e0bd-924c-b9469db447af",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\n",
+                       "url": "http://localhost:8183/restconf/config/ietf-interfaces:interfaces/interface/GigabitEthernet0%2F8%2F0/vpp-vlan:sub-interfaces/sub-interface/1/span",
+                       "preRequestScript": "",
+                       "pathVariables": {},
+                       "method": "DELETE",
+                       "data": [],
+                       "dataMode": "raw",
+                       "version": 2,
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1494481990266,
+                       "name": "Delete port mirroring",
+                       "description": "set span src local0 dst GigabiteEthernet0/8/0",
+                       "collectionId": "b30b26ab-fd5f-368f-713a-4c72315cf663",
+                       "responses": [],
+                       "rawModeData": "{\r\n    \r\n    \"span\": {\r\n    \t\"mirrored-interfaces\": {\r\n    \t\t\"mirrored-interface\": [{\"iface-ref\":\"GigabitEthernet0/8/0\",\"state\":\"receive\"}]\r\n    \t}\r\n    }\r\n    \r\n}"
+               },
+               {
+                       "id": "67359961-1edf-d25f-63d2-ff84552da924",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\n",
+                       "url": "http://localhost:8183/restconf/operational/ietf-interfaces:interfaces-state/interface/GigabitEthernet0%2F8%2F0/span",
+                       "preRequestScript": "",
+                       "pathVariables": {},
+                       "method": "GET",
+                       "data": [],
+                       "dataMode": "raw",
+                       "version": 2,
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1477908227905,
+                       "name": "Read port mirroring",
+                       "description": "show span",
+                       "collectionId": "b30b26ab-fd5f-368f-713a-4c72315cf663",
+                       "responses": [],
+                       "rawModeData": "",
+                       "folder": "cc874576-92fd-fa49-20fe-482333b895c0",
+                       "isFromCollection": true,
+                       "collectionRequestId": "67359961-1edf-d25f-63d2-ff84552da924"
+               },
+               {
+                       "id": "67a1966d-ec28-c131-7fdf-0d8e24ac2b42",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\n",
+                       "url": "http://localhost:8183/restconf/config/ietf-interfaces:interfaces/interface/GigabitEthernet0%2F8%2F0/span",
+                       "preRequestScript": "",
+                       "pathVariables": {},
+                       "method": "DELETE",
+                       "data": [],
+                       "dataMode": "raw",
+                       "version": 2,
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1477907954064,
+                       "name": "Delete port mirroring local0 -> GigabiteEthernet0/8/0",
+                       "description": "",
+                       "collectionId": "b30b26ab-fd5f-368f-713a-4c72315cf663",
+                       "responses": [],
+                       "rawModeData": "",
+                       "folder": "cc874576-92fd-fa49-20fe-482333b895c0"
+               },
+               {
+                       "id": "b2342499-fbb3-02d1-bc7d-3c7d515b8cfa",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\n",
+                       "url": "http://localhost:8183/restconf/config/ietf-interfaces:interfaces/interface/GigabitEthernet0%2F8%2F0/span",
+                       "preRequestScript": "",
+                       "pathVariables": {},
+                       "method": "PUT",
+                       "data": [],
+                       "dataMode": "raw",
+                       "version": 2,
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1477905258870,
+                       "name": "Set port mirroring local0 -> GigabiteEthernet0/8/0",
+                       "description": "set span src local0 dst GigabiteEthernet0/8/0",
+                       "collectionId": "b30b26ab-fd5f-368f-713a-4c72315cf663",
+                       "responses": [],
+                       "rawModeData": "{\r\n    \r\n    \"span\": {\r\n    \t\"mirrored-interfaces\": {\r\n    \t\t\"mirrored-interface\": [{\"iface-ref\":\"local0\",\"state\":\"receive\"}]\r\n    \t}\r\n    }\r\n    \r\n}",
+                       "folder": "cc874576-92fd-fa49-20fe-482333b895c0"
+               },
+               {
+                       "id": "ffd3adcd-345f-d8fb-0393-22ad78528083",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\n",
+                       "url": "http://localhost:8183/restconf/config/ietf-interfaces:interfaces/interface/GigabitEthernet0%2F8%2F0/vpp-vlan:sub-interfaces/sub-interface/1/span",
+                       "preRequestScript": "",
+                       "pathVariables": {},
+                       "method": "PUT",
+                       "data": [],
+                       "dataMode": "raw",
+                       "version": 2,
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1494481863201,
+                       "name": "Set port mirroring GigabitEthernet0/8/0 to GigabitEthernet0/8/0.1",
+                       "description": "set span src local0 dst GigabiteEthernet0/8/0",
+                       "collectionId": "b30b26ab-fd5f-368f-713a-4c72315cf663",
+                       "responses": [],
+                       "rawModeData": "{\r\n    \r\n    \"span\": {\r\n    \t\"mirrored-interfaces\": {\r\n    \t\t\"mirrored-interface\": [{\"iface-ref\":\"GigabitEthernet0/8/0\",\"state\":\"receive\"}]\r\n    \t}\r\n    }\r\n    \r\n}"
+               }
+       ]
+}
\ No newline at end of file
index e75f97d..3d78094 100644 (file)
@@ -31,7 +31,7 @@ import io.fd.hc2vpp.v3po.interfacesstate.VhostUserCustomizer;
 import io.fd.hc2vpp.v3po.interfacesstate.VxlanCustomizer;
 import io.fd.hc2vpp.v3po.interfacesstate.VxlanGpeCustomizer;
 import io.fd.hc2vpp.v3po.interfacesstate.pbb.PbbRewriteStateCustomizer;
-import io.fd.hc2vpp.v3po.interfacesstate.span.MirroredInterfacesCustomizer;
+import io.fd.hc2vpp.v3po.interfacesstate.span.InterfaceMirroredInterfacesCustomizer;
 import io.fd.honeycomb.translate.impl.read.GenericInitListReader;
 import io.fd.honeycomb.translate.impl.read.GenericInitReader;
 import io.fd.honeycomb.translate.impl.read.GenericReader;
@@ -130,7 +130,7 @@ public final class InterfacesStateReaderFactory implements ReaderFactory {
         registry.subtreeAdd(
                 ImmutableSet.of(InstanceIdentifier.create(MirroredInterfaces.class).child(MirroredInterface.class)),
                 new GenericInitReader<>(spanId.child(MirroredInterfaces.class),
-                        new MirroredInterfacesCustomizer(jvpp, ifcNamingCtx)));
+                        new InterfaceMirroredInterfacesCustomizer(jvpp, ifcNamingCtx)));
     }
 
     private void initPbbRewriteAugmentation(final ModifiableReaderRegistryBuilder registry,
index 7fba636..6b9d514 100644 (file)
@@ -141,8 +141,8 @@ public final class InterfacesWriterFactory implements WriterFactory {
                 .child(Span.class)
                 .child(MirroredInterfaces.class)
                 .child(MirroredInterface.class);
-        registry.addAfter(new GenericWriter<>(mirroredIfcId, new MirroredInterfaceCustomizer(jvpp, ifcNamingContext)),
-                ifcId);
+        registry.addAfter(new GenericWriter<>(mirroredIfcId, new MirroredInterfaceCustomizer(jvpp, ifcNamingContext,
+                        id -> id.firstKeyOf(Interface.class).getName())), ifcId);
     }
 
     private void addPbbAugmentationWriters(final InstanceIdentifier<Interface> ifcId,
index be202f6..8c412b5 100644 (file)
@@ -24,12 +24,18 @@ import io.fd.hc2vpp.v3po.interfaces.RewriteCustomizer;
 import io.fd.hc2vpp.v3po.interfaces.SubInterfaceCustomizer;
 import io.fd.hc2vpp.v3po.interfaces.SubInterfaceL2Customizer;
 import io.fd.hc2vpp.v3po.interfaces.SubInterfaceRoutingCustomizer;
+import io.fd.hc2vpp.v3po.interfaces.span.MirroredInterfaceCustomizer;
+import io.fd.hc2vpp.v3po.util.SubInterfaceUtils;
 import io.fd.honeycomb.translate.impl.write.GenericListWriter;
 import io.fd.honeycomb.translate.impl.write.GenericWriter;
 import io.fd.honeycomb.translate.write.WriterFactory;
 import io.fd.honeycomb.translate.write.registry.ModifiableWriterRegistryBuilder;
 import io.fd.vpp.jvpp.core.future.FutureJVppCore;
 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.opendaylight.params.xml.ns.yang.subinterface.span.rev170510.VppSubinterfaceSpanAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.subinterface.span.rev170510.interfaces._interface.sub.interfaces.sub._interface.Span;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.span.attributes.MirroredInterfaces;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.span.attributes.mirrored.interfaces.MirroredInterface;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170509.SubinterfaceAugmentation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170509.interfaces._interface.SubInterfaces;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170509.interfaces._interface.sub.interfaces.SubInterface;
@@ -95,5 +101,14 @@ public final class SubinterfaceAugmentationWriterFactory implements WriterFactor
             L2_ID);
         final InstanceIdentifier<Routing> routingId = SUB_IFC_ID.child(Routing.class);
         registry.add(new GenericWriter<>(routingId, new SubInterfaceRoutingCustomizer(jvpp, ifcContext)));
+
+        final InstanceIdentifier<MirroredInterface> mirroredId =
+                SUB_IFC_ID.augmentation(VppSubinterfaceSpanAugmentation.class)
+                        .child(Span.class)
+                        .child(MirroredInterfaces.class)
+                        .child(MirroredInterface.class);
+        registry.addAfter(new GenericListWriter<>(mirroredId,
+                        new MirroredInterfaceCustomizer(jvpp, ifcContext, SubInterfaceUtils::subInterfaceFullNameConfig)),
+                SUB_IFC_ID);
     }
 }
index 9a66198..ee1fd60 100644 (file)
@@ -24,6 +24,7 @@ import io.fd.hc2vpp.v3po.interfacesstate.RewriteCustomizer;
 import io.fd.hc2vpp.v3po.interfacesstate.SubInterfaceCustomizer;
 import io.fd.hc2vpp.v3po.interfacesstate.SubInterfaceL2Customizer;
 import io.fd.hc2vpp.v3po.interfacesstate.SubInterfaceRoutingCustomizer;
+import io.fd.hc2vpp.v3po.interfacesstate.span.SubInterfaceMirroredInterfacesCustomizer;
 import io.fd.honeycomb.translate.impl.read.GenericInitListReader;
 import io.fd.honeycomb.translate.impl.read.GenericInitReader;
 import io.fd.honeycomb.translate.impl.read.GenericReader;
@@ -31,6 +32,11 @@ import io.fd.honeycomb.translate.read.ReaderFactory;
 import io.fd.honeycomb.translate.read.registry.ModifiableReaderRegistryBuilder;
 import io.fd.vpp.jvpp.core.future.FutureJVppCore;
 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.opendaylight.params.xml.ns.yang.subinterface.span.rev170510.VppSubinterfaceSpanStateAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.subinterface.span.rev170510.VppSubinterfaceSpanStateAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.subinterface.span.rev170510.interfaces.state._interface.sub.interfaces.sub._interface.SpanState;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.subinterface.span.rev170510.interfaces.state._interface.sub.interfaces.sub._interface.SpanStateBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.span.attributes.MirroredInterfaces;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170509.SubinterfaceStateAugmentation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170509.SubinterfaceStateAugmentationBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170509.interfaces.state._interface.SubInterfaces;
@@ -91,5 +97,15 @@ public final class SubinterfaceStateAugmentationReaderFactory implements ReaderF
             new GenericReader<>(l2Id.child(Rewrite.class), new RewriteCustomizer(jvpp, ifcCtx)));
         final InstanceIdentifier<Routing> routingId = subIfcId.child(Routing.class);
         registry.add(new GenericReader<>(routingId, new SubInterfaceRoutingCustomizer(jvpp, ifcCtx)));
+
+        final InstanceIdentifier<VppSubinterfaceSpanStateAugmentation> spanStateAugId = subIfcId.augmentation(VppSubinterfaceSpanStateAugmentation.class);
+        registry.addStructuralReader(spanStateAugId, VppSubinterfaceSpanStateAugmentationBuilder.class);
+
+        final InstanceIdentifier<SpanState> spanStateId = spanStateAugId
+                .child(SpanState.class);
+        registry.addStructuralReader(spanStateId, SpanStateBuilder.class);
+
+        final InstanceIdentifier<MirroredInterfaces> mirroredInterfacesId = spanStateId.child(MirroredInterfaces.class);
+        registry.add(new GenericInitReader<>(mirroredInterfacesId, new SubInterfaceMirroredInterfacesCustomizer(jvpp, ifcCtx)));
     }
 }
index 993120b..4d6ea98 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 Cisco and/or its affiliates.
+ * 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.
@@ -16,6 +16,8 @@
 
 package io.fd.hc2vpp.v3po.interfaces.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;
@@ -24,48 +26,41 @@ import io.fd.honeycomb.translate.write.WriteContext;
 import io.fd.honeycomb.translate.write.WriteFailedException;
 import io.fd.vpp.jvpp.core.dto.SwInterfaceSpanEnableDisable;
 import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import java.util.function.Function;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.SpanState;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.span.attributes.MirroredInterfaces;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.span.attributes.mirrored.interfaces.MirroredInterface;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.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
+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, final NamingContext ifcContext) {
+    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;
     }
 
-    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;
-    }
 
     @Override
-    public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<MirroredInterface> instanceIdentifier,
+    public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<MirroredInterface> id,
                                        @Nonnull final MirroredInterface mirroredInterface,
                                        @Nonnull final WriteContext writeContext)
             throws WriteFailedException {
-        final String destinationInterfaceName = instanceIdentifier.firstKeyOf(Interface.class).getName();
+        final String destinationInterfaceName =
+                destinationInterfaceNameExtractor.apply(cutId(id, MirroredInterfaces.class));
         final String sourceInterfaceName = mirroredInterface.getIfaceRef();
         final SpanState spanState = mirroredInterface.getState();
 
@@ -78,7 +73,7 @@ public final class MirroredInterfaceCustomizer
                         interfaceId(writeContext, ifcContext, sourceInterfaceName),
                         true,
                         spanState))
-                .toCompletableFuture(), instanceIdentifier);
+                .toCompletableFuture(), id);
         LOG.debug("Span for source interface {} | destination interface {} | state {} successfully enabled",
                 sourceInterfaceName, destinationInterfaceName, spanState);
     }
@@ -94,10 +89,11 @@ public final class MirroredInterfaceCustomizer
     }
 
     @Override
-    public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<MirroredInterface> instanceIdentifier,
+    public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<MirroredInterface> id,
                                         @Nonnull final MirroredInterface mirroredInterface,
                                         @Nonnull final WriteContext writeContext) throws WriteFailedException {
-        final String destinationInterfaceName = instanceIdentifier.firstKeyOf(Interface.class).getName();
+        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);
@@ -108,11 +104,24 @@ public final class MirroredInterfaceCustomizer
                         interfaceId(writeContext, ifcContext, sourceInterfaceName),
                         false,
                         null))
-                .toCompletableFuture(), instanceIdentifier);
+                .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());
     }
@@ -19,45 +19,42 @@ package io.fd.hc2vpp.v3po.interfacesstate.span;
 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.v3po.interfacesstate.InterfaceCustomizer;
+import io.fd.honeycomb.translate.MappingContext;
 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.vpp.jvpp.core.dto.SwInterfaceSpanDetailsReplyDump;
 import io.fd.vpp.jvpp.core.dto.SwInterfaceSpanDump;
 import io.fd.vpp.jvpp.core.future.FutureJVppCore;
 import java.util.List;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 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.opendaylight.params.xml.ns.yang.v3po.rev170315.SpanState;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.VppInterfaceAugmentation;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.interfaces._interface.Span;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.interfaces.state._interface.SpanBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.span.attributes.MirroredInterfaces;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.span.attributes.MirroredInterfacesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.span.attributes.mirrored.interfaces.MirroredInterface;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.span.attributes.mirrored.interfaces.MirroredInterfaceBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.span.attributes.mirrored.interfaces.MirroredInterfaceKey;
-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 final class MirroredInterfacesCustomizer
+abstract class AbstractMirroredInterfacesCustomizer
         extends FutureJVppCustomizer
         implements InitializingReaderCustomizer<MirroredInterfaces, MirroredInterfacesBuilder>, JvppReplyConsumer {
 
-    private static final Logger LOG = LoggerFactory.getLogger(MirroredInterfacesCustomizer.class);
+    private static final Logger LOG = LoggerFactory.getLogger(AbstractMirroredInterfacesCustomizer.class);
 
     private final NamingContext ifcContext;
+    private final Function<InstanceIdentifier<MirroredInterfaces>, String> destinationInterfaceNameExtractor;
 
-    public MirroredInterfacesCustomizer(@Nonnull final FutureJVppCore futureJVppCore, final NamingContext ifcContext) {
+    protected AbstractMirroredInterfacesCustomizer(@Nonnull final FutureJVppCore futureJVppCore,
+                                                   @Nonnull final NamingContext ifcContext,
+                                                   @Nonnull final Function<InstanceIdentifier<MirroredInterfaces>, String> destinationInterfaceNameExtractor) {
         super(futureJVppCore);
         this.ifcContext = ifcContext;
+        this.destinationInterfaceNameExtractor = destinationInterfaceNameExtractor;
     }
 
     @Nonnull
@@ -71,8 +68,7 @@ public final class MirroredInterfacesCustomizer
                                       @Nonnull final MirroredInterfacesBuilder builder, @Nonnull final ReadContext ctx)
             throws ReadFailedException {
         LOG.trace("Reading mirrored interfaces under: {}", id);
-        final int dstId =
-                ifcContext.getIndex(id.firstKeyOf(Interface.class).getName(), ctx.getMappingContext());
+        final int dstId = destinationInterfaceIndex(id, ctx.getMappingContext());
 
         final SwInterfaceSpanDetailsReplyDump replyForRead;
         if (ctx.getModificationCache().containsKey(getCacheKey())) {
@@ -110,22 +106,9 @@ public final class MirroredInterfacesCustomizer
         return getClass().getName();
     }
 
-    @Override
-    public void merge(@Nonnull final Builder<? extends DataObject> parentBuilder,
-                      @Nonnull final MirroredInterfaces readValue) {
-        ((SpanBuilder) parentBuilder).setMirroredInterfaces(readValue);
-    }
-
-    @Nonnull
-    @Override
-    public Initialized<? extends DataObject> init(@Nonnull final InstanceIdentifier<MirroredInterfaces> id,
-                                                  @Nonnull final MirroredInterfaces readValue,
-                                                  @Nonnull final ReadContext ctx) {
-        final InstanceIdentifier<MirroredInterfaces> cfgId =
-                InterfaceCustomizer.getCfgId(RWUtils.cutId(id, Interface.class))
-                        .augmentation(VppInterfaceAugmentation.class)
-                        .child(Span.class)
-                        .child(MirroredInterfaces.class);
-        return Initialized.create(cfgId, readValue);
+    private int destinationInterfaceIndex(@Nonnull final InstanceIdentifier<MirroredInterfaces> id,
+                                          @Nonnull final MappingContext mappingContext) {
+        final String destinationInterfaceName = destinationInterfaceNameExtractor.apply(id);
+        return ifcContext.getIndex(destinationInterfaceName, mappingContext);
     }
 }
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/span/InterfaceMirroredInterfacesCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/span/InterfaceMirroredInterfacesCustomizer.java
new file mode 100644 (file)
index 0000000..9f05c61
--- /dev/null
@@ -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.interfacesstate.span;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.v3po.interfacesstate.InterfaceCustomizer;
+import io.fd.honeycomb.translate.read.ReadContext;
+import io.fd.honeycomb.translate.spi.read.Initialized;
+import io.fd.honeycomb.translate.util.RWUtils;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+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.opendaylight.params.xml.ns.yang.v3po.rev170315.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.interfaces.state._interface.SpanBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.span.attributes.MirroredInterfaces;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Provides interface-specific logic to read/init port mirroring configuration
+ */
+public class InterfaceMirroredInterfacesCustomizer extends AbstractMirroredInterfacesCustomizer {
+
+    public InterfaceMirroredInterfacesCustomizer(@Nonnull final FutureJVppCore futureJVppCore,
+                                                 @Nonnull final NamingContext ifcContext) {
+        super(futureJVppCore, ifcContext, id -> id.firstKeyOf(Interface.class).getName());
+    }
+
+    @Nonnull
+    @Override
+    public Initialized<? extends DataObject> init(@Nonnull final InstanceIdentifier<MirroredInterfaces> id,
+                                                  @Nonnull final MirroredInterfaces readValue,
+                                                  @Nonnull final ReadContext ctx) {
+        final InstanceIdentifier<MirroredInterfaces> cfgId =
+                InterfaceCustomizer.getCfgId(RWUtils.cutId(id, Interface.class))
+                        .augmentation(VppInterfaceAugmentation.class)
+                        .child(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.interfaces._interface.Span.class)
+                        .child(MirroredInterfaces.class);
+        return Initialized.create(cfgId, readValue);
+    }
+
+    @Override
+    public void merge(@Nonnull Builder<? extends DataObject> builder, @Nonnull MirroredInterfaces mirroredInterfaces) {
+        ((SpanBuilder) builder).setMirroredInterfaces(mirroredInterfaces);
+    }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/span/SubInterfaceMirroredInterfacesCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/span/SubInterfaceMirroredInterfacesCustomizer.java
new file mode 100644 (file)
index 0000000..8d3557f
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * 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.interfacesstate.span;
+
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.v3po.interfacesstate.SubInterfaceCustomizer;
+import io.fd.hc2vpp.v3po.util.SubInterfaceUtils;
+import io.fd.honeycomb.translate.read.ReadContext;
+import io.fd.honeycomb.translate.spi.read.Initialized;
+import io.fd.honeycomb.translate.util.RWUtils;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.subinterface.span.rev170510.VppSubinterfaceSpanAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.subinterface.span.rev170510.interfaces._interface.sub.interfaces.sub._interface.Span;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.subinterface.span.rev170510.interfaces.state._interface.sub.interfaces.sub._interface.SpanStateBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.span.attributes.MirroredInterfaces;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170509.interfaces.state._interface.sub.interfaces.SubInterface;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Provides sub-interface-specific logic to read/init port mirroring configuration
+ */
+public class SubInterfaceMirroredInterfacesCustomizer extends AbstractMirroredInterfacesCustomizer {
+
+    public SubInterfaceMirroredInterfacesCustomizer(@Nonnull FutureJVppCore futureJVppCore, NamingContext ifcContext) {
+        super(futureJVppCore, ifcContext, SubInterfaceUtils::subInterfaceFullNameOperational);
+    }
+
+    @Nonnull
+    @Override
+    public Initialized<? extends DataObject> init(@Nonnull InstanceIdentifier<MirroredInterfaces> id,
+                                                  @Nonnull MirroredInterfaces readValue,
+                                                  @Nonnull ReadContext readContext) {
+        final InstanceIdentifier<MirroredInterfaces> cfgId =
+                SubInterfaceCustomizer.getCfgId(RWUtils.cutId(id, SubInterface.class))
+                        .augmentation(VppSubinterfaceSpanAugmentation.class)
+                        .child(Span.class)
+                        .child(MirroredInterfaces.class);
+
+        return Initialized.create(cfgId, readValue);
+    }
+
+    @Override
+    public void merge(@Nonnull Builder<? extends DataObject> builder, @Nonnull MirroredInterfaces mirroredInterfaces) {
+        ((SpanStateBuilder) builder).setMirroredInterfaces(mirroredInterfaces);
+    }
+}
index 7b83aaf..6fdf2e1 100644 (file)
@@ -26,7 +26,6 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170509.interfaces._interface.sub.interfaces.SubInterface;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170509.sub._interface.base.attributes.Tags;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170509.sub._interface.base.attributes.tags.Tag;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170509.sub._interface.routing.attributes.Routing;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
 public final class SubInterfaceUtils {
@@ -39,7 +38,7 @@ public final class SubInterfaceUtils {
         return String.format("%s.%d", superIfName, subIfaceId);
     }
 
-    public static String subInterfaceFullNameConfig(final @Nonnull InstanceIdentifier<Routing> instanceIdentifier) {
+    public static String subInterfaceFullNameConfig(final @Nonnull InstanceIdentifier<?> instanceIdentifier) {
         final String parentInterfaceName =
                 checkNotNull(instanceIdentifier.firstKeyOf(Interface.class), "Configuration identifier expected")
                         .getName();
@@ -47,7 +46,7 @@ public final class SubInterfaceUtils {
         return SubInterfaceUtils.getSubInterfaceName(parentInterfaceName, subIfId.intValue());
     }
 
-    public static String subInterfaceFullNameOperational(final @Nonnull InstanceIdentifier<Routing> instanceIdentifier) {
+    public static String subInterfaceFullNameOperational(final @Nonnull InstanceIdentifier<?> instanceIdentifier) {
         final String parentInterfaceName = checkNotNull(instanceIdentifier.firstKeyOf(
                 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class),
                 "Operational identifier expected").getName();
@@ -41,7 +41,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.rev170315.span.attributes.mirrored.interfaces.MirroredInterfaceBuilder;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
-public class MirroredInterfaceCustomizerTest extends WriterCustomizerTest {
+public class MirroredInterfacesCustomizerTest extends WriterCustomizerTest {
 
     private static final String IFACE_NAME = "iface";
     private static final int IFACE_INDEX = 3;
@@ -59,7 +59,8 @@ public class MirroredInterfaceCustomizerTest extends WriterCustomizerTest {
 
     public void setUpTest() {
         interfaceContext = new NamingContext("iface", "iface-context");
-        customizer = new MirroredInterfaceCustomizer(api, interfaceContext);
+        customizer =
+                new MirroredInterfaceCustomizer(api, interfaceContext, id -> id.firstKeyOf(Interface.class).getName());
         defineMapping(mappingContext, IFACE_NAME, IFACE_INDEX, "iface-context");
         defineMapping(mappingContext, SRC_IFACE_NAME, SRC_IFACE_INDEX, "iface-context");
 
index 5d52e76..3a4ce5d 100644 (file)
@@ -124,6 +124,6 @@ public class MirroredInterfacesCustomizerTest
 
     @Override
     protected ReaderCustomizer<MirroredInterfaces, MirroredInterfacesBuilder> initCustomizer() {
-        return new MirroredInterfacesCustomizer(api, interfaceContext);
+        return new InterfaceMirroredInterfacesCustomizer(api, interfaceContext);
     }
 }
\ No newline at end of file