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