Pbb Support 33/1833/30
authorJan Srnicek <jsrnicek@cisco.com>
Fri, 7 Oct 2016 09:11:09 +0000 (11:11 +0200)
committerJan Srnicek <jsrnicek@cisco.com>
Fri, 7 Oct 2016 09:11:09 +0000 (11:11 +0200)
models/implementation refactored to work as rewrite on interfaces

Change-Id: I8ce42905ce8f183c354e718d02291aea2435110d
Signed-off-by: Jan Srnicek <jsrnicek@cisco.com>
v3po/api/src/main/yang/pbb-types.yang [new file with mode: 0644]
v3po/api/src/main/yang/vpp-pbb.yang [new file with mode: 0644]
v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/InterfacesStateReaderFactory.java
v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/InterfacesWriterFactory.java
v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/pbb/PbbRewriteCustomizer.java [new file with mode: 0644]
v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfacesstate/pbb/PbbRewriteStateCustomizer.java [new file with mode: 0644]
v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/pbb/PbbRewriteCustomizerTest.java [new file with mode: 0644]
v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfacesstate/pbb/PbbRewriteStateCustomizerTest.java [new file with mode: 0644]

diff --git a/v3po/api/src/main/yang/pbb-types.yang b/v3po/api/src/main/yang/pbb-types.yang
new file mode 100644 (file)
index 0000000..1b3d4b6
--- /dev/null
@@ -0,0 +1,81 @@
+module pbb-types {
+  yang-version 1;
+  namespace "urn:opendaylight:params:xml:ns:yang:pbb-types";
+  prefix "pbb-types";
+
+  description "Common types used for defining Pbb based subinterfaces";
+
+  revision "2016-07-04" {
+          description
+              "Initial revision.";
+  }
+
+  import ietf-yang-types {
+      prefix yang;
+  }
+
+  import ietf-interfaces {
+      prefix if;
+  }
+
+  import yang-ext {
+      prefix "ext";
+  }
+
+  typedef operation {
+      type enumeration {
+        // NOTE - Does not specify disabled enum value(0), because its used internally to delete/disable rewrite
+        enum "push-2"{
+            value 2;
+        }
+
+        enum "pop-2"{
+            value 4;
+            description "Encapsulate/Decapsulate pbb packet according to incoming/outcoming direction";
+        }
+        enum "translate-2-1"{
+            value 7;
+        }
+      }
+  }
+
+  grouping pbb-rewrite-attributes {
+    description "Provider Backbone Bridge attributes";
+
+    leaf destination-address{
+      type yang:mac-address;
+      description "backbone destination address";
+    }
+
+    leaf source-address{
+      type yang:mac-address;
+      description "backbone source address";
+    }
+
+    leaf outer-tag{
+        type uint16;
+    }
+
+    leaf b-vlan-tag-vlan-id{
+        type uint16{
+            //12 bit range
+            range "1..4095";
+        }
+        description "backbone vlan id";
+    }
+
+    leaf i-tag-isid {
+        type uint32{
+          //24 bit range
+          range "1..16777215";
+        }
+        description "identifier of the backbone service instance ";
+    }
+
+    leaf interface-operation {
+        type operation;
+        default pop-2;
+        description "Define operation that will pbb interface perform while processing packets";
+    }
+  }
+}
diff --git a/v3po/api/src/main/yang/vpp-pbb.yang b/v3po/api/src/main/yang/vpp-pbb.yang
new file mode 100644 (file)
index 0000000..848f04e
--- /dev/null
@@ -0,0 +1,32 @@
+module vpp-pbb {
+  yang-version 1;
+  namespace "urn:opendaylight:params:xml:ns:yang:vpp-pbb";
+  prefix "vpp-pbb";
+
+  revision "2016-04-10" {
+    description "Initial revision of pbb model";
+  }
+
+  import pbb-types{
+    prefix "pbb-types";
+  }
+
+  import yang-ext {
+    prefix "ext";
+  }
+
+  augment /if:interfaces/if:interface {
+     ext:augment-identifier "pbb-rewrite-interface-augmentation";
+     container pbb-rewrite{
+        uses pbb-types:pbb-rewrite-attributes;
+     }
+  }
+
+  augment /if:interfaces-state/if:interface {
+      ext:augment-identifier "pbb-rewrite-state-interface-augmentation";
+      container pbb-rewrite-state{
+         uses pbb-types:pbb-rewrite-attributes;
+         config false;
+      }
+  }
+}
\ No newline at end of file
index 0a94a1b..c7f80e3 100644 (file)
@@ -25,7 +25,6 @@ import io.fd.honeycomb.translate.read.ReaderFactory;
 import io.fd.honeycomb.translate.read.registry.ModifiableReaderRegistryBuilder;
 import io.fd.honeycomb.translate.v3po.interfacesstate.EthernetCustomizer;
 import io.fd.honeycomb.translate.v3po.interfacesstate.GreCustomizer;
-import io.fd.honeycomb.translate.v3po.interfacesstate.acl.ingress.AclCustomizer;
 import io.fd.honeycomb.translate.v3po.interfacesstate.InterfaceCustomizer;
 import io.fd.honeycomb.translate.v3po.interfacesstate.L2Customizer;
 import io.fd.honeycomb.translate.v3po.interfacesstate.ProxyArpCustomizer;
@@ -33,10 +32,12 @@ import io.fd.honeycomb.translate.v3po.interfacesstate.TapCustomizer;
 import io.fd.honeycomb.translate.v3po.interfacesstate.VhostUserCustomizer;
 import io.fd.honeycomb.translate.v3po.interfacesstate.VxlanCustomizer;
 import io.fd.honeycomb.translate.v3po.interfacesstate.VxlanGpeCustomizer;
