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