blob: 3a1631819b911c7e2a57fb76d15eaf2de2e3d437 [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
bharat saraswalf7364db2015-08-11 13:39:31 +0530558 public String toString() {
bharat saraswale1806302015-08-21 12:16:46 +0530559 return MoreObjects.toStringHelper(getClass()).add("PlspIDValue", iPlspId).add("OFlag", yOFlag)
560 .add("AFlag", bAFlag).add("RFlag", bRFlag).add("SFlag", bSFlag).add("DFlag", bDFlag)
561 .add("OptionalTlvList", llOptionalTlv).toString();
bharat saraswalf7364db2015-08-11 13:39:31 +0530562 }
563}