+import io.fd.honeycomb.translate.v3po.interfacesstate.acl.ingress.AclCustomizer;
 import io.fd.honeycomb.translate.v3po.interfacesstate.ip.Ipv4AddressCustomizer;
 import io.fd.honeycomb.translate.v3po.interfacesstate.ip.Ipv4Customizer;
 import io.fd.honeycomb.translate.v3po.interfacesstate.ip.Ipv4NeighbourCustomizer;
 import io.fd.honeycomb.translate.v3po.interfacesstate.ip.Ipv6Customizer;
+import io.fd.honeycomb.translate.v3po.interfacesstate.pbb.PbbRewriteStateCustomizer;
 import io.fd.honeycomb.translate.v3po.vppclassifier.VppClassifierContextManager;
 import io.fd.honeycomb.translate.vpp.util.NamingContext;
 import io.fd.vpp.jvpp.core.future.FutureJVppCore;
@@ -65,6 +66,9 @@ 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.rev150105.interfaces.state._interface.Vxlan;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.VxlanGpe;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.acl.Ingress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.pbb.rev160410.PbbRewriteStateInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.pbb.rev160410.PbbRewriteStateInterfaceAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.pbb.rev160410.interfaces.state._interface.PbbRewriteState;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
 public final class InterfacesStateReaderFactory implements ReaderFactory {
@@ -76,7 +80,7 @@ public final class InterfacesStateReaderFactory implements ReaderFactory {
     private final FutureJVppCore jvpp;
 
     static final InstanceIdentifier<InterfacesState> IFC_STATE_ID =
-        InstanceIdentifier.create(InterfacesState.class);
+            InstanceIdentifier.create(InterfacesState.class);
     static final InstanceIdentifier<Interface> IFC_ID = IFC_STATE_ID.child(Interface.class);
 
     @Inject
@@ -105,6 +109,8 @@ public final class InterfacesStateReaderFactory implements ReaderFactory {
         initInterface2AugmentationReaders(registry, IFC_ID);
         // vpp-vlan.yang
         new SubinterfaceStateAugmentationReaderFactory(jvpp, ifcNamingCtx, bdNamingCtx, classifyContext).init(registry);
+        //vpp-pbb.yang
+        initPbbRewriteAugmentation(registry, IFC_ID);
     }
 
     private void initInterface2AugmentationReaders(final ModifiableReaderRegistryBuilder registry,
@@ -130,39 +136,54 @@ public final class InterfacesStateReaderFactory implements ReaderFactory {
                                                final InstanceIdentifier<Interface> ifcId) {
         //   VppInterfaceStateAugmentation
         final InstanceIdentifier<VppInterfaceStateAugmentation> vppIfcAugId =
-            ifcId.augmentation(VppInterfaceStateAugmentation.class);
+                ifcId.augmentation(VppInterfaceStateAugmentation.class);
         registry.addStructuralReader(vppIfcAugId, VppInterfaceStateAugmentationBuilder.class);
         //    Ethernet
         registry
-            .add(new GenericReader<>(vppIfcAugId.child(Ethernet.class), new EthernetCustomizer(jvpp, ifcNamingCtx)));
+                .add(new GenericReader<>(vppIfcAugId.child(Ethernet.class),
+                        new EthernetCustomizer(jvpp, ifcNamingCtx)));
         //    Tap
         registry.add(new GenericReader<>(vppIfcAugId.child(Tap.class), new TapCustomizer(jvpp, ifcNamingCtx)));
         //    VhostUser
         registry
-            .add(new GenericReader<>(vppIfcAugId.child(VhostUser.class), new VhostUserCustomizer(jvpp, ifcNamingCtx)));
+                .add(new GenericReader<>(vppIfcAugId.child(VhostUser.class),
+                        new VhostUserCustomizer(jvpp, ifcNamingCtx)));
         //    Vxlan
         registry.add(new GenericReader<>(vppIfcAugId.child(Vxlan.class), new VxlanCustomizer(jvpp, ifcNamingCtx)));
         //    VxlanGpe
         registry
-            .add(new GenericReader<>(vppIfcAugId.child(VxlanGpe.class), new VxlanGpeCustomizer(jvpp, ifcNamingCtx)));
+                .add(new GenericReader<>(vppIfcAugId.child(VxlanGpe.class),
+                        new VxlanGpeCustomizer(jvpp, ifcNamingCtx)));
         //    Gre
         registry.add(new GenericReader<>(vppIfcAugId.child(Gre.class), new GreCustomizer(jvpp, ifcNamingCtx)));
         //    L2
         registry
-            .add(new GenericReader<>(vppIfcAugId.child(L2.class), new L2Customizer(jvpp, ifcNamingCtx, bdNamingCtx)));
+                .add(new GenericReader<>(vppIfcAugId.child(L2.class),
+                        new L2Customizer(jvpp, ifcNamingCtx, bdNamingCtx)));
         //    Acl(Structural)
         final InstanceIdentifier<Acl> aclIid = vppIfcAugId.child(Acl.class);
         registry.addStructuralReader(aclIid, AclBuilder.class);
         //    Ingress(Subtree)
         final InstanceIdentifier<Ingress> ingressIdRelative = InstanceIdentifier.create(Ingress.class);
         registry.subtreeAdd(
-            Sets.newHashSet(ingressIdRelative.child(L2Acl.class), ingressIdRelative.child(Ip4Acl.class),
-                ingressIdRelative.child(Ip6Acl.class)),
-            new GenericReader<>(aclIid.child(Ingress.class),
-                new AclCustomizer(jvpp, ifcNamingCtx,
-                    classifyContext)));
+                Sets.newHashSet(ingressIdRelative.child(L2Acl.class), ingressIdRelative.child(Ip4Acl.class),
+                        ingressIdRelative.child(Ip6Acl.class)),
+                new GenericReader<>(aclIid.child(Ingress.class),
+                        new AclCustomizer(jvpp, ifcNamingCtx,
+                                classifyContext)));
         //   Proxy ARP
         registry.add(new GenericReader<>(vppIfcAugId.child(ProxyArp.class), new ProxyArpCustomizer(jvpp,
-            ifcNamingCtx)));
+                ifcNamingCtx)));
     }
