blob: 4df42e05ffa01112d9d6a583afe06607d766e3e9 [file] [log] [blame]
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -07001/*
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.PcepRroObject;
25import org.onosproject.pcepio.types.IPv4SubObject;
26import org.onosproject.pcepio.types.IPv6SubObject;
27import org.onosproject.pcepio.types.LabelSubObject;
28import org.onosproject.pcepio.types.PcepObjectHeader;
29import org.onosproject.pcepio.types.PcepValueType;
30import org.slf4j.Logger;
31import org.slf4j.LoggerFactory;
32
33import com.google.common.base.MoreObjects;
34
35/**
36 * Provides PCEP RRO object.
37 */
38public class PcepRroObjectVer1 implements PcepRroObject {
39
40 /*
41 * rfc3209
42 0 1 2 3
43 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
44 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
45 | Object-Class | OT |Res|P|I| Object Length (bytes) |
46 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
47 | |
48 // (Subobjects) //
49 | |
50 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
51
52 Each subobject has its own Length
53 field. The length contains the total length of the subobject in
54 bytes, including the Type and Length fields. The length MUST always
55 be a multiple of 4, and at least 4.
56
57 An empty RRO with no subobjects is considered illegal.
58 Three kinds of subobjects are currently defined.
59
60 Subobject 1: IPv4 address
61
62 0 1 2 3
63 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
64 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
65 | Type | Length | IPv4 address (4 bytes) |
66 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
67 | IPv4 address (continued) | Prefix Length | Flags |
68 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
69
70 Subobject 2: IPv6 address
71
72 0 1 2 3
73 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
74 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
75 | Type | Length | IPv6 address (16 bytes) |
76 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
77 | IPv6 address (continued) |
78 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
79 | IPv6 address (continued) |
80 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
81 | IPv6 address (continued) |
82 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
83 | IPv6 address (continued) | Prefix Length | Flags |
84 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
85
86 Subobject 3, Label
87
88 0 1 2 3
89 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
90 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
91 | Type | Length | Flags | C-Type |
92 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
93 | Contents of Label Object |
94 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
95
96 */
97 protected static final Logger log = LoggerFactory.getLogger(PcepRroObjectVer1.class);
98
99 public static final byte RRO_OBJ_TYPE = 1;
100 public static final byte RRO_OBJ_CLASS = 8;
101 public static final byte RRO_OBJECT_VERSION = 1;
102 public static final short RRO_OBJ_MINIMUM_LENGTH = 12;
103 public static final int OBJECT_HEADER_LENGTH = 4;
104 public static final int YTYPE_SHIFT_VALUE = 0x7F;
105
106 static final PcepObjectHeader DEFAULT_RRO_OBJECT_HEADER = new PcepObjectHeader(RRO_OBJ_CLASS, RRO_OBJ_TYPE,
107 PcepObjectHeader.REQ_OBJ_OPTIONAL_PROCESS, PcepObjectHeader.RSP_OBJ_PROCESSED, RRO_OBJ_MINIMUM_LENGTH);
108
109 private short rroObjType = 0;
110 private byte length;
111 private byte prefixLength;
112 private byte resvd;
113 PcepObjectHeader rroObjHeader;
Sho SHIMIZU9b8274c2015-09-04 15:54:24 -0700114 private LinkedList<PcepValueType> llSubObjects = new LinkedList<>();
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -0700115
116 /**
117 * Reset variables.
118 */
119 public PcepRroObjectVer1() {
120 this.rroObjHeader = null;
121 this.rroObjType = 0;
122 this.length = 0;
123 }
124
125 /**
126 * constructor to initialize parameters for RRO object.
127 *
128 * @param rroObjHeader RRO object header
129 * @param llSubObjects list of sub objects
130 */
131 public PcepRroObjectVer1(PcepObjectHeader rroObjHeader, LinkedList<PcepValueType> llSubObjects) {
132 this.rroObjHeader = rroObjHeader;
133 this.llSubObjects = llSubObjects;
134 }
135
136 /**
137 * Returns PCEP RRO Object Header.
138 *
139 * @return rroObjHeader RRO Object header
140 */
141 public PcepObjectHeader getRroObjHeader() {
142 return this.rroObjHeader;
143 }
144
145 /**
146 * Sets PCEP RRO Object Header.
147 *
148 * @param obj Object header
149 */
150 public void setRroObjHeader(PcepObjectHeader obj) {
151 this.rroObjHeader = obj;
152 }
153
154 @Override
155 public LinkedList<PcepValueType> getSubObjects() {
156 return this.llSubObjects;
157 }
158
159 @Override
160 public void setSubObjects(LinkedList<PcepValueType> llSubObjects) {
161 this.llSubObjects = llSubObjects;
162 }
163
164 /**
165 * Reads the channel buffer and returns object of PcepRroObject.
166 *
167 * @param cb of type channel buffer
168 * @return object of PcepRroObject
169 * @throws PcepParseException when fails to read from channel buffer
170 */
171 public static PcepRroObject read(ChannelBuffer cb) throws PcepParseException {
172
173 PcepObjectHeader rroObjHeader;
174 LinkedList<PcepValueType> llSubObjects;
175 rroObjHeader = PcepObjectHeader.read(cb);
176
177 //take only RroObject buffer.
178 ChannelBuffer tempCb = cb.readBytes(rroObjHeader.getObjLen() - OBJECT_HEADER_LENGTH);
179 llSubObjects = parseSubObjects(tempCb);
180
181 return new PcepRroObjectVer1(rroObjHeader, llSubObjects);
182 }
183
184 /**
185 * Returns list of sub objects.
186 *
187 * @param cb of type channel buffer
188 * @return list of sub objects
189 * @throws PcepParseException when fails to parse list of sub objects
190 */
191 protected static LinkedList<PcepValueType> parseSubObjects(ChannelBuffer cb) throws PcepParseException {
192
Sho SHIMIZU9b8274c2015-09-04 15:54:24 -0700193 LinkedList<PcepValueType> llSubObjects = new LinkedList<>();
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -0700194
195 while (0 < cb.readableBytes()) {
196
197 //check the Type of the Sub objects
198 byte yType = cb.readByte();
199 yType = (byte) (yType & (YTYPE_SHIFT_VALUE));
200 byte hLength = cb.readByte();
201
202 PcepValueType subObj;
203
204 switch (yType) {
205
206 case IPv4SubObject.TYPE:
207 subObj = IPv4SubObject.read(cb);
208 break;
209 case IPv6SubObject.TYPE:
210 byte[] ipv6Value = new byte[IPv6SubObject.VALUE_LENGTH];
211 cb.readBytes(ipv6Value, 0, IPv6SubObject.VALUE_LENGTH);
212 subObj = new IPv6SubObject(ipv6Value);
213 break;
214 case LabelSubObject.TYPE:
215 subObj = LabelSubObject.read(cb);
216 break;
217 default:
218 throw new PcepParseException(" Unexpected sub object. Type: " + (int) yType);
219 }
220 // Check for the padding
221 int pad = hLength % 4;
222 if (0 < pad) {
223 pad = 4 - pad;
224 if (pad <= cb.readableBytes()) {
225 cb.skipBytes(pad);
226 }
227 }
228 llSubObjects.add(subObj);
229 }
230
231 return llSubObjects;
232 }
233
234 @Override
235 public int write(ChannelBuffer cb) throws PcepParseException {
236 //write Object header
237 int objStartIndex = cb.writerIndex();
238
239 int objLenIndex = rroObjHeader.write(cb);
240
241 if (objLenIndex <= 0) {
242 throw new PcepParseException(" object Length Index" + objLenIndex);
243 }
244
245 ListIterator<PcepValueType> listIterator = llSubObjects.listIterator();
246
247 while (listIterator.hasNext()) {
248 listIterator.next().write(cb);
249 }
250
251 //Update object length now
252 int length = cb.writerIndex() - objStartIndex;
253 cb.setShort(objLenIndex, (short) length);
254 //will be helpful during print().
255 rroObjHeader.setObjLen((short) length);
256
257 //As per RFC the length of object should be multiples of 4
258 int pad = length % 4;
259
260 if (0 != pad) {
261 pad = 4 - pad;
262 for (int i = 0; i < pad; i++) {
263 cb.writeByte((byte) 0);
264 }
265 length = length + pad;
266 }
267 objLenIndex = cb.writerIndex();
268 return objLenIndex;
269 }
270
271 /**
272 * Builder class for PCEP RRO object.
273 */
274 public static class Builder implements PcepRroObject.Builder {
275 private boolean bIsHeaderSet = false;
276
277 private PcepObjectHeader rroObjHeader;
Sho SHIMIZU9b8274c2015-09-04 15:54:24 -0700278 LinkedList<PcepValueType> llSubObjects = new LinkedList<>();
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -0700279
280 private boolean bIsPFlagSet = false;
281 private boolean bPFlag;
282
283 private boolean bIsIFlagSet = false;
284 private boolean bIFlag;
285
286 @Override
287 public PcepRroObject build() {
288
289 PcepObjectHeader rroObjHeader = this.bIsHeaderSet ? this.rroObjHeader : DEFAULT_RRO_OBJECT_HEADER;
290
291 if (bIsPFlagSet) {
292 rroObjHeader.setPFlag(bPFlag);
293 }
294
295 if (bIsIFlagSet) {
296 rroObjHeader.setIFlag(bIFlag);
297 }
298 return new PcepRroObjectVer1(rroObjHeader, this.llSubObjects);
299 }
300
301 @Override
302 public PcepObjectHeader getRroObjHeader() {
303 return this.rroObjHeader;
304 }
305
306 @Override
307 public Builder setRroObjHeader(PcepObjectHeader obj) {
308 this.rroObjHeader = obj;
309 this.bIsHeaderSet = true;
310 return this;
311 }
312
313 @Override
314 public LinkedList<PcepValueType> getSubObjects() {
315 return this.llSubObjects;
316 }
317
318 @Override
319 public Builder setSubObjects(LinkedList<PcepValueType> llSubObjects) {
320 this.llSubObjects = llSubObjects;
321 return this;
322 }
323
324 @Override
325 public Builder setPFlag(boolean value) {
326 this.bPFlag = value;
327 this.bIsPFlagSet = true;
328 return this;
329 }
330
331 @Override
332 public Builder setIFlag(boolean value) {
333 this.bIFlag = value;
334 this.bIsIFlagSet = true;
335 return this;
336 }
337 }
338
339 @Override
340 public String toString() {
Sho SHIMIZU7cdbcf72015-09-03 14:43:05 -0700341 return MoreObjects.toStringHelper(getClass())
342 .add("SubObjects", llSubObjects)
343 .toString();
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -0700344 }
345}