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.base.Preconditions;
12 import com.google.common.collect.HashMultimap;
13 import com.google.common.collect.Lists;
14 import com.google.common.collect.Multimap;
15 import com.google.common.net.InetAddresses;
16 import io.netty.buffer.ByteBuf;
17 import io.netty.buffer.ByteBufUtil;
18 import io.netty.buffer.Unpooled;
19 import java.util.ArrayList;
20 import java.util.Arrays;
21 import java.util.BitSet;
22 import java.util.List;
23 import java.util.Map.Entry;
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.bgp.parser.spi.AttributeUtil;
28 import org.opendaylight.protocol.util.ByteArray;
29 import org.opendaylight.protocol.util.Ipv4Util;
30 import org.opendaylight.protocol.util.Ipv6Util;
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 {
86 private static final int TYPE = 29;
88 private static final int LEGACY_TYPE = 99;
90 private static final Logger LOG = LoggerFactory.getLogger(LinkstateAttributeParser.class);
92 private static final int ROUTE_TAG_LENGTH = 4;
94 private static final int EXTENDED_ROUTE_TAG_LENGTH = 8;
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 static final int UP_DOWN_BIT = 7;
112 private final int type;
114 public LinkstateAttributeParser(final boolean isIanaAssignedType) {
115 if(isIanaAssignedType) {
118 this.type = LEGACY_TYPE;
122 public int getType() {
126 private NlriType getNlriType(final PathAttributesBuilder pab) {
127 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);
128 if (mpr != null && mpr.getMpReachNlri() != null) {
129 final DestinationType dt = mpr.getMpReachNlri().getAdvertizedRoutes().getDestinationType();
130 if (dt instanceof DestinationLinkstateCase) {
131 for (final CLinkstateDestination d : ((DestinationLinkstateCase) dt).getDestinationLinkstate().getCLinkstateDestination()) {
132 return d.getNlriType();
136 LOG.debug("No MP_REACH attribute present");
138 final PathAttributes2 mpu = pab.getAugmentation(PathAttributes2.class);
139 if (mpu != null && mpu.getMpUnreachNlri() != null) {
140 final DestinationType dt = mpu.getMpUnreachNlri().getWithdrawnRoutes().getDestinationType();
141 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) {
142 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()) {
143 return d.getNlriType();
147 LOG.debug("No MP_UNREACH attribute present");
153 public void parseAttribute(final ByteBuf buffer, final PathAttributesBuilder builder) throws BGPParsingException {
154 final NlriType nlriType = getNlriType(builder);
155 if (nlriType == null) {
156 LOG.warn("No Linkstate NLRI found, not parsing Linkstate attribute");
159 final PathAttributes1 a = new PathAttributes1Builder().setLinkstatePathAttribute(parseLinkState(nlriType, buffer)).build();
160 builder.addAugmentation(PathAttributes1.class, a);
163 private static LinkstatePathAttribute parseLinkState(final NlriType nlri, final ByteBuf buffer) throws BGPParsingException {
165 * e.g. IS-IS Area Identifier TLV can occur multiple times
167 final Multimap<Integer, ByteBuf> map = HashMultimap.create();
168 while (buffer.isReadable()) {
169 final int type = buffer.readUnsignedShort();
170 final int length = buffer.readUnsignedShort();
171 final ByteBuf value = buffer.slice(buffer.readerIndex(), length);
172 map.put(type, value);
173 buffer.skipBytes(length);
175 final LinkstatePathAttributeBuilder builder = new LinkstatePathAttributeBuilder();
180 builder.setLinkStateAttribute(parsePrefixAttributes(map));
181 return builder.build();
183 builder.setLinkStateAttribute(parseLinkAttributes(map));
184 return builder.build();
186 builder.setLinkStateAttribute(parseNodeAttributes(map));
187 return builder.build();
189 throw new IllegalStateException("Unhandled NLRI type " + nlri);
193 * Parse Link Attributes.
195 * @param attributes key is the tlv type and value is the value of the tlv
196 * @return {@link LinkStateAttribute}
198 private static LinkStateAttribute parseLinkAttributes(final Multimap<Integer, ByteBuf> attributes) {
199 final LinkAttributesBuilder builder = new LinkAttributesBuilder();
200 for (final Entry<Integer, ByteBuf> entry : attributes.entries()) {
201 LOG.trace("Link attribute TLV {}", entry.getKey());
202 final int key = entry.getKey();
203 final ByteBuf value = entry.getValue();
205 case TlvCode.LOCAL_IPV4_ROUTER_ID:
206 final Ipv4RouterIdentifier lipv4 = new Ipv4RouterIdentifier(Ipv4Util.addressForByteBuf(value));
207 builder.setLocalIpv4RouterId(lipv4);
208 LOG.debug("Parsed IPv4 Router-ID of local node: {}", lipv4);
210 case TlvCode.LOCAL_IPV6_ROUTER_ID:
211 final Ipv6RouterIdentifier lipv6 = new Ipv6RouterIdentifier(Ipv6Util.addressForByteBuf(value));
212 builder.setLocalIpv6RouterId(lipv6);
213 LOG.debug("Parsed IPv6 Router-ID of local node: {}", lipv6);
215 case TlvCode.REMOTE_IPV4_ROUTER_ID:
216 final Ipv4RouterIdentifier ripv4 = new Ipv4RouterIdentifier(Ipv4Util.addressForByteBuf(value));
217 builder.setRemoteIpv4RouterId(ripv4);
218 LOG.debug("Parsed IPv4 Router-ID of remote node: {}", ripv4);
220 case TlvCode.REMOTE_IPV6_ROUTER_ID:
221 final Ipv6RouterIdentifier ripv6 = new Ipv6RouterIdentifier(Ipv6Util.addressForByteBuf(value));
222 builder.setRemoteIpv6RouterId(ripv6);
223 LOG.debug("Parsed IPv6 Router-ID of remote node: {}", ripv6);
225 case TlvCode.ADMIN_GROUP:
226 builder.setAdminGroup(new AdministrativeGroup(value.readUnsignedInt()));
227 LOG.debug("Parsed Administrative Group {}", builder.getAdminGroup());
229 case TlvCode.MAX_BANDWIDTH:
230 builder.setMaxLinkBandwidth(new Bandwidth(ByteArray.readAllBytes(value)));
231 LOG.debug("Parsed Max Bandwidth {}", builder.getMaxLinkBandwidth());
233 case TlvCode.MAX_RESERVABLE_BANDWIDTH:
234 builder.setMaxReservableBandwidth(new Bandwidth(ByteArray.readAllBytes(value)));
235 LOG.debug("Parsed Max Reservable Bandwidth {}", builder.getMaxReservableBandwidth());
237 case TlvCode.UNRESERVED_BANDWIDTH:
238 final List<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.link.state.UnreservedBandwidth> unreservedBandwidth = new ArrayList<>(UNRESERVED_BW_COUNT);
239 for (int i = 0; i < UNRESERVED_BW_COUNT; i++) {
240 final ByteBuf v = value.slice(value.readerIndex(), BANDWIDTH_LENGTH);
241 unreservedBandwidth.add(new UnreservedBandwidthBuilder().setBandwidth(new Bandwidth(ByteArray.readAllBytes(v))).setPriority((short) i).build());
242 value.skipBytes(BANDWIDTH_LENGTH);
244 builder.setUnreservedBandwidth(unreservedBandwidth);
245 LOG.debug("Parsed Unreserved Bandwidth {}", builder.getUnreservedBandwidth());
247 case TlvCode.TE_METRIC:
248 builder.setTeMetric(new TeMetric(ByteArray.bytesToLong(ByteArray.readAllBytes(value))));
249 LOG.debug("Parsed Metric {}", builder.getTeMetric());
251 case TlvCode.LINK_PROTECTION_TYPE:
252 final int l = value.readShort();
253 final LinkProtectionType lpt = LinkProtectionType.forValue(l);
255 LOG.warn("Link Protection Type not recognized: {}", l);
258 builder.setLinkProtection(lpt);
259 LOG.debug("Parsed Link Protection Type {}", lpt);
261 case TlvCode.MPLS_PROTOCOL:
262 final BitSet bits = BitSet.valueOf(ByteArray.readAllBytes(value));
263 builder.setMplsProtocol(new MplsProtocolMask(bits.get(LDP_BIT), bits.get(RSVP_BIT)));
264 LOG.debug("Parsed MPLS Protocols: {}", builder.getMplsProtocol());
267 // length can 3, 2 or 1
268 builder.setMetric(new Metric(ByteArray.bytesToLong(ByteArray.readAllBytes(value))));
269 LOG.debug("Parsed Metric {}", builder.getMetric());
271 case TlvCode.SHARED_RISK_LINK_GROUP:
272 final List<SrlgId> sharedRiskLinkGroups = new ArrayList<>();
273 while (value.isReadable()) {
274 sharedRiskLinkGroups.add(new SrlgId(value.readUnsignedInt()));
276 builder.setSharedRiskLinkGroups(sharedRiskLinkGroups);
277 LOG.debug("Parsed Shared Risk Link Groups {}", Arrays.toString(sharedRiskLinkGroups.toArray()));
279 case TlvCode.LINK_OPAQUE:
280 LOG.debug("Parsed Opaque value : {}", ByteBufUtil.hexDump(value));
282 case TlvCode.LINK_NAME:
283 final String name = new String(ByteArray.readAllBytes(value), Charsets.US_ASCII);
284 builder.setLinkName(name);
285 LOG.debug("Parsed Link Name : {}", name);
288 LOG.warn("TLV {} is not a valid link attribute, ignoring it", key);
291 LOG.trace("Finished parsing Link Attributes.");
292 return new LinkAttributesCaseBuilder().setLinkAttributes(builder.build()).build();
296 * Parse Node Attributes.
298 * @param attributes key is the tlv type and value is the value of the tlv
299 * @return {@link LinkStateAttribute}
301 private static LinkStateAttribute parseNodeAttributes(final Multimap<Integer, ByteBuf> attributes) {
302 final List<TopologyIdentifier> topologyMembership = Lists.newArrayList();
303 final List<IsisAreaIdentifier> areaMembership = Lists.newArrayList();
304 final NodeAttributesBuilder builder = new NodeAttributesBuilder();
305 for (final Entry<Integer, ByteBuf> entry : attributes.entries()) {
306 final int key = entry.getKey();
307 final ByteBuf value = entry.getValue();
308 LOG.trace("Node attribute TLV {}", key);
310 case TlvCode.MULTI_TOPOLOGY_ID:
311 while (value.isReadable()) {
312 final TopologyIdentifier topId = new TopologyIdentifier(value.readUnsignedShort() & LinkstateNlriParser.TOPOLOGY_ID_OFFSET);
313 topologyMembership.add(topId);
314 LOG.debug("Parsed Topology Identifier: {}", topId);
317 case TlvCode.NODE_FLAG_BITS:
318 final BitSet flags = BitSet.valueOf(ByteArray.readAllBytes(value));
319 builder.setNodeFlags(new NodeFlagBits(flags.get(OVERLOAD_BIT), flags.get(ATTACHED_BIT), flags.get(EXTERNAL_BIT), flags.get(ABBR_BIT)));
320 LOG.debug("Parsed Overload bit: {}, attached bit: {}, external bit: {}, area border router: {}.",
321 flags.get(OVERLOAD_BIT), flags.get(ATTACHED_BIT), flags.get(EXTERNAL_BIT), flags.get(ABBR_BIT));
323 case TlvCode.NODE_OPAQUE:
324 LOG.debug("Ignoring opaque value: {}.", ByteBufUtil.hexDump(value));
326 case TlvCode.DYNAMIC_HOSTNAME:
327 builder.setDynamicHostname(new String(ByteArray.readAllBytes(value), Charsets.US_ASCII));
328 LOG.debug("Parsed Node Name {}", builder.getDynamicHostname());
330 case TlvCode.ISIS_AREA_IDENTIFIER:
331 final IsisAreaIdentifier ai = new IsisAreaIdentifier(ByteArray.readAllBytes(value));
332 areaMembership.add(ai);
333 LOG.debug("Parsed AreaIdentifier {}", ai);
335 case TlvCode.LOCAL_IPV4_ROUTER_ID:
336 final Ipv4RouterIdentifier ip4 = new Ipv4RouterIdentifier(Ipv4Util.addressForByteBuf(value));
337 builder.setIpv4RouterId(ip4);
338 LOG.debug("Parsed IPv4 Router Identifier {}", ip4);
340 case TlvCode.LOCAL_IPV6_ROUTER_ID:
341 final Ipv6RouterIdentifier ip6 = new Ipv6RouterIdentifier(Ipv6Util.addressForByteBuf(value));
342 builder.setIpv6RouterId(ip6);
343 LOG.debug("Parsed IPv6 Router Identifier {}", ip6);
346 LOG.warn("TLV {} is not a valid node attribute, ignoring it", key);
349 LOG.trace("Finished parsing Node Attributes.");
350 builder.setTopologyIdentifier(topologyMembership);
351 builder.setIsisAreaId(areaMembership);
352 return new NodeAttributesCaseBuilder().setNodeAttributes(builder.build()).build();
356 * Parse prefix attributes.
358 * @param attributes key is the tlv type and value are the value bytes of the tlv
359 * @return {@link LinkStateAttribute}
361 private static LinkStateAttribute parsePrefixAttributes(final Multimap<Integer, ByteBuf> attributes) {
362 final PrefixAttributesBuilder builder = new PrefixAttributesBuilder();
363 final List<RouteTag> routeTags = Lists.newArrayList();
364 final List<ExtendedRouteTag> exRouteTags = Lists.newArrayList();
365 for (final Entry<Integer, ByteBuf> entry : attributes.entries()) {
366 final int key = entry.getKey();
367 final ByteBuf value = entry.getValue();
368 LOG.trace("Prefix attribute TLV {}", key);
370 case TlvCode.IGP_FLAGS:
371 final BitSet flags = BitSet.valueOf(ByteArray.readAllBytes(value));
372 final boolean upDownBit = flags.get(UP_DOWN_BIT);
373 builder.setIgpBits(new IgpBitsBuilder().setUpDown(new UpDown(upDownBit)).build());
374 LOG.debug("Parsed IGP flag (up/down bit) : {}", upDownBit);
376 case TlvCode.ROUTE_TAG:
377 while (value.isReadable()) {
378 final RouteTag routeTag = new RouteTag(ByteArray.readBytes(value, ROUTE_TAG_LENGTH));
379 routeTags.add(routeTag);
380 LOG.debug("Parsed Route Tag: {}", routeTag);
383 case TlvCode.EXTENDED_ROUTE_TAG:
384 while (value.isReadable()) {
385 final ExtendedRouteTag exRouteTag = new ExtendedRouteTag(ByteArray.readBytes(value, EXTENDED_ROUTE_TAG_LENGTH));
386 exRouteTags.add(exRouteTag);
387 LOG.debug("Parsed Extended Route Tag: {}", exRouteTag);
390 case TlvCode.PREFIX_METRIC:
391 final IgpMetric metric = new IgpMetric(value.readUnsignedInt());
392 builder.setPrefixMetric(metric);
393 LOG.debug("Parsed Metric: {}", metric);
395 case TlvCode.FORWARDING_ADDRESS:
396 final IpAddress fwdAddress = parseForwardingAddress(value);
397 builder.setOspfForwardingAddress(fwdAddress);
398 LOG.debug("Parsed FWD Address: {}", fwdAddress);
400 case TlvCode.PREFIX_OPAQUE:
401 LOG.debug("Parsed Opaque value: {}, not preserving it", ByteBufUtil.hexDump(value));
404 LOG.warn("TLV {} is not a valid prefix attribute, ignoring it", key);
407 LOG.trace("Finished parsing Prefix Attributes.");
408 builder.setRouteTags(routeTags);
409 builder.setExtendedTags(exRouteTags);
410 return new PrefixAttributesCaseBuilder().setPrefixAttributes(builder.build()).build();
413 private static IpAddress parseForwardingAddress(final ByteBuf value) {
414 IpAddress fwdAddress = null;
415 switch (value.readableBytes()) {
416 case Ipv4Util.IP4_LENGTH:
417 fwdAddress = new IpAddress(Ipv4Util.addressForByteBuf(value));
419 case Ipv6Util.IPV6_LENGTH:
420 fwdAddress = new IpAddress(Ipv6Util.addressForByteBuf(value));
423 LOG.debug("Ignoring unsupported forwarding address length {}", value.readableBytes());
429 * Serialize linkstate attributes.
431 * @param attribute DataObject representing LinkstatePathAttribute
432 * @param byteAggregator ByteBuf where all serialized data are aggregated
436 public void serializeAttribute(final DataObject attribute, final ByteBuf byteAggregator) {
437 Preconditions.checkArgument(attribute instanceof PathAttributes, "Attribute parameter is not a PathAttribute object.");
438 final PathAttributes1 pathAttributes1 = ((PathAttributes) attribute).getAugmentation(PathAttributes1.class);
439 if (pathAttributes1 == null) {
442 final LinkStateAttribute linkState = pathAttributes1.getLinkstatePathAttribute().getLinkStateAttribute();
443 final ByteBuf lsBuffer = Unpooled.buffer();
444 if (linkState instanceof LinkAttributesCase) {
445 serializeLinkAttributes((LinkAttributesCase) linkState, lsBuffer);
446 } else if (linkState instanceof NodeAttributesCase) {
447 serializeNodeAttributes((NodeAttributesCase) linkState, lsBuffer);
448 } else if (linkState instanceof PrefixAttributesCase) {
449 serializePrefixAttributes((PrefixAttributesCase) linkState, lsBuffer);
451 AttributeUtil.formatAttribute(AttributeUtil.OPTIONAL, getType(), lsBuffer, byteAggregator);
454 private void serializeLinkAttributes(final LinkAttributesCase linkAttributesCase, final ByteBuf byteAggregator) {
455 final LinkAttributes linkAttributes = linkAttributesCase.getLinkAttributes();
456 LOG.trace("Started serializing Link Attributes");
457 if (linkAttributes.getLocalIpv4RouterId() != null) {
458 writeTLV(TlvCode.LOCAL_IPV4_ROUTER_ID, Unpooled.wrappedBuffer(InetAddresses.forString(linkAttributes.getLocalIpv4RouterId().getValue()).getAddress()), byteAggregator);
460 if (linkAttributes.getLocalIpv6RouterId() != null) {
461 writeTLV(TlvCode.LOCAL_IPV6_ROUTER_ID, Unpooled.wrappedBuffer(InetAddresses.forString(linkAttributes.getLocalIpv6RouterId().getValue()).getAddress()), byteAggregator);
463 if (linkAttributes.getRemoteIpv4RouterId() != null) {
464 writeTLV(TlvCode.REMOTE_IPV4_ROUTER_ID, Unpooled.wrappedBuffer(InetAddresses.forString(linkAttributes.getRemoteIpv4RouterId().getValue()).getAddress()), byteAggregator);
466 if (linkAttributes.getRemoteIpv6RouterId() != null) {
467 writeTLV(TlvCode.REMOTE_IPV6_ROUTER_ID, Unpooled.wrappedBuffer(InetAddresses.forString(linkAttributes.getRemoteIpv6RouterId().getValue()).getAddress()), byteAggregator);
469 if (linkAttributes.getAdminGroup() != null) {
470 writeTLV(TlvCode.ADMIN_GROUP, Unpooled.copyInt(linkAttributes.getAdminGroup().getValue().intValue()), byteAggregator);
472 if (linkAttributes.getMaxLinkBandwidth() != null) {
473 writeTLV(TlvCode.MAX_BANDWIDTH, Unpooled.wrappedBuffer(linkAttributes.getMaxLinkBandwidth().getValue()), byteAggregator);
475 if (linkAttributes.getMaxReservableBandwidth() != null) {
476 writeTLV(TlvCode.MAX_RESERVABLE_BANDWIDTH, Unpooled.wrappedBuffer(linkAttributes.getMaxReservableBandwidth().getValue()), byteAggregator);
478 // this sub-TLV contains eight 32-bit IEEE floating point numbers
479 final List<UnreservedBandwidth> ubList = linkAttributes.getUnreservedBandwidth();
480 if (ubList != null && !ubList.isEmpty()) {
481 final ByteBuf unreservedBandwithBuf = Unpooled.buffer();
482 for (final UnreservedBandwidth unreservedBandwidth : ubList) {
483 unreservedBandwithBuf.writeBytes(unreservedBandwidth.getBandwidth().getValue());
485 writeTLV(TlvCode.UNRESERVED_BANDWIDTH, unreservedBandwithBuf, byteAggregator);
487 if (linkAttributes.getTeMetric() != null) {
488 writeTLV(TlvCode.TE_METRIC, Unpooled.copyLong(linkAttributes.getTeMetric().getValue().longValue()), byteAggregator);
490 if (linkAttributes.getLinkProtection() != null) {
491 writeTLV(TlvCode.LINK_PROTECTION_TYPE, Unpooled.copyShort(linkAttributes.getLinkProtection().getIntValue()), byteAggregator);
493 serializeMplsProtocolMask(linkAttributes.getMplsProtocol(), byteAggregator);
494 if (linkAttributes.getMetric() != null) {
495 // size of metric can be 1,2 or 3 depending on the protocol
496 writeTLV(TlvCode.METRIC, Unpooled.copyMedium(linkAttributes.getMetric().getValue().intValue()), byteAggregator);
498 final List<SrlgId> srlgList = linkAttributes.getSharedRiskLinkGroups();
499 if (srlgList != null && !srlgList.isEmpty()) {
500 final ByteBuf sharedRLGBuf = Unpooled.buffer();
501 for (final SrlgId srlgId : srlgList) {
502 sharedRLGBuf.writeInt(srlgId.getValue().intValue());
504 writeTLV(TlvCode.SHARED_RISK_LINK_GROUP, sharedRLGBuf, byteAggregator);
506 if (linkAttributes.getLinkName() != null) {
507 writeTLV(TlvCode.LINK_NAME, Unpooled.wrappedBuffer(Charsets.UTF_8.encode(linkAttributes.getLinkName())), byteAggregator);
509 LOG.trace("Finished serializing Link Attributes");
512 private static void serializeMplsProtocolMask(final MplsProtocolMask mplsProtocolMask, final ByteBuf byteAggregator ) {
513 if (mplsProtocolMask != null) {
514 final ByteBuf mplsProtocolMaskBuf = Unpooled.buffer();
515 final BitSet mask = new BitSet();
516 if (mplsProtocolMask.isLdp() != null) {
517 mask.set(LDP_BIT, mplsProtocolMask.isLdp());
519 if (mplsProtocolMask.isRsvpte() != null) {
520 mask.set(RSVP_BIT, mplsProtocolMask.isRsvpte());
522 mplsProtocolMaskBuf.writeBytes(mask.toByteArray());
523 writeTLV(TlvCode.MPLS_PROTOCOL, mplsProtocolMaskBuf, byteAggregator);
527 private void serializeNodeAttributes(final NodeAttributesCase nodeAttributesCase, final ByteBuf byteAggregator) {
528 LOG.trace("Started serializing Node Attributes");
529 final NodeAttributes nodeAttributes = nodeAttributesCase.getNodeAttributes();
530 final List<TopologyIdentifier> topList = nodeAttributes.getTopologyIdentifier();
531 if (topList != null && !topList.isEmpty()) {
532 final ByteBuf mpIdBuf = Unpooled.buffer();
533 for (final TopologyIdentifier topologyIdentifier : topList) {
534 mpIdBuf.writeShort(topologyIdentifier.getValue());
536 writeTLV(TlvCode.MULTI_TOPOLOGY_ID, mpIdBuf, byteAggregator);
538 serializeNodeFlagBits(nodeAttributes.getNodeFlags(), byteAggregator);
539 if (nodeAttributes.getDynamicHostname() != null) {
540 writeTLV(TlvCode.DYNAMIC_HOSTNAME, Unpooled.wrappedBuffer(Charsets.UTF_8.encode(nodeAttributes.getDynamicHostname())), byteAggregator);
542 final List<IsisAreaIdentifier> isisList = nodeAttributes.getIsisAreaId();
543 if (isisList != null && !isisList.isEmpty()) {
544 for (final IsisAreaIdentifier isisAreaIdentifier : isisList) {
545 writeTLV(TlvCode.ISIS_AREA_IDENTIFIER, Unpooled.wrappedBuffer(isisAreaIdentifier.getValue()), byteAggregator);
548 if (nodeAttributes.getIpv4RouterId() != null) {
549 writeTLV(TlvCode.LOCAL_IPV4_ROUTER_ID, Unpooled.wrappedBuffer(InetAddresses.forString(nodeAttributes.getIpv4RouterId().getValue()).getAddress()), byteAggregator);
551 if (nodeAttributes.getIpv6RouterId() != null) {
552 writeTLV(TlvCode.LOCAL_IPV6_ROUTER_ID, Unpooled.wrappedBuffer(InetAddresses.forString(nodeAttributes.getIpv6RouterId().getValue()).getAddress()), byteAggregator);
554 LOG.trace("Finished serializing Node Attributes");
557 private static void serializeNodeFlagBits(final NodeFlagBits nodeFlagBits, final ByteBuf byteAggregator) {
558 if (nodeFlagBits != null) {
559 final ByteBuf nodeFlagBuf = Unpooled.buffer();
560 final BitSet flags = new BitSet();
561 if (nodeFlagBits.isOverload() != null) {
562 flags.set(OVERLOAD_BIT, nodeFlagBits.isOverload());
564 if (nodeFlagBits.isAttached() != null) {
565 flags.set(ATTACHED_BIT, nodeFlagBits.isAttached());
567 if (nodeFlagBits.isExternal() != null) {
568 flags.set(EXTERNAL_BIT, nodeFlagBits.isExternal());
570 if (nodeFlagBits.isAbr() != null) {
571 flags.set(ABBR_BIT, nodeFlagBits.isAbr());
573 nodeFlagBuf.writeBytes(flags.toByteArray());
574 writeTLV(TlvCode.NODE_FLAG_BITS, nodeFlagBuf, byteAggregator);
578 private void serializePrefixAttributes(final PrefixAttributesCase prefixAttributesCase, final ByteBuf byteAggregator) {
579 final PrefixAttributes prefixAtrributes = prefixAttributesCase.getPrefixAttributes();
580 if (prefixAtrributes.getIgpBits() != null) {
581 final BitSet igpBit = new BitSet();
582 final Boolean bit = prefixAtrributes.getIgpBits().getUpDown().isUpDown();
584 igpBit.set(UP_DOWN_BIT, bit);
586 writeTLV(TlvCode.IGP_FLAGS, Unpooled.wrappedBuffer(igpBit.toByteArray()), byteAggregator);
588 if (prefixAtrributes.getRouteTags() != null) {
589 final ByteBuf routeTagsBuf = Unpooled.buffer();
590 for (final RouteTag routeTag : prefixAtrributes.getRouteTags()) {
591 routeTagsBuf.writeBytes(routeTag.getValue());
593 writeTLV(TlvCode.ROUTE_TAG, routeTagsBuf, byteAggregator);
595 final List<ExtendedRouteTag> routeTagList = prefixAtrributes.getExtendedTags();
596 if (routeTagList != null && !routeTagList.isEmpty()) {
597 final ByteBuf extendedBuf = Unpooled.buffer();
598 for (final ExtendedRouteTag extendedRouteTag : routeTagList) {
599 extendedBuf.writeBytes(extendedRouteTag.getValue());
601 writeTLV(TlvCode.EXTENDED_ROUTE_TAG, extendedBuf, byteAggregator);
603 if (prefixAtrributes.getPrefixMetric() != null) {
604 writeTLV(TlvCode.PREFIX_METRIC, Unpooled.copyInt(prefixAtrributes.getPrefixMetric().getValue().intValue()), byteAggregator);
606 serializeForwardingAddress(prefixAtrributes.getOspfForwardingAddress(), byteAggregator);
609 private static void serializeForwardingAddress(final IpAddress forwardingAddress, final ByteBuf byteAggregator) {
610 if (forwardingAddress != null) {
611 final ByteBuf ospfBuf = Unpooled.buffer();
612 if (forwardingAddress.getIpv4Address() != null) {
613 ospfBuf.writeBytes(Ipv4Util.bytesForAddress(forwardingAddress.getIpv4Address()));
614 } else if (forwardingAddress.getIpv6Address() != null) {
615 ospfBuf.writeBytes(Ipv6Util.bytesForAddress(forwardingAddress.getIpv6Address()));
617 writeTLV(TlvCode.FORWARDING_ADDRESS, ospfBuf, byteAggregator);
622 * Util method for writing TLV header.
623 * @param type TLV type
624 * @param value TLV value
625 * @param byteAggregator final ByteBuf where the tlv should be serialized
627 protected static void writeTLV(final int type, final ByteBuf value, final ByteBuf byteAggregator){
628 byteAggregator.writeShort(type);
629 byteAggregator.writeShort(value.writerIndex());
630 byteAggregator.writeBytes(value);
631 value.readerIndex(0);
632 LOG.debug("Serialized tlv type {} to: {}", type, ByteBufUtil.hexDump(value));