BUG-2982 : moved path-attributes container to grouping
[bgpcep.git] / bgp / linkstate / src / main / java / org / opendaylight / protocol / bgp / linkstate / nlri / LinkstateNlriParser.java
index 602030feae765104ff587c47d2f28e7cc5278c8a..5e082cd50333a849b25c9c727f209f3bc8265e36 100644 (file)
@@ -7,38 +7,56 @@
  */
 package org.opendaylight.protocol.bgp.linkstate.nlri;
 
+import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
 import java.math.BigInteger;
+import java.util.ArrayList;
 import java.util.List;
-import org.opendaylight.protocol.bgp.linkstate.TlvUtil;
+import org.opendaylight.protocol.bgp.linkstate.spi.TlvUtil;
 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
 import org.opendaylight.protocol.bgp.parser.spi.NlriParser;
 import org.opendaylight.protocol.bgp.parser.spi.NlriSerializer;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.Identifier;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.NlriType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.NodeIdentifier;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.ProtocolId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.RouteDistinguisher;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.ObjectType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.destination.CLinkstateDestination;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.destination.CLinkstateDestinationBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.destination.c.linkstate.destination.LocalNodeDescriptors;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.destination.c.linkstate.destination.RemoteNodeDescriptors;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.path.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationLinkstateCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.path.attributes.mp.reach.nlri.advertized.routes.destination.type.destination.linkstate._case.DestinationLinkstateBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.path.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationLinkstateCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.PathAttributes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.PathAttributes1;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.PathAttributes2;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.MpReachNlriBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.MpUnreachNlri;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.MpUnreachNlriBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.mp.reach.nlri.AdvertizedRoutes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.mp.reach.nlri.AdvertizedRoutesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.mp.unreach.nlri.WithdrawnRoutesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.LinkCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.LinkCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.NodeCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.NodeCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.PrefixCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.PrefixCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.link._case.LinkDescriptors;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.link._case.LocalNodeDescriptors;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.link._case.RemoteNodeDescriptors;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.node._case.NodeDescriptors;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.prefix._case.AdvertisingNodeDescriptors;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.prefix._case.PrefixDescriptors;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationLinkstateCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.attributes.mp.reach.nlri.advertized.routes.destination.type.destination.linkstate._case.DestinationLinkstateBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationLinkstateCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.Attributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.Attributes1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.Attributes2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpReachNlriBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpUnreachNlri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpUnreachNlriBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.mp.reach.nlri.AdvertizedRoutes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.mp.reach.nlri.AdvertizedRoutesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.mp.unreach.nlri.WithdrawnRoutesBuilder;
 import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -46,7 +64,9 @@ import org.slf4j.LoggerFactory;
  * Parser and serializer for Linkstate NLRI.
  */
 public final class LinkstateNlriParser implements NlriParser, NlriSerializer {
+
     private static final Logger LOG = LoggerFactory.getLogger(LinkstateNlriParser.class);
+
     private static final int ROUTE_DISTINGUISHER_LENGTH = 8;
     private static final int PROTOCOL_ID_LENGTH = 1;
     private static final int IDENTIFIER_LENGTH = 8;
@@ -54,9 +74,18 @@ public final class LinkstateNlriParser implements NlriParser, NlriSerializer {
     private static final int TYPE_LENGTH = 2;
     private static final int LENGTH_SIZE = 2;
 
+    private static final int LOCAL_NODE_DESCRIPTORS_TYPE = 256;
+    private static final int REMOTE_NODE_DESCRIPTORS_TYPE = 257;
+
+    private static final NodeIdentifier OBJECT_TYPE_NID = new NodeIdentifier(ObjectType.QNAME);
+    private static final NodeIdentifier NODE_DESCRIPTORS_NID = new NodeIdentifier(NodeDescriptors.QNAME);
+    private static final NodeIdentifier LOCAL_NODE_DESCRIPTORS_NID = new NodeIdentifier(LocalNodeDescriptors.QNAME);
+    private static final NodeIdentifier REMOTE_NODE_DESCRIPTORS_NID = new NodeIdentifier(RemoteNodeDescriptors.QNAME);
+    private static final NodeIdentifier ADVERTISING_NODE_DESCRIPTORS_NID = new NodeIdentifier(AdvertisingNodeDescriptors.QNAME);
 
-    private static final int LOCAL_NODE_DESCRIPTORS = 256;
-    private static final int REMOTE_NODE_DESCRIPTORS = 257;
+    private static final NodeIdentifier DISTINGUISHER_NID = new NodeIdentifier(QName.cachedReference(QName.create(CLinkstateDestination.QNAME, "route-distinguisher")));
+    private static final NodeIdentifier PROTOCOL_ID_NID = new NodeIdentifier(QName.cachedReference(QName.create(CLinkstateDestination.QNAME, "protocol-id")));
+    private static final NodeIdentifier IDENTIFIER_NID = new NodeIdentifier(QName.cachedReference(QName.create(CLinkstateDestination.QNAME, "identifier")));
 
     private final boolean isVpn;
 
@@ -64,15 +93,19 @@ public final class LinkstateNlriParser implements NlriParser, NlriSerializer {
         this.isVpn = isVpn;
     }
 
-    private static NodeIdentifier parseLink(final CLinkstateDestinationBuilder builder, final ByteBuf buffer) throws BGPParsingException {
+    private static org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.NodeIdentifier parseLink(final CLinkstateDestinationBuilder builder, final ByteBuf buffer, final LocalNodeDescriptors localDescriptors)
+            throws BGPParsingException {
         final int type = buffer.readUnsignedShort();
         final int length = buffer.readUnsignedShort();
-        final NodeIdentifier remote = null;
-        if (type == REMOTE_NODE_DESCRIPTORS) {
-            builder.setRemoteNodeDescriptors((RemoteNodeDescriptors) NodeNlriParser.parseNodeDescriptors(buffer.slice(buffer.readerIndex(), length), false));
-            buffer.skipBytes(length);
+        final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.NodeIdentifier remote = null;
+        RemoteNodeDescriptors remoteDescriptors = null;
+        if (type == REMOTE_NODE_DESCRIPTORS_TYPE) {
+            remoteDescriptors = (RemoteNodeDescriptors)NodeNlriParser.parseNodeDescriptors(buffer.readSlice(length), NlriType.Link, false);
         }
-        builder.setLinkDescriptors(LinkNlriParser.parseLinkDescriptors(buffer.slice()));
+        builder.setObjectType(new LinkCaseBuilder()
+            .setLocalNodeDescriptors(localDescriptors)
+            .setRemoteNodeDescriptors(remoteDescriptors)
+            .setLinkDescriptors(LinkNlriParser.parseLinkDescriptors(buffer.slice())).build());
         return remote;
     }
 
@@ -80,21 +113,15 @@ public final class LinkstateNlriParser implements NlriParser, NlriSerializer {
      * Parses common parts for Link State Nodes, Links and Prefixes, that includes protocol ID and identifier tlv.
      *
      * @param nlri as byte array
+     * @param isVpn flag which determines that destination has route distinguisher
      * @return {@link CLinkstateDestination}
      * @throws BGPParsingException if parsing was unsuccessful
      */
     public static List<CLinkstateDestination> parseNlri(final ByteBuf nlri, final boolean isVpn) throws BGPParsingException {
-        if (!nlri.isReadable()) {
-            return null;
-        }
-        final List<CLinkstateDestination> dests = Lists.newArrayList();
-
-        CLinkstateDestinationBuilder builder = null;
-
+        final List<CLinkstateDestination> dests = new ArrayList<>();
         while (nlri.isReadable()) {
-            builder = new CLinkstateDestinationBuilder();
+            final CLinkstateDestinationBuilder builder = new CLinkstateDestinationBuilder();
             final NlriType type = NlriType.forValue(nlri.readUnsignedShort());
-            builder.setNlriType(type);
 
             // length means total length of the tlvs including route distinguisher not including the type field
             final int length = nlri.readUnsignedShort();
@@ -113,36 +140,37 @@ public final class LinkstateNlriParser implements NlriParser, NlriSerializer {
             builder.setIdentifier(identifier);
 
             // if we are dealing with linkstate nodes/links, parse local node descriptor
-            NodeIdentifier localDescriptor = null;
-            int locallength = 0;
+            org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.NodeIdentifier localDescriptor = null;
             final int localtype = nlri.readUnsignedShort();
-            locallength = nlri.readUnsignedShort();
-            if (localtype == LOCAL_NODE_DESCRIPTORS) {
-                localDescriptor = NodeNlriParser.parseNodeDescriptors(nlri.slice(nlri.readerIndex(), locallength), true);
+            final int locallength = nlri.readUnsignedShort();
+            if (localtype == LOCAL_NODE_DESCRIPTORS_TYPE) {
+                localDescriptor = NodeNlriParser.parseNodeDescriptors(nlri.readSlice(locallength), type, true);
             }
-            nlri.skipBytes(locallength);
-            builder.setLocalNodeDescriptors((LocalNodeDescriptors) localDescriptor);
             final int restLength = length - (isVpn ? ROUTE_DISTINGUISHER_LENGTH : 0) - PROTOCOL_ID_LENGTH - IDENTIFIER_LENGTH
                 - TYPE_LENGTH - LENGTH_SIZE - locallength;
             LOG.trace("Restlength {}", restLength);
-            final ByteBuf rest = nlri.slice(nlri.readerIndex(), restLength);
+            final ByteBuf rest = nlri.readSlice(restLength);
             switch (type) {
             case Link:
-                parseLink(builder, rest);
+                parseLink(builder, rest, (LocalNodeDescriptors) localDescriptor);
                 break;
             case Ipv4Prefix:
-                builder.setPrefixDescriptors(PrefixNlriParser.parsePrefixDescriptors(rest, true));
+                builder.setObjectType(new PrefixCaseBuilder()
+                    .setAdvertisingNodeDescriptors((AdvertisingNodeDescriptors)localDescriptor)
+                    .setPrefixDescriptors(PrefixNlriParser.parsePrefixDescriptors(rest, true)).build());
                 break;
             case Ipv6Prefix:
-                builder.setPrefixDescriptors(PrefixNlriParser.parsePrefixDescriptors(rest, false));
+                builder.setObjectType(new PrefixCaseBuilder()
+                    .setAdvertisingNodeDescriptors((AdvertisingNodeDescriptors)localDescriptor)
+                    .setPrefixDescriptors(PrefixNlriParser.parsePrefixDescriptors(rest, false)).build());
                 break;
             case Node:
                 // node nlri is already parsed as it contains only the common fields for node and link nlri
+                builder.setObjectType(new NodeCaseBuilder().setNodeDescriptors((NodeDescriptors)localDescriptor).build());
                 break;
             default:
                 break;
             }
-            nlri.skipBytes(restLength);
             dests.add(builder.build());
         }
         return dests;
@@ -156,8 +184,8 @@ public final class LinkstateNlriParser implements NlriParser, NlriSerializer {
         final List<CLinkstateDestination> dst = parseNlri(nlri, this.isVpn);
 
         builder.setWithdrawnRoutes(new WithdrawnRoutesBuilder().setDestinationType(
-            new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.path.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationLinkstateCaseBuilder().setDestinationLinkstate(
-                new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.path.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.destination.linkstate._case.DestinationLinkstateBuilder().setCLinkstateDestination(
+            new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationLinkstateCaseBuilder().setDestinationLinkstate(
+                new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.destination.linkstate._case.DestinationLinkstateBuilder().setCLinkstateDestination(
                     dst).build()).build()).build());
     }
 
@@ -177,6 +205,7 @@ public final class LinkstateNlriParser implements NlriParser, NlriSerializer {
      * Serializes Linkstate NLRI to byte array. We need this as NLRI serves as a key in upper layers.
      *
      * @param destination Linkstate NLRI to be serialized
+     * @param buffer where Linkstate NLRI will be serialized
      */
     public static void serializeNlri(final CLinkstateDestination destination, final ByteBuf buffer) {
         final ByteBuf nlriByteBuf = Unpooled.buffer();
@@ -185,50 +214,57 @@ public final class LinkstateNlriParser implements NlriParser, NlriSerializer {
         }
         nlriByteBuf.writeByte(destination.getProtocolId().getIntValue());
         nlriByteBuf.writeLong(destination.getIdentifier().getValue().longValue());
-
-        // serialize local node descriptors
         final ByteBuf ldescs = Unpooled.buffer();
-        NodeNlriParser.serializeNodeDescriptors(destination.getLocalNodeDescriptors(), ldescs);
-        TlvUtil.writeTLV(LOCAL_NODE_DESCRIPTORS, ldescs, nlriByteBuf);
-
-        switch (destination.getNlriType()) {
-        case Ipv4Prefix:
-        case Ipv6Prefix:
-            if (destination.getPrefixDescriptors() != null) {
-                PrefixNlriParser.serializePrefixDescriptors(destination.getPrefixDescriptors(), nlriByteBuf);
+        final ObjectType ot = destination.getObjectType();
+        NlriType nlriType = null;
+        if (ot instanceof PrefixCase) {
+            final PrefixCase pCase = (PrefixCase)destination.getObjectType();
+            NodeNlriParser.serializeNodeDescriptors(pCase.getAdvertisingNodeDescriptors(), ldescs);
+            TlvUtil.writeTLV(LOCAL_NODE_DESCRIPTORS_TYPE, ldescs, nlriByteBuf);
+            if (pCase.getPrefixDescriptors() != null) {
+                PrefixNlriParser.serializePrefixDescriptors(pCase.getPrefixDescriptors(), nlriByteBuf);
+                if (pCase.getPrefixDescriptors().getIpReachabilityInformation().getIpv4Prefix() != null) {
+                    nlriType = NlriType.Ipv4Prefix;
+                } else {
+                    nlriType = NlriType.Ipv6Prefix;
+                }
             }
-            break;
-        case Link:
+        } else if (ot instanceof LinkCase) {
+            final LinkCase lCase = (LinkCase)destination.getObjectType();
+            NodeNlriParser.serializeNodeDescriptors(lCase.getLocalNodeDescriptors(), ldescs);
+            TlvUtil.writeTLV(LOCAL_NODE_DESCRIPTORS_TYPE, ldescs, nlriByteBuf);
             final ByteBuf rdescs = Unpooled.buffer();
-            NodeNlriParser.serializeNodeDescriptors(destination.getRemoteNodeDescriptors(), rdescs);
-            TlvUtil.writeTLV(REMOTE_NODE_DESCRIPTORS, rdescs, nlriByteBuf);
-            if (destination.getLinkDescriptors() != null) {
-                LinkNlriParser.serializeLinkDescriptors(destination.getLinkDescriptors(), nlriByteBuf);
+            NodeNlriParser.serializeNodeDescriptors(lCase.getRemoteNodeDescriptors(), rdescs);
+            TlvUtil.writeTLV(REMOTE_NODE_DESCRIPTORS_TYPE, rdescs, nlriByteBuf);
+            if (lCase.getLinkDescriptors() != null) {
+                LinkNlriParser.serializeLinkDescriptors(lCase.getLinkDescriptors(), nlriByteBuf);
             }
-            break;
-        case Node:
-            break;
-        default:
+            nlriType = NlriType.Link;
+        } else if (ot instanceof NodeCase) {
+            final NodeCase nCase = (NodeCase)destination.getObjectType();
+            NodeNlriParser.serializeNodeDescriptors(nCase.getNodeDescriptors(), ldescs);
+            TlvUtil.writeTLV(LOCAL_NODE_DESCRIPTORS_TYPE, ldescs, nlriByteBuf);
+            nlriType = NlriType.Node;
+        } else {
             LOG.warn("Unknown NLRI Type.");
-            break;
         }
-        TlvUtil.writeTLV(destination.getNlriType().getIntValue(), nlriByteBuf, buffer);
+        TlvUtil.writeTLV(nlriType.getIntValue(), nlriByteBuf, buffer);
     }
 
     @Override
     public void serializeAttribute(final DataObject attribute, final ByteBuf byteAggregator) {
-        Preconditions.checkArgument(attribute instanceof PathAttributes, "Attribute parameter is not a PathAttribute object.");
-        final PathAttributes pathAttributes = (PathAttributes) attribute;
-        final PathAttributes1 pathAttributes1 = pathAttributes.getAugmentation(PathAttributes1.class);
-        final PathAttributes2 pathAttributes2 = pathAttributes.getAugmentation(PathAttributes2.class);
+        Preconditions.checkArgument(attribute instanceof Attributes, "Attribute parameter is not a PathAttribute object.");
+        final Attributes pathAttributes = (Attributes) attribute;
+        final Attributes1 pathAttributes1 = pathAttributes.getAugmentation(Attributes1.class);
+        final Attributes2 pathAttributes2 = pathAttributes.getAugmentation(Attributes2.class);
         if (pathAttributes1 != null) {
             final AdvertizedRoutes routes = (pathAttributes1.getMpReachNlri()).getAdvertizedRoutes();
             if (routes != null &&
                 routes.getDestinationType()
                 instanceof
-                org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.path.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationLinkstateCase) {
-                final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.path.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationLinkstateCase
-                linkstateCase = (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.path.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationLinkstateCase) routes.getDestinationType();
+                org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationLinkstateCase) {
+                final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationLinkstateCase
+                linkstateCase = (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationLinkstateCase) routes.getDestinationType();
 
                 for (final CLinkstateDestination cLinkstateDestination : linkstateCase.getDestinationLinkstate().getCLinkstateDestination()) {
                     serializeNlri(cLinkstateDestination, byteAggregator);
@@ -244,4 +280,89 @@ public final class LinkstateNlriParser implements NlriParser, NlriSerializer {
             }
         }
     }
+
+    private static int domProtocolIdValue(final String protocolId) {
+        switch(protocolId) {
+        case "unknown":
+            return 0;
+        case "isis-level1":
+            return 1;
+        case "isis-level2":
+            return 2;
+        case "ospf":
+            return 3;
+        case "direct":
+            return 4;
+        case "static":
+            return 5;
+        default:
+            return 0;
+        }
+    }
+
+    /**
+     * Serializes DOM interpretation of Linkstate NLRI to ByteBuf. Used to create linkstate route key.
+     *
+     * @param linkstate UnkeyedListEntryNode basically CLinkstateDestination in DOM
+     * @param buffer ByteBuf where the key will be serialized
+     */
+    public static void serializeNlri(final UnkeyedListEntryNode linkstate, final ByteBuf buffer) {
+        final ByteBuf nlriByteBuf = Unpooled.buffer();
+
+        // serialize common parts
+        final Optional<DataContainerChild<? extends PathArgument, ?>> distinguisher = linkstate.getChild(DISTINGUISHER_NID);
+        if (distinguisher.isPresent()) {
+            nlriByteBuf.writeBytes(((String)distinguisher.get().getValue()).getBytes());
+        }
+        final Optional<DataContainerChild<? extends PathArgument, ?>> protocolId = linkstate.getChild(PROTOCOL_ID_NID);
+        // DOM representation contains values as are in the model, not as are in generated enum
+        nlriByteBuf.writeLong(domProtocolIdValue((String) protocolId.get().getValue()));
+        final Optional<DataContainerChild<? extends PathArgument, ?>> identifier = linkstate.getChild(IDENTIFIER_NID);
+        nlriByteBuf.writeLong(((BigInteger)identifier.get().getValue()).longValue());
+
+        // serialize node
+        final ByteBuf ldescs = Unpooled.buffer();
+        NlriType nlriType = null;
+        final ChoiceNode objectType = (ChoiceNode) linkstate.getChild(OBJECT_TYPE_NID).get();
+        if (objectType.getChild(ADVERTISING_NODE_DESCRIPTORS_NID).isPresent()) {
+
+            // prefix node descriptors
+            NodeNlriParser.serializeNodeDescriptors((ContainerNode)objectType.getChild(ADVERTISING_NODE_DESCRIPTORS_NID).get(), ldescs);
+            TlvUtil.writeTLV(LinkstateNlriParser.LOCAL_NODE_DESCRIPTORS_TYPE, ldescs, nlriByteBuf);
+            final Optional<DataContainerChild<? extends PathArgument, ?>> prefixDescriptors = objectType.getChild(new NodeIdentifier(PrefixDescriptors.QNAME));
+
+            // prefix descriptors
+            if (prefixDescriptors.isPresent()) {
+                nlriType = PrefixNlriParser.serializePrefixDescriptors((ContainerNode)prefixDescriptors.get(), nlriByteBuf);
+            }
+        } else if (objectType.getChild(LOCAL_NODE_DESCRIPTORS_NID).isPresent()) {
+
+            // link local node descriptors
+            NodeNlriParser.serializeNodeDescriptors((ContainerNode)objectType.getChild(LOCAL_NODE_DESCRIPTORS_NID).get(), ldescs);
+            TlvUtil.writeTLV(LinkstateNlriParser.LOCAL_NODE_DESCRIPTORS_TYPE, ldescs, nlriByteBuf);
+
+            // link remote node descriptors
+            final ByteBuf rdescs = Unpooled.buffer();
+            if (objectType.getChild(REMOTE_NODE_DESCRIPTORS_NID).isPresent()) {
+                NodeNlriParser.serializeNodeDescriptors((ContainerNode)objectType.getChild(REMOTE_NODE_DESCRIPTORS_NID).get(), rdescs);
+                TlvUtil.writeTLV(LinkstateNlriParser.REMOTE_NODE_DESCRIPTORS_TYPE, rdescs, nlriByteBuf);
+            }
+
+            // link descriptors
+            final Optional<DataContainerChild<? extends PathArgument, ?>> linkDescriptors = objectType.getChild(new NodeIdentifier(LinkDescriptors.QNAME));
+            if (linkDescriptors.isPresent()) {
+                LinkNlriParser.serializeLinkDescriptors((ContainerNode)linkDescriptors.get(), nlriByteBuf);
+            }
+            nlriType = NlriType.Link;
+        } else if (objectType.getChild(NODE_DESCRIPTORS_NID).isPresent()) {
+
+            // node descriptors
+            NodeNlriParser.serializeNodeDescriptors((ContainerNode)objectType.getChild(NODE_DESCRIPTORS_NID).get(), ldescs);
+            TlvUtil.writeTLV(LinkstateNlriParser.LOCAL_NODE_DESCRIPTORS_TYPE, ldescs, nlriByteBuf);
+            nlriType = NlriType.Node;
+        } else {
+            LOG.warn("Unknown Object Type.");
+        }
+        TlvUtil.writeTLV(nlriType.getIntValue(), nlriByteBuf, buffer);
+    }
 }