c40ffb67e8105023acc4e05e9aa3e2ff40383a90
[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 java.math.BigInteger;
11 import java.util.Arrays;
12 import java.util.List;
13
14 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
15 import org.opendaylight.protocol.bgp.parser.spi.NlriParser;
16 import org.opendaylight.protocol.bgp.parser.spi.NlriUtil;
17 import org.opendaylight.protocol.concepts.Ipv4Util;
18 import org.opendaylight.protocol.concepts.Ipv6Util;
19 import org.opendaylight.protocol.util.ByteArray;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.AreaIdentifier;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.DomainIdentifier;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.Identifier;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.Ipv4InterfaceIdentifier;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.Ipv6InterfaceIdentifier;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.NlriType;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.NodeIdentifier;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.OspfInterfaceIdentifier;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.OspfRouteType;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.ProtocolId;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.RouteDistinguisher;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.TopologyIdentifier;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.isis.lan.identifier.IsIsRouterIdentifier;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.isis.lan.identifier.IsIsRouterIdentifierBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.linkstate.destination.CLinkstateDestination;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.linkstate.destination.CLinkstateDestinationBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.linkstate.destination.c.linkstate.destination.LinkDescriptors;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.linkstate.destination.c.linkstate.destination.LinkDescriptorsBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.linkstate.destination.c.linkstate.destination.LocalNodeDescriptors;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.linkstate.destination.c.linkstate.destination.LocalNodeDescriptorsBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.linkstate.destination.c.linkstate.destination.PrefixDescriptors;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.linkstate.destination.c.linkstate.destination.PrefixDescriptorsBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.linkstate.destination.c.linkstate.destination.RemoteNodeDescriptors;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.linkstate.destination.c.linkstate.destination.RemoteNodeDescriptorsBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.node.identifier.CRouterIdentifier;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.node.identifier.c.router.identifier.CIsisNodeBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.node.identifier.c.router.identifier.CIsisPseudonodeBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.node.identifier.c.router.identifier.COspfNodeBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.node.identifier.c.router.identifier.COspfPseudonodeBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.node.identifier.c.router.identifier.c.isis.node.IsisNodeBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.node.identifier.c.router.identifier.c.isis.pseudonode.IsisPseudonodeBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.node.identifier.c.router.identifier.c.ospf.node.OspfNodeBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.node.identifier.c.router.identifier.c.ospf.pseudonode.OspfPseudonodeBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.update.path.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationLinkstateBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.update.path.attributes.MpReachNlriBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.update.path.attributes.MpUnreachNlriBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.update.path.attributes.mp.reach.nlri.AdvertizedRoutesBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.update.path.attributes.mp.unreach.nlri.WithdrawnRoutesBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nps.concepts.rev130930.IsoSystemIdentifier;
61 import org.slf4j.Logger;
62 import org.slf4j.LoggerFactory;
63
64 import com.google.common.collect.Lists;
65 import com.google.common.primitives.UnsignedBytes;
66
67 public final class LinkstateNlriParser implements NlriParser {
68         private static final Logger logger = LoggerFactory.getLogger(LinkstateNlriParser.class);
69         private static final int ROUTE_DISTINGUISHER_LENGTH = 8;
70         private static final int PROTOCOL_ID_LENGTH = 1;
71         private static final int IDENTIFIER_LENGTH = 8;
72
73         private static final int TYPE_LENGTH = 2;
74         private static final int LENGTH_SIZE = 2;
75
76         private final boolean isVpn;
77
78         public LinkstateNlriParser(final boolean isVpn) {
79                 this.isVpn = isVpn;
80         }
81
82         private static NodeIdentifier parseLink(final CLinkstateDestinationBuilder builder, final byte[] bytes) throws BGPParsingException {
83                 int byteOffset = 0;
84                 final int type = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, TYPE_LENGTH));
85                 byteOffset += TYPE_LENGTH;
86                 final int length = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, LENGTH_SIZE));
87                 byteOffset += LENGTH_SIZE;
88                 final NodeIdentifier remote = null;
89                 if (type == 257) {
90                         builder.setRemoteNodeDescriptors((RemoteNodeDescriptors) parseNodeDescriptors(ByteArray.subByte(bytes, byteOffset, length),
91                                         false));
92                         byteOffset += length;
93                 }
94                 builder.setLinkDescriptors(parseLinkDescriptors(ByteArray.subByte(bytes, byteOffset, bytes.length - byteOffset)));
95                 return remote;
96         }
97
98         private static LinkDescriptors parseLinkDescriptors(final byte[] bytes) throws BGPParsingException {
99                 int byteOffset = 0;
100                 final LinkDescriptorsBuilder builder = new LinkDescriptorsBuilder();
101                 while (byteOffset != bytes.length) {
102                         final int type = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, TYPE_LENGTH));
103                         byteOffset += TYPE_LENGTH;
104                         final int length = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, LENGTH_SIZE));
105                         byteOffset += LENGTH_SIZE;
106                         final byte[] value = ByteArray.subByte(bytes, byteOffset, length);
107                         logger.trace("Parsing Link Descriptor: {}", Arrays.toString(value));
108                         switch (type) {
109                         case 258:
110                                 builder.setLinkLocalIdentifier(ByteArray.subByte(value, 0, 4));
111                                 builder.setLinkRemoteIdentifier(ByteArray.subByte(value, 4, 4));
112                                 logger.debug("Parsed link local {} remote {} Identifiers.", builder.getLinkLocalIdentifier(),
113                                                 builder.getLinkRemoteIdentifier());
114                                 break;
115                         case 259:
116                                 final Ipv4InterfaceIdentifier lipv4 = new Ipv4InterfaceIdentifier(Ipv4Util.addressForBytes(value));
117                                 builder.setIpv4InterfaceAddress(lipv4);
118                                 logger.debug("Parsed IPv4 interface address {}.", lipv4);
119                                 break;
120                         case 260:
121                                 final Ipv4InterfaceIdentifier ripv4 = new Ipv4InterfaceIdentifier(Ipv4Util.addressForBytes(value));
122                                 builder.setIpv4NeighborAddress(ripv4);
123                                 logger.debug("Parsed IPv4 neighbor address {}.", ripv4);
124                                 break;
125                         case 261:
126                                 final Ipv6InterfaceIdentifier lipv6 = new Ipv6InterfaceIdentifier(Ipv6Util.addressForBytes(value));
127                                 builder.setIpv6InterfaceAddress(lipv6);
128                                 logger.debug("Parsed IPv6 interface address {}.", lipv6);
129                                 break;
130                         case 262:
131                                 final Ipv6InterfaceIdentifier ripv6 = new Ipv6InterfaceIdentifier(Ipv6Util.addressForBytes(value));
132                                 builder.setIpv6NeighborAddress(ripv6);
133                                 logger.debug("Parsed IPv6 neighbor address {}.", ripv6);
134                                 break;
135                         case 263:
136                                 final TopologyIdentifier topId = new TopologyIdentifier(ByteArray.bytesToInt(value) & 0x3fff);
137                                 builder.setMultiTopologyId(topId);
138                                 logger.debug("Parsed topology identifier {}.", topId);
139                                 break;
140                         default:
141                                 throw new BGPParsingException("Link Descriptor not recognized, type: " + type);
142                         }
143                         byteOffset += length;
144                 }
145                 logger.trace("Finished parsing Link descriptors.");
146                 return builder.build();
147         }
148
149         private static NodeIdentifier parseNodeDescriptors(final byte[] bytes, final boolean local) throws BGPParsingException {
150                 int byteOffset = 0;
151                 AsNumber asnumber = null;
152                 DomainIdentifier bgpId = null;
153                 AreaIdentifier ai = null;
154                 CRouterIdentifier routerId = null;
155                 while (byteOffset != bytes.length) {
156                         final int type = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, TYPE_LENGTH));
157                         byteOffset += TYPE_LENGTH;
158                         final int length = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, LENGTH_SIZE));
159                         byteOffset += LENGTH_SIZE;
160                         final byte[] value = ByteArray.subByte(bytes, byteOffset, length);
161                         logger.trace("Parsing Node Descriptor: {}", Arrays.toString(value));
162                         switch (type) {
163                         case 512:
164                                 asnumber = new AsNumber(ByteArray.bytesToLong(value));
165                                 logger.debug("Parsed {}", asnumber);
166                                 break;
167                         case 513:
168                                 bgpId = new DomainIdentifier(value);
169                                 logger.debug("Parsed {}", bgpId);
170                                 break;
171                         case 514:
172                                 ai = new AreaIdentifier(value);
173                                 logger.debug("Parsed area identifier {}", ai);
174                                 break;
175                         case 515:
176                                 routerId = parseRouterId(value);
177                                 logger.debug("Parsed Router Identifier {}", routerId);
178                                 break;
179                         default:
180                                 throw new BGPParsingException("Node Descriptor not recognized, type: " + type);
181                         }
182                         byteOffset += length;
183                 }
184                 logger.trace("Finished parsing Node descriptors.");
185                 return (local) ? new LocalNodeDescriptorsBuilder().setAsNumber(asnumber).setDomainId(bgpId).setAreaId(ai).setCRouterIdentifier(
186                                 routerId).build()
187                                 : new RemoteNodeDescriptorsBuilder().setAsNumber(asnumber).setDomainId(bgpId).setAreaId(ai).setCRouterIdentifier(routerId).build();
188         }
189
190         private static CRouterIdentifier parseRouterId(final byte[] value) throws BGPParsingException {
191                 if (value.length == 6) {
192                         return new CIsisNodeBuilder().setIsisNode(
193                                         new IsisNodeBuilder().setIsoSystemId(new IsoSystemIdentifier(ByteArray.subByte(value, 0, 6))).build()).build();
194                 }
195                 if (value.length == 7) {
196                         if (value[6] == 0) {
197                                 logger.warn("PSN octet is 0. Ignoring System ID.");
198                                 return new CIsisNodeBuilder().setIsisNode(
199                                                 new IsisNodeBuilder().setIsoSystemId(new IsoSystemIdentifier(ByteArray.subByte(value, 0, 6))).build()).build();
200                         } else {
201                                 final IsIsRouterIdentifier iri = new IsIsRouterIdentifierBuilder().setIsoSystemId(
202                                                 new IsoSystemIdentifier(ByteArray.subByte(value, 0, 6))).build();
203                                 return new CIsisPseudonodeBuilder().setIsisPseudonode(
204                                                 new IsisPseudonodeBuilder().setIsIsRouterIdentifier(iri).setPsn((short) UnsignedBytes.toInt(value[6])).build()).build();
205                         }
206                 }
207                 if (value.length == 4) {
208                         return new COspfNodeBuilder().setOspfNode(new OspfNodeBuilder().setOspfRouterId(ByteArray.subByte(value, 0, 4)).build()).build();
209                 }
210                 if (value.length == 8) {
211                         final byte[] o = ByteArray.subByte(value, 0, 4); // FIXME: OSPFv3 vs OSPFv2
212                         final OspfInterfaceIdentifier a = new OspfInterfaceIdentifier(ByteArray.subByte(value, 4, 4));
213                         return new COspfPseudonodeBuilder().setOspfPseudonode(new OspfPseudonodeBuilder().setOspfRouterId(o).setLanInterface(a).build()).build();
214                 }
215                 throw new BGPParsingException("Router Id of invalid length " + value.length);
216         }
217
218         private static PrefixDescriptors parsePrefixDescriptors(final NodeIdentifier localDescriptor, final byte[] bytes)
219                         throws BGPParsingException {
220                 int byteOffset = 0;
221                 final PrefixDescriptorsBuilder builder = new PrefixDescriptorsBuilder();
222                 while (byteOffset != bytes.length) {
223                         final int type = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, TYPE_LENGTH));
224                         byteOffset += TYPE_LENGTH;
225                         final int length = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, LENGTH_SIZE));
226                         byteOffset += LENGTH_SIZE;
227                         final byte[] value = ByteArray.subByte(bytes, byteOffset, length);
228                         logger.trace("Parsing Prefix Descriptor: {}", Arrays.toString(value));
229                         switch (type) {
230                         case 263:
231                                 final TopologyIdentifier topologyId = new TopologyIdentifier(ByteArray.bytesToInt(value) & 0x3fff);
232                                 builder.setMultiTopologyId(topologyId);
233                                 logger.trace("Parsed Topology Identifier: {}", topologyId);
234                                 break;
235                         case 264:
236                                 final int rt = ByteArray.bytesToInt(value);
237                                 final OspfRouteType routeType = OspfRouteType.forValue(rt);
238                                 if (routeType == null) {
239                                         throw new BGPParsingException("Unknown OSPF Route Type: " + rt);
240                                 }
241                                 builder.setOspfRouteType(routeType);
242                                 logger.trace("Parser RouteType: {}", routeType);
243                                 break;
244                         case 265:
245                                 IpPrefix prefix = null;
246                                 final int prefixLength = UnsignedBytes.toInt(value[0]);
247                                 final int size = prefixLength / 8 + ((prefixLength % 8 == 0) ? 0 : 1);
248                                 if (size != value.length - 1) {
249                                         logger.debug("Expected length {}, actual length {}.", size, value.length - 1);
250                                         throw new BGPParsingException("Illegal length of IP reachability TLV: " + (value.length - 1));
251                                 }
252                                 if (size == 4) {
253                                         prefix = new IpPrefix(Ipv4Util.prefixForBytes(ByteArray.subByte(value, 1, size), prefixLength));
254                                 } else {
255                                         prefix = new IpPrefix(Ipv6Util.prefixForBytes(ByteArray.subByte(value, 1, size), prefixLength));
256                                 }
257                                 builder.setIpReachabilityInformation(prefix);
258                                 logger.trace("Parsed IP reachability info: {}", prefix);
259                                 break;
260                         default:
261                                 throw new BGPParsingException("Prefix Descriptor not recognized, type: " + type);
262                         }
263                         byteOffset += length;
264                 }
265                 logger.debug("Finished parsing Prefix descriptors.");
266                 return builder.build();
267         }
268
269         /**
270          * Parses common parts for Link State Nodes, Links and Prefixes, that includes protocol ID and identifier tlv.
271          * 
272          * @param nlri
273          * @return BGPLinkMP or BGPNodeMP
274          * @throws BGPParsingException
275          */
276         private List<CLinkstateDestination> parseNlri(final byte[] nlri) throws BGPParsingException {
277                 if (nlri.length == 0) {
278                         return null;
279                 }
280                 int byteOffset = 0;
281
282                 final List<CLinkstateDestination> dests = Lists.newArrayList();
283
284                 CLinkstateDestinationBuilder builder = null;
285
286                 while (byteOffset != nlri.length) {
287                         builder = new CLinkstateDestinationBuilder();
288                         final NlriType type = NlriType.forValue(ByteArray.bytesToInt(ByteArray.subByte(nlri, byteOffset, TYPE_LENGTH)));
289                         builder.setNlriType(type);
290
291                         byteOffset += TYPE_LENGTH;
292                         // length means total length of the tlvs including route distinguisher not including the type field
293                         final int length = ByteArray.bytesToInt(ByteArray.subByte(nlri, byteOffset, LENGTH_SIZE));
294                         byteOffset += LENGTH_SIZE;
295                         RouteDistinguisher distinguisher = null;
296                         if (this.isVpn) {
297                                 // this parses route distinguisher
298                                 distinguisher = new RouteDistinguisher(BigInteger.valueOf(ByteArray.bytesToLong(ByteArray.subByte(nlri, byteOffset,
299                                                 ROUTE_DISTINGUISHER_LENGTH))));
300                                 builder.setDistinguisher(distinguisher);
301                                 byteOffset += ROUTE_DISTINGUISHER_LENGTH;
302                         }
303                         // parse source protocol
304                         final ProtocolId sp = ProtocolId.forValue(ByteArray.bytesToInt(ByteArray.subByte(nlri, byteOffset, PROTOCOL_ID_LENGTH)));
305                         byteOffset += PROTOCOL_ID_LENGTH;
306                         builder.setProtocolId(sp);
307
308                         // parse identifier
309                         final Identifier identifier = new Identifier(BigInteger.valueOf(ByteArray.bytesToLong(ByteArray.subByte(nlri, byteOffset,
310                                         IDENTIFIER_LENGTH))));
311                         byteOffset += IDENTIFIER_LENGTH;
312                         builder.setIdentifier(identifier);
313
314                         // if we are dealing with linkstate nodes/links, parse local node descriptor
315                         NodeIdentifier localDescriptor = null;
316                         int locallength = 0;
317                         final int localtype = ByteArray.bytesToInt(ByteArray.subByte(nlri, byteOffset, TYPE_LENGTH));
318                         byteOffset += TYPE_LENGTH;
319                         locallength = ByteArray.bytesToInt(ByteArray.subByte(nlri, byteOffset, LENGTH_SIZE));
320                         byteOffset += LENGTH_SIZE;
321                         if (localtype == 256) {
322                                 localDescriptor = parseNodeDescriptors(ByteArray.subByte(nlri, byteOffset, locallength), true);
323                         }
324                         byteOffset += locallength;
325                         builder.setLocalNodeDescriptors((LocalNodeDescriptors) localDescriptor);
326                         final int restLength = length - (this.isVpn ? ROUTE_DISTINGUISHER_LENGTH : 0) - PROTOCOL_ID_LENGTH - IDENTIFIER_LENGTH
327                                         - TYPE_LENGTH - LENGTH_SIZE - locallength;
328                         logger.trace("Restlength {}", restLength);
329                         switch (type) {
330                         case Link:
331                                 parseLink(builder, ByteArray.subByte(nlri, byteOffset, restLength));
332                                 break;
333                         case Ipv4Prefix:
334                         case Ipv6Prefix:
335                                 builder.setPrefixDescriptors(parsePrefixDescriptors(localDescriptor, ByteArray.subByte(nlri, byteOffset, restLength)));
336                                 break;
337                         case Node:
338                                 // node nlri is already parsed as it contains only the common fields for node and link nlri
339                                 break;
340                         }
341                         byteOffset += restLength;
342                         dests.add(builder.build());
343                 }
344                 return dests;
345         }
346
347         @Override
348         public final void parseNlri(final byte[] nlri, final MpUnreachNlriBuilder builder) throws BGPParsingException {
349                 if (nlri.length == 0) {
350                         return;
351                 }
352                 final List<CLinkstateDestination> dst = parseNlri(nlri);
353
354                 builder.setWithdrawnRoutes(new WithdrawnRoutesBuilder().setDestinationType(
355                                 new DestinationLinkstateBuilder().setCLinkstateDestination(dst).build()).build());
356         }
357
358         @Override
359         public void parseNlri(final byte[] nlri, final byte[] nextHop, final MpReachNlriBuilder builder) throws BGPParsingException {
360                 final List<CLinkstateDestination> dst = parseNlri(nlri);
361
362                 builder.setAdvertizedRoutes(new AdvertizedRoutesBuilder().setDestinationType(
363                                 new DestinationLinkstateBuilder().setCLinkstateDestination(dst).build()).build());
364                 NlriUtil.parseNextHop(nextHop, builder);
365         }
366
367         public static byte[] serializeNlri(final CLinkstateDestination destination) {
368                 // FIXME: BUG-108: finish this
369                 throw new UnsupportedOperationException("BUG-108: not implemented");
370         }
371 }