+
+    private void initPbbRewriteAugmentation(final ModifiableReaderRegistryBuilder registry,
+                                            final InstanceIdentifier<Interface> ifcId) {
+
+        registry.addStructuralReader(ifcId.augmentation(PbbRewriteStateInterfaceAugmentation.class),
+                PbbRewriteStateInterfaceAugmentationBuilder.class);
+
+        registry.add(new GenericReader<>(ifcId.augmentation(PbbRewriteStateInterfaceAugmentation.class).child(
+                PbbRewriteState.class), new PbbRewriteStateCustomizer(jvpp)));
+    }
+
 }
index 29a6ac5..d138dac 100644 (file)
@@ -41,6 +41,7 @@ import io.fd.honeycomb.translate.v3po.interfaces.ip.Ipv4AddressCustomizer;
 import io.fd.honeycomb.translate.v3po.interfaces.ip.Ipv4Customizer;
 import io.fd.honeycomb.translate.v3po.interfaces.ip.Ipv4NeighbourCustomizer;
 import io.fd.honeycomb.translate.v3po.interfaces.ip.Ipv6Customizer;
+import io.fd.honeycomb.translate.v3po.interfaces.pbb.PbbRewriteCustomizer;
 import io.fd.honeycomb.translate.v3po.vppclassifier.VppClassifierContextManager;
 import io.fd.honeycomb.translate.vpp.util.NamingContext;
 import io.fd.honeycomb.translate.write.WriterFactory;
@@ -71,24 +72,26 @@ 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.rev150105.interfaces._interface.Vxlan;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.VxlanGpe;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.acl.Ingress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.pbb.rev160410.PbbRewriteInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.pbb.rev160410.interfaces._interface.PbbRewrite;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
 public final class InterfacesWriterFactory implements WriterFactory {
 
     public static final InstanceIdentifier<Interface> IFC_ID =
-        InstanceIdentifier.create(Interfaces.class).child(Interface.class);
+            InstanceIdentifier.create(Interfaces.class).child(Interface.class);
     public static final InstanceIdentifier<VppInterfaceAugmentation> VPP_IFC_AUG_ID =
-        IFC_ID.augmentation(VppInterfaceAugmentation.class);
+            IFC_ID.augmentation(VppInterfaceAugmentation.class);
     public static final InstanceIdentifier<Acl> ACL_ID = VPP_IFC_AUG_ID.child(Acl.class);
     public static final InstanceIdentifier<Ingress> INGRESS_ACL_ID = ACL_ID.child(Ingress.class);
     public static final InstanceIdentifier<L2> L2_ID = VPP_IFC_AUG_ID.child(L2.class);
     public static final InstanceIdentifier<IetfAcl> IETF_ACL_ID = VPP_IFC_AUG_ID.child(IetfAcl.class);
     public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.ietf.acl.Ingress>
-        INGRESS_IETF_ACL_ID = IETF_ACL_ID.child(
-        org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.ietf.acl.Ingress.class);
+            INGRESS_IETF_ACL_ID = IETF_ACL_ID.child(
+            org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.ietf.acl.Ingress.class);
     public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.ietf.acl.Egress>
-        EGRESS_IETF_ACL_ID = IETF_ACL_ID.child(
-        org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.ietf.acl.Egress.class);
+            EGRESS_IETF_ACL_ID = IETF_ACL_ID.child(
+            org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.ietf.acl.Egress.class);
 
     private final FutureJVppCore jvpp;
     private final IetfAClWriter aclWriter;
@@ -123,7 +126,9 @@ public final class InterfacesWriterFactory implements WriterFactory {
         addInterface1AugmentationWriters(IFC_ID, registry);
         //   SubinterfaceAugmentation
         new SubinterfaceAugmentationWriterFactory(jvpp, aclWriter, ifcNamingContext, bdNamingContext,
-            classifyTableContext).init(registry);
+                classifyTableContext).init(registry);
+
+        addPbbAugmentationWriters(IFC_ID, registry);
     }
 
     private void addInterface1AugmentationWriters(final InstanceIdentifier<Interface> ifcId,
@@ -131,19 +136,19 @@ public final class InterfacesWriterFactory implements WriterFactory {
         final InstanceIdentifier<Interface1> ifc1AugId = ifcId.augmentation(Interface1.class);
         // Ipv6(after interface) =
         registry.addAfter(new GenericWriter<>(ifc1AugId.child(Ipv6.class), new Ipv6Customizer(jvpp)),
-            ifcId);
+                ifcId);
         // Ipv4(after interface)
         final InstanceIdentifier<Ipv4> ipv4Id = ifc1AugId.child(Ipv4.class);
         registry.addAfter(new GenericWriter<>(ipv4Id, new Ipv4Customizer(jvpp)),
-            ifcId);
+                ifcId);
         //  Address(after Ipv4) =
         final InstanceIdentifier<Address> ipv4AddressId = ipv4Id.child(Address.class);
         registry.addAfter(new GenericListWriter<>(ipv4AddressId, new Ipv4AddressCustomizer(jvpp, ifcNamingContext)),
-            ipv4Id);
+                ipv4Id);
         //  Neighbor(after ipv4Address)
         registry.addAfter(new GenericListWriter<>(ipv4Id.child(Neighbor.class), new Ipv4NeighbourCustomizer(jvpp,
-                ifcNamingContext)),
-            ipv4AddressId);
+                        ifcNamingContext)),
+                ipv4AddressId);
     }
 
     private void addVppInterfaceAgmentationWriters(final InstanceIdentifier<Interface> ifcId,
@@ -151,24 +156,24 @@ public final class InterfacesWriterFactory implements WriterFactory {
         // VhostUser(Needs to be executed before Interface customizer) =
         final InstanceIdentifier<VhostUser> vhostId = VPP_IFC_AUG_ID.child(VhostUser.class);
         registry.addBefore(new GenericWriter<>(vhostId, new VhostUserCustomizer(jvpp, ifcNamingContext)),
-            ifcId);
+                ifcId);
         // Vxlan(Needs to be executed before Interface customizer) =
         final InstanceIdentifier<Vxlan> vxlanId = VPP_IFC_AUG_ID.child(Vxlan.class);
         registry.addBefore(new GenericWriter<>(vxlanId, new VxlanCustomizer(jvpp, ifcNamingContext, ifcDisableContext)),
-            ifcId);
+                ifcId);
         // VxlanGpe(Needs to be executed before Interface customizer) =
         final InstanceIdentifier<VxlanGpe> vxlanGpeId = VPP_IFC_AUG_ID.child(VxlanGpe.class);
         registry.addBefore(new GenericWriter<>(vxlanGpeId,
-            new VxlanGpeCustomizer(jvpp, ifcNamingContext, ifcDisableContext)), ifcId);
+                new VxlanGpeCustomizer(jvpp, ifcNamingContext, ifcDisableContext)), ifcId);
         // Tap(Needs to be executed before Interface customizer) =
         final InstanceIdentifier<Tap> tapId = VPP_IFC_AUG_ID.child(Tap.class);
         registry.addBefore(new GenericWriter<>(tapId, new TapCustomizer(jvpp, ifcNamingContext)),
-            ifcId);
+                ifcId);
 
         // Gre(Needs to be executed before Interface customizer) =
         final InstanceIdentifier<Gre> greId = VPP_IFC_AUG_ID.child(Gre.class);
         registry.addBefore(new GenericWriter<>(greId, new GreCustomizer(jvpp, ifcNamingContext)),
-            ifcId);
+                ifcId);
 
 
         final Set<InstanceIdentifier<?>> specificIfcTypes = Sets.newHashSet(vhostId, vxlanGpeId, vxlanGpeId, tapId);
