blob: b45a0c2a21906868152b12163366202c666fd1a9 [file] [log] [blame]
bharat saraswalf7364db2015-08-11 13:39:31 +05301/*
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.PcepEroObject;
25import org.onosproject.pcepio.types.AutonomousSystemTlv;
26import org.onosproject.pcepio.types.IPv4SubObject;
27import org.onosproject.pcepio.types.IPv6SubObject;
28import org.onosproject.pcepio.types.PathKeySubObject;
29import org.onosproject.pcepio.types.PcepErrorDetailInfo;
30import org.onosproject.pcepio.types.PcepObjectHeader;
31import org.onosproject.pcepio.types.PcepValueType;
32import org.onosproject.pcepio.types.SrEroSubObject;
33import org.slf4j.Logger;
34import org.slf4j.LoggerFactory;
35
36import com.google.common.base.MoreObjects;
37
38/*
39 * rfc3209
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 | |
46 // (Subobjects) //
47 | |
48 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
49
50 If a Path message contains multiple EXPLICIT_ROUTE objects, only the
51 first object is meaningful. Subsequent EXPLICIT_ROUTE objects MAY be
52 ignored and SHOULD NOT be propagated.
53
54 In current implementation, only strict hops are supported. So,
55 empty ERO with no sub-objects is considered illegal.
56
57 Subobjects:
58 0 1
59 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
60 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-------------//----------------+
61 |L| Type | Length | (Subobject contents) |
62 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-------------//----------------+
63
64 L
65
66 The L bit is an attribute of the subobject. The L bit is set
67 if the subobject represents a loose hop in the explicit route.
68 If the bit is not set, the subobject represents a strict hop in
69 the explicit route.
70
71 Type
72
73 The Type indicates the type of contents of the subobject.
74
75
76 Subobject 1: IPv4 address
77
78 0 1 2 3
79 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
80 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
81 |L| Type | Length | IPv4 address (4 bytes) |
82 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
83 | IPv4 address (continued) | Prefix Length | Resvd |
84 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
85
86 Subobject 2: IPv6 Prefix
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 |L| Type | Length | IPv6 address (16 bytes) |
92 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
93 | IPv6 address (continued) |
94 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
95 | IPv6 address (continued) |
96 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
97 | IPv6 address (continued) |
98 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
99 | IPv6 address (continued) | Prefix Length | Resvd |
100 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
101
102 Subobject 3: Autonomous System Number
103
104 The contents of an Autonomous System (AS) number subobject are a 2-
105 octet AS number. The abstract node represented by this subobject is
106 the set of nodes belonging to the autonomous system.
107
108 The length of the AS number subobject is 4 octets.
109
110 Subobject 4: PATH_KEY_32_BIT_SUB_OBJ_TYPE:
111
112 Pathkey subobject(RFC 5520):
113 0 1 2 3
114 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
115 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
116 |L| Type | Length | Path-Key |
117 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
118 | PCE ID (4 bytes) |
119 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
120
121 Subobject 5: SR_ERO_SUB_OBJ_TYPE:
122
123 SR-ERO subobject: (draft-ietf-pce-segment-routing-00)
124 0 1 2 3
125 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
126 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
127 |L| Type | Length | ST | Flags |F|S|C|M|
128 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
129 | SID |
130 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
131 // NAI (variable) //
132 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
133 */
134public class PcepEroObjectVer1 implements PcepEroObject {
135
136 protected static final Logger log = LoggerFactory.getLogger(PcepEroObjectVer1.class);
137
138 public static final byte ERO_OBJ_TYPE = 1;
139 public static final byte ERO_OBJ_CLASS = 7;
140 public static final byte ERO_OBJECT_VERSION = 1;
141 public static final short ERO_OBJ_MINIMUM_LENGTH = 12;
142 public static final byte IPV4_TYPE = 1;
143 public static final byte PATH_KEY_32_BIT_SUB_OBJ_TYPE = 64;
144 public static final int LABEL_SUB_OBJ_TYPE = 3;
145 public static final int SR_ERO_SUB_OBJ_TYPE = 96;
146 public static final int OBJECT_HEADER_LENGTH = 4;
147 public static final int YTYPE_SHIFT_VALUE = 0x7F;
148
149 static final PcepObjectHeader DEFAULT_ERO_OBJECT_HEADER = new PcepObjectHeader(ERO_OBJ_CLASS, ERO_OBJ_TYPE,
150 PcepObjectHeader.REQ_OBJ_OPTIONAL_PROCESS, PcepObjectHeader.RSP_OBJ_PROCESSED, ERO_OBJ_MINIMUM_LENGTH);
151
152 private PcepObjectHeader eroObjHeader;
153 private LinkedList<PcepValueType> llSubObjects = new LinkedList<PcepValueType>();
154
155 /**
156 * reset variables.
157 */
158 public PcepEroObjectVer1() {
159 this.eroObjHeader = null;
160 this.llSubObjects = null;
161 }
162
163 /**
164 * Constructor to initialize parameters of ERO object.
165 *
166 * @param eroObjHeader ERO object header
167 * @param llSubObjects list of sub objects.
168 */
169 public PcepEroObjectVer1(PcepObjectHeader eroObjHeader, LinkedList<PcepValueType> llSubObjects) {
170
171 this.eroObjHeader = eroObjHeader;
172 this.llSubObjects = llSubObjects;
173 }
174
175 /**
176 * Returns ERO object header.
177 *
178 * @return eroObjHeader ERO object header
179 */
180 public PcepObjectHeader getEroObjHeader() {
181 return this.eroObjHeader;
182 }
183
184 /**
185 * Sets Object Header.
186 *
187 * @param obj ERO object header
188 */
189 public void setEroObjHeader(PcepObjectHeader obj) {
190 this.eroObjHeader = obj;
191 }
192
193 @Override
194 public LinkedList<PcepValueType> getSubObjects() {
195 return this.llSubObjects;
196 }
197
198 @Override
199 public void setSubObjects(LinkedList<PcepValueType> llSubObjects) {
200 this.llSubObjects = llSubObjects;
201 }
202
203 /**
204 * Reads from channel buffer and returns object of PcepEroObject.
205 *
206 * @param cb channel buffer.
207 * @return object of PcepEroObject
208 * @throws PcepParseException when ERO object is not present in channel buffer
209 */
210 public static PcepEroObject read(ChannelBuffer cb) throws PcepParseException {
211
212 PcepObjectHeader eroObjHeader;
213 LinkedList<PcepValueType> llSubObjects = new LinkedList<PcepValueType>();
214
215 eroObjHeader = PcepObjectHeader.read(cb);
216
217 if (eroObjHeader.getObjClass() != PcepEroObjectVer1.ERO_OBJ_CLASS) {
218 log.debug("ErrorType:" + PcepErrorDetailInfo.ERROR_TYPE_6 + " ErrorValue:"
219 + PcepErrorDetailInfo.ERROR_VALUE_9);
220 throw new PcepParseException(PcepErrorDetailInfo.ERROR_TYPE_6, PcepErrorDetailInfo.ERROR_VALUE_9);
221 }
222
223 if (eroObjHeader.getObjLen() > OBJECT_HEADER_LENGTH) {
224 ChannelBuffer tempCb = cb.readBytes(eroObjHeader.getObjLen() - OBJECT_HEADER_LENGTH);
225 llSubObjects = parseSubObjects(tempCb);
226 }
227 return new PcepEroObjectVer1(eroObjHeader, llSubObjects);
228 }
229
230 /**
231 * Parse list of Sub Objects.
232 *
233 * @param cb channel buffer
234 * @return list of Sub Objects
235 * @throws PcepParseException when fails to parse sub object list
236 */
237 protected static LinkedList<PcepValueType> parseSubObjects(ChannelBuffer cb) throws PcepParseException {
238
239 LinkedList<PcepValueType> llSubObjects = new LinkedList<PcepValueType>();
240
241 while (0 < cb.readableBytes()) {
242
243 //check the Type of the TLV
244 byte yType = cb.readByte();
245 yType = (byte) (yType & (YTYPE_SHIFT_VALUE));
246 byte hLength = cb.readByte();
247
248 PcepValueType subObj;
249
250 switch (yType) {
251
252 case IPv4SubObject.TYPE:
253 subObj = IPv4SubObject.read(cb);
254 break;
255 case IPv6SubObject.TYPE:
256 byte[] ipv6Value = new byte[IPv6SubObject.VALUE_LENGTH];
257 cb.readBytes(ipv6Value, 0, IPv6SubObject.VALUE_LENGTH);
258 subObj = new IPv6SubObject(ipv6Value);
259 break;
260 case AutonomousSystemTlv.TYPE:
261 subObj = AutonomousSystemTlv.read(cb);
262 break;
263 case PathKeySubObject.TYPE:
264 subObj = PathKeySubObject.read(cb);
265 break;
266 case SrEroSubObject.TYPE:
267 subObj = SrEroSubObject.read(cb);
268 break;
269 default:
270 throw new PcepParseException("Unexpected sub object. Type: " + (int) yType);
271 }
272 // Check for the padding
273 int pad = hLength % 4;
274 if (0 < pad) {
275 pad = 4 - pad;
276 if (pad <= cb.readableBytes()) {
277 cb.skipBytes(pad);
278 }
279 }
280
281 llSubObjects.add(subObj);
282 }
283 if (0 < cb.readableBytes()) {
284 throw new PcepParseException("Subobject parsing error. Extra bytes received.");
285 }
286 return llSubObjects;
287 }
288
289 @Override
290 public int write(ChannelBuffer cb) throws PcepParseException {
291
292 //write Object header
293 int objStartIndex = cb.writerIndex();
294
295 int objLenIndex = eroObjHeader.write(cb);
296
297 if (objLenIndex <= 0) {
298 throw new PcepParseException("Failed to write ERO object header. Index " + objLenIndex);
299 }
300
301 ListIterator<PcepValueType> listIterator = llSubObjects.listIterator();
302
303 while (listIterator.hasNext()) {
304 listIterator.next().write(cb);
305 }
306
307 //Update object length now
308 int length = cb.writerIndex() - objStartIndex;
309 cb.setShort(objLenIndex, (short) length);
310 //will be helpful during print().
311 eroObjHeader.setObjLen((short) length);
312
313 //As per RFC the length of object should be multiples of 4
314 int pad = length % 4;
315
316 if (pad != 0) {
317 pad = 4 - pad;
318 for (int i = 0; i < pad; i++) {
319 cb.writeByte((byte) 0);
320 }
321 length = length + pad;
322 }
323
324 objLenIndex = cb.writerIndex();
325 return objLenIndex;
326 }
327
328 /**
329 * Builder class for PCEP ERO object.
330 */
331 public static class Builder implements PcepEroObject.Builder {
332
333 private boolean bIsHeaderSet = false;
334
335 private boolean bIsPFlagSet = false;
336 private boolean bPFlag;
337
338 private boolean bIsIFlagSet = false;
339 private boolean bIFlag;
340
341 private PcepObjectHeader eroObjHeader;
342 LinkedList<PcepValueType> llSubObjects = new LinkedList<PcepValueType>();
343
344 @Override
345 public PcepEroObject build() {
346
347 PcepObjectHeader eroObjHeader = this.bIsHeaderSet ? this.eroObjHeader : DEFAULT_ERO_OBJECT_HEADER;
348
349 if (bIsPFlagSet) {
350 eroObjHeader.setPFlag(bPFlag);
351 }
352
353 if (bIsIFlagSet) {
354 eroObjHeader.setIFlag(bIFlag);
355 }
356
357 return new PcepEroObjectVer1(eroObjHeader, this.llSubObjects);
358 }
359
360 @Override
361 public PcepObjectHeader getEroObjHeader() {
362 return this.eroObjHeader;
363 }
364
365 @Override
366 public Builder setEroObjHeader(PcepObjectHeader obj) {
367 this.eroObjHeader = obj;
368 this.bIsHeaderSet = true;
369 return this;
370 }
371
372 @Override
373 public LinkedList<PcepValueType> getSubObjects() {
374 return this.llSubObjects;
375 }
376
377 @Override
378 public Builder setSubObjects(LinkedList<PcepValueType> llSubObjects) {
379 this.llSubObjects = llSubObjects;
380 return this;
381 }
382
383 @Override
384 public Builder setPFlag(boolean value) {
385 this.bPFlag = value;
386 this.bIsPFlagSet = true;
387 return this;
388 }
389
390 @Override
391 public Builder setIFlag(boolean value) {
392 this.bIFlag = value;
393 this.bIsIFlagSet = true;
394 return this;
395 }
bharat saraswalf7364db2015-08-11 13:39:31 +0530396 }
397
398 @Override
399 public String toString() {
bharat saraswale1806302015-08-21 12:16:46 +0530400 return MoreObjects.toStringHelper(getClass()).add("EroObjHeader", eroObjHeader).add("SubObjects", llSubObjects)
bharat saraswalf7364db2015-08-11 13:39:31 +0530401 .toString();
402 }
403}