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