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