3229cc11f72722e91ce97461a8bf4366450e3593
[onosfw.git] /
1 /*
2  * Copyright 2015 Open Networking Laboratory
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.onosproject.bgpio.protocol.link_state;
17
18 import java.util.Iterator;
19 import java.util.LinkedList;
20 import java.util.List;
21 import java.util.Objects;
22
23 import org.jboss.netty.buffer.ChannelBuffer;
24 import org.onosproject.bgpio.exceptions.BGPParseException;
25 import org.onosproject.bgpio.types.BGPErrorType;
26 import org.onosproject.bgpio.types.BGPValueType;
27 import org.onosproject.bgpio.types.IPv4AddressTlv;
28 import org.onosproject.bgpio.types.IPv6AddressTlv;
29 import org.onosproject.bgpio.types.LinkLocalRemoteIdentifiersTlv;
30 import org.onosproject.bgpio.types.attr.BgpAttrNodeMultiTopologyId;
31 import org.onosproject.bgpio.util.UnSupportedAttribute;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35 import com.google.common.base.MoreObjects;
36 import com.google.common.base.Preconditions;
37
38 /**
39  * Implementation of local node descriptors, remote node descriptors and link descriptors.
40  */
41 public class BGPLinkLSIdentifier {
42     private static final Logger log = LoggerFactory.getLogger(BGPLinkLSIdentifier.class);
43     public static final short IPV4_INTERFACE_ADDRESS_TYPE = 259;
44     public static final short IPV4_NEIGHBOR_ADDRESS_TYPE = 260;
45     public static final short IPV6_INTERFACE_ADDRESS_TYPE = 261;
46     public static final short IPV6_NEIGHBOR_ADDRESS_TYPE = 262;
47     public static final int TYPE_AND_LEN = 4;
48
49     private NodeDescriptors localNodeDescriptors;
50     private NodeDescriptors remoteNodeDescriptors;
51     private List<BGPValueType> linkDescriptor;
52
53     /**
54      * Initialize fields.
55      */
56     public BGPLinkLSIdentifier() {
57         this.localNodeDescriptors = null;
58         this.remoteNodeDescriptors = null;
59         this.linkDescriptor = null;
60     }
61
62     /**
63      * Constructors to initialize parameters.
64      *
65      * @param localNodeDescriptors local node descriptors
66      * @param remoteNodeDescriptors remote node descriptors
67      * @param linkDescriptor link descriptors
68      */
69     public BGPLinkLSIdentifier(NodeDescriptors localNodeDescriptors, NodeDescriptors remoteNodeDescriptors,
70             LinkedList<BGPValueType> linkDescriptor) {
71         this.localNodeDescriptors = Preconditions.checkNotNull(localNodeDescriptors);
72         this.remoteNodeDescriptors = Preconditions.checkNotNull(remoteNodeDescriptors);
73         this.linkDescriptor = Preconditions.checkNotNull(linkDescriptor);
74     }
75
76     /**
77      * Reads channel buffer and parses link identifier.
78      *
79      * @param cb ChannelBuffer
80      * @param protocolId in linkstate nlri
81      * @return object of BGPLinkLSIdentifier
82      * @throws BGPParseException while parsing link identifier
83      */
84     public static BGPLinkLSIdentifier parseLinkIdendifier(ChannelBuffer cb, byte protocolId) throws BGPParseException {
85         //Parse local node descriptor
86         NodeDescriptors localNodeDescriptors = new NodeDescriptors();
87         localNodeDescriptors = parseNodeDescriptors(cb, NodeDescriptors.LOCAL_NODE_DES_TYPE, protocolId);
88
89         //Parse remote node descriptor
90         NodeDescriptors remoteNodeDescriptors = new NodeDescriptors();
91         remoteNodeDescriptors = parseNodeDescriptors(cb, NodeDescriptors.REMOTE_NODE_DES_TYPE, protocolId);
92
93         //Parse link descriptor
94         LinkedList<BGPValueType> linkDescriptor = new LinkedList<>();
95         linkDescriptor = parseLinkDescriptors(cb);
96         return new BGPLinkLSIdentifier(localNodeDescriptors, remoteNodeDescriptors, linkDescriptor);
97     }
98
99     /**
100      * Parses Local/Remote node descriptors.
101      *
102      * @param cb ChannelBuffer
103      * @param desType descriptor type
104      * @param protocolId protocol identifier
105      * @return object of NodeDescriptors
106      * @throws BGPParseException while parsing Local/Remote node descriptors
107      */
108     public static NodeDescriptors parseNodeDescriptors(ChannelBuffer cb, short desType, byte protocolId)
109             throws BGPParseException {
110         ChannelBuffer tempBuf = cb;
111         short type = cb.readShort();
112         short length = cb.readShort();
113         if (cb.readableBytes() < length) {
114             throw new BGPParseException(BGPErrorType.UPDATE_MESSAGE_ERROR, BGPErrorType.OPTIONAL_ATTRIBUTE_ERROR,
115                     tempBuf.readBytes(cb.readableBytes() + TYPE_AND_LEN));
116         }
117         NodeDescriptors nodeIdentifier = new NodeDescriptors();
118         ChannelBuffer tempCb = cb.readBytes(length);
119
120         if (type == desType) {
121             nodeIdentifier = NodeDescriptors.read(tempCb, length, desType, protocolId);
122         } else {
123             throw new BGPParseException(BGPErrorType.UPDATE_MESSAGE_ERROR, BGPErrorType.MALFORMED_ATTRIBUTE_LIST, null);
124         }
125         return nodeIdentifier;
126     }
127
128     /**
129      * Parses link descriptors.
130      *
131      * @param cb ChannelBuffer
132      * @return list of link descriptors
133      * @throws BGPParseException while parsing link descriptors
134      */
135     public static LinkedList<BGPValueType> parseLinkDescriptors(ChannelBuffer cb) throws BGPParseException {
136         LinkedList<BGPValueType> linkDescriptor = new LinkedList<>();
137         BGPValueType tlv = null;
138         int count = 0;
139
140         while (cb.readableBytes() > 0) {
141             ChannelBuffer tempBuf = cb;
142             short type = cb.readShort();
143             short length = cb.readShort();
144             if (cb.readableBytes() < length) {
145                 throw new BGPParseException(BGPErrorType.UPDATE_MESSAGE_ERROR, BGPErrorType.OPTIONAL_ATTRIBUTE_ERROR,
146                         tempBuf.readBytes(cb.readableBytes() + TYPE_AND_LEN));
147             }
148             ChannelBuffer tempCb = cb.readBytes(length);
149             switch (type) {
150             case LinkLocalRemoteIdentifiersTlv.TYPE:
151                 tlv = LinkLocalRemoteIdentifiersTlv.read(tempCb);
152                 break;
153             case IPV4_INTERFACE_ADDRESS_TYPE:
154                 tlv = IPv4AddressTlv.read(tempCb, IPV4_INTERFACE_ADDRESS_TYPE);
155                 break;
156             case IPV4_NEIGHBOR_ADDRESS_TYPE:
157                 tlv = IPv4AddressTlv.read(tempCb, IPV4_NEIGHBOR_ADDRESS_TYPE);
158                 break;
159             case IPV6_INTERFACE_ADDRESS_TYPE:
160                 tlv = IPv6AddressTlv.read(tempCb, IPV6_INTERFACE_ADDRESS_TYPE);
161                 break;
162             case IPV6_NEIGHBOR_ADDRESS_TYPE:
163                 tlv = IPv6AddressTlv.read(tempCb, IPV6_NEIGHBOR_ADDRESS_TYPE);
164                 break;
165             case BgpAttrNodeMultiTopologyId.ATTRNODE_MULTITOPOLOGY:
166                 tlv = BgpAttrNodeMultiTopologyId.read(tempCb);
167                 count = count++;
168                 //MultiTopologyId TLV cannot repeat more than once
169                 if (count > 1) {
170                     //length + 4 implies data contains type, length and value
171                     throw new BGPParseException(BGPErrorType.UPDATE_MESSAGE_ERROR,
172                             BGPErrorType.OPTIONAL_ATTRIBUTE_ERROR, tempBuf.readBytes(length
173                                     + TYPE_AND_LEN));
174                 }
175                 break;
176             default:
177                 UnSupportedAttribute.skipBytes(tempCb, length);
178             }
179             linkDescriptor.add(tlv);
180         }
181         return linkDescriptor;
182     }
183
184     /**
185      * Returns local node descriptors.
186      *
187      * @return local node descriptors
188      */
189     public NodeDescriptors localNodeDescriptors() {
190         return this.localNodeDescriptors;
191     }
192
193     /**
194      * Returns remote node descriptors.
195      *
196      * @return remote node descriptors
197      */
198     public NodeDescriptors remoteNodeDescriptors() {
199         return this.remoteNodeDescriptors;
200     }
201
202     /**
203      * Returns link descriptors.
204      *
205      * @return link descriptors
206      */
207     public List<BGPValueType> linkDescriptors() {
208         return this.linkDescriptor;
209     }
210
211     @Override
212     public int hashCode() {
213         return Objects.hash(linkDescriptor, localNodeDescriptors, remoteNodeDescriptors);
214     }
215
216     @Override
217     public boolean equals(Object obj) {
218         if (this == obj) {
219             return true;
220         }
221         if (obj instanceof BGPLinkLSIdentifier) {
222             int countObjSubTlv = 0;
223             int countOtherSubTlv = 0;
224             boolean isCommonSubTlv = true;
225             BGPLinkLSIdentifier other = (BGPLinkLSIdentifier) obj;
226             Iterator<BGPValueType> objListIterator = other.linkDescriptor.iterator();
227             countOtherSubTlv = other.linkDescriptor.size();
228             countObjSubTlv = linkDescriptor.size();
229             if (countObjSubTlv != countOtherSubTlv) {
230                 return false;
231             } else {
232                 while (objListIterator.hasNext() && isCommonSubTlv) {
233                     BGPValueType subTlv = objListIterator.next();
234                     isCommonSubTlv = Objects.equals(linkDescriptor.contains(subTlv),
235                             other.linkDescriptor.contains(subTlv));
236                 }
237                 return isCommonSubTlv && Objects.equals(this.localNodeDescriptors, other.localNodeDescriptors)
238                         && Objects.equals(this.remoteNodeDescriptors, other.remoteNodeDescriptors);
239             }
240         }
241         return false;
242     }
243
244     @Override
245     public String toString() {
246         return MoreObjects.toStringHelper(getClass())
247                 .add("localNodeDescriptors", localNodeDescriptors)
248                 .add("remoteNodeDescriptors", remoteNodeDescriptors)
249                 .add("linkDescriptor", linkDescriptor)
250                 .toString();
251     }
252 }