BUG-6257: Implement PMSI tunnel attribute handler 87/46687/1
authorClaudio D. Gasparini <cgaspari@cisco.com>
Wed, 28 Sep 2016 09:24:25 +0000 (11:24 +0200)
committerMilos Fabian <milfabia@cisco.com>
Fri, 7 Oct 2016 18:21:46 +0000 (18:21 +0000)
-Fix pmsi tunnel attibute yang model
-Implement PMSI tunnel attribute handler
-Implement test

Change-Id: Iffc1750724c3e97d1694fba8360007741ad08d80
Signed-off-by: Claudio D. Gasparini <cgaspari@cisco.com>
(cherry picked from commit 7cfbcfb35072f4b1e3ae3b02f09f7791c72f1527)

22 files changed:
bgp/evpn/pom.xml
bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/BGPActivator.java
bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/PMSITunnelAttributeHandler.java [new file with mode: 0644]
bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/BidirPimTreeParser.java [new file with mode: 0644]
bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/IngressReplicationParser.java [new file with mode: 0644]
bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/MldpMp2mpLspParser.java [new file with mode: 0644]
bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/MldpP2mpLspParser.java [new file with mode: 0644]
bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/OpaqueUtil.java [new file with mode: 0644]
bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/PAddressPMulticastGroupUtil.java [new file with mode: 0644]
bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/PimSmTreeParser.java [new file with mode: 0644]
bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/PimSsmTreeParser.java [new file with mode: 0644]
bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/RsvpTeP2MpLspParser.java [new file with mode: 0644]
bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/TunnelIdentifierHandler.java [new file with mode: 0644]
bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/TunnelIdentifierParser.java [new file with mode: 0644]
bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/TunnelIdentifierSerializer.java [new file with mode: 0644]
bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/TunnelType.java [new file with mode: 0644]
bgp/evpn/src/main/yang/bgp-evpn.yang
bgp/evpn/src/main/yang/pmsi-tunnel.yang
bgp/evpn/src/test/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/OpaqueUtilTest.java [new file with mode: 0644]
bgp/evpn/src/test/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/PAddressPMulticastGroupUtilTest.java [new file with mode: 0644]
bgp/evpn/src/test/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/PMSITunnelAttributeHandlerTest.java [new file with mode: 0644]
bgp/evpn/src/test/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/PMSITunnelAttributeHandlerTestUtil.java [new file with mode: 0644]

index 6650838b59b4fc6843fb1ea1a661b717cfb94953..1b9a26003a959ab28b7e3f0db4b085ddb305ad33 100644 (file)
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>yang-data-impl</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.mdsal.model</groupId>
+            <artifactId>yang-ext</artifactId>
+        </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>bgp-concepts</artifactId>
             <artifactId>sal-binding-broker-impl</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>bgp-parser-impl</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
     <build>
         <plugins>
index a802751e70f3e1a7951cc4ed0ff48dadbff724a5..c3480b9bfbaa5b9dcc172e682cecbcb2fc147714 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.protocol.bgp.evpn.impl;
 
 import java.util.ArrayList;
 import java.util.List;
+import org.opendaylight.protocol.bgp.evpn.impl.attributes.PMSITunnelAttributeHandler;
 import org.opendaylight.protocol.bgp.evpn.impl.esi.types.ESIActivator;
 import org.opendaylight.protocol.bgp.evpn.impl.extended.communities.DefaultGatewayExtCom;
 import org.opendaylight.protocol.bgp.evpn.impl.extended.communities.ESILabelExtCom;
@@ -47,9 +48,17 @@ public final class BGPActivator extends AbstractBGPExtensionProviderActivator {
         NlriActivator.registerNlriParsers(regs);
         registerExtendedCommunities(context, regs);
         ESIActivator.registerEsiTypeParsers(regs);
+
+        registerAttributesHandler(context, regs);
         return regs;
     }
 
