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;
17 import io.netty.buffer.ByteBuf;
18 import io.netty.buffer.ByteBufUtil;
19 import io.netty.buffer.Unpooled;
21 import java.util.Arrays;
22 import java.util.BitSet;
23 import java.util.List;
24 import java.util.Map.Entry;
26 import org.opendaylight.protocol.bgp.parser.AttributeFlags;
27 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
28 import org.opendaylight.protocol.bgp.parser.spi.AttributeParser;
29 import org.opendaylight.protocol.bgp.parser.spi.AttributeSerializer;
30 import org.opendaylight.protocol.concepts.Ipv4Util;
31 import org.opendaylight.protocol.concepts.Ipv6Util;
32 import org.opendaylight.protocol.util.ByteArray;
33 import org.opendaylight.protocol.util.Values;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.AdministrativeGroup;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.ExtendedRouteTag;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.IgpBits.UpDown;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.Ipv4RouterIdentifier;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.Ipv6RouterIdentifier;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.IsisAreaIdentifier;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.LinkProtectionType;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.MplsProtocolMask;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.NlriType;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.NodeFlagBits;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.PathAttributes1;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.PathAttributes1Builder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.RouteTag;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.TopologyIdentifier;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.link.state.UnreservedBandwidth;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.link.state.UnreservedBandwidthBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.linkstate.destination.CLinkstateDestination;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.prefix.state.IgpBitsBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.update.path.attributes.LinkstatePathAttribute;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.update.path.attributes.LinkstatePathAttributeBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.update.path.attributes.linkstate.path.attribute.LinkStateAttribute;
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.LinkAttributesCase;
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.LinkAttributesCaseBuilder;
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.NodeAttributesCase;
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.NodeAttributesCaseBuilder;
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.PrefixAttributesCase;
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.PrefixAttributesCaseBuilder;
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.link.attributes._case.LinkAttributes;
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.link.attributes._case.LinkAttributesBuilder;
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.node.attributes._case.NodeAttributes;
65 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;
66 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;
67 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;
68 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;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.PathAttributes;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.PathAttributesBuilder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.PathAttributes2;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.destination.DestinationType;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.Bandwidth;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.IgpMetric;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.Metric;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.TeMetric;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev130820.SrlgId;
78 import org.opendaylight.yangtools.yang.binding.DataObject;
79 import org.slf4j.Logger;
80 import org.slf4j.LoggerFactory;
83 * Parser for Link State Path Attribute.
85 * @see <a href="http://tools.ietf.org/html/draft-gredler-idr-ls-distribution-04">BGP-LS draft</a>
87 public class LinkstateAttributeParser implements AttributeParser, AttributeSerializer {
88 // TODO: replace with actual values by IANA
89 public static final int TYPE = 99;
91 private static final Logger LOG = LoggerFactory.getLogger(LinkstateAttributeParser.class);
93 private static final int ROUTE_TAG_LENGTH = 4;
95 private static final int EXTENDED_ROUTE_TAG_LENGTH = 8;
97 private static final int SRLG_LENGTH = 4;
99 private static final int UNRESERVED_BW_COUNT = 8;
101 private static final int BANDWIDTH_LENGTH = 4;
104 private static final int OVERLOAD_BIT = 7;
105 private static final int ATTACHED_BIT = 6;
106 private static final int EXTERNAL_BIT = 5;
107 private static final int ABBR_BIT = 4;
109 // MPLS protection mask bits
110 private static final int LDP_BIT = 7;
111 private static final int RSVP_BIT = 6;
113 private NlriType getNlriType(final PathAttributesBuilder pab) {
114 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);
115 if (mpr != null && mpr.getMpReachNlri() != null) {
116 final DestinationType dt = mpr.getMpReachNlri().getAdvertizedRoutes().getDestinationType();
117 if (dt instanceof DestinationLinkstateCase) {
118 for (final CLinkstateDestination d : ((DestinationLinkstateCase) dt).getDestinationLinkstate().getCLinkstateDestination()) {
119 return d.getNlriType();
123 LOG.debug("No MP_REACH attribute present");
125 final PathAttributes2 mpu = pab.getAugmentation(PathAttributes2.class);
126 if (mpu != null && mpu.getMpUnreachNlri() != null) {
127 final DestinationType dt = mpu.getMpUnreachNlri().getWithdrawnRoutes().getDestinationType();
128 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) {
129 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()) {
130 return d.getNlriType();
134 LOG.debug("No MP_UNREACH attribute present");
140 public void parseAttribute(final ByteBuf buffer, final PathAttributesBuilder builder) throws BGPParsingException {
141 final NlriType type = getNlriType(builder);
143 LOG.warn("No Linkstate NLRI found, not parsing Linkstate attribute");
146 final PathAttributes1 a = new PathAttributes1Builder().setLinkstatePathAttribute(parseLinkState(type, buffer)).build();
147 builder.addAugmentation(PathAttributes1.class, a);
150 private static LinkstatePathAttribute parseLinkState(final NlriType nlri, final ByteBuf buffer) throws BGPParsingException {
152 * e.g. IS-IS Area Identifier TLV can occur multiple times
154 final Multimap<Integer, byte[]> map = HashMultimap.create();
155 while (buffer.isReadable()) {
156 final int type = buffer.readUnsignedShort();
157 final int length = buffer.readUnsignedShort();
158 final byte[] value = ByteArray.readBytes(buffer, length);
159 map.put(type, value);
161 final LinkstatePathAttributeBuilder builder = new LinkstatePathAttributeBuilder();
166 builder.setLinkStateAttribute(parsePrefixAttributes(map));
167 return builder.build();
169 builder.setLinkStateAttribute(parseLinkAttributes(map));
170 return builder.build();
172 builder.setLinkStateAttribute(parseNodeAttributes(map));
173 return builder.build();
175 throw new IllegalStateException("Unhandled NLRI type " + nlri);
179 * Parse Link Attributes.
181 * @param attributes key is the tlv type and value is the value of the tlv
182 * @return {@link LinkStateAttribute}
184 private static LinkStateAttribute parseLinkAttributes(final Multimap<Integer, byte[]> attributes) {
185 final LinkAttributesBuilder builder = new LinkAttributesBuilder();
186 for (final Entry<Integer, byte[]> entry : attributes.entries()) {
187 LOG.trace("Link attribute TLV {}", entry.getKey());
188 final int key = entry.getKey();
189 final byte[] value = entry.getValue();
191 case TlvCode.LOCAL_IPV4_ROUTER_ID:
192 final Ipv4RouterIdentifier lipv4 = new Ipv4RouterIdentifier(Ipv4Util.addressForBytes(value));
193 builder.setLocalIpv4RouterId(lipv4);
194 LOG.debug("Parsed IPv4 Router-ID of local node: {}", lipv4);
196 case TlvCode.LOCAL_IPV6_ROUTER_ID:
197 final Ipv6RouterIdentifier lipv6 = new Ipv6RouterIdentifier(Ipv6Util.addressForBytes(value));
198 builder.setLocalIpv6RouterId(lipv6);
199 LOG.debug("Parsed IPv6 Router-ID of local node: {}", lipv6);
201 case TlvCode.REMOTE_IPV4_ROUTER_ID:
202 final Ipv4RouterIdentifier ripv4 = new Ipv4RouterIdentifier(Ipv4Util.addressForBytes(value));
203 builder.setRemoteIpv4RouterId(ripv4);
204 LOG.debug("Parsed IPv4 Router-ID of remote node: {}", ripv4);
206 case TlvCode.REMOTE_IPV6_ROUTER_ID:
207 final Ipv6RouterIdentifier ripv6 = new Ipv6RouterIdentifier(Ipv6Util.addressForBytes(value));
208 builder.setRemoteIpv6RouterId(ripv6);
209 LOG.debug("Parsed IPv6 Router-ID of remote node: {}", ripv6);
211 case TlvCode.ADMIN_GROUP:
212 builder.setAdminGroup(new AdministrativeGroup(ByteArray.bytesToLong(value)));
213 LOG.debug("Parsed Administrative Group {}", builder.getAdminGroup());
215 case TlvCode.MAX_BANDWIDTH:
216 builder.setMaxLinkBandwidth(new Bandwidth(value));
217 LOG.debug("Parsed Max Bandwidth {}", builder.getMaxLinkBandwidth());
219 case TlvCode.MAX_RESERVABLE_BANDWIDTH:
220 builder.setMaxReservableBandwidth(new Bandwidth(value));
221 LOG.debug("Parsed Max Reservable Bandwidth {}", builder.getMaxReservableBandwidth());
223 case TlvCode.UNRESERVED_BANDWIDTH:
225 final List<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.link.state.UnreservedBandwidth> unreservedBandwidth = Lists.newArrayList();
226 for (int i = 0; i < UNRESERVED_BW_COUNT; i++) {
227 final byte[] v = ByteArray.subByte(value, index, BANDWIDTH_LENGTH);
228 unreservedBandwidth.add(new UnreservedBandwidthBuilder().setBandwidth(new Bandwidth(v)).setPriority((short) i).build());
229 index += BANDWIDTH_LENGTH;
231 builder.setUnreservedBandwidth(unreservedBandwidth);
232 LOG.debug("Parsed Unreserved Bandwidth {}", builder.getUnreservedBandwidth());
234 case TlvCode.TE_METRIC:
235 builder.setTeMetric(new TeMetric(ByteArray.bytesToLong(value)));
236 LOG.debug("Parsed Metric {}", builder.getTeMetric());
238 case TlvCode.LINK_PROTECTION_TYPE:
239 final LinkProtectionType lpt = LinkProtectionType.forValue(UnsignedBytes.toInt(value[1]));
241 LOG.warn("Link Protection Type not recognized: {}", UnsignedBytes.toInt(value[1]));
244 builder.setLinkProtection(lpt);
245 LOG.debug("Parsed Link Protection Type {}", lpt);
247 case TlvCode.MPLS_PROTOCOL:
248 final boolean[] bits = ByteArray.parseBits(value[0]);
249 builder.setMplsProtocol(new MplsProtocolMask(bits[0], bits[1]));
250 LOG.debug("Parsed MPLS Protocols: {}", builder.getMplsProtocol());
253 builder.setMetric(new Metric(ByteArray.bytesToLong(value)));
254 LOG.debug("Parsed Metric {}", builder.getMetric());
256 case TlvCode.SHARED_RISK_LINK_GROUP:
258 final List<SrlgId> sharedRiskLinkGroups = Lists.newArrayList();
259 while (i != value.length) {
260 sharedRiskLinkGroups.add(new SrlgId(ByteArray.bytesToLong(ByteArray.subByte(value, i, SRLG_LENGTH))));
263 builder.setSharedRiskLinkGroups(sharedRiskLinkGroups);
264 LOG.debug("Parsed Shared Risk Link Groups {}", Arrays.toString(sharedRiskLinkGroups.toArray()));
266 case TlvCode.LINK_OPAQUE:
267 final byte[] opaque = value;
268 LOG.debug("Parsed Opaque value : {}", Arrays.toString(opaque));
270 case TlvCode.LINK_NAME:
271 final String name = new String(value, Charsets.US_ASCII);
272 builder.setLinkName(name);
273 LOG.debug("Parsed Link Name : {}", name);
276 LOG.warn("TLV {} is not a valid link attribute, ignoring it", key);
279 LOG.trace("Finished parsing Link Attributes.");
280 return new LinkAttributesCaseBuilder().setLinkAttributes(builder.build()).build();
284 * Parse Node Attributes.
286 * @param attributes key is the tlv type and value is the value of the tlv
287 * @return {@link LinkStateAttribute}
289 private static LinkStateAttribute parseNodeAttributes(final Multimap<Integer, byte[]> attributes) {
290 final List<TopologyIdentifier> topologyMembership = Lists.newArrayList();
291 final List<IsisAreaIdentifier> areaMembership = Lists.newArrayList();
292 final NodeAttributesBuilder builder = new NodeAttributesBuilder();
293 for (final Entry<Integer, byte[]> entry : attributes.entries()) {
294 final int key = entry.getKey();
295 final byte[] value = entry.getValue();
296 LOG.trace("Node attribute TLV {}", key);
298 case TlvCode.MULTI_TOPOLOGY_ID:
300 while (i != value.length) {
301 final TopologyIdentifier topId = new TopologyIdentifier(ByteArray.bytesToInt(ByteArray.subByte(value, i, 2)) & 0x3fff);
302 topologyMembership.add(topId);
303 LOG.debug("Parsed Topology Identifier: {}", topId);
307 case TlvCode.NODE_FLAG_BITS:
308 final boolean[] flags = ByteArray.parseBits(value[0]);
309 builder.setNodeFlags(new NodeFlagBits(flags[0], flags[1], flags[2], flags[3]));
310 LOG.debug("Parsed Overload bit: {}, attached bit: {}, external bit: {}, area border router: {}.", flags[0], flags[1],
313 case TlvCode.NODE_OPAQUE:
314 LOG.debug("Ignoring opaque value: {}.", Arrays.toString(value));
316 case TlvCode.DYNAMIC_HOSTNAME:
317 builder.setDynamicHostname(new String(value, Charsets.US_ASCII));
318 LOG.debug("Parsed Node Name {}", builder.getDynamicHostname());
320 case TlvCode.ISIS_AREA_IDENTIFIER:
321 final IsisAreaIdentifier ai = new IsisAreaIdentifier(value);
322 areaMembership.add(ai);
323 LOG.debug("Parsed AreaIdentifier {}", ai);
325 case TlvCode.LOCAL_IPV4_ROUTER_ID:
326 final Ipv4RouterIdentifier ip4 = new Ipv4RouterIdentifier(Ipv4Util.addressForBytes(value));
327 builder.setIpv4RouterId(ip4);
328 LOG.debug("Parsed IPv4 Router Identifier {}", ip4);
330 case TlvCode.LOCAL_IPV6_ROUTER_ID:
331 final Ipv6RouterIdentifier ip6 = new Ipv6RouterIdentifier(Ipv6Util.addressForBytes(value));
332 builder.setIpv6RouterId(ip6);
333 LOG.debug("Parsed IPv6 Router Identifier {}", ip6);
336 LOG.warn("TLV {} is not a valid node attribute, ignoring it", key);
339 LOG.trace("Finished parsing Node Attributes.");
340 builder.setTopologyIdentifier(topologyMembership);
341 builder.setIsisAreaId(areaMembership);
342 return new NodeAttributesCaseBuilder().setNodeAttributes(builder.build()).build();
346 * Parse prefix attributes.
348 * @param attributes key is the tlv type and value are the value bytes of the tlv
349 * @return {@link LinkStateAttribute}
351 private static LinkStateAttribute parsePrefixAttributes(final Multimap<Integer, byte[]> attributes) {
352 final PrefixAttributesBuilder builder = new PrefixAttributesBuilder();
353 final List<RouteTag> routeTags = Lists.newArrayList();
354 final List<ExtendedRouteTag> exRouteTags = Lists.newArrayList();
355 for (final Entry<Integer, byte[]> entry : attributes.entries()) {
356 final int key = entry.getKey();
357 final byte[] value = entry.getValue();
358 LOG.trace("Prefix attribute TLV {}", key);
360 case TlvCode.IGP_FLAGS:
361 final boolean[] flags = ByteArray.parseBits(value[0]);
362 final boolean upDownBit = flags[0];
363 builder.setIgpBits(new IgpBitsBuilder().setUpDown(new UpDown(upDownBit)).build());
364 LOG.debug("Parsed IGP flag (up/down bit) : {}", upDownBit);
366 case TlvCode.ROUTE_TAG:
368 while (offset != value.length) {
369 final RouteTag routeTag = new RouteTag(ByteArray.subByte(value, offset, ROUTE_TAG_LENGTH));
370 routeTags.add(routeTag);
371 LOG.debug("Parsed Route Tag: {}", routeTag);
372 offset += ROUTE_TAG_LENGTH;
375 case TlvCode.EXTENDED_ROUTE_TAG:
377 while (offset != value.length) {
378 final ExtendedRouteTag exRouteTag = new ExtendedRouteTag(ByteArray.subByte(value, offset, EXTENDED_ROUTE_TAG_LENGTH));
379 exRouteTags.add(exRouteTag);
380 LOG.debug("Parsed Extended Route Tag: {}", exRouteTag);
381 offset += EXTENDED_ROUTE_TAG_LENGTH;
384 case TlvCode.PREFIX_METRIC:
385 final IgpMetric metric = new IgpMetric(ByteArray.bytesToLong(value));
386 builder.setPrefixMetric(metric);
387 LOG.debug("Parsed Metric: {}", metric);
389 case TlvCode.FORWARDING_ADDRESS:
390 IpAddress fwdAddress = null;
391 switch (value.length) {
392 case Ipv4Util.IP4_LENGTH:
393 fwdAddress = new IpAddress(Ipv4Util.addressForBytes(value));
395 case Ipv6Util.IPV6_LENGTH:
396 fwdAddress = new IpAddress(Ipv6Util.addressForBytes(value));
399 LOG.debug("Ignoring unsupported forwarding address length {}", value.length);
401 builder.setOspfForwardingAddress(fwdAddress);
402 LOG.debug("Parsed FWD Address: {}", fwdAddress);
404 case TlvCode.PREFIX_OPAQUE:
405 LOG.debug("Parsed Opaque value: {}, not preserving it", ByteArray.bytesToHexString(value));
408 LOG.warn("TLV {} is not a valid prefix attribute, ignoring it", key);
411 LOG.trace("Finished parsing Prefix Attributes.");
412 builder.setRouteTags(routeTags);
413 builder.setExtendedTags(exRouteTags);
414 return new PrefixAttributesCaseBuilder().setPrefixAttributes(builder.build()).build();
418 * Serialize linkstate attributes.
420 * @param attribute DataObject representing LinkstatePathAttribute
421 * @param byteAggregator ByteBuf where all serialized data are aggregated
425 public void serializeAttribute(final DataObject attribute, final ByteBuf linkstateAttrBuffer) {
426 final PathAttributes1 pathAttributes1 = ((PathAttributes) attribute).getAugmentation(PathAttributes1.class);
427 if (pathAttributes1 == null) {
430 final LinkStateAttribute linkState = pathAttributes1.getLinkstatePathAttribute().getLinkStateAttribute();
431 final ByteBuf byteAggregator = Unpooled.buffer();
432 if (linkState instanceof LinkAttributesCase) {
433 serializeLinkAttributes((LinkAttributesCase) linkState, byteAggregator);
434 } else if (linkState instanceof NodeAttributesCase) {
435 serializeNodeAttributes((NodeAttributesCase) linkState, byteAggregator);
436 } else if (linkState instanceof PrefixAttributesCase) {
437 serializePrefixAttributes((PrefixAttributesCase) linkState, byteAggregator);
439 if (byteAggregator.writerIndex() > Values.UNSIGNED_BYTE_MAX_VALUE) {
440 linkstateAttrBuffer.writeByte(AttributeFlags.OPTIONAL | AttributeFlags.EXTENDED);
441 linkstateAttrBuffer.writeByte(TYPE);
442 linkstateAttrBuffer.writeShort(byteAggregator.writerIndex());
444 linkstateAttrBuffer.writeByte(AttributeFlags.OPTIONAL);
445 linkstateAttrBuffer.writeByte(TYPE);
446 linkstateAttrBuffer.writeByte(byteAggregator.writerIndex());
448 linkstateAttrBuffer.writeBytes(byteAggregator);
451 private void serializeLinkAttributes(final LinkAttributesCase linkAttributesCase, final ByteBuf byteAggregator) {
452 final LinkAttributes linkAttributes = linkAttributesCase.getLinkAttributes();
453 LOG.trace("Started serializing Link Attributes");
454 if (linkAttributes.getLocalIpv4RouterId() != null) {
455 writeTLV(TlvCode.LOCAL_IPV4_ROUTER_ID, Unpooled.wrappedBuffer(InetAddresses.forString(linkAttributes.getLocalIpv4RouterId().getValue()).getAddress()), byteAggregator);
457 if (linkAttributes.getLocalIpv6RouterId() != null) {
458 writeTLV(TlvCode.LOCAL_IPV6_ROUTER_ID, Unpooled.wrappedBuffer(InetAddresses.forString(linkAttributes.getLocalIpv6RouterId().getValue()).getAddress()), byteAggregator);
460 if (linkAttributes.getRemoteIpv4RouterId() != null) {
461 writeTLV(TlvCode.REMOTE_IPV4_ROUTER_ID, Unpooled.wrappedBuffer(InetAddresses.forString(linkAttributes.getRemoteIpv4RouterId().getValue()).getAddress()), byteAggregator);
463 if (linkAttributes.getRemoteIpv6RouterId() != null) {
464 writeTLV(TlvCode.REMOTE_IPV6_ROUTER_ID, Unpooled.wrappedBuffer(InetAddresses.forString(linkAttributes.getRemoteIpv6RouterId().getValue()).getAddress()), byteAggregator);
466 if (linkAttributes.getAdminGroup() != null) {
467 writeTLV(TlvCode.ADMIN_GROUP, Unpooled.copyInt(linkAttributes.getAdminGroup().getValue().intValue()), byteAggregator);
469 if (linkAttributes.getMaxLinkBandwidth() != null) {
470 writeTLV(TlvCode.MAX_BANDWIDTH, Unpooled.wrappedBuffer(linkAttributes.getMaxLinkBandwidth().getValue()), byteAggregator);
472 if (linkAttributes.getMaxReservableBandwidth() != null) {
473 writeTLV(TlvCode.MAX_RESERVABLE_BANDWIDTH, Unpooled.wrappedBuffer(linkAttributes.getMaxReservableBandwidth().getValue()), byteAggregator);
475 // this sub-TLV contains eight 32-bit IEEE floating point numbers
476 if (linkAttributes.getUnreservedBandwidth() != null) {
477 final ByteBuf unreservedBandwithBuf = Unpooled.buffer();
478 for (final UnreservedBandwidth unreservedBandwidth : linkAttributes.getUnreservedBandwidth()) {
479 unreservedBandwithBuf.writeBytes(unreservedBandwidth.getBandwidth().getValue());
481 writeTLV(TlvCode.UNRESERVED_BANDWIDTH, unreservedBandwithBuf, byteAggregator);
483 if (linkAttributes.getTeMetric() != null) {
484 writeTLV(TlvCode.TE_METRIC, Unpooled.copyLong(linkAttributes.getTeMetric().getValue().longValue()), byteAggregator);
486 if (linkAttributes.getLinkProtection() != null) {
487 writeTLV(TlvCode.LINK_PROTECTION_TYPE, Unpooled.copyShort(linkAttributes.getLinkProtection().getIntValue()), byteAggregator);
489 MplsProtocolMask mplsProtocolMask = linkAttributes.getMplsProtocol();
490 if (mplsProtocolMask != null) {
491 final ByteBuf mplsProtocolMaskBuf = Unpooled.buffer();
492 final BitSet mask = new BitSet();
493 if (mplsProtocolMask.isLdp() != null) {
494 mask.set(LDP_BIT, mplsProtocolMask.isLdp());
496 if (mplsProtocolMask.isRsvpte() != null) {
497 mask.set(RSVP_BIT, mplsProtocolMask.isRsvpte());
499 mplsProtocolMaskBuf.writeBytes(mask.toByteArray());
500 writeTLV(TlvCode.MPLS_PROTOCOL, mplsProtocolMaskBuf, byteAggregator);
502 if (linkAttributes.getMetric() != null) {
503 // size of metric can be 1,2 or 3 depending on the protocol
504 writeTLV(TlvCode.METRIC, Unpooled.copyMedium(linkAttributes.getMetric().getValue().intValue()), byteAggregator);
506 if (linkAttributes.getSharedRiskLinkGroups() != null) {
507 final ByteBuf sharedRLGBuf = Unpooled.buffer();
508 for (final SrlgId srlgId : linkAttributes.getSharedRiskLinkGroups()) {
509 sharedRLGBuf.writeInt(srlgId.getValue().intValue());
511 writeTLV(TlvCode.SHARED_RISK_LINK_GROUP, sharedRLGBuf, byteAggregator);
513 if (linkAttributes.getLinkName() != null) {
514 writeTLV(TlvCode.LINK_NAME, Unpooled.wrappedBuffer(linkAttributes.getLinkName().getBytes()), byteAggregator);
516 LOG.trace("Finished serializing Link Attributes");
519 private void serializeNodeAttributes(final NodeAttributesCase nodeAttributesCase, final ByteBuf byteAggregator) {
520 LOG.trace("Started serializing Node Attributes");
521 final NodeAttributes nodeAttributes = nodeAttributesCase.getNodeAttributes();
522 if (nodeAttributes.getTopologyIdentifier() != null) {
523 final ByteBuf mpIdBuf = Unpooled.buffer();
524 for (final TopologyIdentifier topologyIdentifier : nodeAttributes.getTopologyIdentifier()) {
525 mpIdBuf.writeShort(topologyIdentifier.getValue());
527 writeTLV(TlvCode.MULTI_TOPOLOGY_ID, mpIdBuf, byteAggregator);
529 final NodeFlagBits nodeFlagBits = nodeAttributes.getNodeFlags();
530 if (nodeFlagBits != null) {
531 final ByteBuf nodeFlagBuf = Unpooled.buffer();
532 final BitSet flags = new BitSet();
533 if (nodeFlagBits.isOverload() != null) {
534 flags.set(OVERLOAD_BIT, nodeFlagBits.isOverload());
536 if (nodeFlagBits.isAttached() != null) {
537 flags.set(ATTACHED_BIT, nodeFlagBits.isAttached());
539 if (nodeFlagBits.isExternal() != null) {
540 flags.set(EXTERNAL_BIT, nodeFlagBits.isExternal());
542 if (nodeFlagBits.isAbr() != null) {
543 flags.set(ABBR_BIT, nodeFlagBits.isAbr());
545 nodeFlagBuf.writeBytes(flags.toByteArray());
546 writeTLV(TlvCode.NODE_FLAG_BITS, nodeFlagBuf, byteAggregator);
548 if (nodeAttributes.getDynamicHostname() != null) {
549 writeTLV(TlvCode.DYNAMIC_HOSTNAME, Unpooled.wrappedBuffer(nodeAttributes.getDynamicHostname().getBytes()), byteAggregator);
551 if (nodeAttributes.getIsisAreaId() != null) {
552 for (final IsisAreaIdentifier isisAreaIdentifier : nodeAttributes.getIsisAreaId()) {
553 writeTLV(TlvCode.ISIS_AREA_IDENTIFIER, Unpooled.wrappedBuffer(isisAreaIdentifier.getValue()), byteAggregator);
556 if (nodeAttributes.getIpv4RouterId() != null) {
557 writeTLV(TlvCode.LOCAL_IPV4_ROUTER_ID, Unpooled.wrappedBuffer(InetAddresses.forString(nodeAttributes.getIpv4RouterId().getValue()).getAddress()), byteAggregator);
559 if (nodeAttributes.getIpv6RouterId() != null) {
560 writeTLV(TlvCode.LOCAL_IPV6_ROUTER_ID, Unpooled.wrappedBuffer(InetAddresses.forString(nodeAttributes.getIpv6RouterId().getValue()).getAddress()), byteAggregator);
562 LOG.trace("Finished serializing Node Attributes");
565 private void serializePrefixAttributes(final PrefixAttributesCase prefixAttributesCase, final ByteBuf byteAggregator) {
566 final PrefixAttributes prefixAtrributes = prefixAttributesCase.getPrefixAttributes();
567 if (prefixAtrributes.getIgpBits() != null) {
568 BitSet igpBit = new BitSet();
569 Boolean bit = prefixAtrributes.getIgpBits().getUpDown().isUpDown();
573 writeTLV(TlvCode.IGP_FLAGS, Unpooled.wrappedBuffer(igpBit.toByteArray()), byteAggregator);
575 if (prefixAtrributes.getRouteTags() != null) {
576 final ByteBuf routeTagsBuf = Unpooled.buffer();
577 for (final RouteTag routeTag : prefixAtrributes.getRouteTags()) {
578 routeTagsBuf.writeBytes(routeTag.getValue());
580 writeTLV(TlvCode.ROUTE_TAG, routeTagsBuf, byteAggregator);
582 if (prefixAtrributes.getExtendedTags() != null) {
583 final ByteBuf extendedBuf = Unpooled.buffer();
584 for (final ExtendedRouteTag extendedRouteTag : prefixAtrributes.getExtendedTags()) {
585 extendedBuf.writeBytes(extendedRouteTag.getValue());
587 writeTLV(TlvCode.EXTENDED_ROUTE_TAG, extendedBuf, byteAggregator);
589 if (prefixAtrributes.getPrefixMetric() != null) {
590 writeTLV(TlvCode.PREFIX_METRIC, Unpooled.copyInt(prefixAtrributes.getPrefixMetric().getValue().intValue()), byteAggregator);
592 IpAddress forwardingAddress = prefixAtrributes.getOspfForwardingAddress();
593 if (forwardingAddress != null) {
594 final ByteBuf ospfBuf = Unpooled.buffer();
595 if (forwardingAddress.getIpv4Address() != null) {
596 ospfBuf.writeBytes(Ipv4Util.bytesForAddress(forwardingAddress.getIpv4Address()));
597 } else if (forwardingAddress.getIpv6Address() != null) {
598 ospfBuf.writeBytes(Ipv6Util.bytesForAddress(forwardingAddress.getIpv6Address()));
600 writeTLV(TlvCode.FORWARDING_ADDRESS, ospfBuf, byteAggregator);
605 * Util method for writing TLV header.
606 * @param type TLV type
607 * @param value TLV value
608 * @param byteAggregator final ByteBuf where the tlv should be serialized
610 private static void writeTLV(final int type, final ByteBuf value, final ByteBuf byteAggregator){
611 byteAggregator.writeShort(type);
612 byteAggregator.writeShort(value.writerIndex());
613 byteAggregator.writeBytes(value);
614 value.readerIndex(0);
615 LOG.debug("Serialized tlv type {} to: {}", type, ByteBufUtil.hexDump(value));