MVPN Attributes Handlers 66/71966/1
authorClaudio D. Gasparini <claudio.gasparini@pantheon.tech>
Fri, 11 May 2018 10:19:36 +0000 (12:19 +0200)
committerClaudio D. Gasparini <claudio.gasparini@pantheon.tech>
Fri, 11 May 2018 10:20:10 +0000 (12:20 +0200)
- PMSI Tunnel Attributes
- PE Distinguisher Labels

JIRA: BGPCEP-396
Change-Id: I243f325260a46c16f6f9412282b83b8f415b0ea2
Signed-off-by: Claudio D. Gasparini <claudio.gasparini@pantheon.tech>
24 files changed:
bgp/mvpn/pom.xml
bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/BGPActivator.java
bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/TunnelIdentifierActivator.java [new file with mode: 0644]
bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/OpaqueUtil.java [new file with mode: 0644]
bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/PEDistinguisherLabelsAttributeHandler.java [new file with mode: 0644]
bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/PMSITunnelAttributeHandler.java [new file with mode: 0644]
bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/tunnel/identifier/BidirPimTreeParser.java [new file with mode: 0644]
bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/tunnel/identifier/IngressReplicationParser.java [new file with mode: 0644]
bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/tunnel/identifier/MldpMp2mpLspParser.java [new file with mode: 0644]
bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/tunnel/identifier/MldpP2mpLspParser.java [new file with mode: 0644]
bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/tunnel/identifier/PAddressPMulticastGroupUtil.java [new file with mode: 0644]
bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/tunnel/identifier/PimSmTreeParser.java [new file with mode: 0644]
bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/tunnel/identifier/PimSsmTreeParser.java [new file with mode: 0644]
bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/tunnel/identifier/RsvpTeP2MpLspParser.java [new file with mode: 0644]
bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/spi/attributes/tunnel/identifier/AbstractTunnelIdentifier.java [new file with mode: 0644]
bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/spi/attributes/tunnel/identifier/TunnelIdentifierParser.java [new file with mode: 0644]
bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/spi/attributes/tunnel/identifier/TunnelIdentifierSerializer.java [new file with mode: 0644]
bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/spi/pojo/attributes/tunnel/identifier/SimpleTunnelIdentifierRegistry.java [new file with mode: 0644]
bgp/mvpn/src/main/yang/pmsi-tunnel.yang
bgp/mvpn/src/test/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/PEDistinguisherLabelsAttributeHandlerTest.java [new file with mode: 0644]
bgp/mvpn/src/test/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/PMSITunnelAttributeHandlerTest.java [new file with mode: 0644]
bgp/mvpn/src/test/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/PMSITunnelAttributeHandlerTestUtil.java [new file with mode: 0644]
bgp/mvpn/src/test/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/tunnel/identifier/OpaqueUtilTest.java [new file with mode: 0644]
bgp/mvpn/src/test/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/tunnel/identifier/PAddressPMulticastGroupUtilTest.java [new file with mode: 0644]

index d90356ee85e7a3d7670d293ad46f755f966c9788..82138008bedf88b53255bd1ac6297fc7d54ebc24 100644 (file)
             <groupId>${project.groupId}</groupId>
             <artifactId>bgp-rib-spi</artifactId>
         </dependency>
+        <!-- test scope dependencies -->
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>bgp-parser-impl</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <scm>
index 3dcd24590c776970b4df86ef1c521fc4be8d0f51..f27801336fb323de2b6c9f96daf5687c778ec2f0 100644 (file)
@@ -11,6 +11,8 @@ package org.opendaylight.protocol.bgp.mvpn.impl;
 import com.google.common.annotations.VisibleForTesting;
 import java.util.ArrayList;
 import java.util.List;
+import org.opendaylight.protocol.bgp.mvpn.impl.attributes.PEDistinguisherLabelsAttributeHandler;
+import org.opendaylight.protocol.bgp.mvpn.impl.attributes.PMSITunnelAttributeHandler;
 import org.opendaylight.protocol.bgp.mvpn.impl.attributes.extended.community.SourceAS4OctectHandler;
 import org.opendaylight.protocol.bgp.mvpn.impl.attributes.extended.community.SourceASHandler;
 import org.opendaylight.protocol.bgp.mvpn.impl.attributes.extended.community.VrfRouteImportHandler;
