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