Bump versions to 0.21.7-SNAPSHOT
[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.ImmutableSet;
15 import com.google.common.collect.Multimap;
16 import io.netty.buffer.ByteBuf;
17 import io.netty.buffer.ByteBufUtil;
18 import io.netty.buffer.Unpooled;
19 import java.util.ArrayList;
20 import java.util.List;
21 import java.util.Map.Entry;
22 import java.util.Set;
23 import org.opendaylight.protocol.bgp.linkstate.impl.attribute.sr.BindingSidLabelParser;
24 import org.opendaylight.protocol.bgp.linkstate.impl.attribute.sr.Ipv6SrPrefixAttributesParser;
25 import org.opendaylight.protocol.bgp.linkstate.impl.attribute.sr.RangeTlvParser;
26 import org.opendaylight.protocol.bgp.linkstate.impl.attribute.sr.SrPrefixAttributesParser;
27 import org.opendaylight.protocol.bgp.linkstate.spi.TlvUtil;
28 import org.opendaylight.protocol.util.BitArray;
29 import org.opendaylight.protocol.util.ByteArray;
30 import org.opendaylight.protocol.util.Ipv4Util;
31 import org.opendaylight.protocol.util.Ipv6Util;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressNoZone;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.ExtendedRouteTag;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.IgpBits.UpDown;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.ProtocolId;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.RouteTag;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.LinkStateAttribute;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.PrefixAttributesCase;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.PrefixAttributesCaseBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.prefix.attributes._case.PrefixAttributes;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.prefix.attributes._case.PrefixAttributesBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.prefix.state.IgpBits;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.prefix.state.IgpBitsBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.prefix.state.Ipv6SrPrefix;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.prefix.state.SrBindingSidLabels;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.prefix.state.SrPrefix;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.prefix.state.SrRange;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.IgpMetric;
49 import org.opendaylight.yangtools.yang.common.netty.ByteBufUtils;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
52
53 @VisibleForTesting
54 public final class PrefixAttributesParser {
55
56     /* Segment routing TLV */
57     public static final int BINDING_SID = 1160;
58     private static final Logger LOG = LoggerFactory.getLogger(PrefixAttributesParser.class);
59     private static final int ROUTE_TAG_LENGTH = 4;
60     private static final int EXTENDED_ROUTE_TAG_LENGTH = 8;
61     private static final int FLAGS_SIZE = 8;
62     private static final int UP_DOWN_BIT = 0;
63     private static final int OSPF_NO_UNICAST = 1;
64     private static final int OSPF_LOCAL_ADDRESS = 2;
65     private static final int OSPF_PROPAGATE_ADDRESS = 3;
66     /* Prefix Attribute TLVs */
67     private static final int IGP_FLAGS = 1152;
68     private static final int ROUTE_TAG = 1153;
69     private static final int EXTENDED_ROUTE_TAG = 1154;
70     private static final int PREFIX_METRIC = 1155;
71     private static final int FORWARDING_ADDRESS = 1156;
72     private static final int PREFIX_OPAQUE = 1157;
73     private static final int RANGE = 1159;
74
75     private PrefixAttributesParser() {
76
77     }
78
79     /**
80      * Parse prefix attributes.
81      *
82      * @param attributes key is the tlv type and value are the value bytes of the tlv
83      * @param protocolId to differentiate parsing methods
84      * @return {@link LinkStateAttribute}
85      */
86     static LinkStateAttribute parsePrefixAttributes(final Multimap<Integer, ByteBuf> attributes,
87             final ProtocolId protocolId) {
88         final PrefixAttributesBuilder builder = new PrefixAttributesBuilder();
89         final List<RouteTag> routeTags = new ArrayList<>();
90         final List<ExtendedRouteTag> exRouteTags = new ArrayList<>();
91         for (final Entry<Integer, ByteBuf> entry : attributes.entries()) {
92             final int key = entry.getKey();
93             final ByteBuf value = entry.getValue();
94             LOG.trace("Prefix attribute TLV {}", key);
95             parseAttribute(key, value, protocolId, builder, routeTags, exRouteTags);
96         }
97         LOG.trace("Finished parsing Prefix Attributes.");
98         builder.setRouteTags(ImmutableSet.copyOf(routeTags));
99         builder.setExtendedTags(ImmutableSet.copyOf(exRouteTags));
100         return new PrefixAttributesCaseBuilder().setPrefixAttributes(builder.build()).build();
101     }
102
103     private static void parseAttribute(final int key, final ByteBuf value, final ProtocolId protocolId,
104             final PrefixAttributesBuilder builder, final List<RouteTag> routeTags,
105             final List<ExtendedRouteTag> exRouteTags) {
106         switch (key) {
107             case IGP_FLAGS:
108                 parseIgpFags(builder, value);
109                 break;
110             case ROUTE_TAG:
111                 parseRouteTags(routeTags, value);
112                 break;
113             case EXTENDED_ROUTE_TAG:
114                 parseExtendedRouteTags(exRouteTags, value);
115                 break;
116             case PREFIX_METRIC:
117                 final IgpMetric metric = new IgpMetric(ByteBufUtils.readUint32(value));
118                 builder.setPrefixMetric(metric);
119                 LOG.debug("Parsed Metric: {}", metric);
120                 break;
121             case FORWARDING_ADDRESS:
122                 final IpAddressNoZone fwdAddress = parseForwardingAddress(value);
123                 builder.setOspfForwardingAddress(fwdAddress);
124                 LOG.debug("Parsed FWD Address: {}", fwdAddress);
125                 break;
126             case PREFIX_OPAQUE:
127                 if (LOG.isDebugEnabled()) {
128                     LOG.debug("Parsed Opaque value: {}, not preserving it", ByteBufUtil.hexDump(value));
129                 }
130                 break;
131             case PREFIX_SID:
132                 final SrPrefix prefix = SrPrefixAttributesParser.parseSrPrefix(value, protocolId);
133                 builder.setSrPrefix(prefix);
134                 LOG.debug("Parsed SR Prefix: {}", prefix);
135                 break;
136             case IPV6_PREFIX_SID:
137                 final Ipv6SrPrefix ipv6Prefix = Ipv6SrPrefixAttributesParser.parseSrIpv6Prefix(value);
138                 builder.setIpv6SrPrefix(ipv6Prefix);
139                 LOG.debug("Parsed Ipv6 SR Prefix: {}", ipv6Prefix);
140                 break;
141             case RANGE:
142                 final SrRange range = RangeTlvParser.parseSrRange(value, protocolId);
143                 builder.setSrRange(range);
144                 LOG.debug("Parsed SR Range: {}", range);
145                 break;
146             case BINDING_SID:
147                 parseBindingSid(builder, value, protocolId);
148                 break;
149             default:
150                 LOG.warn("TLV {} is not a valid prefix attribute, ignoring it", key);
151         }
152     }
153
154     private static void parseIgpFags(final PrefixAttributesBuilder builder, final ByteBuf value) {
155         final BitArray flags = BitArray.valueOf(value, FLAGS_SIZE);
156         final boolean upDownBit = flags.get(UP_DOWN_BIT);
157         builder.setIgpBits(new IgpBitsBuilder().setUpDown(new UpDown(upDownBit)).setIsIsUpDown(upDownBit)
158             .setOspfNoUnicast(flags.get(OSPF_NO_UNICAST))
159             .setOspfLocalAddress(flags.get(OSPF_LOCAL_ADDRESS))
160             .setOspfPropagateNssa(flags.get(OSPF_PROPAGATE_ADDRESS)).build());
161         LOG.debug("Parsed IGP flag (up/down bit) : {}", upDownBit);
162     }
163
164     private static void parseBindingSid(final PrefixAttributesBuilder builder, final ByteBuf value,
165             final ProtocolId protocolId) {
166         final List<SrBindingSidLabels> labels;
167         if (builder.getSrBindingSidLabels() != null) {
168             labels = builder.getSrBindingSidLabels();
169         } else {
170             labels = new ArrayList<>();
171             builder.setSrBindingSidLabels(labels);
172         }
173         final SrBindingSidLabels label = BindingSidLabelParser.parseBindingSidLabel(value, protocolId);
174         labels.add(label);
175         LOG.debug("Parsed SR Binding SID {}", label);
176     }
177
178     private static void parseRouteTags(final List<RouteTag> routeTags, final ByteBuf value) {
179         while (value.isReadable()) {
180             final RouteTag routeTag = new RouteTag(ByteArray.readBytes(value, ROUTE_TAG_LENGTH));
181             routeTags.add(routeTag);
182             LOG.debug("Parsed Route Tag: {}", routeTag);
183         }
184     }
185
186     private static void parseExtendedRouteTags(final List<ExtendedRouteTag> exRouteTags, final ByteBuf value) {
187         while (value.isReadable()) {
188             final ExtendedRouteTag exRouteTag = new ExtendedRouteTag(ByteArray.readBytes(value,
189                 EXTENDED_ROUTE_TAG_LENGTH));
190             exRouteTags.add(exRouteTag);
191             LOG.debug("Parsed Extended Route Tag: {}", exRouteTag);
192         }
193     }
194
195     private static IpAddressNoZone parseForwardingAddress(final ByteBuf value) {
196         switch (value.readableBytes()) {
197             case Ipv4Util.IP4_LENGTH:
198                 return new IpAddressNoZone(Ipv4Util.addressForByteBuf(value));
199             case Ipv6Util.IPV6_LENGTH:
200                 return new IpAddressNoZone(Ipv6Util.addressForByteBuf(value));
201             default:
202                 LOG.debug("Ignoring unsupported forwarding address length {}", value.readableBytes());
203                 return null;
204         }
205     }
206
207     static void serializePrefixAttributes(final PrefixAttributesCase prefixAttributesCase,
208             final ByteBuf byteAggregator) {
209         final PrefixAttributes prefixAtrributes = prefixAttributesCase.getPrefixAttributes();
210         if (prefixAtrributes.getIgpBits() != null) {
211             final BitArray igpBit = new BitArray(FLAGS_SIZE);
212             final IgpBits igpBits = prefixAtrributes.getIgpBits();
213             igpBit.set(UP_DOWN_BIT, igpBits.getUpDown().getUpDown() || igpBits.getIsIsUpDown());
214             igpBit.set(OSPF_NO_UNICAST, igpBits.getOspfNoUnicast());
215             igpBit.set(OSPF_LOCAL_ADDRESS, igpBits.getOspfLocalAddress());
216             igpBit.set(OSPF_PROPAGATE_ADDRESS, igpBits.getOspfPropagateNssa());
217             TlvUtil.writeTLV(IGP_FLAGS, Unpooled.wrappedBuffer(igpBit.array()), byteAggregator);
218         }
219         serializeRouteTags(prefixAtrributes.getRouteTags(), byteAggregator);
220         serializeExtendedRouteTags(prefixAtrributes.getExtendedTags(), byteAggregator);
221         serializePrefixMetric(prefixAtrributes.getPrefixMetric(), byteAggregator);
222         serializeForwardingAddress(prefixAtrributes.getOspfForwardingAddress(), byteAggregator);
223         serializeSrPrefix(prefixAtrributes.getSrPrefix(), byteAggregator);
224         serializeIpv6SrPrefix(prefixAtrributes.getIpv6SrPrefix(), byteAggregator);
225         serializeSrRange(prefixAtrributes.getSrRange(), byteAggregator);
226         serializeSrBindingLabel(prefixAtrributes.getSrBindingSidLabels(), byteAggregator);
227     }
228
229     private static void serializeSrBindingLabel(final List<SrBindingSidLabels> srBindingSidLabels,
230             final ByteBuf byteAggregator) {
231         if (srBindingSidLabels != null) {
232             for (final SrBindingSidLabels bindingSid : srBindingSidLabels) {
233                 final ByteBuf sidBuffer = Unpooled.buffer();
234                 BindingSidLabelParser.serializeBindingSidAttributes(bindingSid.getWeight(), bindingSid.getFlags(),
235                     bindingSid.getBindingSubTlvs(), sidBuffer);
236                 TlvUtil.writeTLV(PrefixAttributesParser.BINDING_SID, sidBuffer, byteAggregator);
237             }
238         }
239     }
240
241     private static void serializeSrRange(final SrRange srRange, final ByteBuf byteAggregator) {
242         if (srRange != null) {
243             final ByteBuf sidBuffer = Unpooled.buffer();
244             RangeTlvParser.serializeSrRange(srRange, sidBuffer);
245             TlvUtil.writeTLV(RANGE, sidBuffer, byteAggregator);
246         }
247     }
248
249     private static void serializeIpv6SrPrefix(final Ipv6SrPrefix ipv6SrPrefix, final ByteBuf byteAggregator) {
250         if (ipv6SrPrefix != null) {
251             final ByteBuf buffer = Unpooled.buffer();
252             Ipv6SrPrefixAttributesParser.serializeIpv6SrPrefix(ipv6SrPrefix, buffer);
253             TlvUtil.writeTLV(IPV6_PREFIX_SID, buffer, byteAggregator);
254         }
255     }
256
257     private static void serializeSrPrefix(final SrPrefix srPrefix, final ByteBuf byteAggregator) {
258         if (srPrefix != null) {
259             final ByteBuf buffer = Unpooled.buffer();
260             SrPrefixAttributesParser.serializeSrPrefix(srPrefix, buffer);
261             TlvUtil.writeTLV(PREFIX_SID, buffer, byteAggregator);
262         }
263     }
264
265     private static void serializePrefixMetric(final IgpMetric prefixMetric, final ByteBuf byteAggregator) {
266         if (prefixMetric != null) {
267             TlvUtil.writeTLV(PREFIX_METRIC, Unpooled.copyInt(prefixMetric.getValue().intValue()), byteAggregator);
268         }
269     }
270
271     private static void serializeRouteTags(final Set<RouteTag> routeTags, final ByteBuf byteAggregator) {
272         if (routeTags != null) {
273             final ByteBuf routeTagsBuf = Unpooled.buffer();
274             for (final RouteTag routeTag : routeTags) {
275                 routeTagsBuf.writeBytes(routeTag.getValue());
276             }
277             TlvUtil.writeTLV(ROUTE_TAG, routeTagsBuf, byteAggregator);
278         }
279     }
280
281     private static void serializeExtendedRouteTags(final Set<ExtendedRouteTag> exRouteTags,
282             final ByteBuf byteAggregator) {
283         if (exRouteTags != null) {
284             final ByteBuf extendedBuf = Unpooled.buffer();
285             for (final ExtendedRouteTag exRouteTag : exRouteTags) {
286                 extendedBuf.writeBytes(exRouteTag.getValue());
287             }
288             TlvUtil.writeTLV(EXTENDED_ROUTE_TAG, extendedBuf, byteAggregator);
289         }
290     }
291
292     private static void serializeForwardingAddress(final IpAddressNoZone forwardingAddress,
293             final ByteBuf byteAggregator) {
294         if (forwardingAddress != null) {
295             final ByteBuf ospfBuf = Unpooled.buffer();
296             if (forwardingAddress.getIpv4AddressNoZone() != null) {
297                 ospfBuf.writeBytes(Ipv4Util.bytesForAddress(forwardingAddress.getIpv4AddressNoZone()));
298             } else if (forwardingAddress.getIpv6AddressNoZone() != null) {
299                 ospfBuf.writeBytes(Ipv6Util.bytesForAddress(forwardingAddress.getIpv6AddressNoZone()));
300             }
301             TlvUtil.writeTLV(FORWARDING_ADDRESS, ospfBuf, byteAggregator);
302         }
303     }
304 }