Moved Ipv4Util and Ipv6Util from concepts to util
[bgpcep.git] / bgp / linkstate / src / main / java / org / opendaylight / protocol / bgp / linkstate / LinkstateNlriParser.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.protocol.bgp.linkstate;
9
10 import com.google.common.collect.Lists;
11 import com.google.common.primitives.UnsignedBytes;
12 import com.google.common.primitives.UnsignedInteger;
13 import io.netty.buffer.ByteBuf;
14 import io.netty.buffer.Unpooled;
15 import java.math.BigInteger;
16 import java.util.Arrays;
17 import java.util.List;
18 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
19 import org.opendaylight.protocol.bgp.parser.spi.NlriParser;
20 import org.opendaylight.protocol.bgp.parser.spi.NlriUtil;
21 import org.opendaylight.protocol.util.ByteArray;
22 import org.opendaylight.protocol.util.Ipv4Util;
23 import org.opendaylight.protocol.util.Ipv6Util;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.AreaIdentifier;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.DomainIdentifier;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.Identifier;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.Ipv4InterfaceIdentifier;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.Ipv6InterfaceIdentifier;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.NlriType;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.NodeIdentifier;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.OspfInterfaceIdentifier;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.OspfRouteType;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.ProtocolId;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.RouteDistinguisher;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.TopologyIdentifier;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.isis.lan.identifier.IsIsRouterIdentifier;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.isis.lan.identifier.IsIsRouterIdentifierBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.linkstate.destination.CLinkstateDestination;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.linkstate.destination.CLinkstateDestinationBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.linkstate.destination.c.linkstate.destination.LinkDescriptors;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.linkstate.destination.c.linkstate.destination.LinkDescriptorsBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.linkstate.destination.c.linkstate.destination.LocalNodeDescriptors;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.linkstate.destination.c.linkstate.destination.LocalNodeDescriptorsBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.linkstate.destination.c.linkstate.destination.PrefixDescriptors;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.linkstate.destination.c.linkstate.destination.PrefixDescriptorsBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.linkstate.destination.c.linkstate.destination.RemoteNodeDescriptors;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.linkstate.destination.c.linkstate.destination.RemoteNodeDescriptorsBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.node.identifier.CRouterIdentifier;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.node.identifier.c.router.identifier.IsisNodeCase;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.node.identifier.c.router.identifier.IsisNodeCaseBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.node.identifier.c.router.identifier.IsisPseudonodeCase;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.node.identifier.c.router.identifier.IsisPseudonodeCaseBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.node.identifier.c.router.identifier.OspfNodeCase;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.node.identifier.c.router.identifier.OspfNodeCaseBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.node.identifier.c.router.identifier.OspfPseudonodeCase;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.node.identifier.c.router.identifier.OspfPseudonodeCaseBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.node.identifier.c.router.identifier.isis.node._case.IsisNode;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.node.identifier.c.router.identifier.isis.node._case.IsisNodeBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.node.identifier.c.router.identifier.isis.pseudonode._case.IsisPseudonode;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.node.identifier.c.router.identifier.isis.pseudonode._case.IsisPseudonodeBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.node.identifier.c.router.identifier.ospf.node._case.OspfNodeBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.node.identifier.c.router.identifier.ospf.pseudonode._case.OspfPseudonode;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.node.identifier.c.router.identifier.ospf.pseudonode._case.OspfPseudonodeBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.update.path.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationLinkstateCaseBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.update.path.attributes.mp.reach.nlri.advertized.routes.destination.type.destination.linkstate._case.DestinationLinkstateBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.MpReachNlriBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.MpUnreachNlriBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.mp.reach.nlri.AdvertizedRoutesBuilder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.mp.unreach.nlri.WithdrawnRoutesBuilder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.IsoSystemIdentifier;
73 import org.slf4j.Logger;
74 import org.slf4j.LoggerFactory;
75
76 /**
77  * Parser and serializer for Linkstate NLRI.
78  */
79 public final class LinkstateNlriParser implements NlriParser {
80     private static final Logger LOG = LoggerFactory.getLogger(LinkstateNlriParser.class);
81     private static final int ROUTE_DISTINGUISHER_LENGTH = 8;
82     private static final int PROTOCOL_ID_LENGTH = 1;
83     private static final int IDENTIFIER_LENGTH = 8;
84     private static final int LINK_IDENTIFIER_LENGTH = 4;
85     private static final int ISO_SYSTEM_ID_LENGTH = 6;
86     private static final int PSN_LENGTH = 1;
87
88     private static final int TYPE_LENGTH = 2;
89     private static final int LENGTH_SIZE = 2;
90
91     private final boolean isVpn;
92
93     public LinkstateNlriParser(final boolean isVpn) {
94         this.isVpn = isVpn;
95     }
96
97     private static NodeIdentifier parseLink(final CLinkstateDestinationBuilder builder, final ByteBuf buffer) throws BGPParsingException {
98         final int type = buffer.readUnsignedShort();
99         final int length = buffer.readUnsignedShort();
100         final NodeIdentifier remote = null;
101         if (type == TlvCode.REMOTE_NODE_DESCRIPTORS) {
102             builder.setRemoteNodeDescriptors((RemoteNodeDescriptors) parseNodeDescriptors(buffer.slice(buffer.readerIndex(), length), false));
103             buffer.skipBytes(length);
104         }
105         builder.setLinkDescriptors(parseLinkDescriptors(buffer.slice()));
106         return remote;
107     }
108
109     private static LinkDescriptors parseLinkDescriptors(final ByteBuf buffer) throws BGPParsingException {
110         final LinkDescriptorsBuilder builder = new LinkDescriptorsBuilder();
111         while (buffer.isReadable()) {
112             final int type = buffer.readUnsignedShort();
113             final int length = buffer.readUnsignedShort();
114             final byte[] value = ByteArray.readBytes(buffer, length);
115             LOG.trace("Parsing Link Descriptor: {}", Arrays.toString(value));
116             switch (type) {
117             case TlvCode.LINK_LR_IDENTIFIERS:
118                 builder.setLinkLocalIdentifier(ByteArray.bytesToUint32(ByteArray.subByte(value, 0, LINK_IDENTIFIER_LENGTH)).longValue());
119                 builder.setLinkRemoteIdentifier(ByteArray.bytesToUint32(
120                         ByteArray.subByte(value, LINK_IDENTIFIER_LENGTH, LINK_IDENTIFIER_LENGTH)).longValue());
121                 LOG.debug("Parsed link local {} remote {} Identifiers.", builder.getLinkLocalIdentifier(),
122                         builder.getLinkRemoteIdentifier());
123                 break;
124             case TlvCode.IPV4_IFACE_ADDRESS:
125                 final Ipv4InterfaceIdentifier lipv4 = new Ipv4InterfaceIdentifier(Ipv4Util.addressForBytes(value));
126                 builder.setIpv4InterfaceAddress(lipv4);
127                 LOG.debug("Parsed IPv4 interface address {}.", lipv4);
128                 break;
129             case TlvCode.IPV4_NEIGHBOR_ADDRESS:
130                 final Ipv4InterfaceIdentifier ripv4 = new Ipv4InterfaceIdentifier(Ipv4Util.addressForBytes(value));
131                 builder.setIpv4NeighborAddress(ripv4);
132                 LOG.debug("Parsed IPv4 neighbor address {}.", ripv4);
133                 break;
134             case TlvCode.IPV6_IFACE_ADDRESS:
135                 final Ipv6InterfaceIdentifier lipv6 = new Ipv6InterfaceIdentifier(Ipv6Util.addressForBytes(value));
136                 builder.setIpv6InterfaceAddress(lipv6);
137                 LOG.debug("Parsed IPv6 interface address {}.", lipv6);
138                 break;
139             case TlvCode.IPV6_NEIGHBOR_ADDRESS:
140                 final Ipv6InterfaceIdentifier ripv6 = new Ipv6InterfaceIdentifier(Ipv6Util.addressForBytes(value));
141                 builder.setIpv6NeighborAddress(ripv6);
142                 LOG.debug("Parsed IPv6 neighbor address {}.", ripv6);
143                 break;
144             case TlvCode.MULTI_TOPOLOGY_ID:
145                 final TopologyIdentifier topId = new TopologyIdentifier(ByteArray.bytesToInt(value) & 0x3fff);
146                 builder.setMultiTopologyId(topId);
147                 LOG.debug("Parsed topology identifier {}.", topId);
148                 break;
149             default:
150                 throw new BGPParsingException("Link Descriptor not recognized, type: " + type);
151             }
152         }
153         LOG.trace("Finished parsing Link descriptors.");
154         return builder.build();
155     }
156
157     private static NodeIdentifier parseNodeDescriptors(final ByteBuf buffer, final boolean local) throws BGPParsingException {
158         AsNumber asnumber = null;
159         DomainIdentifier bgpId = null;
160         AreaIdentifier ai = null;
161         CRouterIdentifier routerId = null;
162         while (buffer.isReadable()) {
163             final int type = buffer.readUnsignedShort();
164             final int length = buffer.readUnsignedShort();
165             final byte[] value = ByteArray.readBytes(buffer, length);
166             LOG.trace("Parsing Node Descriptor: {}", Arrays.toString(value));
167             switch (type) {
168             case TlvCode.AS_NUMBER:
169                 asnumber = new AsNumber(ByteArray.bytesToLong(value));
170                 LOG.debug("Parsed {}", asnumber);
171                 break;
172             case TlvCode.BGP_LS_ID:
173                 bgpId = new DomainIdentifier(UnsignedInteger.fromIntBits(ByteArray.bytesToInt(value)).longValue());
174                 LOG.debug("Parsed {}", bgpId);
175                 break;
176             case TlvCode.AREA_ID:
177                 ai = new AreaIdentifier(UnsignedInteger.fromIntBits(ByteArray.bytesToInt(value)).longValue());
178                 LOG.debug("Parsed area identifier {}", ai);
179                 break;
180             case TlvCode.IGP_ROUTER_ID:
181                 routerId = parseRouterId(value);
182                 LOG.debug("Parsed Router Identifier {}", routerId);
183                 break;
184             default:
185                 throw new BGPParsingException("Node Descriptor not recognized, type: " + type);
186             }
187         }
188         LOG.trace("Finished parsing Node descriptors.");
189         return (local) ? new LocalNodeDescriptorsBuilder().setAsNumber(asnumber).setDomainId(bgpId).setAreaId(ai).setCRouterIdentifier(
190                 routerId).build()
191                 : new RemoteNodeDescriptorsBuilder().setAsNumber(asnumber).setDomainId(bgpId).setAreaId(ai).setCRouterIdentifier(routerId).build();
192     }
193
194     private static CRouterIdentifier parseRouterId(final byte[] value) throws BGPParsingException {
195         if (value.length == ISO_SYSTEM_ID_LENGTH) {
196             return new IsisNodeCaseBuilder().setIsisNode(
197                     new IsisNodeBuilder().setIsoSystemId(new IsoSystemIdentifier(ByteArray.subByte(value, 0, ISO_SYSTEM_ID_LENGTH))).build()).build();
198         }
199         if (value.length == ISO_SYSTEM_ID_LENGTH + PSN_LENGTH) {
200             if (value[ISO_SYSTEM_ID_LENGTH] == 0) {
201                 LOG.warn("PSN octet is 0. Ignoring System ID.");
202                 return new IsisNodeCaseBuilder().setIsisNode(
203                         new IsisNodeBuilder().setIsoSystemId(new IsoSystemIdentifier(ByteArray.subByte(value, 0, ISO_SYSTEM_ID_LENGTH))).build()).build();
204             } else {
205                 final IsIsRouterIdentifier iri = new IsIsRouterIdentifierBuilder().setIsoSystemId(
206                         new IsoSystemIdentifier(ByteArray.subByte(value, 0, ISO_SYSTEM_ID_LENGTH))).build();
207                 return new IsisPseudonodeCaseBuilder().setIsisPseudonode(
208                         new IsisPseudonodeBuilder().setIsIsRouterIdentifier(iri).setPsn(
209                                 (short) UnsignedBytes.toInt(value[ISO_SYSTEM_ID_LENGTH])).build()).build();
210             }
211         }
212         if (value.length == 4) {
213             return new OspfNodeCaseBuilder().setOspfNode(
214                     new OspfNodeBuilder().setOspfRouterId(ByteArray.bytesToUint32(value).longValue()).build()).build();
215         }
216         if (value.length == 8) {
217             final byte[] o = ByteArray.subByte(value, 0, 4);
218             final OspfInterfaceIdentifier a = new OspfInterfaceIdentifier(ByteArray.bytesToUint32(ByteArray.subByte(value, 4, 4)).longValue());
219             return new OspfPseudonodeCaseBuilder().setOspfPseudonode(
220                     new OspfPseudonodeBuilder().setOspfRouterId(ByteArray.bytesToUint32(o).longValue()).setLanInterface(a).build()).build();
221         }
222         throw new BGPParsingException("Router Id of invalid length " + value.length);
223     }
224
225     private static PrefixDescriptors parsePrefixDescriptors(final ByteBuf buffer, final boolean ipv4) throws BGPParsingException {
226         final PrefixDescriptorsBuilder builder = new PrefixDescriptorsBuilder();
227         while (buffer.isReadable()) {
228             final int type = buffer.readUnsignedShort();
229             final int length = buffer.readUnsignedShort();
230             final byte[] value = ByteArray.readBytes(buffer, length);
231             LOG.trace("Parsing Prefix Descriptor: {}", Arrays.toString(value));
232             switch (type) {
233             case TlvCode.MULTI_TOPOLOGY_ID:
234                 final TopologyIdentifier topologyId = new TopologyIdentifier(ByteArray.bytesToInt(value) & 0x3fff);
235                 builder.setMultiTopologyId(topologyId);
236                 LOG.trace("Parsed Topology Identifier: {}", topologyId);
237                 break;
238             case TlvCode.OSPF_ROUTE_TYPE:
239                 final int rt = ByteArray.bytesToInt(value);
240                 final OspfRouteType routeType = OspfRouteType.forValue(rt);
241                 if (routeType == null) {
242                     throw new BGPParsingException("Unknown OSPF Route Type: " + rt);
243                 }
244                 builder.setOspfRouteType(routeType);
245                 LOG.trace("Parser RouteType: {}", routeType);
246                 break;
247             case TlvCode.IP_REACHABILITY:
248                 IpPrefix prefix = null;
249                 final int prefixLength = UnsignedBytes.toInt(value[0]);
250                 final int size = prefixLength / Byte.SIZE + ((prefixLength % Byte.SIZE == 0) ? 0 : 1);
251                 if (size != value.length - 1) {
252                     LOG.debug("Expected length {}, actual length {}.", size, value.length - 1);
253                     throw new BGPParsingException("Illegal length of IP reachability TLV: " + (value.length - 1));
254                 }
255                 if (ipv4) {
256                     prefix = new IpPrefix(Ipv4Util.prefixForBytes(ByteArray.subByte(value, 1, size), prefixLength));
257                 } else {
258                     prefix = new IpPrefix(Ipv6Util.prefixForBytes(ByteArray.subByte(value, 1, size), prefixLength));
259                 }
260                 builder.setIpReachabilityInformation(prefix);
261                 LOG.trace("Parsed IP reachability info: {}", prefix);
262                 break;
263             default:
264                 throw new BGPParsingException("Prefix Descriptor not recognized, type: " + type);
265             }
266         }
267         LOG.debug("Finished parsing Prefix descriptors.");
268         return builder.build();
269     }
270
271     /**
272      * Parses common parts for Link State Nodes, Links and Prefixes, that includes protocol ID and identifier tlv.
273      *
274      * @param nlri as byte array
275      * @return {@link CLinkstateDestination}
276      * @throws BGPParsingException if parsing was unsuccessful
277      */
278     private List<CLinkstateDestination> parseNlri(final ByteBuf nlri) throws BGPParsingException {
279         if (!nlri.isReadable()) {
280             return null;
281         }
282         final List<CLinkstateDestination> dests = Lists.newArrayList();
283
284         CLinkstateDestinationBuilder builder = null;
285
286         while (nlri.isReadable()) {
287             builder = new CLinkstateDestinationBuilder();
288             final NlriType type = NlriType.forValue(nlri.readUnsignedShort());
289             builder.setNlriType(type);
290
291             // length means total length of the tlvs including route distinguisher not including the type field
292             final int length = nlri.readUnsignedShort();
293             RouteDistinguisher distinguisher = null;
294             if (this.isVpn) {
295                 // this parses route distinguisher
296                 distinguisher = new RouteDistinguisher(BigInteger.valueOf(nlri.readLong()));
297                 builder.setDistinguisher(distinguisher);
298             }
299             // parse source protocol
300             final ProtocolId sp = ProtocolId.forValue(UnsignedBytes.toInt(nlri.readByte()));
301             builder.setProtocolId(sp);
302
303             // parse identifier
304             final Identifier identifier = new Identifier(BigInteger.valueOf(nlri.readLong()));
305             builder.setIdentifier(identifier);
306
307             // if we are dealing with linkstate nodes/links, parse local node descriptor
308             NodeIdentifier localDescriptor = null;
309             int locallength = 0;
310             final int localtype = nlri.readUnsignedShort();
311             locallength = nlri.readUnsignedShort();
312             if (localtype == TlvCode.LOCAL_NODE_DESCRIPTORS) {
313                 localDescriptor = parseNodeDescriptors(nlri.slice(nlri.readerIndex(), locallength), true);
314             }
315             nlri.skipBytes(locallength);
316             builder.setLocalNodeDescriptors((LocalNodeDescriptors) localDescriptor);
317             final int restLength = length - (this.isVpn ? ROUTE_DISTINGUISHER_LENGTH : 0) - PROTOCOL_ID_LENGTH - IDENTIFIER_LENGTH
318                     - TYPE_LENGTH - LENGTH_SIZE - locallength;
319             LOG.trace("Restlength {}", restLength);
320             ByteBuf rest = nlri.slice(nlri.readerIndex(), restLength);
321             switch (type) {
322             case Link:
323                 parseLink(builder, rest);
324                 break;
325             case Ipv4Prefix:
326                 builder.setPrefixDescriptors(parsePrefixDescriptors(rest, true));
327                 break;
328             case Ipv6Prefix:
329                 builder.setPrefixDescriptors(parsePrefixDescriptors(rest, false));
330                 break;
331             case Node:
332                 // node nlri is already parsed as it contains only the common fields for node and link nlri
333                 break;
334             }
335             nlri.skipBytes(restLength);
336             dests.add(builder.build());
337         }
338         return dests;
339     }
340
341     @Override
342     public void parseNlri(final ByteBuf nlri, final MpUnreachNlriBuilder builder) throws BGPParsingException {
343         if (!nlri.isReadable()) {
344             return;
345         }
346         final List<CLinkstateDestination> dst = parseNlri(nlri);
347
348         builder.setWithdrawnRoutes(new WithdrawnRoutesBuilder().setDestinationType(
349                 new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.update.path.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationLinkstateCaseBuilder().setDestinationLinkstate(
350                         new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.update.path.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.destination.linkstate._case.DestinationLinkstateBuilder().setCLinkstateDestination(
351                                 dst).build()).build()).build());
352     }
353
354     @Override
355     public void parseNlri(final ByteBuf nlri, final byte[] nextHop, final MpReachNlriBuilder builder) throws BGPParsingException {
356         if (!nlri.isReadable()) {
357             return;
358         }
359         final List<CLinkstateDestination> dst = parseNlri(nlri);
360
361         builder.setAdvertizedRoutes(new AdvertizedRoutesBuilder().setDestinationType(
362                 new DestinationLinkstateCaseBuilder().setDestinationLinkstate(
363                         new DestinationLinkstateBuilder().setCLinkstateDestination(dst).build()).build()).build());
364         NlriUtil.parseNextHop(nextHop, builder);
365     }
366
367     /**
368      * Serializes Linkstate NLRI to byte array. We need this as NLRI serves as a key in upper layers.
369      *
370      * @param destination Linkstate NLRI to be serialized
371      * @return byte array
372      */
373     public static byte[] serializeNlri(final CLinkstateDestination destination) {
374         final ByteBuf finalBuffer = Unpooled.buffer();
375         finalBuffer.writeShort(destination.getNlriType().getIntValue());
376         final ByteBuf buffer = Unpooled.buffer();
377         if (destination.getDistinguisher() != null) {
378             buffer.writeBytes(destination.getDistinguisher().getValue().toByteArray());
379         }
380         buffer.writeByte(destination.getProtocolId().getIntValue());
381         buffer.writeBytes(ByteArray.longToBytes(destination.getIdentifier().getValue().longValue(), IDENTIFIER_LENGTH));
382
383         // serialize local node descriptors
384         final byte[] ldescs = serializeNodeDescriptors(destination.getLocalNodeDescriptors());
385         buffer.writeShort(TlvCode.LOCAL_NODE_DESCRIPTORS);
386         buffer.writeShort(ldescs.length);
387         buffer.writeBytes(ldescs);
388
389         switch (destination.getNlriType()) {
390         case Ipv4Prefix:
391         case Ipv6Prefix:
392             if (destination.getPrefixDescriptors() != null) {
393                 serializePrefixDescriptors(buffer, destination.getPrefixDescriptors());
394             }
395             break;
396         case Link:
397             final byte[] rdescs = serializeNodeDescriptors(destination.getRemoteNodeDescriptors());
398             buffer.writeShort(TlvCode.REMOTE_NODE_DESCRIPTORS);
399             buffer.writeShort(rdescs.length);
400             buffer.writeBytes(rdescs);
401             if (destination.getLinkDescriptors() != null) {
402                 serializeLinkDescriptors(buffer, destination.getLinkDescriptors());
403             }
404             break;
405         case Node:
406             break;
407         default:
408             LOG.warn("Unknown NLRI Type.");
409             break;
410         }
411         finalBuffer.writeShort(buffer.readableBytes());
412         finalBuffer.writeBytes(buffer);
413         return ByteArray.subByte(finalBuffer.array(), 0, finalBuffer.readableBytes());
414     }
415
416     private static byte[] serializeNodeDescriptors(final NodeIdentifier descriptors) {
417         final ByteBuf buffer = Unpooled.buffer();
418         final int length = Integer.SIZE / Byte.SIZE;
419         if (descriptors.getAsNumber() != null) {
420             buffer.writeShort(TlvCode.AS_NUMBER);
421             buffer.writeShort(length);
422             buffer.writeInt(UnsignedInteger.valueOf(descriptors.getAsNumber().getValue()).intValue());
423         }
424         if (descriptors.getDomainId() != null) {
425             buffer.writeShort(TlvCode.BGP_LS_ID);
426             buffer.writeShort(length);
427             buffer.writeInt(UnsignedInteger.valueOf(descriptors.getDomainId().getValue()).intValue());
428         }
429         if (descriptors.getAreaId() != null) {
430             buffer.writeShort(TlvCode.AREA_ID);
431             buffer.writeShort(length);
432             buffer.writeInt(UnsignedInteger.valueOf(descriptors.getAreaId().getValue()).intValue());
433         }
434         if (descriptors.getCRouterIdentifier() != null) {
435             final byte[] value = serializeRouterId(descriptors.getCRouterIdentifier());
436             buffer.writeShort(TlvCode.IGP_ROUTER_ID);
437             buffer.writeShort(value.length);
438             buffer.writeBytes(value);
439         }
440         return ByteArray.readAllBytes(buffer);
441     }
442
443     private static byte[] serializeRouterId(final CRouterIdentifier routerId) {
444         byte[] bytes = null;
445         if (routerId instanceof IsisNodeCase) {
446             final IsisNode isis = ((IsisNodeCase) routerId).getIsisNode();
447             bytes = isis.getIsoSystemId().getValue();
448         } else if (routerId instanceof IsisPseudonodeCase) {
449             bytes = new byte[ISO_SYSTEM_ID_LENGTH + PSN_LENGTH];
450             final IsisPseudonode isis = ((IsisPseudonodeCase) routerId).getIsisPseudonode();
451             ByteArray.copyWhole(isis.getIsIsRouterIdentifier().getIsoSystemId().getValue(), bytes, 0);
452             bytes[6] = UnsignedBytes.checkedCast((isis.getPsn() != null) ? isis.getPsn() : 0);
453         } else if (routerId instanceof OspfNodeCase) {
454             bytes = ByteArray.uint32ToBytes(((OspfNodeCase) routerId).getOspfNode().getOspfRouterId());
455         } else if (routerId instanceof OspfPseudonodeCase) {
456             final OspfPseudonode node = ((OspfPseudonodeCase) routerId).getOspfPseudonode();
457             bytes = new byte[2 * Integer.SIZE / Byte.SIZE];
458             ByteArray.copyWhole(ByteArray.uint32ToBytes(node.getOspfRouterId()), bytes, 0);
459             ByteArray.copyWhole(ByteArray.uint32ToBytes(node.getLanInterface().getValue()), bytes, Integer.SIZE / Byte.SIZE);
460         }
461         return bytes;
462     }
463
464     private static void serializeLinkDescriptors(final ByteBuf buffer, final LinkDescriptors descriptors) {
465         if (descriptors.getLinkLocalIdentifier() != null && descriptors.getLinkRemoteIdentifier() != null) {
466             buffer.writeShort(TlvCode.LINK_LR_IDENTIFIERS);
467             buffer.writeShort(LINK_IDENTIFIER_LENGTH);
468             buffer.writeInt(UnsignedInteger.valueOf(descriptors.getLinkLocalIdentifier()).intValue());
469             buffer.writeInt(UnsignedInteger.valueOf(descriptors.getLinkRemoteIdentifier()).intValue());
470         }
471         if (descriptors.getIpv4InterfaceAddress() != null) {
472             final byte[] ipv4Address = Ipv4Util.bytesForAddress(descriptors.getIpv4InterfaceAddress());
473             buffer.writeShort(TlvCode.IPV4_IFACE_ADDRESS);
474             buffer.writeShort(ipv4Address.length);
475             buffer.writeBytes(ipv4Address);
476         }
477         if (descriptors.getIpv4NeighborAddress() != null) {
478             final byte[] ipv4Address = Ipv4Util.bytesForAddress(descriptors.getIpv4NeighborAddress());
479             buffer.writeShort(TlvCode.IPV4_NEIGHBOR_ADDRESS);
480             buffer.writeShort(ipv4Address.length);
481             buffer.writeBytes(ipv4Address);
482         }
483         if (descriptors.getIpv6InterfaceAddress() != null) {
484             final byte[] ipv6Address = Ipv6Util.bytesForAddress(descriptors.getIpv6InterfaceAddress());
485             buffer.writeShort(TlvCode.IPV6_IFACE_ADDRESS);
486             buffer.writeShort(ipv6Address.length);
487             buffer.writeBytes(ipv6Address);
488         }
489         if (descriptors.getIpv6NeighborAddress() != null) {
490             final byte[] ipv6Address = Ipv6Util.bytesForAddress(descriptors.getIpv6NeighborAddress());
491             buffer.writeShort(TlvCode.IPV6_NEIGHBOR_ADDRESS);
492             buffer.writeShort(ipv6Address.length);
493             buffer.writeBytes(ipv6Address);
494         }
495         if (descriptors.getMultiTopologyId() != null) {
496             buffer.writeShort(TlvCode.MULTI_TOPOLOGY_ID);
497             buffer.writeShort(Short.SIZE / Byte.SIZE);
498             buffer.writeShort(descriptors.getMultiTopologyId().getValue());
499         }
500     }
501
502     private static void serializePrefixDescriptors(final ByteBuf buffer, final PrefixDescriptors descriptors) {
503         if (descriptors.getMultiTopologyId() != null) {
504             buffer.writeShort(TlvCode.MULTI_TOPOLOGY_ID);
505             buffer.writeShort(Short.SIZE / Byte.SIZE);
506             buffer.writeShort(descriptors.getMultiTopologyId().getValue());
507         }
508         if (descriptors.getOspfRouteType() != null) {
509             buffer.writeShort(TlvCode.OSPF_ROUTE_TYPE);
510             buffer.writeShort(1);
511             buffer.writeByte(descriptors.getOspfRouteType().getIntValue());
512         }
513         if (descriptors.getIpReachabilityInformation() != null) {
514             final IpPrefix prefix = descriptors.getIpReachabilityInformation();
515             byte[] prefixBytes = null;
516             final int prefixLength = Ipv4Util.getPrefixLength(prefix);
517             if (prefix.getIpv4Prefix() != null) {
518                 prefixBytes = ByteArray.trim(ByteArray.subByte(Ipv4Util.bytesForPrefix(prefix.getIpv4Prefix()), 0,
519                         Ipv4Util.bytesForPrefix(prefix.getIpv4Prefix()).length - 1));
520             } else if (prefix.getIpv6Prefix() != null) {
521                 prefixBytes = ByteArray.trim(ByteArray.subByte(Ipv6Util.bytesForPrefix(prefix.getIpv6Prefix()), 0,
522                         Ipv6Util.bytesForPrefix(prefix.getIpv6Prefix()).length - 1));
523             }
524             buffer.writeShort(TlvCode.IP_REACHABILITY);
525             buffer.writeShort(1 + prefixBytes.length);
526             buffer.writeByte(prefixLength);
527             buffer.writeBytes(prefixBytes);
528         }
529     }
530 }