@@ -31,7 +33,14 @@ public final class BGPActivator extends AbstractBGPExtensionProviderActivator {
     private static void registerAttributesHandler(
             final BGPExtensionProviderContext context,
             final List<AutoCloseable> regs) {
-        //TODO
+        final PEDistinguisherLabelsAttributeHandler peDistHandler =
+                new PEDistinguisherLabelsAttributeHandler();
+        regs.add(context.registerAttributeParser(peDistHandler.getType(), peDistHandler));
+        regs.add(context.registerAttributeSerializer(peDistHandler.getClazz(), peDistHandler));
+
+        final PMSITunnelAttributeHandler pmsiParser = new PMSITunnelAttributeHandler();
+        regs.add(context.registerAttributeParser(pmsiParser.getType(), pmsiParser));
+        regs.add(context.registerAttributeSerializer(pmsiParser.getClazz(), pmsiParser));
     }
 
     private static void registerNlriHandler(
@@ -63,6 +72,7 @@ public final class BGPActivator extends AbstractBGPExtensionProviderActivator {
     @Override
     protected List<AutoCloseable> startImpl(final BGPExtensionProviderContext context) {
         final List<AutoCloseable> regs = new ArrayList<>();
+        TunnelIdentifierActivator.registerTunnelIdentifierHandlers(context, regs);
         registerNlriHandler(context, regs);
         registerExtendedCommunities(context, regs);
         registerAttributesHandler(context, regs);
diff --git a/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/TunnelIdentifierActivator.java b/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/TunnelIdentifierActivator.java
new file mode 100644 (file)
index 0000000..5be504c
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2018 AT&T Intellectual Property. 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.mvpn.impl;
+
+import java.util.List;
+import org.opendaylight.protocol.bgp.mvpn.impl.attributes.tunnel.identifier.BidirPimTreeParser;
+import org.opendaylight.protocol.bgp.mvpn.impl.attributes.tunnel.identifier.IngressReplicationParser;
+import org.opendaylight.protocol.bgp.mvpn.impl.attributes.tunnel.identifier.MldpMp2mpLspParser;
+import org.opendaylight.protocol.bgp.mvpn.impl.attributes.tunnel.identifier.MldpP2mpLspParser;
+import org.opendaylight.protocol.bgp.mvpn.impl.attributes.tunnel.identifier.PimSmTreeParser;
+import org.opendaylight.protocol.bgp.mvpn.impl.attributes.tunnel.identifier.PimSsmTreeParser;
+import org.opendaylight.protocol.bgp.mvpn.impl.attributes.tunnel.identifier.RsvpTeP2MpLspParser;
+import org.opendaylight.protocol.bgp.mvpn.spi.pojo.attributes.tunnel.identifier.SimpleTunnelIdentifierRegistry;
+import org.opendaylight.protocol.bgp.parser.spi.BGPExtensionProviderContext;
+
+/**
+ * Tunnel Identifier PMSI handlers Activator.
+ *
+ * @author Claudio D. Gasparini
+ */
+final class TunnelIdentifierActivator {
+    private TunnelIdentifierActivator() {
+        throw new UnsupportedOperationException();
+    }
+
+    static void registerTunnelIdentifierHandlers(
+            final BGPExtensionProviderContext context,
+            final List<AutoCloseable> regs) {
+        final SimpleTunnelIdentifierRegistry tunnelIdentifierReg = SimpleTunnelIdentifierRegistry.getInstance();
+
+        final RsvpTeP2MpLspParser rsvpTeP2MpLspParser = new RsvpTeP2MpLspParser();
+        regs.add(tunnelIdentifierReg.registerParser(rsvpTeP2MpLspParser));
+        regs.add(tunnelIdentifierReg.registerSerializer(rsvpTeP2MpLspParser));
+
+        final MldpP2mpLspParser mldpP2mpLspParser = new MldpP2mpLspParser(context.getAddressFamilyRegistry());
+        regs.add(tunnelIdentifierReg.registerParser(mldpP2mpLspParser));
+        regs.add(tunnelIdentifierReg.registerSerializer(mldpP2mpLspParser));
+
+        final PimSsmTreeParser pimSsmTreeParser = new PimSsmTreeParser();
+        regs.add(tunnelIdentifierReg.registerParser(pimSsmTreeParser));
+        regs.add(tunnelIdentifierReg.registerSerializer(pimSsmTreeParser));
+
+        final PimSmTreeParser pimSmTreeParser = new PimSmTreeParser();
+        regs.add(tunnelIdentifierReg.registerParser(pimSmTreeParser));
+        regs.add(tunnelIdentifierReg.registerSerializer(pimSmTreeParser));
+
+        final BidirPimTreeParser bidirPimTreeParser = new BidirPimTreeParser();
+        regs.add(tunnelIdentifierReg.registerParser(bidirPimTreeParser));
+        regs.add(tunnelIdentifierReg.registerSerializer(bidirPimTreeParser));
+
+        final IngressReplicationParser ingressReplicationParser = new IngressReplicationParser();
+        regs.add(tunnelIdentifierReg.registerParser(ingressReplicationParser));
+        regs.add(tunnelIdentifierReg.registerSerializer(ingressReplicationParser));
+
+        final MldpMp2mpLspParser mldpMp2mpLspParser = new MldpMp2mpLspParser();
+        regs.add(tunnelIdentifierReg.registerParser(mldpMp2mpLspParser));
+        regs.add(tunnelIdentifierReg.registerSerializer(mldpMp2mpLspParser));
+    }
+}
diff --git a/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/OpaqueUtil.java b/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/OpaqueUtil.java
new file mode 100644 (file)
index 0000000..808482b
--- /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.mvpn.impl.attributes;
+
+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.rev180329.Opaque;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.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.rev180329.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.mldp.p2mp.lsp.mldp.p2mp.lsp.OpaqueValueBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class OpaqueUtil {
+    public static final short GENERIC_LSP_IDENTIFIER = 1;
+    public 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();
+    }
+
+    public 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);
+    }
+
+    public 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));
+    }
+
+    public 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;
+    }
+
+    public 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/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/PEDistinguisherLabelsAttributeHandler.java b/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/PEDistinguisherLabelsAttributeHandler.java
new file mode 100644 (file)
index 0000000..b975a9f
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2018 AT&T Intellectual Property. 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.mvpn.impl.attributes;
+
+import static org.opendaylight.protocol.bgp.parser.spi.AttributeUtil.formatAttribute;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import java.util.List;
+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.Ipv4Util;
+import org.opendaylight.protocol.util.Ipv6Util;
+import org.opendaylight.protocol.util.MplsLabelUtil;
+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.message.rev180329.path.attributes.Attributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.AttributesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.bgp.rib.route.PeDistinguisherLabelsAttributeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.bgp.rib.route.PeDistinguisherLabelsAttributeAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.pe.distinguisher.labels.attribute.PeDistinguisherLabelsAttribute;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.pe.distinguisher.labels.attribute.PeDistinguisherLabelsAttributeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.pe.distinguisher.labels.attribute.pe.distinguisher.labels.attribute.PeDistinguisherLabelAttribute;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.pe.distinguisher.labels.attribute.pe.distinguisher.labels.attribute.PeDistinguisherLabelAttributeBuilder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+
+/**
+ * PE Distinguisher Labels Attribute Handler.
+ * https://tools.ietf.org/html/rfc6514#section-8
+ *
+ * @author Claudio D. Gasparini
+ */
+public final class PEDistinguisherLabelsAttributeHandler implements AttributeParser, AttributeSerializer {
+
+    private static int TYPE = 27;
+
+    public PEDistinguisherLabelsAttributeHandler() {
+    }
+
+    @Override
+    public void parseAttribute(final ByteBuf buffer, final AttributesBuilder builder) {
+        if (!buffer.isReadable()) {
+            return;
+        }
+        final boolean isIpv4 = buffer.readableBytes() % 7 == 0;
+        final boolean isIpv6 = buffer.readableBytes() % 19 == 0;
+        Preconditions.checkArgument(isIpv4 || isIpv6,
+                "Length of byte array should be multiple of 7 or multiple of 19");
+
+        final List<PeDistinguisherLabelAttribute> list = Lists.newArrayList();
+        while (buffer.isReadable()) {
+            final PeDistinguisherLabelAttributeBuilder attribute = new PeDistinguisherLabelAttributeBuilder();
+            if (isIpv4) {
+                attribute.setPeAddress(new IpAddress(Ipv4Util.addressForByteBuf(buffer)));
+            } else {
+                attribute.setPeAddress(new IpAddress(Ipv6Util.addressForByteBuf(buffer)));
+            }
+            attribute.setMplsLabel(MplsLabelUtil.mplsLabelForByteBuf(buffer));
+            list.add(attribute.build());
+        }
+
+        builder.addAugmentation(PeDistinguisherLabelsAttributeAugmentation.class,
+                new PeDistinguisherLabelsAttributeAugmentationBuilder()
+                        .setPeDistinguisherLabelsAttribute(new PeDistinguisherLabelsAttributeBuilder()
+                                .setPeDistinguisherLabelAttribute(list).build()).build());
+    }
+
+    @Override
+    public void serializeAttribute(final DataObject attribute, final ByteBuf byteAggregator) {
+        Preconditions.checkArgument(attribute instanceof Attributes,
+                "Attribute parameter is not a PathAttribute object.");
+        final PeDistinguisherLabelsAttributeAugmentation ipv4Att =
+                ((Attributes) attribute).getAugmentation(PeDistinguisherLabelsAttributeAugmentation.class);
+
+        if (ipv4Att == null) {
+            return;
+        }
+
+        final List<PeDistinguisherLabelAttribute> distinguishers
+                = ipv4Att.getPeDistinguisherLabelsAttribute().getPeDistinguisherLabelAttribute();
+        final ByteBuf buffer = Unpooled.buffer();
+        for (final PeDistinguisherLabelAttribute peDist : distinguishers) {
+            if (peDist.getPeAddress().getIpv4Address() != null) {
+                buffer.writeBytes(Ipv4Util.bytesForAddress(peDist.getPeAddress().getIpv4Address()));
+            } else {
+                buffer.writeBytes(Ipv6Util.bytesForAddress(peDist.getPeAddress().getIpv6Address()));
+            }
+            buffer.writeBytes(MplsLabelUtil.byteBufForMplsLabel(peDist.getMplsLabel()));
+        }
+        formatAttribute(AttributeUtil.OPTIONAL | AttributeUtil.TRANSITIVE, TYPE, buffer, byteAggregator);
+    }
+
+    public int getType() {
+        return TYPE;
+    }
+
+    public Class<? extends DataObject> getClazz() {
+        return PeDistinguisherLabelsAttribute.class;
+    }
+}
diff --git a/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/PMSITunnelAttributeHandler.java b/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/PMSITunnelAttributeHandler.java
new file mode 100644 (file)
index 0000000..b39e0b2
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2018 AT&T Intellectual Property. 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.mvpn.impl.attributes;
+
+import com.google.common.base.Preconditions;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import org.opendaylight.protocol.bgp.mvpn.spi.pojo.attributes.tunnel.identifier.SimpleTunnelIdentifierRegistry;
+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.message.rev180329.path.attributes.Attributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.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.rev180329.bgp.rib.route.PmsiTunnelAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.bgp.rib.route.PmsiTunnelAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.PmsiTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.PmsiTunnelBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi.tunnel.TunnelIdentifier;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+
+/**
+ * PE Distinguisher Labels Attribute Handler.
+ * https://tools.ietf.org/html/rfc6514#section-5
+ *
+ * @author Claudio D. Gasparini
+ */
+public final class PMSITunnelAttributeHandler implements AttributeParser, AttributeSerializer {
+    private static final int PMSI_ATTRIBUTE = 22;
+    private static final int MPLS_LENGTH = 3;
+    private final SimpleTunnelIdentifierRegistry tunnelIdentifierHandler =
+            SimpleTunnelIdentifierRegistry.getInstance();
+
+    private static void parseMpls(final PmsiTunnelBuilder pmsiTunnelBuilder, final ByteBuf buffer) {
+        final MplsLabel mpls = MplsLabelUtil.mplsLabelForByteBuf(buffer);
+        if (mpls.getValue() != 0) {
+            pmsiTunnelBuilder.setMplsLabel(mpls);
+        }
+    }
+
+    private static void serializeMpls(final MplsLabel mplsLabel, final ByteBuf body) {
+        if (mplsLabel == null) {
+            body.writeZero(MPLS_LENGTH);
+            return;
+        }
+        body.writeBytes(MplsLabelUtil.byteBufForMplsLabel(mplsLabel));
+    }
+
+    private static void serializeFlag(final PmsiTunnel pmsiTunnelAttribute, final ByteBuf body) {
+        body.writeBoolean(pmsiTunnelAttribute.isLeafInformationRequired());
+    }
+
+    @Override
+    public void parseAttribute(final ByteBuf buffer, 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());
+    }
+
+    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);
+    }
+
+    public Class<? extends DataObject> getClazz() {
+        return org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.PmsiTunnel.class;
+    }
+}
diff --git a/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/tunnel/identifier/BidirPimTreeParser.java b/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/tunnel/identifier/BidirPimTreeParser.java
new file mode 100644 (file)
index 0000000..5c4e7b9
--- /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.mvpn.impl.attributes.tunnel.identifier;
+
+import io.netty.buffer.ByteBuf;
+import org.opendaylight.protocol.bgp.mvpn.spi.attributes.tunnel.identifier.AbstractTunnelIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.PmsiTunnelType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi.tunnel.TunnelIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.BidirPimTree;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.BidirPimTreeBuilder;
+
+public final class BidirPimTreeParser extends AbstractTunnelIdentifier<BidirPimTree> {
+    public int getType() {
+        return PmsiTunnelType.BidirPimTree.getIntValue();
+    }
+
+    @Override
+    public int serialize(final BidirPimTree tunnelIdentifier, final ByteBuf buffer) {
+        PAddressPMulticastGroupUtil.serializeSenderPMulticastGroup(tunnelIdentifier.getBidirPimTree(), buffer);
+        return PmsiTunnelType.BidirPimTree.getIntValue();
+    }
+
+    @Override
+    public Class<? extends TunnelIdentifier> getClazz() {
+        return BidirPimTree.class;
+    }
+
+    @Override
+    public BidirPimTree parse(final ByteBuf buffer) {
+        final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.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.rev180329.pmsi.tunnel
+                        .pmsi.tunnel.tunnel.identifier.bidir.pim.tree.BidirPimTreeBuilder(PAddressPMulticastGroupUtil
+                        .parseSenderPMulticastGroup(buffer));
+        return new BidirPimTreeBuilder().setBidirPimTree(bidirPimTree.build()).build();
+    }
+}
diff --git a/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/tunnel/identifier/IngressReplicationParser.java b/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/tunnel/identifier/IngressReplicationParser.java
new file mode 100644 (file)
index 0000000..ab24903
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * 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.mvpn.impl.attributes.tunnel.identifier;
+
+import static org.opendaylight.protocol.bgp.mvpn.impl.attributes.tunnel.identifier.PAddressPMulticastGroupUtil.parseIpAddress;
+import static org.opendaylight.protocol.bgp.mvpn.impl.attributes.tunnel.identifier.PAddressPMulticastGroupUtil.serializeIpAddress;
+
+import io.netty.buffer.ByteBuf;
+import org.opendaylight.protocol.bgp.mvpn.spi.attributes.tunnel.identifier.AbstractTunnelIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.PmsiTunnelType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi.tunnel.TunnelIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.IngressReplication;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.IngressReplicationBuilder;
+
+public final class IngressReplicationParser extends AbstractTunnelIdentifier<IngressReplication> {
+    @Override
+    public int serialize(final IngressReplication tunnelIdentifier, final ByteBuf buffer) {
+        final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi
+                .tunnel.tunnel.identifier.ingress.replication.IngressReplication ingressReplication =
+                tunnelIdentifier.getIngressReplication();
+        serializeIpAddress(ingressReplication.getReceivingEndpointAddress(), buffer);
+        return getType();
+    }
+
+    @Override
+    public Class<? extends TunnelIdentifier> getClazz() {
+        return IngressReplication.class;
+    }
+
+    @Override
+    public IngressReplication parse(final ByteBuf buffer) {
+        final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi
+                .tunnel.tunnel.identifier.ingress.replication.IngressReplication builder =
+                new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel
+                        .pmsi.tunnel.tunnel.identifier.ingress.replication.IngressReplicationBuilder()
+                        .setReceivingEndpointAddress(parseIpAddress(buffer.readableBytes(), buffer)).build();
+        return new IngressReplicationBuilder().setIngressReplication(builder).build();
+    }
+
+    @Override
+    public int getType() {
+        return PmsiTunnelType.IngressReplication.getIntValue();
+    }
+}
diff --git a/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/tunnel/identifier/MldpMp2mpLspParser.java b/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/tunnel/identifier/MldpMp2mpLspParser.java
new file mode 100644 (file)
index 0000000..8f5a27c
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * 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.mvpn.impl.attributes.tunnel.identifier;
+
+import static org.opendaylight.protocol.bgp.mvpn.spi.pojo.attributes.tunnel.identifier.SimpleTunnelIdentifierRegistry.NO_TUNNEL_INFORMATION_PRESENT;
+
+import io.netty.buffer.ByteBuf;
+import org.opendaylight.protocol.bgp.mvpn.impl.attributes.OpaqueUtil;
+import org.opendaylight.protocol.bgp.mvpn.spi.attributes.tunnel.identifier.AbstractTunnelIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.Opaque;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.PmsiTunnelType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi.tunnel.TunnelIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.MldpMp2mpLsp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.MldpMp2mpLspBuilder;
+
+public final class MldpMp2mpLspParser extends AbstractTunnelIdentifier<MldpMp2mpLsp> {
+    @Override
+    public int serialize(final MldpMp2mpLsp tunnelIdentifier, final ByteBuf buffer) {
+        final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi
+                .tunnel.tunnel.identifier.mldp.mp2mp.lsp.MldpMp2mpLsp mldpMp2mpLsp =
+                tunnelIdentifier.getMldpMp2mpLsp();
+        if (!OpaqueUtil.serializeOpaque(mldpMp2mpLsp, buffer)) {
+            return NO_TUNNEL_INFORMATION_PRESENT;
+        }
+        return getType();
+    }
+
+    @Override
+    public Class<? extends TunnelIdentifier> getClazz() {
+        return MldpMp2mpLsp.class;
+    }
+
+    @Override
+    public MldpMp2mpLsp 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.rev180329.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.rev180329.pmsi.tunnel
+                        .pmsi.tunnel.tunnel.identifier.mldp.mp2mp.lsp.MldpMp2mpLspBuilder(opaque).build();
+        return new MldpMp2mpLspBuilder().setMldpMp2mpLsp(mldpMp2mpLsp).build();
+    }
+
+    @Override
+    public int getType() {
+        return PmsiTunnelType.MldpMp2mpLsp.getIntValue();
+    }
+}
diff --git a/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/tunnel/identifier/MldpP2mpLspParser.java b/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/tunnel/identifier/MldpP2mpLspParser.java
new file mode 100644 (file)
index 0000000..c6e50e0
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * 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.mvpn.impl.attributes.tunnel.identifier;
+
+import static org.opendaylight.protocol.bgp.mvpn.impl.attributes.OpaqueUtil.serializeOpaqueList;
+import static org.opendaylight.protocol.bgp.mvpn.impl.attributes.tunnel.identifier.PAddressPMulticastGroupUtil.parseIpAddress;
+import static org.opendaylight.protocol.bgp.mvpn.impl.attributes.tunnel.identifier.PAddressPMulticastGroupUtil.serializeIpAddress;
+import static org.opendaylight.protocol.bgp.mvpn.spi.pojo.attributes.tunnel.identifier.SimpleTunnelIdentifierRegistry.NO_TUNNEL_INFORMATION_PRESENT;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufUtil;
+import io.netty.buffer.Unpooled;
+import org.opendaylight.protocol.bgp.mvpn.impl.attributes.OpaqueUtil;
+import org.opendaylight.protocol.bgp.mvpn.spi.attributes.tunnel.identifier.AbstractTunnelIdentifier;
+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.rev180329.AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.PmsiTunnelType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi.tunnel.TunnelIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.MldpP2mpLsp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.MldpP2mpLspBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class MldpP2mpLspParser extends AbstractTunnelIdentifier<MldpP2mpLsp> {
+    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;
+
+    public MldpP2mpLspParser(final AddressFamilyRegistry addressFamilyRegistry) {
+        this.addressFamilyRegistry = addressFamilyRegistry;
+    }
+
+    @Override
+    public int serialize(final MldpP2mpLsp tunnelIdentifier, final ByteBuf buffer) {
+        final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi
+                .tunnel.tunnel.identifier.mldp.p2mp.lsp.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 getType();
+    }
+
+    @Override
+    public Class<? extends TunnelIdentifier> getClazz() {
+        return MldpP2mpLsp.class;
+    }
+
+    @Override
+    public int getType() {
+        return PmsiTunnelType.MldpP2mpLsp.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 MldpP2mpLsp parse(final ByteBuf buffer) {
+        final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.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.rev180329.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/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/tunnel/identifier/PAddressPMulticastGroupUtil.java b/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/tunnel/identifier/PAddressPMulticastGroupUtil.java
new file mode 100644 (file)
index 0000000..773e341
--- /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.mvpn.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.rev180329.PAddressPMulticastGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.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/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/tunnel/identifier/PimSmTreeParser.java b/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/tunnel/identifier/PimSmTreeParser.java
new file mode 100644 (file)
index 0000000..ddcd1c0
--- /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.mvpn.impl.attributes.tunnel.identifier;
+
+import io.netty.buffer.ByteBuf;
+import org.opendaylight.protocol.bgp.mvpn.spi.attributes.tunnel.identifier.AbstractTunnelIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.PmsiTunnelType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi.tunnel.TunnelIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.PimSmTree;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.PimSmTreeBuilder;
+
+public final class PimSmTreeParser extends AbstractTunnelIdentifier<PimSmTree> {
+    @Override
+    public int serialize(final PimSmTree tunnelIdentifier, final ByteBuf buffer) {
+        PAddressPMulticastGroupUtil.serializeSenderPMulticastGroup(tunnelIdentifier
+                .getPimSmTree(), buffer);
+        return getType();
+    }
+
+    @Override
+    public Class<? extends TunnelIdentifier> getClazz() {
+        return PimSmTree.class;
+    }
+
+    @Override
+    public PimSmTree parse(final ByteBuf buffer) {
+        final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.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.rev180329.pmsi.tunnel
+                        .pmsi.tunnel.tunnel.identifier.pim.sm.tree.PimSmTreeBuilder(PAddressPMulticastGroupUtil
+                        .parseSenderPMulticastGroup(buffer));
+        return new PimSmTreeBuilder().setPimSmTree(pimSmTree.build()).build();
+    }
+
+    @Override
+    public int getType() {
+        return PmsiTunnelType.PimSmTree.getIntValue();
+    }
+}
diff --git a/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/tunnel/identifier/PimSsmTreeParser.java b/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/tunnel/identifier/PimSsmTreeParser.java
new file mode 100644 (file)
index 0000000..36aac32
--- /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.mvpn.impl.attributes.tunnel.identifier;
+
+import io.netty.buffer.ByteBuf;
+import org.opendaylight.protocol.bgp.mvpn.spi.attributes.tunnel.identifier.AbstractTunnelIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.PmsiTunnelType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi.tunnel.TunnelIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.PimSsmTree;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.PimSsmTreeBuilder;
+
+public final class PimSsmTreeParser extends AbstractTunnelIdentifier<PimSsmTree> {
+    @Override
+    public int serialize(final PimSsmTree tunnelIdentifier, final ByteBuf buffer) {
+        PAddressPMulticastGroupUtil
+                .serializeSenderPMulticastGroup(tunnelIdentifier.getPimSsmTree(), buffer);
+        return getType();
+    }
+
+    @Override
+    public Class<? extends TunnelIdentifier> getClazz() {
+        return PimSsmTree.class;
+    }
+
+    @Override
+    public PimSsmTree parse(final ByteBuf buffer) {
+        final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.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.rev180329.pmsi.tunnel
+                        .pmsi.tunnel.tunnel.identifier.pim.ssm.tree.PimSsmTreeBuilder(PAddressPMulticastGroupUtil
+                        .parseSenderPMulticastGroup(buffer));
+        return new PimSsmTreeBuilder().setPimSsmTree(pimSsmTree.build()).build();
+    }
+
+    @Override
+    public int getType() {
+        return PmsiTunnelType.PimSsmTree.getIntValue();
+    }
+}
diff --git a/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/tunnel/identifier/RsvpTeP2MpLspParser.java b/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/tunnel/identifier/RsvpTeP2MpLspParser.java
new file mode 100644 (file)
index 0000000..2927b88
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * 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.mvpn.impl.attributes.tunnel.identifier;
+
+import static org.opendaylight.protocol.bgp.mvpn.impl.attributes.tunnel.identifier.PAddressPMulticastGroupUtil.parseIpAddress;
+import static org.opendaylight.protocol.bgp.mvpn.impl.attributes.tunnel.identifier.PAddressPMulticastGroupUtil.serializeIpAddress;
+
+import io.netty.buffer.ByteBuf;
+import org.opendaylight.protocol.bgp.mvpn.spi.attributes.tunnel.identifier.AbstractTunnelIdentifier;
+import org.opendaylight.protocol.util.ByteBufWriteUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.PmsiTunnelType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi.tunnel.TunnelIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.RsvpTeP2mpLsp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.RsvpTeP2mpLspBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.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.rev180329.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.rsvp.te.p2mp.lsp.RsvpTeP2mpLpsBuilder;
+
+public final class RsvpTeP2MpLspParser extends AbstractTunnelIdentifier<RsvpTeP2mpLsp> {
+
+    private static final int RESERVED = 2;
+
+    @Override
+    public Class<? extends TunnelIdentifier> getClazz() {
+        return RsvpTeP2mpLsp.class;
+    }
+
+    @Override
+    public int serialize(final RsvpTeP2mpLsp tunnelIdentifier, final ByteBuf buffer) {
+        final RsvpTeP2mpLps rsvpTeP2mpLsp = tunnelIdentifier.getRsvpTeP2mpLps();
+        ByteBufWriteUtil.writeUnsignedInt(rsvpTeP2mpLsp.getP2mpId(), buffer);
+        buffer.writeZero(RESERVED);
+        ByteBufWriteUtil.writeUnsignedShort(rsvpTeP2mpLsp.getTunnelId(), buffer);
+        serializeIpAddress(rsvpTeP2mpLsp.getExtendedTunnelId(), buffer);
+        return getType();
+    }
+
+    @Override
+    public RsvpTeP2mpLsp 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();
+    }
+
+    @Override
+    public int getType() {
+        return PmsiTunnelType.RsvpTeP2mpLps.getIntValue();
+    }
+}
diff --git a/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/spi/attributes/tunnel/identifier/AbstractTunnelIdentifier.java b/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/spi/attributes/tunnel/identifier/AbstractTunnelIdentifier.java
new file mode 100644 (file)
index 0000000..306446d
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2018 AT&T Intellectual Property. 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.mvpn.spi.attributes.tunnel.identifier;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi.tunnel.TunnelIdentifier;
+
+/**
+ * Common Abstract Tunnel Identifier.
+ * @author Claudio D. Gasparini
+ */
+public abstract class AbstractTunnelIdentifier<T extends TunnelIdentifier>
+        implements TunnelIdentifierSerializer<T>, TunnelIdentifierParser<T> {
+}
diff --git a/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/spi/attributes/tunnel/identifier/TunnelIdentifierParser.java b/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/spi/attributes/tunnel/identifier/TunnelIdentifierParser.java
new file mode 100644 (file)
index 0000000..74e9a9a
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * 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.mvpn.spi.attributes.tunnel.identifier;
+
+import io.netty.buffer.ByteBuf;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi.tunnel.TunnelIdentifier;
+
+public interface TunnelIdentifierParser<T extends TunnelIdentifier> {
+    /**
+     * Parse Tunnel Identifier from buffer.
+     *
+     * @param buffer Encoded Tunnel Identifier in ByteBuf.
+     * @return Parsed Tunnel Identifier body
+     */
+    @Nullable
+    T parse(@Nonnull ByteBuf buffer);
+
+    int getType();
+}
diff --git a/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/spi/attributes/tunnel/identifier/TunnelIdentifierSerializer.java b/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/spi/attributes/tunnel/identifier/TunnelIdentifierSerializer.java
new file mode 100644 (file)
index 0000000..14db242
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * 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.mvpn.spi.attributes.tunnel.identifier;
+
+import io.netty.buffer.ByteBuf;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi.tunnel.TunnelIdentifier;
+
+public interface TunnelIdentifierSerializer<T extends TunnelIdentifier> {
+    /**
+     * Serialize tunnel identifier.
+     *
+     * @param tunnelIdentifier Tunnel Identifier body
+     * @param buffer           Encoded Tunnel Identifier in ByteBuf
+     * @return Tunnel identifier Type
+     */
+    int serialize(@Nonnull T tunnelIdentifier, @Nonnull ByteBuf buffer);
+
+    Class<? extends TunnelIdentifier> getClazz();
+}
diff --git a/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/spi/pojo/attributes/tunnel/identifier/SimpleTunnelIdentifierRegistry.java b/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/spi/pojo/attributes/tunnel/identifier/SimpleTunnelIdentifierRegistry.java
new file mode 100644 (file)
index 0000000..7eaec04
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * 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.mvpn.spi.pojo.attributes.tunnel.identifier;
+
+import io.netty.buffer.ByteBuf;
+import org.opendaylight.protocol.bgp.mvpn.spi.attributes.tunnel.identifier.TunnelIdentifierParser;
+import org.opendaylight.protocol.bgp.mvpn.spi.attributes.tunnel.identifier.TunnelIdentifierSerializer;
+import org.opendaylight.protocol.concepts.AbstractRegistration;
+import org.opendaylight.protocol.concepts.HandlerRegistry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi.tunnel.TunnelIdentifier;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class SimpleTunnelIdentifierRegistry {
+    public static final int NO_TUNNEL_INFORMATION_PRESENT = 0;
+    private static final SimpleTunnelIdentifierRegistry SINGLETON = new SimpleTunnelIdentifierRegistry();
+    private static final Logger LOG = LoggerFactory.getLogger(SimpleTunnelIdentifierRegistry.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<>();
+
+    private SimpleTunnelIdentifierRegistry() {
+    }
+
+    public static SimpleTunnelIdentifierRegistry getInstance() {
+        return SINGLETON;
+    }
+
+    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);
+    }
+
+    public AbstractRegistration registerParser(final TunnelIdentifierParser parser) {
+        return this.handlers.registerParser(parser.getType(), parser);
+    }
+
+    public AbstractRegistration registerSerializer(final TunnelIdentifierSerializer serializer) {
+        return this.handlers.registerSerializer(serializer.getClazz(), serializer);
+    }
+}
index cc7d69c9ab4fea88c88d346d591d1da436025cde..90fb72675f3c14c1ff7ea128ccbdc69cf5d71d49 100644 (file)
@@ -36,6 +36,32 @@ module pmsi-tunnel {
         reference "https://tools.ietf.org/html/rfc6514#section-5";
     }
 
+    typedef pmsi-tunnel-type {
+        type enumeration {
+            enum rsvp-te-p2mp-lps {
+                value 1;
+            }
+            enum mldp-p2mp-lsp {
+                value 2;
+            }
+            enum pim-ssm-tree {
+                value 3;
+            }
+            enum pim-sm-tree {
+                value 4;
+            }
+            enum bidir-pim-tree {
+                value 5;
+            }
+            enum ingress-replication {
+                value 6;
+            }
+            enum mldp-mp2mp-lsp {
+                value 7;
+            }
+        }
+    }
+
     grouping opaque {
         leaf opaque-type {
             mandatory true;
diff --git a/bgp/mvpn/src/test/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/PEDistinguisherLabelsAttributeHandlerTest.java b/bgp/mvpn/src/test/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/PEDistinguisherLabelsAttributeHandlerTest.java
new file mode 100644 (file)
index 0000000..2da2c84
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2018 AT&T Intellectual Property. 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.mvpn.impl.attributes;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.mvpn.impl.BGPActivator;
+import org.opendaylight.protocol.bgp.parser.spi.AttributeRegistry;
+import org.opendaylight.protocol.bgp.parser.spi.BGPExtensionProviderContext;
+import org.opendaylight.protocol.bgp.parser.spi.pojo.SimpleBGPExtensionProviderContext;
+import org.opendaylight.protocol.util.ByteArray;
+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.message.rev180329.path.attributes.Attributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.AttributesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.bgp.rib.route.PeDistinguisherLabelsAttributeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.bgp.rib.route.PeDistinguisherLabelsAttributeAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.pe.distinguisher.labels.attribute.PeDistinguisherLabelsAttributeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.pe.distinguisher.labels.attribute.pe.distinguisher.labels.attribute.PeDistinguisherLabelAttribute;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.pe.distinguisher.labels.attribute.pe.distinguisher.labels.attribute.PeDistinguisherLabelAttributeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.MplsLabel;
+
+public class PEDistinguisherLabelsAttributeHandlerTest {
+    /**
+     * ATT - TYPE - ATT LENGTH.
+     * PE ADDRESS - MPLS LABEL
+     * PE ADDRESS - MPLS LABEL
+     */
+    private static final byte[] PE_DISTINGUISHER_LABELS = {
+        (byte) 0xC0, (byte) 0x1B, (byte) 0x0e,
+        (byte) 0x7F, (byte) 0x00, (byte) 0x00, (byte) 0x01,
+        (byte) 0x00, (byte) 0x00, (byte) 0x10,
+        (byte) 0x7F, (byte) 0x00, (byte) 0x00, (byte) 0x02,
+        (byte) 0x00, (byte) 0x00, (byte) 0x20,
+    };
+    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 testPEDistinguisherLabelsHandler() throws Exception {
+        final Attributes expected = buildPEDistinguisherLabelsAttributAttribute();
+        final ByteBuf actual = Unpooled.buffer();
+        this.handler.serializeAttribute(expected, actual);
+        assertArrayEquals(PE_DISTINGUISHER_LABELS, ByteArray.readAllBytes(actual));
+        final Attributes actualAttr = this.handler.parseAttributes(
+                Unpooled.wrappedBuffer(PE_DISTINGUISHER_LABELS), null);
+        assertEquals(expected, actualAttr);
+    }
+
+    private Attributes buildPEDistinguisherLabelsAttributAttribute() {
+        final List<PeDistinguisherLabelAttribute> peAtt = new ArrayList<>();
+
+        peAtt.add(new PeDistinguisherLabelAttributeBuilder()
+                .setPeAddress(new IpAddress(new Ipv4Address("127.0.0.1")))
+                .setMplsLabel(new MplsLabel(1L))
+                .build());
+        peAtt.add(new PeDistinguisherLabelAttributeBuilder()
+                .setPeAddress(new IpAddress(new Ipv4Address("127.0.0.2")))
+                .setMplsLabel(new MplsLabel(2L))
+                .build());
+        return new AttributesBuilder()
+                .setUnrecognizedAttributes(Collections.emptyList())
+                .addAugmentation(PeDistinguisherLabelsAttributeAugmentation.class,
+                        new PeDistinguisherLabelsAttributeAugmentationBuilder()
+                                .setPeDistinguisherLabelsAttribute(new PeDistinguisherLabelsAttributeBuilder()
+                                        .setPeDistinguisherLabelAttribute(peAtt).build()).build()).build();
+    }
+}
\ No newline at end of file
diff --git a/bgp/mvpn/src/test/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/PMSITunnelAttributeHandlerTest.java b/bgp/mvpn/src/test/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/PMSITunnelAttributeHandlerTest.java
new file mode 100644 (file)
index 0000000..0f268a0
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ * 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.mvpn.impl.attributes;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.opendaylight.protocol.bgp.mvpn.impl.attributes.PMSITunnelAttributeHandlerTestUtil.BIDIR_PIM_EXPECTED;
+import static org.opendaylight.protocol.bgp.mvpn.impl.attributes.PMSITunnelAttributeHandlerTestUtil.INGRESS_REPLICATION_EXPECTED;
+import static org.opendaylight.protocol.bgp.mvpn.impl.attributes.PMSITunnelAttributeHandlerTestUtil.M_LDP_MP_2_MP_LSP_EXPECTED;
+import static org.opendaylight.protocol.bgp.mvpn.impl.attributes.PMSITunnelAttributeHandlerTestUtil.M_LDP_MP_2_MP_LSP_WRONG;
+import static org.opendaylight.protocol.bgp.mvpn.impl.attributes.PMSITunnelAttributeHandlerTestUtil.M_LDP_P2MP_LSP_EXPECTED_IPV4;
+import static org.opendaylight.protocol.bgp.mvpn.impl.attributes.PMSITunnelAttributeHandlerTestUtil.M_LDP_P2MP_LSP_EXPECTED_IPV4_2;
+import static org.opendaylight.protocol.bgp.mvpn.impl.attributes.PMSITunnelAttributeHandlerTestUtil.M_LDP_P2MP_LSP_EXPECTED_IPV6;
+import static org.opendaylight.protocol.bgp.mvpn.impl.attributes.PMSITunnelAttributeHandlerTestUtil.M_LDP_P2MP_LSP_EXPECTED_L2VPN;
+import static org.opendaylight.protocol.bgp.mvpn.impl.attributes.PMSITunnelAttributeHandlerTestUtil.M_LDP_P2MP_LSP_EXPECTED_WRONG_FAMILY;
+import static org.opendaylight.protocol.bgp.mvpn.impl.attributes.PMSITunnelAttributeHandlerTestUtil.NO_TUNNEL_INFORMATION_PRESENT_EXPECTED;
+import static org.opendaylight.protocol.bgp.mvpn.impl.attributes.PMSITunnelAttributeHandlerTestUtil.PIM_SM_TREE_EXPECTED;
+import static org.opendaylight.protocol.bgp.mvpn.impl.attributes.PMSITunnelAttributeHandlerTestUtil.PIM_SSM_TREE_EXPECTED;
+import static org.opendaylight.protocol.bgp.mvpn.impl.attributes.PMSITunnelAttributeHandlerTestUtil.RSVP_TE_P2MP_LSP_LSP_EXPECTED;
+import static org.opendaylight.protocol.bgp.mvpn.impl.attributes.PMSITunnelAttributeHandlerTestUtil.buildBidirPimTreeAttribute;
+import static org.opendaylight.protocol.bgp.mvpn.impl.attributes.PMSITunnelAttributeHandlerTestUtil.buildIngressReplicationAttribute;
+import static org.opendaylight.protocol.bgp.mvpn.impl.attributes.PMSITunnelAttributeHandlerTestUtil.buildMLDpMp2mPLspAttribute;
+import static org.opendaylight.protocol.bgp.mvpn.impl.attributes.PMSITunnelAttributeHandlerTestUtil.buildMldpMP2mpLspWrongAttribute;
+import static org.opendaylight.protocol.bgp.mvpn.impl.attributes.PMSITunnelAttributeHandlerTestUtil.buildMldpP2mpLspIpv4Attribute;
+import static org.opendaylight.protocol.bgp.mvpn.impl.attributes.PMSITunnelAttributeHandlerTestUtil.buildMldpP2mpLspIpv6Attribute;
+import static org.opendaylight.protocol.bgp.mvpn.impl.attributes.PMSITunnelAttributeHandlerTestUtil.buildMldpp2MPLspL2vpnAttribute;
+import static org.opendaylight.protocol.bgp.mvpn.impl.attributes.PMSITunnelAttributeHandlerTestUtil.buildNoSupportedFamilyAttribute;
+import static org.opendaylight.protocol.bgp.mvpn.impl.attributes.PMSITunnelAttributeHandlerTestUtil.buildNoSupportedOpaqueAttribute;
+import static org.opendaylight.protocol.bgp.mvpn.impl.attributes.PMSITunnelAttributeHandlerTestUtil.buildPimSMTreeAttribute;
+import static org.opendaylight.protocol.bgp.mvpn.impl.attributes.PMSITunnelAttributeHandlerTestUtil.buildPimSSMTreeAttribute;
+import static org.opendaylight.protocol.bgp.mvpn.impl.attributes.PMSITunnelAttributeHandlerTestUtil.buildRsvpTep2MPLspAttribute;
+import static org.opendaylight.protocol.bgp.mvpn.impl.attributes.PMSITunnelAttributeHandlerTestUtil.buildWOTunnelInfAttribute;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.mvpn.impl.BGPActivator;
+import org.opendaylight.protocol.bgp.parser.spi.AttributeRegistry;
+import org.opendaylight.protocol.bgp.parser.spi.BGPExtensionProviderContext;
+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.rev180329.path.attributes.Attributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.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() {
+        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 Attributes expectedIpv4Att = buildMldpP2mpLspIpv4Attribute();
+        final ByteBuf actualIpv4 = Unpooled.buffer();
+        this.handler.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 = buildRsvpTep2MPLspAttribute();
+        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 testPMSITunnelAttributeParser() {
+        final PMSITunnelAttributeHandler pmsiHandler = new PMSITunnelAttributeHandler();
+        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/mvpn/src/test/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/PMSITunnelAttributeHandlerTestUtil.java b/bgp/mvpn/src/test/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/PMSITunnelAttributeHandlerTestUtil.java
new file mode 100644 (file)
index 0000000..52ccc3b
--- /dev/null
@@ -0,0 +1,421 @@
+/*
+ * 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.mvpn.impl.attributes;
+
+import static java.util.Collections.singletonList;
+
+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.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+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.bgp.message.rev180329.path.attributes.Attributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.AttributesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.Ipv4AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.Ipv6AddressFamily;
+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.rev180329.PAddressPMulticastGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.bgp.rib.route.PmsiTunnelAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.bgp.rib.route.PmsiTunnelAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.PmsiTunnelBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi.tunnel.TunnelIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.BidirPimTreeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.IngressReplicationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.MldpMp2mpLspBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.MldpP2mpLspBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.PimSmTreeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.PimSsmTreeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.RsvpTeP2mpLspBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.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.rev180329.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.mldp.p2mp.lsp.mldp.p2mp.lsp.OpaqueValueBuilder;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+
+final class PMSITunnelAttributeHandlerTestUtil {
+    private static final MplsLabel MPLS_LABEL = new MplsLabel(24001L);
+    /**
+     * ATT - TYPE - ATT LENGTH.
+     * PMSI FLAG - PMSI TYPE 0- MPLS LABEL
+     * No tunnel information present
+     */
+    static final 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
+     */
+    static final 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
+     */
+    static final 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
+     */
+    static final 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
+     */
+    static final 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) 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 IPV4
+     */
+    static final 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
+     */
+    static final 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
+     */
+    static final 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
+     */
+    static final 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
+     */
+    static final 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
+     */
+    static final 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
+     */
+    static final 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
+     */
+    static final 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
+    };
+    private static final IpAddress P_MULTICAST = new IpAddress(new Ipv4Address("23.1.1.1"));
+    private static final IpAddress IP_ADDRESS = new IpAddress(new Ipv4Address("1.1.1.1"));
+    private static final Short NO_SUPPORTED_OPAQUE = 200;
+    private static final short GENERIC_LSP_IDENTIFIER = 1;
+    private static final HexString OPAQUE_TEST = new HexString("07:00:0b:00:00:01:00:00:00:01:00:00:00:00");
+    private static final HexString OPAQUE_TEST2
+            = new HexString("07:00:0b:00:00:01:00:00:00:01:00:00:00:00:01:02");
+    private static final IpAddress IPV6 = new IpAddress(new Ipv6Address("2001::1"));
+    private static final short EXTENDED_TYPE = 255;
+
+    private PMSITunnelAttributeHandlerTestUtil() {
+        throw new UnsupportedOperationException();
+    }
+
+    private static PAddressPMulticastGroup buildPAddressPMulticastGroup() {
+        return new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel
+                .pmsi.tunnel.tunnel.identifier.bidir.pim.tree.BidirPimTreeBuilder()
+                .setPAddress(IP_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
+                        .rev180329.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.rev180329.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.rev180329.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 = singletonList(new OpaqueValueBuilder()
+                .setOpaque(OPAQUE_TEST).setOpaqueType(NO_SUPPORTED_OPAQUE).build());
+        pmsiTunnelBuilder.setTunnelIdentifier(buildMldpP2mpLsp(IP_ADDRESS, Ipv4AddressFamily.class, nonSupported));
+        return buildAttribute(pmsiTunnelBuilder);
+    }
+
+    static Attributes buildNoSupportedFamilyAttribute() {
+        final PmsiTunnelBuilder pmsiTunnelBuilder = getPmsiTunnelBuilder();
+        pmsiTunnelBuilder.setTunnelIdentifier(buildMldpP2mpLsp(IP_ADDRESS, NonSupportedAddressFamily.class,
+                createOpaqueList()));
+        return buildAttribute(pmsiTunnelBuilder);
+    }
+
+    static Attributes buildMldpP2mpLspIpv4Attribute() {
+        final PmsiTunnelBuilder pmsiTunnelBuilder = getPmsiTunnelBuilder();
+        pmsiTunnelBuilder.setTunnelIdentifier(
+                buildMldpP2mpLsp(IP_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(IP_ADDRESS, Ipv4AddressFamily.class, createOpaqueList()));
+        return buildAttribute(pmsiTunnelBuilder);
+    }
+
+    private static TunnelIdentifier buildMldpP2mpLsp(final IpAddress ipAddress,
+            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
+                        .rev180329.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.mldp.p2mp.lsp.MldpP2mpLspBuilder()
+                        .setRootNodeAddress(ipAddress).setAddressFamily(family).setOpaqueValue(opaqueList).build())
+                .build();
+    }
+
+    static Attributes buildRsvpTep2MPLspAttribute() {
+        final PmsiTunnelBuilder pmsiTunnelBuilder = getPmsiTunnelBuilder();
+        pmsiTunnelBuilder.setTunnelIdentifier(new RsvpTeP2mpLspBuilder()
+                .setRsvpTeP2mpLps(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel
+                        .rev180329.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.rsvp.te.p2mp.lsp.RsvpTeP2mpLpsBuilder()
+                        .setP2mpId(3458L).setTunnelId(15).setExtendedTunnelId(IP_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.rev180329.pmsi.tunnel.pmsi
+                .tunnel.tunnel.identifier.ingress.replication.IngressReplicationBuilder()
+                .setReceivingEndpointAddress(IP_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.rev180329.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.rev180329.pmsi.tunnel.pmsi.tunnel.tunnel
+                .identifier.mldp.mp2mp.lsp.MldpMp2mpLspBuilder().setOpaque(OPAQUE_TEST)
+                .setOpaqueType(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(GENERIC_LSP_IDENTIFIER).build());
+        opaqueValues.add(new OpaqueValueBuilder().setOpaque(OPAQUE_TEST2)
+                .setOpaqueType((short) 2).setOpaqueType(EXTENDED_TYPE)
+                .setOpaqueExtendedType(4).build());
+        return opaqueValues;
+    }
+
+    static Attributes buildWOTunnelInfAttribute() {
+        final PmsiTunnelBuilder pmsiTunnelBuilder = getPmsiTunnelBuilder();
+        return buildAttribute(pmsiTunnelBuilder);
+    }
+
+    private interface NonSupportedAddressFamily extends AddressFamily {
+
+    }
+
+    static class MockTunnelIdentifier implements TunnelIdentifier, DataObject {
+        @Override
+        public Class<? extends DataContainer> getImplementedInterface() {
+            return MockTunnelIdentifier.class;
+        }
+    }
+}
diff --git a/bgp/mvpn/src/test/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/tunnel/identifier/OpaqueUtilTest.java b/bgp/mvpn/src/test/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/tunnel/identifier/OpaqueUtilTest.java
new file mode 100644 (file)
index 0000000..9fc14cf
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * 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.mvpn.impl.attributes.tunnel.identifier;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import java.util.Arrays;
+import java.util.List;
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.mvpn.impl.attributes.OpaqueUtil;
+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.rev180329.Opaque;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.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.rev180329.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.mldp.p2mp.lsp.mldp.p2mp.lsp.OpaqueValueBuilder;
+
+public class OpaqueUtilTest {
+    private static final byte[] OPAQUE_WRONG = {
+        (byte) 0xfc, (byte) 0x00, (byte) 0x03, // Opaque Type - Length
+        (byte) 0xb5, (byte) 0xeb, (byte) 0x2d,  //Value
+    };
+
+    private static final 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 static final 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 static final 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
+    };
+
+    private static final HexString OPAQUE_TEST = new HexString("07:00:0b:00:00:01:00:00:00:01:00:00:00:00");
+    private static final HexString OPAQUE_TEST2
+            = new HexString("07:00:0b:00:00:01:00:00:00:01:00:00:00:00:01:02");
+    private static final Opaque OPAQUE = new OpaqueValueBuilder().setOpaque(OPAQUE_TEST)
+            .setOpaqueType(OpaqueUtil.GENERIC_LSP_IDENTIFIER).build();
+    private static final Opaque OPAQUE_EXTENDED = new OpaqueValueBuilder().setOpaque(OPAQUE_TEST2)
+            .setOpaqueType((short) 2).setOpaqueType(OpaqueUtil.EXTENDED_TYPE).setOpaqueExtendedType(4).build();
+    private static final List<OpaqueValue> OPAQUE_VALUE_LIST = Arrays.asList((OpaqueValue) OPAQUE,
+            (OpaqueValue) OPAQUE_EXTENDED);
+
+    @Test
+    public void serializeOpaque() {
+        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() {
+        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)));
+    }
+}
\ No newline at end of file
diff --git a/bgp/mvpn/src/test/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/tunnel/identifier/PAddressPMulticastGroupUtilTest.java b/bgp/mvpn/src/test/java/org/opendaylight/protocol/bgp/mvpn/impl/attributes/tunnel/identifier/PAddressPMulticastGroupUtilTest.java
new file mode 100644 (file)
index 0000000..2ccdc11
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * 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.mvpn.impl.attributes.tunnel.identifier;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+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.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.PAddressPMulticastGroup;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+
+public class PAddressPMulticastGroupUtilTest {
+    private static final String IPV6_MODEL = "2001::1";
+    private static final IpAddress IPV6 = new IpAddress(new Ipv6Address(IPV6_MODEL));
+    private static final byte[] IPV4_ADDRESS_EXPECTED = {(byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01};
+    private static final byte[] IPV6_ADDRESS_EXPECTED = {
+        0x20, (byte) 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
+    };
+    private static final byte[] SENDER_P_MULTICAST_GROUP_EXPECTED = {
+        (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x17, (byte) 0x01, (byte) 0x01, (byte) 0x01
+    };
+    private static final IpAddress IP_ADDRESS = new IpAddress(new Ipv4Address("1.1.1.1"));
+    private static final IpAddress P_MULTICAST = new IpAddress(new Ipv4Address("23.1.1.1"));
+
+    @Test
+    public void parseIpAddress() {
+        final ByteBuf ipv4Actual = Unpooled.buffer();
+        PAddressPMulticastGroupUtil.serializeIpAddress(IP_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(IP_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() {
+        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(IP_ADDRESS, actual.getPAddress());
+        assertEquals(P_MULTICAST, actual.getPMulticastGroup());
+    }
+
+    private static class MyPAddressPMulticastGroup implements PAddressPMulticastGroup {
+        @Override
+        public IpAddress getPAddress() {
+            return IP_ADDRESS;
+        }
+
+        @Override
+        public IpAddress getPMulticastGroup() {
+            return P_MULTICAST;
+        }
+
+        @Override
+        public Class<? extends DataContainer> getImplementedInterface() {
+            return null;
+        }
+    }
+}
\ No newline at end of file