blob: 4b97d05171a623d9eba95946d80644cbf72fddf5 [file] [log] [blame]
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -07003 *
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;
Mahesh Poojary Sf1bbd362016-02-25 18:19:59 +053025import org.onosproject.pcepio.types.AutonomousSystemNumberSubObject;
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -070026import 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 * Provides PCEP Ero Object.
40 */
41public class PcepEroObjectVer1 implements PcepEroObject {
42 /*
43 * rfc3209
44 0 1 2 3
45 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
46 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
47 | Object-Class | OT |Res|P|I| Object Length (bytes) |
48 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
49 | |
50 // (Subobjects) //
51 | |
52 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
53
54 If a Path message contains multiple EXPLICIT_ROUTE objects, only the
55 first object is meaningful. Subsequent EXPLICIT_ROUTE objects MAY be
56 ignored and SHOULD NOT be propagated.
57
58 In current implementation, only strict hops are supported. So,
59 empty ERO with no sub-objects is considered illegal.
60
61 Subobjects:
62 0 1
63 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
64 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-------------//----------------+
65 |L| Type | Length | (Subobject contents) |
66 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-------------//----------------+
67
68 L
69
70 The L bit is an attribute of the subobject. The L bit is set
71 if the subobject represents a loose hop in the explicit route.
72 If the bit is not set, the subobject represents a strict hop in
73 the explicit route.
74
75 Type
76
77 The Type indicates the type of contents of the subobject.
78
79
80 Subobject 1: IPv4 address
81
82 0 1 2 3
83 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
84 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
85 |L| Type | Length | IPv4 address (4 bytes) |
86 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
87 | IPv4 address (continued) | Prefix Length | Resvd |
88 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
89
90 Subobject 2: IPv6 Prefix
91
92 0 1 2 3
93 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
94 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
95 |L| Type | Length | IPv6 address (16 bytes) |
96 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
97 | IPv6 address (continued) |
98 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
99 | IPv6 address (continued) |
100 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
101 | IPv6 address (continued) |
102 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
103 | IPv6 address (continued) | Prefix Length | Resvd |
104 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
105
106 Subobject 3: Autonomous System Number
107
108 The contents of an Autonomous System (AS) number subobject are a 2-
109 octet AS number. The abstract node represented by this subobject is
110 the set of nodes belonging to the autonomous system.
111
112 The length of the AS number subobject is 4 octets.
113
114 Subobject 4: PATH_KEY_32_BIT_SUB_OBJ_TYPE:
115
116 Pathkey subobject(RFC 5520):
117 0 1 2 3
118 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
119 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
120 |L| Type | Length | Path-Key |
121 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
122 | PCE ID (4 bytes) |
123 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
124
125 Subobject 5: SR_ERO_SUB_OBJ_TYPE:
126
127 SR-ERO subobject: (draft-ietf-pce-segment-routing-00)
128 0 1 2 3
129 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
130 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
131 |L| Type | Length | ST | Flags |F|S|C|M|
132 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
133 | SID |
134 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
135 // NAI (variable) //
136 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
137 */
138
139 protected static final Logger log = LoggerFactory.getLogger(PcepEroObjectVer1.class);
140
141 public static final byte ERO_OBJ_TYPE = 1;
142 public static final byte ERO_OBJ_CLASS = 7;
143 public static final byte ERO_OBJECT_VERSION = 1;
144 public static final short ERO_OBJ_MINIMUM_LENGTH = 12;
145 public static final byte IPV4_TYPE = 1;
146 public static final byte PATH_KEY_32_BIT_SUB_OBJ_TYPE = 64;
147 public static final int LABEL_SUB_OBJ_TYPE = 3;
148 public static final int SR_ERO_SUB_OBJ_TYPE = 96;
149 public static final int OBJECT_HEADER_LENGTH = 4;
Mahesh Poojary Sf1bbd362016-02-25 18:19:59 +0530150 public static final int TYPE_SHIFT_VALUE = 0x7F;
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -0700151
Mahesh Poojary Sf1bbd362016-02-25 18:19:59 +0530152 public static final PcepObjectHeader DEFAULT_ERO_OBJECT_HEADER = new PcepObjectHeader(ERO_OBJ_CLASS, ERO_OBJ_TYPE,
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -0700153 PcepObjectHeader.REQ_OBJ_OPTIONAL_PROCESS, PcepObjectHeader.RSP_OBJ_PROCESSED, ERO_OBJ_MINIMUM_LENGTH);
154
155 private PcepObjectHeader eroObjHeader;
Mahesh Poojary Sf1bbd362016-02-25 18:19:59 +0530156 private LinkedList<PcepValueType> subObjectList = new LinkedList<>();
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -0700157
158 /**
159 * reset variables.
160 */
161 public PcepEroObjectVer1() {
162 this.eroObjHeader = null;
Mahesh Poojary Sf1bbd362016-02-25 18:19:59 +0530163 this.subObjectList = null;
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -0700164 }
165
166 /**
167 * Constructor to initialize parameters of ERO object.
168 *
169 * @param eroObjHeader ERO object header
Mahesh Poojary Sf1bbd362016-02-25 18:19:59 +0530170 * @param subObjectList list of sub objects.
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -0700171 */
Mahesh Poojary Sf1bbd362016-02-25 18:19:59 +0530172 public PcepEroObjectVer1(PcepObjectHeader eroObjHeader, LinkedList<PcepValueType> subObjectList) {
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -0700173
174 this.eroObjHeader = eroObjHeader;
Mahesh Poojary Sf1bbd362016-02-25 18:19:59 +0530175 this.subObjectList = subObjectList;
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -0700176 }
177
178 /**
179 * Returns ERO object header.
180 *
181 * @return eroObjHeader ERO object header
182 */
183 public PcepObjectHeader getEroObjHeader() {
184 return this.eroObjHeader;
185 }
186
187 /**
188 * Sets Object Header.
189 *
190 * @param obj ERO object header
191 */
192 public void setEroObjHeader(PcepObjectHeader obj) {
193 this.eroObjHeader = obj;
194 }
195
196 @Override
197 public LinkedList<PcepValueType> getSubObjects() {
Mahesh Poojary Sf1bbd362016-02-25 18:19:59 +0530198 return this.subObjectList;
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -0700199 }
200
201 @Override
Mahesh Poojary Sf1bbd362016-02-25 18:19:59 +0530202 public void setSubObjects(LinkedList<PcepValueType> subObjectList) {
203 this.subObjectList = subObjectList;
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -0700204 }
205
206 /**
207 * Reads from channel buffer and returns object of PcepEroObject.
208 *
209 * @param cb channel buffer.
210 * @return object of PcepEroObject
211 * @throws PcepParseException when ERO object is not present in channel buffer
212 */
213 public static PcepEroObject read(ChannelBuffer cb) throws PcepParseException {
214
215 PcepObjectHeader eroObjHeader;
Mahesh Poojary Sf1bbd362016-02-25 18:19:59 +0530216 LinkedList<PcepValueType> subObjectList = new LinkedList<>();
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -0700217
218 eroObjHeader = PcepObjectHeader.read(cb);
219
220 if (eroObjHeader.getObjClass() != PcepEroObjectVer1.ERO_OBJ_CLASS) {
221 log.debug("ErrorType:" + PcepErrorDetailInfo.ERROR_TYPE_6 + " ErrorValue:"
222 + PcepErrorDetailInfo.ERROR_VALUE_9);
223 throw new PcepParseException(PcepErrorDetailInfo.ERROR_TYPE_6, PcepErrorDetailInfo.ERROR_VALUE_9);
224 }
225
226 if (eroObjHeader.getObjLen() > OBJECT_HEADER_LENGTH) {
227 ChannelBuffer tempCb = cb.readBytes(eroObjHeader.getObjLen() - OBJECT_HEADER_LENGTH);
Mahesh Poojary Sf1bbd362016-02-25 18:19:59 +0530228 subObjectList = parseSubObjects(tempCb);
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -0700229 }
Mahesh Poojary Sf1bbd362016-02-25 18:19:59 +0530230 return new PcepEroObjectVer1(eroObjHeader, subObjectList);
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -0700231 }
232
233 /**
234 * Parse list of Sub Objects.
235 *
236 * @param cb channel buffer
237 * @return list of Sub Objects
238 * @throws PcepParseException when fails to parse sub object list
239 */
240 protected static LinkedList<PcepValueType> parseSubObjects(ChannelBuffer cb) throws PcepParseException {
241
Mahesh Poojary Sf1bbd362016-02-25 18:19:59 +0530242 LinkedList<PcepValueType> subObjectList = new LinkedList<>();
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -0700243
244 while (0 < cb.readableBytes()) {
245
246 //check the Type of the TLV
Mahesh Poojary Sf1bbd362016-02-25 18:19:59 +0530247 short type = cb.readByte();
248 type = (short) (type & (TYPE_SHIFT_VALUE));
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -0700249 byte hLength = cb.readByte();
250
251 PcepValueType subObj;
252
Mahesh Poojary Sf1bbd362016-02-25 18:19:59 +0530253 switch (type) {
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -0700254
255 case IPv4SubObject.TYPE:
256 subObj = IPv4SubObject.read(cb);
257 break;
258 case IPv6SubObject.TYPE:
259 byte[] ipv6Value = new byte[IPv6SubObject.VALUE_LENGTH];
260 cb.readBytes(ipv6Value, 0, IPv6SubObject.VALUE_LENGTH);
261 subObj = new IPv6SubObject(ipv6Value);
262 break;
Mahesh Poojary Sf1bbd362016-02-25 18:19:59 +0530263 case AutonomousSystemNumberSubObject.TYPE:
264 subObj = AutonomousSystemNumberSubObject.read(cb);
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -0700265 break;
266 case PathKeySubObject.TYPE:
267 subObj = PathKeySubObject.read(cb);
268 break;
269 case SrEroSubObject.TYPE:
270 subObj = SrEroSubObject.read(cb);
271 break;
272 default:
Mahesh Poojary Sf1bbd362016-02-25 18:19:59 +0530273 throw new PcepParseException("Unexpected sub object. Type: " + (int) type);
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -0700274 }
275 // Check for the padding
276 int pad = hLength % 4;
277 if (0 < pad) {
278 pad = 4 - pad;
279 if (pad <= cb.readableBytes()) {
280 cb.skipBytes(pad);
281 }
282 }
283
Mahesh Poojary Sf1bbd362016-02-25 18:19:59 +0530284 subObjectList.add(subObj);
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -0700285 }
286 if (0 < cb.readableBytes()) {
287 throw new PcepParseException("Subobject parsing error. Extra bytes received.");
288 }
Mahesh Poojary Sf1bbd362016-02-25 18:19:59 +0530289 return subObjectList;
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -0700290 }
291
292 @Override
293 public int write(ChannelBuffer cb) throws PcepParseException {
294
295 //write Object header
296 int objStartIndex = cb.writerIndex();
297
298 int objLenIndex = eroObjHeader.write(cb);
299
300 if (objLenIndex <= 0) {
301 throw new PcepParseException("Failed to write ERO object header. Index " + objLenIndex);
302 }
303
Mahesh Poojary Sf1bbd362016-02-25 18:19:59 +0530304 ListIterator<PcepValueType> listIterator = subObjectList.listIterator();
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -0700305
306 while (listIterator.hasNext()) {
307 listIterator.next().write(cb);
308 }
309
310 //Update object length now
311 int length = cb.writerIndex() - objStartIndex;
312 cb.setShort(objLenIndex, (short) length);
313 //will be helpful during print().
314 eroObjHeader.setObjLen((short) length);
315
316 //As per RFC the length of object should be multiples of 4
317 int pad = length % 4;
318
319 if (pad != 0) {
320 pad = 4 - pad;
321 for (int i = 0; i < pad; i++) {
322 cb.writeByte((byte) 0);
323 }
324 length = length + pad;
325 }
326
327 objLenIndex = cb.writerIndex();
328 return objLenIndex;
329 }
330
331 /**
332 * Builder class for PCEP ERO object.
333 */
334 public static class Builder implements PcepEroObject.Builder {
335
336 private boolean bIsHeaderSet = false;
337
338 private boolean bIsPFlagSet = false;
339 private boolean bPFlag;
340
341 private boolean bIsIFlagSet = false;
342 private boolean bIFlag;
343
344 private PcepObjectHeader eroObjHeader;
Mahesh Poojary Sf1bbd362016-02-25 18:19:59 +0530345 LinkedList<PcepValueType> subObjectList = new LinkedList<>();
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -0700346
347 @Override
348 public PcepEroObject build() {
349
350 PcepObjectHeader eroObjHeader = this.bIsHeaderSet ? this.eroObjHeader : DEFAULT_ERO_OBJECT_HEADER;
351
352 if (bIsPFlagSet) {
353 eroObjHeader.setPFlag(bPFlag);
354 }
355
356 if (bIsIFlagSet) {
357 eroObjHeader.setIFlag(bIFlag);
358 }
359
Mahesh Poojary Sf1bbd362016-02-25 18:19:59 +0530360 return new PcepEroObjectVer1(eroObjHeader, this.subObjectList);
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -0700361 }
362
363 @Override
364 public PcepObjectHeader getEroObjHeader() {
365 return this.eroObjHeader;
366 }
367
368 @Override
369 public Builder setEroObjHeader(PcepObjectHeader obj) {
370 this.eroObjHeader = obj;
371 this.bIsHeaderSet = true;
372 return this;
373 }
374
375 @Override
376 public LinkedList<PcepValueType> getSubObjects() {
Mahesh Poojary Sf1bbd362016-02-25 18:19:59 +0530377 return this.subObjectList;
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -0700378 }
379
380 @Override
Mahesh Poojary Sf1bbd362016-02-25 18:19:59 +0530381 public Builder setSubObjects(LinkedList<PcepValueType> subObjectList) {
382 this.subObjectList = subObjectList;
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -0700383 return this;
384 }
385
386 @Override
387 public Builder setPFlag(boolean value) {
388 this.bPFlag = value;
389 this.bIsPFlagSet = true;
390 return this;
391 }
392
393 @Override
394 public Builder setIFlag(boolean value) {
395 this.bIFlag = value;
396 this.bIsIFlagSet = true;
397 return this;
398 }
399 }
400
401 @Override
402 public String toString() {
Mahesh Poojary Sf1bbd362016-02-25 18:19:59 +0530403 return MoreObjects.toStringHelper(getClass()).omitNullValues()
404 .add("EroObjHeader", eroObjHeader)
405 .add("SubObjects", subObjectList)
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -0700406 .toString();
407 }
408}