b1c6940658bbeb428e6b288d6dd9982fa69f5102
[onosfw.git] /
1 /*
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
17 package org.onosproject.pcepio.protocol.ver1;
18
19 import java.util.LinkedList;
20 import java.util.ListIterator;
21
22 import org.jboss.netty.buffer.ChannelBuffer;
23 import org.onosproject.pcepio.exceptions.PcepParseException;
24 import org.onosproject.pcepio.protocol.PcepTEObject;
25 import org.onosproject.pcepio.types.LocalTENodeDescriptorsTlv;
26 import org.onosproject.pcepio.types.PcepObjectHeader;
27 import org.onosproject.pcepio.types.PcepValueType;
28 import org.onosproject.pcepio.types.RemoteTENodeDescriptorsTlv;
29 import org.onosproject.pcepio.types.RoutingUniverseTlv;
30 import org.onosproject.pcepio.types.TELinkAttributesTlv;
31 import org.onosproject.pcepio.types.TELinkDescriptorsTlv;
32 import org.onosproject.pcepio.types.TENodeAttributesTlv;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36 import com.google.common.base.MoreObjects;
37
38 /**
39  * Provides PCEP TE Object.
40  */
41 public 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
214         bSFlag = (iTemp & FLAG_SET_S_FLAG) == FLAG_SET_S_FLAG;
215         bRFlag = (iTemp & FLAG_SET_R_FLAG) == FLAG_SET_R_FLAG;
216
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
280         llOutOptionalTlv = new LinkedList<>();
281
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
291             case RoutingUniverseTlv.TYPE:
292                 lValue = cb.readLong();
293                 tlv = new RoutingUniverseTlv(lValue);
294                 break;
295             case LocalTENodeDescriptorsTlv.TYPE:
296                 tlv = LocalTENodeDescriptorsTlv.read(cb, hLength);
297                 break;
298             case RemoteTENodeDescriptorsTlv.TYPE:
299                 tlv = RemoteTENodeDescriptorsTlv.read(cb, hLength);
300                 break;
301             case TELinkDescriptorsTlv.TYPE:
302                 tlv = TELinkDescriptorsTlv.read(cb, hLength);
303                 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         }
330         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
346             if (tlv == null) {
347                 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         }
362         return cb.writerIndex();
363     }
364
365     /**
366      * Builder class for PCEP te object.
367      */
368     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;
380         private LinkedList<PcepValueType> llOptionalTlv = new LinkedList<>();
381
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() {
497         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();
505     }
506 }