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