2b319c12a9683dcaebec161de283b96ca305f9bf
[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.PcepLspObject;
25 import org.onosproject.pcepio.types.PcepErrorDetailInfo;
26 import org.onosproject.pcepio.types.PcepObjectHeader;
27 import org.onosproject.pcepio.types.PcepValueType;
28 import org.onosproject.pcepio.types.StatefulIPv4LspIdentidiersTlv;
29 import org.onosproject.pcepio.types.StatefulLspDbVerTlv;
30 import org.onosproject.pcepio.types.StatefulLspErrorCodeTlv;
31 import org.onosproject.pcepio.types.StatefulRsvpErrorSpecTlv;
32 import org.onosproject.pcepio.types.SymbolicPathNameTlv;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36 import com.google.common.base.MoreObjects;
37
38 /**
39  * Provides PCEP lsp object.
40  */
41 public class PcepLspObjectVer1 implements PcepLspObject {
42
43     /*
44      message format.
45      Reference : draft-ietf-pce-stateful-pce-11, section 7.3.
46       0                   1                   2                   3
47       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
48      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
49      | Object-Class  |   OT  |Res|P|I|   Object Length (bytes)       |
50      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
51      |                PLSP-ID                |    Flag |    O|A|R|S|D|
52      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
53      //                        TLVs                                 //
54      |                                                               |
55      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
56
57                      The LSP Object format
58      */
59     protected static final Logger log = LoggerFactory.getLogger(PcepLspObjectVer1.class);
60
61     public static final byte LSP_OBJ_TYPE = 1;
62     public static final byte LSP_OBJ_CLASS = 32;
63     public static final byte LSP_OBJECT_VERSION = 1;
64
65     // LSP_OBJ_MINIMUM_LENGTH = CommonHeaderLen(4)+ LspObjectHeaderLen(4)+TlvAssumedMinLength(8)
66     public static final short LSP_OBJ_MINIMUM_LENGTH = 16;
67
68     public static final int DEFAULT_PLSPID = 0;
69     public static final byte DEFAULT_OFLAG = 1;
70     public static final boolean DEFAULT_AFLAG = false;
71     public static final boolean DEFAULT_RFLAG = false;
72     public static final boolean DEFAULT_SFLAG = false;
73     public static final boolean DEFAULT_DFLAG = false;
74     public static final int OBJECT_HEADER_LENGTH = 4;
75     public static final int PLSPID_SHIFT_VALUE = 12;
76     public static final int OFLAG_SHIFT_VALUE = 4;
77     public static final int AFLAG_SHIFT_VALUE = 3;
78     public static final int RFLAG_SHIFT_VALUE = 2;
79     public static final int SFLAG_SHIFT_VALUE = 1;
80     public static final int PLSPID_TEMP_SHIFT_VALUE = 0xFFFFF000;
81     public static final int OFLAG_TEMP_SHIFT_VALUE = 0x70;
82     public static final int AFLAG_TEMP_SHIFT_VALUE = 0x08;
83     public static final int RFLAG_TEMP_SHIFT_VALUE = 0x04;
84     public static final int SFLAG_TEMP_SHIFT_VALUE = 0x02;
85     public static final int DFLAG_TEMP_SHIFT_VALUE = 0x01;
86     public static final int BIT_SET = 1;
87     public static final int BIT_RESET = 0;
88     public static final int MINIMUM_COMMON_HEADER_LENGTH = 4;
89
90     static final PcepObjectHeader DEFAULT_LSP_OBJECT_HEADER = new PcepObjectHeader(LSP_OBJ_CLASS, LSP_OBJ_TYPE,
91             PcepObjectHeader.REQ_OBJ_OPTIONAL_PROCESS, PcepObjectHeader.RSP_OBJ_PROCESSED, LSP_OBJ_MINIMUM_LENGTH);
92
93     private PcepObjectHeader lspObjHeader;
94     private int iPlspId;
95     // 3-bits
96     private byte yOFlag;
97     private boolean bAFlag;
98     private boolean bRFlag;
99     private boolean bSFlag;
100     private boolean bDFlag;
101
102     // Optional TLV
103     private LinkedList<PcepValueType> llOptionalTlv;
104
105     /**
106      * Constructor to initialize all the member variables.
107      *
108      * @param lspObjHeader lsp object header
109      * @param iPlspId plsp id
110      * @param yOFlag O flag
111      * @param bAFlag A flag
112      * @param bRFlag R flag
113      * @param bSFlag S flag
114      * @param bDFlag D flag
115      * @param llOptionalTlv list of optional tlv
116      */
117     public PcepLspObjectVer1(PcepObjectHeader lspObjHeader, int iPlspId, byte yOFlag, boolean bAFlag, boolean bRFlag,
118             boolean bSFlag, boolean bDFlag, LinkedList<PcepValueType> llOptionalTlv) {
119
120         this.lspObjHeader = lspObjHeader;
121         this.iPlspId = iPlspId;
122         this.yOFlag = yOFlag;
123         this.bAFlag = bAFlag;
124         this.bRFlag = bRFlag;
125         this.bSFlag = bSFlag;
126         this.bDFlag = bDFlag;
127         this.llOptionalTlv = llOptionalTlv;
128     }
129
130     /**
131      * Sets lsp Object Header.
132      *
133      * @param obj lsp object header
134      */
135     public void setLspObjHeader(PcepObjectHeader obj) {
136         this.lspObjHeader = obj;
137     }
138
139     @Override
140     public void setPlspId(int iPlspId) {
141         this.iPlspId = iPlspId;
142     }
143
144     @Override
145     public void setOFlag(byte yOFlag) {
146         this.yOFlag = yOFlag;
147     }
148
149     @Override
150     public void setAFlag(boolean bAFlag) {
151         this.bAFlag = bAFlag;
152     }
153
154     @Override
155     public void setRFlag(boolean bRFlag) {
156         this.bRFlag = bRFlag;
157     }
158
159     @Override
160     public void setSFlag(boolean bSFlag) {
161         this.bSFlag = bSFlag;
162     }
163
164     @Override
165     public void setDFlag(boolean bDFlag) {
166         this.bDFlag = bDFlag;
167     }
168
169     /**
170      * Returns lsp object header.
171      *
172      * @return lspObjHeader
173      */
174     public PcepObjectHeader getLspObjHeader() {
175         return this.lspObjHeader;
176     }
177
178     @Override
179     public int getPlspId() {
180         return this.iPlspId;
181     }
182
183     @Override
184     public byte getOFlag() {
185         return this.yOFlag;
186     }
187
188     @Override
189     public boolean getAFlag() {
190         return this.bAFlag;
191     }
192
193     @Override
194     public boolean getRFlag() {
195         return this.bRFlag;
196     }
197
198     @Override
199     public boolean getSFlag() {
200         return this.bSFlag;
201     }
202
203     @Override
204     public boolean getDFlag() {
205         return this.bDFlag;
206     }
207
208     @Override
209     public LinkedList<PcepValueType> getOptionalTlv() {
210         return this.llOptionalTlv;
211     }
212
213     @Override
214     public void setOptionalTlv(LinkedList<PcepValueType> llOptionalTlv) {
215         this.llOptionalTlv = llOptionalTlv;
216     }
217
218     /**
219      * Parse channel buffer and returns object of PcepLspObject.
220      *
221      * @param cb of type channel buffer
222      * @return object of  PcepLspObject
223      * @throws PcepParseException when lsp object is not present in channel buffer
224      */
225     public static PcepLspObject read(ChannelBuffer cb) throws PcepParseException {
226
227         PcepObjectHeader lspObjHeader;
228         int iPlspId;
229         // 3-bits
230         byte yOFlag;
231         boolean bAFlag;
232         boolean bRFlag;
233         boolean bSFlag;
234         boolean bDFlag;
235
236         // Optional TLV
237         LinkedList<PcepValueType> llOptionalTlv = new LinkedList<>();
238
239         lspObjHeader = PcepObjectHeader.read(cb);
240
241         if (lspObjHeader.getObjClass() != PcepLspObjectVer1.LSP_OBJ_CLASS) {
242             throw new PcepParseException(PcepErrorDetailInfo.ERROR_TYPE_6, PcepErrorDetailInfo.ERROR_VALUE_8);
243         }
244         //take only LspObject buffer.
245         ChannelBuffer tempCb = cb.readBytes(lspObjHeader.getObjLen() - OBJECT_HEADER_LENGTH);
246
247         Integer iTemp = tempCb.readInt();
248         iPlspId = (iTemp & PLSPID_TEMP_SHIFT_VALUE) >> PLSPID_SHIFT_VALUE;
249         Integer iX = (iTemp & OFLAG_TEMP_SHIFT_VALUE) >> OFLAG_SHIFT_VALUE;
250         yOFlag = iX.byteValue();
251         iX = (iTemp & AFLAG_TEMP_SHIFT_VALUE) >> AFLAG_SHIFT_VALUE;
252         bAFlag = iX > 0;
253         iX = (iTemp & RFLAG_TEMP_SHIFT_VALUE) >> RFLAG_SHIFT_VALUE;
254         bRFlag = iX > 0;
255         iX = (iTemp & SFLAG_TEMP_SHIFT_VALUE) >> SFLAG_SHIFT_VALUE;
256         bSFlag = iX > 0;
257         iX = iTemp & DFLAG_TEMP_SHIFT_VALUE;
258         bDFlag = iX > 0;
259
260         // parse optional TLV
261         llOptionalTlv = parseOptionalTlv(tempCb);
262
263         return new PcepLspObjectVer1(lspObjHeader, iPlspId, yOFlag, bAFlag, bRFlag, bSFlag, bDFlag, llOptionalTlv);
264     }
265
266     @Override
267     public int write(ChannelBuffer cb) throws PcepParseException {
268
269         //write Object header
270         int objStartIndex = cb.writerIndex();
271
272         int objLenIndex = lspObjHeader.write(cb);
273
274         if (objLenIndex <= 0) {
275             throw new PcepParseException("Failed to write lsp object header. Index " + objLenIndex);
276         }
277
278         int iTemp = iPlspId << PLSPID_SHIFT_VALUE;
279         iTemp = iTemp | (yOFlag << OFLAG_SHIFT_VALUE);
280         byte bFlag;
281         iTemp = bAFlag ? (iTemp | AFLAG_TEMP_SHIFT_VALUE) : iTemp;
282
283         bFlag = (bRFlag) ? (byte) BIT_SET : BIT_RESET;
284         iTemp = iTemp | (bFlag << RFLAG_SHIFT_VALUE);
285         bFlag = (bSFlag) ? (byte) BIT_SET : BIT_RESET;
286         iTemp = iTemp | (bFlag << SFLAG_SHIFT_VALUE);
287         bFlag = (bDFlag) ? (byte) BIT_SET : BIT_RESET;
288         iTemp = iTemp | bFlag;
289         cb.writeInt(iTemp);
290
291         // Add optional TLV
292         packOptionalTlv(cb);
293
294         //Update object length now
295         int length = cb.writerIndex() - objStartIndex;
296         //will be helpful during print().
297         lspObjHeader.setObjLen((short) length);
298         // As per RFC the length of object should be
299         // multiples of 4
300
301         cb.setShort(objLenIndex, (short) length);
302
303         return length;
304     }
305
306     /**
307      * Returns Linked list of optional tlvs.
308      *
309      * @param cb of channel buffer.
310      * @return list of optional tlvs
311      * @throws PcepParseException when unsupported tlv is received
312      */
313     protected static LinkedList<PcepValueType> parseOptionalTlv(ChannelBuffer cb) throws PcepParseException {
314
315         LinkedList<PcepValueType> llOutOptionalTlv;
316
317         llOutOptionalTlv = new LinkedList<>();
318
319         while (MINIMUM_COMMON_HEADER_LENGTH <= cb.readableBytes()) {
320
321             PcepValueType tlv;
322             short hType = cb.readShort();
323             short hLength = cb.readShort();
324             int iValue = 0;
325
326             switch (hType) {
327
328             case StatefulIPv4LspIdentidiersTlv.TYPE:
329                 tlv = StatefulIPv4LspIdentidiersTlv.read(cb);
330                 break;
331             case StatefulLspErrorCodeTlv.TYPE:
332                 iValue = cb.readInt();
333                 tlv = new StatefulLspErrorCodeTlv(iValue);
334                 break;
335             case StatefulRsvpErrorSpecTlv.TYPE:
336                 tlv = StatefulRsvpErrorSpecTlv.read(cb);
337                 break;
338             case SymbolicPathNameTlv.TYPE:
339                 tlv = SymbolicPathNameTlv.read(cb, hLength);
340                 break;
341             case StatefulLspDbVerTlv.TYPE:
342                 tlv = StatefulLspDbVerTlv.read(cb);
343                 break;
344             default:
345                 throw new PcepParseException("Received unsupported TLV type :" + hType);
346             }
347             // Check for the padding
348             int pad = hLength % 4;
349             if (0 < pad) {
350                 pad = 4 - pad;
351                 if (pad <= cb.readableBytes()) {
352                     cb.skipBytes(pad);
353                 }
354             }
355
356             llOutOptionalTlv.add(tlv);
357         }
358
359         if (0 < cb.readableBytes()) {
360
361             throw new PcepParseException("Optional Tlv parsing error. Extra bytes received.");
362         }
363         return llOutOptionalTlv;
364     }
365
366     /**
367      * returns writer index.
368      *
369      * @param cb of type channel buffer
370      * @return length of bytes written to channel buffer
371      */
372     protected int packOptionalTlv(ChannelBuffer cb) {
373
374         ListIterator<PcepValueType> listIterator = llOptionalTlv.listIterator();
375         int startIndex = cb.writerIndex();
376
377         while (listIterator.hasNext()) {
378             PcepValueType tlv = listIterator.next();
379
380             if (tlv == null) {
381                 log.debug("tlv is null from OptionalTlv list");
382                 continue;
383             }
384
385             tlv.write(cb);
386
387             // need to take care of padding
388             int pad = tlv.getLength() % 4;
389
390             if (0 != pad) {
391                 pad = 4 - pad;
392                 for (int i = 0; i < pad; ++i) {
393                     cb.writeByte((byte) 0);
394                 }
395             }
396         }
397
398         return cb.writerIndex() - startIndex;
399     }
400
401     /**
402      * Builder class for PCEP lsp Object.
403      */
404     public static class Builder implements PcepLspObject.Builder {
405
406         private boolean bIsHeaderSet = false;
407         private boolean bIsPlspIdSet = false;
408         private boolean bIsOFlagSet = false;
409         private boolean bIsRFlagSet = false;
410         private boolean bIsAFlagSet = false;
411         private boolean bIsDFlagSet = false;
412         private boolean bIsSFlagSet = false;
413
414         private PcepObjectHeader lspObjHeader;
415         private byte yOFlag;
416         private boolean bAFlag;
417         private boolean bDFlag;
418         private boolean bSFlag;
419         private boolean bRFlag;
420         LinkedList<PcepValueType> llOptionalTlv = null;
421
422         private int plspId;
423
424         private boolean bIsPFlagSet = false;
425         private boolean bPFlag;
426
427         private boolean bIsIFlagSet = false;
428         private boolean bIFlag;
429
430         @Override
431         public PcepLspObject build() {
432             PcepObjectHeader lspObjHeader = this.bIsHeaderSet ? this.lspObjHeader : DEFAULT_LSP_OBJECT_HEADER;
433
434             int plspId = this.bIsPlspIdSet ? this.plspId : DEFAULT_PLSPID;
435             byte yOFlag = this.bIsOFlagSet ? this.yOFlag : DEFAULT_OFLAG;
436             boolean bAFlag = this.bIsAFlagSet ? this.bAFlag : DEFAULT_AFLAG;
437             boolean bRFlag = this.bIsRFlagSet ? this.bRFlag : DEFAULT_RFLAG;
438             boolean bSFlag = this.bIsSFlagSet ? this.bSFlag : DEFAULT_SFLAG;
439             boolean bDFlag = this.bIsDFlagSet ? this.bDFlag : DEFAULT_DFLAG;
440
441             if (bIsPFlagSet) {
442                 lspObjHeader.setPFlag(bPFlag);
443             }
444
445             if (bIsIFlagSet) {
446                 lspObjHeader.setIFlag(bIFlag);
447             }
448
449             return new PcepLspObjectVer1(lspObjHeader, plspId, yOFlag, bAFlag, bRFlag, bSFlag, bDFlag, llOptionalTlv);
450         }
451
452         @Override
453         public PcepObjectHeader getLspObjHeader() {
454             return this.lspObjHeader;
455         }
456
457         @Override
458         public Builder setLspObjHeader(PcepObjectHeader obj) {
459             this.lspObjHeader = obj;
460             this.bIsHeaderSet = true;
461             return this;
462         }
463
464         @Override
465         public int getPlspId() {
466             return this.plspId;
467         }
468
469         @Override
470         public Builder setPlspId(int value) {
471             this.plspId = value;
472             this.bIsPlspIdSet = true;
473             return this;
474         }
475
476         @Override
477         public byte getOFlag() {
478             return this.yOFlag;
479         }
480
481         @Override
482         public Builder setOFlag(byte value) {
483             this.yOFlag = value;
484             this.bIsOFlagSet = true;
485             return this;
486         }
487
488         @Override
489         public boolean getAFlag() {
490             return this.bAFlag;
491         }
492
493         @Override
494         public Builder setAFlag(boolean value) {
495             this.bAFlag = value;
496             this.bIsAFlagSet = true;
497             return this;
498         }
499
500         @Override
501         public boolean getRFlag() {
502             return this.bRFlag;
503         }
504
505         @Override
506         public Builder setRFlag(boolean value) {
507             this.bRFlag = value;
508             this.bIsRFlagSet = true;
509             return this;
510         }
511
512         @Override
513         public boolean getSFlag() {
514             return this.bSFlag;
515         }
516
517         @Override
518         public Builder setSFlag(boolean value) {
519             this.bSFlag = value;
520             this.bIsSFlagSet = true;
521             return this;
522         }
523
524         @Override
525         public boolean getDFlag() {
526             return this.bDFlag;
527         }
528
529         @Override
530         public Builder setDFlag(boolean value) {
531             this.bDFlag = value;
532             this.bIsDFlagSet = true;
533             return this;
534         }
535
536         @Override
537         public Builder setOptionalTlv(LinkedList<PcepValueType> llOptionalTlv) {
538             this.llOptionalTlv = llOptionalTlv;
539             return this;
540         }
541
542         @Override
543         public LinkedList<PcepValueType> getOptionalTlv() {
544             return this.llOptionalTlv;
545         }
546
547         @Override
548         public Builder setPFlag(boolean value) {
549             this.bPFlag = value;
550             this.bIsPFlagSet = true;
551             return this;
552         }
553
554         @Override
555         public Builder setIFlag(boolean value) {
556             this.bIFlag = value;
557             this.bIsIFlagSet = true;
558             return this;
559         }
560
561     }
562
563     @Override
564     public String toString() {
565         return MoreObjects.toStringHelper(getClass())
566                 .add("PlspIDValue", iPlspId)
567                 .add("OFlag", yOFlag)
568                 .add("AFlag", bAFlag)
569                 .add("RFlag", bRFlag)
570                 .add("SFlag", bSFlag)
571                 .add("DFlag", bDFlag)
572                 .add("OptionalTlvList", llOptionalTlv)
573                 .toString();
574     }
575 }