@@ -177,48 +182,54 @@ public final class InterfacesWriterFactory implements WriterFactory {
         registry.add(new GenericWriter<>(VPP_IFC_AUG_ID.child(Ethernet.class), new EthernetCustomizer(jvpp)));
         // Routing(Execute only after specific interface customizers) =
         registry.addAfter(
-            new GenericWriter<>(VPP_IFC_AUG_ID.child(Routing.class), new RoutingCustomizer(jvpp, ifcNamingContext)),
-            specificIfcTypes);
+                new GenericWriter<>(VPP_IFC_AUG_ID.child(Routing.class), new RoutingCustomizer(jvpp, ifcNamingContext)),
+                specificIfcTypes);
         // L2(Execute only after subinterface (and all other ifc types) =
         registry.addAfter(new GenericWriter<>(L2_ID, new L2Customizer(jvpp, ifcNamingContext, bdNamingContext)),
-            SubinterfaceAugmentationWriterFactory.SUB_IFC_ID);
+                SubinterfaceAugmentationWriterFactory.SUB_IFC_ID);
         // Proxy Arp (execute after specific interface customizers)
         registry.addAfter(
-            new GenericWriter<>(VPP_IFC_AUG_ID.child(ProxyArp.class), new ProxyArpCustomizer(jvpp)),
-            specificIfcTypes);
+                new GenericWriter<>(VPP_IFC_AUG_ID.child(ProxyArp.class), new ProxyArpCustomizer(jvpp)),
+                specificIfcTypes);
         // Ingress (execute after classify table and session writers)
         // also handles L2Acl, Ip4Acl and Ip6Acl:
         final InstanceIdentifier<Ingress> ingressId = InstanceIdentifier.create(Ingress.class);
         registry
