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