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