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.base.Charsets;
11 import com.google.common.collect.HashMultimap;
12 import com.google.common.collect.Lists;
13 import com.google.common.collect.Multimap;
14 import com.google.common.net.InetAddresses;
15 import com.google.common.primitives.UnsignedBytes;
16 import io.netty.buffer.ByteBuf;
17 import io.netty.buffer.ByteBufUtil;
18 import io.netty.buffer.Unpooled;
19 import java.util.Arrays;
20 import java.util.BitSet;
21 import java.util.List;
22 import java.util.Map.Entry;
23 import org.opendaylight.protocol.bgp.parser.AttributeFlags;
24 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
25 import org.opendaylight.protocol.bgp.parser.spi.AttributeParser;
26 import org.opendaylight.protocol.bgp.parser.spi.AttributeSerializer;
27 import org.opendaylight.protocol.util.ByteArray;
28 import org.opendaylight.protocol.util.Ipv4Util;
29 import org.opendaylight.protocol.util.Ipv6Util;
30 import org.opendaylight.protocol.util.Values;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.AdministrativeGroup;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.ExtendedRouteTag;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.IgpBits.UpDown;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.Ipv4RouterIdentifier;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.Ipv6RouterIdentifier;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.IsisAreaIdentifier;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.LinkProtectionType;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.MplsProtocolMask;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.NlriType;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.NodeFlagBits;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.PathAttributes1;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.PathAttributes1Builder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.RouteTag;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.TopologyIdentifier;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.link.state.UnreservedBandwidth;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.link.state.UnreservedBandwidthBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.linkstate.destination.CLinkstateDestination;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.prefix.state.IgpBitsBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.update.path.attributes.LinkstatePathAttribute;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.update.path.attributes.LinkstatePathAttributeBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.update.path.attributes.linkstate.path.attribute.LinkStateAttribute;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.update.path.attributes.linkstate.path.attribute.link.state.attribute.LinkAttributesCase;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.update.path.attributes.linkstate.path.attribute.link.state.attribute.LinkAttributesCaseBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.update.path.attributes.linkstate.path.attribute.link.state.attribute.NodeAttributesCase;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.update.path.attributes.linkstate.path.attribute.link.state.attribute.NodeAttributesCaseBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.update.path.attributes.linkstate.path.attribute.link.state.attribute.PrefixAttributesCase;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.update.path.attributes.linkstate.path.attribute.link.state.attribute.PrefixAttributesCaseBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.update.path.attributes.linkstate.path.attribute.link.state.attribute.link.attributes._case.LinkAttributes;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.update.path.attributes.linkstate.path.attribute.link.state.attribute.link.attributes._case.LinkAttributesBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.update.path.attributes.linkstate.path.attribute.link.state.attribute.node.attributes._case.NodeAttributes;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.update.path.attributes.linkstate.path.attribute.link.state.attribute.node.attributes._case.NodeAttributesBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.update.path.attributes.linkstate.path.attribute.link.state.attribute.prefix.attributes._case.PrefixAttributes;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.update.path.attributes.linkstate.path.attribute.link.state.attribute.prefix.attributes._case.PrefixAttributesBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.update.path.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationLinkstateCase;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.PathAttributes;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.PathAttributesBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.PathAttributes2;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.destination.DestinationType;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.Bandwidth;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.IgpMetric;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.Metric;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.TeMetric;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev130820.SrlgId;
75 import org.opendaylight.yangtools.yang.binding.DataObject;
76 import org.slf4j.Logger;
77 import org.slf4j.LoggerFactory;
80 * Parser for Link State Path Attribute.
82 * @see <a href="http://tools.ietf.org/html/draft-gredler-idr-ls-distribution-04">BGP-LS draft</a>
84 public class LinkstateAttributeParser implements AttributeParser, AttributeSerializer {
85 // TODO: replace with actual values by IANA
86 public static final int TYPE = 99;
88 private static final Logger LOG = LoggerFactory.getLogger(LinkstateAttributeParser.class);
90 private static final int ROUTE_TAG_LENGTH = 4;
92 private static final int EXTENDED_ROUTE_TAG_LENGTH = 8;
94 private static final int SRLG_LENGTH = 4;
96 private static final int UNRESERVED_BW_COUNT = 8;
98 private static final int BANDWIDTH_LENGTH = 4;
101 private static final int OVERLOAD_BIT = 7;
102 private static final int ATTACHED_BIT = 6;
103 private static final int EXTERNAL_BIT = 5;
104 private static final int ABBR_BIT = 4;
106 // MPLS protection mask bits
107 private static final int LDP_BIT = 7;
108 private static final int RSVP_BIT = 6;
110 private NlriType getNlriType(final PathAttributesBuilder pab) {
111 final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.PathAttributes1 mpr = pab.getAugmentation(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.PathAttributes1.class);
112 if (mpr != null && mpr.getMpReachNlri() != null) {
113 final DestinationType dt = mpr.getMpReachNlri().getAdvertizedRoutes().getDestinationType();
114 if (dt instanceof DestinationLinkstateCase) {
115 for (final CLinkstateDestination d : ((DestinationLinkstateCase) dt).getDestinationLinkstate().getCLinkstateDestination()) {
116 return d.getNlriType();
120 LOG.debug("No MP_REACH attribute present");
122 final PathAttributes2 mpu = pab.getAugmentation(PathAttributes2.class);
123 if (mpu != null && mpu.getMpUnreachNlri() != null) {
124 final DestinationType dt = mpu.getMpUnreachNlri().getWithdrawnRoutes().getDestinationType();
125 if (dt instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.update.path.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationLinkstateCase) {
126 for (final CLinkstateDestination d : ((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.update.path.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationLinkstateCase) dt).getDestinationLinkstate().getCLinkstateDestination()) {
127 return d.getNlriType();
131 LOG.debug("No MP_UNREACH attribute present");
137 public void parseAttribute(final ByteBuf buffer, final PathAttributesBuilder builder) throws BGPParsingException {
138 final NlriType type = getNlriType(builder);
140 LOG.warn("No Linkstate NLRI found, not parsing Linkstate attribute");
143 final PathAttributes1 a = new PathAttributes1Builder().setLinkstatePathAttribute(parseLinkState(type, buffer)).build();
144 builder.addAugmentation(PathAttributes1.class, a);
147 private static LinkstatePathAttribute parseLinkState(final NlriType nlri, final ByteBuf buffer) throws BGPParsingException {
149 * e.g. IS-IS Area Identifier TLV can occur multiple times
151 final Multimap<Integer, byte[]> map = HashMultimap.create();
152 while (buffer.isReadable()) {
153 final int type = buffer.readUnsignedShort();
154 final int length = buffer.readUnsignedShort();
155 final byte[] value = ByteArray.readBytes(buffer, length);
156 map.put(type, value);
158 final LinkstatePathAttributeBuilder builder = new LinkstatePathAttributeBuilder();
163 builder.setLinkStateAttribute(parsePrefixAttributes(map));
164 return builder.build();
166 builder.setLinkStateAttribute(parseLinkAttributes(map));
167 return builder.build();
169 builder.setLinkStateAttribute(parseNodeAttributes(map));
170 return builder.build();
172 throw new IllegalStateException("Unhandled NLRI type " + nlri);
176 * Parse Link Attributes.
178 * @param attributes key is the tlv type and value is the value of the tlv
179 * @return {@link LinkStateAttribute}
181 private static LinkStateAttribute parseLinkAttributes(final Multimap<Integer, byte[]> attributes) {
182 final LinkAttributesBuilder builder = new LinkAttributesBuilder();
183 for (final Entry<Integer, byte[]> entry : attributes.entries()) {
184 LOG.trace("Link attribute TLV {}", entry.getKey());
185 final int key = entry.getKey();
186 final byte[] value = entry.getValue();
188 case TlvCode.LOCAL_IPV4_ROUTER_ID:
189 final Ipv4RouterIdentifier lipv4 = new Ipv4RouterIdentifier(Ipv4Util.addressForBytes(value));
190 builder.setLocalIpv4RouterId(lipv4);
191 LOG.debug("Parsed IPv4 Router-ID of local node: {}", lipv4);
193 case TlvCode.LOCAL_IPV6_ROUTER_ID:
194 final Ipv6RouterIdentifier lipv6 = new Ipv6RouterIdentifier(Ipv6Util.addressForBytes(value));
195 builder.setLocalIpv6RouterId(lipv6);
196 LOG.debug("Parsed IPv6 Router-ID of local node: {}", lipv6);
198 case TlvCode.REMOTE_IPV4_ROUTER_ID:
199 final Ipv4RouterIdentifier ripv4 = new Ipv4RouterIdentifier(Ipv4Util.addressForBytes(value));
200 builder.setRemoteIpv4RouterId(ripv4);
201 LOG.debug("Parsed IPv4 Router-ID of remote node: {}", ripv4);
203 case TlvCode.REMOTE_IPV6_ROUTER_ID:
204 final Ipv6RouterIdentifier ripv6 = new Ipv6RouterIdentifier(Ipv6Util.addressForBytes(value));
205 builder.setRemoteIpv6RouterId(ripv6);
206 LOG.debug("Parsed IPv6 Router-ID of remote node: {}", ripv6);
208 case TlvCode.ADMIN_GROUP:
209 builder.setAdminGroup(new AdministrativeGroup(ByteArray.bytesToLong(value)));
210 LOG.debug("Parsed Administrative Group {}", builder.getAdminGroup());
212 case TlvCode.MAX_BANDWIDTH:
213 builder.setMaxLinkBandwidth(new Bandwidth(value));
214 LOG.debug("Parsed Max Bandwidth {}", builder.getMaxLinkBandwidth());
216 case TlvCode.MAX_RESERVABLE_BANDWIDTH:
217 builder.setMaxReservableBandwidth(new Bandwidth(value));
218 LOG.debug("Parsed Max Reservable Bandwidth {}", builder.getMaxReservableBandwidth());
220 case TlvCode.UNRESERVED_BANDWIDTH:
222 final List<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.link.state.UnreservedBandwidth> unreservedBandwidth = Lists.newArrayList();
223 for (int i = 0; i < UNRESERVED_BW_COUNT; i++) {
224 final byte[] v = ByteArray.subByte(value, index, BANDWIDTH_LENGTH);
225 unreservedBandwidth.add(new UnreservedBandwidthBuilder().setBandwidth(new Bandwidth(v)).setPriority((short) i).build());
226 index += BANDWIDTH_LENGTH;
228 builder.setUnreservedBandwidth(unreservedBandwidth);
229 LOG.debug("Parsed Unreserved Bandwidth {}", builder.getUnreservedBandwidth());
231 case TlvCode.TE_METRIC:
232 builder.setTeMetric(new TeMetric(ByteArray.bytesToLong(value)));
233 LOG.debug("Parsed Metric {}", builder.getTeMetric());
235 case TlvCode.LINK_PROTECTION_TYPE:
236 final LinkProtectionType lpt = LinkProtectionType.forValue(UnsignedBytes.toInt(value[1]));
238 LOG.warn("Link Protection Type not recognized: {}", UnsignedBytes.toInt(value[1]));
241 builder.setLinkProtection(lpt);
242 LOG.debug("Parsed Link Protection Type {}", lpt);
244 case TlvCode.MPLS_PROTOCOL:
245 final boolean[] bits = ByteArray.parseBits(value[0]);
246 builder.setMplsProtocol(new MplsProtocolMask(bits[0], bits[1]));
247 LOG.debug("Parsed MPLS Protocols: {}", builder.getMplsProtocol());
250 builder.setMetric(new Metric(ByteArray.bytesToLong(value)));
251 LOG.debug("Parsed Metric {}", builder.getMetric());
253 case TlvCode.SHARED_RISK_LINK_GROUP:
255 final List<SrlgId> sharedRiskLinkGroups = Lists.newArrayList();
256 while (i != value.length) {
257 sharedRiskLinkGroups.add(new SrlgId(ByteArray.bytesToLong(ByteArray.subByte(value, i, SRLG_LENGTH))));
260 builder.setSharedRiskLinkGroups(sharedRiskLinkGroups);
261 LOG.debug("Parsed Shared Risk Link Groups {}", Arrays.toString(sharedRiskLinkGroups.toArray()));
263 case TlvCode.LINK_OPAQUE:
264 final byte[] opaque = value;
265 LOG.debug("Parsed Opaque value : {}", Arrays.toString(opaque));
267 case TlvCode.LINK_NAME:
268 final String name = new String(value, Charsets.US_ASCII);
269 builder.setLinkName(name);
270 LOG.debug("Parsed Link Name : {}", name);
273 LOG.warn("TLV {} is not a valid link attribute, ignoring it", key);
276 LOG.trace("Finished parsing Link Attributes.");
277 return new LinkAttributesCaseBuilder().setLinkAttributes(builder.build()).build();
281 * Parse Node Attributes.
283 * @param attributes key is the tlv type and value is the value of the tlv
284 * @return {@link LinkStateAttribute}
286 private static LinkStateAttribute parseNodeAttributes(final Multimap<Integer, byte[]> attributes) {
287 final List<TopologyIdentifier> topologyMembership = Lists.newArrayList();
288 final List<IsisAreaIdentifier> areaMembership = Lists.newArrayList();
289 final NodeAttributesBuilder builder = new NodeAttributesBuilder();
290 for (final Entry<Integer, byte[]> entry : attributes.entries()) {
291 final int key = entry.getKey();
292 final byte[] value = entry.getValue();
293 LOG.trace("Node attribute TLV {}", key);
295 case TlvCode.MULTI_TOPOLOGY_ID:
297 while (i != value.length) {
298 final TopologyIdentifier topId = new TopologyIdentifier(ByteArray.bytesToInt(ByteArray.subByte(value, i, 2)) & 0x3fff);
299 topologyMembership.add(topId);
300 LOG.debug("Parsed Topology Identifier: {}", topId);
304 case TlvCode.NODE_FLAG_BITS:
305 final boolean[] flags = ByteArray.parseBits(value[0]);
306 builder.setNodeFlags(new NodeFlagBits(flags[0], flags[1], flags[2], flags[3]));
307 LOG.debug("Parsed Overload bit: {}, attached bit: {}, external bit: {}, area border router: {}.", flags[0], flags[1],
310 case TlvCode.NODE_OPAQUE:
311 LOG.debug("Ignoring opaque value: {}.", Arrays.toString(value));
313 case TlvCode.DYNAMIC_HOSTNAME:
314 builder.setDynamicHostname(new String(value, Charsets.US_ASCII));
315 LOG.debug("Parsed Node Name {}", builder.getDynamicHostname());
317 case TlvCode.ISIS_AREA_IDENTIFIER:
318 final IsisAreaIdentifier ai = new IsisAreaIdentifier(value);
319 areaMembership.add(ai);
320 LOG.debug("Parsed AreaIdentifier {}", ai);
322 case TlvCode.LOCAL_IPV4_ROUTER_ID:
323 final Ipv4RouterIdentifier ip4 = new Ipv4RouterIdentifier(Ipv4Util.addressForBytes(value));
324 builder.setIpv4RouterId(ip4);
325 LOG.debug("Parsed IPv4 Router Identifier {}", ip4);
327 case TlvCode.LOCAL_IPV6_ROUTER_ID:
328 final Ipv6RouterIdentifier ip6 = new Ipv6RouterIdentifier(Ipv6Util.addressForBytes(value));
329 builder.setIpv6RouterId(ip6);
330 LOG.debug("Parsed IPv6 Router Identifier {}", ip6);
333 LOG.warn("TLV {} is not a valid node attribute, ignoring it", key);
336 LOG.trace("Finished parsing Node Attributes.");
337 builder.setTopologyIdentifier(topologyMembership);
338 builder.setIsisAreaId(areaMembership);
339 return new NodeAttributesCaseBuilder().setNodeAttributes(builder.build()).build();
343 * Parse prefix attributes.
345 * @param attributes key is the tlv type and value are the value bytes of the tlv
346 * @return {@link LinkStateAttribute}
348 private static LinkStateAttribute parsePrefixAttributes(final Multimap<Integer, byte[]> attributes) {
349 final PrefixAttributesBuilder builder = new PrefixAttributesBuilder();
350 final List<RouteTag> routeTags = Lists.newArrayList();
351 final List<ExtendedRouteTag> exRouteTags = Lists.newArrayList();
352 for (final Entry<Integer, byte[]> entry : attributes.entries()) {
353 final int key = entry.getKey();
354 final byte[] value = entry.getValue();
355 LOG.trace("Prefix attribute TLV {}", key);
357 case TlvCode.IGP_FLAGS:
358 final boolean[] flags = ByteArray.parseBits(value[0]);
359 final boolean upDownBit = flags[0];
360 builder.setIgpBits(new IgpBitsBuilder().setUpDown(new UpDown(upDownBit)).build());
361 LOG.debug("Parsed IGP flag (up/down bit) : {}", upDownBit);
363 case TlvCode.ROUTE_TAG:
365 while (offset != value.length) {
366 final RouteTag routeTag = new RouteTag(ByteArray.subByte(value, offset, ROUTE_TAG_LENGTH));
367 routeTags.add(routeTag);
368 LOG.debug("Parsed Route Tag: {}", routeTag);
369 offset += ROUTE_TAG_LENGTH;
372 case TlvCode.EXTENDED_ROUTE_TAG:
374 while (offset != value.length) {
375 final ExtendedRouteTag exRouteTag = new ExtendedRouteTag(ByteArray.subByte(value, offset, EXTENDED_ROUTE_TAG_LENGTH));
376 exRouteTags.add(exRouteTag);
377 LOG.debug("Parsed Extended Route Tag: {}", exRouteTag);
378 offset += EXTENDED_ROUTE_TAG_LENGTH;
381 case TlvCode.PREFIX_METRIC:
382 final IgpMetric metric = new IgpMetric(ByteArray.bytesToLong(value));
383 builder.setPrefixMetric(metric);
384 LOG.debug("Parsed Metric: {}", metric);
386 case TlvCode.FORWARDING_ADDRESS:
387 IpAddress fwdAddress = null;
388 switch (value.length) {
389 case Ipv4Util.IP4_LENGTH:
390 fwdAddress = new IpAddress(Ipv4Util.addressForBytes(value));
392 case Ipv6Util.IPV6_LENGTH:
393 fwdAddress = new IpAddress(Ipv6Util.addressForBytes(value));
396 LOG.debug("Ignoring unsupported forwarding address length {}", value.length);
398 builder.setOspfForwardingAddress(fwdAddress);
399 LOG.debug("Parsed FWD Address: {}", fwdAddress);
401 case TlvCode.PREFIX_OPAQUE:
402 LOG.debug("Parsed Opaque value: {}, not preserving it", ByteArray.bytesToHexString(value));
405 LOG.warn("TLV {} is not a valid prefix attribute, ignoring it", key);
408 LOG.trace("Finished parsing Prefix Attributes.");
409 builder.setRouteTags(routeTags);
410 builder.setExtendedTags(exRouteTags);
411 return new PrefixAttributesCaseBuilder().setPrefixAttributes(builder.build()).build();
415 * Serialize linkstate attributes.
417 * @param attribute DataObject representing LinkstatePathAttribute
418 * @param byteAggregator ByteBuf where all serialized data are aggregated
422 public void serializeAttribute(final DataObject attribute, final ByteBuf linkstateAttrBuffer) {
423 final PathAttributes1 pathAttributes1 = ((PathAttributes) attribute).getAugmentation(PathAttributes1.class);
424 if (pathAttributes1 == null) {
427 final LinkStateAttribute linkState = pathAttributes1.getLinkstatePathAttribute().getLinkStateAttribute();
428 final ByteBuf byteAggregator = Unpooled.buffer();
429 if (linkState instanceof LinkAttributesCase) {
430 serializeLinkAttributes((LinkAttributesCase) linkState, byteAggregator);
431 } else if (linkState instanceof NodeAttributesCase) {
432 serializeNodeAttributes((NodeAttributesCase) linkState, byteAggregator);
433 } else if (linkState instanceof PrefixAttributesCase) {
434 serializePrefixAttributes((PrefixAttributesCase) linkState, byteAggregator);
436 if (byteAggregator.writerIndex() > Values.UNSIGNED_BYTE_MAX_VALUE) {
437 linkstateAttrBuffer.writeByte(AttributeFlags.OPTIONAL | AttributeFlags.EXTENDED);
438 linkstateAttrBuffer.writeByte(TYPE);
439 linkstateAttrBuffer.writeShort(byteAggregator.writerIndex());
441 linkstateAttrBuffer.writeByte(AttributeFlags.OPTIONAL);
442 linkstateAttrBuffer.writeByte(TYPE);
443 linkstateAttrBuffer.writeByte(byteAggregator.writerIndex());
445 linkstateAttrBuffer.writeBytes(byteAggregator);
448 private void serializeLinkAttributes(final LinkAttributesCase linkAttributesCase, final ByteBuf byteAggregator) {
449 final LinkAttributes linkAttributes = linkAttributesCase.getLinkAttributes();
450 LOG.trace("Started serializing Link Attributes");
451 if (linkAttributes.getLocalIpv4RouterId() != null) {
452 writeTLV(TlvCode.LOCAL_IPV4_ROUTER_ID, Unpooled.wrappedBuffer(InetAddresses.forString(linkAttributes.getLocalIpv4RouterId().getValue()).getAddress()), byteAggregator);
454 if (linkAttributes.getLocalIpv6RouterId() != null) {
455 writeTLV(TlvCode.LOCAL_IPV6_ROUTER_ID, Unpooled.wrappedBuffer(InetAddresses.forString(linkAttributes.getLocalIpv6RouterId().getValue()).getAddress()), byteAggregator);
457 if (linkAttributes.getRemoteIpv4RouterId() != null) {
458 writeTLV(TlvCode.REMOTE_IPV4_ROUTER_ID, Unpooled.wrappedBuffer(InetAddresses.forString(linkAttributes.getRemoteIpv4RouterId().getValue()).getAddress()), byteAggregator);
460 if (linkAttributes.getRemoteIpv6RouterId() != null) {
461 writeTLV(TlvCode.REMOTE_IPV6_ROUTER_ID, Unpooled.wrappedBuffer(InetAddresses.forString(linkAttributes.getRemoteIpv6RouterId().getValue()).getAddress()), byteAggregator);
463 if (linkAttributes.getAdminGroup() != null) {
464 writeTLV(TlvCode.ADMIN_GROUP, Unpooled.copyInt(linkAttributes.getAdminGroup().getValue().intValue()), byteAggregator);
466 if (linkAttributes.getMaxLinkBandwidth() != null) {
467 writeTLV(TlvCode.MAX_BANDWIDTH, Unpooled.wrappedBuffer(linkAttributes.getMaxLinkBandwidth().getValue()), byteAggregator);
469 if (linkAttributes.getMaxReservableBandwidth() != null) {
470 writeTLV(TlvCode.MAX_RESERVABLE_BANDWIDTH, Unpooled.wrappedBuffer(linkAttributes.getMaxReservableBandwidth().getValue()), byteAggregator);
472 // this sub-TLV contains eight 32-bit IEEE floating point numbers
473 if (linkAttributes.getUnreservedBandwidth() != null) {
474 final ByteBuf unreservedBandwithBuf = Unpooled.buffer();
475 for (final UnreservedBandwidth unreservedBandwidth : linkAttributes.getUnreservedBandwidth()) {
476 unreservedBandwithBuf.writeBytes(unreservedBandwidth.getBandwidth().getValue());
478 writeTLV(TlvCode.UNRESERVED_BANDWIDTH, unreservedBandwithBuf, byteAggregator);
480 if (linkAttributes.getTeMetric() != null) {
481 writeTLV(TlvCode.TE_METRIC, Unpooled.copyLong(linkAttributes.getTeMetric().getValue().longValue()), byteAggregator);
483 if (linkAttributes.getLinkProtection() != null) {
484 writeTLV(TlvCode.LINK_PROTECTION_TYPE, Unpooled.copyShort(linkAttributes.getLinkProtection().getIntValue()), byteAggregator);
486 MplsProtocolMask mplsProtocolMask = linkAttributes.getMplsProtocol();
487 if (mplsProtocolMask != null) {
488 final ByteBuf mplsProtocolMaskBuf = Unpooled.buffer();
489 final BitSet mask = new BitSet();
490 if (mplsProtocolMask.isLdp() != null) {
491 mask.set(LDP_BIT, mplsProtocolMask.isLdp());
493 if (mplsProtocolMask.isRsvpte() != null) {
494 mask.set(RSVP_BIT, mplsProtocolMask.isRsvpte());
496 mplsProtocolMaskBuf.writeBytes(mask.toByteArray());
497 writeTLV(TlvCode.MPLS_PROTOCOL, mplsProtocolMaskBuf, byteAggregator);
499 if (linkAttributes.getMetric() != null) {
500 // size of metric can be 1,2 or 3 depending on the protocol
501 writeTLV(TlvCode.METRIC, Unpooled.copyMedium(linkAttributes.getMetric().getValue().intValue()), byteAggregator);
503 if (linkAttributes.getSharedRiskLinkGroups() != null) {
504 final ByteBuf sharedRLGBuf = Unpooled.buffer();
505 for (final SrlgId srlgId : linkAttributes.getSharedRiskLinkGroups()) {
506 sharedRLGBuf.writeInt(srlgId.getValue().intValue());
508 writeTLV(TlvCode.SHARED_RISK_LINK_GROUP, sharedRLGBuf, byteAggregator);
510 if (linkAttributes.getLinkName() != null) {
511 writeTLV(TlvCode.LINK_NAME, Unpooled.wrappedBuffer(linkAttributes.getLinkName().getBytes()), byteAggregator);
513 LOG.trace("Finished serializing Link Attributes");
516 private void serializeNodeAttributes(final NodeAttributesCase nodeAttributesCase, final ByteBuf byteAggregator) {
517 LOG.trace("Started serializing Node Attributes");
518 final NodeAttributes nodeAttributes = nodeAttributesCase.getNodeAttributes();
519 if (nodeAttributes.getTopologyIdentifier() != null) {
520 final ByteBuf mpIdBuf = Unpooled.buffer();
521 for (final TopologyIdentifier topologyIdentifier : nodeAttributes.getTopologyIdentifier()) {
522 mpIdBuf.writeShort(topologyIdentifier.getValue());
524 writeTLV(TlvCode.MULTI_TOPOLOGY_ID, mpIdBuf, byteAggregator);
526 final NodeFlagBits nodeFlagBits = nodeAttributes.getNodeFlags();
527 if (nodeFlagBits != null) {
528 final ByteBuf nodeFlagBuf = Unpooled.buffer();
529 final BitSet flags = new BitSet();
530 if (nodeFlagBits.isOverload() != null) {
531 flags.set(OVERLOAD_BIT, nodeFlagBits.isOverload());
533 if (nodeFlagBits.isAttached() != null) {
534 flags.set(ATTACHED_BIT, nodeFlagBits.isAttached());
536 if (nodeFlagBits.isExternal() != null) {
537 flags.set(EXTERNAL_BIT, nodeFlagBits.isExternal());
539 if (nodeFlagBits.isAbr() != null) {
540 flags.set(ABBR_BIT, nodeFlagBits.isAbr());
542 nodeFlagBuf.writeBytes(flags.toByteArray());
543 writeTLV(TlvCode.NODE_FLAG_BITS, nodeFlagBuf, byteAggregator);
545 if (nodeAttributes.getDynamicHostname() != null) {
546 writeTLV(TlvCode.DYNAMIC_HOSTNAME, Unpooled.wrappedBuffer(nodeAttributes.getDynamicHostname().getBytes()), byteAggregator);
548 if (nodeAttributes.getIsisAreaId() != null) {
549 for (final IsisAreaIdentifier isisAreaIdentifier : nodeAttributes.getIsisAreaId()) {
550 writeTLV(TlvCode.ISIS_AREA_IDENTIFIER, Unpooled.wrappedBuffer(isisAreaIdentifier.getValue()), byteAggregator);
553 if (nodeAttributes.getIpv4RouterId() != null) {
554 writeTLV(TlvCode.LOCAL_IPV4_ROUTER_ID, Unpooled.wrappedBuffer(InetAddresses.forString(nodeAttributes.getIpv4RouterId().getValue()).getAddress()), byteAggregator);
556 if (nodeAttributes.getIpv6RouterId() != null) {
557 writeTLV(TlvCode.LOCAL_IPV6_ROUTER_ID, Unpooled.wrappedBuffer(InetAddresses.forString(nodeAttributes.getIpv6RouterId().getValue()).getAddress()), byteAggregator);
559 LOG.trace("Finished serializing Node Attributes");
562 private void serializePrefixAttributes(final PrefixAttributesCase prefixAttributesCase, final ByteBuf byteAggregator) {
563 final PrefixAttributes prefixAtrributes = prefixAttributesCase.getPrefixAttributes();
564 if (prefixAtrributes.getIgpBits() != null) {
565 BitSet igpBit = new BitSet();
566 Boolean bit = prefixAtrributes.getIgpBits().getUpDown().isUpDown();
570 writeTLV(TlvCode.IGP_FLAGS, Unpooled.wrappedBuffer(igpBit.toByteArray()), byteAggregator);
572 if (prefixAtrributes.getRouteTags() != null) {
573 final ByteBuf routeTagsBuf = Unpooled.buffer();
574 for (final RouteTag routeTag : prefixAtrributes.getRouteTags()) {
575 routeTagsBuf.writeBytes(routeTag.getValue());
577 writeTLV(TlvCode.ROUTE_TAG, routeTagsBuf, byteAggregator);
579 if (prefixAtrributes.getExtendedTags() != null) {
580 final ByteBuf extendedBuf = Unpooled.buffer();
581 for (final ExtendedRouteTag extendedRouteTag : prefixAtrributes.getExtendedTags()) {
582 extendedBuf.writeBytes(extendedRouteTag.getValue());
584 writeTLV(TlvCode.EXTENDED_ROUTE_TAG, extendedBuf, byteAggregator);
586 if (prefixAtrributes.getPrefixMetric() != null) {
587 writeTLV(TlvCode.PREFIX_METRIC, Unpooled.copyInt(prefixAtrributes.getPrefixMetric().getValue().intValue()), byteAggregator);
589 IpAddress forwardingAddress = prefixAtrributes.getOspfForwardingAddress();
590 if (forwardingAddress != null) {
591 final ByteBuf ospfBuf = Unpooled.buffer();
592 if (forwardingAddress.getIpv4Address() != null) {
593 ospfBuf.writeBytes(Ipv4Util.bytesForAddress(forwardingAddress.getIpv4Address()));
594 } else if (forwardingAddress.getIpv6Address() != null) {
595 ospfBuf.writeBytes(Ipv6Util.bytesForAddress(forwardingAddress.getIpv6Address()));
597 writeTLV(TlvCode.FORWARDING_ADDRESS, ospfBuf, byteAggregator);
602 * Util method for writing TLV header.
603 * @param type TLV type
604 * @param value TLV value
605 * @param byteAggregator final ByteBuf where the tlv should be serialized
607 private static void writeTLV(final int type, final ByteBuf value, final ByteBuf byteAggregator){
608 byteAggregator.writeShort(type);
609 byteAggregator.writeShort(value.writerIndex());
610 byteAggregator.writeBytes(value);
611 value.readerIndex(0);
612 LOG.debug("Serialized tlv type {} to: {}", type, ByteBufUtil.hexDump(value));