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