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.impl.attribute;
10 import static org.opendaylight.protocol.bgp.linkstate.impl.attribute.sr.binding.sid.sub.tlvs.Ipv4PrefixSidParser.PREFIX_SID;
11 import static org.opendaylight.protocol.bgp.linkstate.impl.attribute.sr.binding.sid.sub.tlvs.Ipv6PrefixSidParser.IPV6_PREFIX_SID;
13 import com.google.common.annotations.VisibleForTesting;
14 import com.google.common.collect.Multimap;
15 import io.netty.buffer.ByteBuf;
16 import io.netty.buffer.ByteBufUtil;
17 import io.netty.buffer.Unpooled;
18 import java.util.ArrayList;
19 import java.util.List;
20 import java.util.Map.Entry;
21 import org.opendaylight.protocol.bgp.linkstate.impl.attribute.sr.BindingSidLabelParser;
22 import org.opendaylight.protocol.bgp.linkstate.impl.attribute.sr.Ipv6SrPrefixAttributesParser;
23 import org.opendaylight.protocol.bgp.linkstate.impl.attribute.sr.RangeTlvParser;
24 import org.opendaylight.protocol.bgp.linkstate.impl.attribute.sr.SrPrefixAttributesParser;
25 import org.opendaylight.protocol.bgp.linkstate.spi.TlvUtil;
26 import org.opendaylight.protocol.util.BitArray;
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.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.ExtendedRouteTag;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.IgpBits.UpDown;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.ProtocolId;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.RouteTag;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.path.attribute.LinkStateAttribute;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.path.attribute.link.state.attribute.PrefixAttributesCase;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.path.attribute.link.state.attribute.PrefixAttributesCaseBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.path.attribute.link.state.attribute.prefix.attributes._case.PrefixAttributes;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.path.attribute.link.state.attribute.prefix.attributes._case.PrefixAttributesBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.prefix.state.IgpBits;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.prefix.state.IgpBitsBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.prefix.state.Ipv6SrPrefix;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.prefix.state.SrBindingSidLabels;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.prefix.state.SrPrefix;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.prefix.state.SrRange;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.IgpMetric;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
51 public final class PrefixAttributesParser {
53 /* Segment routing TLV */
54 public static final int BINDING_SID = 1160;
55 private static final Logger LOG = LoggerFactory.getLogger(PrefixAttributesParser.class);
56 private static final int ROUTE_TAG_LENGTH = 4;
57 private static final int EXTENDED_ROUTE_TAG_LENGTH = 8;
58 private static final int FLAGS_SIZE = 8;
59 private static final int UP_DOWN_BIT = 0;
60 private static final int OSPF_NO_UNICAST = 1;
61 private static final int OSPF_LOCAL_ADDRESS = 2;
62 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;
70 private static final int RANGE = 1159;
72 private PrefixAttributesParser() {
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,
84 final ProtocolId protocolId) {
85 final PrefixAttributesBuilder builder = new PrefixAttributesBuilder();
86 final List<RouteTag> routeTags = new ArrayList<>();
87 final List<ExtendedRouteTag> exRouteTags = new ArrayList<>();
88 for (final Entry<Integer, ByteBuf> entry : attributes.entries()) {
89 final int key = entry.getKey();
90 final ByteBuf value = entry.getValue();
91 LOG.trace("Prefix attribute TLV {}", key);
92 parseAttribute(key, value, protocolId, builder, routeTags, exRouteTags);
94 LOG.trace("Finished parsing Prefix Attributes.");
95 builder.setRouteTags(routeTags);
96 builder.setExtendedTags(exRouteTags);
97 return new PrefixAttributesCaseBuilder().setPrefixAttributes(builder.build()).build();
100 private static void parseAttribute(final int key, final ByteBuf value, final ProtocolId protocolId,
101 final PrefixAttributesBuilder builder, final List<RouteTag> routeTags,
102 final List<ExtendedRouteTag> exRouteTags) {
105 parseIgpFags(builder, value);
108 parseRouteTags(routeTags, value);
110 case EXTENDED_ROUTE_TAG:
111 parseExtendedRouteTags(exRouteTags, value);
114 final IgpMetric metric = new IgpMetric(value.readUnsignedInt());
115 builder.setPrefixMetric(metric);
116 LOG.debug("Parsed Metric: {}", metric);
118 case FORWARDING_ADDRESS:
119 final IpAddress fwdAddress = parseForwardingAddress(value);
120 builder.setOspfForwardingAddress(fwdAddress);
121 LOG.debug("Parsed FWD Address: {}", fwdAddress);
124 if (LOG.isDebugEnabled()) {
125 LOG.debug("Parsed Opaque value: {}, not preserving it", ByteBufUtil.hexDump(value));
129 final SrPrefix prefix = SrPrefixAttributesParser.parseSrPrefix(value, protocolId);
130 builder.setSrPrefix(prefix);
131 LOG.debug("Parsed SR Prefix: {}", prefix);
133 case IPV6_PREFIX_SID:
134 final Ipv6SrPrefix ipv6Prefix = Ipv6SrPrefixAttributesParser.parseSrIpv6Prefix(value);
135 builder.setIpv6SrPrefix(ipv6Prefix);
136 LOG.debug("Parsed Ipv6 SR Prefix: {}", ipv6Prefix);
139 final SrRange range = RangeTlvParser.parseSrRange(value, protocolId);
140 builder.setSrRange(range);
141 LOG.debug("Parsed SR Range: {}", range);
144 parseBindingSid(builder, value, protocolId);
147 LOG.warn("TLV {} is not a valid prefix attribute, ignoring it", key);
151 private static void parseIgpFags(final PrefixAttributesBuilder builder, final ByteBuf value) {
152 final BitArray flags = BitArray.valueOf(value, FLAGS_SIZE);
153 final boolean upDownBit = flags.get(UP_DOWN_BIT);
154 builder.setIgpBits(new IgpBitsBuilder().setUpDown(new UpDown(upDownBit)).setIsIsUpDown(upDownBit)
155 .setOspfNoUnicast(flags.get(OSPF_NO_UNICAST))
156 .setOspfLocalAddress(flags.get(OSPF_LOCAL_ADDRESS))
157 .setOspfPropagateNssa(flags.get(OSPF_PROPAGATE_ADDRESS)).build());
158 LOG.debug("Parsed IGP flag (up/down bit) : {}", upDownBit);
161 private static void parseBindingSid(final PrefixAttributesBuilder builder, final ByteBuf value,
162 final ProtocolId protocolId) {
163 final List<SrBindingSidLabels> labels;
164 if (builder.getSrBindingSidLabels() != null) {
165 labels = builder.getSrBindingSidLabels();
167 labels = new ArrayList<>();
168 builder.setSrBindingSidLabels(labels);
170 final SrBindingSidLabels label = BindingSidLabelParser.parseBindingSidLabel(value, protocolId);
172 LOG.debug("Parsed SR Binding SID {}", label);
175 private static void parseRouteTags(final List<RouteTag> routeTags, final ByteBuf value) {
176 while (value.isReadable()) {
177 final RouteTag routeTag = new RouteTag(ByteArray.readBytes(value, ROUTE_TAG_LENGTH));
178 routeTags.add(routeTag);
179 LOG.debug("Parsed Route Tag: {}", routeTag);
183 private static void parseExtendedRouteTags(final List<ExtendedRouteTag> exRouteTags, final ByteBuf value) {
184 while (value.isReadable()) {
185 final ExtendedRouteTag exRouteTag = new ExtendedRouteTag(ByteArray.readBytes(value,
186 EXTENDED_ROUTE_TAG_LENGTH));
187 exRouteTags.add(exRouteTag);
188 LOG.debug("Parsed Extended Route Tag: {}", exRouteTag);
192 private static IpAddress parseForwardingAddress(final ByteBuf value) {
193 switch (value.readableBytes()) {
194 case Ipv4Util.IP4_LENGTH:
195 return new IpAddress(Ipv4Util.addressForByteBuf(value));
196 case Ipv6Util.IPV6_LENGTH:
197 return new IpAddress(Ipv6Util.addressForByteBuf(value));
199 LOG.debug("Ignoring unsupported forwarding address length {}", value.readableBytes());
204 static void serializePrefixAttributes(final PrefixAttributesCase prefixAttributesCase,
205 final ByteBuf byteAggregator) {
206 final PrefixAttributes prefixAtrributes = prefixAttributesCase.getPrefixAttributes();
207 if (prefixAtrributes.getIgpBits() != null) {
208 final BitArray igpBit = new BitArray(FLAGS_SIZE);
209 final IgpBits igpBits = prefixAtrributes.getIgpBits();
210 igpBit.set(UP_DOWN_BIT, igpBits.getUpDown().isUpDown() || igpBits.isIsIsUpDown());
211 igpBit.set(OSPF_NO_UNICAST, igpBits.isOspfNoUnicast());
212 igpBit.set(OSPF_LOCAL_ADDRESS, igpBits.isOspfLocalAddress());
213 igpBit.set(OSPF_PROPAGATE_ADDRESS, igpBits.isOspfPropagateNssa());
214 TlvUtil.writeTLV(IGP_FLAGS, Unpooled.wrappedBuffer(igpBit.array()), byteAggregator);
216 serializeRouteTags(prefixAtrributes.getRouteTags(), byteAggregator);
217 serializeExtendedRouteTags(prefixAtrributes.getExtendedTags(), byteAggregator);
218 serializePrefixMetric(prefixAtrributes.getPrefixMetric(), byteAggregator);
219 serializeForwardingAddress(prefixAtrributes.getOspfForwardingAddress(), byteAggregator);
220 serializeSrPrefix(prefixAtrributes.getSrPrefix(), byteAggregator);
221 serializeIpv6SrPrefix(prefixAtrributes.getIpv6SrPrefix(), byteAggregator);
222 serializeSrRange(prefixAtrributes.getSrRange(), byteAggregator);
223 serializeSrBindingLabel(prefixAtrributes.getSrBindingSidLabels(), byteAggregator);
226 private static void serializeSrBindingLabel(final List<SrBindingSidLabels> srBindingSidLabels,
227 final ByteBuf byteAggregator) {
228 if (srBindingSidLabels != null) {
229 for (final SrBindingSidLabels bindingSid : srBindingSidLabels) {
230 final ByteBuf sidBuffer = Unpooled.buffer();
231 BindingSidLabelParser.serializeBindingSidAttributes(bindingSid.getWeight(), bindingSid.getFlags(),
232 bindingSid.getBindingSubTlvs(), sidBuffer);
233 TlvUtil.writeTLV(PrefixAttributesParser.BINDING_SID, sidBuffer, byteAggregator);
238 private static void serializeSrRange(final SrRange srRange, final ByteBuf byteAggregator) {
239 if (srRange != null) {
240 final ByteBuf sidBuffer = Unpooled.buffer();
241 RangeTlvParser.serializeSrRange(srRange, sidBuffer);
242 TlvUtil.writeTLV(RANGE, sidBuffer, byteAggregator);
246 private static void serializeIpv6SrPrefix(final Ipv6SrPrefix ipv6SrPrefix, final ByteBuf byteAggregator) {
247 if (ipv6SrPrefix != null) {
248 final ByteBuf buffer = Unpooled.buffer();
249 Ipv6SrPrefixAttributesParser.serializeIpv6SrPrefix(ipv6SrPrefix, buffer);
250 TlvUtil.writeTLV(IPV6_PREFIX_SID, buffer, byteAggregator);
254 private static void serializeSrPrefix(final SrPrefix srPrefix, final ByteBuf byteAggregator) {
255 if (srPrefix != null) {
256 final ByteBuf buffer = Unpooled.buffer();
257 SrPrefixAttributesParser.serializeSrPrefix(srPrefix, buffer);
258 TlvUtil.writeTLV(PREFIX_SID, buffer, byteAggregator);
262 private static void serializePrefixMetric(final IgpMetric prefixMetric, final ByteBuf byteAggregator) {
263 if (prefixMetric != null) {
264 TlvUtil.writeTLV(PREFIX_METRIC, Unpooled.copyInt(prefixMetric.getValue().intValue()), byteAggregator);
268 private static void serializeRouteTags(final List<RouteTag> routeTags, final ByteBuf byteAggregator) {
269 if (routeTags != null) {
270 final ByteBuf routeTagsBuf = Unpooled.buffer();
271 for (final RouteTag routeTag : routeTags) {
272 routeTagsBuf.writeBytes(routeTag.getValue());
274 TlvUtil.writeTLV(ROUTE_TAG, routeTagsBuf, byteAggregator);
278 private static void serializeExtendedRouteTags(final List<ExtendedRouteTag> exRouteTags,
279 final ByteBuf byteAggregator) {
280 if (exRouteTags != null) {
281 final ByteBuf extendedBuf = Unpooled.buffer();
282 for (final ExtendedRouteTag exRouteTag : exRouteTags) {
283 extendedBuf.writeBytes(exRouteTag.getValue());
285 TlvUtil.writeTLV(EXTENDED_ROUTE_TAG, extendedBuf, byteAggregator);
289 private static void serializeForwardingAddress(final IpAddress forwardingAddress, final ByteBuf byteAggregator) {
290 if (forwardingAddress != null) {
291 final ByteBuf ospfBuf = Unpooled.buffer();
292 if (forwardingAddress.getIpv4Address() != null) {
293 ospfBuf.writeBytes(Ipv4Util.bytesForAddress(forwardingAddress.getIpv4Address()));
294 } else if (forwardingAddress.getIpv6Address() != null) {
295 ospfBuf.writeBytes(Ipv6Util.bytesForAddress(forwardingAddress.getIpv6Address()));
297 TlvUtil.writeTLV(FORWARDING_ADDRESS, ospfBuf, byteAggregator);