d9bcbd61388fb9e8bf14b3234efd5321812ac00e
[bgpcep.git] / bgp / linkstate / src / main / java / org / opendaylight / protocol / bgp / linkstate / attribute / PrefixAttributesParser.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.protocol.bgp.linkstate.attribute;
9
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.RouteTag;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.path.attribute.LinkStateAttribute;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.path.attribute.link.state.attribute.PrefixAttributesCase;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.path.attribute.link.state.attribute.PrefixAttributesCaseBuilder;
33 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;
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.PrefixAttributesBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.prefix.state.IgpBitsBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.prefix.state.SrBindingSidLabel;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.prefix.state.SrPrefix;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.prefix.state.SrRange;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.IgpMetric;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43 @VisibleForTesting
44 public final class PrefixAttributesParser {
45
46     private static final Logger LOG = LoggerFactory.getLogger(PrefixAttributesParser.class);
47
48     private PrefixAttributesParser() {
49         throw new UnsupportedOperationException();
50     }
51
52     private static final int ROUTE_TAG_LENGTH = 4;
53     private static final int EXTENDED_ROUTE_TAG_LENGTH = 8;
54
55     private static final int FLAGS_SIZE = 8;
56     private static final int UP_DOWN_BIT = 0;
57
58     /* Prefix Attribute TLVs */
59     private static final int IGP_FLAGS = 1152;
60     private static final int ROUTE_TAG = 1153;
61     private static final int EXTENDED_ROUTE_TAG = 1154;
62     private static final int PREFIX_METRIC = 1155;
63     private static final int FORWARDING_ADDRESS = 1156;
64     private static final int PREFIX_OPAQUE = 1157;
65
66     /* Segment routing TLV */
67     public static final int PREFIX_SID = 1158;
68     public static final int RANGE = 1159;
69     public static final int BINDING_SID = 1160;
70
71     /**
72      * Parse prefix attributes.
73      *
74      * @param attributes key is the tlv type and value are the value bytes of the tlv
75      * @return {@link LinkStateAttribute}
76      */
77     static LinkStateAttribute parsePrefixAttributes(final Multimap<Integer, ByteBuf> attributes) {
78         final PrefixAttributesBuilder builder = new PrefixAttributesBuilder();
79         final List<RouteTag> routeTags = new ArrayList<>();
80         final List<ExtendedRouteTag> exRouteTags = new ArrayList<>();
81         for (final Entry<Integer, ByteBuf> entry : attributes.entries()) {
82             final int key = entry.getKey();
83             final ByteBuf value = entry.getValue();
84             LOG.trace("Prefix attribute TLV {}", key);
85             parseAttribute(key, value, builder, routeTags, exRouteTags);
86         }
87         LOG.trace("Finished parsing Prefix Attributes.");
88         builder.setRouteTags(routeTags);
89         builder.setExtendedTags(exRouteTags);
90         return new PrefixAttributesCaseBuilder().setPrefixAttributes(builder.build()).build();
91     }
92
93     private static void parseAttribute(final int key, final ByteBuf value, final PrefixAttributesBuilder builder, final List<RouteTag> routeTags, final List<ExtendedRouteTag> exRouteTags) {
94         switch (key) {
95         case IGP_FLAGS:
96             final BitArray flags = BitArray.valueOf(value, FLAGS_SIZE);
97             final boolean upDownBit = flags.get(UP_DOWN_BIT);
98             builder.setIgpBits(new IgpBitsBuilder().setUpDown(new UpDown(upDownBit)).build());
99             LOG.debug("Parsed IGP flag (up/down bit) : {}", upDownBit);
100             break;
101         case ROUTE_TAG:
102             parseRouteTags(routeTags, value);
103             break;
104         case EXTENDED_ROUTE_TAG:
105             parseExtendedRouteTags(exRouteTags, value);
106             break;
107         case PREFIX_METRIC:
108             final IgpMetric metric = new IgpMetric(value.readUnsignedInt());
109             builder.setPrefixMetric(metric);
110             LOG.debug("Parsed Metric: {}", metric);
111             break;
112         case FORWARDING_ADDRESS:
113             final IpAddress fwdAddress = parseForwardingAddress(value);
114             builder.setOspfForwardingAddress(fwdAddress);
115             LOG.debug("Parsed FWD Address: {}", fwdAddress);
116             break;
117         case PREFIX_OPAQUE:
118             if (LOG.isDebugEnabled()) {
119                 LOG.debug("Parsed Opaque value: {}, not preserving it", ByteBufUtil.hexDump(value));
120             }
121             break;
122         case PREFIX_SID:
123             final SrPrefix prefix = SrPrefixAttributesParser.parseSrPrefix(value);
124             builder.setSrPrefix(prefix);
125             LOG.debug("Parsed SR Prefix: {}", prefix);
126             break;
127         case RANGE:
128             final SrRange range = RangeTlvParser.parseSrRange(value);
129             builder.setSrRange(range);
130             LOG.debug("Parsed SR Range: {}", range);
131             break;
132         case BINDING_SID:
133             final SrBindingSidLabel label = BindingSidLabelParser.parseBindingSidLabel(value);
134             builder.setSrBindingSidLabel(label);
135             LOG.debug("Parsed SR Binding SID {}", label);
136             break;
137         default:
138             LOG.warn("TLV {} is not a valid prefix attribute, ignoring it", key);
139         }
140     }
141
142     private static void parseRouteTags(final List<RouteTag> routeTags, final ByteBuf value) {
143         while (value.isReadable()) {
144             final RouteTag routeTag = new RouteTag(ByteArray.readBytes(value, ROUTE_TAG_LENGTH));
145             routeTags.add(routeTag);
146             LOG.debug("Parsed Route Tag: {}", routeTag);
147         }
148     }
149
150     private static void parseExtendedRouteTags(final List<ExtendedRouteTag> exRouteTags, final ByteBuf value) {
151         while (value.isReadable()) {
152             final ExtendedRouteTag exRouteTag = new ExtendedRouteTag(ByteArray.readBytes(value, EXTENDED_ROUTE_TAG_LENGTH));
153             exRouteTags.add(exRouteTag);
154             LOG.debug("Parsed Extended Route Tag: {}", exRouteTag);
155         }
156     }
157
158     private static IpAddress parseForwardingAddress(final ByteBuf value) {
159         IpAddress fwdAddress = null;
160         switch (value.readableBytes()) {
161         case Ipv4Util.IP4_LENGTH:
162             fwdAddress = new IpAddress(Ipv4Util.addressForByteBuf(value));
163             break;
164         case Ipv6Util.IPV6_LENGTH:
165             fwdAddress = new IpAddress(Ipv6Util.addressForByteBuf(value));
166             break;
167         default:
168             LOG.debug("Ignoring unsupported forwarding address length {}", value.readableBytes());
169         }
170         return fwdAddress;
171     }
172
173     static void serializePrefixAttributes(final PrefixAttributesCase prefixAttributesCase, final ByteBuf byteAggregator) {
174         final PrefixAttributes prefixAtrributes = prefixAttributesCase.getPrefixAttributes();
175         if (prefixAtrributes.getIgpBits() != null) {
176             final BitArray igpBit = new BitArray(FLAGS_SIZE);
177             igpBit.set(UP_DOWN_BIT, prefixAtrributes.getIgpBits().getUpDown().isUpDown());
178             TlvUtil.writeTLV(IGP_FLAGS, Unpooled.wrappedBuffer(igpBit.array()), byteAggregator);
179         }
180         serializeRouteTags(prefixAtrributes.getRouteTags(), byteAggregator);
181         serializeExtendedRouteTags(prefixAtrributes.getExtendedTags(), byteAggregator);
182         if (prefixAtrributes.getPrefixMetric() != null) {
183             TlvUtil.writeTLV(PREFIX_METRIC, Unpooled.copyInt(prefixAtrributes.getPrefixMetric().getValue().intValue()), byteAggregator);
184         }
185         serializeForwardingAddress(prefixAtrributes.getOspfForwardingAddress(), byteAggregator);
186         if (prefixAtrributes.getSrPrefix() != null) {
187             final ByteBuf buffer = Unpooled.buffer();
188             SrPrefixAttributesParser.serializeSrPrefix(prefixAtrributes.getSrPrefix(), buffer);
189             TlvUtil.writeTLV(PREFIX_SID, buffer, byteAggregator);
190         }
191         if (prefixAtrributes.getSrRange() != null) {
192             final ByteBuf sidBuffer = Unpooled.buffer();
193             RangeTlvParser.serializeSrRange(prefixAtrributes.getSrRange(), sidBuffer);
194             TlvUtil.writeTLV(RANGE, sidBuffer, byteAggregator);
195         }
196         if (prefixAtrributes.getSrBindingSidLabel() != null) {
197             final ByteBuf sidBuffer = Unpooled.buffer();
198             BindingSidLabelParser.serializeBindingSidLabel(prefixAtrributes.getSrBindingSidLabel(), sidBuffer);
199             TlvUtil.writeTLV(BINDING_SID, sidBuffer, byteAggregator);
200         }
201     }
202
203     private static void serializeRouteTags(final List<RouteTag> routeTags, final ByteBuf byteAggregator) {
204         if (routeTags != null) {
205             final ByteBuf routeTagsBuf = Unpooled.buffer();
206             for (final RouteTag routeTag : routeTags) {
207                 routeTagsBuf.writeBytes(routeTag.getValue());
208             }
209             TlvUtil.writeTLV(ROUTE_TAG, routeTagsBuf, byteAggregator);
210         }
211     }
212
213     private static void serializeExtendedRouteTags(final List<ExtendedRouteTag> exRouteTags, final ByteBuf byteAggregator) {
214         if (exRouteTags != null) {
215             final ByteBuf extendedBuf = Unpooled.buffer();
216             for (final ExtendedRouteTag exRouteTag : exRouteTags) {
217                 extendedBuf.writeBytes(exRouteTag.getValue());
218             }
219             TlvUtil.writeTLV(EXTENDED_ROUTE_TAG, extendedBuf, byteAggregator);
220         }
221     }
222
223     private static void serializeForwardingAddress(final IpAddress forwardingAddress, final ByteBuf byteAggregator) {
224         if (forwardingAddress != null) {
225             final ByteBuf ospfBuf = Unpooled.buffer();
226             if (forwardingAddress.getIpv4Address() != null) {
227                 ospfBuf.writeBytes(Ipv4Util.bytesForAddress(forwardingAddress.getIpv4Address()));
228             } else if (forwardingAddress.getIpv6Address() != null) {
229                 ospfBuf.writeBytes(Ipv6Util.bytesForAddress(forwardingAddress.getIpv6Address()));
230             }
231             TlvUtil.writeTLV(FORWARDING_ADDRESS, ospfBuf, byteAggregator);
232         }
233     }
234 }