2 * Copyright (c) 2014 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.attribute;
10 import com.google.common.collect.Multimap;
11 import io.netty.buffer.ByteBuf;
12 import io.netty.buffer.ByteBufUtil;
13 import io.netty.buffer.Unpooled;
14 import java.util.ArrayList;
15 import java.util.BitSet;
16 import java.util.List;
17 import java.util.Map.Entry;
18 import org.opendaylight.protocol.bgp.linkstate.attribute.sr.SrPrefixAttributesParser;
19 import org.opendaylight.protocol.bgp.linkstate.spi.TlvUtil;
20 import org.opendaylight.protocol.util.ByteArray;
21 import org.opendaylight.protocol.util.Ipv4Util;
22 import org.opendaylight.protocol.util.Ipv6Util;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.ExtendedRouteTag;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.IgpBits.UpDown;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.RouteTag;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.prefix.state.IgpBitsBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.prefix.state.SrPrefix;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.path.attributes.linkstate.path.attribute.LinkStateAttribute;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.path.attributes.linkstate.path.attribute.link.state.attribute.PrefixAttributesCase;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.path.attributes.linkstate.path.attribute.link.state.attribute.PrefixAttributesCaseBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.path.attributes.linkstate.path.attribute.link.state.attribute.prefix.attributes._case.PrefixAttributes;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.path.attributes.linkstate.path.attribute.link.state.attribute.prefix.attributes._case.PrefixAttributesBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.IgpMetric;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
38 final class PrefixAttributesParser {
40 private static final Logger LOG = LoggerFactory.getLogger(PrefixAttributesParser.class);
42 private static final int ROUTE_TAG_LENGTH = 4;
43 private static final int EXTENDED_ROUTE_TAG_LENGTH = 8;
44 private static final int UP_DOWN_BIT = 7;
46 /* Prefix Attribute TLVs */
47 private static final int IGP_FLAGS = 1152;
48 private static final int ROUTE_TAG = 1153;
49 private static final int EXTENDED_ROUTE_TAG = 1154;
50 private static final int PREFIX_METRIC = 1155;
51 private static final int FORWARDING_ADDRESS = 1156;
52 private static final int PREFIX_OPAQUE = 1157;
54 /* Segment routing TLV */
55 private static final int PREFIX_SID = 1158;
58 * Parse prefix attributes.
60 * @param attributes key is the tlv type and value are the value bytes of the tlv
61 * @return {@link LinkStateAttribute}
63 static LinkStateAttribute parsePrefixAttributes(final Multimap<Integer, ByteBuf> attributes) {
64 final PrefixAttributesBuilder builder = new PrefixAttributesBuilder();
65 final List<RouteTag> routeTags = new ArrayList<>();
66 final List<ExtendedRouteTag> exRouteTags = new ArrayList<>();
67 for (final Entry<Integer, ByteBuf> entry : attributes.entries()) {
68 final int key = entry.getKey();
69 final ByteBuf value = entry.getValue();
70 LOG.trace("Prefix attribute TLV {}", key);
73 final BitSet flags = BitSet.valueOf(ByteArray.readAllBytes(value));
74 final boolean upDownBit = flags.get(UP_DOWN_BIT);
75 builder.setIgpBits(new IgpBitsBuilder().setUpDown(new UpDown(upDownBit)).build());
76 LOG.debug("Parsed IGP flag (up/down bit) : {}", upDownBit);
79 while (value.isReadable()) {
80 final RouteTag routeTag = new RouteTag(ByteArray.readBytes(value, ROUTE_TAG_LENGTH));
81 routeTags.add(routeTag);
82 LOG.debug("Parsed Route Tag: {}", routeTag);
85 case EXTENDED_ROUTE_TAG:
86 while (value.isReadable()) {
87 final ExtendedRouteTag exRouteTag = new ExtendedRouteTag(ByteArray.readBytes(value, EXTENDED_ROUTE_TAG_LENGTH));
88 exRouteTags.add(exRouteTag);
89 LOG.debug("Parsed Extended Route Tag: {}", exRouteTag);
93 final IgpMetric metric = new IgpMetric(value.readUnsignedInt());
94 builder.setPrefixMetric(metric);
95 LOG.debug("Parsed Metric: {}", metric);
97 case FORWARDING_ADDRESS:
98 final IpAddress fwdAddress = parseForwardingAddress(value);
99 builder.setOspfForwardingAddress(fwdAddress);
100 LOG.debug("Parsed FWD Address: {}", fwdAddress);
103 LOG.debug("Parsed Opaque value: {}, not preserving it", ByteBufUtil.hexDump(value));
106 final SrPrefix prefix = SrPrefixAttributesParser.parseSrPrefix(value);
107 builder.setSrPrefix(prefix);
108 LOG.debug("Parsed SR Prefix: {}", prefix);
111 LOG.warn("TLV {} is not a valid prefix attribute, ignoring it", key);
114 LOG.trace("Finished parsing Prefix Attributes.");
115 builder.setRouteTags(routeTags);
116 builder.setExtendedTags(exRouteTags);
117 return new PrefixAttributesCaseBuilder().setPrefixAttributes(builder.build()).build();
120 private static IpAddress parseForwardingAddress(final ByteBuf value) {
121 IpAddress fwdAddress = null;
122 switch (value.readableBytes()) {
123 case Ipv4Util.IP4_LENGTH:
124 fwdAddress = new IpAddress(Ipv4Util.addressForByteBuf(value));
126 case Ipv6Util.IPV6_LENGTH:
127 fwdAddress = new IpAddress(Ipv6Util.addressForByteBuf(value));
130 LOG.debug("Ignoring unsupported forwarding address length {}", value.readableBytes());
135 static void serializePrefixAttributes(final PrefixAttributesCase prefixAttributesCase, final ByteBuf byteAggregator) {
136 final PrefixAttributes prefixAtrributes = prefixAttributesCase.getPrefixAttributes();
137 if (prefixAtrributes.getIgpBits() != null) {
138 final BitSet igpBit = new BitSet();
139 final Boolean bit = prefixAtrributes.getIgpBits().getUpDown().isUpDown();
141 igpBit.set(UP_DOWN_BIT, bit);
143 TlvUtil.writeTLV(IGP_FLAGS, Unpooled.wrappedBuffer(igpBit.toByteArray()), byteAggregator);
145 if (prefixAtrributes.getRouteTags() != null) {
146 final ByteBuf routeTagsBuf = Unpooled.buffer();
147 for (final RouteTag routeTag : prefixAtrributes.getRouteTags()) {
148 routeTagsBuf.writeBytes(routeTag.getValue());
150 TlvUtil.writeTLV(ROUTE_TAG, routeTagsBuf, byteAggregator);
152 final List<ExtendedRouteTag> routeTagList = prefixAtrributes.getExtendedTags();
153 if (routeTagList != null) {
154 final ByteBuf extendedBuf = Unpooled.buffer();
155 for (final ExtendedRouteTag extendedRouteTag : routeTagList) {
156 extendedBuf.writeBytes(extendedRouteTag.getValue());
158 TlvUtil.writeTLV(EXTENDED_ROUTE_TAG, extendedBuf, byteAggregator);
160 serializeForwardingAddress(prefixAtrributes.getOspfForwardingAddress(), byteAggregator);
161 if (prefixAtrributes.getPrefixMetric() != null) {
162 TlvUtil.writeTLV(PREFIX_METRIC, Unpooled.copyInt(prefixAtrributes.getPrefixMetric().getValue().intValue()), byteAggregator);
164 if (prefixAtrributes.getSrPrefix() != null) {
165 final ByteBuf b = Unpooled.buffer();
166 SrPrefixAttributesParser.serializeSrPrefix(prefixAtrributes.getSrPrefix(), b);
167 TlvUtil.writeTLV(PREFIX_SID, b, byteAggregator);
172 private static void serializeForwardingAddress(final IpAddress forwardingAddress, final ByteBuf byteAggregator) {
173 if (forwardingAddress != null) {
174 final ByteBuf ospfBuf = Unpooled.buffer();
175 if (forwardingAddress.getIpv4Address() != null) {
176 ospfBuf.writeBytes(Ipv4Util.bytesForAddress(forwardingAddress.getIpv4Address()));
177 } else if (forwardingAddress.getIpv6Address() != null) {
178 ospfBuf.writeBytes(Ipv6Util.bytesForAddress(forwardingAddress.getIpv6Address()));
180 TlvUtil.writeTLV(FORWARDING_ADDRESS, ospfBuf, byteAggregator);