2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.protocol.bgp.linkstate;
10 import io.netty.buffer.ByteBuf;
11 import io.netty.buffer.Unpooled;
13 import java.math.BigInteger;
14 import java.util.Arrays;
15 import java.util.List;
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;
75 import com.google.common.collect.Lists;
76 import com.google.common.primitives.UnsignedBytes;
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;
84 private static final int TYPE_LENGTH = 2;
85 private static final int LENGTH_SIZE = 2;
87 private final boolean isVpn;
89 public LinkstateNlriParser(final boolean isVpn) {
93 private static NodeIdentifier parseLink(final CLinkstateDestinationBuilder builder, final byte[] bytes) throws BGPParsingException {
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),
103 byteOffset += length;
105 builder.setLinkDescriptors(parseLinkDescriptors(ByteArray.subByte(bytes, byteOffset, bytes.length - byteOffset)));
109 private static LinkDescriptors parseLinkDescriptors(final byte[] bytes) throws BGPParsingException {
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));
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());
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);
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);
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);
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);
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);
152 throw new BGPParsingException("Link Descriptor not recognized, type: " + type);
154 byteOffset += length;
156 LOG.trace("Finished parsing Link descriptors.");
157 return builder.build();
160 private static NodeIdentifier parseNodeDescriptors(final byte[] bytes, final boolean local) throws BGPParsingException {
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));
174 case TlvCode.AS_NUMBER:
175 asnumber = new AsNumber(ByteArray.bytesToLong(value));
176 LOG.debug("Parsed {}", asnumber);
178 case TlvCode.BGP_LS_ID:
179 bgpId = new DomainIdentifier(value);
180 LOG.debug("Parsed {}", bgpId);
182 case TlvCode.AREA_ID:
183 ai = new AreaIdentifier(value);
184 LOG.debug("Parsed area identifier {}", ai);
186 case TlvCode.IGP_ROUTER_ID:
187 routerId = parseRouterId(value);
188 LOG.debug("Parsed Router Identifier {}", routerId);
191 throw new BGPParsingException("Node Descriptor not recognized, type: " + type);
193 byteOffset += length;
195 LOG.trace("Finished parsing Node descriptors.");
196 return (local) ? new LocalNodeDescriptorsBuilder().setAsNumber(asnumber).setDomainId(bgpId).setAreaId(ai).setCRouterIdentifier(
198 : new RemoteNodeDescriptorsBuilder().setAsNumber(asnumber).setDomainId(bgpId).setAreaId(ai).setCRouterIdentifier(routerId).build();
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();
206 if (value.length == 7) {
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();
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();
218 if (value.length == 4) {
219 return new OspfNodeCaseBuilder().setOspfNode(new OspfNodeBuilder().setOspfRouterId(ByteArray.subByte(value, 0, 4)).build()).build();
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();
227 throw new BGPParsingException("Router Id of invalid length " + value.length);
230 private static PrefixDescriptors parsePrefixDescriptors(final NodeIdentifier localDescriptor, final byte[] bytes, final boolean ipv4)
231 throws BGPParsingException {
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));
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);
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);
253 builder.setOspfRouteType(routeType);
254 LOG.trace("Parser RouteType: {}", routeType);
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));
265 prefix = new IpPrefix(Ipv4Util.prefixForBytes(ByteArray.subByte(value, 1, size), prefixLength));
267 prefix = new IpPrefix(Ipv6Util.prefixForBytes(ByteArray.subByte(value, 1, size), prefixLength));
269 builder.setIpReachabilityInformation(prefix);
270 LOG.trace("Parsed IP reachability info: {}", prefix);
273 throw new BGPParsingException("Prefix Descriptor not recognized, type: " + type);
275 byteOffset += length;
277 LOG.debug("Finished parsing Prefix descriptors.");
278 return builder.build();
282 * Parses common parts for Link State Nodes, Links and Prefixes, that includes protocol ID and identifier tlv.
285 * @return BGPLinkMP or BGPNodeMP
286 * @throws BGPParsingException
288 private List<CLinkstateDestination> parseNlri(final byte[] nlri) throws BGPParsingException {
289 if (nlri.length == 0) {
294 final List<CLinkstateDestination> dests = Lists.newArrayList();
296 CLinkstateDestinationBuilder builder = null;
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);
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;
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;
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);
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);
326 // if we are dealing with linkstate nodes/links, parse local node descriptor
327 NodeIdentifier localDescriptor = null;
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);
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);
343 parseLink(builder, ByteArray.subByte(nlri, byteOffset, restLength));
346 builder.setPrefixDescriptors(parsePrefixDescriptors(localDescriptor, ByteArray.subByte(nlri, byteOffset, restLength), true));
349 builder.setPrefixDescriptors(parsePrefixDescriptors(localDescriptor, ByteArray.subByte(nlri, byteOffset, restLength), false));
352 // node nlri is already parsed as it contains only the common fields for node and link nlri
355 byteOffset += restLength;
356 dests.add(builder.build());
362 public final void parseNlri(final byte[] nlri, final MpUnreachNlriBuilder builder) throws BGPParsingException {
363 if (nlri.length == 0) {
366 final List<CLinkstateDestination> dst = parseNlri(nlri);
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());
375 public void parseNlri(final byte[] nlri, final byte[] nextHop, final MpReachNlriBuilder builder) throws BGPParsingException {
376 final List<CLinkstateDestination> dst = parseNlri(nlri);
378 builder.setAdvertizedRoutes(new AdvertizedRoutesBuilder().setDestinationType(
379 new DestinationLinkstateCaseBuilder().setDestinationLinkstate(
380 new DestinationLinkstateBuilder().setCLinkstateDestination(dst).build()).build()).build());
381 NlriUtil.parseNextHop(nextHop, builder);
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());
391 buffer.writeByte(destination.getProtocolId().getIntValue());
392 buffer.writeBytes(ByteArray.longToBytes(destination.getIdentifier().getValue().longValue(), IDENTIFIER_LENGTH));
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);
400 switch (destination.getNlriType()) {
403 if (destination.getPrefixDescriptors() != null) {
404 serializePrefixDescriptors(buffer, destination.getPrefixDescriptors());
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());
419 LOG.warn("Unknown NLRI Type.");
422 finalBuffer.writeShort(buffer.readableBytes());
423 finalBuffer.writeBytes(buffer);
424 return ByteArray.subByte(finalBuffer.array(), 0, finalBuffer.readableBytes());
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));
435 if (descriptors.getDomainId() != null) {
436 buffer.writeShort(TlvCode.BGP_LS_ID);
437 buffer.writeShort(length);
438 buffer.writeBytes(descriptors.getDomainId().getValue());
440 if (descriptors.getAreaId() != null) {
441 buffer.writeShort(TlvCode.AREA_ID);
442 buffer.writeShort(length);
443 buffer.writeBytes(descriptors.getAreaId().getValue());
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);
451 return ByteArray.subByte(buffer.array(), 0, buffer.readableBytes());
454 private static byte[] serializeRouterId(final CRouterIdentifier routerId) {
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);
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);
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);
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);
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);
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);
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());
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());
521 if (descriptors.getOspfRouteType() != null) {
522 buffer.writeShort(TlvCode.OSPF_ROUTE_TYPE);
523 buffer.writeShort(1);
524 buffer.writeByte(descriptors.getOspfRouteType().getIntValue());
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));
537 buffer.writeShort(TlvCode.IP_REACHABILITY);
538 buffer.writeShort(1 + prefixBytes.length);
539 buffer.writeByte(prefixLength);
540 buffer.writeBytes(prefixBytes);