BUG-608 : implemented SrPrefix parser/serializers
[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.collect.Multimap;
11 import io.netty.buffer.ByteBuf;
12 import io.netty.buffer.ByteBufUtil;
13 import io.netty.buffer.Unpooled;
14 import java.util.ArrayList;
15 import java.util.BitSet;
16 import java.util.List;
17 import java.util.Map.Entry;
18 import org.opendaylight.protocol.bgp.linkstate.attribute.sr.SrPrefixAttributesParser;
19 import org.opendaylight.protocol.bgp.linkstate.spi.TlvUtil;
20 import org.opendaylight.protocol.util.ByteArray;
21 import org.opendaylight.protocol.util.Ipv4Util;
22 import org.opendaylight.protocol.util.Ipv6Util;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.ExtendedRouteTag;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.IgpBits.UpDown;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.RouteTag;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.prefix.state.IgpBitsBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.prefix.state.SrPrefix;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.path.attributes.linkstate.path.attribute.LinkStateAttribute;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.path.attributes.linkstate.path.attribute.link.state.attribute.PrefixAttributesCase;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.path.attributes.linkstate.path.attribute.link.state.attribute.PrefixAttributesCaseBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.path.attributes.linkstate.path.attribute.link.state.attribute.prefix.attributes._case.PrefixAttributes;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.path.attributes.linkstate.path.attribute.link.state.attribute.prefix.attributes._case.PrefixAttributesBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.IgpMetric;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 final class PrefixAttributesParser {
39
40     private static final Logger LOG = LoggerFactory.getLogger(PrefixAttributesParser.class);
41
42     private static final int ROUTE_TAG_LENGTH = 4;
43     private static final int EXTENDED_ROUTE_TAG_LENGTH = 8;
44     private static final int UP_DOWN_BIT = 7;
45
46     /* Prefix Attribute TLVs */
47     private static final int IGP_FLAGS = 1152;
48     private static final int ROUTE_TAG = 1153;
49     private static final int EXTENDED_ROUTE_TAG = 1154;
50     private static final int PREFIX_METRIC = 1155;
51     private static final int FORWARDING_ADDRESS = 1156;
52     private static final int PREFIX_OPAQUE = 1157;
53
54     /* Segment routing TLV */
55     private static final int PREFIX_SID = 1158;
56
57     /**
58      * Parse prefix attributes.
59      *
60      * @param attributes key is the tlv type and value are the value bytes of the tlv
61      * @return {@link LinkStateAttribute}
62      */
63     static LinkStateAttribute parsePrefixAttributes(final Multimap<Integer, ByteBuf> attributes) {
64         final PrefixAttributesBuilder builder = new PrefixAttributesBuilder();
65         final List<RouteTag> routeTags = new ArrayList<>();
66         final List<ExtendedRouteTag> exRouteTags = new ArrayList<>();
67         for (final Entry<Integer, ByteBuf> entry : attributes.entries()) {
68             final int key = entry.getKey();
69             final ByteBuf value = entry.getValue();
70             LOG.trace("Prefix attribute TLV {}", key);
71             switch (key) {
72             case IGP_FLAGS:
73                 final BitSet flags = BitSet.valueOf(ByteArray.readAllBytes(value));
74                 final boolean upDownBit = flags.get(UP_DOWN_BIT);
75                 builder.setIgpBits(new IgpBitsBuilder().setUpDown(new UpDown(upDownBit)).build());
76                 LOG.debug("Parsed IGP flag (up/down bit) : {}", upDownBit);
77                 break;
78             case ROUTE_TAG:
79                 while (value.isReadable()) {
80                     final RouteTag routeTag = new RouteTag(ByteArray.readBytes(value, ROUTE_TAG_LENGTH));
81                     routeTags.add(routeTag);
82                     LOG.debug("Parsed Route Tag: {}", routeTag);
83                 }
84                 break;
85             case EXTENDED_ROUTE_TAG:
86                 while (value.isReadable()) {
87                     final ExtendedRouteTag exRouteTag = new ExtendedRouteTag(ByteArray.readBytes(value, EXTENDED_ROUTE_TAG_LENGTH));
88                     exRouteTags.add(exRouteTag);
89                     LOG.debug("Parsed Extended Route Tag: {}", exRouteTag);
90                 }
91                 break;
92             case PREFIX_METRIC:
93                 final IgpMetric metric = new IgpMetric(value.readUnsignedInt());
94                 builder.setPrefixMetric(metric);
95                 LOG.debug("Parsed Metric: {}", metric);
96                 break;
97             case FORWARDING_ADDRESS:
98                 final IpAddress fwdAddress = parseForwardingAddress(value);
99                 builder.setOspfForwardingAddress(fwdAddress);
100                 LOG.debug("Parsed FWD Address: {}", fwdAddress);
101                 break;
102             case PREFIX_OPAQUE:
103                 LOG.debug("Parsed Opaque value: {}, not preserving it", ByteBufUtil.hexDump(value));
104                 break;
105             case PREFIX_SID:
106                 final SrPrefix prefix = SrPrefixAttributesParser.parseSrPrefix(value);
107                 builder.setSrPrefix(prefix);
108                 LOG.debug("Parsed SR Prefix: {}", prefix);
109                 break;
110             default:
111                 LOG.warn("TLV {} is not a valid prefix attribute, ignoring it", key);
112             }
113         }
114         LOG.trace("Finished parsing Prefix Attributes.");
115         builder.setRouteTags(routeTags);
116         builder.setExtendedTags(exRouteTags);
117         return new PrefixAttributesCaseBuilder().setPrefixAttributes(builder.build()).build();
118     }
119
120     private static IpAddress parseForwardingAddress(final ByteBuf value) {
121         IpAddress fwdAddress = null;
122         switch (value.readableBytes()) {
123         case Ipv4Util.IP4_LENGTH:
124             fwdAddress = new IpAddress(Ipv4Util.addressForByteBuf(value));
125             break;
126         case Ipv6Util.IPV6_LENGTH:
127             fwdAddress = new IpAddress(Ipv6Util.addressForByteBuf(value));
128             break;
129         default:
130             LOG.debug("Ignoring unsupported forwarding address length {}", value.readableBytes());
131         }
132         return fwdAddress;
133     }
134
135     static void serializePrefixAttributes(final PrefixAttributesCase prefixAttributesCase, final ByteBuf byteAggregator) {
136         final PrefixAttributes prefixAtrributes = prefixAttributesCase.getPrefixAttributes();
137         if (prefixAtrributes.getIgpBits() != null) {
138             final BitSet igpBit = new BitSet();
139             final Boolean bit = prefixAtrributes.getIgpBits().getUpDown().isUpDown();
140             if (bit != null) {
141                 igpBit.set(UP_DOWN_BIT, bit);
142             }
143             TlvUtil.writeTLV(IGP_FLAGS, Unpooled.wrappedBuffer(igpBit.toByteArray()), byteAggregator);
144         }
145         if (prefixAtrributes.getRouteTags() != null) {
146             final ByteBuf routeTagsBuf = Unpooled.buffer();
147             for (final RouteTag routeTag : prefixAtrributes.getRouteTags()) {
148                 routeTagsBuf.writeBytes(routeTag.getValue());
149             }
150             TlvUtil.writeTLV(ROUTE_TAG, routeTagsBuf, byteAggregator);
151         }
152         final List<ExtendedRouteTag> routeTagList = prefixAtrributes.getExtendedTags();
153         if (routeTagList != null) {
154             final ByteBuf extendedBuf = Unpooled.buffer();
155             for (final ExtendedRouteTag extendedRouteTag : routeTagList) {
156                 extendedBuf.writeBytes(extendedRouteTag.getValue());
157             }
158             TlvUtil.writeTLV(EXTENDED_ROUTE_TAG, extendedBuf, byteAggregator);
159         }
160         serializeForwardingAddress(prefixAtrributes.getOspfForwardingAddress(), byteAggregator);
161         if (prefixAtrributes.getPrefixMetric() != null) {
162             TlvUtil.writeTLV(PREFIX_METRIC, Unpooled.copyInt(prefixAtrributes.getPrefixMetric().getValue().intValue()), byteAggregator);
163         }
164         if (prefixAtrributes.getSrPrefix() != null) {
165             final ByteBuf b = Unpooled.buffer();
166             SrPrefixAttributesParser.serializeSrPrefix(prefixAtrributes.getSrPrefix(), b);
167             TlvUtil.writeTLV(PREFIX_SID, b, byteAggregator);
168         }
169
170     }
171
172     private static void serializeForwardingAddress(final IpAddress forwardingAddress, final ByteBuf byteAggregator) {
173         if (forwardingAddress != null) {
174             final ByteBuf ospfBuf = Unpooled.buffer();
175             if (forwardingAddress.getIpv4Address() != null) {
176                 ospfBuf.writeBytes(Ipv4Util.bytesForAddress(forwardingAddress.getIpv4Address()));
177             } else if (forwardingAddress.getIpv6Address() != null) {
178                 ospfBuf.writeBytes(Ipv6Util.bytesForAddress(forwardingAddress.getIpv6Address()));
179             }
180             TlvUtil.writeTLV(FORWARDING_ADDRESS, ospfBuf, byteAggregator);
181         }
182     }
183 }