-            .subtreeAddAfter(
-                Sets.newHashSet(ingressId.child(L2Acl.class), ingressId.child(Ip4Acl.class),
-                    ingressId.child(Ip6Acl.class)),
-                new GenericWriter<>(INGRESS_ACL_ID,
-                    new AclCustomizer(jvpp, ifcNamingContext, classifyTableContext)),
-                Sets.newHashSet(CLASSIFY_TABLE_ID, CLASSIFY_SESSION_ID));
+                .subtreeAddAfter(
+                        Sets.newHashSet(ingressId.child(L2Acl.class), ingressId.child(Ip4Acl.class),
+                                ingressId.child(Ip6Acl.class)),
+                        new GenericWriter<>(INGRESS_ACL_ID,
+                                new AclCustomizer(jvpp, ifcNamingContext, classifyTableContext)),
+                        Sets.newHashSet(CLASSIFY_TABLE_ID, CLASSIFY_SESSION_ID));
 
         // Ingress IETF-ACL, also handles AccessLists and Acl:
         final InstanceIdentifier<AccessLists> accessListsIdIngress = InstanceIdentifier.create(
-            org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.ietf.acl.Ingress.class)
-            .child(AccessLists.class);
+                org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.ietf.acl.Ingress.class)
+                .child(AccessLists.class);
         final InstanceIdentifier<?> aclIdIngress = accessListsIdIngress.child(
-            org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.ietf.acl.base.attributes.access.lists.Acl.class);
+                org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.ietf.acl.base.attributes.access.lists.Acl.class);
         registry.subtreeAdd(
-            Sets.newHashSet(accessListsIdIngress, aclIdIngress),
-            new GenericWriter<>(INGRESS_IETF_ACL_ID, new IetfAclCustomizer(aclWriter, ifcNamingContext)));
+                Sets.newHashSet(accessListsIdIngress, aclIdIngress),
+                new GenericWriter<>(INGRESS_IETF_ACL_ID, new IetfAclCustomizer(aclWriter, ifcNamingContext)));
 
         // Ingress IETF-ACL, also handles AccessLists and Acl:
         final InstanceIdentifier<AccessLists> accessListsIdEgress = InstanceIdentifier.create(
-            org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.ietf.acl.Egress.class)
-            .child(AccessLists.class);
+                org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.ietf.acl.Egress.class)
+                .child(AccessLists.class);
         final InstanceIdentifier<?> aclIdEgress = accessListsIdEgress.child(
-            org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.ietf.acl.base.attributes.access.lists.Acl.class);
+                org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.ietf.acl.base.attributes.access.lists.Acl.class);
         registry.subtreeAdd(
-            Sets.newHashSet(accessListsIdEgress, aclIdEgress),
-            new GenericWriter<>(EGRESS_IETF_ACL_ID,
-                new io.fd.honeycomb.translate.v3po.interfaces.acl.egress.IetfAclCustomizer(aclWriter,
-                    ifcNamingContext)));
+                Sets.newHashSet(accessListsIdEgress, aclIdEgress),
+                new GenericWriter<>(EGRESS_IETF_ACL_ID,
+                        new io.fd.honeycomb.translate.v3po.interfaces.acl.egress.IetfAclCustomizer(aclWriter,
+                                ifcNamingContext)));
     }
 
