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