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