2e01bdaaa2b4ddb2fbe381c7df7576a5e814d5b5
[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.PcepIroObject;
25 import org.onosproject.pcepio.types.IPv4SubObject;
26 import org.onosproject.pcepio.types.PcepObjectHeader;
27 import org.onosproject.pcepio.types.PcepValueType;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 import com.google.common.base.MoreObjects;
32
33 /**
34  * Provides PCEP iro object.
35  */
36 public class PcepIroObjectVer1 implements PcepIroObject {
37
38     /*
39       0                   1                   2                   3
40       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
41       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
42       |                                                               |
43       //                      (Sub-objects)                           //
44       |                                                               |
45       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
46
47                      The IRO Object format
48
49         Each IPV4 suboject
50
51         0                   1                   2                   3
52         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
53         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
54         |L|    Type     |     Length    | IPv4 address (4 bytes)        |
55         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
56         | IPv4 address (continued)      | Prefix Length |      Resvd    |
57         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
58      */
59     protected static final Logger log = LoggerFactory.getLogger(PcepIroObjectVer1.class);
60
61     public static final byte IRO_OBJ_TYPE = 1;
62     public static final byte IRO_OBJ_CLASS = 10;
63     public static final byte IRO_OBJECT_VERSION = 1;
64     public static final short IRO_OBJ_MINIMUM_LENGTH = 12;
65     public static final int OBJECT_HEADER_LENGTH = 4;
66     public static final int YTYPE_SHIFT_VALUE = 0x7F;
67
68     public static final PcepObjectHeader DEFAULT_IRO_OBJECT_HEADER = new PcepObjectHeader(IRO_OBJ_CLASS, IRO_OBJ_TYPE,
69             PcepObjectHeader.REQ_OBJ_OPTIONAL_PROCESS, PcepObjectHeader.RSP_OBJ_PROCESSED, IRO_OBJ_MINIMUM_LENGTH);
70
71     private short iroObjType = 0;
72     private byte yLength;
73     private byte yPrefixLength;
74     private byte yResvd;
75     private PcepObjectHeader iroObjHeader;
76     private LinkedList<PcepValueType> llSubObjects = new LinkedList<>();
77
78     /**
79      * Default constructor.
80      */
81     public PcepIroObjectVer1() {
82         this.iroObjHeader = null;
83         this.iroObjType = 0;
84         this.yLength = 0;
85     }
86
87     /**
88      * Constructor to initialize member variables.
89      *
90      * @param iroObjHeader IRO object header
91      * @param llSubObjects list of sub-objects
92      */
93     public PcepIroObjectVer1(PcepObjectHeader iroObjHeader, LinkedList<PcepValueType> llSubObjects) {
94         this.iroObjHeader = iroObjHeader;
95         this.llSubObjects = llSubObjects;
96     }
97
98     /**
99      * Returns object header.
100      *
101      * @return iroObjHeader IRO object header
102      */
103     public PcepObjectHeader getIroObjHeader() {
104         return this.iroObjHeader;
105     }
106
107     /**
108      * Sets IRO Object Header.
109      *
110      * @param obj IRO object header
111      */
112     public void setIroObjHeader(PcepObjectHeader obj) {
113         this.iroObjHeader = obj;
114     }
115
116     @Override
117     public LinkedList<PcepValueType> getSubObjects() {
118         return this.llSubObjects;
119     }
120
121     @Override
122     public void setSubObjects(LinkedList<PcepValueType> llSubObjects) {
123         this.llSubObjects = llSubObjects;
124     }
125
126     /**
127      * Reads from channel buffer and return object of PcepIroObject.
128      *
129      * @param cb of type channel buffer
130      * @return object of PcepIroObject
131      * @throws PcepParseException while parsing from channel buffer
132      */
133     public static PcepIroObject read(ChannelBuffer cb) throws PcepParseException {
134
135         PcepObjectHeader iroObjHeader;
136         LinkedList<PcepValueType> llSubObjects;
137
138         iroObjHeader = PcepObjectHeader.read(cb);
139
140         //take only IroObject buffer.
141         ChannelBuffer tempCb = cb.readBytes(iroObjHeader.getObjLen() - OBJECT_HEADER_LENGTH);
142         llSubObjects = parseSubObjects(tempCb);
143         return new PcepIroObjectVer1(iroObjHeader, llSubObjects);
144     }
145
146     /**
147      * Returns linked list of sub objects.
148      *
149      * @param cb of type channel buffer
150      * @return linked list of sub objects
151      * @throws PcepParseException while parsing subobjects from channel buffer
152      */
153     protected static LinkedList<PcepValueType> parseSubObjects(ChannelBuffer cb) throws PcepParseException {
154
155         LinkedList<PcepValueType> llSubObjects = new LinkedList<>();
156
157         while (0 < cb.readableBytes()) {
158
159             //check the Type of the Subobjects.
160             byte yType = cb.readByte();
161             yType = (byte) (yType & (YTYPE_SHIFT_VALUE));
162             byte hLength = cb.readByte();
163
164             PcepValueType subObj;
165             switch (yType) {
166
167             case IPv4SubObject.TYPE:
168                 subObj = IPv4SubObject.read(cb);
169                 break;
170
171             default:
172                 throw new PcepParseException("Invalid sub object. Type: " + (int) yType);
173             }
174
175             // Check for the padding
176             int pad = hLength % 4;
177             if (0 < pad) {
178                 pad = 4 - pad;
179                 if (pad <= cb.readableBytes()) {
180                     cb.skipBytes(pad);
181                 }
182             }
183             llSubObjects.add(subObj);
184         }
185         return llSubObjects;
186     }
187
188     @Override
189     public int write(ChannelBuffer cb) throws PcepParseException {
190         //write Object header
191         int objStartIndex = cb.writerIndex();
192
193         int objLenIndex = iroObjHeader.write(cb);
194
195         if (objLenIndex <= 0) {
196             throw new PcepParseException(" ObjectLength is " + objLenIndex);
197         }
198
199         ListIterator<PcepValueType> listIterator = llSubObjects.listIterator();
200         while (listIterator.hasNext()) {
201             listIterator.next().write(cb);
202         }
203
204         //Update object length now
205         int length = cb.writerIndex() - objStartIndex;
206         //will be helpful during print().
207         iroObjHeader.setObjLen((short) length);
208         // As per RFC the length of object should be
209         // multiples of 4
210         int pad = length % 4;
211         if (pad != 0) {
212             pad = 4 - pad;
213             for (int i = 0; i < pad; i++) {
214                 cb.writeByte((byte) 0);
215             }
216             length = length + pad;
217         }
218         cb.setShort(objLenIndex, (short) length);
219         objLenIndex = cb.writerIndex();
220         return objLenIndex;
221     }
222
223     /**
224      * Builder class for PCEP iro object.
225      */
226     public static class Builder implements PcepIroObject.Builder {
227
228         private boolean bIsHeaderSet = false;
229
230         private PcepObjectHeader iroObjHeader;
231         LinkedList<PcepValueType> llSubObjects = new LinkedList<>();
232
233         private boolean bIsPFlagSet = false;
234         private boolean bPFlag;
235
236         private boolean bIsIFlagSet = false;
237         private boolean bIFlag;
238
239         @Override
240         public PcepIroObject build() {
241
242             PcepObjectHeader iroObjHeader = this.bIsHeaderSet ? this.iroObjHeader : DEFAULT_IRO_OBJECT_HEADER;
243
244             if (bIsPFlagSet) {
245                 iroObjHeader.setPFlag(bPFlag);
246             }
247
248             if (bIsIFlagSet) {
249                 iroObjHeader.setIFlag(bIFlag);
250             }
251
252             return new PcepIroObjectVer1(iroObjHeader, this.llSubObjects);
253         }
254
255         @Override
256         public PcepObjectHeader getIroObjHeader() {
257             return this.iroObjHeader;
258         }
259
260         @Override
261         public Builder setIroObjHeader(PcepObjectHeader obj) {
262             this.iroObjHeader = obj;
263             this.bIsHeaderSet = true;
264             return this;
265         }
266
267         @Override
268         public LinkedList<PcepValueType> getSubObjects() {
269             return this.llSubObjects;
270         }
271
272         @Override
273         public Builder setSubObjects(LinkedList<PcepValueType> llSubObjects) {
274             this.llSubObjects = llSubObjects;
275             return this;
276         }
277
278         @Override
279         public Builder setPFlag(boolean value) {
280             this.bPFlag = value;
281             this.bIsPFlagSet = true;
282             return this;
283         }
284
285         @Override
286         public Builder setIFlag(boolean value) {
287             this.bIFlag = value;
288             this.bIsIFlagSet = true;
289             return this;
290         }
291     }
292
293     @Override
294     public String toString() {
295         return MoreObjects.toStringHelper(getClass())
296                 .add("IroObjectHeader", iroObjHeader)
297                 .add("SubObjects", llSubObjects).toString();
298     }
299 }