Bump versions to 0.21.7-SNAPSHOT
[bgpcep.git] / bgp / extensions / linkstate / src / main / java / org / opendaylight / protocol / bgp / linkstate / impl / attribute / NodeAttributesParser.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.yangtools.yang.common.netty.ByteBufUtils.writeUint16;
11
12 import com.google.common.annotations.VisibleForTesting;
13 import com.google.common.collect.ImmutableSet;
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.nio.charset.StandardCharsets;
19 import java.util.Map.Entry;
20 import java.util.Set;
21 import org.opendaylight.protocol.bgp.linkstate.impl.attribute.sr.SrNodeAttributesParser;
22 import org.opendaylight.protocol.bgp.linkstate.spi.TlvUtil;
23 import org.opendaylight.protocol.util.BitArray;
24 import org.opendaylight.protocol.util.ByteArray;
25 import org.opendaylight.protocol.util.Ipv4Util;
26 import org.opendaylight.protocol.util.Ipv6Util;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.Ipv4RouterIdentifier;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.Ipv6RouterIdentifier;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.IsisAreaIdentifier;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.NodeFlagBits;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.ProtocolId;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.TopologyIdentifier;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.LinkStateAttribute;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.NodeAttributesCase;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.NodeAttributesCaseBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.node.attributes._case.NodeAttributes;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.node.attributes._case.NodeAttributesBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.node.state.SrAlgorithm;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.node.state.SrCapabilities;
40 import org.opendaylight.yangtools.yang.common.Uint16;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
43
44 @VisibleForTesting
45 public final class NodeAttributesParser {
46
47     private static final Logger LOG = LoggerFactory.getLogger(NodeAttributesParser.class);
48     private static final int FLAGS_SIZE = 8;
49     // node flag bits
50     private static final int OVERLOAD_BIT = 0;
51     private static final int ATTACHED_BIT = 1;
52     private static final int EXTERNAL_BIT = 2;
53     private static final int ABBR_BIT = 3;
54     private static final int ROUTER_BIT = 4;
55     private static final int V6_BIT = 5;
56     /* Node Attribute TLVs */
57     private static final int NODE_FLAG_BITS = 1024;
58     private static final int NODE_OPAQUE = 1025;
59     private static final int DYNAMIC_HOSTNAME = 1026;
60     private static final int ISIS_AREA_IDENTIFIER = 1027;
61     /* Segment routing TLVs */
62     private static final int SR_CAPABILITIES = 1034;
63     private static final int SR_ALGORITHMS = 1035;
64
65     private NodeAttributesParser() {
66
67     }
68
69     /**
70      * Parse Node Attributes.
71      *
72      * @param attributes key is the tlv type and value is the value of the tlv
73      * @param protocolId to differentiate parsing methods
74      * @return {@link LinkStateAttribute}
75      */
76     static LinkStateAttribute parseNodeAttributes(final Multimap<Integer, ByteBuf> attributes,
77             final ProtocolId protocolId) {
78         final var topologyMembership = ImmutableSet.<TopologyIdentifier>builder();
79         final var areaMembership = ImmutableSet.<IsisAreaIdentifier>builder();
80         final NodeAttributesBuilder builder = new NodeAttributesBuilder();
81         for (final Entry<Integer, ByteBuf> entry : attributes.entries()) {
82             final int key = entry.getKey();
83             final ByteBuf value = entry.getValue();
84             LOG.trace("Node attribute TLV {}", key);
85             switch (key) {
86                 case TlvUtil.MULTI_TOPOLOGY_ID:
87                     parseTopologyId(topologyMembership, value);
88                     break;
89                 case NODE_FLAG_BITS:
90                     parseNodeFlags(value, builder);
91                     break;
92                 case NODE_OPAQUE:
93                     if (LOG.isDebugEnabled()) {
94                         LOG.debug("Ignoring opaque value: {}.", ByteBufUtil.hexDump(value));
95                     }
96                     break;
97                 case DYNAMIC_HOSTNAME:
98                     builder.setDynamicHostname(new String(ByteArray.readAllBytes(value), StandardCharsets.US_ASCII));
99                     LOG.debug("Parsed Node Name {}", builder.getDynamicHostname());
100                     break;
101                 case ISIS_AREA_IDENTIFIER:
102                     final IsisAreaIdentifier ai = new IsisAreaIdentifier(ByteArray.readAllBytes(value));
103                     areaMembership.add(ai);
104                     LOG.debug("Parsed AreaIdentifier {}", ai);
105                     break;
106                 case TlvUtil.LOCAL_IPV4_ROUTER_ID:
107                     final Ipv4RouterIdentifier ip4 = new Ipv4RouterIdentifier(Ipv4Util.addressForByteBuf(value));
108                     builder.setIpv4RouterId(ip4);
109                     LOG.debug("Parsed IPv4 Router Identifier {}", ip4);
110                     break;
111                 case TlvUtil.LOCAL_IPV6_ROUTER_ID:
112                     final Ipv6RouterIdentifier ip6 = new Ipv6RouterIdentifier(Ipv6Util.addressForByteBuf(value));
113                     builder.setIpv6RouterId(ip6);
114                     LOG.debug("Parsed IPv6 Router Identifier {}", ip6);
115                     break;
116                 case SR_CAPABILITIES:
117                     final SrCapabilities caps = SrNodeAttributesParser.parseSrCapabilities(value, protocolId);
118                     builder.setSrCapabilities(caps);
119                     LOG.debug("Parsed SR Capabilities {}", caps);
120                     break;
121                 case SR_ALGORITHMS:
122                     final SrAlgorithm algs = SrNodeAttributesParser.parseSrAlgorithms(value);
123                     builder.setSrAlgorithm(algs);
124                     LOG.debug("Parsed SR Algorithms {}", algs);
125                     break;
126                 default:
127                     LOG.warn("TLV {} is not a valid node attribute, ignoring it", key);
128             }
129         }
130         LOG.trace("Finished parsing Node Attributes.");
131         builder.setTopologyIdentifier(topologyMembership.build());
132         builder.setIsisAreaId(areaMembership.build());
133         return new NodeAttributesCaseBuilder().setNodeAttributes(builder.build()).build();
134     }
135
136     private static void parseNodeFlags(final ByteBuf value, final NodeAttributesBuilder builder) {
137         final BitArray flags = BitArray.valueOf(value, FLAGS_SIZE);
138         builder.setNodeFlags(new NodeFlagBits(flags.get(OVERLOAD_BIT), flags.get(ATTACHED_BIT), flags.get(EXTERNAL_BIT),
139             flags.get(ABBR_BIT), flags.get(ROUTER_BIT), flags.get(V6_BIT)));
140         LOG.debug("Parsed Overload bit: {}, attached bit: {}, external bit: {}, area border router: {}.",
141             flags.get(OVERLOAD_BIT), flags.get(ATTACHED_BIT), flags.get(EXTERNAL_BIT), flags.get(ABBR_BIT));
142     }
143
144     private static void parseTopologyId(final ImmutableSet.Builder<TopologyIdentifier> topologyMembership,
145             final ByteBuf value) {
146         while (value.isReadable()) {
147             final TopologyIdentifier topId = new TopologyIdentifier(
148                 Uint16.valueOf(value.readUnsignedShort() & TlvUtil.TOPOLOGY_ID_OFFSET));
149             topologyMembership.add(topId);
150             LOG.debug("Parsed Topology Identifier: {}", topId);
151         }
152     }
153
154     static void serializeNodeAttributes(final NodeAttributesCase nodeAttributesCase, final ByteBuf byteAggregator) {
155         LOG.trace("Started serializing Node Attributes");
156         final NodeAttributes nodeAttributes = nodeAttributesCase.getNodeAttributes();
157         serializeTopologyId(nodeAttributes.getTopologyIdentifier(), byteAggregator);
158         serializeNodeFlagBits(nodeAttributes.getNodeFlags(), byteAggregator);
159         if (nodeAttributes.getDynamicHostname() != null) {
160             TlvUtil.writeTLV(DYNAMIC_HOSTNAME, Unpooled.wrappedBuffer(StandardCharsets.UTF_8.encode(
161                 nodeAttributes.getDynamicHostname())), byteAggregator);
162         }
163         final Set<IsisAreaIdentifier> isisList = nodeAttributes.getIsisAreaId();
164         if (isisList != null) {
165             for (final IsisAreaIdentifier isisAreaIdentifier : isisList) {
166                 TlvUtil.writeTLV(ISIS_AREA_IDENTIFIER, Unpooled.wrappedBuffer(isisAreaIdentifier.getValue()),
167                     byteAggregator);
168             }
169         }
170         if (nodeAttributes.getIpv4RouterId() != null) {
171             TlvUtil.writeTLV(TlvUtil.LOCAL_IPV4_ROUTER_ID, Ipv4Util.byteBufForAddress(nodeAttributes.getIpv4RouterId()),
172                 byteAggregator);
173         }
174         if (nodeAttributes.getIpv6RouterId() != null) {
175             TlvUtil.writeTLV(TlvUtil.LOCAL_IPV6_ROUTER_ID, Ipv6Util.byteBufForAddress(nodeAttributes.getIpv6RouterId()),
176                 byteAggregator);
177         }
178         if (nodeAttributes.getSrCapabilities() != null) {
179             final ByteBuf capBuffer = Unpooled.buffer();
180             SrNodeAttributesParser.serializeSrCapabilities(nodeAttributes.getSrCapabilities(), capBuffer);
181             TlvUtil.writeTLV(SR_CAPABILITIES, capBuffer, byteAggregator);
182         }
183         if (nodeAttributes.getSrAlgorithm() != null) {
184             final ByteBuf capBuffer = Unpooled.buffer();
185             SrNodeAttributesParser.serializeSrAlgorithms(nodeAttributes.getSrAlgorithm(), capBuffer);
186             TlvUtil.writeTLV(SR_ALGORITHMS, capBuffer, byteAggregator);
187         }
188         LOG.trace("Finished serializing Node Attributes");
189     }
190
191     private static void serializeTopologyId(final Set<TopologyIdentifier> topList, final ByteBuf byteAggregator) {
192         if (topList != null) {
193             final ByteBuf mpIdBuf = Unpooled.buffer();
194             for (final TopologyIdentifier topologyIdentifier : topList) {
195                 writeUint16(mpIdBuf, topologyIdentifier.getValue());
196             }
197             TlvUtil.writeTLV(TlvUtil.MULTI_TOPOLOGY_ID, mpIdBuf, byteAggregator);
198         }
199     }
200
201     private static void serializeNodeFlagBits(final NodeFlagBits nodeFlagBits, final ByteBuf byteAggregator) {
202         if (nodeFlagBits != null) {
203             final ByteBuf nodeFlagBuf = Unpooled.buffer(1);
204             final BitArray flags = new BitArray(FLAGS_SIZE);
205             flags.set(OVERLOAD_BIT, nodeFlagBits.getOverload());
206             flags.set(ATTACHED_BIT, nodeFlagBits.getAttached());
207             flags.set(EXTERNAL_BIT, nodeFlagBits.getExternal());
208             flags.set(ABBR_BIT, nodeFlagBits.getAbr());
209             flags.set(ROUTER_BIT, nodeFlagBits.getRouter());
210             flags.set(V6_BIT, nodeFlagBits.getV6());
211             flags.toByteBuf(nodeFlagBuf);
212             TlvUtil.writeTLV(NODE_FLAG_BITS, nodeFlagBuf, byteAggregator);
213         }
214     }
215 }