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.annotations.VisibleForTesting;
11 import com.google.common.collect.Multimap;
12 import io.netty.buffer.ByteBuf;
13 import io.netty.buffer.ByteBufUtil;
14 import io.netty.buffer.Unpooled;
15 import java.util.ArrayList;
16 import java.util.List;
17 import java.util.Map.Entry;
18 import org.opendaylight.protocol.bgp.linkstate.attribute.sr.BindingSidLabelParser;
19 import org.opendaylight.protocol.bgp.linkstate.attribute.sr.RangeTlvParser;
20 import org.opendaylight.protocol.bgp.linkstate.attribute.sr.SrPrefixAttributesParser;
21 import org.opendaylight.protocol.bgp.linkstate.spi.TlvUtil;
22 import org.opendaylight.protocol.util.BitArray;
23 import org.opendaylight.protocol.util.ByteArray;
24 import org.opendaylight.protocol.util.Ipv4Util;
25 import org.opendaylight.protocol.util.Ipv6Util;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.ExtendedRouteTag;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.IgpBits.UpDown;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.ProtocolId;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.RouteTag;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.path.attribute.LinkStateAttribute;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.path.attribute.link.state.attribute.PrefixAttributesCase;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.path.attribute.link.state.attribute.PrefixAttributesCaseBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.path.attribute.link.state.attribute.prefix.attributes._case.PrefixAttributes;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.path.attribute.link.state.attribute.prefix.attributes._case.PrefixAttributesBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.prefix.state.IgpBits;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.prefix.state.IgpBitsBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.prefix.state.SrBindingSidLabels;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.prefix.state.SrPrefix;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.prefix.state.SrRange;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.IgpMetric;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
46 public final class PrefixAttributesParser {
48 private static final Logger LOG = LoggerFactory.getLogger(PrefixAttributesParser.class);
50 private PrefixAttributesParser() {
51 throw new UnsupportedOperationException();
54 private static final int ROUTE_TAG_LENGTH = 4;
55 private static final int EXTENDED_ROUTE_TAG_LENGTH = 8;
57 private static final int FLAGS_SIZE = 8;
58 private static final int UP_DOWN_BIT = 0;
59 private static final int OSPF_NO_UNICAST = 1;
60 private static final int OSPF_LOCAL_ADDRESS = 2;
61 private static final int OSPF_PROPAGATE_ADDRESS = 3;
63 /* Prefix Attribute TLVs */
64 private static final int IGP_FLAGS = 1152;
65 private static final int ROUTE_TAG = 1153;
66 private static final int EXTENDED_ROUTE_TAG = 1154;
67 private static final int PREFIX_METRIC = 1155;
68 private static final int FORWARDING_ADDRESS = 1156;
69 private static final int PREFIX_OPAQUE = 1157;
71 /* Segment routing TLV */
72 public static final int PREFIX_SID = 1158;
73 public static final int RANGE = 1159;
74 public static final int BINDING_SID = 1160;
77 * Parse prefix attributes.
79 * @param attributes key is the tlv type and value are the value bytes of the tlv
80 * @param protocolId to differentiate parsing methods
81 * @return {@link LinkStateAttribute}
83 static LinkStateAttribute parsePrefixAttributes(final Multimap<Integer, ByteBuf> attributes, final ProtocolId protocolId) {
84 final PrefixAttributesBuilder builder = new PrefixAttributesBuilder();
85 final List<RouteTag> routeTags = new ArrayList<>();
86 final List<ExtendedRouteTag> exRouteTags = new ArrayList<>();
87 for (final Entry<Integer, ByteBuf> entry : attributes.entries()) {
88 final int key = entry.getKey();
89 final ByteBuf value = entry.getValue();
90 LOG.trace("Prefix attribute TLV {}", key);
91 parseAttribute(key, value, protocolId, builder, routeTags, exRouteTags);
93 LOG.trace("Finished parsing Prefix Attributes.");
94 builder.setRouteTags(routeTags);
95 builder.setExtendedTags(exRouteTags);
96 return new PrefixAttributesCaseBuilder().setPrefixAttributes(builder.build()).build();
99 private static void parseAttribute(final int key, final ByteBuf value, final ProtocolId protocolId, final PrefixAttributesBuilder builder, final List<RouteTag> routeTags, final List<ExtendedRouteTag> exRouteTags) {
102 final BitArray flags = BitArray.valueOf(value, FLAGS_SIZE);
103 final boolean upDownBit = flags.get(UP_DOWN_BIT);
104 final boolean ospfNoUnicast = flags.get(OSPF_NO_UNICAST);
105 final boolean ospfLocalAddress = flags.get(OSPF_LOCAL_ADDRESS);
106 final boolean ospfPropagateAddress = flags.get(OSPF_PROPAGATE_ADDRESS);
107 builder.setIgpBits(new IgpBitsBuilder().setUpDown(new UpDown(upDownBit))
108 .setIsIsUpDown(upDownBit)
109 .setOspfNoUnicast(ospfNoUnicast)
110 .setOspfLocalAddress(ospfLocalAddress)
111 .setOspfPropagateNssa(ospfPropagateAddress)
113 LOG.debug("Parsed IGP flag (up/down bit) : {}", upDownBit);
116 parseRouteTags(routeTags, value);
118 case EXTENDED_ROUTE_TAG:
119 parseExtendedRouteTags(exRouteTags, value);
122 final IgpMetric metric = new IgpMetric(value.readUnsignedInt());
123 builder.setPrefixMetric(metric);
124 LOG.debug("Parsed Metric: {}", metric);
126 case FORWARDING_ADDRESS:
127 final IpAddress fwdAddress = parseForwardingAddress(value);
128 builder.setOspfForwardingAddress(fwdAddress);
129 LOG.debug("Parsed FWD Address: {}", fwdAddress);
132 if (LOG.isDebugEnabled()) {
133 LOG.debug("Parsed Opaque value: {}, not preserving it", ByteBufUtil.hexDump(value));
137 final SrPrefix prefix = SrPrefixAttributesParser.parseSrPrefix(value, protocolId);
138 builder.setSrPrefix(prefix);
139 LOG.debug("Parsed SR Prefix: {}", prefix);
142 final SrRange range = RangeTlvParser.parseSrRange(value, protocolId);
143 builder.setSrRange(range);
144 LOG.debug("Parsed SR Range: {}", range);
147 final SrBindingSidLabels label = BindingSidLabelParser.parseBindingSidLabel(value, protocolId);
148 if (builder.getSrBindingSidLabels() != null) {
149 builder.getSrBindingSidLabels().add(label);
151 final List<SrBindingSidLabels> labels = new ArrayList<SrBindingSidLabels>();
153 builder.setSrBindingSidLabels(labels);
155 LOG.debug("Parsed SR Binding SID {}", label);
158 LOG.warn("TLV {} is not a valid prefix attribute, ignoring it", key);
162 private static void parseRouteTags(final List<RouteTag> routeTags, final ByteBuf value) {
163 while (value.isReadable()) {
164 final RouteTag routeTag = new RouteTag(ByteArray.readBytes(value, ROUTE_TAG_LENGTH));
165 routeTags.add(routeTag);
166 LOG.debug("Parsed Route Tag: {}", routeTag);
170 private static void parseExtendedRouteTags(final List<ExtendedRouteTag> exRouteTags, final ByteBuf value) {
171 while (value.isReadable()) {
172 final ExtendedRouteTag exRouteTag = new ExtendedRouteTag(ByteArray.readBytes(value, EXTENDED_ROUTE_TAG_LENGTH));
173 exRouteTags.add(exRouteTag);
174 LOG.debug("Parsed Extended Route Tag: {}", exRouteTag);
178 private static IpAddress parseForwardingAddress(final ByteBuf value) {
179 IpAddress fwdAddress = null;
180 switch (value.readableBytes()) {
181 case Ipv4Util.IP4_LENGTH:
182 fwdAddress = new IpAddress(Ipv4Util.addressForByteBuf(value));
184 case Ipv6Util.IPV6_LENGTH:
185 fwdAddress = new IpAddress(Ipv6Util.addressForByteBuf(value));
188 LOG.debug("Ignoring unsupported forwarding address length {}", value.readableBytes());
193 static void serializePrefixAttributes(final PrefixAttributesCase prefixAttributesCase, final ByteBuf byteAggregator) {
194 final PrefixAttributes prefixAtrributes = prefixAttributesCase.getPrefixAttributes();
195 if (prefixAtrributes.getIgpBits() != null) {
196 final BitArray igpBit = new BitArray(FLAGS_SIZE);
197 final IgpBits igpBits = prefixAtrributes.getIgpBits();
198 igpBit.set(UP_DOWN_BIT, igpBits.getUpDown().isUpDown() || igpBits.isIsIsUpDown());
199 igpBit.set(OSPF_NO_UNICAST, igpBits.isOspfNoUnicast());
200 igpBit.set(OSPF_LOCAL_ADDRESS, igpBits.isOspfLocalAddress());
201 igpBit.set(OSPF_PROPAGATE_ADDRESS, igpBits.isOspfPropagateNssa());
202 TlvUtil.writeTLV(IGP_FLAGS, Unpooled.wrappedBuffer(igpBit.array()), byteAggregator);
204 serializeRouteTags(prefixAtrributes.getRouteTags(), byteAggregator);
205 serializeExtendedRouteTags(prefixAtrributes.getExtendedTags(), byteAggregator);
206 if (prefixAtrributes.getPrefixMetric() != null) {
207 TlvUtil.writeTLV(PREFIX_METRIC, Unpooled.copyInt(prefixAtrributes.getPrefixMetric().getValue().intValue()), byteAggregator);
209 serializeForwardingAddress(prefixAtrributes.getOspfForwardingAddress(), byteAggregator);
210 if (prefixAtrributes.getSrPrefix() != null) {
211 final ByteBuf buffer = Unpooled.buffer();
212 SrPrefixAttributesParser.serializeSrPrefix(prefixAtrributes.getSrPrefix(), buffer);
213 TlvUtil.writeTLV(PREFIX_SID, buffer, byteAggregator);
215 if (prefixAtrributes.getSrRange() != null) {
216 final ByteBuf sidBuffer = Unpooled.buffer();
217 RangeTlvParser.serializeSrRange(prefixAtrributes.getSrRange(), sidBuffer);
218 TlvUtil.writeTLV(RANGE, sidBuffer, byteAggregator);
220 if (prefixAtrributes.getSrBindingSidLabels() != null) {
221 BindingSidLabelParser.serializeBindingSidLabels(prefixAtrributes.getSrBindingSidLabels(), byteAggregator, BINDING_SID);
225 private static void serializeRouteTags(final List<RouteTag> routeTags, final ByteBuf byteAggregator) {
226 if (routeTags != null) {
227 final ByteBuf routeTagsBuf = Unpooled.buffer();
228 for (final RouteTag routeTag : routeTags) {
229 routeTagsBuf.writeBytes(routeTag.getValue());
231 TlvUtil.writeTLV(ROUTE_TAG, routeTagsBuf, byteAggregator);
235 private static void serializeExtendedRouteTags(final List<ExtendedRouteTag> exRouteTags, final ByteBuf byteAggregator) {
236 if (exRouteTags != null) {
237 final ByteBuf extendedBuf = Unpooled.buffer();
238 for (final ExtendedRouteTag exRouteTag : exRouteTags) {
239 extendedBuf.writeBytes(exRouteTag.getValue());
241 TlvUtil.writeTLV(EXTENDED_ROUTE_TAG, extendedBuf, byteAggregator);
245 private static void serializeForwardingAddress(final IpAddress forwardingAddress, final ByteBuf byteAggregator) {
246 if (forwardingAddress != null) {
247 final ByteBuf ospfBuf = Unpooled.buffer();
248 if (forwardingAddress.getIpv4Address() != null) {
249 ospfBuf.writeBytes(Ipv4Util.bytesForAddress(forwardingAddress.getIpv4Address()));
250 } else if (forwardingAddress.getIpv6Address() != null) {
251 ospfBuf.writeBytes(Ipv6Util.bytesForAddress(forwardingAddress.getIpv6Address()));
253 TlvUtil.writeTLV(FORWARDING_ADDRESS, ospfBuf, byteAggregator);