3967a2217a1f0cef3c858162ba4757b1a9e24ad9
[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.linkstate;
17
18 import java.util.Iterator;
19 import java.util.LinkedList;
20 import java.util.List;
21 import java.util.ListIterator;
22 import java.util.Objects;
23
24 import org.jboss.netty.buffer.ChannelBuffer;
25 import org.onosproject.bgpio.exceptions.BgpParseException;
26 import org.onosproject.bgpio.types.BgpErrorType;
27 import org.onosproject.bgpio.types.BgpValueType;
28 import org.onosproject.bgpio.types.IPv4AddressTlv;
29 import org.onosproject.bgpio.types.IPv6AddressTlv;
30 import org.onosproject.bgpio.types.LinkLocalRemoteIdentifiersTlv;
31 import org.onosproject.bgpio.types.attr.BgpAttrNodeMultiTopologyId;
32 import org.onosproject.bgpio.util.Constants;
33 import org.onosproject.bgpio.util.UnSupportedAttribute;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37 import com.google.common.base.MoreObjects;
38 import com.google.common.base.Preconditions;
39
40 /**
41  * Implementation of local node descriptors, remote node descriptors and link descriptors.
42  */
43 public class BgpLinkLSIdentifier implements Comparable<Object> {
44     private static final Logger log = LoggerFactory.getLogger(BgpLinkLSIdentifier.class);
45     public static final short IPV4_INTERFACE_ADDRESS_TYPE = 259;
46     public static final short IPV4_NEIGHBOR_ADDRESS_TYPE = 260;
47     public static final short IPV6_INTERFACE_ADDRESS_TYPE = 261;
48     public static final short IPV6_NEIGHBOR_ADDRESS_TYPE = 262;
49
50     private NodeDescriptors localNodeDescriptors;
51     private NodeDescriptors remoteNodeDescriptors;
52     private List<BgpValueType> linkDescriptor;
53
54     /**
55      * Initialize fields.
56      */
57     public BgpLinkLSIdentifier() {
58         this.localNodeDescriptors = null;
59         this.remoteNodeDescriptors = null;
60         this.linkDescriptor = null;
61     }
62
63     /**
64      * Constructors to initialize parameters.
65      *
66      * @param localNodeDescriptors local node descriptors
67      * @param remoteNodeDescriptors remote node descriptors
68      * @param linkDescriptor link descriptors
69      */
70     public BgpLinkLSIdentifier(NodeDescriptors localNodeDescriptors, NodeDescriptors remoteNodeDescriptors,
71             LinkedList<BgpValueType> linkDescriptor) {
72         this.localNodeDescriptors = Preconditions.checkNotNull(localNodeDescriptors);
73         this.remoteNodeDescriptors = Preconditions.checkNotNull(remoteNodeDescriptors);
74         this.linkDescriptor = Preconditions.checkNotNull(linkDescriptor);
75     }
76
77     /**
78      * Reads channel buffer and parses link identifier.
79      *
80      * @param cb ChannelBuffer
81      * @param protocolId in linkstate nlri
82      * @return object of BGPLinkLSIdentifier
83      * @throws BgpParseException while parsing link identifier
84      */
85     public static BgpLinkLSIdentifier parseLinkIdendifier(ChannelBuffer cb, byte protocolId) throws BgpParseException {
86         //Parse local node descriptor
87         NodeDescriptors localNodeDescriptors = new NodeDescriptors();
88         localNodeDescriptors = parseNodeDescriptors(cb, NodeDescriptors.LOCAL_NODE_DES_TYPE, protocolId);
89
90         //Parse remote node descriptor
91         NodeDescriptors remoteNodeDescriptors = new NodeDescriptors();
92         remoteNodeDescriptors = parseNodeDescriptors(cb, NodeDescriptors.REMOTE_NODE_DES_TYPE, protocolId);
93
94         //Parse link descriptor
95         LinkedList<BgpValueType> linkDescriptor = new LinkedList<>();
96         linkDescriptor = parseLinkDescriptors(cb);
97         return new BgpLinkLSIdentifier(localNodeDescriptors, remoteNodeDescriptors, linkDescriptor);
98     }
99
100     /**
101      * Parses Local/Remote node descriptors.
102      *
103      * @param cb ChannelBuffer
104      * @param desType descriptor type
105      * @param protocolId protocol identifier
106      * @return object of NodeDescriptors
107      * @throws BgpParseException while parsing Local/Remote node descriptors
108      */
109     public static NodeDescriptors parseNodeDescriptors(ChannelBuffer cb, short desType, byte protocolId)
110             throws BgpParseException {
111         log.debug("parse Node descriptors");
112         ChannelBuffer tempBuf = cb.copy();
113         short type = cb.readShort();
114         short length = cb.readShort();
115         if (cb.readableBytes() < length) {
116             throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.OPTIONAL_ATTRIBUTE_ERROR,
117                     tempBuf.readBytes(cb.readableBytes() + Constants.TYPE_AND_LEN_AS_SHORT));
118         }
119         NodeDescriptors nodeIdentifier = new NodeDescriptors();
120         ChannelBuffer tempCb = cb.readBytes(length);
121
122         if (type == desType) {
123             nodeIdentifier = NodeDescriptors.read(tempCb, length, desType, protocolId);
124         } else {
125             throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.MALFORMED_ATTRIBUTE_LIST, null);
126         }
127         return nodeIdentifier;
128     }
129
130     /**
131      * Parses link descriptors.
132      *
133      * @param cb ChannelBuffer
134      * @return list of link descriptors
135      * @throws BgpParseException while parsing link descriptors
136      */
137     public static LinkedList<BgpValueType> parseLinkDescriptors(ChannelBuffer cb) throws BgpParseException {
138         LinkedList<BgpValueType> linkDescriptor = new LinkedList<>();
139         BgpValueType tlv = null;
140         int count = 0;
141
142         while (cb.readableBytes() > 0) {
143             ChannelBuffer tempBuf = cb.copy();
144             short type = cb.readShort();
145             short length = cb.readShort();
146             if (cb.readableBytes() < length) {
147                 throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.OPTIONAL_ATTRIBUTE_ERROR,
148                         tempBuf.readBytes(cb.readableBytes() + Constants.TYPE_AND_LEN_AS_SHORT));
149             }
150             ChannelBuffer tempCb = cb.readBytes(length);
151             switch (type) {
152             case LinkLocalRemoteIdentifiersTlv.TYPE:
153                 tlv = LinkLocalRemoteIdentifiersTlv.read(tempCb);
154                 break;
155             case IPV4_INTERFACE_ADDRESS_TYPE:
156                 tlv = IPv4AddressTlv.read(tempCb, IPV4_INTERFACE_ADDRESS_TYPE);
157                 break;
158             case IPV4_NEIGHBOR_ADDRESS_TYPE:
159                 tlv = IPv4AddressTlv.read(tempCb, IPV4_NEIGHBOR_ADDRESS_TYPE);
160                 break;
161             case IPV6_INTERFACE_ADDRESS_TYPE:
162                 tlv = IPv6AddressTlv.read(tempCb, IPV6_INTERFACE_ADDRESS_TYPE);
163                 break;
164             case IPV6_NEIGHBOR_ADDRESS_TYPE:
165                 tlv = IPv6AddressTlv.read(tempCb, IPV6_NEIGHBOR_ADDRESS_TYPE);
166                 break;
167             case BgpAttrNodeMultiTopologyId.ATTRNODE_MULTITOPOLOGY:
168                 tlv = BgpAttrNodeMultiTopologyId.read(tempCb);
169                 count = count++;
170                 //MultiTopologyId TLV cannot repeat more than once
171                 if (count > 1) {
172                     //length + 4 implies data contains type, length and value
173                     throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR,
174                             BgpErrorType.OPTIONAL_ATTRIBUTE_ERROR, tempBuf.readBytes(length
175                                     + Constants.TYPE_AND_LEN_AS_SHORT));
176                 }
177                 break;
178             default:
179                 UnSupportedAttribute.skipBytes(tempCb, length);
180             }
181             linkDescriptor.add(tlv);
182         }
183         return linkDescriptor;
184     }
185
186     /**
187      * Returns local node descriptors.
188      *
189      * @return local node descriptors
190      */
191     public NodeDescriptors localNodeDescriptors() {
192         return this.localNodeDescriptors;
193     }
194
195     /**
196      * Returns remote node descriptors.
197      *
198      * @return remote node descriptors
199      */
200     public NodeDescriptors remoteNodeDescriptors() {
201         return this.remoteNodeDescriptors;
202     }
203
204     /**
205      * Returns link descriptors.
206      *
207      * @return link descriptors
208      */
209     public List<BgpValueType> linkDescriptors() {
210         return this.linkDescriptor;
211     }
212
213     @Override
214     public int hashCode() {
215         return Objects.hash(linkDescriptor, localNodeDescriptors, remoteNodeDescriptors);
216     }
217
218     @Override
219     public boolean equals(Object obj) {
220         if (this == obj) {
221             return true;
222         }
223         if (obj instanceof BgpLinkLSIdentifier) {
224             int countObjSubTlv = 0;
225             int countOtherSubTlv = 0;
226             boolean isCommonSubTlv = true;
227             BgpLinkLSIdentifier other = (BgpLinkLSIdentifier) obj;
228             Iterator<BgpValueType> objListIterator = other.linkDescriptor.iterator();
229             countOtherSubTlv = other.linkDescriptor.size();
230             countObjSubTlv = linkDescriptor.size();
231             if (countObjSubTlv != countOtherSubTlv) {
232                 return false;
233             } else {
234                 while (objListIterator.hasNext() && isCommonSubTlv) {
235                     BgpValueType subTlv = objListIterator.next();
236                     if (linkDescriptor.contains(subTlv) && other.linkDescriptor.contains(subTlv)) {
237                         isCommonSubTlv = Objects.equals(linkDescriptor.get(linkDescriptor.indexOf(subTlv)),
238                                          other.linkDescriptor.get(other.linkDescriptor.indexOf(subTlv)));
239                     } else {
240                         isCommonSubTlv = false;
241                     }
242                 }
243                 return isCommonSubTlv && Objects.equals(this.localNodeDescriptors, other.localNodeDescriptors)
244                         && Objects.equals(this.remoteNodeDescriptors, other.remoteNodeDescriptors);
245             }
246         }
247         return false;
248     }
249
250     @Override
251     public String toString() {
252         return MoreObjects.toStringHelper(getClass())
253                 .add("localNodeDescriptors", localNodeDescriptors)
254                 .add("remoteNodeDescriptors", remoteNodeDescriptors)
255                 .add("linkDescriptor", linkDescriptor)
256                 .toString();
257     }
258
259     @Override
260     public int compareTo(Object o) {
261         if (this.equals(o)) {
262             return 0;
263         }
264         int result = this.localNodeDescriptors.compareTo(((BgpLinkLSIdentifier) o).localNodeDescriptors);
265         if (result != 0) {
266             return result;
267         } else if (this.remoteNodeDescriptors.compareTo(((BgpLinkLSIdentifier) o).remoteNodeDescriptors) != 0) {
268             return this.remoteNodeDescriptors.compareTo(((BgpLinkLSIdentifier) o).remoteNodeDescriptors);
269         } else {
270             int countOtherSubTlv = ((BgpLinkLSIdentifier) o).linkDescriptor.size();
271             int countObjSubTlv = linkDescriptor.size();
272             if (countOtherSubTlv != countObjSubTlv) {
273                 if (countOtherSubTlv > countObjSubTlv) {
274                     return 1;
275                 } else {
276                     return -1;
277                 }
278            }
279             ListIterator<BgpValueType> listIterator = linkDescriptor.listIterator();
280             ListIterator<BgpValueType> listIteratorOther = ((BgpLinkLSIdentifier) o).linkDescriptor.listIterator();
281             while (listIterator.hasNext()) {
282                 BgpValueType tlv = listIterator.next();
283                 BgpValueType tlv1 = listIteratorOther.next();
284                 if (linkDescriptor.contains(tlv) && ((BgpLinkLSIdentifier) o).linkDescriptor.contains(tlv1)) {
285                     int res = linkDescriptor.get(linkDescriptor.indexOf(tlv)).compareTo(
286                             ((BgpLinkLSIdentifier) o).linkDescriptor.get(((BgpLinkLSIdentifier) o).linkDescriptor
287                                     .indexOf(tlv1)));
288                     if (res != 0) {
289                         return res;
290                     }
291                 }
292             }
293         }
294         return 0;
295     }
296 }