2 * Copyright 2015 Open Networking Laboratory
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package org.onosproject.pcepio.protocol.ver1;
19 import java.util.LinkedList;
20 import java.util.ListIterator;
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;
36 import com.google.common.base.MoreObjects;
39 * Provides PCEP lsp object.
41 public class PcepLspObjectVer1 implements PcepLspObject {
45 Reference : draft-ietf-pce-stateful-pce-11, section 7.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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
55 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
59 protected static final Logger log = LoggerFactory.getLogger(PcepLspObjectVer1.class);
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;
65 // LSP_OBJ_MINIMUM_LENGTH = CommonHeaderLen(4)+ LspObjectHeaderLen(4)+TlvAssumedMinLength(8)
66 public static final short LSP_OBJ_MINIMUM_LENGTH = 16;
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;
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);
93 private PcepObjectHeader lspObjHeader;
97 private boolean bAFlag;
98 private boolean bRFlag;
99 private boolean bSFlag;
100 private boolean bDFlag;
103 private LinkedList<PcepValueType> llOptionalTlv;
106 * Constructor to initialize all the member variables.
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
117 public PcepLspObjectVer1(PcepObjectHeader lspObjHeader, int iPlspId, byte yOFlag, boolean bAFlag, boolean bRFlag,
118 boolean bSFlag, boolean bDFlag, LinkedList<PcepValueType> llOptionalTlv) {
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;
131 * Sets lsp Object Header.
133 * @param obj lsp object header
135 public void setLspObjHeader(PcepObjectHeader obj) {
136 this.lspObjHeader = obj;
140 public void setPlspId(int iPlspId) {
141 this.iPlspId = iPlspId;
145 public void setOFlag(byte yOFlag) {
146 this.yOFlag = yOFlag;
150 public void setAFlag(boolean bAFlag) {
151 this.bAFlag = bAFlag;
155 public void setRFlag(boolean bRFlag) {
156 this.bRFlag = bRFlag;
160 public void setSFlag(boolean bSFlag) {
161 this.bSFlag = bSFlag;
165 public void setDFlag(boolean bDFlag) {
166 this.bDFlag = bDFlag;
170 * Returns lsp object header.
172 * @return lspObjHeader
174 public PcepObjectHeader getLspObjHeader() {
175 return this.lspObjHeader;
179 public int getPlspId() {
184 public byte getOFlag() {
189 public boolean getAFlag() {
194 public boolean getRFlag() {
199 public boolean getSFlag() {
204 public boolean getDFlag() {
209 public LinkedList<PcepValueType> getOptionalTlv() {
210 return this.llOptionalTlv;
214 public void setOptionalTlv(LinkedList<PcepValueType> llOptionalTlv) {
215 this.llOptionalTlv = llOptionalTlv;
219 * Parse channel buffer and returns object of PcepLspObject.
221 * @param cb of type channel buffer
222 * @return object of PcepLspObject
223 * @throws PcepParseException when lsp object is not present in channel buffer
225 public static PcepLspObject read(ChannelBuffer cb) throws PcepParseException {
227 PcepObjectHeader lspObjHeader;
237 LinkedList<PcepValueType> llOptionalTlv = new LinkedList<>();
239 lspObjHeader = PcepObjectHeader.read(cb);
241 if (lspObjHeader.getObjClass() != PcepLspObjectVer1.LSP_OBJ_CLASS) {
242 throw new PcepParseException(PcepErrorDetailInfo.ERROR_TYPE_6, PcepErrorDetailInfo.ERROR_VALUE_8);
244 //take only LspObject buffer.
245 ChannelBuffer tempCb = cb.readBytes(lspObjHeader.getObjLen() - OBJECT_HEADER_LENGTH);
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;
253 iX = (iTemp & RFLAG_TEMP_SHIFT_VALUE) >> RFLAG_SHIFT_VALUE;
255 iX = (iTemp & SFLAG_TEMP_SHIFT_VALUE) >> SFLAG_SHIFT_VALUE;
257 iX = iTemp & DFLAG_TEMP_SHIFT_VALUE;
260 // parse optional TLV
261 llOptionalTlv = parseOptionalTlv(tempCb);
263 return new PcepLspObjectVer1(lspObjHeader, iPlspId, yOFlag, bAFlag, bRFlag, bSFlag, bDFlag, llOptionalTlv);
267 public int write(ChannelBuffer cb) throws PcepParseException {
269 //write Object header
270 int objStartIndex = cb.writerIndex();
272 int objLenIndex = lspObjHeader.write(cb);
274 if (objLenIndex <= 0) {
275 throw new PcepParseException("Failed to write lsp object header. Index " + objLenIndex);
278 int iTemp = iPlspId << PLSPID_SHIFT_VALUE;
279 iTemp = iTemp | (yOFlag << OFLAG_SHIFT_VALUE);
281 iTemp = bAFlag ? (iTemp | AFLAG_TEMP_SHIFT_VALUE) : iTemp;
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;
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
301 cb.setShort(objLenIndex, (short) length);
307 * Returns Linked list of optional tlvs.
309 * @param cb of channel buffer.
310 * @return list of optional tlvs
311 * @throws PcepParseException when unsupported tlv is received
313 protected static LinkedList<PcepValueType> parseOptionalTlv(ChannelBuffer cb) throws PcepParseException {
315 LinkedList<PcepValueType> llOutOptionalTlv;
317 llOutOptionalTlv = new LinkedList<>();
319 while (MINIMUM_COMMON_HEADER_LENGTH <= cb.readableBytes()) {
322 short hType = cb.readShort();
323 short hLength = cb.readShort();
328 case StatefulIPv4LspIdentidiersTlv.TYPE:
329 tlv = StatefulIPv4LspIdentidiersTlv.read(cb);
331 case StatefulLspErrorCodeTlv.TYPE:
332 iValue = cb.readInt();
333 tlv = new StatefulLspErrorCodeTlv(iValue);
335 case StatefulRsvpErrorSpecTlv.TYPE:
336 tlv = StatefulRsvpErrorSpecTlv.read(cb);
338 case SymbolicPathNameTlv.TYPE:
339 tlv = SymbolicPathNameTlv.read(cb, hLength);
341 case StatefulLspDbVerTlv.TYPE:
342 tlv = StatefulLspDbVerTlv.read(cb);
345 throw new PcepParseException("Received unsupported TLV type :" + hType);
347 // Check for the padding
348 int pad = hLength % 4;
351 if (pad <= cb.readableBytes()) {
356 llOutOptionalTlv.add(tlv);
359 if (0 < cb.readableBytes()) {
361 throw new PcepParseException("Optional Tlv parsing error. Extra bytes received.");
363 return llOutOptionalTlv;
367 * returns writer index.
369 * @param cb of type channel buffer
370 * @return length of bytes written to channel buffer
372 protected int packOptionalTlv(ChannelBuffer cb) {
374 ListIterator<PcepValueType> listIterator = llOptionalTlv.listIterator();
375 int startIndex = cb.writerIndex();
377 while (listIterator.hasNext()) {
378 PcepValueType tlv = listIterator.next();
381 log.debug("tlv is null from OptionalTlv list");
387 // need to take care of padding
388 int pad = tlv.getLength() % 4;
392 for (int i = 0; i < pad; ++i) {
393 cb.writeByte((byte) 0);
398 return cb.writerIndex() - startIndex;
402 * Builder class for PCEP lsp Object.
404 public static class Builder implements PcepLspObject.Builder {
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;
414 private PcepObjectHeader lspObjHeader;
416 private boolean bAFlag;
417 private boolean bDFlag;
418 private boolean bSFlag;
419 private boolean bRFlag;
420 LinkedList<PcepValueType> llOptionalTlv = null;
424 private boolean bIsPFlagSet = false;
425 private boolean bPFlag;
427 private boolean bIsIFlagSet = false;
428 private boolean bIFlag;
431 public PcepLspObject build() {
432 PcepObjectHeader lspObjHeader = this.bIsHeaderSet ? this.lspObjHeader : DEFAULT_LSP_OBJECT_HEADER;
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;
442 lspObjHeader.setPFlag(bPFlag);
446 lspObjHeader.setIFlag(bIFlag);
449 return new PcepLspObjectVer1(lspObjHeader, plspId, yOFlag, bAFlag, bRFlag, bSFlag, bDFlag, llOptionalTlv);
453 public PcepObjectHeader getLspObjHeader() {
454 return this.lspObjHeader;
458 public Builder setLspObjHeader(PcepObjectHeader obj) {
459 this.lspObjHeader = obj;
460 this.bIsHeaderSet = true;
465 public int getPlspId() {
470 public Builder setPlspId(int value) {
472 this.bIsPlspIdSet = true;
477 public byte getOFlag() {
482 public Builder setOFlag(byte value) {
484 this.bIsOFlagSet = true;
489 public boolean getAFlag() {
494 public Builder setAFlag(boolean value) {
496 this.bIsAFlagSet = true;
501 public boolean getRFlag() {
506 public Builder setRFlag(boolean value) {
508 this.bIsRFlagSet = true;
513 public boolean getSFlag() {
518 public Builder setSFlag(boolean value) {
520 this.bIsSFlagSet = true;
525 public boolean getDFlag() {
530 public Builder setDFlag(boolean value) {
532 this.bIsDFlagSet = true;
537 public Builder setOptionalTlv(LinkedList<PcepValueType> llOptionalTlv) {
538 this.llOptionalTlv = llOptionalTlv;
543 public LinkedList<PcepValueType> getOptionalTlv() {
544 return this.llOptionalTlv;
548 public Builder setPFlag(boolean value) {
550 this.bIsPFlagSet = true;
555 public Builder setIFlag(boolean value) {
557 this.bIsIFlagSet = true;
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)