blob: 2b319c12a9683dcaebec161de283b96ca305f9bf [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;
Mahesh Poojary S5eab8572015-09-01 17:45:48 +053029import org.onosproject.pcepio.types.StatefulLspDbVerTlv;
bharat saraswalf7364db2015-08-11 13:39:31 +053030import org.onosproject.pcepio.types.StatefulLspErrorCodeTlv;
31import org.onosproject.pcepio.types.StatefulRsvpErrorSpecTlv;
32import org.onosproject.pcepio.types.SymbolicPathNameTlv;
33import org.slf4j.Logger;
34import org.slf4j.LoggerFactory;
35
36import com.google.common.base.MoreObjects;
37
Phanendra Manda51fb9c22015-09-01 16:17:41 +053038/**
39 * Provides PCEP lsp object.
40 */
41public class PcepLspObjectVer1 implements PcepLspObject {
42
43 /*
bharat saraswalf7364db2015-08-11 13:39:31 +053044 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
Phanendra Manda51fb9c22015-09-01 16:17:41 +053058 */
bharat saraswalf7364db2015-08-11 13:39:31 +053059 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
Sho SHIMIZU9b8274c2015-09-04 15:54:24 -0700237 LinkedList<PcepValueType> llOptionalTlv = new LinkedList<>();
bharat saraswalf7364db2015-08-11 13:39:31 +0530238
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;
Phanendra Mandaf346ea82015-09-04 15:21:39 -0700252 bAFlag = iX > 0;
bharat saraswalf7364db2015-08-11 13:39:31 +0530253 iX = (iTemp & RFLAG_TEMP_SHIFT_VALUE) >> RFLAG_SHIFT_VALUE;
Phanendra Mandaf346ea82015-09-04 15:21:39 -0700254 bRFlag = iX > 0;
bharat saraswalf7364db2015-08-11 13:39:31 +0530255 iX = (iTemp & SFLAG_TEMP_SHIFT_VALUE) >> SFLAG_SHIFT_VALUE;
Phanendra Mandaf346ea82015-09-04 15:21:39 -0700256 bSFlag = iX > 0;
bharat saraswalf7364db2015-08-11 13:39:31 +0530257 iX = iTemp & DFLAG_TEMP_SHIFT_VALUE;
Phanendra Mandaf346ea82015-09-04 15:21:39 -0700258 bDFlag = iX > 0;
bharat saraswalf7364db2015-08-11 13:39:31 +0530259
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
Sho SHIMIZU9b8274c2015-09-04 15:54:24 -0700317 llOutOptionalTlv = new LinkedList<>();
bharat saraswalf7364db2015-08-11 13:39:31 +0530318
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;
Mahesh Poojary S5eab8572015-09-01 17:45:48 +0530341 case StatefulLspDbVerTlv.TYPE:
342 tlv = StatefulLspDbVerTlv.read(cb);
343 break;
bharat saraswalf7364db2015-08-11 13:39:31 +0530344 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
Sho SHIMIZUde09fa02015-09-03 09:39:52 -0700380 if (tlv == null) {
bharat saraswalf7364db2015-08-11 13:39:31 +0530381 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
bharat saraswalf7364db2015-08-11 13:39:31 +0530564 public String toString() {
Sho SHIMIZU7cdbcf72015-09-03 14:43:05 -0700565 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();
bharat saraswalf7364db2015-08-11 13:39:31 +0530574 }
575}