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.parser.impl.message.update;
10 import java.util.Arrays;
11 import java.util.HashMap;
12 import java.util.List;
14 import java.util.Map.Entry;
16 import java.util.SortedSet;
18 import org.opendaylight.protocol.bgp.concepts.BGPSubsequentAddressFamily;
19 import org.opendaylight.protocol.bgp.concepts.NextHop;
20 import org.opendaylight.protocol.bgp.linkstate.AdministrativeGroup;
21 import org.opendaylight.protocol.bgp.linkstate.AreaIdentifier;
22 import org.opendaylight.protocol.bgp.linkstate.DomainIdentifier;
23 import org.opendaylight.protocol.bgp.linkstate.ExtendedRouteTag;
24 import org.opendaylight.protocol.bgp.linkstate.IPv4InterfaceIdentifier;
25 import org.opendaylight.protocol.bgp.linkstate.IPv4PrefixIdentifier;
26 import org.opendaylight.protocol.bgp.linkstate.IPv4RouterIdentifier;
27 import org.opendaylight.protocol.bgp.linkstate.IPv6InterfaceIdentifier;
28 import org.opendaylight.protocol.bgp.linkstate.IPv6PrefixIdentifier;
29 import org.opendaylight.protocol.bgp.linkstate.IPv6RouterIdentifier;
30 import org.opendaylight.protocol.bgp.linkstate.ISISAreaIdentifier;
31 import org.opendaylight.protocol.bgp.linkstate.ISISLANIdentifier;
32 import org.opendaylight.protocol.bgp.linkstate.ISISNetworkPrefixState;
33 import org.opendaylight.protocol.bgp.linkstate.ISISRouterIdentifier;
34 import org.opendaylight.protocol.bgp.linkstate.InterfaceIdentifier;
35 import org.opendaylight.protocol.bgp.linkstate.LinkAnchor;
36 import org.opendaylight.protocol.bgp.linkstate.LinkIdentifier;
37 import org.opendaylight.protocol.bgp.linkstate.LinkProtectionType;
38 import org.opendaylight.protocol.bgp.linkstate.MPLSProtocol;
39 import org.opendaylight.protocol.bgp.linkstate.NetworkLinkImpl;
40 import org.opendaylight.protocol.bgp.linkstate.NetworkLinkState;
41 import org.opendaylight.protocol.bgp.linkstate.NetworkNodeImpl;
42 import org.opendaylight.protocol.bgp.linkstate.NetworkObjectState;
43 import org.opendaylight.protocol.bgp.linkstate.NetworkPrefixState;
44 import org.opendaylight.protocol.bgp.linkstate.NodeIdentifier;
45 import org.opendaylight.protocol.bgp.linkstate.OSPFInterfaceIdentifier;
46 import org.opendaylight.protocol.bgp.linkstate.OSPFNetworkPrefixState;
47 import org.opendaylight.protocol.bgp.linkstate.OSPFPrefixIdentifier;
48 import org.opendaylight.protocol.bgp.linkstate.OSPFRouteType;
49 import org.opendaylight.protocol.bgp.linkstate.OSPFRouterIdentifier;
50 import org.opendaylight.protocol.bgp.linkstate.OSPFv3LANIdentifier;
51 import org.opendaylight.protocol.bgp.linkstate.PrefixIdentifier;
52 import org.opendaylight.protocol.bgp.linkstate.RouteTag;
53 import org.opendaylight.protocol.bgp.linkstate.RouterIdentifier;
54 import org.opendaylight.protocol.bgp.linkstate.SourceProtocol;
55 import org.opendaylight.protocol.bgp.linkstate.TopologyIdentifier;
56 import org.opendaylight.protocol.bgp.linkstate.TopologyNodeInformation;
57 import org.opendaylight.protocol.bgp.linkstate.UnnumberedLinkIdentifier;
58 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
59 import org.opendaylight.protocol.bgp.parser.impl.BGPLinkMP;
60 import org.opendaylight.protocol.bgp.parser.impl.BGPNodeMP;
61 import org.opendaylight.protocol.bgp.parser.impl.ByteList;
62 import org.opendaylight.protocol.bgp.parser.impl.MPReach;
63 import org.opendaylight.protocol.concepts.ASNumber;
64 import org.opendaylight.protocol.concepts.Bandwidth;
65 import org.opendaylight.protocol.concepts.IGPMetric;
66 import org.opendaylight.protocol.concepts.IPv4Address;
67 import org.opendaylight.protocol.concepts.IPv4Prefix;
68 import org.opendaylight.protocol.concepts.IPv6;
69 import org.opendaylight.protocol.concepts.IPv6Address;
70 import org.opendaylight.protocol.concepts.IPv6Prefix;
71 import org.opendaylight.protocol.concepts.ISOSystemIdentifier;
72 import org.opendaylight.protocol.concepts.Metric;
73 import org.opendaylight.protocol.concepts.Prefix;
74 import org.opendaylight.protocol.concepts.SharedRiskLinkGroup;
75 import org.opendaylight.protocol.concepts.TEMetric;
76 import org.opendaylight.protocol.util.ByteArray;
77 import org.slf4j.Logger;
78 import org.slf4j.LoggerFactory;
80 import com.google.common.base.Charsets;
81 import com.google.common.collect.Lists;
82 import com.google.common.collect.Maps;
83 import com.google.common.collect.Sets;
84 import com.google.common.primitives.UnsignedBytes;
87 * Parser for Link State information.
89 * @see <a href="http://tools.ietf.org/html/draft-gredler-idr-ls-distribution-01">BGP-LS draft</a>
91 public class LinkStateParser {
93 private static final Logger logger = LoggerFactory.getLogger(LinkStateParser.class);
95 private static final int TYPE_LENGTH = 2;
97 private static final int LENGTH_SIZE = 2;
99 private static final int ROUTE_DISTINGUISHER_LENGTH = 8;
101 private static final int PROTOCOL_ID_LENGTH = 1;
103 private static final int IDENTIFIER_LENGTH = 8;
105 private static final Set<Integer> nodeTlvs = Sets.newHashSet(263, 1024, 1025, 1026, 1027, 1028, 1029);
107 private static final Set<Integer> linkTlvs = Sets.newHashSet(1028, 1029, 1030, 1031, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095,
110 private static final Set<Integer> prefixTlvs = Sets.newHashSet(1152, 1153, 1154, 1155, 1156, 1157);
112 private enum NlriType {
113 LinkNLRI, NodeNLRI, IPv4Prefixes, IPv6Prefixes
116 private LinkStateParser() {
120 * Parses common parts for Link State Nodes, Links and Prefixes, that includes protocol ID and identifier tlv.
125 * @return BGPLinkMP or BGPNodeMP
126 * @throws BGPParsingException
128 protected static MPReach<?> parseLSNlri(final boolean reachable, final BGPSubsequentAddressFamily safi, final NextHop<?> nextHop,
129 final byte[] bytes) throws BGPParsingException {
130 if (bytes.length == 0)
133 final Set<LinkIdentifier> links = Sets.newHashSet();
134 final Set<NodeIdentifier> nodes = Sets.newHashSet();
135 final Set<PrefixIdentifier<?>> descs = Sets.newHashSet();
138 SourceProtocol sp = null;
140 while (byteOffset != bytes.length) {
141 final NlriType type = parseNLRItype(ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, TYPE_LENGTH)));
142 byteOffset += TYPE_LENGTH;
143 // length means total length of the tlvs including route distinguisher not including the type field
144 final int length = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, LENGTH_SIZE));
145 byteOffset += LENGTH_SIZE;
146 if (safi == BGPSubsequentAddressFamily.MPLSLabeledVPN) {
147 // this parses route distinguisher
148 ByteArray.bytesToLong(ByteArray.subByte(bytes, byteOffset, ROUTE_DISTINGUISHER_LENGTH));
149 byteOffset += ROUTE_DISTINGUISHER_LENGTH;
151 // parse source protocol
152 sp = parseProtocolId(ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, PROTOCOL_ID_LENGTH)));
153 byteOffset += PROTOCOL_ID_LENGTH;
156 identifier = ByteArray.bytesToLong(ByteArray.subByte(bytes, byteOffset, IDENTIFIER_LENGTH));
157 byteOffset += IDENTIFIER_LENGTH;
159 // if we are dealing with linkstate nodes/links, parse local node descriptor
160 NodeIdentifier localDescriptor = null;
162 final int localtype = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, TYPE_LENGTH));
163 byteOffset += TYPE_LENGTH;
164 locallength = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, LENGTH_SIZE));
165 byteOffset += LENGTH_SIZE;
166 if (localtype == 256) {
167 localDescriptor = parseNodeDescriptors(ByteArray.subByte(bytes, byteOffset, locallength));
169 byteOffset += locallength;
170 final int restLength = length - ((safi == BGPSubsequentAddressFamily.MPLSLabeledVPN) ? ROUTE_DISTINGUISHER_LENGTH : 0)
171 - PROTOCOL_ID_LENGTH - IDENTIFIER_LENGTH - TYPE_LENGTH - LENGTH_SIZE - locallength;
172 logger.debug("Restlength {}", restLength);
175 links.add(parseLink(localDescriptor, sp, ByteArray.subByte(bytes, byteOffset, restLength)));
179 descs.add(parsePrefixDescriptors(localDescriptor, ByteArray.subByte(bytes, byteOffset, restLength)));
182 // node nlri is already parsed as it contains only the common fields for node and link nlri
183 nodes.add(localDescriptor);
186 byteOffset += restLength;
188 if (!links.isEmpty())
189 return new BGPLinkMP(identifier, sp, reachable, links);
190 else if (!nodes.isEmpty())
191 return new BGPNodeMP(identifier, sp, reachable, nodes);
192 // else if (!descs.isEmpty())
193 // return new BGPIPv4PrefixMP(identifier, sp, descs, reachable);
197 protected static Map<Integer, ByteList> parseLinkState(final byte[] bytes) {
198 final Map<Integer, ByteList> map = new HashMap<Integer, ByteList>();
200 while (byteOffset != bytes.length) {
201 final int type = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, TYPE_LENGTH));
202 byteOffset += TYPE_LENGTH;
203 final int length = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, LENGTH_SIZE));
204 byteOffset += LENGTH_SIZE;
205 final byte[] value = ByteArray.subByte(bytes, byteOffset, length);
206 ByteList values = map.containsKey(type) ? values = map.get(type) : new ByteList();
208 map.put(type, values);
209 byteOffset += length;
214 public static boolean verifyLink(final Set<Integer> keys) {
215 for (final Integer i : keys)
216 if (!linkTlvs.contains(i)) {
217 logger.warn("Invalid link attribute {}", i);
223 public static boolean verifyNode(final Set<Integer> keys) {
224 for (final Integer i : keys)
225 if (!nodeTlvs.contains(i)) {
226 logger.warn("Invalid node attribute {}", i);
232 public static boolean verifyPrefix(final Set<Integer> keys) {
233 for (final Integer i : keys)
234 if (!prefixTlvs.contains(i)) {
235 logger.warn("Invalid prefix attribute {}", i);
242 * Parse protocol ID from int to enum
244 * @param protocolId int parsed from byte array
245 * @return enum SourceProtocol
246 * @throws BGPParsingException if the type is unrecognized
248 private static SourceProtocol parseProtocolId(final int protocolId) throws BGPParsingException {
249 switch (protocolId) {
251 return SourceProtocol.Unknown;
253 return SourceProtocol.ISISLevel1;
255 return SourceProtocol.ISISLevel2;
257 return SourceProtocol.OSPF;
259 return SourceProtocol.Direct;
261 return SourceProtocol.Static;
263 throw new BGPParsingException("Unknown Source Protocol ID: " + protocolId);
267 private static OSPFRouteType parseRouteType(final int type) throws BGPParsingException {
270 return null; // for IS-IS it needs to be 0
272 return OSPFRouteType.Intra_Area;
274 return OSPFRouteType.Inter_Area;
276 return OSPFRouteType.External1;
278 return OSPFRouteType.External2;
280 return OSPFRouteType.NSSA1;
282 return OSPFRouteType.NSSA2;
284 throw new BGPParsingException("Unknown OSPF Route Type: " + type);
288 private static LinkIdentifier parseLink(final NodeIdentifier local, final SourceProtocol spi, final byte[] bytes)
289 throws BGPParsingException {
291 final int type = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, TYPE_LENGTH));
292 byteOffset += TYPE_LENGTH;
293 final int length = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, LENGTH_SIZE));
294 byteOffset += LENGTH_SIZE;
295 NodeIdentifier remote = null;
297 remote = parseNodeDescriptors(ByteArray.subByte(bytes, byteOffset, length));
298 byteOffset += length;
301 return parseLinkDescriptors(local, remote, ByteArray.subByte(bytes, byteOffset, bytes.length - byteOffset));
305 * Parse Link Descriptors.
309 * @param remoteAnchor
312 * @throws BGPParsingException
314 private static LinkIdentifier parseLinkDescriptors(final NodeIdentifier local, final NodeIdentifier remote, final byte[] bytes)
315 throws BGPParsingException {
317 final List<InterfaceIdentifier> localIdentifiers = Lists.newArrayList();
318 final List<InterfaceIdentifier> remoteIdentifiers = Lists.newArrayList();
319 TopologyIdentifier topId = null;
320 while (byteOffset != bytes.length) {
321 final int type = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, TYPE_LENGTH));
322 byteOffset += TYPE_LENGTH;
323 final int length = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, LENGTH_SIZE));
324 byteOffset += LENGTH_SIZE;
325 final byte[] value = ByteArray.subByte(bytes, byteOffset, length);
326 logger.debug("Parsing Link Descriptor: {}", Arrays.toString(value));
329 final UnnumberedLinkIdentifier l = new UnnumberedLinkIdentifier(ByteArray.bytesToLong(ByteArray.subByte(value, 0, 4)));
330 final UnnumberedLinkIdentifier r = new UnnumberedLinkIdentifier(ByteArray.bytesToLong(ByteArray.subByte(value, 4, 4)));
331 localIdentifiers.add(l);
332 remoteIdentifiers.add(r);
333 logger.trace("Parsed link local {} remote {} Identifiers.", local, remote);
336 final IPv4InterfaceIdentifier lipv4 = new IPv4InterfaceIdentifier(new IPv4Address(value));
337 localIdentifiers.add(lipv4);
338 logger.trace("Parsed IPv4 interface address {}.", lipv4);
341 final IPv4InterfaceIdentifier ripv4 = new IPv4InterfaceIdentifier(new IPv4Address(value));
342 remoteIdentifiers.add(ripv4);
343 logger.trace("Parsed IPv4 neighbor address {}.", ripv4);
346 final IPv6InterfaceIdentifier lipv6 = new IPv6InterfaceIdentifier(new IPv6Address(value));
347 localIdentifiers.add(lipv6);
348 logger.trace("Parsed IPv6 interface address {}.", lipv6);
351 final IPv6InterfaceIdentifier ripv6 = new IPv6InterfaceIdentifier(new IPv6Address(value));
352 remoteIdentifiers.add(ripv6);
353 logger.trace("Parsed IPv6 neighbor address {}.", ripv6);
356 topId = new TopologyIdentifier(ByteArray.bytesToLong(value) & 0x3fff);
357 logger.trace("Parsed topology identifier {}.", topId);
360 throw new BGPParsingException("Link Descriptor not recognized, type: " + type);
362 byteOffset += length;
364 logger.debug("Finished parsing Link descriptors.");
365 if (localIdentifiers.size() != 1)
366 throw new BGPParsingException("Invalid number of local interface identifiers.");
367 final LinkAnchor localAnchor = new LinkAnchor(local, localIdentifiers.get(0));
368 LinkAnchor remoteAnchor = null;
369 if (remoteIdentifiers.size() > 0) {
370 remoteAnchor = new LinkAnchor(remote, remoteIdentifiers.get(0));
372 remoteAnchor = new LinkAnchor(remote, null);
373 return new LinkIdentifier(topId, localAnchor, remoteAnchor);
377 * Parse Node Descriptors. There can be only one TLV present from each type.
382 * @throws BGPParsingException
384 private static NodeIdentifier parseNodeDescriptors(final byte[] bytes) throws BGPParsingException {
386 ASNumber asnumber = null;
387 DomainIdentifier bgpId = null;
388 AreaIdentifier ai = null;
389 RouterIdentifier routerId = null;
390 while (byteOffset != bytes.length) {
391 final int type = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, TYPE_LENGTH));
392 byteOffset += TYPE_LENGTH;
393 final int length = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, LENGTH_SIZE));
394 byteOffset += LENGTH_SIZE;
395 final byte[] value = ByteArray.subByte(bytes, byteOffset, length);
396 logger.debug("Parsing Node Descriptor: {}", Arrays.toString(value));
399 asnumber = new ASNumber(ByteArray.bytesToLong(value));
400 logger.trace("Parsed AS number {}", asnumber);
403 bgpId = new DomainIdentifier(value);
404 logger.trace("Parsed bgpId {}", bgpId);
407 ai = new AreaIdentifier(value);
408 logger.trace("Parsed area identifier {}", ai);
411 if (value.length == 6) {
412 routerId = new ISISRouterIdentifier(new ISOSystemIdentifier(ByteArray.subByte(value, 0, 6)));
413 } else if (value.length == 7) {
415 logger.warn("PSN octet is 0. Ignoring System ID.");
416 routerId = new ISISRouterIdentifier(new ISOSystemIdentifier(ByteArray.subByte(value, 0, 6)));
419 routerId = new ISISLANIdentifier(new ISOSystemIdentifier(ByteArray.subByte(value, 0, 6)), value[6]);
420 } else if (value.length == 4) {
421 routerId = new OSPFRouterIdentifier(ByteArray.subByte(value, 0, 4));
422 } else if (value.length == 8) {
423 final byte[] o = ByteArray.subByte(value, 0, 4); // FIXME: OSPFv3 vs OSPFv2
424 final OSPFInterfaceIdentifier a = new OSPFInterfaceIdentifier(ByteArray.subByte(value, 4, 4));
425 routerId = new OSPFv3LANIdentifier(new OSPFRouterIdentifier(o), a);
427 logger.trace("Parsed Router Identifier {}", routerId);
430 throw new BGPParsingException("Node Descriptor not recognized, type: " + type);
432 byteOffset += length;
434 logger.debug("Finished parsing Node descriptors.");
435 return new NodeIdentifier(asnumber, bgpId, ai, routerId);
438 private static PrefixIdentifier<?> parsePrefixDescriptors(final NodeIdentifier localDescriptor, final byte[] bytes)
439 throws BGPParsingException {
441 TopologyIdentifier topologyId = null;
442 OSPFRouteType routeType = null;
443 Prefix<?> prefix = null;
444 while (byteOffset != bytes.length) {
445 final int type = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, TYPE_LENGTH));
446 byteOffset += TYPE_LENGTH;
447 final int length = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, LENGTH_SIZE));
448 byteOffset += LENGTH_SIZE;
449 final byte[] value = ByteArray.subByte(bytes, byteOffset, length);
450 logger.trace("Parsing Prefix Descriptor: {}", Arrays.toString(value));
453 topologyId = new TopologyIdentifier(ByteArray.bytesToLong(value) & 0x3fff);
454 logger.trace("Parsed Topology Identifier: {}", topologyId);
457 final int rt = ByteArray.bytesToInt(value);
458 routeType = parseRouteType(rt);
459 logger.trace("Parser RouteType: {}", routeType);
462 final int prefixLength = UnsignedBytes.toInt(value[0]);
463 final int size = prefixLength / 8 + ((prefixLength % 8 == 0) ? 0 : 1);
464 if (size != value.length - 1) {
465 logger.debug("Expected length {}, actual length {}.", size, value.length - 1);
466 throw new BGPParsingException("Illegal length of IP reachability TLV: " + (value.length - 1));
468 prefix = IPv6.FAMILY.prefixForBytes(ByteArray.subByte(value, 1, size), prefixLength);
469 logger.trace("Parsed IP reachability info: {}", prefix);
472 throw new BGPParsingException("Prefix Descriptor not recognized, type: " + type);
474 byteOffset += length;
476 logger.debug("Finished parsing Prefix descriptors.");
477 if (routeType != null) {
478 if (prefix instanceof IPv4Prefix) {
479 return new OSPFPrefixIdentifier<IPv4Address>(localDescriptor, (IPv4Prefix) prefix, routeType);
481 return new OSPFPrefixIdentifier<IPv6Address>(localDescriptor, (IPv6Prefix) prefix, routeType);
484 return (prefix instanceof IPv4Prefix) ? new IPv4PrefixIdentifier(localDescriptor, (IPv4Prefix) prefix)
485 : new IPv6PrefixIdentifier(localDescriptor, (IPv6Prefix) prefix);
489 * Parse Link Attributes.
494 * @throws BGPParsingException
496 public static NetworkLinkImpl parseLinkAttributes(final LinkIdentifier linkId, final Map<Integer, ByteList> attributes)
497 throws BGPParsingException {
499 final Set<SharedRiskLinkGroup> sharedRiskLinkGroups = Sets.newHashSet();
500 final Set<MPLSProtocol> enabledMPLSProtocols = Sets.newHashSet();
501 NetworkLinkState state = NetworkLinkState.EMPTY;
503 // FIXME: we should put these somewhere
504 final Set<RouterIdentifier> localIds = Sets.newHashSet();
505 final Set<RouterIdentifier> remoteIds = Sets.newHashSet();
508 for (final Entry<Integer, ByteList> entry : attributes.entrySet()) {
509 logger.debug("Link attribute TLV {}", entry.getKey());
511 for (final byte[] value : entry.getValue().getBytes()) {
513 switch (entry.getKey()) {
515 final IPv4RouterIdentifier lipv4 = new IPv4RouterIdentifier(new IPv4Address(value));
517 logger.trace("Parsed IPv4 Router-ID of local node: {}", lipv4);
520 final IPv6RouterIdentifier lipv6 = new IPv6RouterIdentifier(new IPv6Address(value));
522 logger.trace("Parsed IPv6 Router-ID of local node: {}", lipv6);
525 final IPv4RouterIdentifier ripv4 = new IPv4RouterIdentifier(new IPv4Address(value));
526 remoteIds.add(ripv4);
527 logger.trace("Parsed IPv4 Router-ID of remote node: {}", ripv4);
530 final IPv6RouterIdentifier ripv6 = new IPv6RouterIdentifier(new IPv6Address(value));
531 remoteIds.add(ripv6);
532 logger.trace("Parsed IPv6 Router-ID of remote node: {}", ripv6);
535 state = state.withAdministrativeGroup(new AdministrativeGroup(ByteArray.bytesToLong(value)));
536 logger.trace("Parsed Administrative Group {}", state.getAdministrativeGroup());
539 state = state.withMaximumBandwidth(new Bandwidth(ByteArray.bytesToFloat(value)));
540 logger.trace("Parsed Max Bandwidth {}", state.getMaximumBandwidth());
543 state = state.withReservableBandwidth(new Bandwidth(ByteArray.bytesToFloat(value)));
544 logger.trace("Parsed Max Reservable Bandwidth {}", state.getMaximumReservableBandwidth());
548 final Bandwidth[] unreservedBandwidth = new Bandwidth[8];
549 for (int i = 0; i < 8; i++) {
550 unreservedBandwidth[i] = new Bandwidth(ByteArray.bytesToFloat(ByteArray.subByte(value, index, 4)));
553 state = state.withUnreservedBandwidth(unreservedBandwidth);
554 logger.trace("Parsed Unreserved Bandwidth {}", Arrays.toString(state.getUnreservedBandwidth()));
557 state = state.withMetric(TEMetric.class, new TEMetric(ByteArray.bytesToInt(value)));
558 logger.trace("Parsed Metric {}", state.getMetric(TEMetric.class));
561 state = state.withProtectionType(parseLinkProtectionType(UnsignedBytes.toInt(value[0])));
562 logger.trace("Parsed Link Protection Type {}", state.getProtectionType());
565 final boolean[] bits = ByteArray.parseBits(value[0]);
566 if (bits[0] == true) {
567 enabledMPLSProtocols.add(MPLSProtocol.LDP);
569 if (bits[1] == true) {
570 enabledMPLSProtocols.add(MPLSProtocol.RSVPTE);
572 logger.trace("Parsed MPLS Protocols: {}", Arrays.toString(enabledMPLSProtocols.toArray()));
575 state = state.withDefaultMetric(new IGPMetric(ByteArray.bytesToLong(value)));
576 logger.trace("Parsed Metric {}", state.getDefaultMetric());
580 while (i != value.length) {
581 sharedRiskLinkGroups.add(new SharedRiskLinkGroup(ByteArray.bytesToLong(ByteArray.subByte(value, i, 4))));
584 logger.trace("Parsed Shared Risk Link Groups {}", Arrays.toString(sharedRiskLinkGroups.toArray()));
587 final byte[] opaque = value;
588 logger.trace("Parsed Opaque value : {}", Arrays.toString(opaque));
591 name = new String(value, Charsets.US_ASCII);
592 logger.trace("Parsed Link Name : ", name);
595 throw new BGPParsingException("Link Attribute not recognized, type: " + entry.getKey());
599 state = state.withEnabledMPLSProtocols(enabledMPLSProtocols);
600 state = state.withSharedRiskLinkGroups(sharedRiskLinkGroups);
601 state = state.withSymbolicName(name);
602 final NetworkLinkImpl link = new NetworkLinkImpl(linkId, state);
603 logger.debug("Finished parsing Link Attributes.");
608 * Parse Node Attributes.
613 * @throws BGPParsingException
615 public static NetworkNodeImpl parseNodeAttributes(final NodeIdentifier nodeId, final Map<Integer, ByteList> attributes)
616 throws BGPParsingException {
617 final Map<TopologyIdentifier, TopologyNodeInformation> topologyMembership = Maps.newHashMap();
618 final Set<ISISAreaIdentifier> areaMembership = Sets.newHashSet();
619 final NetworkNodeImpl node = new NetworkNodeImpl(nodeId);
620 final Set<RouterIdentifier> ids = Sets.newHashSet();
621 for (final Entry<Integer, ByteList> entry : attributes.entrySet()) {
622 logger.debug("Node attribute TLV {}", entry.getKey());
623 for (final byte[] value : entry.getValue().getBytes()) {
624 switch (entry.getKey()) {
626 final boolean[] bits = ByteArray.parseBits(value[0]);
627 final TopologyNodeInformation topNodeInfo = new TopologyNodeInformation(bits[1], bits[0]);
628 final TopologyIdentifier topId = new TopologyIdentifier(ByteArray.bytesToLong(value) & 0x3fff);
629 topologyMembership.put(topId, topNodeInfo);
630 logger.trace("Parsed Topology Identifier: {} and Topology Node Information: {}", topId, topNodeInfo);
633 final boolean[] flags = ByteArray.parseBits(value[0]);
634 node.currentState().withExternal(flags[2]);
635 node.currentState().withAreaBorderRouter(flags[3]);
636 logger.trace("Parsed External bit {}, area border router {}.", flags[2], flags[3]);
639 logger.debug("Ignoring opaque value: {}.", Arrays.toString(value));
642 node.currentState().withDynamicHostname(new String(value, Charsets.US_ASCII));
643 logger.trace("Parsed Node Name {}", node.currentState().getDynamicHostname());
646 final ISISAreaIdentifier ai = new ISISAreaIdentifier(value);
647 areaMembership.add(ai);
648 logger.trace("Parsed AreaIdentifier {}", ai);
651 final IPv4RouterIdentifier ip4 = new IPv4RouterIdentifier(new IPv4Address(value));
653 logger.trace("Parsed IPv4 Router Identifier {}", ip4);
656 final IPv6RouterIdentifier ip6 = new IPv6RouterIdentifier(new IPv6Address(value));
658 logger.trace("Parsed IPv6 Router Identifier {}", ip6);
661 throw new BGPParsingException("Node Attribute not recognized, type: " + entry.getKey());
666 node.currentState().withAreaMembership(areaMembership);
667 node.currentState().withIdentifierAlternatives(ids);
668 node.currentState().withTopologyMembership(topologyMembership);
669 logger.debug("Finished parsing Node Attributes.");
673 public static NetworkPrefixState parsePrefixAttributes(final SourceProtocol src, final NetworkObjectState nos,
674 final Map<Integer, ByteList> attributes) throws BGPParsingException {
676 boolean upDownBit = false;
677 final SortedSet<RouteTag> routeTags = Sets.newTreeSet();
678 final SortedSet<ExtendedRouteTag> exRouteTags = Sets.newTreeSet();
679 Metric<?> metric = null;
680 IPv4Address fwdAddress4 = null;
681 IPv6Address fwdAddress6 = null;
682 for (final Entry<Integer, ByteList> entry : attributes.entrySet()) {
683 logger.debug("Prefix attribute TLV {}", entry.getKey());
684 for (final byte[] value : entry.getValue().getBytes()) {
685 switch (entry.getKey()) {
687 final boolean[] flags = ByteArray.parseBits(value[0]);
688 upDownBit = flags[2];
689 logger.trace("Parsed IGP flag (up/down bit) : {}", upDownBit);
693 while (offset != value.length) {
694 final RouteTag routeTag = new RouteTag(ByteArray.subByte(value, offset, 4));
695 routeTags.add(routeTag);
696 logger.trace("Parsed Route Tag: {}", routeTag);
702 while (offset != value.length) {
703 final ExtendedRouteTag exRouteTag = new ExtendedRouteTag(value);
704 exRouteTags.add(exRouteTag);
705 logger.trace("Parsed Extended Route Tag: {}", exRouteTag);
710 metric = new IGPMetric(ByteArray.bytesToLong(value));
711 logger.trace("Parsed Metric: {}", metric);
714 switch (value.length) {
716 fwdAddress4 = new IPv4Address(value);
717 logger.trace("Parsed FWD Address: {}", fwdAddress4);
720 fwdAddress6 = new IPv6Address(value);
721 logger.trace("Parsed FWD Address: {}", fwdAddress6);
724 logger.debug("Ignoring unsupported forwarding address length {}", value.length);
729 final byte[] opaque = value;
730 logger.trace("Parsed Opaque value: {}", Arrays.toString(opaque));
733 throw new BGPParsingException("Prefix Attribute not recognized, type: " + entry.getKey());
738 logger.debug("Finished parsing Prefix Attributes.");
740 final NetworkPrefixState nps = new NetworkPrefixState(nos, routeTags, metric);
744 return new ISISNetworkPrefixState(nps, exRouteTags, upDownBit);
746 if (fwdAddress4 != null)
747 return new OSPFNetworkPrefixState<IPv4Address>(nps, fwdAddress4);
748 if (fwdAddress6 != null)
749 return new OSPFNetworkPrefixState<IPv6Address>(nps, fwdAddress6);
750 logger.debug("OSPF-sourced has no forwarding address");
758 * Parse Link Protection Type from int to enum
760 * @param type int parsed from byte array
761 * @return enum LinkProtectionType
762 * @throws BGPParsingException if the type is unrecognized
764 private static LinkProtectionType parseLinkProtectionType(final int type) throws BGPParsingException {
767 return LinkProtectionType.EXTRA_TRAFFIC;
769 return LinkProtectionType.UNPROTECTED;
771 return LinkProtectionType.SHARED;
773 return LinkProtectionType.DEDICATED_ONE_TO_ONE;
775 return LinkProtectionType.DEDICATED_ONE_PLUS_ONE;
777 throw new BGPParsingException("Link Protection Type not recognized: " + type);
782 * Parse NLRI Type from int to enum
784 * @param type int parsed from byte array
785 * @return enum NlriType
786 * @throws BGPParsingException if the type is unrecognized
788 private static NlriType parseNLRItype(final int type) throws BGPParsingException {
791 return NlriType.NodeNLRI;
793 return NlriType.LinkNLRI;
795 return NlriType.IPv4Prefixes;
797 return NlriType.IPv6Prefixes;
799 throw new BGPParsingException("NLRI Type not recognized: " + type);