9c75b3a6e2dd0b9bdb479c83c9f00cc1054e2dbb
[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.PcepSrpObject;
25 import org.onosproject.pcepio.types.PcepObjectHeader;
26 import org.onosproject.pcepio.types.PcepValueType;
27 import org.onosproject.pcepio.types.SymbolicPathNameTlv;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 import com.google.common.base.MoreObjects;
32
33 /**
34  * Provides PCEP SRP obejct.
35  */
36 public class PcepSrpObjectVer1 implements PcepSrpObject {
37
38     /*
39      * ref : draft-ietf-pce-stateful-pce-10, section : 7.2
40     0                   1                   2                   3
41     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
42     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
43     | Object-Class  |   OT  |Res|P|I|   Object Length (bytes)       |
44     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
45     |                          Flags                              |R|
46     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
47     |                        SRP-ID-number                          |
48     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
49     |                                                               |
50     //                      Optional TLVs                          //
51     |                                                               |
52     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
53
54      */
55     protected static final Logger log = LoggerFactory.getLogger(PcepSrpObjectVer1.class);
56
57     public static final byte SRP_OBJ_TYPE = 1;
58     public static final byte SRP_OBJ_CLASS = 33;
59     public static final byte SRP_OBJECT_VERSION = 1;
60     public static final short SRP_OBJ_MINIMUM_LENGTH = 12;
61     public static final int MINIMUM_COMMON_HEADER_LENGTH = 4;
62     public static final boolean DEFAULT_RFLAG = false;
63
64     static final PcepObjectHeader DEFAULT_SRP_OBJECT_HEADER = new PcepObjectHeader(SRP_OBJ_CLASS, SRP_OBJ_TYPE,
65             PcepObjectHeader.REQ_OBJ_OPTIONAL_PROCESS, PcepObjectHeader.RSP_OBJ_PROCESSED, SRP_OBJ_MINIMUM_LENGTH);
66
67     private PcepObjectHeader srpObjHeader;
68     private static int flags;
69     private boolean bRFlag;
70     private int srpId;
71
72     //Optional TLV
73     private LinkedList<PcepValueType> llOptionalTlv;
74     public static final byte BBIT_SET = 1;
75     public static final byte BBIT_RESET = 0;
76
77     /**
78      * Constructor to initialize member variables.
79      *
80      * @param srpObjHeader srp object header
81      * @param bRFlag R flag
82      * @param srpID srp Id
83      * @param llOptionalTlv list of optional tlv
84      */
85     public PcepSrpObjectVer1(PcepObjectHeader srpObjHeader, boolean bRFlag, int srpID,
86             LinkedList<PcepValueType> llOptionalTlv) {
87
88         this.srpObjHeader = srpObjHeader;
89         this.bRFlag = bRFlag;
90         this.srpId = srpID;
91         this.llOptionalTlv = llOptionalTlv;
92     }
93
94     /**
95      * sets the SRP object header.
96      *
97      * @param obj srp object header
98      */
99     public void setSrpObjHeader(PcepObjectHeader obj) {
100         this.srpObjHeader = obj;
101     }
102
103     @Override
104     public void setSrpID(int srpID) {
105         this.srpId = srpID;
106     }
107
108     @Override
109     public void setRFlag(boolean bRFlag) {
110         this.bRFlag = bRFlag;
111     }
112
113     /**
114      * Returns SRP object header.
115      *
116      * @return srpObjHeader
117      */
118     public PcepObjectHeader getSrpObjHeader() {
119         return this.srpObjHeader;
120     }
121
122     @Override
123     public int getSrpID() {
124         return this.srpId;
125     }
126
127     @Override
128     public boolean getRFlag() {
129         return this.bRFlag;
130     }
131
132     @Override
133     public void setOptionalTlv(LinkedList<PcepValueType> llOptionalTlv) {
134         this.llOptionalTlv = llOptionalTlv;
135
136     }
137
138     @Override
139     public LinkedList<PcepValueType> getOptionalTlv() {
140         return this.llOptionalTlv;
141     }
142
143     /**
144      * Reads from channel buffer and returns instance of PCEP SRP object.
145      *
146      * @param cb of channel buffer.
147      * @return PCEP SRP object
148      * @throws PcepParseException when srp object is not received in channel buffer
149      */
150     public static PcepSrpObject read(ChannelBuffer cb) throws PcepParseException {
151
152         log.debug("SrpObject::read");
153         PcepObjectHeader srpObjHeader;
154         boolean bRFlag;
155
156         int srpID;
157         int flags;
158         LinkedList<PcepValueType> llOptionalTlv = new LinkedList<>();
159
160         srpObjHeader = PcepObjectHeader.read(cb);
161
162         if (srpObjHeader.getObjClass() != SRP_OBJ_CLASS) {
163             throw new PcepParseException("SRP object expected. But received " + srpObjHeader.getObjClass());
164         }
165
166         //take only SrpObject buffer.
167         ChannelBuffer tempCb = cb.readBytes(srpObjHeader.getObjLen() - MINIMUM_COMMON_HEADER_LENGTH);
168         flags = tempCb.readInt();
169         bRFlag = 0 < flags;
170         srpID = tempCb.readInt();
171
172         llOptionalTlv = parseOptionalTlv(tempCb);
173
174         return new PcepSrpObjectVer1(srpObjHeader, bRFlag, srpID, llOptionalTlv);
175     }
176
177     @Override
178     public int write(ChannelBuffer cb) throws PcepParseException {
179
180         int objStartIndex = cb.writerIndex();
181
182         //write common header
183         int objLenIndex = srpObjHeader.write(cb);
184
185         //write Flags
186         byte bFlag;
187
188         bFlag = (bRFlag) ? BBIT_SET : BBIT_RESET;
189
190         cb.writeInt(bFlag);
191
192         //write SrpId
193         cb.writeInt(srpId);
194
195         // Add optional TLV
196         if (!packOptionalTlv(cb)) {
197             throw new PcepParseException("Failed to write srp tlv to channel buffer.");
198         }
199
200         //now write SRP Object Length
201         cb.setShort(objLenIndex, (short) (cb.writerIndex() - objStartIndex));
202
203         return cb.writerIndex();
204     }
205
206     /**
207      * Parse Optional TLvs from the channel buffer.
208      *
209      * @param cb of type channel buffer
210      * @return list of optional tlvs
211      * @throws PcepParseException when unsupported tlv is received in srp object
212      */
213     public static LinkedList<PcepValueType> parseOptionalTlv(ChannelBuffer cb) throws PcepParseException {
214
215         LinkedList<PcepValueType> llOutOptionalTlv = new LinkedList<>();
216
217         while (MINIMUM_COMMON_HEADER_LENGTH <= cb.readableBytes()) {
218
219             PcepValueType tlv;
220             short hType = cb.readShort();
221             short hLength = cb.readShort();
222
223             switch (hType) {
224
225             case SymbolicPathNameTlv.TYPE:
226                 tlv = SymbolicPathNameTlv.read(cb, hLength);
227                 cb.skipBytes(hLength);
228                 break;
229
230             default:
231                 throw new PcepParseException("Unsupported TLV received in SRP Object.");
232             }
233
234             // Check for the padding
235             int pad = hLength % 4;
236             if (0 < pad) {
237                 pad = 4 - pad;
238                 if (pad <= cb.readableBytes()) {
239                     cb.skipBytes(pad);
240                 }
241             }
242             llOutOptionalTlv.add(tlv);
243         }
244
245         return llOutOptionalTlv;
246     }
247
248     /**
249      * Writes optional tlvs to channel buffer.
250      *
251      * @param cb of type channel buffer
252      * @return true if writing optional tlv to channel buffer is success.
253      */
254     protected boolean packOptionalTlv(ChannelBuffer cb) {
255
256         ListIterator<PcepValueType> listIterator = llOptionalTlv.listIterator();
257
258         while (listIterator.hasNext()) {
259             PcepValueType tlv = listIterator.next();
260
261             if (tlv == null) {
262                 log.debug("tlv is null from OptionalTlv list");
263                 continue;
264             }
265             tlv.write(cb);
266
267             // need to take care of padding
268             int pad = tlv.getLength() % 4;
269
270             if (0 != pad) {
271                 pad = 4 - pad;
272                 for (int i = 0; i < pad; ++i) {
273                     cb.writeByte((byte) 0);
274                 }
275             }
276         }
277
278         return true;
279     }
280
281     /**
282      * Builder class for PCEP srp Object.
283      */
284     public static class Builder implements PcepSrpObject.Builder {
285         private boolean bIsHeaderSet = false;
286         private boolean bIsSrpIdset = false;
287         private boolean bIsRFlagSet = false;
288
289         private PcepObjectHeader srpObjHeader;
290         private int srpId;
291         private boolean bRFlag;
292         LinkedList<PcepValueType> llOptionalTlv = new LinkedList<>();
293
294         private boolean bIsPFlagSet = false;
295         private boolean bPFlag;
296
297         private boolean bIsIFlagSet = false;
298         private boolean bIFlag;
299
300         @Override
301         public PcepSrpObject build() throws PcepParseException {
302             PcepObjectHeader srpObjHeader = this.bIsHeaderSet ? this.srpObjHeader : DEFAULT_SRP_OBJECT_HEADER;
303
304             boolean bRFlag = this.bIsRFlagSet ? this.bRFlag : DEFAULT_RFLAG;
305
306             if (!this.bIsSrpIdset) {
307                 throw new PcepParseException("SrpID not set while building SRP Object.");
308             }
309
310             if (bIsPFlagSet) {
311                 srpObjHeader.setPFlag(bPFlag);
312             }
313
314             if (bIsIFlagSet) {
315                 srpObjHeader.setIFlag(bIFlag);
316             }
317
318             return new PcepSrpObjectVer1(srpObjHeader, bRFlag, this.srpId, this.llOptionalTlv);
319         }
320
321         @Override
322         public PcepObjectHeader getSrpObjHeader() {
323             return this.srpObjHeader;
324         }
325
326         @Override
327         public Builder setSrpObjHeader(PcepObjectHeader obj) {
328             this.srpObjHeader = obj;
329             this.bIsHeaderSet = true;
330             return this;
331         }
332
333         @Override
334         public int getSrpID() {
335             return this.srpId;
336         }
337
338         @Override
339         public Builder setSrpID(int srpID) {
340             this.srpId = srpID;
341             this.bIsSrpIdset = true;
342             return this;
343         }
344
345         @Override
346         public boolean getRFlag() {
347             return this.bRFlag;
348         }
349
350         @Override
351         public Builder setRFlag(boolean bRFlag) {
352             this.bRFlag = bRFlag;
353             this.bIsRFlagSet = true;
354             return this;
355         }
356
357         @Override
358         public Builder setOptionalTlv(LinkedList<PcepValueType> llOptionalTlv) {
359             this.llOptionalTlv = llOptionalTlv;
360             return this;
361         }
362
363         @Override
364         public LinkedList<PcepValueType> getOptionalTlv() {
365             return this.llOptionalTlv;
366         }
367
368         @Override
369         public Builder setPFlag(boolean value) {
370             this.bPFlag = value;
371             this.bIsPFlagSet = true;
372             return this;
373         }
374
375         @Override
376         public Builder setIFlag(boolean value) {
377             this.bIFlag = value;
378             this.bIsIFlagSet = true;
379             return this;
380         }
381
382     }
383
384     @Override
385     public String toString() {
386         return MoreObjects.toStringHelper(getClass())
387                 .add("RFlag", bRFlag)
388                 .add("SRPID", srpId)
389                 .add("OptionalTlvList", llOptionalTlv)
390                 .toString();
391     }
392 }