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.math.BigInteger;
11 import java.util.Arrays;
12 import java.util.HashMap;
13 import java.util.List;
15 import java.util.Map.Entry;
18 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
19 import org.opendaylight.protocol.bgp.parser.impl.ByteList;
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.IpAddress;
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.rev130918.AdministrativeGroup;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.AreaIdentifier;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.DomainIdentifier;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.ExtendedRouteTag;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.Identifier;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.IgpBits.UpDown;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.Ipv4InterfaceIdentifier;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.Ipv4RouterIdentifier;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.Ipv6InterfaceIdentifier;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.Ipv6RouterIdentifier;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.IsisAreaIdentifier;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.LinkProtectionType;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.MplsProtocolMask;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.NlriType;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.NodeFlagBits;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.NodeIdentifier;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.OspfInterfaceIdentifier;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.OspfRouteType;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.ProtocolId;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.RouteDistinguisher;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.RouteTag;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.SharedRiskLinkGroup;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.TopologyIdentifier;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.isis.lan.identifier.IsIsRouterIdentifier;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.isis.lan.identifier.IsIsRouterIdentifierBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.link.state.UnreservedBandwidthBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.linkstate.destination.CLinkstateDestination;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.linkstate.destination.CLinkstateDestinationBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.linkstate.destination.c.linkstate.destination.LinkDescriptors;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.linkstate.destination.c.linkstate.destination.LinkDescriptorsBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.linkstate.destination.c.linkstate.destination.LocalNodeDescriptors;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.linkstate.destination.c.linkstate.destination.LocalNodeDescriptorsBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.linkstate.destination.c.linkstate.destination.PrefixDescriptors;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.linkstate.destination.c.linkstate.destination.PrefixDescriptorsBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.linkstate.destination.c.linkstate.destination.RemoteNodeDescriptors;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.node.identifier.CRouterIdentifier;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.node.identifier.c.router.identifier.CIsisNodeBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.node.identifier.c.router.identifier.CIsisPseudonodeBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.node.identifier.c.router.identifier.COspfNodeBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.node.identifier.c.router.identifier.COspfPseudonodeBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.node.identifier.c.router.identifier.c.isis.node.IsisNodeBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.node.identifier.c.router.identifier.c.isis.pseudonode.IsisPseudonodeBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.node.identifier.c.router.identifier.c.ospf.node.OspfNodeBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.node.identifier.c.router.identifier.c.ospf.pseudonode.OspfPseudonodeBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.prefix.state.IgpBitsBuilder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.update.path.attributes.LinkstatePathAttribute;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.update.path.attributes.LinkstatePathAttributeBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.update.path.attributes.linkstate.path.attribute.link.state.attribute.LinkAttributes;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.update.path.attributes.linkstate.path.attribute.link.state.attribute.LinkAttributesBuilder;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.update.path.attributes.linkstate.path.attribute.link.state.attribute.NodeAttributes;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.update.path.attributes.linkstate.path.attribute.link.state.attribute.NodeAttributesBuilder;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.update.path.attributes.linkstate.path.attribute.link.state.attribute.PrefixAttributes;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.update.path.attributes.linkstate.path.attribute.link.state.attribute.PrefixAttributesBuilder;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.MplsLabeledVpnSubsequentAddressFamily;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.SubsequentAddressFamily;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nps.concepts.rev130930.Bandwidth;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nps.concepts.rev130930.IgpMetric;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nps.concepts.rev130930.IsoSystemIdentifier;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nps.concepts.rev130930.Metric;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nps.concepts.rev130930.TeMetric;
86 import org.slf4j.Logger;
87 import org.slf4j.LoggerFactory;
89 import com.google.common.base.Charsets;
90 import com.google.common.collect.Lists;
91 import com.google.common.collect.Sets;
92 import com.google.common.primitives.UnsignedBytes;
95 * Parser for Link State information.
97 * @see <a href="http://tools.ietf.org/html/draft-gredler-idr-ls-distribution-01">BGP-LS draft</a>
99 public class LinkStateParser {
101 private static final Logger logger = LoggerFactory.getLogger(LinkStateParser.class);
103 private static final int TYPE_LENGTH = 2;
105 private static final int LENGTH_SIZE = 2;
107 private static final int ROUTE_DISTINGUISHER_LENGTH = 8;
109 private static final int PROTOCOL_ID_LENGTH = 1;
111 private static final int IDENTIFIER_LENGTH = 8;
113 private static final Set<Integer> nodeTlvs = Sets.newHashSet(263, 1024, 1025, 1026, 1027, 1028, 1029);
115 private static final Set<Integer> linkTlvs = Sets.newHashSet(1028, 1029, 1030, 1031, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095,
118 private static final Set<Integer> prefixTlvs = Sets.newHashSet(1152, 1153, 1154, 1155, 1156, 1157);
120 private LinkStateParser() {
124 * Parses common parts for Link State Nodes, Links and Prefixes, that includes protocol ID and identifier tlv.
129 * @return BGPLinkMP or BGPNodeMP
130 * @throws BGPParsingException
132 protected static CLinkstateDestination parseLSNlri(final Class<? extends SubsequentAddressFamily> safi, final byte[] bytes)
133 throws BGPParsingException {
134 if (bytes.length == 0) {
139 final CLinkstateDestinationBuilder builder = new CLinkstateDestinationBuilder();
141 while (byteOffset != bytes.length) {
142 final NlriType type = NlriType.forValue(ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, TYPE_LENGTH)));
143 builder.setNlriType(type);
145 byteOffset += TYPE_LENGTH;
146 // length means total length of the tlvs including route distinguisher not including the type field
147 final int length = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, LENGTH_SIZE));
148 byteOffset += LENGTH_SIZE;
149 RouteDistinguisher distinguisher = null;
150 if (safi == MplsLabeledVpnSubsequentAddressFamily.class) {
151 // this parses route distinguisher
152 distinguisher = new RouteDistinguisher(BigInteger.valueOf(ByteArray.bytesToLong(ByteArray.subByte(bytes, byteOffset,
153 ROUTE_DISTINGUISHER_LENGTH))));
154 builder.setDistinguisher(distinguisher);
155 byteOffset += ROUTE_DISTINGUISHER_LENGTH;
157 // parse source protocol
158 final ProtocolId sp = ProtocolId.forValue(ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, PROTOCOL_ID_LENGTH)));
159 byteOffset += PROTOCOL_ID_LENGTH;
160 builder.setProtocolId(sp);
163 final Identifier identifier = new Identifier(BigInteger.valueOf(ByteArray.bytesToLong(ByteArray.subByte(bytes, byteOffset,
164 IDENTIFIER_LENGTH))));
165 byteOffset += IDENTIFIER_LENGTH;
166 builder.setIdentifier(identifier);
168 // if we are dealing with linkstate nodes/links, parse local node descriptor
169 NodeIdentifier localDescriptor = null;
171 final int localtype = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, TYPE_LENGTH));
172 byteOffset += TYPE_LENGTH;
173 locallength = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, LENGTH_SIZE));
174 byteOffset += LENGTH_SIZE;
175 if (localtype == 256) {
176 localDescriptor = parseNodeDescriptors(ByteArray.subByte(bytes, byteOffset, locallength));
178 byteOffset += locallength;
179 builder.setLocalNodeDescriptors((LocalNodeDescriptors) localDescriptor);
180 final int restLength = length - ((safi == MplsLabeledVpnSubsequentAddressFamily.class) ? ROUTE_DISTINGUISHER_LENGTH : 0)
181 - PROTOCOL_ID_LENGTH - IDENTIFIER_LENGTH - TYPE_LENGTH - LENGTH_SIZE - locallength;
182 logger.debug("Restlength {}", restLength);
185 parseLink(builder, ByteArray.subByte(bytes, byteOffset, restLength));
189 builder.setPrefixDescriptors(parsePrefixDescriptors(localDescriptor, ByteArray.subByte(bytes, byteOffset, restLength)));
192 // node nlri is already parsed as it contains only the common fields for node and link nlri
195 byteOffset += restLength;
197 return builder.build();
200 public static boolean verifyLink(final Set<Integer> keys) {
201 for (final Integer i : keys) {
202 if (!linkTlvs.contains(i)) {
203 logger.warn("Invalid link attribute {}", i);
210 public static boolean verifyNode(final Set<Integer> keys) {
211 for (final Integer i : keys) {
212 if (!nodeTlvs.contains(i)) {
213 logger.warn("Invalid node attribute {}", i);
220 public static boolean verifyPrefix(final Set<Integer> keys) {
221 for (final Integer i : keys) {
222 if (!prefixTlvs.contains(i)) {
223 logger.warn("Invalid prefix attribute {}", i);
230 private static NodeIdentifier parseLink(final CLinkstateDestinationBuilder builder, final byte[] bytes) throws BGPParsingException {
232 final int type = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, TYPE_LENGTH));
233 byteOffset += TYPE_LENGTH;
234 final int length = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, LENGTH_SIZE));
235 byteOffset += LENGTH_SIZE;
236 final NodeIdentifier remote = null;
238 builder.setRemoteNodeDescriptors((RemoteNodeDescriptors) parseNodeDescriptors(ByteArray.subByte(bytes, byteOffset, length)));
239 byteOffset += length;
241 builder.setLinkDescriptors(parseLinkDescriptors(ByteArray.subByte(bytes, byteOffset, bytes.length - byteOffset)));
245 private static LinkDescriptors parseLinkDescriptors(final byte[] bytes) throws BGPParsingException {
247 final LinkDescriptorsBuilder builder = new LinkDescriptorsBuilder();
248 while (byteOffset != bytes.length) {
249 final int type = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, TYPE_LENGTH));
250 byteOffset += TYPE_LENGTH;
251 final int length = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, LENGTH_SIZE));
252 byteOffset += LENGTH_SIZE;
253 final byte[] value = ByteArray.subByte(bytes, byteOffset, length);
254 logger.debug("Parsing Link Descriptor: {}", Arrays.toString(value));
257 builder.setLinkLocalIdentifier(ByteArray.subByte(value, 0, 4));
258 builder.setLinkRemoteIdentifier(ByteArray.subByte(value, 4, 4));
259 logger.trace("Parsed link local {} remote {} Identifiers.", builder.getLinkLocalIdentifier(),
260 builder.getLinkRemoteIdentifier());
263 final Ipv4InterfaceIdentifier lipv4 = new Ipv4InterfaceIdentifier(Ipv4Util.addressForBytes(value));
264 builder.setIpv4InterfaceAddress(lipv4);
265 logger.trace("Parsed IPv4 interface address {}.", lipv4);
268 final Ipv4InterfaceIdentifier ripv4 = new Ipv4InterfaceIdentifier(Ipv4Util.addressForBytes(value));
269 builder.setIpv4NeighborAddress(ripv4);
270 logger.trace("Parsed IPv4 neighbor address {}.", ripv4);
273 final Ipv6InterfaceIdentifier lipv6 = new Ipv6InterfaceIdentifier(Ipv6Util.addressForBytes(value));
274 builder.setIpv6InterfaceAddress(lipv6);
275 logger.trace("Parsed IPv6 interface address {}.", lipv6);
278 final Ipv6InterfaceIdentifier ripv6 = new Ipv6InterfaceIdentifier(Ipv6Util.addressForBytes(value));
279 builder.setIpv6NeighborAddress(ripv6);
280 logger.trace("Parsed IPv6 neighbor address {}.", ripv6);
283 final TopologyIdentifier topId = new TopologyIdentifier(ByteArray.bytesToInt(value) & 0x3fff);
284 builder.setMultiTopologyId(topId);
285 logger.trace("Parsed topology identifier {}.", topId);
288 throw new BGPParsingException("Link Descriptor not recognized, type: " + type);
290 byteOffset += length;
292 logger.debug("Finished parsing Link descriptors.");
293 return builder.build();
296 private static NodeIdentifier parseNodeDescriptors(final byte[] bytes) throws BGPParsingException {
298 AsNumber asnumber = null;
299 DomainIdentifier bgpId = null;
300 AreaIdentifier ai = null;
301 CRouterIdentifier routerId = null;
302 while (byteOffset != bytes.length) {
303 final int type = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, TYPE_LENGTH));
304 byteOffset += TYPE_LENGTH;
305 final int length = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, LENGTH_SIZE));
306 byteOffset += LENGTH_SIZE;
307 final byte[] value = ByteArray.subByte(bytes, byteOffset, length);
308 logger.debug("Parsing Node Descriptor: {}", Arrays.toString(value));
311 asnumber = new AsNumber(ByteArray.bytesToLong(value));
312 logger.trace("Parsed AS number {}", asnumber);
315 bgpId = new DomainIdentifier(value);
316 logger.trace("Parsed bgpId {}", bgpId);
319 ai = new AreaIdentifier(value);
320 logger.trace("Parsed area identifier {}", ai);
323 if (value.length == 6) {
324 routerId = new CIsisNodeBuilder().setIsisNode(
325 new IsisNodeBuilder().setIsoSystemId(new IsoSystemIdentifier(ByteArray.subByte(value, 0, 6))).build()).build();
326 } else if (value.length == 7) {
328 logger.warn("PSN octet is 0. Ignoring System ID.");
329 routerId = new CIsisNodeBuilder().setIsisNode(
330 new IsisNodeBuilder().setIsoSystemId(new IsoSystemIdentifier(ByteArray.subByte(value, 0, 6))).build()).build();
333 final IsIsRouterIdentifier iri = new IsIsRouterIdentifierBuilder().setIsoSystemId(
334 new IsoSystemIdentifier(ByteArray.subByte(value, 0, 6))).build();
335 routerId = new CIsisPseudonodeBuilder().setIsisPseudonode(
336 new IsisPseudonodeBuilder().setIsIsRouterIdentifier(iri).setPsn((short) UnsignedBytes.toInt(value[6])).build()).build();
338 } else if (value.length == 4) {
339 routerId = new COspfNodeBuilder().setOspfNode(
340 new OspfNodeBuilder().setOspfRouterId(ByteArray.subByte(value, 0, 4)).build()).build();
341 } else if (value.length == 8) {
342 final byte[] o = ByteArray.subByte(value, 0, 4); // FIXME: OSPFv3 vs OSPFv2
343 final OspfInterfaceIdentifier a = new OspfInterfaceIdentifier(ByteArray.subByte(value, 4, 4));
344 routerId = new COspfPseudonodeBuilder().setOspfPseudonode(
345 new OspfPseudonodeBuilder().setOspfRouterId(o).setLanInterface(a).build()).build();
347 logger.trace("Parsed Router Identifier {}", routerId);
350 throw new BGPParsingException("Node Descriptor not recognized, type: " + type);
352 byteOffset += length;
354 logger.debug("Finished parsing Node descriptors.");
355 return new LocalNodeDescriptorsBuilder().setAsNumber(asnumber).setDomainId(bgpId).setAreaId(ai).setCRouterIdentifier(routerId).build();
358 private static PrefixDescriptors parsePrefixDescriptors(final NodeIdentifier localDescriptor, final byte[] bytes)
359 throws BGPParsingException {
361 final PrefixDescriptorsBuilder builder = new PrefixDescriptorsBuilder();
362 while (byteOffset != bytes.length) {
363 final int type = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, TYPE_LENGTH));
364 byteOffset += TYPE_LENGTH;
365 final int length = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, LENGTH_SIZE));
366 byteOffset += LENGTH_SIZE;
367 final byte[] value = ByteArray.subByte(bytes, byteOffset, length);
368 logger.trace("Parsing Prefix Descriptor: {}", Arrays.toString(value));
371 final TopologyIdentifier topologyId = new TopologyIdentifier(ByteArray.bytesToInt(value) & 0x3fff);
372 builder.setMultiTopologyId(topologyId);
373 logger.trace("Parsed Topology Identifier: {}", topologyId);
376 final int rt = ByteArray.bytesToInt(value);
377 final OspfRouteType routeType = OspfRouteType.forValue(rt);
378 if (routeType == null)
379 throw new BGPParsingException("Unknown OSPF Route Type: " + rt);
380 builder.setOspfRouteType(routeType);
381 logger.trace("Parser RouteType: {}", routeType);
384 IpPrefix prefix = null;
385 final int prefixLength = UnsignedBytes.toInt(value[0]);
386 final int size = prefixLength / 8 + ((prefixLength % 8 == 0) ? 0 : 1);
387 if (size != value.length - 1) {
388 logger.debug("Expected length {}, actual length {}.", size, value.length - 1);
389 throw new BGPParsingException("Illegal length of IP reachability TLV: " + (value.length - 1));
392 prefix = new IpPrefix(Ipv4Util.prefixForBytes(ByteArray.subByte(value, 1, size), prefixLength));
394 prefix = new IpPrefix(Ipv6Util.prefixForBytes(ByteArray.subByte(value, 1, size), prefixLength));
395 builder.setIpReachabilityInformation(prefix);
396 logger.trace("Parsed IP reachability info: {}", prefix);
399 throw new BGPParsingException("Prefix Descriptor not recognized, type: " + type);
401 byteOffset += length;
403 logger.debug("Finished parsing Prefix descriptors.");
404 return builder.build();
407 protected static LinkstatePathAttribute parseLinkState(final byte[] bytes) throws BGPParsingException {
408 final Map<Integer, ByteList> map = new HashMap<Integer, ByteList>();
410 while (byteOffset != bytes.length) {
411 final int type = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, TYPE_LENGTH));
412 byteOffset += TYPE_LENGTH;
413 final int length = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, LENGTH_SIZE));
414 byteOffset += LENGTH_SIZE;
415 final byte[] value = ByteArray.subByte(bytes, byteOffset, length);
416 ByteList values = map.containsKey(type) ? values = map.get(type) : new ByteList();
418 map.put(type, values);
419 byteOffset += length;
421 final LinkstatePathAttributeBuilder builder = new LinkstatePathAttributeBuilder();
422 if (verifyLink(map.keySet())) {
423 builder.setLinkStateAttribute(parseLinkAttributes(map));
424 } else if (verifyNode(map.keySet())) {
425 builder.setLinkStateAttribute(parseNodeAttributes(map));
426 } else if (verifyPrefix(map.keySet())) {
427 builder.setLinkStateAttribute(parsePrefixAttributes(map));
429 return builder.build();
433 * Parse Link Attributes.
435 * @param attributes key is the tlv type and value is the value of the tlv
436 * @return {@link LinkAttributes}
437 * @throws BGPParsingException if a link attribute is not recognized
439 public static LinkAttributes parseLinkAttributes(final Map<Integer, ByteList> attributes) throws BGPParsingException {
441 final LinkAttributesBuilder builder = new LinkAttributesBuilder();
442 for (final Entry<Integer, ByteList> entry : attributes.entrySet()) {
443 logger.debug("Link attribute TLV {}", entry.getKey());
445 for (final byte[] value : entry.getValue().getBytes()) {
447 switch (entry.getKey()) {
449 final Ipv4RouterIdentifier lipv4 = new Ipv4RouterIdentifier(Ipv4Util.addressForBytes(value));
450 builder.setLocalIpv4RouterId(lipv4);
451 logger.trace("Parsed IPv4 Router-ID of local node: {}", lipv4);
454 final Ipv6RouterIdentifier lipv6 = new Ipv6RouterIdentifier(Ipv6Util.addressForBytes(value));
455 builder.setLocalIpv6RouterId(lipv6);
456 logger.trace("Parsed IPv6 Router-ID of local node: {}", lipv6);
459 final Ipv4RouterIdentifier ripv4 = new Ipv4RouterIdentifier(Ipv4Util.addressForBytes(value));
460 builder.setRemoteIpv4RouterId(ripv4);
461 logger.trace("Parsed IPv4 Router-ID of remote node: {}", ripv4);
464 final Ipv6RouterIdentifier ripv6 = new Ipv6RouterIdentifier(Ipv6Util.addressForBytes(value));
465 builder.setRemoteIpv6RouterId(ripv6);
466 logger.trace("Parsed IPv6 Router-ID of remote node: {}", ripv6);
469 builder.setAdminGroup(new AdministrativeGroup(ByteArray.bytesToLong(value)));
470 logger.trace("Parsed Administrative Group {}", builder.getAdminGroup());
473 builder.setMaxLinkBandwidth(new Bandwidth(value));
474 logger.trace("Parsed Max Bandwidth {}", builder.getMaxLinkBandwidth());
477 builder.setMaxReservableBandwidth(new Bandwidth(value));
478 logger.trace("Parsed Max Reservable Bandwidth {}", builder.getMaxReservableBandwidth());
482 final List<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.link.state.UnreservedBandwidth> unreservedBandwidth = Lists.newArrayList();
483 for (int i = 0; i < 8; i++) {
484 unreservedBandwidth.add(new UnreservedBandwidthBuilder().setBandwidth(
485 new Bandwidth(ByteArray.subByte(value, index, 4))).setPriority((short) i).build());
488 builder.setUnreservedBandwidth(unreservedBandwidth);
489 logger.trace("Parsed Unreserved Bandwidth {}", builder.getUnreservedBandwidth());
492 builder.setTeMetric(new TeMetric(ByteArray.bytesToLong(value)));
493 logger.trace("Parsed Metric {}", builder.getTeMetric());
496 final LinkProtectionType lpt = LinkProtectionType.forValue(UnsignedBytes.toInt(value[0]));
498 throw new BGPParsingException("Link Protection Type not recognized: " + UnsignedBytes.toInt(value[0]));
499 builder.setLinkProtection(lpt);
500 logger.trace("Parsed Link Protection Type {}", lpt);
503 final boolean[] bits = ByteArray.parseBits(value[0]);
504 builder.setMplsProtocol(new MplsProtocolMask(bits[0], bits[1]));
505 logger.trace("Parsed MPLS Protocols: {}", builder.getMplsProtocol());
508 builder.setMetric(new Metric(ByteArray.bytesToLong(value)));
509 logger.trace("Parsed Metric {}", builder.getMetric());
513 final List<SharedRiskLinkGroup> sharedRiskLinkGroups = Lists.newArrayList();
514 while (i != value.length) {
515 sharedRiskLinkGroups.add(new SharedRiskLinkGroup(ByteArray.bytesToLong(ByteArray.subByte(value, i, 4))));
518 builder.setSharedRiskLinkGroups(sharedRiskLinkGroups);
519 logger.trace("Parsed Shared Risk Link Groups {}", Arrays.toString(sharedRiskLinkGroups.toArray()));
522 final byte[] opaque = value;
523 logger.trace("Parsed Opaque value : {}", Arrays.toString(opaque));
526 final String name = new String(value, Charsets.US_ASCII);
527 builder.setLinkName(name);
528 logger.trace("Parsed Link Name : ", name);
531 throw new BGPParsingException("Link Attribute not recognized, type: " + entry.getKey());
535 logger.debug("Finished parsing Link Attributes.");
536 return builder.build();
540 * Parse Node Attributes.
542 * @param attributes key is the tlv type and value is the value of the tlv
543 * @return {@link NodeAttributes}
544 * @throws BGPParsingException if a node attribute is not recognized
546 public static NodeAttributes parseNodeAttributes(final Map<Integer, ByteList> attributes) throws BGPParsingException {
547 final List<TopologyIdentifier> topologyMembership = Lists.newArrayList();
548 final List<IsisAreaIdentifier> areaMembership = Lists.newArrayList();
549 final NodeAttributesBuilder builder = new NodeAttributesBuilder();
550 for (final Entry<Integer, ByteList> entry : attributes.entrySet()) {
551 logger.debug("Node attribute TLV {}", entry.getKey());
552 for (final byte[] value : entry.getValue().getBytes()) {
553 switch (entry.getKey()) {
556 while (i != value.length) {
557 final TopologyIdentifier topId = new TopologyIdentifier(ByteArray.bytesToInt(ByteArray.subByte(value, i, 2)) & 0x3fff);
558 topologyMembership.add(topId);
559 logger.trace("Parsed Topology Identifier: {}", topId);
564 final boolean[] flags = ByteArray.parseBits(value[0]);
565 builder.setNodeFlags(new NodeFlagBits(flags[0], flags[1], flags[2], flags[3]));
566 logger.trace("Parsed External bit {}, area border router {}.", flags[2], flags[3]);
569 logger.debug("Ignoring opaque value: {}.", Arrays.toString(value));
572 builder.setDynamicHostname(new String(value, Charsets.US_ASCII));
573 logger.trace("Parsed Node Name {}", builder.getDynamicHostname());
576 final IsisAreaIdentifier ai = new IsisAreaIdentifier(value);
577 areaMembership.add(ai);
578 logger.trace("Parsed AreaIdentifier {}", ai);
581 final Ipv4RouterIdentifier ip4 = new Ipv4RouterIdentifier(Ipv4Util.addressForBytes(value));
582 builder.setIpv4RouterId(ip4);
583 logger.trace("Parsed IPv4 Router Identifier {}", ip4);
586 final Ipv6RouterIdentifier ip6 = new Ipv6RouterIdentifier(Ipv6Util.addressForBytes(value));
587 builder.setIpv6RouterId(ip6);
588 logger.trace("Parsed IPv6 Router Identifier {}", ip6);
591 throw new BGPParsingException("Node Attribute not recognized, type: " + entry.getKey());
595 builder.setTopologyIdentifier(topologyMembership);
596 builder.setIsisAreaId(areaMembership);
597 logger.debug("Finished parsing Node Attributes.");
598 return builder.build();
602 * Parse prefix attributes.
604 * @param attributes key is the tlv type and value are the value bytes of the tlv
605 * @return {@link PrefixAttributes}
606 * @throws BGPParsingException if some prefix attributes is not recognized
608 public static PrefixAttributes parsePrefixAttributes(final Map<Integer, ByteList> attributes) throws BGPParsingException {
609 final PrefixAttributesBuilder builder = new PrefixAttributesBuilder();
610 final List<RouteTag> routeTags = Lists.newArrayList();
611 final List<ExtendedRouteTag> exRouteTags = Lists.newArrayList();
612 for (final Entry<Integer, ByteList> entry : attributes.entrySet()) {
613 logger.debug("Prefix attribute TLV {}", entry.getKey());
614 for (final byte[] value : entry.getValue().getBytes()) {
615 switch (entry.getKey()) {
617 final boolean[] flags = ByteArray.parseBits(value[0]);
618 final boolean upDownBit = flags[2];
619 builder.setIgpBits(new IgpBitsBuilder().setUpDown(new UpDown(upDownBit)).build());
620 logger.trace("Parsed IGP flag (up/down bit) : {}", upDownBit);
624 while (offset != value.length) {
625 final RouteTag routeTag = new RouteTag(ByteArray.subByte(value, offset, 4));
626 routeTags.add(routeTag);
627 logger.trace("Parsed Route Tag: {}", routeTag);
633 while (offset != value.length) {
634 final ExtendedRouteTag exRouteTag = new ExtendedRouteTag(value);
635 exRouteTags.add(exRouteTag);
636 logger.trace("Parsed Extended Route Tag: {}", exRouteTag);
641 final IgpMetric metric = new IgpMetric(ByteArray.bytesToLong(value));
642 builder.setPrefixMetric(metric);
643 logger.trace("Parsed Metric: {}", metric);
646 IpAddress fwdAddress = null;
647 switch (value.length) {
649 fwdAddress = new IpAddress(Ipv4Util.addressForBytes(value));
652 fwdAddress = new IpAddress(Ipv6Util.addressForBytes(value));
655 logger.debug("Ignoring unsupported forwarding address length {}", value.length);
657 logger.trace("Parsed FWD Address: {}", fwdAddress);
660 final byte[] opaque = value;
661 logger.trace("Parsed Opaque value: {}", Arrays.toString(opaque));
664 throw new BGPParsingException("Prefix Attribute not recognized, type: " + entry.getKey());
668 logger.debug("Finished parsing Prefix Attributes.");
669 builder.setRouteTags(routeTags);
670 builder.setExtendedTags(exRouteTags);
671 return builder.build();