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