9e4be9115a5b12d78541666f801e3fba32706651
[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.pcepio.protocol.ver1;
18
19 import java.util.LinkedList;
20 import java.util.ListIterator;
21
22 import org.jboss.netty.buffer.ChannelBuffer;
23 import org.onosproject.pcepio.exceptions.PcepParseException;
24 import org.onosproject.pcepio.protocol.PcepLabelRangeObject;
25 import org.onosproject.pcepio.types.PathSetupTypeTlv;
26 import org.onosproject.pcepio.types.PcepObjectHeader;
27 import org.onosproject.pcepio.types.PcepValueType;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 import com.google.common.base.MoreObjects;
32
33 /**
34  * Provides PCEP label range object.
35  */
36 public class PcepLabelRangeObjectVer1 implements PcepLabelRangeObject {
37
38     /*
39      * ref : draft-zhao-pce-pcep-extension-for-pce-controller-01, section : 7.2
40             0                   1                   2                     3
41             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
42            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
43            | label type    | range size                                    |
44            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
45            |                        label base                             |
46            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
47            |                                                               |
48            //                      Optional TLVs                           //
49            |                                                               |
50            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
51
52                                LABEL-RANGE Object
53      */
54     protected static final Logger log = LoggerFactory.getLogger(PcepLabelRangeObjectVer1.class);
55
56     public static final byte LABEL_RANGE_OBJ_TYPE = 1;
57     public static final byte LABEL_RANGE_OBJ_CLASS = 60; //to be defined
58     public static final byte LABEL_RANGE_OBJECT_VERSION = 1;
59     public static final short LABEL_RANGE_OBJ_MINIMUM_LENGTH = 12;
60     public static final int MINIMUM_COMMON_HEADER_LENGTH = 4;
61     //P flag and I flag must be set to 0
62     static final PcepObjectHeader DEFAULT_LABELRANGE_OBJECT_HEADER = new PcepObjectHeader(LABEL_RANGE_OBJ_CLASS,
63             LABEL_RANGE_OBJ_TYPE, PcepObjectHeader.REQ_OBJ_OPTIONAL_PROCESS, PcepObjectHeader.RSP_OBJ_PROCESSED,
64             LABEL_RANGE_OBJ_MINIMUM_LENGTH);
65
66     private PcepObjectHeader labelRangeObjHeader;
67     private byte labelType;
68     private int rangeSize;
69     private int labelBase;
70     //Optional TLV
71     private LinkedList<PcepValueType> llOptionalTlv;
72
73     /**
74      * Constructor to initialize parameters for PCEP label range object.
75      *
76      * @param labelRangeObjHeader label range object header
77      * @param labelType label type
78      * @param rangeSize range size
79      * @param labelBase label base
80      * @param llOptionalTlv list of optional tlvs
81      */
82     public PcepLabelRangeObjectVer1(PcepObjectHeader labelRangeObjHeader, byte labelType, int rangeSize, int labelBase,
83             LinkedList<PcepValueType> llOptionalTlv) {
84         this.labelRangeObjHeader = labelRangeObjHeader;
85         this.labelType = labelType;
86         this.rangeSize = rangeSize;
87         this.llOptionalTlv = llOptionalTlv;
88         this.labelBase = labelBase;
89     }
90
91     @Override
92     public void setLabelRangeObjHeader(PcepObjectHeader obj) {
93         this.labelRangeObjHeader = obj;
94     }
95
96     @Override
97     public void setLabelType(byte labelType) {
98         this.labelType = labelType;
99     }
100
101     @Override
102     public void setRangeSize(int rangeSize) {
103         this.rangeSize = rangeSize;
104     }
105
106     @Override
107     public void setLabelBase(int labelBase) {
108         this.labelBase = labelBase;
109     }
110
111     @Override
112     public PcepObjectHeader getLabelRangeObjHeader() {
113         return this.labelRangeObjHeader;
114     }
115
116     @Override
117     public byte getLabelType() {
118         return this.labelType;
119     }
120
121     @Override
122     public int getRangeSize() {
123         return this.rangeSize;
124     }
125
126     @Override
127     public int getLabelBase() {
128         return this.labelBase;
129     }
130
131     /**
132      * Reads from the channel buffer and returns object of  PcepLabelRangeObject.
133      *
134      * @param cb of type channel buffer
135      * @return object of  PcepLabelRangeObject
136      * @throws PcepParseException when fails to read from channel buffer
137      */
138     public static PcepLabelRangeObject read(ChannelBuffer cb) throws PcepParseException {
139
140         PcepObjectHeader labelRangeObjHeader;
141         byte labelType;
142         int rangeSize;
143         int labelBase;
144
145         LinkedList<PcepValueType> llOptionalTlv = new LinkedList<>();
146
147         labelRangeObjHeader = PcepObjectHeader.read(cb);
148
149         //take only LabelRangeObject buffer.
150         ChannelBuffer tempCb = cb.readBytes(labelRangeObjHeader.getObjLen() - MINIMUM_COMMON_HEADER_LENGTH);
151         int temp = 0;
152         temp = tempCb.readInt();
153         rangeSize = temp & 0x00FFFFFF;
154         labelType = (byte) (temp >> 24);
155         labelBase = tempCb.readInt();
156         llOptionalTlv = parseOptionalTlv(tempCb);
157         return new PcepLabelRangeObjectVer1(labelRangeObjHeader, labelType, rangeSize, labelBase, llOptionalTlv);
158     }
159
160     @Override
161     public int write(ChannelBuffer cb) throws PcepParseException {
162
163         int objStartIndex = cb.writerIndex();
164
165         //write common header
166         int objLenIndex = labelRangeObjHeader.write(cb);
167         int temp = 0;
168         temp = labelType;
169         temp = temp << 24;
170         temp = temp | rangeSize;
171         cb.writeInt(temp);
172
173         // Add optional TLV
174         if (!packOptionalTlv(cb)) {
175             throw new PcepParseException("Error while writing Optional tlv.");
176         }
177
178         //now write LabelRange Object Length
179         cb.setShort(objLenIndex, (short) (cb.writerIndex() - objStartIndex));
180         return cb.writerIndex() - objStartIndex;
181     }
182
183     /**
184      * Returns list of optional tlvs.
185      *
186      * @param cb of type channle buffer
187      * @return list of optional tlvs
188      * @throws PcepParseException whne fails to parse list of optional tlvs
189      */
190     public static LinkedList<PcepValueType> parseOptionalTlv(ChannelBuffer cb) throws PcepParseException {
191
192         LinkedList<PcepValueType> llOutOptionalTlv = new LinkedList<>();
193
194         while (MINIMUM_COMMON_HEADER_LENGTH <= cb.readableBytes()) {
195
196             PcepValueType tlv;
197             int iValue;
198             short hType = cb.readShort();
199             short hLength = cb.readShort();
200
201             switch (hType) {
202
203             case PathSetupTypeTlv.TYPE:
204                 iValue = cb.readInt();
205                 tlv = new PathSetupTypeTlv(iValue);
206                 break;
207
208             default:
209                 throw new PcepParseException("Unsupported TLV in LabelRange Object.");
210             }
211
212             // Check for the padding
213             int pad = hLength % 4;
214             if (0 < pad) {
215                 pad = 4 - pad;
216                 if (pad <= cb.readableBytes()) {
217                     cb.skipBytes(pad);
218                 }
219             }
220             llOutOptionalTlv.add(tlv);
221         }
222         return llOutOptionalTlv;
223     }
224
225     /**
226      * Pack optional tlvs.
227      *
228      * @param cb of channel buffer
229      * @return true
230      */
231     protected boolean packOptionalTlv(ChannelBuffer cb) {
232
233         ListIterator<PcepValueType> listIterator = llOptionalTlv.listIterator();
234
235         while (listIterator.hasNext()) {
236             PcepValueType tlv = listIterator.next();
237
238             if (tlv == null) {
239                 log.debug("tlv is null from OptionalTlv list");
240                 continue;
241             }
242             tlv.write(cb);
243
244             // need to take care of padding
245             int pad = tlv.getLength() % 4;
246             if (0 != pad) {
247                 pad = 4 - pad;
248                 for (int i = 0; i < pad; ++i) {
249                     cb.writeByte((byte) 0);
250                 }
251             }
252         }
253         return true;
254     }
255
256     /**
257      * Builder class for PCEP label range object.
258      */
259     public static class Builder implements PcepLabelRangeObject.Builder {
260         private boolean bIsHeaderSet = false;
261         private boolean bIsLabelType = false;
262         private boolean bIsRangeSize = false;
263         private boolean bIsLabelBase = false;
264
265         byte labelType;
266         int rangeSize;
267         int labelBase;
268         private boolean bIsPFlagSet = false;
269         private boolean bPFlag;
270
271         private boolean bIsIFlagSet = false;
272         private boolean bIFlag;
273         private PcepObjectHeader labelRangeObjHeader;
274
275         LinkedList<PcepValueType> llOptionalTlv = new LinkedList<>();
276
277         @Override
278         public PcepLabelRangeObject build() throws PcepParseException {
279             PcepObjectHeader labelRangeObjHeader = this.bIsHeaderSet ? this.labelRangeObjHeader
280                     : DEFAULT_LABELRANGE_OBJECT_HEADER;
281
282             if (!this.bIsLabelType) {
283                 throw new PcepParseException("LabelType NOT Set while building label range object.");
284             }
285
286             if (!this.bIsRangeSize) {
287                 throw new PcepParseException("RangeSize NOT Set while building label range object.");
288             }
289
290             if (!this.bIsLabelBase) {
291                 throw new PcepParseException("LabelBase NOT Set while building label range object.");
292             }
293
294             if (bIsPFlagSet) {
295                 labelRangeObjHeader.setPFlag(bPFlag);
296             }
297
298             if (bIsIFlagSet) {
299                 labelRangeObjHeader.setIFlag(bIFlag);
300             }
301             return new PcepLabelRangeObjectVer1(labelRangeObjHeader, this.labelType, this.rangeSize, this.labelBase,
302                     this.llOptionalTlv);
303         }
304
305         @Override
306         public PcepObjectHeader getLabelRangeObjHeader() {
307             return this.labelRangeObjHeader;
308         }
309
310         @Override
311         public Builder setLabelRangeObjHeader(PcepObjectHeader obj) {
312             this.labelRangeObjHeader = obj;
313             this.bIsHeaderSet = true;
314             return this;
315         }
316
317         @Override
318         public byte getLabelType() {
319             return this.labelType;
320         }
321
322         @Override
323         public Builder setLabelType(byte labelType) {
324             this.labelType = labelType;
325             this.bIsLabelType = true;
326             return this;
327         }
328
329         @Override
330         public int getRangeSize() {
331             return this.rangeSize;
332         }
333
334         @Override
335         public Builder setRangeSize(int rangeSize) {
336             this.rangeSize = rangeSize;
337             this.bIsRangeSize = true;
338             return this;
339         }
340
341         @Override
342         public int getLabelBase() {
343             return this.labelBase;
344         }
345
346         @Override
347         public Builder setLabelBase(int labelBase) {
348             this.labelBase = labelBase;
349             this.bIsLabelBase = true;
350             return this;
351         }
352
353         @Override
354         public Builder setPFlag(boolean value) {
355             this.bPFlag = value;
356             this.bIsPFlagSet = true;
357             return this;
358         }
359
360         @Override
361         public Builder setIFlag(boolean value) {
362             this.bIFlag = value;
363             this.bIsIFlagSet = true;
364             return this;
365         }
366     }
367
368     @Override
369     public String toString() {
370         return MoreObjects.toStringHelper(getClass())
371                 .add("LabelType", labelType)
372                 .add("rangeSize", rangeSize)
373                 .add("labelBase", labelBase)
374                 .add("optionalTlvList", llOptionalTlv)
375                 .toString();
376     }
377 }