blob: 51a8eafde89b118d7b9dc9fbf00e6e8791142abc [file] [log] [blame]
Mahesh Poojary S5afd06c2015-08-21 14:51:04 +05301/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
Mahesh Poojary S5afd06c2015-08-21 14:51:04 +05303 *
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.PcepOpenObject;
25import org.onosproject.pcepio.protocol.PcepType;
26import org.onosproject.pcepio.protocol.PcepVersion;
27import org.onosproject.pcepio.types.GmplsCapabilityTlv;
Priyanka B21f4b732016-03-21 20:54:12 +053028import org.onosproject.pcepio.types.NodeAttributesTlv;
Mahesh Poojary S5afd06c2015-08-21 14:51:04 +053029import org.onosproject.pcepio.types.PceccCapabilityTlv;
30import org.onosproject.pcepio.types.PcepLabelDbVerTlv;
31import org.onosproject.pcepio.types.PcepObjectHeader;
32import org.onosproject.pcepio.types.PcepValueType;
Priyanka B21f4b732016-03-21 20:54:12 +053033import org.onosproject.pcepio.types.SrPceCapabilityTlv;
Mahesh Poojary S5afd06c2015-08-21 14:51:04 +053034import org.onosproject.pcepio.types.StatefulLspDbVerTlv;
35import org.onosproject.pcepio.types.StatefulPceCapabilityTlv;
Mahesh Poojary Sf1bbd362016-02-25 18:19:59 +053036import org.onosproject.pcepio.types.LsCapabilityTlv;
Mahesh Poojary S5afd06c2015-08-21 14:51:04 +053037import org.slf4j.Logger;
38import org.slf4j.LoggerFactory;
39
40import com.google.common.base.MoreObjects;
41
Phanendra Manda51fb9c22015-09-01 16:17:41 +053042/**
43 * Provides PCEP open object.
44 */
45public class PcepOpenObjectVer1 implements PcepOpenObject {
46
47 /*
Mahesh Poojary S5afd06c2015-08-21 14:51:04 +053048 message format.
49 0 1 2 3
50 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
51 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
52 | Object-Class | OT |Res|P|I| Object Length (bytes) |
53 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
54 | Ver | Flags | Keepalive | DeadTimer | SID |
55 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
56 | |
57 // Optional TLVs //
58 | |
59 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
60
61 The OPEN Object format
Phanendra Manda51fb9c22015-09-01 16:17:41 +053062 */
Ray Milkey9c9cde42018-01-12 14:22:06 -080063 private static final Logger log = LoggerFactory.getLogger(PcepOpenObjectVer1.class);
Mahesh Poojary S5afd06c2015-08-21 14:51:04 +053064
65 public static final PcepType MSG_TYPE = PcepType.OPEN;
66 public static final byte OPEN_OBJECT_VERSION = 1;
67 public static final byte OPEN_OBJ_TYPE = 1;
68 public static final byte OPEN_OBJ_CLASS = 1;
69 public static final byte DEFAULT_KEEPALIVE_TIME = 30;
70 public static final byte DEFAULT_DEAD_TIME = 120;
71 public static final short OPEN_OBJ_MINIMUM_LENGTH = 8;
72 public static final int DEFAULT_GMPLS_CAPABILITY_TLV_IVALUE = 0X0;
73 public static final int DEFAULT_STATEFUL_PCE_CAPABILITY_TLV_IVALUE = 0xf;
74 public static final int DEFAULT_PCECC_CAPABILITY_TLV_IVALUE = 0x7;
75 public static final int DEFAULT_PCEP_LABEL_DB_VER_TLV_IVALUE = 0X0;
76
77 public static final PcepObjectHeader DEFAULT_OPEN_HEADER = new PcepObjectHeader(OPEN_OBJ_CLASS, OPEN_OBJ_TYPE,
78 PcepObjectHeader.REQ_OBJ_OPTIONAL_PROCESS, PcepObjectHeader.RSP_OBJ_PROCESSED, OPEN_OBJ_MINIMUM_LENGTH);
79
80 private PcepObjectHeader openObjHeader;
81 private byte keepAliveTime;
82 private byte deadTime;
83 private byte sessionId;
84 private LinkedList<PcepValueType> llOptionalTlv;
85
86 /**
87 * Default constructor.
88 */
89 public PcepOpenObjectVer1() {
90 this.openObjHeader = null;
91 this.keepAliveTime = 0;
92 this.deadTime = 0;
93 this.sessionId = 0;
94 this.llOptionalTlv = null;
95 }
96
97 /**
98 * Constructor to initialize all member variables.
99 *
100 * @param openObjHeader Open Object Header
101 * @param keepAliveTime Keepalive timer value
102 * @param deadTime Dead timer value
103 * @param sessionID session id
104 * @param llOptionalTlv Optional TLV
105 */
106 public PcepOpenObjectVer1(PcepObjectHeader openObjHeader, byte keepAliveTime, byte deadTime, byte sessionID,
107 LinkedList<PcepValueType> llOptionalTlv) {
108 this.openObjHeader = openObjHeader;
109 this.keepAliveTime = keepAliveTime;
110 this.deadTime = deadTime;
111 this.sessionId = sessionID;
112 this.llOptionalTlv = llOptionalTlv;
113 }
114
115 @Override
116 public PcepObjectHeader getOpenObjHeader() {
117 return this.openObjHeader;
118 }
119
120 @Override
121 public void setOpenObjHeader(PcepObjectHeader obj) {
122 this.openObjHeader = obj;
123 }
124
125 @Override
126 public byte getKeepAliveTime() {
127 return this.keepAliveTime;
128 }
129
130 @Override
131 public void setKeepAliveTime(byte value) {
132 this.keepAliveTime = value;
133 }
134
135 @Override
136 public PcepVersion getVersion() {
137 return PcepVersion.PCEP_1;
138 }
139
140 @Override
141 public byte getDeadTime() {
142 return this.deadTime;
143 }
144
145 @Override
146 public void setDeadTime(byte value) {
147 this.deadTime = value;
148 }
149
150 @Override
151 public byte getSessionId() {
152 return this.sessionId;
153 }
154
155 @Override
156 public void setSessionId(byte value) {
157 this.sessionId = value;
158 }
159
160 @Override
161 public LinkedList<PcepValueType> getOptionalTlv() {
162 return this.llOptionalTlv;
163 }
164
165 @Override
166 public void setOptionalTlv(LinkedList<PcepValueType> llOptionalTlv) {
167 this.llOptionalTlv = llOptionalTlv;
168 }
169
170 /**
171 * Reads from channel buffer and returns object of PcepOpenObject.
172 *
173 * @param cb of type channel buffer
174 * @return object of PcepOpenObject
175 * @throws PcepParseException if mandatory fields are missing
176 */
177 public static PcepOpenObject read(ChannelBuffer cb) throws PcepParseException {
178
179 PcepObjectHeader openObjHeader;
180 byte version;
181 byte keepAliveTime;
182 byte deadTime;
183 byte sessionID;
184 LinkedList<PcepValueType> llOptionalTlv;
185
186 openObjHeader = PcepObjectHeader.read(cb);
187 version = cb.readByte();
188 version = (byte) (version >> PcepMessageVer1.SHIFT_FLAG);
189 if (version != OPEN_OBJECT_VERSION) {
190 throw new PcepParseException("Wrong version: Expected=PcepVersion.PCEP_1(1), got=" + version);
191 }
192 /* Keepalive */
193 keepAliveTime = cb.readByte();
194
195 /* DeadTimer */
196 deadTime = cb.readByte();
197
198 /* SID */
199 sessionID = cb.readByte();
200
201 // Optional TLV
202 llOptionalTlv = parseOptionalTlv(cb);
203
204 return new PcepOpenObjectVer1(openObjHeader, keepAliveTime, deadTime, sessionID, llOptionalTlv);
205 }
206
207 /**
208 * Returns linkedlist of optional tlvs.
209 *
210 * @param cb of type channel buffer
211 * @return llOptionalTlv Optional TLV
212 * @throws PcepParseException if mandatory fields are missing
213 */
214 protected static LinkedList<PcepValueType> parseOptionalTlv(ChannelBuffer cb) throws PcepParseException {
215
216 LinkedList<PcepValueType> llOptionalTlv;
217
Sho SHIMIZU9b8274c2015-09-04 15:54:24 -0700218 llOptionalTlv = new LinkedList<>();
Mahesh Poojary S5afd06c2015-08-21 14:51:04 +0530219
220 while (4 <= cb.readableBytes()) {
221 PcepValueType tlv;
222 short hType = cb.readShort();
223 short hLength = cb.readShort();
224
225 switch (hType) {
226 case GmplsCapabilityTlv.TYPE:
227 log.debug("GmplsCapabilityTlv");
228 if (GmplsCapabilityTlv.LENGTH != hLength) {
229 throw new PcepParseException("Invalid length received for Gmpls_Capability_Tlv.");
230 }
231 int iValue = cb.readInt();
232 tlv = new GmplsCapabilityTlv(iValue);
233 break;
234 case StatefulPceCapabilityTlv.TYPE:
235 log.debug("StatefulPceCapabilityTlv");
236 if (StatefulPceCapabilityTlv.LENGTH != hLength) {
237 throw new PcepParseException("Invalid length received for StatefulPceCapabilityTlv.");
238 }
239 tlv = StatefulPceCapabilityTlv.read(cb);
240 break;
241 case PceccCapabilityTlv.TYPE:
242 log.debug("PceccCapabilityTlv");
243 if (PceccCapabilityTlv.LENGTH != hLength) {
244 throw new PcepParseException("Invalid length for PceccCapabilityTlv.");
245 }
246 iValue = cb.readInt();
247 tlv = new PceccCapabilityTlv(iValue);
248 break;
249 case StatefulLspDbVerTlv.TYPE:
250 log.debug("StatefulLspDbVerTlv");
251 if (StatefulLspDbVerTlv.LENGTH != hLength) {
252 throw new PcepParseException("Invalid length received for StatefulLspDbVerTlv.");
253 }
254 long lValue = cb.readLong();
255 tlv = new StatefulLspDbVerTlv(lValue);
256 break;
Mahesh Poojary Sf1bbd362016-02-25 18:19:59 +0530257 case LsCapabilityTlv.TYPE:
258 log.debug("LsCapabilityTlv");
259 if (LsCapabilityTlv.LENGTH != hLength) {
260 throw new PcepParseException("Invalid length received for LsCapabilityTlv.");
Mahesh Poojary S5afd06c2015-08-21 14:51:04 +0530261 }
262 iValue = cb.readInt();
Mahesh Poojary Sf1bbd362016-02-25 18:19:59 +0530263 tlv = new LsCapabilityTlv(iValue);
Mahesh Poojary S5afd06c2015-08-21 14:51:04 +0530264 break;
265 case PcepLabelDbVerTlv.TYPE:
266 log.debug("PcepLabelDbVerTlv");
267 if (PcepLabelDbVerTlv.LENGTH != hLength) {
268 throw new PcepParseException("Invalid length received for PcepLabelDbVerTlv.");
269 }
270 lValue = cb.readLong();
271 tlv = new PcepLabelDbVerTlv(lValue);
272 break;
Priyanka B21f4b732016-03-21 20:54:12 +0530273 case NodeAttributesTlv.TYPE:
274 log.debug("NodeAttributesTlv");
275 if (cb.readableBytes() < hLength) {
276 throw new PcepParseException("Invalid length for NodeAttributesTlv.");
277 }
278 tlv = NodeAttributesTlv.read(cb.readBytes(hLength), hLength);
279 break;
280 case SrPceCapabilityTlv.TYPE:
281 log.debug("SrPceCapabilityTlv");
282 if (SrPceCapabilityTlv.LENGTH != hLength) {
283 throw new PcepParseException("Invalid length received for SrPceCapabilityTlv.");
284 }
285 tlv = SrPceCapabilityTlv.read(cb);
286 break;
Mahesh Poojary S5afd06c2015-08-21 14:51:04 +0530287 default:
288 log.debug("Unsupported TLV: " + hType);
289 cb.skipBytes(hLength);
Avantika-Huaweifb630482016-08-09 11:42:11 +0530290 tlv = null;
Mahesh Poojary S5afd06c2015-08-21 14:51:04 +0530291 }
292
Avantika-Huaweifb630482016-08-09 11:42:11 +0530293 // Check for the padding
294 int pad = hLength % 4;
295 if (0 < pad) {
296 pad = 4 - pad;
297 if (pad <= cb.readableBytes()) {
298 cb.skipBytes(pad);
299 }
300 }
301
302 if (tlv != null) {
303 llOptionalTlv.add(tlv);
304 }
Mahesh Poojary S5afd06c2015-08-21 14:51:04 +0530305 }
306
307 if (0 < cb.readableBytes()) {
308 throw new PcepParseException("Optional Tlv parsing error. Extra bytes received.");
309 }
310
311 return llOptionalTlv;
312 }
313
314 @Override
315 public int write(ChannelBuffer cb) throws PcepParseException {
316
317 int objStartIndex = cb.writerIndex();
318
319 //write common header
320 int objLenIndex = openObjHeader.write(cb);
321
322 if (objLenIndex <= 0) {
323 throw new PcepParseException("Unable to write Open object header.");
324 }
325
326 cb.writeByte((byte) (OPEN_OBJECT_VERSION << PcepMessageVer1.SHIFT_FLAG));
327 cb.writeByte(this.keepAliveTime);
328 cb.writeByte(this.deadTime);
329 cb.writeByte(this.sessionId);
330
331 //Pack optional TLV
332 packOptionalTlv(cb);
333
334 //now write OPEN Object Length
335 int length = cb.writerIndex() - objStartIndex;
336 cb.setShort(objLenIndex, (short) length);
337 //will be helpful during print().
338 this.openObjHeader.setObjLen((short) length);
339
340 return length;
341 }
342
343 /**
344 * Returns writer index.
345 *
346 * @param cb of type channel buffer.
347 * @return writer index
348 */
349 protected int packOptionalTlv(ChannelBuffer cb) {
350 int startIndex = cb.writerIndex();
351
352 LinkedList<PcepValueType> llOptionalTlv = this.llOptionalTlv;
353 ListIterator<PcepValueType> listIterator = llOptionalTlv.listIterator();
354 while (listIterator.hasNext()) {
355 PcepValueType tlv = listIterator.next();
Sho SHIMIZUde09fa02015-09-03 09:39:52 -0700356 if (tlv == null) {
Mahesh Poojary S5afd06c2015-08-21 14:51:04 +0530357 log.debug("TLV is null from OptionalTlv list");
358 continue;
359 }
360
361 tlv.write(cb);
362
363 // need to take care of padding
364 int pad = tlv.getLength() % 4;
365
366 if (0 != pad) {
367 pad = 4 - pad;
368 for (int i = 0; i < pad; ++i) {
369 cb.writeByte((byte) 0);
370 }
371 }
372 }
Mahesh Poojary S5afd06c2015-08-21 14:51:04 +0530373 return cb.writerIndex() - startIndex;
374 }
375
Phanendra Manda51fb9c22015-09-01 16:17:41 +0530376 /**
377 * Builder class for PCPE open object.
378 */
Mahesh Poojary S5afd06c2015-08-21 14:51:04 +0530379 public static class Builder implements PcepOpenObject.Builder {
380 // Pcep open message fields
381 private boolean bIsHeaderSet = false;
382 private PcepObjectHeader openObjHeader;
383 private boolean bIsKeepAliveTimeSet = false;
384 private byte keepAliveTime;
385 private boolean bIsDeadTimeSet = false;
386 private byte deadTime;
387 private boolean bIsSessionIDSet = false;
388 private byte sessionID;
389 private boolean bIsOptionalTlvSet = false;
Sho SHIMIZU9b8274c2015-09-04 15:54:24 -0700390 private LinkedList<PcepValueType> llOptionalTlv = new LinkedList<>();
Mahesh Poojary S5afd06c2015-08-21 14:51:04 +0530391
392 private boolean bIsPFlagSet = false;
393 private boolean bPFlag;
394
395 private boolean bIsIFlagSet = false;
396 private boolean bIFlag;
397
398 @Override
399 public PcepOpenObject build() throws PcepParseException {
400 PcepObjectHeader openObjHeader = this.bIsHeaderSet ? this.openObjHeader : DEFAULT_OPEN_HEADER;
401 byte keepAliveTime = this.bIsKeepAliveTimeSet ? this.keepAliveTime : DEFAULT_KEEPALIVE_TIME;
402 byte deadTime = this.bIsDeadTimeSet ? this.deadTime : DEFAULT_DEAD_TIME;
403
404 if (!this.bIsSessionIDSet) {
405 throw new PcepParseException("SessionID is not set (mandatory)");
406 }
407 if (!this.bIsOptionalTlvSet) {
408 //Add tlv to list
409 //Add GmplsCapabilityTlv
410 PcepValueType tlv;
411 int iValue = DEFAULT_GMPLS_CAPABILITY_TLV_IVALUE;
412 tlv = new GmplsCapabilityTlv(iValue);
413 this.llOptionalTlv.add(tlv);
414
415 //Add StatefulPceCapabilityTlv
416 iValue = DEFAULT_STATEFUL_PCE_CAPABILITY_TLV_IVALUE;
417 tlv = new StatefulPceCapabilityTlv(iValue);
418 this.llOptionalTlv.add(tlv);
419
420 }
421
422 if (bIsPFlagSet) {
423 openObjHeader.setPFlag(bPFlag);
424 }
425
426 if (bIsIFlagSet) {
427 openObjHeader.setIFlag(bIFlag);
428 }
429
430 return new PcepOpenObjectVer1(openObjHeader, keepAliveTime, deadTime, this.sessionID, this.llOptionalTlv);
431 }
432
433 @Override
434 public PcepObjectHeader getOpenObjHeader() {
435 return this.openObjHeader;
436 }
437
438 @Override
439 public Builder setOpenObjHeader(PcepObjectHeader obj) {
440 this.openObjHeader = obj;
441 this.bIsHeaderSet = true;
442 return this;
443 }
444
445 @Override
446 public byte getKeepAliveTime() {
447 return this.keepAliveTime;
448 }
449
450 @Override
451 public Builder setKeepAliveTime(byte value) {
452 this.keepAliveTime = value;
453 this.bIsKeepAliveTimeSet = true;
454 return this;
455 }
456
457 @Override
458 public byte getDeadTime() {
459 return this.deadTime;
460 }
461
462 @Override
463 public Builder setDeadTime(byte value) {
464 this.deadTime = value;
465 this.bIsDeadTimeSet = true;
466 return this;
467 }
468
469 @Override
470 public byte getSessionId() {
471 return this.sessionID;
472 }
473
474 @Override
475 public Builder setSessionId(byte value) {
476 this.sessionID = value;
477 this.bIsSessionIDSet = true;
478 return this;
479 }
480
481 @Override
482 public Builder setOptionalTlv(LinkedList<PcepValueType> llOptionalTlv) {
483 this.llOptionalTlv = llOptionalTlv;
484 this.bIsOptionalTlvSet = true;
485 return this;
486 }
487
488 @Override
489 public LinkedList<PcepValueType> getOptionalTlv() {
490 return this.llOptionalTlv;
491 }
492
493 @Override
494 public Builder setPFlag(boolean value) {
495 this.bPFlag = value;
496 this.bIsPFlagSet = true;
497 return this;
498 }
499
500 @Override
501 public Builder setIFlag(boolean value) {
502 this.bIFlag = value;
503 this.bIsIFlagSet = true;
504 return this;
505 }
506 }
507
508 @Override
509 public String toString() {
Sho SHIMIZU7cdbcf72015-09-03 14:43:05 -0700510 return MoreObjects.toStringHelper(getClass())
511 .add("ObjectHeader", openObjHeader)
512 .add("Keepalive", keepAliveTime)
513 .add("DeadTimer", deadTime)
514 .add("SessionId", sessionId)
515 .add("OptionalTlv", llOptionalTlv)
516 .toString();
Mahesh Poojary S5afd06c2015-08-21 14:51:04 +0530517 }
518}