b31dac2c6d33e79f87e967bbed355b4acd22cefc
[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.pcepio.types;
17
18 import java.util.Iterator;
19 import java.util.LinkedList;
20 import java.util.ListIterator;
21 import java.util.Objects;
22
23 import org.jboss.netty.buffer.ChannelBuffer;
24 import org.onosproject.pcepio.exceptions.PcepParseException;
25 import org.onosproject.pcepio.protocol.PcepVersion;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28
29 import com.google.common.base.MoreObjects;
30
31 /**
32  * Provides Local TE Node Descriptors TLV which contains Node Descriptor Sub-TLVs.
33  */
34 public class LocalTENodeDescriptorsTlv implements PcepValueType {
35
36     /* REFERENCE :draft-ietf-idr-ls-distribution-10
37      *  0                   1                   2                   3
38       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
39      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
40      |           Type=[TBD8]         |             Length            |
41      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
42      |                                                               |
43      //              Node Descriptor Sub-TLVs (variable)            //
44      |                                                               |
45      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
46      Note: Length is including header here. Refer Routing Universe TLV.
47      */
48
49     protected static final Logger log = LoggerFactory.getLogger(LocalTENodeDescriptorsTlv.class);
50
51     public static final short TYPE = 1637; //TODD:change this TBD8
52     public short hLength;
53
54     public static final int TLV_HEADER_LENGTH = 4;
55     // Node Descriptor Sub-TLVs (variable)
56     private LinkedList<PcepValueType> llNodeDescriptorSubTLVs;
57
58     /**
59      * Constructor to initialize llNodeDescriptorSubTLVs.
60      *
61      * @param llNodeDescriptorSubTLVs LinkedList of PcepValueType
62      */
63     public LocalTENodeDescriptorsTlv(LinkedList<PcepValueType> llNodeDescriptorSubTLVs) {
64         this.llNodeDescriptorSubTLVs = llNodeDescriptorSubTLVs;
65     }
66
67     /**
68      * Returns a new object of LocalTENodeDescriptorsTLV.
69      *
70      * @param llNodeDescriptorSubTLVs linked list of Node Descriptor Sub TLVs
71      * @return object of LocalTENodeDescriptorsTLV
72      */
73     public static LocalTENodeDescriptorsTlv of(final LinkedList<PcepValueType> llNodeDescriptorSubTLVs) {
74         return new LocalTENodeDescriptorsTlv(llNodeDescriptorSubTLVs);
75     }
76
77     /**
78      * Returns Linked List of tlvs.
79      *
80      * @return llNodeDescriptorSubTLVs linked list of Node Descriptor Sub TLV
81      */
82     public LinkedList<PcepValueType> getllNodeDescriptorSubTLVs() {
83         return llNodeDescriptorSubTLVs;
84     }
85
86     @Override
87     public PcepVersion getVersion() {
88         return PcepVersion.PCEP_1;
89     }
90
91     @Override
92     public short getType() {
93         return TYPE;
94     }
95
96     @Override
97     public short getLength() {
98         return hLength;
99     }
100
101     @Override
102     public int hashCode() {
103         return Objects.hash(llNodeDescriptorSubTLVs.hashCode());
104     }
105
106     @Override
107     public boolean equals(Object obj) {
108         if (this == obj) {
109             return true;
110         }
111
112         /*
113          * Here we have a list of Tlv so to compare each sub tlv between the object
114          * we have to take a list iterator so one by one we can get each sub tlv object
115          * and can compare them.
116          * it may be possible that the size of 2 lists is not equal so we have to first check
117          * the size, if both are same then we should check for the subtlv objects otherwise
118          * we should return false.
119          */
120         if (obj instanceof LocalTENodeDescriptorsTlv) {
121             int countObjSubTlv = 0;
122             int countOtherSubTlv = 0;
123             boolean isCommonSubTlv = true;
124             LocalTENodeDescriptorsTlv other = (LocalTENodeDescriptorsTlv) obj;
125             Iterator<PcepValueType> objListIterator = ((LocalTENodeDescriptorsTlv) obj).llNodeDescriptorSubTLVs
126                     .iterator();
127             countObjSubTlv = ((LocalTENodeDescriptorsTlv) obj).llNodeDescriptorSubTLVs.size();
128             countOtherSubTlv = other.llNodeDescriptorSubTLVs.size();
129             if (countObjSubTlv != countOtherSubTlv) {
130                 return false;
131             } else {
132                 while (objListIterator.hasNext() && isCommonSubTlv) {
133                     PcepValueType subTlv = objListIterator.next();
134                     isCommonSubTlv = Objects.equals(llNodeDescriptorSubTLVs.contains(subTlv),
135                             other.llNodeDescriptorSubTLVs.contains(subTlv));
136                 }
137                 return isCommonSubTlv;
138             }
139         }
140         return false;
141     }
142
143     @Override
144     public int write(ChannelBuffer c) {
145         int tlvStartIndex = c.writerIndex();
146         c.writeShort(TYPE);
147         int tlvLenIndex = c.writerIndex();
148         hLength = 0;
149         c.writeShort(0);
150
151         ListIterator<PcepValueType> listIterator = llNodeDescriptorSubTLVs.listIterator();
152
153         while (listIterator.hasNext()) {
154             PcepValueType tlv = listIterator.next();
155             if (tlv == null) {
156                 log.debug("TLV is null from subTlv list");
157                 continue;
158             }
159             tlv.write(c);
160
161             // need to take care of padding
162             int pad = tlv.getLength() % 4;
163
164             if (0 != pad) {
165                 pad = 4 - pad;
166                 for (int i = 0; i < pad; ++i) {
167                     c.writeByte((byte) 0);
168                 }
169             }
170         }
171         hLength = (short) (c.writerIndex() - tlvStartIndex);
172         c.setShort(tlvLenIndex, (hLength - TLV_HEADER_LENGTH));
173         return c.writerIndex() - tlvStartIndex;
174     }
175
176     /**
177      * Reads the channel buffer and returns object of AutonomousSystemTlv.
178      *
179      * @param c input channel buffer
180      * @param hLength length of subtlvs.
181      * @return object of AutonomousSystemTlv
182      * @throws PcepParseException if mandatory fields are missing
183      */
184     public static PcepValueType read(ChannelBuffer c, short hLength) throws PcepParseException {
185
186         // Node Descriptor Sub-TLVs (variable)
187         LinkedList<PcepValueType> llNodeDescriptorSubTLVs = new LinkedList<>();
188
189         ChannelBuffer tempCb = c.readBytes(hLength);
190
191         while (TLV_HEADER_LENGTH <= tempCb.readableBytes()) {
192
193             PcepValueType tlv;
194             short hType = tempCb.readShort();
195             int iValue = 0;
196             short length = tempCb.readShort();
197
198             switch (hType) {
199
200             case AutonomousSystemTlv.TYPE:
201                 iValue = tempCb.readInt();
202                 tlv = new AutonomousSystemTlv(iValue);
203                 break;
204             case BGPLSidentifierTlv.TYPE:
205                 iValue = tempCb.readInt();
206                 tlv = new BGPLSidentifierTlv(iValue);
207                 break;
208             case OSPFareaIDsubTlv.TYPE:
209                 iValue = tempCb.readInt();
210                 tlv = new OSPFareaIDsubTlv(iValue);
211                 break;
212             case RouterIDSubTlv.TYPE:
213                 tlv = RouterIDSubTlv.read(tempCb, length);
214                 break;
215
216             default:
217                 throw new PcepParseException("Unsupported Sub TLV type :" + hType);
218             }
219
220             // Check for the padding
221             int pad = length % 4;
222             if (0 < pad) {
223                 pad = 4 - pad;
224                 if (pad <= tempCb.readableBytes()) {
225                     tempCb.skipBytes(pad);
226                 }
227             }
228
229             llNodeDescriptorSubTLVs.add(tlv);
230         }
231
232         if (0 < tempCb.readableBytes()) {
233             throw new PcepParseException("Sub Tlv parsing error. Extra bytes received.");
234         }
235         return new LocalTENodeDescriptorsTlv(llNodeDescriptorSubTLVs);
236     }
237
238     @Override
239     public String toString() {
240         return MoreObjects.toStringHelper(getClass())
241                 .add("Type", TYPE)
242                 .add("Length", hLength)
243                 .add("NodeDescriptorSubTLVs", llNodeDescriptorSubTLVs)
244                 .toString();
245     }
246 }