aac5138921dd92a23f9be5cf716971647a98de64
[bgpcep.git] / bgp / extensions / linkstate / src / main / java / org / opendaylight / protocol / bgp / linkstate / impl / 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.impl.attribute;
9
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;
12
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;
49
50 @VisibleForTesting
51 public final class PrefixAttributesParser {
52
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;
71
72     private PrefixAttributesParser() {
73         throw new UnsupportedOperationException();
74     }
75
76     /**
77      * Parse prefix attributes.
78      *
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}
82      */
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);
92         }
93         LOG.trace("Finished parsing Prefix Attributes.");
94         builder.setRouteTags(routeTags);
95         builder.setExtendedTags(exRouteTags);
96         return new PrefixAttributesCaseBuilder().setPrefixAttributes(builder.build()).build();
97     }
98
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) {
100         switch (key) {
101         case IGP_FLAGS:
102             parseIgpFags(builder, value);
103             break;
104         case ROUTE_TAG:
105             parseRouteTags(routeTags, value);
106             break;
107         case EXTENDED_ROUTE_TAG:
108             parseExtendedRouteTags(exRouteTags, value);
109             break;
110         case PREFIX_METRIC:
111             final IgpMetric metric = new IgpMetric(value.readUnsignedInt());
112             builder.setPrefixMetric(metric);
113             LOG.debug("Parsed Metric: {}", metric);
114             break;
115         case FORWARDING_ADDRESS:
116             final IpAddress fwdAddress = parseForwardingAddress(value);
117             builder.setOspfForwardingAddress(fwdAddress);
118             LOG.debug("Parsed FWD Address: {}", fwdAddress);
119             break;
120         case PREFIX_OPAQUE:
121             if (LOG.isDebugEnabled()) {
122                 LOG.debug("Parsed Opaque value: {}, not preserving it", ByteBufUtil.hexDump(value));
123             }
124             break;
125         case PREFIX_SID:
126             final SrPrefix prefix = SrPrefixAttributesParser.parseSrPrefix(value, protocolId);
127             builder.setSrPrefix(prefix);
128             LOG.debug("Parsed SR Prefix: {}", prefix);
129             break;
130         case IPV6_PREFIX_SID:
131             final Ipv6SrPrefix ipv6Prefix = Ipv6SrPrefixAttributesParser.parseSrIpv6Prefix(value);
132             builder.setIpv6SrPrefix(ipv6Prefix);
133             LOG.debug("Parsed Ipv6 SR Prefix: {}", ipv6Prefix);
134             break;
135         case RANGE:
136             final SrRange range = RangeTlvParser.parseSrRange(value, protocolId);
137             builder.setSrRange(range);
138             LOG.debug("Parsed SR Range: {}", range);
139             break;
140         case BINDING_SID:
141             parseBindingSid(builder, value, protocolId);
142             break;
143         default:
144             LOG.warn("TLV {} is not a valid prefix attribute, ignoring it", key);
145         }
146     }
147
148     private static void parseIgpFags(final PrefixAttributesBuilder builder, final ByteBuf value) {
149         final BitArray flags = BitArray.valueOf(value, FLAGS_SIZE);
150         final boolean upDownBit = flags.get(UP_DOWN_BIT);
151         builder.setIgpBits(new IgpBitsBuilder().setUpDown(new UpDown(upDownBit)).setIsIsUpDown(upDownBit).setOspfNoUnicast(flags.get(OSPF_NO_UNICAST))
152             .setOspfLocalAddress(flags.get(OSPF_LOCAL_ADDRESS)).setOspfPropagateNssa(flags.get(OSPF_PROPAGATE_ADDRESS)).build());
153         LOG.debug("Parsed IGP flag (up/down bit) : {}", upDownBit);
154     }
155
156     private static void parseBindingSid(final PrefixAttributesBuilder builder, final ByteBuf value, final ProtocolId protocolId) {
157         final List<SrBindingSidLabels> labels;
158         if (builder.getSrBindingSidLabels() != null) {
159             labels = builder.getSrBindingSidLabels();
160         } else {
161             labels = new ArrayList<>();
162             builder.setSrBindingSidLabels(labels);
163         }
164         final SrBindingSidLabels label = BindingSidLabelParser.parseBindingSidLabel(value, protocolId);
165         labels.add(label);
166         LOG.debug("Parsed SR Binding SID {}", label);
167     }
168
169     private static void parseRouteTags(final List<RouteTag> routeTags, final ByteBuf value) {
170         while (value.isReadable()) {
171             final RouteTag routeTag = new RouteTag(ByteArray.readBytes(value, ROUTE_TAG_LENGTH));
172             routeTags.add(routeTag);
173             LOG.debug("Parsed Route Tag: {}", routeTag);
174         }
175     }
176
177     private static void parseExtendedRouteTags(final List<ExtendedRouteTag> exRouteTags, final ByteBuf value) {
178         while (value.isReadable()) {
179             final ExtendedRouteTag exRouteTag = new ExtendedRouteTag(ByteArray.readBytes(value, EXTENDED_ROUTE_TAG_LENGTH));
180             exRouteTags.add(exRouteTag);
181             LOG.debug("Parsed Extended Route Tag: {}", exRouteTag);
182         }
183     }
184
185     private static IpAddress parseForwardingAddress(final ByteBuf value) {
186         IpAddress fwdAddress = null;
187         switch (value.readableBytes()) {
188         case Ipv4Util.IP4_LENGTH:
189             fwdAddress = new IpAddress(Ipv4Util.addressForByteBuf(value));
190             break;
191         case Ipv6Util.IPV6_LENGTH:
192             fwdAddress = new IpAddress(Ipv6Util.addressForByteBuf(value));
193             break;
194         default:
195             LOG.debug("Ignoring unsupported forwarding address length {}", value.readableBytes());
196         }
197         return fwdAddress;
198     }
199
200     static void serializePrefixAttributes(final PrefixAttributesCase prefixAttributesCase, final ByteBuf byteAggregator) {
201         final PrefixAttributes prefixAtrributes = prefixAttributesCase.getPrefixAttributes();
202         if (prefixAtrributes.getIgpBits() != null) {
203             final BitArray igpBit = new BitArray(FLAGS_SIZE);
204             final IgpBits igpBits = prefixAtrributes.getIgpBits();
205             igpBit.set(UP_DOWN_BIT, igpBits.getUpDown().isUpDown() || igpBits.isIsIsUpDown());
206             igpBit.set(OSPF_NO_UNICAST, igpBits.isOspfNoUnicast());
207             igpBit.set(OSPF_LOCAL_ADDRESS, igpBits.isOspfLocalAddress());
208             igpBit.set(OSPF_PROPAGATE_ADDRESS, igpBits.isOspfPropagateNssa());
209             TlvUtil.writeTLV(IGP_FLAGS, Unpooled.wrappedBuffer(igpBit.array()), byteAggregator);
210         }
211         serializeRouteTags(prefixAtrributes.getRouteTags(), byteAggregator);
212         serializeExtendedRouteTags(prefixAtrributes.getExtendedTags(), byteAggregator);
213         serializePrefixMetric(prefixAtrributes.getPrefixMetric(), byteAggregator);
214         serializeForwardingAddress(prefixAtrributes.getOspfForwardingAddress(), byteAggregator);
215         serializeSrPrefix(prefixAtrributes.getSrPrefix(), byteAggregator);
216         serializeIpv6SrPrefix(prefixAtrributes.getIpv6SrPrefix(), byteAggregator);
217         serializeSrRange(prefixAtrributes.getSrRange(), byteAggregator);
218         serializeSrBindingLabel(prefixAtrributes.getSrBindingSidLabels(), byteAggregator);
219     }
220
221     private static void serializeSrBindingLabel(final List<SrBindingSidLabels> srBindingSidLabels, final ByteBuf byteAggregator) {
222         if (srBindingSidLabels != null) {
223             for (final SrBindingSidLabels bindingSid : srBindingSidLabels) {
224                 final ByteBuf sidBuffer = Unpooled.buffer();
225                 BindingSidLabelParser.serializeBindingSidAttributes(bindingSid.getWeight(), bindingSid.getFlags(), bindingSid.getBindingSubTlvs(), sidBuffer);
226                 TlvUtil.writeTLV(PrefixAttributesParser.BINDING_SID, sidBuffer, byteAggregator);
227             }
228         }
229     }
230
231     private static void serializeSrRange(final SrRange srRange, final ByteBuf byteAggregator) {
232         if (srRange != null) {
233             final ByteBuf sidBuffer = Unpooled.buffer();
234             RangeTlvParser.serializeSrRange(srRange, sidBuffer);
235             TlvUtil.writeTLV(RANGE, sidBuffer, byteAggregator);
236         }
237     }
238
239     private static void serializeIpv6SrPrefix(final Ipv6SrPrefix ipv6SrPrefix, final ByteBuf byteAggregator) {
240         if (ipv6SrPrefix != null) {
241             final ByteBuf buffer = Unpooled.buffer();
242             Ipv6SrPrefixAttributesParser.serializeIpv6SrPrefix(ipv6SrPrefix, buffer);
243             TlvUtil.writeTLV(IPV6_PREFIX_SID, buffer, byteAggregator);
244         }
245     }
246
247     private static void serializeSrPrefix(final SrPrefix srPrefix, final ByteBuf byteAggregator) {
248         if (srPrefix != null) {
249             final ByteBuf buffer = Unpooled.buffer();
250             SrPrefixAttributesParser.serializeSrPrefix(srPrefix, buffer);
251             TlvUtil.writeTLV(PREFIX_SID, buffer, byteAggregator);
252         }
253     }
254
255     private static void serializePrefixMetric(final IgpMetric prefixMetric, final ByteBuf byteAggregator) {
256         if (prefixMetric != null) {
257             TlvUtil.writeTLV(PREFIX_METRIC, Unpooled.copyInt(prefixMetric.getValue().intValue()), byteAggregator);
258         }
259     }
260
261     private static void serializeRouteTags(final List<RouteTag> routeTags, final ByteBuf byteAggregator) {
262         if (routeTags != null) {
263             final ByteBuf routeTagsBuf = Unpooled.buffer();
264             for (final RouteTag routeTag : routeTags) {
265                 routeTagsBuf.writeBytes(routeTag.getValue());
266             }
267             TlvUtil.writeTLV(ROUTE_TAG, routeTagsBuf, byteAggregator);
268         }
269     }
270
271     private static void serializeExtendedRouteTags(final List<ExtendedRouteTag> exRouteTags, final ByteBuf byteAggregator) {
272         if (exRouteTags != null) {
273             final ByteBuf extendedBuf = Unpooled.buffer();
274             for (final ExtendedRouteTag exRouteTag : exRouteTags) {
275                 extendedBuf.writeBytes(exRouteTag.getValue());
276             }
277             TlvUtil.writeTLV(EXTENDED_ROUTE_TAG, extendedBuf, byteAggregator);
278         }
279     }
280
281     private static void serializeForwardingAddress(final IpAddress forwardingAddress, final ByteBuf byteAggregator) {
282         if (forwardingAddress != null) {
283             final ByteBuf ospfBuf = Unpooled.buffer();
284             if (forwardingAddress.getIpv4Address() != null) {
285                 ospfBuf.writeBytes(Ipv4Util.bytesForAddress(forwardingAddress.getIpv4Address()));
286             } else if (forwardingAddress.getIpv6Address() != null) {
287                 ospfBuf.writeBytes(Ipv6Util.bytesForAddress(forwardingAddress.getIpv6Address()));
288             }
289             TlvUtil.writeTLV(FORWARDING_ADDRESS, ospfBuf, byteAggregator);
290         }
291     }
292 }