blob: b1c6940658bbeb428e6b288d6dd9982fa69f5102 [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.PcepTEObject;
Sho SHIMIZUa5356ec2015-09-03 13:27:38 -070025import org.onosproject.pcepio.types.LocalTENodeDescriptorsTlv;
Mahesh Poojary S5afd06c2015-08-21 14:51:04 +053026import org.onosproject.pcepio.types.PcepObjectHeader;
27import org.onosproject.pcepio.types.PcepValueType;
Sho SHIMIZUa5356ec2015-09-03 13:27:38 -070028import org.onosproject.pcepio.types.RemoteTENodeDescriptorsTlv;
29import org.onosproject.pcepio.types.RoutingUniverseTlv;
Mahesh Poojary S5afd06c2015-08-21 14:51:04 +053030import org.onosproject.pcepio.types.TELinkAttributesTlv;
Sho SHIMIZUa5356ec2015-09-03 13:27:38 -070031import org.onosproject.pcepio.types.TELinkDescriptorsTlv;
Mahesh Poojary S5afd06c2015-08-21 14:51:04 +053032import org.onosproject.pcepio.types.TENodeAttributesTlv;
33import org.slf4j.Logger;
34import org.slf4j.LoggerFactory;
35
36import com.google.common.base.MoreObjects;
37
Phanendra Manda51fb9c22015-09-01 16:17:41 +053038/**
39 * Provides PCEP TE Object.
40 */
Mahesh Poojary S5afd06c2015-08-21 14:51:04 +053041public class PcepTEObjectVer1 implements PcepTEObject {
42 /*
43 *
44 reference: PCEP Extension for Transporting TE Data draft-dhodylee-pce-pcep-te-data-extn-02.
45 TE Object-Class is [TBD6].
46
47 Two Object-Type values are defined for the TE object:
48
49 o TE Node: TE Object-Type is 1.
50
51 o TE Link: TE Object-Type is 2.
52
53 The format of the TE object body is as follows:
54
55 0 1 2 3
56 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
57 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
58 | Protocol-ID | Flag |R|S|
59 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
60 | TE-ID |
61 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
62 // TLVs //
63 | |
64 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
65 */
66
67 protected static final Logger log = LoggerFactory.getLogger(PcepTEObjectVer1.class);
68
69 public static final byte TE_OBJ_TYPE_NODE_VALUE = 1;
70 public static final byte TE_OBJ_TYPE_LINK_VALUE = 2;
71
72 public static final byte TE_OBJ_CLASS = 101; //TBD6 in RFC.
73 public static final byte TE_OBJECT_VERSION = 1;
74
75 // TE_OBJ_MINIMUM_LENGTH = TEObjectHeaderLen(4)+ TEObjectLen(8)
76 public static final short TE_OBJ_MINIMUM_LENGTH = 12;
77
78 // Signaled ,all default values to be checked.
79 public static final byte DEFAULT_PROTOCOL_ID = 1; //IS-IS Level 1
80 public static final boolean DEFAULT_R_FLAG = false;
81 public static final boolean DEFAULT_S_FLAG = false;
82 public static final int DEFAULT_TE_ID = 0;
83
84 public static final int OBJECT_HEADER_LENGTH = 4;
85 public static final int RIGHT_SHIFT_ONE = 1;
86 public static final int RIGHT_FIRST_FLAG = 0x1;
87 public static final int FLAG_SET_R_FLAG = 0x2;
88 public static final int FLAG_SET_S_FLAG = 0x1;
89 public static final int MINIMUM_COMMON_HEADER_LENGTH = 4;
90 public static final int MINIMUM_TLV_HEADER_LENGTH = 4;
91
92 public static final PcepObjectHeader DEFAULT_TE_OBJECT_HEADER = new PcepObjectHeader(TE_OBJ_CLASS,
93 TE_OBJ_TYPE_NODE_VALUE, PcepObjectHeader.REQ_OBJ_OPTIONAL_PROCESS, PcepObjectHeader.RSP_OBJ_PROCESSED,
94 TE_OBJ_MINIMUM_LENGTH);
95
96 private PcepObjectHeader teObjHeader;
97 private byte yProtocolId;
98 // 2-flags
99 private boolean bRFlag;
100 private boolean bSFlag;
101 private int iTEId;
102 // Optional TLV
103 private LinkedList<PcepValueType> llOptionalTlv;
104
105 /**
106 * Constructor to initialize variables.
107 *
108 * @param teObjHeader TE Object header
109 * @param yProtocolId Protocol-ID
110 * @param bRFlag R-flag
111 * @param bSFlag S-flag
112 * @param iTEId TE-ID
113 * @param llOptionalTlv linked list of Optional TLV
114 */
115 public PcepTEObjectVer1(PcepObjectHeader teObjHeader, byte yProtocolId, boolean bRFlag, boolean bSFlag, int iTEId,
116 LinkedList<PcepValueType> llOptionalTlv) {
117
118 this.teObjHeader = teObjHeader;
119 this.yProtocolId = yProtocolId;
120 this.bRFlag = bRFlag;
121 this.bSFlag = bSFlag;
122 this.iTEId = iTEId;
123 this.llOptionalTlv = llOptionalTlv;
124 }
125
126 @Override
127 public PcepObjectHeader getTEObjHeader() {
128 return this.teObjHeader;
129 }
130
131 @Override
132 public void setTEObjHeader(PcepObjectHeader obj) {
133 this.teObjHeader = obj;
134 }
135
136 @Override
137 public byte getProtocolId() {
138 return this.yProtocolId;
139 }
140
141 @Override
142 public void setProtocolId(byte yProtId) {
143 this.yProtocolId = yProtId;
144 }
145
146 @Override
147 public boolean getRFlag() {
148 return this.bRFlag;
149 }
150
151 @Override
152 public void setRFlag(boolean bRFlag) {
153 this.bRFlag = bRFlag;
154 }
155
156 @Override
157 public boolean getSFlag() {
158 return this.bSFlag;
159 }
160
161 @Override
162 public void setSFlag(boolean bSFlag) {
163 this.bSFlag = bSFlag;
164 }
165
166 @Override
167 public int getTEId() {
168 return this.iTEId;
169 }
170
171 @Override
172 public void setTEId(int iTEId) {
173 this.iTEId = iTEId;
174 }
175
176 @Override
177 public LinkedList<PcepValueType> getOptionalTlv() {
178 return this.llOptionalTlv;
179 }
180
181 @Override
182 public void setOptionalTlv(LinkedList<PcepValueType> llOptionalTlv) {
183 this.llOptionalTlv = llOptionalTlv;
184 }
185
186 /**
187 * Reads from the channel buffer and returns Object of PcepTEObject.
188 *
189 * @param cb of type channel buffer
190 * @return Object of PcepTEObject
191 * @throws PcepParseException if mandatory fields are missing
192 */
193 public static PcepTEObject read(ChannelBuffer cb) throws PcepParseException {
194 log.debug("read");
195
196 PcepObjectHeader teObjHeader;
197 byte yProtocolId;
198 // 2-flags
199 boolean bRFlag;
200 boolean bSFlag;
201 int iTEId;
202 LinkedList<PcepValueType> llOptionalTlv;
203
204 teObjHeader = PcepObjectHeader.read(cb);
205
206 //take only TEObject buffer.
207 ChannelBuffer tempCb = cb.readBytes(teObjHeader.getObjLen() - OBJECT_HEADER_LENGTH);
208
209 yProtocolId = tempCb.readByte();
210 //ignore first two bytes of Flags
211 tempCb.readShort();
212
213 Integer iTemp = (int) tempCb.readByte(); //read 3rd byte Flag
Phanendra Mandaf346ea82015-09-04 15:21:39 -0700214 bSFlag = (iTemp & FLAG_SET_S_FLAG) == FLAG_SET_S_FLAG;
215 bRFlag = (iTemp & FLAG_SET_R_FLAG) == FLAG_SET_R_FLAG;
Mahesh Poojary S5afd06c2015-08-21 14:51:04 +0530216
217 iTEId = tempCb.readInt();
218
219 // parse optional TLV
220 llOptionalTlv = parseOptionalTlv(tempCb);
221
222 return new PcepTEObjectVer1(teObjHeader, yProtocolId, bRFlag, bSFlag, iTEId, llOptionalTlv);
223 }
224
225 @Override
226 public int write(ChannelBuffer cb) throws PcepParseException {
227
228 //write Object header
229 int objStartIndex = cb.writerIndex();
230 int objLenIndex = teObjHeader.write(cb);
231
232 if (objLenIndex <= 0) {
233 throw new PcepParseException("ObjectLength Index is " + objLenIndex);
234 }
235
236 //write Protocol ID
237 cb.writeByte(this.yProtocolId);
238
239 //write Flag
240 cb.writeShort(0);
241
242 byte bTemp = 0;
243 if (bSFlag) {
244 bTemp = FLAG_SET_S_FLAG;
245 }
246
247 if (bRFlag) {
248 bTemp = (byte) (bTemp | FLAG_SET_R_FLAG);
249 }
250 cb.writeByte(bTemp);
251
252 //write TEId
253 cb.writeInt(iTEId);
254
255 // Add optional TLV
256 packOptionalTlv(cb);
257
258 //Update object length now
259 int length = cb.writerIndex() - objStartIndex;
260
261 //will be helpful during print().
262 teObjHeader.setObjLen((short) length);
263
264 cb.setShort(objLenIndex, (short) length);
265
266 return cb.writerIndex();
267 }
268
269 /**
270 * Returns Linked list of PCEP Value Type.
271 *
272 * @param cb of channel buffer
273 * @return Linked list of PCEP Value Type
274 * @throws PcepParseException if mandatory fields are missing
275 */
276 protected static LinkedList<PcepValueType> parseOptionalTlv(ChannelBuffer cb) throws PcepParseException {
277
278 LinkedList<PcepValueType> llOutOptionalTlv;
279
Sho SHIMIZU9b8274c2015-09-04 15:54:24 -0700280 llOutOptionalTlv = new LinkedList<>();
Mahesh Poojary S5afd06c2015-08-21 14:51:04 +0530281
282 while (MINIMUM_TLV_HEADER_LENGTH <= cb.readableBytes()) {
283
284 PcepValueType tlv;
285 short hType = cb.readShort();
286 short hLength = cb.readShort();
287 long lValue = 0;
288
289 switch (hType) {
290
Sho SHIMIZUa5356ec2015-09-03 13:27:38 -0700291 case RoutingUniverseTlv.TYPE:
Mahesh Poojary S5afd06c2015-08-21 14:51:04 +0530292 lValue = cb.readLong();
Sho SHIMIZUa5356ec2015-09-03 13:27:38 -0700293 tlv = new RoutingUniverseTlv(lValue);
Mahesh Poojary S5afd06c2015-08-21 14:51:04 +0530294 break;
Sho SHIMIZUa5356ec2015-09-03 13:27:38 -0700295 case LocalTENodeDescriptorsTlv.TYPE:
296 tlv = LocalTENodeDescriptorsTlv.read(cb, hLength);
Mahesh Poojary S5afd06c2015-08-21 14:51:04 +0530297 break;
Sho SHIMIZUa5356ec2015-09-03 13:27:38 -0700298 case RemoteTENodeDescriptorsTlv.TYPE:
299 tlv = RemoteTENodeDescriptorsTlv.read(cb, hLength);
Mahesh Poojary S5afd06c2015-08-21 14:51:04 +0530300 break;
Sho SHIMIZUa5356ec2015-09-03 13:27:38 -0700301 case TELinkDescriptorsTlv.TYPE:
302 tlv = TELinkDescriptorsTlv.read(cb, hLength);
Mahesh Poojary S5afd06c2015-08-21 14:51:04 +0530303 break;
304 case TENodeAttributesTlv.TYPE:
305 tlv = TENodeAttributesTlv.read(cb, hLength);
306 break;
307 case TELinkAttributesTlv.TYPE:
308 tlv = TELinkAttributesTlv.read(cb, hLength);
309 break;
310 default:
311 throw new PcepParseException("Unsupported TLV type :" + hType);
312 }
313
314 // Check for the padding
315 int pad = hLength % 4;
316 if (0 < pad) {
317 pad = 4 - pad;
318 if (pad <= cb.readableBytes()) {
319 cb.skipBytes(pad);
320 }
321 }
322
323 llOutOptionalTlv.add(tlv);
324 }
325
326 if (0 < cb.readableBytes()) {
327
328 throw new PcepParseException("Optional Tlv parsing error. Extra bytes received.");
329 }
Mahesh Poojary S5afd06c2015-08-21 14:51:04 +0530330 return llOutOptionalTlv;
331 }
332
333 /**
334 * Returns the writer index.
335 *
336 * @param cb of type channel buffer
337 * @return the writer index.
338 */
339 protected int packOptionalTlv(ChannelBuffer cb) {
340
341 ListIterator<PcepValueType> listIterator = llOptionalTlv.listIterator();
342
343 while (listIterator.hasNext()) {
344 PcepValueType tlv = listIterator.next();
345
Sho SHIMIZUde09fa02015-09-03 09:39:52 -0700346 if (tlv == null) {
Mahesh Poojary S5afd06c2015-08-21 14:51:04 +0530347 log.debug("TLV is null from OptionalTlv list");
348 continue;
349 }
350 tlv.write(cb);
351
352 // need to take care of padding
353 int pad = tlv.getLength() % 4;
354
355 if (0 != pad) {
356 pad = 4 - pad;
357 for (int i = 0; i < pad; ++i) {
358 cb.writeByte((byte) 0);
359 }
360 }
361 }
Mahesh Poojary S5afd06c2015-08-21 14:51:04 +0530362 return cb.writerIndex();
363 }
364
Phanendra Manda51fb9c22015-09-01 16:17:41 +0530365 /**
366 * Builder class for PCEP te object.
367 */
Mahesh Poojary S5afd06c2015-08-21 14:51:04 +0530368 public static class Builder implements PcepTEObject.Builder {
369 private boolean bIsHeaderSet = false;
370 private boolean bIsProtocolIdSet = false;
371 private boolean bIsRFlagSet = false;
372 private boolean bIsSFlagSet = false;
373 private boolean bIsTEIdSet = false;
374
375 private PcepObjectHeader teObjHeader;
376 private byte yProtocolId;
377 private boolean bRFlag;
378 private boolean bSFlag;
379 private int iTEId;
Sho SHIMIZU9b8274c2015-09-04 15:54:24 -0700380 private LinkedList<PcepValueType> llOptionalTlv = new LinkedList<>();
Mahesh Poojary S5afd06c2015-08-21 14:51:04 +0530381
382 private boolean bIsPFlagSet = false;
383 private boolean bPFlag;
384
385 private boolean bIsIFlagSet = false;
386 private boolean bIFlag;
387
388 @Override
389 public PcepTEObject build() {
390 PcepObjectHeader teObjHeader = this.bIsHeaderSet ? this.teObjHeader : DEFAULT_TE_OBJECT_HEADER;
391
392 byte yProtocolId = this.bIsProtocolIdSet ? this.yProtocolId : DEFAULT_PROTOCOL_ID;
393 boolean bRFlag = this.bIsRFlagSet ? this.bRFlag : DEFAULT_R_FLAG;
394 boolean bSFlag = this.bIsSFlagSet ? this.bSFlag : DEFAULT_S_FLAG;
395 int iTEId = this.bIsTEIdSet ? this.iTEId : DEFAULT_TE_ID;
396
397 if (bIsPFlagSet) {
398 teObjHeader.setPFlag(bPFlag);
399 }
400
401 if (bIsIFlagSet) {
402 teObjHeader.setIFlag(bIFlag);
403 }
404
405 return new PcepTEObjectVer1(teObjHeader, yProtocolId, bRFlag, bSFlag, iTEId, llOptionalTlv);
406
407 }
408
409 @Override
410 public PcepObjectHeader getTEObjHeader() {
411 return this.teObjHeader;
412 }
413
414 @Override
415 public Builder setTEObjHeader(PcepObjectHeader obj) {
416 this.teObjHeader = obj;
417 this.bIsHeaderSet = true;
418 return this;
419 }
420
421 @Override
422 public byte getProtocolId() {
423 return this.yProtocolId;
424 }
425
426 @Override
427 public Builder setProtocolId(byte yProtId) {
428 this.yProtocolId = yProtId;
429 this.bIsProtocolIdSet = true;
430 return this;
431 }
432
433 @Override
434 public boolean getRFlag() {
435 return this.bRFlag;
436 }
437
438 @Override
439 public Builder setRFlag(boolean bRFlag) {
440 this.bRFlag = bRFlag;
441 this.bIsRFlagSet = true;
442 return this;
443 }
444
445 @Override
446 public boolean getSFlag() {
447 return this.bSFlag;
448 }
449
450 @Override
451 public Builder setSFlag(boolean bSFlag) {
452 this.bSFlag = bSFlag;
453 this.bIsSFlagSet = true;
454 return this;
455 }
456
457 @Override
458 public int getTEId() {
459 return this.iTEId;
460 }
461
462 @Override
463 public Builder setTEId(int iTEId) {
464 this.iTEId = iTEId;
465 this.bIsTEIdSet = true;
466 return this;
467 }
468
469 @Override
470 public LinkedList<PcepValueType> getOptionalTlv() {
471 return this.llOptionalTlv;
472 }
473
474 @Override
475 public Builder setOptionalTlv(LinkedList<PcepValueType> llOptionalTlv) {
476 this.llOptionalTlv = llOptionalTlv;
477 return this;
478 }
479
480 @Override
481 public Builder setPFlag(boolean value) {
482 this.bPFlag = value;
483 this.bIsPFlagSet = true;
484 return this;
485 }
486
487 @Override
488 public Builder setIFlag(boolean value) {
489 this.bIFlag = value;
490 this.bIsIFlagSet = true;
491 return this;
492 }
493 }
494
495 @Override
496 public String toString() {
Sho SHIMIZU7cdbcf72015-09-03 14:43:05 -0700497 return MoreObjects.toStringHelper(getClass())
498 .add("ObjectHeader", teObjHeader)
499 .add("ProtocolId", yProtocolId)
500 .add("RFlag", (bRFlag) ? 1 : 0)
501 .add("SFlag", (bSFlag) ? 1 : 0)
502 .add("TeId", iTEId)
503 .add("OptionalTlv", llOptionalTlv)
504 .toString();
Mahesh Poojary S5afd06c2015-08-21 14:51:04 +0530505 }
506}