+    private void registerAttributesHandler(final BGPExtensionProviderContext context, final List<AutoCloseable> regs) {
+        final PMSITunnelAttributeHandler pmsiParser = new PMSITunnelAttributeHandler(context.getAddressFamilyRegistry());
+        regs.add(context.registerAttributeParser(pmsiParser.getType(), pmsiParser));
+        regs.add(context.registerAttributeSerializer(pmsiParser.getClazz(), pmsiParser));
+    }
+
     private void registerNlriHandler(final BGPExtensionProviderContext context, final List<AutoCloseable> regs) {
         final NextHopParserSerializer nextHopParser = new NextHopParserSerializer() {};
         final EvpnNlriParser nlriHandler = new EvpnNlriParser();
diff --git a/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/PMSITunnelAttributeHandler.java b/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/PMSITunnelAttributeHandler.java
new file mode 100644 (file)
index 0000000..90b6995
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.evpn.impl.attributes;
+
+import com.google.common.base.Preconditions;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import javax.annotation.Nonnull;
+import org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.TunnelIdentifierHandler;
+import org.opendaylight.protocol.bgp.parser.spi.AddressFamilyRegistry;
+import org.opendaylight.protocol.bgp.parser.spi.AttributeParser;
+import org.opendaylight.protocol.bgp.parser.spi.AttributeSerializer;
+import org.opendaylight.protocol.bgp.parser.spi.AttributeUtil;
+import org.opendaylight.protocol.util.MplsLabelUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.evpn.routes.evpn.routes.evpn.route.PmsiTunnelAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.evpn.routes.evpn.routes.evpn.route.PmsiTunnelAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.Attributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.AttributesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.MplsLabel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.PmsiTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.PmsiTunnelBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.TunnelIdentifier;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+
+public final class PMSITunnelAttributeHandler implements AttributeParser, AttributeSerializer {
+    private static final int PMSI_ATTRIBUTE = 22;
+    private static final int MPLS_LENGTH = 3;
+    private final TunnelIdentifierHandler tunnelIdentifierHandler;
+
+    public PMSITunnelAttributeHandler(final AddressFamilyRegistry addressFamilyRegistry) {
+        this.tunnelIdentifierHandler = new TunnelIdentifierHandler(addressFamilyRegistry);
+    }
+
+    @Override
+    public void parseAttribute(@Nonnull final ByteBuf buffer, @Nonnull final AttributesBuilder builder) {
+        if (!buffer.isReadable()) {
+            return;
+        }
+        final PmsiTunnelBuilder pmsiTunnelBuilder = new PmsiTunnelBuilder();
+        pmsiTunnelBuilder.setLeafInformationRequired(buffer.readBoolean());
+        final int tunnelType = buffer.readUnsignedByte();
+        parseMpls(pmsiTunnelBuilder, buffer);
+        final TunnelIdentifier tunnelIdentifier = this.tunnelIdentifierHandler.parse(tunnelType, buffer);
+        if (tunnelIdentifier != null) {
+            pmsiTunnelBuilder.setTunnelIdentifier(tunnelIdentifier);
+        }
+        builder.addAugmentation(PmsiTunnelAugmentation.class, new PmsiTunnelAugmentationBuilder().setPmsiTunnel(pmsiTunnelBuilder.build()).build());
+    }
+
+    private void parseMpls(final PmsiTunnelBuilder pmsiTunnelBuilder, final ByteBuf buffer) {
+        final MplsLabel mpls = MplsLabelUtil.mplsLabelForByteBuf(buffer);
+        if(mpls.getValue() != 0) {
+            pmsiTunnelBuilder.setMplsLabel(mpls);
+        }
+    }
+
+    public int getType() {
+        return PMSI_ATTRIBUTE;
+    }
+
+    @Override
+    public void serializeAttribute(final DataObject attribute, final ByteBuf byteAggregator) {
+        Preconditions.checkArgument(attribute instanceof Attributes, "Attribute parameter is not a PathAttribute object.");
+        final PmsiTunnelAugmentation pmsiTunnelAugmentation = ((Attributes) attribute).getAugmentation(PmsiTunnelAugmentation.class);
+        if (pmsiTunnelAugmentation == null) {
+            return;
+        }
+
+        final PmsiTunnel pmsiTunnelAttribute = pmsiTunnelAugmentation.getPmsiTunnel();
+        final TunnelIdentifier tunnel = pmsiTunnelAttribute.getTunnelIdentifier();
+        final ByteBuf tunnelBuffer = Unpooled.buffer();
+        final int tunnelType = this.tunnelIdentifierHandler.serialize(tunnel, tunnelBuffer);
+        final ByteBuf body = Unpooled.buffer();
+        serializeFlag(pmsiTunnelAttribute, body);
+        body.writeByte(tunnelType);
+        serializeMpls(pmsiTunnelAttribute.getMplsLabel(), body);
+        body.writeBytes(tunnelBuffer);
+        AttributeUtil.formatAttribute(AttributeUtil.OPTIONAL, getType(), body, byteAggregator);
+    }
+
+    private void serializeMpls(final MplsLabel mplsLabel, final ByteBuf body) {
+        if(mplsLabel == null) {
+            body.writeZero(MPLS_LENGTH);
+        }
+        body.writeBytes(MplsLabelUtil.byteBufForMplsLabel(mplsLabel));
+    }
+
+    private void serializeFlag(final PmsiTunnel pmsiTunnelAttribute, final ByteBuf body) {
+        body.writeBoolean(pmsiTunnelAttribute.isLeafInformationRequired());
+    }
+
+    public Class<? extends DataObject> getClazz() {
+        return org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.PmsiTunnel.class;
+    }
+}
diff --git a/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/BidirPimTreeParser.java b/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/BidirPimTreeParser.java
new file mode 100644 (file)
index 0000000..b005379
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier;
+
+import com.google.common.base.Preconditions;
+import io.netty.buffer.ByteBuf;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.TunnelIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.BidirPimTree;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.BidirPimTreeBuilder;
+
+final class BidirPimTreeParser implements TunnelIdentifierSerializer, TunnelIdentifierParser {
+    @Override
+    public int serialize(final TunnelIdentifier tunnelIdentifier, final ByteBuf buffer) {
+        Preconditions.checkArgument(tunnelIdentifier instanceof BidirPimTree, "The tunnelIdentifier %s is not BidirPimTree type.", tunnelIdentifier);
+        PAddressPMulticastGroupUtil.serializeSenderPMulticastGroup(((BidirPimTree) tunnelIdentifier).getBidirPimTree(), buffer);
+        return TunnelType.BIDIR_PIM_TREE.getIntValue();
+    }
+
+    @Override
+    public TunnelIdentifier parse(final ByteBuf buffer) {
+        final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.bidir.pim.tree.
+            BidirPimTreeBuilder bidirPimTree = new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.bidir.pim.tree.
+            BidirPimTreeBuilder(PAddressPMulticastGroupUtil.parseSenderPMulticastGroup(buffer));
+        return new BidirPimTreeBuilder().setBidirPimTree(bidirPimTree.build()).build();
+    }
+}
diff --git a/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/IngressReplicationParser.java b/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/IngressReplicationParser.java
new file mode 100644 (file)
index 0000000..20bfd30
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier;
+
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.PAddressPMulticastGroupUtil.parseIpAddress;
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.PAddressPMulticastGroupUtil.serializeIpAddress;
+
+import com.google.common.base.Preconditions;
+import io.netty.buffer.ByteBuf;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.TunnelIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.IngressReplication;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.IngressReplicationBuilder;
+
+final class IngressReplicationParser implements TunnelIdentifierSerializer, TunnelIdentifierParser {
+    @Override
+    public int serialize(final TunnelIdentifier tunnelIdentifier, final ByteBuf buffer) {
+        Preconditions.checkArgument(tunnelIdentifier instanceof IngressReplication, "The tunnelIdentifier %s is not IngressReplication type.", tunnelIdentifier);
+        final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.ingress.replication.
+            IngressReplication ingressReplication = ((IngressReplication) tunnelIdentifier).getIngressReplication();
+        serializeIpAddress(ingressReplication.getReceivingEndpointAddress(), buffer);
+        return TunnelType.INGRESS_REPLICATION.getIntValue();
+    }
+
+    @Override
+    public TunnelIdentifier parse(final ByteBuf buffer) {
+        final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier
+            .ingress.replication.IngressReplication builder = new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi
+            .tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.ingress.replication.IngressReplicationBuilder()
+            .setReceivingEndpointAddress(parseIpAddress(buffer.readableBytes(), buffer)).build();
+        return new IngressReplicationBuilder().setIngressReplication(builder).build();
+    }
+}
diff --git a/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/MldpMp2mpLspParser.java b/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/MldpMp2mpLspParser.java
new file mode 100644 (file)
index 0000000..bd4d31d
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier;
+
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.TunnelIdentifierHandler.NO_TUNNEL_INFORMATION_PRESENT;
+
+import com.google.common.base.Preconditions;
+import io.netty.buffer.ByteBuf;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.Opaque;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.TunnelIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.MldpMp2mpLsp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.MldpMp2mpLspBuilder;
+
+final class MldpMp2mpLspParser implements TunnelIdentifierSerializer, TunnelIdentifierParser {
+    @Override
+    public int serialize(final TunnelIdentifier tunnelIdentifier, final ByteBuf buffer) {
+        Preconditions.checkArgument(tunnelIdentifier instanceof MldpMp2mpLsp, "The tunnelIdentifier %s is not MldpMp2mpLsp type.", tunnelIdentifier);
+        final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.mldp.mp2mp.lsp.
+            MldpMp2mpLsp mldpMp2mpLsp = ((MldpMp2mpLsp) tunnelIdentifier).getMldpMp2mpLsp();
+        if (!OpaqueUtil.serializeOpaque(mldpMp2mpLsp, buffer)) {
+            return NO_TUNNEL_INFORMATION_PRESENT;
+        }
+        return TunnelType.M_LDP_MP_2_MP_LSP.getIntValue();
+    }
+
+    @Override
+    public TunnelIdentifier parse(final ByteBuf buffer) {
+        final Opaque opaque = OpaqueUtil.parseOpaque(buffer);
+        if (opaque == null) {
+            return null;
+        }
+        final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.mldp.mp2mp.lsp.
+            MldpMp2mpLsp mldpMp2mpLsp = new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.mldp.mp2mp.lsp.
+            MldpMp2mpLspBuilder(opaque).build();
+        return new MldpMp2mpLspBuilder().setMldpMp2mpLsp(mldpMp2mpLsp).build();
+    }
+}
diff --git a/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/MldpP2mpLspParser.java b/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/MldpP2mpLspParser.java
new file mode 100644 (file)
index 0000000..cc30e4e
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier;
+
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.OpaqueUtil.serializeOpaqueList;
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.PAddressPMulticastGroupUtil.parseIpAddress;
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.PAddressPMulticastGroupUtil.serializeIpAddress;
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.TunnelIdentifierHandler.NO_TUNNEL_INFORMATION_PRESENT;
+
+import com.google.common.base.Preconditions;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufUtil;
+import io.netty.buffer.Unpooled;
+import org.opendaylight.protocol.bgp.parser.spi.AddressFamilyRegistry;
+import org.opendaylight.protocol.util.ByteBufWriteUtil;
+import org.opendaylight.protocol.util.Ipv4Util;
+import org.opendaylight.protocol.util.Ipv6Util;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.TunnelIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.MldpP2mpLsp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.MldpP2mpLspBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+final class MldpP2mpLspParser implements TunnelIdentifierSerializer, TunnelIdentifierParser {
+    private static final Logger LOG = LoggerFactory.getLogger(MldpP2mpLspParser.class);
+    private static final short P2MP_TYPE = 6;
+    private static final int RESERVED = 1;
+    private final AddressFamilyRegistry addressFamilyRegistry;
+
+    MldpP2mpLspParser(final AddressFamilyRegistry addressFamilyRegistry) {
+        this.addressFamilyRegistry = addressFamilyRegistry;
+    }
+
+    @Override
+    public int serialize(final TunnelIdentifier tunnelIdentifier, final ByteBuf buffer) {
+        Preconditions.checkArgument(tunnelIdentifier instanceof MldpP2mpLsp, "The tunnelIdentifier %s is not RsvpTeP2mpLps type.", tunnelIdentifier);
+        final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.mldp
+            .p2mp.lsp.MldpP2mpLsp mldpP2mpLsp = ((MldpP2mpLsp) tunnelIdentifier).getMldpP2mpLsp();
+
+        final ByteBuf opaqueValues = Unpooled.buffer();
+        final int addressFamily = getAddressFamilyValue(mldpP2mpLsp.getAddressFamily());
+
+        if (!serializeOpaqueList(mldpP2mpLsp.getOpaqueValue(), opaqueValues) || addressFamily == 0) {
+            return NO_TUNNEL_INFORMATION_PRESENT;
+        }
+        final IpAddress rootNode = mldpP2mpLsp.getRootNodeAddress();
+        ByteBufWriteUtil.writeUnsignedByte(P2MP_TYPE, buffer);
+        ByteBufWriteUtil.writeUnsignedShort(addressFamily, buffer);
+        ByteBufWriteUtil.writeUnsignedByte(getAdressFamilyLength(rootNode), buffer);
+        serializeIpAddress(rootNode, buffer);
+
+        ByteBufWriteUtil.writeUnsignedShort(opaqueValues.readableBytes(), buffer);
+        buffer.writeBytes(opaqueValues);
+        return TunnelType.MLDP_P2MP_LSP.getIntValue();
+    }
+
+    private static short getAdressFamilyLength(final IpAddress ipAddress) {
+        if (ipAddress.getIpv4Address() == null) {
+            return Ipv6Util.IPV6_LENGTH;
+        }
+        return Ipv4Util.IP4_LENGTH;
+    }
+
+    private int getAddressFamilyValue(final Class<? extends AddressFamily> addressFamily) {
+        final Integer type = this.addressFamilyRegistry.numberForClass(addressFamily);
+        if (type == null) {
+            return 0;
+        }
+        return type;
+    }
+
+    @Override
+    public TunnelIdentifier parse(final ByteBuf buffer) {
+        final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.mldp
+            .p2mp.lsp.MldpP2mpLspBuilder mldpP2mpLsp = new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.mldp
+            .p2mp.lsp.MldpP2mpLspBuilder();
+        buffer.skipBytes(RESERVED);
+        final Class<? extends AddressFamily> addressFamily = this.addressFamilyRegistry.classForFamily(buffer.readUnsignedShort());
+        if (addressFamily == null) {
+            LOG.debug("Skipping serialization of TunnelIdentifier {}, address family type  supported", ByteBufUtil.hexDump(buffer));
+            return null;
+        }
+        mldpP2mpLsp.setAddressFamily(addressFamily);
+        final short rootNodeLength = buffer.readUnsignedByte();
+        mldpP2mpLsp.setRootNodeAddress(parseIpAddress(rootNodeLength, buffer.readBytes(rootNodeLength)));
+        final int opaqueValueLength = buffer.readUnsignedShort();
+        mldpP2mpLsp.setOpaqueValue(OpaqueUtil.parseOpaqueList(buffer.readBytes(opaqueValueLength)));
+        return new MldpP2mpLspBuilder().setMldpP2mpLsp(mldpP2mpLsp.build()).build();
+    }
+}
diff --git a/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/OpaqueUtil.java b/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/OpaqueUtil.java
new file mode 100644 (file)
index 0000000..d5909b6
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Splitter;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufUtil;
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.DatatypeConverter;
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.util.ByteBufWriteUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.HexString;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.Opaque;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.mldp.p2mp.lsp.mldp.p2mp.lsp.OpaqueValue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.mldp.p2mp.lsp.mldp.p2mp.lsp.OpaqueValueBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+final class OpaqueUtil {
+    static final short GENERIC_LSP_IDENTIFIER = 1;
+    static final short EXTENDED_TYPE = 255;
+    private static final Logger LOG = LoggerFactory.getLogger(OpaqueUtil.class);
+    private static final String SEPARATOR = ":";
+    private static final String EMPTY_SEPARATOR = "";
+
+    private OpaqueUtil() {
+        throw new UnsupportedOperationException();
+    }
+
+    static boolean serializeOpaque(final Opaque opaque, final ByteBuf byteBuf) {
+        final Short type = opaque.getOpaqueType();
+        switch (type) {
+        case GENERIC_LSP_IDENTIFIER:
+            ByteBufWriteUtil.writeUnsignedByte(type, byteBuf);
+            writeGeneric(opaque.getOpaque(), byteBuf);
+            break;
+        case EXTENDED_TYPE:
+            ByteBufWriteUtil.writeUnsignedByte(type, byteBuf);
+            writeExtended(opaque.getOpaque(), opaque.getOpaqueExtendedType(), byteBuf);
+            break;
+        default:
+            LOG.debug("Skipping serialization of Opaque Value {}", opaque);
+            return false;
+        }
+        return true;
+    }
+
+    private static void writeExtended(final HexString opaque, final Integer opaqueExtendedType, final ByteBuf byteBuf) {
+        final byte[] output = writeOpaqueValue(opaque.getValue());
+        ByteBufWriteUtil.writeUnsignedShort(opaqueExtendedType, byteBuf);
+        ByteBufWriteUtil.writeUnsignedShort(output.length, byteBuf);
+        byteBuf.writeBytes(output);
+    }
+
+    private static void writeGeneric(final HexString opaque, final ByteBuf byteBuf) {
+        final byte[] output = writeOpaqueValue(opaque.getValue());
+        ByteBufWriteUtil.writeUnsignedShort(output.length, byteBuf);
+        byteBuf.writeBytes(output);
+    }
+
+    private static byte[] writeOpaqueValue(final String opaque) {
+        final String joined = opaque.replace(SEPARATOR, EMPTY_SEPARATOR);
+        return DatatypeConverter.parseHexBinary(joined);
+    }
+
+    static Opaque parseOpaque(final ByteBuf buffer) {
+        final short type = buffer.readUnsignedByte();
+        final OpaqueValueBuilder builder = new OpaqueValueBuilder();
+        switch (type) {
+        case GENERIC_LSP_IDENTIFIER:
+            builder.setOpaque(buildOpaqueValue(buffer));
+            break;
+        case EXTENDED_TYPE:
+            buildExtended(builder, buffer);
+            break;
+        default:
+            final int length = buffer.readUnsignedShort();
+            buffer.skipBytes(length);
+            LOG.debug("Skipping parsing of Opaque Value {}", buffer);
+            return null;
+        }
+        builder.setOpaqueType(type);
+        return builder.build();
+    }
+
+    private static void buildExtended(final OpaqueValueBuilder builder, final ByteBuf buffer) {
+        final int extendedType = buffer.readUnsignedShort();
+        final HexString opaqueValue = buildOpaqueValue(buffer);
+        builder.setOpaqueExtendedType(extendedType).setOpaque(opaqueValue);
+    }
+
+    private static HexString buildOpaqueValue(final ByteBuf buffer) {
+        final int length = buffer.readUnsignedShort();
+        final byte[] value = ByteArray.readBytes(buffer, length);
+        final String hexDump = ByteBufUtil.hexDump(value);
+        final Iterable<String> splitted = Splitter.fixedLength(2).split(hexDump);
+        return new HexString(Joiner.on(SEPARATOR).join(splitted));
+    }
+
+    static List<OpaqueValue> parseOpaqueList(final ByteBuf byteBuf) {
+        final List<OpaqueValue> opaqueValues = new ArrayList<>();
+        while (byteBuf.isReadable()) {
+            final Opaque opaque = parseOpaque(byteBuf);
+            if (opaque != null) {
+                opaqueValues.add((OpaqueValue) opaque);
+            }
+        }
+        return opaqueValues;
+    }
+
+    static boolean serializeOpaqueList(final List<OpaqueValue> mldpP2mpLsp, final ByteBuf buffer) {
+        boolean parsed = false;
+        for (final OpaqueValue opaque : mldpP2mpLsp) {
+            if (serializeOpaque(opaque, buffer)) {
+                parsed = true;
+            }
+        }
+        return parsed;
+    }
+}
diff --git a/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/PAddressPMulticastGroupUtil.java b/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/PAddressPMulticastGroupUtil.java
new file mode 100644 (file)
index 0000000..5d64264
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier;
+
+import io.netty.buffer.ByteBuf;
+import org.opendaylight.protocol.util.Ipv4Util;
+import org.opendaylight.protocol.util.Ipv6Util;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.PAddressPMulticastGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.bidir.pim.tree.BidirPimTreeBuilder;
+
+final class PAddressPMulticastGroupUtil {
+    private PAddressPMulticastGroupUtil() {
+        throw new UnsupportedOperationException();
+    }
+
+    static void serializeIpAddress(final IpAddress ipAddress, final ByteBuf byteBuf) {
+        if (ipAddress.getIpv4Address() != null) {
+            byteBuf.writeBytes(Ipv4Util.bytesForAddress(ipAddress.getIpv4Address()));
+        } else {
+            byteBuf.writeBytes(Ipv6Util.bytesForAddress(ipAddress.getIpv6Address()));
+        }
+    }
+
+    static IpAddress parseIpAddress(final int ipLength, final ByteBuf buffer) {
+        if (ipLength == Ipv6Util.IPV6_LENGTH) {
+            return new IpAddress(Ipv6Util.addressForByteBuf(buffer));
+        } else if (ipLength == Ipv4Util.IP4_LENGTH) {
+            return new IpAddress(Ipv4Util.addressForByteBuf(buffer));
+        }
+        return null;
+    }
+
+    static void serializeSenderPMulticastGroup(final PAddressPMulticastGroup bidir, final ByteBuf byteBuf) {
+        serializeIpAddress(bidir.getPAddress(), byteBuf);
+        serializeIpAddress(bidir.getPMulticastGroup(), byteBuf);
+    }
+
+    static PAddressPMulticastGroup parseSenderPMulticastGroup(final ByteBuf buffer) {
+        final int ipLength = buffer.readableBytes() / 2;
+        final IpAddress pSenderAddress = parseIpAddress(ipLength, buffer);
+        final IpAddress pMulticastGroup = parseIpAddress(ipLength, buffer);
+        return new BidirPimTreeBuilder().setPAddress(pSenderAddress).setPMulticastGroup(pMulticastGroup).build();
+    }
+
+}
diff --git a/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/PimSmTreeParser.java b/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/PimSmTreeParser.java
new file mode 100644 (file)
index 0000000..c237afe
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier;
+
+
+import com.google.common.base.Preconditions;
+import io.netty.buffer.ByteBuf;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.TunnelIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.PimSmTree;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.PimSmTreeBuilder;
+
+final class PimSmTreeParser implements TunnelIdentifierSerializer, TunnelIdentifierParser {
+    @Override
+    public int serialize(final TunnelIdentifier tunnelIdentifier, final ByteBuf buffer) {
+        Preconditions.checkArgument(tunnelIdentifier instanceof PimSmTree, "The tunnelIdentifier %s is not PimSmTree type.", tunnelIdentifier);
+        PAddressPMulticastGroupUtil.serializeSenderPMulticastGroup(((PimSmTree) tunnelIdentifier).getPimSmTree(), buffer);
+        return TunnelType.PIM_SM_TREE.getIntValue();
+    }
+
+    @Override
+    public TunnelIdentifier parse(final ByteBuf buffer) {
+        final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.pim.sm.tree.
+            PimSmTreeBuilder pimSmTree = new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.pim.sm.tree.
+            PimSmTreeBuilder(PAddressPMulticastGroupUtil.parseSenderPMulticastGroup(buffer));
+        return new PimSmTreeBuilder().setPimSmTree(pimSmTree.build()).build();
+    }
+}
diff --git a/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/PimSsmTreeParser.java b/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/PimSsmTreeParser.java
new file mode 100644 (file)
index 0000000..43d9a54
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier;
+
+import com.google.common.base.Preconditions;
+import io.netty.buffer.ByteBuf;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.TunnelIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.PimSsmTree;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.PimSsmTreeBuilder;
+
+final class PimSsmTreeParser implements TunnelIdentifierSerializer, TunnelIdentifierParser {
+    @Override
+    public int serialize(final TunnelIdentifier tunnelIdentifier, final ByteBuf buffer) {
+        Preconditions.checkArgument(tunnelIdentifier instanceof PimSsmTree, "The tunnelIdentifier %s is not PimSsmTree type.", tunnelIdentifier);
+        PAddressPMulticastGroupUtil.serializeSenderPMulticastGroup(((PimSsmTree) tunnelIdentifier).getPimSsmTree(), buffer);
+        return TunnelType.PIM_SSM_TREE.getIntValue();
+    }
+
+    @Override
+    public TunnelIdentifier parse(final ByteBuf buffer) {
+        final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.pim.ssm.tree.
+            PimSsmTreeBuilder pimSsmTree = new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.pim.ssm.tree.
+            PimSsmTreeBuilder(PAddressPMulticastGroupUtil.parseSenderPMulticastGroup(buffer));
+        return new PimSsmTreeBuilder().setPimSsmTree(pimSsmTree.build()).build();
+    }
+}
diff --git a/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/RsvpTeP2MpLspParser.java b/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/RsvpTeP2MpLspParser.java
new file mode 100644 (file)
index 0000000..c39fce5
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier;
+
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.PAddressPMulticastGroupUtil.parseIpAddress;
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.PAddressPMulticastGroupUtil.serializeIpAddress;
+
+import com.google.common.base.Preconditions;
+import io.netty.buffer.ByteBuf;
+import org.opendaylight.protocol.util.ByteBufWriteUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.TunnelIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.RsvpTeP2mpLsp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.RsvpTeP2mpLspBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.rsvp.te.p2mp.lsp.RsvpTeP2mpLps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.rsvp.te.p2mp.lsp.RsvpTeP2mpLpsBuilder;
+
+final class RsvpTeP2MpLspParser implements TunnelIdentifierSerializer, TunnelIdentifierParser {
+
+    private static final int RESERVED = 2;
+
+    @Override
+    public int serialize(final TunnelIdentifier tunnelIdentifier, final ByteBuf buffer) {
+        Preconditions.checkArgument(tunnelIdentifier instanceof RsvpTeP2mpLsp, "The tunnelIdentifier %s is not RsvpTeP2mpLps type.", tunnelIdentifier);
+        final RsvpTeP2mpLps rsvpTeP2mpLsp = ((RsvpTeP2mpLsp) tunnelIdentifier).getRsvpTeP2mpLps();
+        ByteBufWriteUtil.writeUnsignedInt(rsvpTeP2mpLsp.getP2mpId(), buffer);
+        buffer.writeZero(RESERVED);
+        ByteBufWriteUtil.writeUnsignedShort(rsvpTeP2mpLsp.getTunnelId(), buffer);
+        serializeIpAddress(rsvpTeP2mpLsp.getExtendedTunnelId(), buffer);
+        return TunnelType.RSVP_TE_P2MP_LSP.getIntValue();
+    }
+
+    @Override
+    public TunnelIdentifier parse(final ByteBuf buffer) {
+        final RsvpTeP2mpLpsBuilder rsvpTeP2mpLps = new RsvpTeP2mpLpsBuilder();
+        rsvpTeP2mpLps.setP2mpId(buffer.readUnsignedInt());
+        buffer.skipBytes(2);
+        rsvpTeP2mpLps.setTunnelId(buffer.readUnsignedShort());
+        final int ipLength = buffer.readableBytes();
+        rsvpTeP2mpLps.setExtendedTunnelId(parseIpAddress(ipLength, buffer));
+        return new RsvpTeP2mpLspBuilder().setRsvpTeP2mpLps(rsvpTeP2mpLps.build()).build();
+    }
+}
diff --git a/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/TunnelIdentifierHandler.java b/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/TunnelIdentifierHandler.java
new file mode 100644 (file)
index 0000000..d6c34c8
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier;
+
+import io.netty.buffer.ByteBuf;
+import org.opendaylight.protocol.bgp.parser.spi.AddressFamilyRegistry;
+import org.opendaylight.protocol.concepts.HandlerRegistry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.TunnelIdentifier;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class TunnelIdentifierHandler {
+    static final int NO_TUNNEL_INFORMATION_PRESENT = 0;
+    private static final Logger LOG = LoggerFactory.getLogger(TunnelIdentifierHandler.class);
+    private static final String SKIP_SERIALIZATION = "Skipping serialization of PMSI Tunnel Attribute {}";
+    private static final String SKIP_PARSE = "Skipping parsing of PMSI Tunnel Attribute type {}";
+    private final HandlerRegistry<DataContainer, TunnelIdentifierParser, TunnelIdentifierSerializer> handlers = new HandlerRegistry<>();
+
+    public TunnelIdentifierHandler(final AddressFamilyRegistry addressFamilyRegistry) {
+        final RsvpTeP2MpLspParser rsvpTeP2MpLspParser = new RsvpTeP2MpLspParser();
+        this.handlers.registerParser(TunnelType.RSVP_TE_P2MP_LSP.getIntValue(), rsvpTeP2MpLspParser);
+        this.handlers.registerSerializer(TunnelType.RSVP_TE_P2MP_LSP.getClazz(), rsvpTeP2MpLspParser);
+
+        final MldpP2mpLspParser mldpP2mpLspParser = new MldpP2mpLspParser(addressFamilyRegistry);
+        this.handlers.registerParser(TunnelType.MLDP_P2MP_LSP.getIntValue(), mldpP2mpLspParser);
+        this.handlers.registerSerializer(TunnelType.MLDP_P2MP_LSP.getClazz(), mldpP2mpLspParser);
+
+        final PimSsmTreeParser pimSsmTreeParser = new PimSsmTreeParser();
+        this.handlers.registerParser(TunnelType.PIM_SSM_TREE.getIntValue(), pimSsmTreeParser);
+        this.handlers.registerSerializer(TunnelType.PIM_SSM_TREE.getClazz(), pimSsmTreeParser);
+
+        final PimSmTreeParser pimSmTreeParser = new PimSmTreeParser();
+        this.handlers.registerParser(TunnelType.PIM_SM_TREE.getIntValue(), pimSmTreeParser);
+        this.handlers.registerSerializer(TunnelType.PIM_SM_TREE.getClazz(), pimSmTreeParser);
+
+        final BidirPimTreeParser bidirPimTreeParser = new BidirPimTreeParser();
+        this.handlers.registerParser(TunnelType.BIDIR_PIM_TREE.getIntValue(), bidirPimTreeParser);
+        this.handlers.registerSerializer(TunnelType.BIDIR_PIM_TREE.getClazz(), bidirPimTreeParser);
+
+        final IngressReplicationParser ingressReplicationParser = new IngressReplicationParser();
+        this.handlers.registerParser(TunnelType.INGRESS_REPLICATION.getIntValue(), ingressReplicationParser);
+        this.handlers.registerSerializer(TunnelType.INGRESS_REPLICATION.getClazz(), ingressReplicationParser);
+
+        final MldpMp2mpLspParser mldpMp2mpLspParser = new MldpMp2mpLspParser();
+        this.handlers.registerParser(TunnelType.M_LDP_MP_2_MP_LSP.getIntValue(), mldpMp2mpLspParser);
+        this.handlers.registerSerializer(TunnelType.M_LDP_MP_2_MP_LSP.getClazz(), mldpMp2mpLspParser);
+    }
+
+    public TunnelIdentifier parse(final int tunnelType, final ByteBuf buffer) {
+        final TunnelIdentifierParser parser = this.handlers.getParser(tunnelType);
+        if (!buffer.isReadable() || parser == null) {
+            LOG.debug(SKIP_PARSE, tunnelType);
+            return null;
+        }
+        return parser.parse(buffer);
+    }
+
+    public int serialize(final TunnelIdentifier tunnel, final ByteBuf tunnelBuffer) {
+        if (tunnel == null) {
+            LOG.debug(SKIP_SERIALIZATION);
+            return NO_TUNNEL_INFORMATION_PRESENT;
+        }
+        final TunnelIdentifierSerializer serializer = this.handlers.getSerializer(tunnel.getImplementedInterface());
+        if (serializer == null) {
+            LOG.debug(SKIP_SERIALIZATION, tunnel);
+            return NO_TUNNEL_INFORMATION_PRESENT;
+        }
+        return serializer.serialize(tunnel, tunnelBuffer);
+    }
+}
diff --git a/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/TunnelIdentifierParser.java b/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/TunnelIdentifierParser.java
new file mode 100644 (file)
index 0000000..dc67b56
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier;
+
+import io.netty.buffer.ByteBuf;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.TunnelIdentifier;
+
+interface TunnelIdentifierParser {
+    /**
+     * Parse Tunnel Identifier from buffer.
+     * @param buffer Encoded Tunnel Identifier in ByteBuf.
+     * @return Parsed Tunnel Identifier body
+     */
+    TunnelIdentifier parse(ByteBuf buffer);
+}
diff --git a/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/TunnelIdentifierSerializer.java b/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/TunnelIdentifierSerializer.java
new file mode 100644 (file)
index 0000000..8a83505
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier;
+
+import io.netty.buffer.ByteBuf;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.TunnelIdentifier;
+
+interface TunnelIdentifierSerializer {
+    /**
+     * Serialize tunnel identifier
+     * @param tunnelIdentifier Tunnel Identifier body
+     * @param buffer Encoded Tunnel Identifier in ByteBuf
+     * @return Tunnel identifier Type
+     */
+    int serialize(TunnelIdentifier tunnelIdentifier, ByteBuf buffer);
+}
diff --git a/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/TunnelType.java b/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/TunnelType.java
new file mode 100644 (file)
index 0000000..ee6c62f
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.TunnelIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.BidirPimTree;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.IngressReplication;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.MldpMp2mpLsp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.MldpP2mpLsp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.PimSmTree;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.PimSsmTree;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.RsvpTeP2mpLsp;
+
+
+enum TunnelType {
+    RSVP_TE_P2MP_LSP(1, RsvpTeP2mpLsp.class),
+    MLDP_P2MP_LSP(2, MldpP2mpLsp.class),
+    PIM_SSM_TREE(3, PimSsmTree.class),
+    PIM_SM_TREE(4, PimSmTree.class),
+    BIDIR_PIM_TREE(5, BidirPimTree.class),
+    INGRESS_REPLICATION(6, IngressReplication.class),
+    M_LDP_MP_2_MP_LSP(7, MldpMp2mpLsp.class);
+
+    final Class<? extends TunnelIdentifier> clazz;
+    final int value;
+
+    TunnelType(final int value, final Class<? extends TunnelIdentifier> clazz) {
+        this.value = value;
+        this.clazz = clazz;
+    }
+
+    public Class<? extends TunnelIdentifier> getClazz() {
+        return clazz;
+    }
+
+    public int getIntValue() {
+        return value;
+    }
+}
index 4ea8927b2cdbf4417e7b3c10be3c4992c9fc255e..995e89e94f3667cb4924caa773be6ab28b37a809 100644 (file)
@@ -13,6 +13,7 @@ module odl-bgp-evpn {
     import bgp-message { prefix bgp-msg; revision-date 2013-09-19; }
     import bgp-multiprotocol { prefix bgp-mp; revision-date 2013-09-19; }
     import pmsi-tunnel { prefix pmsi; revision-date 2016-08-12; }
+    import yang-ext { prefix ext; revision-date 2013-07-09; }
 
     organization "Cisco Systems, Inc.";
 
@@ -389,6 +390,7 @@ module odl-bgp-evpn {
                 uses evpn;
                 uses bgp-rib:route {
                     augment "attributes" {
+                        ext:augment-identifier pmsi-tunnel-augmentation;
                         uses pmsi:pmsi-tunnel;
                     }
                     augment "attributes/extended-communities/extended-community" {
index b6b3ed13f68a7371fef8c0eefaf77fcefd25755d..693c70950a108c52ac5414368d421e079af53f42 100644 (file)
@@ -7,6 +7,7 @@ module pmsi-tunnel {
     import bgp-types { prefix bgp-t; revision-date 2013-09-19; }
     import ietf-inet-types { prefix inet; revision-date 2013-07-15; }
     import network-concepts { prefix netc; revision-date 2013-11-25; }
+    import ietf-yang-types { prefix yang; }
 
     organization "AT&T Services, Inc.";
 
@@ -31,14 +32,26 @@ module pmsi-tunnel {
 
     grouping opaque {
         leaf opaque-type {
+            mandatory true;
             type uint8;
         }
         leaf opaque-extended-type {
             type uint16;
         }
         leaf opaque {
-            // Base-64 encoded
-            type string;
+            mandatory true;
+            type yang:hex-string;
+        }
+    }
+
+    grouping p-address-p-multicast-group {
+        leaf p-address {
+            mandatory true;
+            type inet:ip-address;
+        }
+        leaf p-multicast-group {
+            mandatory true;
+            type inet:ip-address;
         }
     }
 
@@ -53,24 +66,21 @@ module pmsi-tunnel {
             }
             leaf mpls-label {
                 type netc:mpls-label;
-                mandatory true;
             }
             choice tunnel-identifier {
                 case rsvp-te-p2mp-lsp {
                     container rsvp-te-p2mp-lps {
                         reference "https://tools.ietf.org/html/rfc4875#section-19.1.1";
                         leaf p2mp-id {
+                            mandatory true;
                             type uint32;
                         }
                         leaf tunnel-id {
+                            mandatory true;
                             type uint16;
                         }
-                        leaf address-family {
-                            type identityref {
-                                base bgp-t:address-family;
-                            }
-                        }
                         leaf extended-tunnel-id {
+                            mandatory true;
                             type inet:ip-address;
                         }
                     }
@@ -79,47 +89,36 @@ module pmsi-tunnel {
                     container mldp-p2mp-lsp {
                         reference "https://tools.ietf.org/html/rfc6388#section-2.2";
                         leaf address-family {
+                            mandatory true;
                             type identityref {
                                 base bgp-t:address-family;
                             }
                         }
                         leaf root-node-address {
+                            mandatory true;
                             type inet:ip-address;
                         }
-                        uses opaque;
+                        list opaque-value {
+                            uses opaque;
+                        }
                     }
                 }
                 case pim-ssm-tree {
                     container pim-ssm-tree {
                         reference "https://tools.ietf.org/html/rfc6514#section-5";
-                        leaf p-root-node-address {
-                            type inet:ip-address;
-                        }
-                        leaf p-multicast-group {
-                            type inet:ip-address;
-                        }
+                        uses p-address-p-multicast-group;
                     }
                 }
                 case pim-sm-tree {
                     container pim-sm-tree {
                         reference "https://tools.ietf.org/html/rfc6514#section-5";
-                        leaf p-sender-address {
-                            type inet:ip-address;
-                        }
-                        leaf p-multicast-group {
-                            type inet:ip-address;
-                        }
+                        uses p-address-p-multicast-group;
                     }
                 }
                 case bidir-pim-tree {
                     container bidir-pim-tree {
                         reference "https://tools.ietf.org/html/rfc6514#section-5";
-                        leaf p-sender-address {
-                            type inet:ip-address;
-                        }
-                        leaf p-multicast-group {
-                            type inet:ip-address;
-                        }
+                        uses p-address-p-multicast-group;
                     }
                 }
                 case ingress-replication {
diff --git a/bgp/evpn/src/test/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/OpaqueUtilTest.java b/bgp/evpn/src/test/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/OpaqueUtilTest.java
new file mode 100644 (file)
index 0000000..3aee20a
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier;
+
+import static junit.framework.TestCase.assertNull;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Arrays;
+import java.util.List;
+import org.junit.Test;
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.HexString;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.Opaque;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.mldp.p2mp.lsp.mldp.p2mp.lsp.OpaqueValue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.mldp.p2mp.lsp.mldp.p2mp.lsp.OpaqueValueBuilder;
+
+public class OpaqueUtilTest {
+    private final static byte[] OPAQUE_WRONG= {
+        (byte) 0xfc, (byte) 0x00, (byte) 0x03, // Opaque Type - Length
+        (byte) 0xb5, (byte) 0xeb, (byte) 0x2d,  //Value
+    };
+
+    private final static byte[] OPAQUE_EXPECTED = {
+        (byte) 0x01, (byte) 0x00, (byte) 0x0e, // Opaque Type - Length
+        (byte) 0x07, (byte) 0x00, (byte) 0x0B, //Value
+        (byte) 0x00, (byte) 0x00, (byte) 0x01,
+        (byte) 0x00, (byte) 0x00, (byte) 0x00,
+        (byte) 0x01, (byte) 0x00, (byte) 0x00,
+        (byte) 0x00, (byte) 0x00
+    };
+    private final static byte[] OPAQUE_EXT_EXPECTED = {
+        (byte) 0xff, (byte) 0x00, (byte) 0x04, (byte) 0x00, (byte) 0x10, // Opaque Type -Ext Type - Length
+        (byte) 0x07, (byte) 0x00, (byte) 0x0B, //Value
+        (byte) 0x00, (byte) 0x00, (byte) 0x01,
+        (byte) 0x00, (byte) 0x00, (byte) 0x00,
+        (byte) 0x01, (byte) 0x00, (byte) 0x00,
+        (byte) 0x00, (byte) 0x00, (byte) 0x01,
+        (byte) 0x02
+    };
+    private final static byte[] OPAQUE_VALUES_EXPECTED = {
+        (byte) 0x01, (byte) 0x00, (byte) 0x0e, // Opaque Type - Length
+        (byte) 0x07, (byte) 0x00, (byte) 0x0B, //Value
+        (byte) 0x00, (byte) 0x00, (byte) 0x01,
+        (byte) 0x00, (byte) 0x00, (byte) 0x00,
+        (byte) 0x01, (byte) 0x00, (byte) 0x00,
+        (byte) 0x00, (byte) 0x00,
+        (byte) 0xff, (byte) 0x00, (byte) 0x04, (byte) 0x00, (byte) 0x10, // Opaque Type -Ext Type - Length
+        (byte) 0x07, (byte) 0x00, (byte) 0x0B, //Value
+        (byte) 0x00, (byte) 0x00, (byte) 0x01,
+        (byte) 0x00, (byte) 0x00, (byte) 0x00,
+        (byte) 0x01, (byte) 0x00, (byte) 0x00,
+        (byte) 0x00, (byte) 0x00, (byte) 0x01,
+        (byte) 0x02
+    };
+
+    static final HexString OPAQUE_TEST = new HexString("07:00:0b:00:00:01:00:00:00:01:00:00:00:00");
+    static final HexString OPAQUE_TEST2 = new HexString ("07:00:0b:00:00:01:00:00:00:01:00:00:00:00:01:02");
+    private final static Opaque OPAQUE = new OpaqueValueBuilder().setOpaque(OPAQUE_TEST).setOpaqueType(OpaqueUtil.GENERIC_LSP_IDENTIFIER).build();
+    private final static Opaque OPAQUE_EXTENDED = new OpaqueValueBuilder().setOpaque(OPAQUE_TEST2).setOpaqueType((short) 2)
+        .setOpaqueType(OpaqueUtil.EXTENDED_TYPE).setOpaqueExtendedType(4).build();
+    private final static List<OpaqueValue> OPAQUE_VALUE_LIST = Arrays.asList((OpaqueValue) OPAQUE, (OpaqueValue) OPAQUE_EXTENDED);
+
+    @Test
+    public void serializeOpaque() throws Exception {
+        final ByteBuf actualOpaque = Unpooled.buffer();
+        OpaqueUtil.serializeOpaque(OPAQUE, actualOpaque);
+        assertArrayEquals(OPAQUE_EXPECTED, ByteArray.readAllBytes(actualOpaque));
+
+        final ByteBuf actualOpaqueExt = Unpooled.buffer();
+        OpaqueUtil.serializeOpaque(OPAQUE_EXTENDED, actualOpaqueExt);
+        assertArrayEquals(OPAQUE_EXT_EXPECTED, ByteArray.readAllBytes(actualOpaqueExt));
+
+        final ByteBuf empty = Unpooled.buffer();
+        OpaqueUtil.serializeOpaque(new OpaqueValueBuilder().setOpaqueType((short) 5).build(), actualOpaqueExt);
+        assertArrayEquals(new byte[0], ByteArray.readAllBytes(empty));
+
+        final Opaque opaque = OpaqueUtil.parseOpaque(Unpooled.wrappedBuffer(OPAQUE_EXPECTED));
+        assertEquals(OPAQUE, opaque);
+
+        final Opaque opaqueExt = OpaqueUtil.parseOpaque(Unpooled.wrappedBuffer(OPAQUE_EXT_EXPECTED));
+        assertEquals(OPAQUE_EXTENDED, opaqueExt);
+
+        assertNull(OpaqueUtil.parseOpaque(Unpooled.wrappedBuffer(OPAQUE_WRONG)));
+    }
+
+    @Test
+    public void parseOpaqueList() throws Exception {
+        final ByteBuf opaqueValues = Unpooled.buffer();
+        OpaqueUtil.serializeOpaqueList(OPAQUE_VALUE_LIST, opaqueValues);
+        assertArrayEquals(OPAQUE_VALUES_EXPECTED, ByteArray.readAllBytes(opaqueValues));
+        assertEquals(OPAQUE_VALUE_LIST, OpaqueUtil.parseOpaqueList(Unpooled.wrappedBuffer(OPAQUE_VALUES_EXPECTED)));
+    }
+
+    @Test(expected = UnsupportedOperationException.class)
+    public void testPrivateConstructor() throws Throwable {
+        final Constructor<OpaqueUtil> c = OpaqueUtil.class.getDeclaredConstructor();
+        c.setAccessible(true);
+        try {
+            c.newInstance();
+        } catch (final InvocationTargetException e) {
+            throw e.getCause();
+        }
+    }
+}
\ No newline at end of file
diff --git a/bgp/evpn/src/test/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/PAddressPMulticastGroupUtilTest.java b/bgp/evpn/src/test/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/PAddressPMulticastGroupUtilTest.java
new file mode 100644 (file)
index 0000000..b7c8b56
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.opendaylight.protocol.bgp.evpn.impl.EvpnTestUtil.IPV6;
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.PMSITunnelAttributeHandlerTestUtil.P_ADDRESS;
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.PMSITunnelAttributeHandlerTestUtil.P_MULTICAST;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import org.junit.Test;
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.util.Ipv4Util;
+import org.opendaylight.protocol.util.Ipv6Util;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.PAddressPMulticastGroup;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+
+public class PAddressPMulticastGroupUtilTest {
+    private final static byte[] IPV4_ADDRESS_EXPECTED = {
+        (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01
+    };
+    private final static byte[] IPV6_ADDRESS_EXPECTED = {
+        0x20, (byte) 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
+    };
+
+    private final static byte[] SENDER_P_MULTICAST_GROUP_EXPECTED = {
+        (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01,
+        (byte) 0x17, (byte) 0x01, (byte) 0x01, (byte) 0x01
+    };
+
+    private static class MyPAddressPMulticastGroup implements PAddressPMulticastGroup {
+        @Override
+        public IpAddress getPAddress() {
+            return P_ADDRESS;
+        }
+
+        @Override
+        public IpAddress getPMulticastGroup() {
+            return P_MULTICAST;
+        }
+
+        @Override
+        public Class<? extends DataContainer> getImplementedInterface() {
+            return null;
+        }
+    }
+
+    @Test
+    public void parseIpAddress() throws Exception {
+        final ByteBuf ipv4Actual = Unpooled.buffer();
+        PAddressPMulticastGroupUtil.serializeIpAddress(P_ADDRESS, ipv4Actual);
+        assertArrayEquals(IPV4_ADDRESS_EXPECTED, ByteArray.readAllBytes(ipv4Actual));
+        final ByteBuf ipv6Actual = Unpooled.buffer();
+        PAddressPMulticastGroupUtil.serializeIpAddress(IPV6, ipv6Actual);
+        assertArrayEquals(IPV6_ADDRESS_EXPECTED, ByteArray.readAllBytes(ipv6Actual));
+        assertEquals(P_ADDRESS, PAddressPMulticastGroupUtil.parseIpAddress(Ipv4Util.IP4_LENGTH, Unpooled.wrappedBuffer(IPV4_ADDRESS_EXPECTED)));
+        assertEquals(IPV6, PAddressPMulticastGroupUtil.parseIpAddress(Ipv6Util.IPV6_LENGTH, Unpooled.wrappedBuffer(IPV6_ADDRESS_EXPECTED)));
+        assertNull(PAddressPMulticastGroupUtil.parseIpAddress(6, Unpooled.wrappedBuffer(IPV4_ADDRESS_EXPECTED)));
+    }
+
+    @Test
+    public void parseIpAddressPMulticastGroup() throws Exception {
+        final PAddressPMulticastGroup pAddressPMulticastGroup = new MyPAddressPMulticastGroup();
+        final ByteBuf pAddressPMulticastGroupActual = Unpooled.buffer();
+        PAddressPMulticastGroupUtil.serializeSenderPMulticastGroup(pAddressPMulticastGroup, pAddressPMulticastGroupActual);
+        assertArrayEquals(SENDER_P_MULTICAST_GROUP_EXPECTED, ByteArray.readAllBytes(pAddressPMulticastGroupActual));
+
+        final PAddressPMulticastGroup actual = PAddressPMulticastGroupUtil.parseSenderPMulticastGroup(Unpooled.wrappedBuffer
+            (SENDER_P_MULTICAST_GROUP_EXPECTED));
+        assertEquals(pAddressPMulticastGroup.getPAddress(), actual.getPAddress());
+        assertEquals(pAddressPMulticastGroup.getPMulticastGroup(), actual.getPMulticastGroup());
+    }
+
+    @Test(expected = UnsupportedOperationException.class)
+    public void testPrivateConstructor() throws Throwable {
+        final Constructor<PAddressPMulticastGroupUtil> constructor = PAddressPMulticastGroupUtil.class.getDeclaredConstructor();
+        constructor.setAccessible(true);
+        try {
+            constructor.newInstance();
+        } catch (final InvocationTargetException e) {
+            throw e.getCause();
+        }
+    }
+}
\ No newline at end of file
diff --git a/bgp/evpn/src/test/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/PMSITunnelAttributeHandlerTest.java b/bgp/evpn/src/test/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/PMSITunnelAttributeHandlerTest.java
new file mode 100644 (file)
index 0000000..990713f
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier;
+
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.PMSITunnelAttributeHandlerTestUtil.BIDIR_PIM_EXPECTED;
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.PMSITunnelAttributeHandlerTestUtil.INGRESS_REPLICATION_EXPECTED;
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.PMSITunnelAttributeHandlerTestUtil.M_LDP_MP_2_MP_LSP_EXPECTED;
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.PMSITunnelAttributeHandlerTestUtil.M_LDP_MP_2_MP_LSP_WRONG;
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.PMSITunnelAttributeHandlerTestUtil.M_LDP_P2MP_LSP_EXPECTED_IPV4;
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.PMSITunnelAttributeHandlerTestUtil.M_LDP_P2MP_LSP_EXPECTED_IPV4_2;
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.PMSITunnelAttributeHandlerTestUtil.M_LDP_P2MP_LSP_EXPECTED_IPV6;
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.PMSITunnelAttributeHandlerTestUtil.M_LDP_P2MP_LSP_EXPECTED_L2VPN;
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.PMSITunnelAttributeHandlerTestUtil.M_LDP_P2MP_LSP_EXPECTED_WRONG_FAMILY;
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.PMSITunnelAttributeHandlerTestUtil.MockTunnelIdentifier;
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.PMSITunnelAttributeHandlerTestUtil.NO_TUNNEL_INFORMATION_PRESENT_EXPECTED;
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.PMSITunnelAttributeHandlerTestUtil.PIM_SM_TREE_EXPECTED;
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.PMSITunnelAttributeHandlerTestUtil.PIM_SSM_TREE_EXPECTED;
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.PMSITunnelAttributeHandlerTestUtil.RSVP_TE_P2MP_LSP_LSP_EXPECTED;
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.PMSITunnelAttributeHandlerTestUtil.buildBidirPimTreeAttribute;
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.PMSITunnelAttributeHandlerTestUtil.buildINGRESSREPLICATIONAttribute;
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.PMSITunnelAttributeHandlerTestUtil.buildMLDPMP2MPLSPAttribute;
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.PMSITunnelAttributeHandlerTestUtil.buildMLDPMP2MPLSPWrongAttribute;
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.PMSITunnelAttributeHandlerTestUtil.buildMLDPP2MPLSPIpv4Attribute;
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.PMSITunnelAttributeHandlerTestUtil.buildMLDPP2MPLSPIpv6Attribute;
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.PMSITunnelAttributeHandlerTestUtil.buildMLDPP2MPLSPL2vpnAttribute;
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.PMSITunnelAttributeHandlerTestUtil.buildNoSupportedFamilyAttribute;
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.PMSITunnelAttributeHandlerTestUtil.buildNoSupportedOpaqueAttribute;
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.PMSITunnelAttributeHandlerTestUtil.buildPimSMTreeAttribute;
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.PMSITunnelAttributeHandlerTestUtil.buildPimSSMTreeAttribute;
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.PMSITunnelAttributeHandlerTestUtil.buildRSVPTEP2MPLSPLSPAttribute;
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.PMSITunnelAttributeHandlerTestUtil.buildWOTunnelInfAttribute;
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.TunnelIdentifierHandler.NO_TUNNEL_INFORMATION_PRESENT;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.evpn.impl.BGPActivator;
+import org.opendaylight.protocol.bgp.evpn.impl.attributes.PMSITunnelAttributeHandler;
+import org.opendaylight.protocol.bgp.parser.spi.AttributeRegistry;
+import org.opendaylight.protocol.bgp.parser.spi.BGPExtensionProviderContext;
+import org.opendaylight.protocol.bgp.parser.spi.pojo.ServiceLoaderBGPExtensionProviderContext;
+import org.opendaylight.protocol.bgp.parser.spi.pojo.SimpleBGPExtensionProviderContext;
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.Attributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.AttributesBuilder;
+
+public class PMSITunnelAttributeHandlerTest {
+
+    private AttributeRegistry handler;
+
+    @Before
+    public void setUp() {
+        final BGPExtensionProviderContext ctx = new SimpleBGPExtensionProviderContext();
+
+        final org.opendaylight.protocol.bgp.parser.impl.BGPActivator inetActivator = new org.opendaylight.protocol.bgp.parser.impl.BGPActivator();
+        inetActivator.start(ctx);
+        final BGPActivator bgpActivator = new BGPActivator();
+        bgpActivator.start(ctx);
+        this.handler = ctx.getAttributeRegistry();
+    }
+
+    @Test
+    public void testBidirPimTree() throws Exception {
+        final Attributes attributes = buildBidirPimTreeAttribute();
+        final ByteBuf actual = Unpooled.buffer();
+        this.handler.serializeAttribute(attributes, actual);
+        assertArrayEquals(BIDIR_PIM_EXPECTED, ByteArray.readAllBytes(actual));
+        final Attributes expected = buildBidirPimTreeAttribute();
+        final Attributes actualAttr = this.handler.parseAttributes(Unpooled.wrappedBuffer(BIDIR_PIM_EXPECTED), null);
+        assertEquals(expected, actualAttr);
+    }
+
+    @Test
+    public void testPimSMTree() throws Exception {
+        final Attributes attributes = buildPimSMTreeAttribute();
+        final ByteBuf actual = Unpooled.buffer();
+        this.handler.serializeAttribute(attributes, actual);
+        assertArrayEquals(PIM_SM_TREE_EXPECTED, ByteArray.readAllBytes(actual));
+        final Attributes expected = buildPimSMTreeAttribute();
+        final Attributes actualAttr = this.handler.parseAttributes(Unpooled.wrappedBuffer(PIM_SM_TREE_EXPECTED), null);
+        assertEquals(expected, actualAttr);
+    }
+
+    @Test
+    public void serializePimSSMTree() throws Exception {
+        final Attributes attributes = buildPimSSMTreeAttribute();
+        final ByteBuf actual = Unpooled.buffer();
+        this.handler.serializeAttribute(attributes, actual);
+        assertArrayEquals(PIM_SSM_TREE_EXPECTED, ByteArray.readAllBytes(actual));
+    }
+
+    @Test
+    public void parsePimSSMTree() throws Exception {
+        final Attributes expected = buildPimSSMTreeAttribute();
+        final Attributes actual = this.handler.parseAttributes(Unpooled.wrappedBuffer(PIM_SSM_TREE_EXPECTED), null);
+        assertEquals(expected, actual);
+    }
+
+    @Test
+    public void testMldpP2MpLsp() throws Exception {
+        final ByteBuf actualIpv4 = Unpooled.buffer();
+        final Attributes expectedIpv4Att = buildMLDPP2MPLSPIpv4Attribute();
+
+        final BGPExtensionProviderContext providerContext = ServiceLoaderBGPExtensionProviderContext.getSingletonInstance();
+        providerContext.getAttributeRegistry().serializeAttribute(expectedIpv4Att, actualIpv4);
+        assertArrayEquals(M_LDP_P2MP_LSP_EXPECTED_IPV4, ByteArray.readAllBytes(actualIpv4));
+
+        final Attributes actualIpv4Attribute = this.handler.parseAttributes(Unpooled.wrappedBuffer(M_LDP_P2MP_LSP_EXPECTED_IPV4_2), null);
+        assertEquals(expectedIpv4Att, actualIpv4Attribute);
+
+        final Attributes expectedIpv6Att = buildMLDPP2MPLSPIpv6Attribute();
+        final ByteBuf actualIpv6 = Unpooled.buffer();
+        this.handler.serializeAttribute(expectedIpv6Att, actualIpv6);
+        assertArrayEquals(M_LDP_P2MP_LSP_EXPECTED_IPV6, ByteArray.readAllBytes(actualIpv6));
+
+        final Attributes actualIpv6Attribute = this.handler.parseAttributes(Unpooled.wrappedBuffer(M_LDP_P2MP_LSP_EXPECTED_IPV6), null);
+        assertEquals(expectedIpv6Att, actualIpv6Attribute);
+
+        final ByteBuf actualL2vpn = Unpooled.buffer();
+        this.handler.serializeAttribute(buildNoSupportedFamilyAttribute(), actualL2vpn);
+        assertArrayEquals(new byte[0], ByteArray.readAllBytes(actualIpv4));
+
+
+        final Attributes actualWrongFamily = this.handler.parseAttributes(Unpooled.wrappedBuffer(M_LDP_P2MP_LSP_EXPECTED_WRONG_FAMILY), null);
+        assertEquals(buildWOTunnelInfAttribute(), actualWrongFamily);
+
+        final Attributes expectedL2vpnAtt = buildMLDPP2MPLSPL2vpnAttribute();
+        final Attributes actualL2vpnAttribute = this.handler.parseAttributes(Unpooled.wrappedBuffer(M_LDP_P2MP_LSP_EXPECTED_L2VPN), null);
+        assertEquals(expectedL2vpnAtt, actualL2vpnAttribute);
+
+        final ByteBuf actualL2vp = Unpooled.buffer();
+        this.handler.serializeAttribute(expectedL2vpnAtt, actualL2vp);
+        assertArrayEquals(M_LDP_P2MP_LSP_EXPECTED_L2VPN, ByteArray.readAllBytes(actualL2vp));
+
+        final ByteBuf actualNonSupportedOpaques = Unpooled.buffer();
+        this.handler.serializeAttribute(buildNoSupportedOpaqueAttribute(), actualNonSupportedOpaques);
+        assertArrayEquals(NO_TUNNEL_INFORMATION_PRESENT_EXPECTED, ByteArray.readAllBytes(actualNonSupportedOpaques));
+    }
+
+    @Test
+    public void testRsvpteP2MplspLsp() throws Exception {
+        final Attributes expected = buildRSVPTEP2MPLSPLSPAttribute();
+        final ByteBuf actual = Unpooled.buffer();
+        this.handler.serializeAttribute(expected, actual);
+        assertArrayEquals(RSVP_TE_P2MP_LSP_LSP_EXPECTED, ByteArray.readAllBytes(actual));
+        final Attributes actualAttr = this.handler.parseAttributes(Unpooled.wrappedBuffer(RSVP_TE_P2MP_LSP_LSP_EXPECTED), null);
+        assertEquals(expected, actualAttr);
+    }
+
+    @Test
+    public void testIngressReplication() throws Exception {
+        final Attributes expected = buildINGRESSREPLICATIONAttribute();
+        final ByteBuf actual = Unpooled.buffer();
+        this.handler.serializeAttribute(expected, actual);
+        assertArrayEquals(INGRESS_REPLICATION_EXPECTED, ByteArray.readAllBytes(actual));
+        final Attributes actualAttr = this.handler.parseAttributes(Unpooled.wrappedBuffer(INGRESS_REPLICATION_EXPECTED), null);
+        assertEquals(expected, actualAttr);
+    }
+
+    @Test
+    public void testMldpmP2MpLsp() throws Exception {
+        final Attributes expected = buildMLDPMP2MPLSPAttribute();
+        final ByteBuf actual = Unpooled.buffer();
+        this.handler.serializeAttribute(expected, actual);
+        assertArrayEquals(M_LDP_MP_2_MP_LSP_EXPECTED, ByteArray.readAllBytes(actual));
+
+        final Attributes actualAttr = this.handler.parseAttributes(Unpooled.wrappedBuffer(M_LDP_MP_2_MP_LSP_EXPECTED), null);
+        assertEquals(expected, actualAttr);
+
+        final Attributes actualWrong = this.handler.parseAttributes(Unpooled.wrappedBuffer(M_LDP_MP_2_MP_LSP_WRONG), null);
+        assertEquals(buildWOTunnelInfAttribute(), actualWrong);
+
+        final Attributes wrongAttribute = buildMLDPMP2MPLSPWrongAttribute();
+        final ByteBuf actualWrongBuf = Unpooled.buffer();
+        this.handler.serializeAttribute(wrongAttribute, actualWrongBuf);
+        assertArrayEquals(NO_TUNNEL_INFORMATION_PRESENT_EXPECTED, ByteArray.readAllBytes(actualWrongBuf));
+    }
+
+
+    @Test
+    public void serializeNoTunnelInfPresentExpected() throws Exception {
+        final Attributes attributes = buildWOTunnelInfAttribute();
+        final ByteBuf actual = Unpooled.buffer();
+        this.handler.serializeAttribute(attributes, actual);
+        assertArrayEquals(NO_TUNNEL_INFORMATION_PRESENT_EXPECTED, ByteArray.readAllBytes(actual));
+        final Attributes expected = buildWOTunnelInfAttribute();
+        final Attributes actualAttr = this.handler.parseAttributes(Unpooled.wrappedBuffer(NO_TUNNEL_INFORMATION_PRESENT_EXPECTED), null);
+        assertEquals(expected, actualAttr);
+    }
+
+    @Test
+    public void testTunnelIdentifierUtil() throws Throwable {
+        final TunnelIdentifierHandler tunnelIdentifierHandler = new TunnelIdentifierHandler(ServiceLoaderBGPExtensionProviderContext
+            .getSingletonInstance().getAddressFamilyRegistry());
+        assertNull(tunnelIdentifierHandler.parse(1, Unpooled.buffer()));
+        assertNull(tunnelIdentifierHandler.parse(125, Unpooled.buffer()));
+        assertEquals(NO_TUNNEL_INFORMATION_PRESENT, tunnelIdentifierHandler.serialize(new MockTunnelIdentifier(), Unpooled.buffer()));
+    }
+
+    @Test
+    public void testPMSITunnelAttributeParser() throws Throwable {
+        final PMSITunnelAttributeHandler pmsiHandler = new PMSITunnelAttributeHandler(ServiceLoaderBGPExtensionProviderContext
+            .getSingletonInstance().getAddressFamilyRegistry());
+        assertEquals(22, pmsiHandler.getType());
+        final AttributesBuilder builder = new AttributesBuilder();
+        final ByteBuf emptyBuffer = Unpooled.buffer();
+        pmsiHandler.parseAttribute(emptyBuffer, builder);
+        final Attributes emptyAttributes = new AttributesBuilder().build();
+        assertEquals(emptyAttributes, builder.build());
+        pmsiHandler.serializeAttribute(emptyAttributes, emptyBuffer);
+        assertEquals(Unpooled.buffer(), emptyBuffer);
+    }
+}
\ No newline at end of file
diff --git a/bgp/evpn/src/test/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/PMSITunnelAttributeHandlerTestUtil.java b/bgp/evpn/src/test/java/org/opendaylight/protocol/bgp/evpn/impl/attributes/tunnel/identifier/PMSITunnelAttributeHandlerTestUtil.java
new file mode 100644 (file)
index 0000000..0c5a1e2
--- /dev/null
@@ -0,0 +1,391 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier;
+
+import static org.opendaylight.protocol.bgp.evpn.impl.EvpnTestUtil.IPV6;
+import static org.opendaylight.protocol.bgp.evpn.impl.EvpnTestUtil.MPLS_LABEL;
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.OpaqueUtilTest.OPAQUE_TEST;
+import static org.opendaylight.protocol.bgp.evpn.impl.attributes.tunnel.identifier.OpaqueUtilTest.OPAQUE_TEST2;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.L2vpnAddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.evpn.routes.evpn.routes.evpn.route.PmsiTunnelAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.evpn.routes.evpn.routes.evpn.route.PmsiTunnelAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.Attributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.AttributesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Ipv4AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Ipv6AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.PAddressPMulticastGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.PmsiTunnelBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.TunnelIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.BidirPimTreeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.IngressReplicationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.MldpMp2mpLspBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.MldpP2mpLspBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.PimSmTreeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.PimSsmTreeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.RsvpTeP2mpLspBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.mldp.p2mp.lsp.mldp.p2mp.lsp.OpaqueValue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.mldp.p2mp.lsp.mldp.p2mp.lsp.OpaqueValueBuilder;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+
+final class PMSITunnelAttributeHandlerTestUtil {
+    /**
+     * ATT - TYPE - ATT LENGTH
+     * PMSI FLAG - PMSI TYPE 0- MPLS LABEL
+     * No tunnel information present
+     */
+    final static byte[] NO_TUNNEL_INFORMATION_PRESENT_EXPECTED = {
+        (byte) 0x80, (byte) 0x16, (byte) 0x05,
+        (byte) 0x01, (byte) 0x00, (byte) 0x05, (byte) 0xdc, (byte) 0x10
+    };
+    /**
+     * ATT - TYPE - ATT LENGTH
+     * PMSI FLAG - PMSI TYPE 1- MPLS LABEL
+     * mLDP P2MP LSP
+     */
+    final static byte[] RSVP_TE_P2MP_LSP_LSP_EXPECTED = {
+        (byte) 0x80, (byte) 0x16, (byte) 0x11,
+        (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0xdc, (byte) 0x10,
+        (byte) 0x00, (byte) 0x00, (byte) 0x0d, (byte) 0x82,
+        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0f,
+        (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01,
+    };
+    /**
+     * ATT - TYPE - ATT LENGTH
+     * PMSI FLAG - PMSI TYPE 2- MPLS LABEL
+     * mLDP P2MP LSP
+     */
+    final static byte[] M_LDP_P2MP_LSP_EXPECTED_IPV4 = {
+        (byte) 0x80, (byte) 0x16, (byte) 0x35,
+        (byte) 0x01, (byte) 0x02, (byte) 0x05, (byte) 0xdc, (byte) 0x10,
+        (byte) 0x06, (byte) 0x00, (byte) 0x01, (byte) 0x04,
+        (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01,
+        (byte) 0x00, (byte) 0x26, //Opaque Values Length
+        (byte) 0x01, (byte) 0x00, (byte) 0x0e, // Opaque Type - Length
+        (byte) 0x07, (byte) 0x00, (byte) 0x0B, //Value
+        (byte) 0x00, (byte) 0x00, (byte) 0x01,
+        (byte) 0x00, (byte) 0x00, (byte) 0x00,
+        (byte) 0x01, (byte) 0x00, (byte) 0x00,
+        (byte) 0x00, (byte) 0x00,
+        (byte) 0xff, (byte) 0x00, (byte) 0x04, (byte) 0x00, (byte) 0x10, // Opaque Type -Ext Type - Length
+        (byte) 0x07, (byte) 0x00, (byte) 0x0B, //Value
+        (byte) 0x00, (byte) 0x00, (byte) 0x01,
+        (byte) 0x00, (byte) 0x00, (byte) 0x00,
+        (byte) 0x01, (byte) 0x00, (byte) 0x00,
+        (byte) 0x00, (byte) 0x00, (byte) 0x01,
+        (byte) 0x02
+    };
+    /**
+     * ATT - TYPE - ATT LENGTH
+     * PMSI FLAG - PMSI TYPE 2- MPLS LABEL
+     * mLDP P2MP LSP
+     */
+    final static byte[] M_LDP_P2MP_LSP_EXPECTED_WRONG_FAMILY = {
+        (byte) 0x80, (byte) 0x16, (byte) 0x20,
+        (byte) 0x01, (byte) 0x02, (byte) 0x05, (byte) 0xdc, (byte) 0x10,
+        (byte) 0x06, (byte) 0x00, (byte) 0xfc, (byte) 0x04,
+        (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01,
+        (byte) 0x00, (byte) 0x11, //Opaque Values Length
+        (byte) 0x01, (byte) 0x00, (byte) 0x03, // Opaque Type - Length
+        (byte) 0xb5, (byte) 0xeb, (byte) 0x2d,  //Value
+        (byte) 0xff, (byte) 0x00, (byte) 0x04, (byte) 0x00, (byte) 0x06, // Opaque Type -Ext Type - Length
+        (byte) 0xb5, (byte) 0xeb, (byte) 0x2d, (byte) 0xd7, (byte) 0x6d, (byte) 0xf8, //Value
+    };
+    /**
+     * ATT - TYPE - ATT LENGTH
+     * PMSI FLAG - PMSI TYPE 2- MPLS LABEL
+     * mLDP P2MP LSP L2VPN
+     */
+    final static byte[] M_LDP_P2MP_LSP_EXPECTED_L2VPN = {
+        (byte) 0x80, (byte) 0x16, (byte) 0x35,
+        (byte) 0x01, (byte) 0x02, (byte) 0x05, (byte) 0xdc, (byte) 0x10,
+        (byte) 0x06, (byte) 0x00, (byte) 0x19, (byte) 0x04,
+        (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01,
+        (byte) 0x00, (byte) 0x26, //Opaque Values Length
+        (byte) 0x01, (byte) 0x00, (byte) 0x0e, // Opaque Type - Length
+        (byte) 0x07, (byte) 0x00, (byte) 0x0B, //Value
+        (byte) 0x00, (byte) 0x00, (byte) 0x01,
+        (byte) 0x00, (byte) 0x00, (byte) 0x00,
+        (byte) 0x01, (byte) 0x00, (byte) 0x00,
+        (byte) 0x00, (byte) 0x00,
+        (byte) 0xff, (byte) 0x00, (byte) 0x04, (byte) 0x00, (byte) 0x10, // Opaque Type -Ext Type - Length
+        (byte) 0x07, (byte) 0x00, (byte) 0x0B, //Value
+        (byte) 0x00, (byte) 0x00, (byte) 0x01,
+        (byte) 0x00, (byte) 0x00, (byte) 0x00,
+        (byte) 0x01, (byte) 0x00, (byte) 0x00,
+        (byte) 0x00, (byte) 0x00, (byte) 0x01,
+        (byte) 0x02
+    };
+    /**
+     * ATT - TYPE - ATT LENGTH
+     * PMSI FLAG - PMSI TYPE 2- MPLS LABEL
+     * mLDP P2MP LSP IPV4
+     */
+    final static byte[] M_LDP_P2MP_LSP_EXPECTED_IPV4_2 = {
+        (byte) 0x80, (byte) 0x16, (byte) 0x3b,
+        (byte) 0x01, (byte) 0x02, (byte) 0x05, (byte) 0xdc, (byte) 0x10,
+        (byte) 0x06, (byte) 0x00, (byte) 0x01, (byte) 0x04,
+        (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01,
+        (byte) 0x00, (byte) 0x2c, //Opaque Values Length
+        (byte) 0x01, (byte) 0x00, (byte) 0x0e, // Opaque Type - Length
+        (byte) 0x07, (byte) 0x00, (byte) 0x0B, //Value
+        (byte) 0x00, (byte) 0x00, (byte) 0x01,
+        (byte) 0x00, (byte) 0x00, (byte) 0x00,
+        (byte) 0x01, (byte) 0x00, (byte) 0x00,
+        (byte) 0x00, (byte) 0x00,
+        (byte) 0xfc, (byte) 0x00, (byte) 0x03, // Wrong Opaque Type - Length
+        (byte) 0xb5, (byte) 0xeb, (byte) 0x2d,  //Value
+        (byte) 0xff, (byte) 0x00, (byte) 0x04, (byte) 0x00, (byte) 0x10, // Opaque Type -Ext Type - Length
+        (byte) 0x07, (byte) 0x00, (byte) 0x0B, //Value
+        (byte) 0x00, (byte) 0x00, (byte) 0x01,
+        (byte) 0x00, (byte) 0x00, (byte) 0x00,
+        (byte) 0x01, (byte) 0x00, (byte) 0x00,
+        (byte) 0x00, (byte) 0x00, (byte) 0x01,
+        (byte) 0x02
+    };
+    /**
+     * ATT - TYPE - ATT LENGTH
+     * PMSI FLAG - PMSI TYPE 2- MPLS LABEL
+     * mLDP P2MP LSP IPV6
+     */
+    final static byte[] M_LDP_P2MP_LSP_EXPECTED_IPV6 = {
+        (byte) 0x80, (byte) 0x16, (byte) 0x41,
+        (byte) 0x01, (byte) 0x02, (byte) 0x05, (byte) 0xdc, (byte) 0x10,
+        (byte) 0x06, (byte) 0x00, (byte) 0x02, (byte) 0x10,
+        (byte) 0x20, (byte) 0x01, (byte) 0x00, (byte) 0x00,
+        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01,
+        (byte) 0x00, (byte) 0x26, //Opaque Values Length
+        (byte) 0x01, (byte) 0x00, (byte) 0x0e, // Opaque Type - Length
+        (byte) 0x07, (byte) 0x00, (byte) 0x0B, //Value
+        (byte) 0x00, (byte) 0x00, (byte) 0x01,
+        (byte) 0x00, (byte) 0x00, (byte) 0x00,
+        (byte) 0x01, (byte) 0x00, (byte) 0x00,
+        (byte) 0x00, (byte) 0x00,
+        (byte) 0xff, (byte) 0x00, (byte) 0x04, (byte) 0x00, (byte) 0x10, // Opaque Type -Ext Type - Length
+        (byte) 0x07, (byte) 0x00, (byte) 0x0B, //Value
+        (byte) 0x00, (byte) 0x00, (byte) 0x01,
+        (byte) 0x00, (byte) 0x00, (byte) 0x00,
+        (byte) 0x01, (byte) 0x00, (byte) 0x00,
+        (byte) 0x00, (byte) 0x00, (byte) 0x01,
+        (byte) 0x02
+    };
+    /**
+     * ATT - TYPE - ATT LENGTH
+     * PMSI FLAG - PMSI TYPE 3- MPLS LABEL
+     * PIM-SSM Tree
+     */
+    final static byte[] PIM_SSM_TREE_EXPECTED = {
+        (byte) 0x80, (byte) 0x16, (byte) 0x0d,
+        (byte) 0x01, (byte) 0x03, (byte) 0x05, (byte) 0xdc, (byte) 0x10,
+        (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01,
+        (byte) 0x17, (byte) 0x01, (byte) 0x01, (byte) 0x01
+    };
+    /**
+     * ATT - TYPE - ATT LENGTH
+     * PMSI FLAG - PMSI TYPE 4- MPLS LABEL
+     * PIM-SM Tree
+     */
+    final static byte[] PIM_SM_TREE_EXPECTED = {
+        (byte) 0x80, (byte) 0x16, (byte) 0x0d,
+        (byte) 0x01, (byte) 0x04, (byte) 0x05, (byte) 0xdc, (byte) 0x10,
+        (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01,
+        (byte) 0x17, (byte) 0x01, (byte) 0x01, (byte) 0x01
+    };
+    /**
+     * ATT - TYPE - ATT LENGTH
+     * PMSI FLAG - PMSI TYPE 5- MPLS LABEL
+     * BIDIR-PIM Tree
+     */
+    final static byte[] BIDIR_PIM_EXPECTED = {
+        (byte) 0x80, (byte) 0x16, (byte) 0x0d,
+        (byte) 0x01, (byte) 0x05, (byte) 0x05, (byte) 0xdc, (byte) 0x10,
+        (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01,
+        (byte) 0x17, (byte) 0x01, (byte) 0x01, (byte) 0x01
+    };
+    /**
+     * ATT - TYPE - ATT LENGTH
+     * PMSI FLAG - PMSI TYPE 6- MPLS LABEL
+     * Ingress Replication
+     */
+    final static byte[] INGRESS_REPLICATION_EXPECTED = {
+        (byte) 0x80, (byte) 0x16, (byte) 0x09,
+        (byte) 0x01, (byte) 0x06, (byte) 0x05, (byte) 0xdc, (byte) 0x10,
+        (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01
+    };
+    /**
+     * ATT - TYPE - ATT LENGTH
+     * PMSI FLAG - PMSI TYPE 7- MPLS LABEL
+     * mLDP MP2MP LSP
+     */
+    final static byte[] M_LDP_MP_2_MP_LSP_EXPECTED = {
+        (byte) 0x80, (byte) 0x16, (byte) 0x16,
+        (byte) 0x01, (byte) 0x07, (byte) 0x05, (byte) 0xdc, (byte) 0x10,
+        (byte) 0x01, (byte) 0x00, (byte) 0x0e, // Opaque Type - Length
+        (byte) 0x07, (byte) 0x00, (byte) 0x0B, //Value
+        (byte) 0x00, (byte) 0x00, (byte) 0x01,
+        (byte) 0x00, (byte) 0x00, (byte) 0x00,
+        (byte) 0x01, (byte) 0x00, (byte) 0x00,
+        (byte) 0x00, (byte) 0x00
+    };
+    /**
+     * ATT - TYPE - ATT LENGTH
+     * PMSI FLAG - PMSI TYPE 7- MPLS LABEL
+     * mLDP MP2MP LSP
+     */
+    final static byte[] M_LDP_MP_2_MP_LSP_WRONG = {
+        (byte) 0x80, (byte) 0x16, (byte) 0x0b,
+        (byte) 0x01, (byte) 0x07, (byte) 0x05, (byte) 0xdc, (byte) 0x10,
+        (byte) 0xfc, (byte) 0x00, (byte) 0x03, // Opaque Type - Length
+        (byte) 0xb5, (byte) 0xeb, (byte) 0x2d,  //Value
+    };
+
+    static final IpAddress P_MULTICAST = new IpAddress(new Ipv4Address("23.1.1.1"));
+    static final IpAddress P_ADDRESS = new IpAddress(new Ipv4Address("1.1.1.1"));
+    private static final Short NO_SUPPORTED_OPAQUE = 200;
+
+    static class MockTunnelIdentifier implements TunnelIdentifier {
+        @Override
+        public Class<? extends DataContainer> getImplementedInterface() {
+            return MockTunnelIdentifier.class;
+        }
+    }
+
+    static abstract class NonSupportedAddressFamily extends AddressFamily {
+    }
+
+    private static PAddressPMulticastGroup buildPAddressPMulticastGroup() {
+        return new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier
+            .bidir.pim.tree.BidirPimTreeBuilder().setPAddress(P_ADDRESS).setPMulticastGroup(P_MULTICAST).build();
+    }
+
+    private static PmsiTunnelBuilder getPmsiTunnelBuilder() {
+        final PmsiTunnelBuilder pmsiTunnelBuilder = new PmsiTunnelBuilder();
+        pmsiTunnelBuilder.setLeafInformationRequired(true);
+        pmsiTunnelBuilder.setMplsLabel(MPLS_LABEL);
+        return pmsiTunnelBuilder;
+    }
+
+    private static Attributes buildAttribute(final PmsiTunnelBuilder pmsiTunnelBuilder) {
+        return new AttributesBuilder().setUnrecognizedAttributes(Collections.emptyList()).addAugmentation(PmsiTunnelAugmentation.class,
+            new PmsiTunnelAugmentationBuilder().setPmsiTunnel(pmsiTunnelBuilder.build()).build()).build();
+    }
+
+    static Attributes buildBidirPimTreeAttribute() {
+        final PmsiTunnelBuilder pmsiTunnelBuilder = getPmsiTunnelBuilder();
+        pmsiTunnelBuilder.setTunnelIdentifier(new BidirPimTreeBuilder().setBidirPimTree(new org.opendaylight.yang.gen.v1.urn.opendaylight.params
+            .xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.bidir.pim.tree.BidirPimTreeBuilder(buildPAddressPMulticastGroup()).build()).build());
+        return buildAttribute(pmsiTunnelBuilder);
+    }
+
+    static Attributes buildPimSMTreeAttribute() {
+        final PmsiTunnelBuilder pmsiTunnelBuilder = getPmsiTunnelBuilder();
+        pmsiTunnelBuilder.setTunnelIdentifier(new PimSmTreeBuilder().setPimSmTree(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns
+            .yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.pim.sm.tree.PimSmTreeBuilder(buildPAddressPMulticastGroup()).build()).build());
+        return buildAttribute(pmsiTunnelBuilder);
+    }
+
+    static Attributes buildPimSSMTreeAttribute() {
+        final PmsiTunnelBuilder pmsiTunnelBuilder = getPmsiTunnelBuilder();
+        pmsiTunnelBuilder.setTunnelIdentifier(new PimSsmTreeBuilder().setPimSsmTree(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns
+            .yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.pim.ssm.tree.PimSsmTreeBuilder(buildPAddressPMulticastGroup()).build()).build());
+        return buildAttribute(pmsiTunnelBuilder);
+    }
+
+    static Attributes buildNoSupportedOpaqueAttribute() {
+        final PmsiTunnelBuilder pmsiTunnelBuilder = getPmsiTunnelBuilder();
+        final List<OpaqueValue> nonSupported = Collections.singletonList(new OpaqueValueBuilder().setOpaque(OPAQUE_TEST).setOpaqueType(NO_SUPPORTED_OPAQUE).build());
+        pmsiTunnelBuilder.setTunnelIdentifier(buildMldpP2mpLsp(P_ADDRESS, Ipv4AddressFamily.class, nonSupported));
+        return buildAttribute(pmsiTunnelBuilder);
+    }
+
+    static Attributes buildNoSupportedFamilyAttribute() {
+        final PmsiTunnelBuilder pmsiTunnelBuilder = getPmsiTunnelBuilder();
+        pmsiTunnelBuilder.setTunnelIdentifier(buildMldpP2mpLsp(P_ADDRESS, NonSupportedAddressFamily.class, createOpaqueList()));
+        return buildAttribute(pmsiTunnelBuilder);
+    }
+
+    static Attributes buildMLDPP2MPLSPIpv4Attribute() {
+        final PmsiTunnelBuilder pmsiTunnelBuilder = getPmsiTunnelBuilder();
+        pmsiTunnelBuilder.setTunnelIdentifier(buildMldpP2mpLsp(P_ADDRESS, Ipv4AddressFamily.class, createOpaqueList()));
+        return buildAttribute(pmsiTunnelBuilder);
+    }
+
+    static Attributes buildMLDPP2MPLSPIpv6Attribute() {
+        final PmsiTunnelBuilder pmsiTunnelBuilder = new PmsiTunnelBuilder();
+        pmsiTunnelBuilder.setLeafInformationRequired(true);
+        pmsiTunnelBuilder.setMplsLabel(MPLS_LABEL);
+        pmsiTunnelBuilder.setTunnelIdentifier(buildMldpP2mpLsp(IPV6, Ipv6AddressFamily.class, createOpaqueList()));
+        return buildAttribute(pmsiTunnelBuilder);
+    }
+
+    static Attributes buildMLDPP2MPLSPL2vpnAttribute() {
+        final PmsiTunnelBuilder pmsiTunnelBuilder = getPmsiTunnelBuilder();
+        pmsiTunnelBuilder.setTunnelIdentifier(buildMldpP2mpLsp(P_ADDRESS, L2vpnAddressFamily.class, createOpaqueList()));
+        return buildAttribute(pmsiTunnelBuilder);
+    }
+
+    private static TunnelIdentifier buildMldpP2mpLsp(final IpAddress pAddress, final Class<? extends AddressFamily> family, final List<OpaqueValue> opaqueList) {
+        return new MldpP2mpLspBuilder().setMldpP2mpLsp(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml
+            .ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.mldp.p2mp.lsp.MldpP2mpLspBuilder()
+            .setRootNodeAddress(pAddress).setAddressFamily(family).setOpaqueValue(opaqueList).build()).build();
+    }
+
+    static Attributes buildRSVPTEP2MPLSPLSPAttribute() {
+        final PmsiTunnelBuilder pmsiTunnelBuilder = getPmsiTunnelBuilder();
+        pmsiTunnelBuilder.setTunnelIdentifier(new RsvpTeP2mpLspBuilder().setRsvpTeP2mpLps(new org.opendaylight.yang.gen.v1.urn.opendaylight.params
+            .xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.rsvp.te.p2mp.lsp.RsvpTeP2mpLpsBuilder()
+            .setP2mpId(3458L).setTunnelId(15).setExtendedTunnelId(P_ADDRESS).build()).build());
+        return buildAttribute(pmsiTunnelBuilder);
+    }
+
+    static Attributes buildINGRESSREPLICATIONAttribute() {
+        final PmsiTunnelBuilder pmsiTunnelBuilder = getPmsiTunnelBuilder();
+        pmsiTunnelBuilder.setTunnelIdentifier(new IngressReplicationBuilder().setIngressReplication(new org.opendaylight.yang.gen.v1.urn
+            .opendaylight.params.xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.ingress.replication.IngressReplicationBuilder()
+            .setReceivingEndpointAddress(P_ADDRESS).build()).build());
+        return buildAttribute(pmsiTunnelBuilder);
+    }
+
+    static Attributes buildMLDPMP2MPLSPWrongAttribute() {
+        final PmsiTunnelBuilder pmsiTunnelBuilder = getPmsiTunnelBuilder();
+        pmsiTunnelBuilder.setTunnelIdentifier(new MldpMp2mpLspBuilder().setMldpMp2mpLsp(new org.opendaylight.yang.gen.v1.urn.opendaylight.params
+            .xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.mldp.mp2mp.lsp
+            .MldpMp2mpLspBuilder().setOpaque(OPAQUE_TEST).setOpaqueType(NO_SUPPORTED_OPAQUE).build()).build());
+        return buildAttribute(pmsiTunnelBuilder);
+    }
+
+    static Attributes buildMLDPMP2MPLSPAttribute() {
+        final PmsiTunnelBuilder pmsiTunnelBuilder = getPmsiTunnelBuilder();
+        pmsiTunnelBuilder.setTunnelIdentifier(new MldpMp2mpLspBuilder().setMldpMp2mpLsp(new org.opendaylight.yang.gen.v1.urn.opendaylight.params
+            .xml.ns.yang.pmsi.tunnel.rev160812.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.mldp.mp2mp.lsp
+            .MldpMp2mpLspBuilder().setOpaque(OPAQUE_TEST).setOpaqueType(OpaqueUtil.GENERIC_LSP_IDENTIFIER).build()).build());
+        return buildAttribute(pmsiTunnelBuilder);
+    }
+
+    private static List<OpaqueValue> createOpaqueList() {
+        final List<OpaqueValue> opaqueValues = new ArrayList<>();
+        opaqueValues.add(new OpaqueValueBuilder().setOpaque(OPAQUE_TEST).setOpaqueType(OpaqueUtil.GENERIC_LSP_IDENTIFIER).build());
+        opaqueValues.add(new OpaqueValueBuilder().setOpaque(OPAQUE_TEST2).setOpaqueType((short) 2).setOpaqueType(OpaqueUtil.EXTENDED_TYPE)
+            .setOpaqueExtendedType(4).build());
+        return opaqueValues;
+    }
+
+    static Attributes buildWOTunnelInfAttribute() {
+        final PmsiTunnelBuilder pmsiTunnelBuilder = getPmsiTunnelBuilder();
+        return buildAttribute(pmsiTunnelBuilder);
+    }
+}