+    private void addPbbAugmentationWriters(final InstanceIdentifier<Interface> ifcId,
+                                           final ModifiableWriterRegistryBuilder registry) {
+        final InstanceIdentifier<PbbRewrite> pbbRewriteId =
+                ifcId.augmentation(PbbRewriteInterfaceAugmentation.class).child(PbbRewrite.class);
 
+        registry.add(new GenericWriter<>(pbbRewriteId, new PbbRewriteCustomizer(jvpp, ifcNamingContext)));
+    }
 }
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/pbb/PbbRewriteCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/pbb/PbbRewriteCustomizer.java
new file mode 100644 (file)
index 0000000..79256ea
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.translate.v3po.interfaces.pbb;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.honeycomb.translate.spi.write.WriterCustomizer;
+import io.fd.honeycomb.translate.vpp.util.FutureJVppCustomizer;
+import io.fd.honeycomb.translate.vpp.util.JvppReplyConsumer;
+import io.fd.honeycomb.translate.vpp.util.MacTranslator;
+import io.fd.honeycomb.translate.vpp.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.VppBaseCallException;
+import io.fd.vpp.jvpp.core.dto.L2InterfacePbbTagRewrite;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import java.util.concurrent.TimeoutException;
+import javax.annotation.Nonnull;
+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.vpp.pbb.rev160410.interfaces._interface.PbbRewrite;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class PbbRewriteCustomizer extends FutureJVppCustomizer
+        implements WriterCustomizer<PbbRewrite>, MacTranslator, JvppReplyConsumer {
+
+    private static final int OPERATION_DISABLE = 0;
+
+    private final NamingContext interfaceNamingContext;
+
+    public PbbRewriteCustomizer(@Nonnull final FutureJVppCore futureJVppCore,
+                                @Nonnull final NamingContext interfaceNamingContext) {
+        super(futureJVppCore);
+        this.interfaceNamingContext = checkNotNull(interfaceNamingContext, "Interface naming context cannot be null");
+    }
+
+    @Override
+    public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<PbbRewrite> id,
+                                       @Nonnull final PbbRewrite dataAfter, @Nonnull final WriteContext writeContext)
+            throws WriteFailedException {
+        try {
+            setPbbRewrite(id, dataAfter, writeContext, false);
+        } catch (TimeoutException | VppBaseCallException e) {
+            throw new WriteFailedException.CreateFailedException(id, dataAfter, e);
+        }
+    }
+
+    @Override
+    public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<PbbRewrite> id,
+                                        @Nonnull final PbbRewrite dataBefore, @Nonnull final PbbRewrite dataAfter,
+                                        @Nonnull final WriteContext writeContext) throws WriteFailedException {
+        try {
+            setPbbRewrite(id, dataAfter, writeContext, false);
+        } catch (TimeoutException | VppBaseCallException e) {
+            throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, e);
+        }
+    }
+
+    @Override
+    public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<PbbRewrite> id,
+                                        @Nonnull final PbbRewrite dataBefore, @Nonnull final WriteContext writeContext)
+            throws WriteFailedException {
+
+        try {
+            setPbbRewrite(id, dataBefore, writeContext, true);
+        } catch (TimeoutException | VppBaseCallException e) {
+            throw new WriteFailedException.DeleteFailedException(id, e);
+        }
+    }
+
+    private void setPbbRewrite(final InstanceIdentifier<PbbRewrite> id, final PbbRewrite data,
+                               final WriteContext writeContext, final boolean disable)
+            throws TimeoutException, VppBaseCallException {
+        final String interfaceName = checkNotNull(id.firstKeyOf(Interface.class), "Interface key not found").getName();
+
+        final L2InterfacePbbTagRewrite request = new L2InterfacePbbTagRewrite();
+
+        //checking all attributes in preconditions(pbb-rewrite is subcontainer, so there can't be mandatory statements)
+        request.swIfIndex = interfaceNamingContext.getIndex(interfaceName, writeContext.getMappingContext());
+        request.bDmac = parseMac(verifiedDestinationAddress(data));
+        request.bSmac = parseMac(verifiedSourceAddress(data));
+        request.bVlanid = verifiedBVlanId(data);
+        request.iSid = verifiedISid(data);
+        request.vtrOp = verifiedOperation(data, disable);
+
+        //not sure whats gonna happen to this attribute, so its left optional for now
+        if (data.getOuterTag() != null) {
+            request.outerTag = data.getOuterTag().shortValue();
+        }
+
+        getReply(getFutureJVpp().l2InterfacePbbTagRewrite(request).toCompletableFuture());
+    }
+
+    private String verifiedDestinationAddress(final PbbRewrite data) {
+        return checkNotNull(data.getDestinationAddress(), "Destination address cannot be null").getValue();
+    }
+
+    private String verifiedSourceAddress(final PbbRewrite data) {
+        return checkNotNull(data.getSourceAddress(), "Destination address cannot be null").getValue();
+    }
+
+    private byte verifiedBVlanId(final PbbRewrite data) {
+        return (byte) checkNotNull(data.getBVlanTagVlanId(), "BVlan id cannot be null").shortValue();
+    }
+
+    private int verifiedISid(final PbbRewrite data) {
+        return checkNotNull(data.getITagIsid(), "ISid cannot be null").intValue();
+    }
+
+    // if disabled ,then uses non-public allowed value 0, which is equal to operation disable
+    private int verifiedOperation(final PbbRewrite data, final boolean disable) {
+
+        return disable
+                ? OPERATION_DISABLE
+                : checkNotNull(data.getInterfaceOperation(), "Operation cannot be null").getIntValue();
+    }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfacesstate/pbb/PbbRewriteStateCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfacesstate/pbb/PbbRewriteStateCustomizer.java
new file mode 100644 (file)
index 0000000..718e3b1
--- /dev/null
@@ -0,0 +1,42 @@
+package io.fd.honeycomb.translate.v3po.interfacesstate.pbb;
+
+
+import io.fd.honeycomb.translate.read.ReadContext;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.honeycomb.translate.vpp.util.FutureJVppCustomizer;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.pbb.rev160410.PbbRewriteStateInterfaceAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.pbb.rev160410.interfaces.state._interface.PbbRewriteState;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.pbb.rev160410.interfaces.state._interface.PbbRewriteStateBuilder;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class PbbRewriteStateCustomizer extends FutureJVppCustomizer
+        implements ReaderCustomizer<PbbRewriteState, PbbRewriteStateBuilder> {
+
+    public PbbRewriteStateCustomizer(@Nonnull final FutureJVppCore futureJVppCore) {
+        super(futureJVppCore);
+    }
+
+    @Nonnull
+    @Override
+    public PbbRewriteStateBuilder getBuilder(@Nonnull final InstanceIdentifier<PbbRewriteState> id) {
+        return new PbbRewriteStateBuilder();
+    }
+
+    @Override
+    public void readCurrentAttributes(@Nonnull final InstanceIdentifier<PbbRewriteState> id,
+                                      @Nonnull final PbbRewriteStateBuilder builder, @Nonnull final ReadContext ctx)
+            throws ReadFailedException {
+        //TODO implement read after https://jira.fd.io/browse/VPP-468
+    }
+
+    @Override
+    public void merge(@Nonnull final Builder<? extends DataObject> parentBuilder,
+                      @Nonnull final PbbRewriteState readValue) {
+        ((PbbRewriteStateInterfaceAugmentationBuilder) parentBuilder).setPbbRewriteState(readValue);
+    }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/pbb/PbbRewriteCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/pbb/PbbRewriteCustomizerTest.java
new file mode 100644 (file)
index 0000000..d7ac115
--- /dev/null
@@ -0,0 +1,296 @@
+package io.fd.honeycomb.translate.v3po.interfaces.pbb;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import io.fd.honeycomb.translate.vpp.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.honeycomb.vpp.test.write.WriterCustomizerTest;
+import io.fd.vpp.jvpp.VppCallbackException;
+import io.fd.vpp.jvpp.core.dto.L2InterfacePbbTagRewrite;
+import io.fd.vpp.jvpp.core.dto.L2InterfacePbbTagRewriteReply;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+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.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pbb.types.rev160704.Operation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.pbb.rev160410.PbbRewriteInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.pbb.rev160410.interfaces._interface.PbbRewrite;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.pbb.rev160410.interfaces._interface.PbbRewriteBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class PbbRewriteCustomizerTest extends WriterCustomizerTest {
+
+    @Captor
+    private ArgumentCaptor<L2InterfacePbbTagRewrite> rewriteArgumentCaptor;
+
+    private NamingContext interfaceContext;
+    private PbbRewriteCustomizer customizer;
+    private InstanceIdentifier<PbbRewrite> validId;
+    private InstanceIdentifier<PbbRewrite> invalidId;
+
+    @Override
+    protected void setUp() throws Exception {
+        interfaceContext = new NamingContext("interface", "interface-context");
+        customizer = new PbbRewriteCustomizer(api, interfaceContext);
+
+        defineMapping(mappingContext, "pbb-interface", 1, "interface-context");
+        validId = InstanceIdentifier.create(Interfaces.class)
+                .child(Interface.class, new InterfaceKey("pbb-interface"))
+                .augmentation(PbbRewriteInterfaceAugmentation.class)
+                .child(PbbRewrite.class);
+
+        invalidId = InstanceIdentifier.create(PbbRewrite.class);
+    }
+
+    @Test
+    public void testWrite() throws WriteFailedException {
+        whenRewriteThenSuccess();
+        customizer.writeCurrentAttributes(validId, validData(), writeContext);
+        verifyRewriteRequest(desiredSetResult());
+    }
+
+    @Test
+    public void testWriteFailedCallFailed() {
+        whenRewriteThenFail();
+        final PbbRewrite validData = validData();
+        try {
+            customizer.writeCurrentAttributes(validId, validData, writeContext);
+        } catch (Exception e) {
+            assertTrue(e instanceof WriteFailedException.CreateFailedException);
+            assertTrue(e.getCause() instanceof VppCallbackException);
+
+            final WriteFailedException.CreateFailedException ex = ((WriteFailedException.CreateFailedException) e);
+            assertEquals(validId, ex.getFailedId());
+            assertEquals(validData, ex.getData());
+            return;
+        }
+
+        fail("Test should have failed");
+    }
+
+    @Test
+    public void testWriteFailedInvalidData() {
+        verifyInvalidWriteDataCombination(invalidDataNoDestination());
+        verifyInvalidWriteDataCombination(invalidDataNoSource());
+        verifyInvalidWriteDataCombination(invalidDataNoItag());
+        verifyInvalidWriteDataCombination(invalidDataNoOperation());
+        verifyInvalidWriteDataCombination(invalidDataNoVlan());
+    }
+
+    @Test
+    public void testUpdate() throws WriteFailedException {
+        whenRewriteThenSuccess();
+        final PbbRewrite rewrite = validData();
+        customizer.updateCurrentAttributes(validId, rewrite, rewrite, writeContext);
+        verifyRewriteRequest(desiredSetResult());
+    }
+
+    @Test
+    public void testUpdateFailedCallFailed() {
+        whenRewriteThenFail();
+        final PbbRewrite invalidData = invalidDataNoVlan();
+        final PbbRewrite validData = validData();
+        try {
+            customizer.updateCurrentAttributes(validId, invalidData, validData, writeContext);
+        } catch (Exception e) {
+            assertTrue(e instanceof WriteFailedException.UpdateFailedException);
+            assertTrue(e.getCause() instanceof VppCallbackException);
+
+            final WriteFailedException.UpdateFailedException ex = ((WriteFailedException.UpdateFailedException) e);
+            assertEquals(validId, ex.getFailedId());
+            assertEquals(invalidData, ex.getDataBefore());
+            assertEquals(validData, ex.getDataAfter());
+            return;
+        }
+
+        fail("Test should have failed");
+    }
+
+    @Test
+    public void testUpdateFailedInvalidData() {
+        verifyInvalidUpdateDataCombination(invalidDataNoDestination());
+        verifyInvalidUpdateDataCombination(invalidDataNoSource());
+        verifyInvalidUpdateDataCombination(invalidDataNoItag());
+        verifyInvalidUpdateDataCombination(invalidDataNoOperation());
+        verifyInvalidUpdateDataCombination(invalidDataNoVlan());
+    }
+
+    @Test
+    public void testDelete() throws WriteFailedException {
+        whenRewriteThenSuccess();
+        customizer.deleteCurrentAttributes(validId, validData(), writeContext);
+        verifyRewriteRequest(desiredDisableResult());
+    }
+
+    @Test
+    public void testDeleteFailedCallFailed() {
+        whenRewriteThenFail();
+        final PbbRewrite validData = validData();
+        try {
+            customizer.deleteCurrentAttributes(validId, validData, writeContext);
+        } catch (Exception e) {
+            assertTrue(e instanceof WriteFailedException.DeleteFailedException);
+            assertTrue(e.getCause() instanceof VppCallbackException);
+            assertEquals(validId, ((WriteFailedException.DeleteFailedException) e).getFailedId());
+            return;
+        }
+
+        fail("Test should have failed");
+    }
+
+    @Test
+    public void testDeleteFailedInvalidData() {
+        verifyInvalidDeleteDataCombination(invalidDataNoDestination());
+        verifyInvalidDeleteDataCombination(invalidDataNoSource());
+        verifyInvalidDeleteDataCombination(invalidDataNoItag());
+        verifyInvalidDeleteDataCombination(invalidDataNoOperation());
+        verifyInvalidDeleteDataCombination(invalidDataNoVlan());
+    }
+
+    private void whenRewriteThenSuccess() {
+        when(api.l2InterfacePbbTagRewrite(any())).thenReturn(future(new L2InterfacePbbTagRewriteReply()));
+    }
+
+    private void whenRewriteThenFail() {
+        when(api.l2InterfacePbbTagRewrite(any())).thenReturn(failedFuture());
+    }
+
+    private void verifyInvalidWriteDataCombination(final PbbRewrite invalidData) {
+        try {
+            customizer.writeCurrentAttributes(validId, invalidData, writeContext);
+        } catch (Exception e) {
+            assertTrue(e instanceof NullPointerException);
+            return;
+        }
+
+        fail("Verifying of invalid combination failed");
+    }
+
+    private void verifyInvalidUpdateDataCombination(final PbbRewrite invalidData) {
+        try {
+            customizer.updateCurrentAttributes(validId, validData(), invalidData, writeContext);
+        } catch (Exception e) {
+            assertTrue(e instanceof NullPointerException);
+            return;
+        }
+
+        fail("Verifying of invalid combination failed");
+    }
+
+
+    private void verifyInvalidDeleteDataCombination(final PbbRewrite invalidData) {
+        try {
+            customizer.deleteCurrentAttributes(validId, invalidData, writeContext);
+        } catch (Exception e) {
+            assertTrue(e instanceof NullPointerException);
+            return;
+        }
+
+        fail("Verifying of invalid combination failed");
+    }
+
+
+    private L2InterfacePbbTagRewrite desiredSetResult() {
+        final L2InterfacePbbTagRewrite desiredResult = new L2InterfacePbbTagRewrite();
+        desiredResult.swIfIndex = 1;
+        desiredResult.vtrOp = Operation.Pop2.getIntValue();
+        desiredResult.bDmac = new byte[]{-69, -69, -69, -69, -69, -69};
+        desiredResult.bSmac = new byte[]{-86, -86, -86, -86, -86, -86};
+        desiredResult.bVlanid = 1;
+        desiredResult.iSid = 2;
+
+        return desiredResult;
+    }
+
+    private L2InterfacePbbTagRewrite desiredDisableResult() {
+        final L2InterfacePbbTagRewrite desiredResult = new L2InterfacePbbTagRewrite();
+        desiredResult.swIfIndex = 1;
+        desiredResult.vtrOp = 0;
+        desiredResult.bDmac = new byte[]{-69, -69, -69, -69, -69, -69};
+        desiredResult.bSmac = new byte[]{-86, -86, -86, -86, -86, -86};
+        desiredResult.bVlanid = 1;
+        desiredResult.iSid = 2;
+
+        return desiredResult;
+    }
+
+    private void verifyRewriteRequest(final L2InterfacePbbTagRewrite desiredResult) {
+        verify(api, times(1)).l2InterfacePbbTagRewrite(rewriteArgumentCaptor.capture());
+
+        final L2InterfacePbbTagRewrite actualRequest = rewriteArgumentCaptor.getValue();
+
+        assertNotNull(actualRequest);
+        assertEquals(actualRequest.bVlanid, desiredResult.bVlanid);
+        assertEquals(actualRequest.iSid, desiredResult.iSid);
+        assertEquals(actualRequest.vtrOp, desiredResult.vtrOp);
+        assertEquals(actualRequest.outerTag, desiredResult.outerTag);
+        assertArrayEquals(actualRequest.bDmac, desiredResult.bDmac);
+        assertArrayEquals(actualRequest.bSmac, desiredResult.bSmac);
+    }
+
+    private PbbRewrite invalidDataNoDestination() {
+        return new PbbRewriteBuilder()
+                .setBVlanTagVlanId(1)
+                .setITagIsid(2L)
+                .setSourceAddress(new MacAddress("aa:aa:aa:aa:aa:aa"))
+                .setInterfaceOperation(Operation.Pop2)
+                .build();
+    }
+
+    private PbbRewrite invalidDataNoSource() {
+        return new PbbRewriteBuilder()
+                .setBVlanTagVlanId(1)
+                .setITagIsid(2L)
+                .setDestinationAddress(new MacAddress("bb:bb:bb:bb:bb:bb"))
+                .setInterfaceOperation(Operation.Pop2)
+                .build();
+    }
+
+    private PbbRewrite invalidDataNoItag() {
+        return new PbbRewriteBuilder()
+                .setBVlanTagVlanId(1)
+                .setSourceAddress(new MacAddress("aa:aa:aa:aa:aa:aa"))
+                .setDestinationAddress(new MacAddress("bb:bb:bb:bb:bb:bb"))
+                .setInterfaceOperation(Operation.Pop2)
+                .build();
+    }
+
+    private PbbRewrite invalidDataNoVlan() {
+        return new PbbRewriteBuilder()
+                .setITagIsid(2L)
+                .setSourceAddress(new MacAddress("aa:aa:aa:aa:aa:aa"))
+                .setDestinationAddress(new MacAddress("bb:bb:bb:bb:bb:bb"))
+                .setInterfaceOperation(Operation.Pop2)
+                .build();
+    }
+
+    private PbbRewrite invalidDataNoOperation() {
+        return new PbbRewriteBuilder()
+                .setITagIsid(2L)
+                .setSourceAddress(new MacAddress("aa:aa:aa:aa:aa:aa"))
+                .setDestinationAddress(new MacAddress("bb:bb:bb:bb:bb:bb"))
+                .setInterfaceOperation(Operation.Pop2)
+                .build();
+    }
+
+    private PbbRewrite validData() {
+        return new PbbRewriteBuilder()
+                .setBVlanTagVlanId(1)
+                .setITagIsid(2L)
+                .setSourceAddress(new MacAddress("aa:aa:aa:aa:aa:aa"))
+                .setDestinationAddress(new MacAddress("bb:bb:bb:bb:bb:bb"))
+                .setInterfaceOperation(Operation.Pop2)
+                .build();
+    }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfacesstate/pbb/PbbRewriteStateCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfacesstate/pbb/PbbRewriteStateCustomizerTest.java
new file mode 100644 (file)
index 0000000..a5c9680
--- /dev/null
@@ -0,0 +1,19 @@
+package io.fd.honeycomb.translate.v3po.interfacesstate.pbb;
+
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.honeycomb.vpp.test.read.ReaderCustomizerTest;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.pbb.rev160410.PbbRewriteStateInterfaceAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.pbb.rev160410.interfaces.state._interface.PbbRewriteState;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.pbb.rev160410.interfaces.state._interface.PbbRewriteStateBuilder;
+
+public class PbbRewriteStateCustomizerTest extends ReaderCustomizerTest<PbbRewriteState, PbbRewriteStateBuilder> {
+
+    public PbbRewriteStateCustomizerTest() {
+        super(PbbRewriteState.class, PbbRewriteStateInterfaceAugmentationBuilder.class);
+    }
+
+    @Override
+    protected ReaderCustomizer<PbbRewriteState, PbbRewriteStateBuilder> initCustomizer() {
+        return new PbbRewriteStateCustomizer(api);
+    }
+}