blob: ae8ec34faaef8d2f14f273ebefa5907130cd5b8c [file] [log] [blame]
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
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.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 */
Ray Milkey9c9cde42018-01-12 14:22:06 -080097 private static final Logger log = LoggerFactory.getLogger(PcepRroObjectVer1.class);
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -070098
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 }
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -0700265 }
266 objLenIndex = cb.writerIndex();
267 return objLenIndex;
268 }
269
270 /**
271 * Builder class for PCEP RRO object.
272 */
273 public static class Builder implements PcepRroObject.Builder {
274 private boolean bIsHeaderSet = false;
275
276 private PcepObjectHeader rroObjHeader;
Sho SHIMIZU9b8274c2015-09-04 15:54:24 -0700277 LinkedList<PcepValueType> llSubObjects = new LinkedList<>();
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -0700278
279 private boolean bIsPFlagSet = false;
280 private boolean bPFlag;
281
282 private boolean bIsIFlagSet = false;
283 private boolean bIFlag;
284
285 @Override
286 public PcepRroObject build() {
287
288 PcepObjectHeader rroObjHeader = this.bIsHeaderSet ? this.rroObjHeader : DEFAULT_RRO_OBJECT_HEADER;
289
290 if (bIsPFlagSet) {
291 rroObjHeader.setPFlag(bPFlag);
292 }
293
294 if (bIsIFlagSet) {
295 rroObjHeader.setIFlag(bIFlag);
296 }
297 return new PcepRroObjectVer1(rroObjHeader, this.llSubObjects);
298 }
299
300 @Override
301 public PcepObjectHeader getRroObjHeader() {
302 return this.rroObjHeader;
303 }
304
305 @Override
306 public Builder setRroObjHeader(PcepObjectHeader obj) {
307 this.rroObjHeader = obj;
308 this.bIsHeaderSet = true;
309 return this;
310 }
311
312 @Override
313 public LinkedList<PcepValueType> getSubObjects() {
314 return this.llSubObjects;
315 }
316
317 @Override
318 public Builder setSubObjects(LinkedList<PcepValueType> llSubObjects) {
319 this.llSubObjects = llSubObjects;
320 return this;
321 }
322
323 @Override
324 public Builder setPFlag(boolean value) {
325 this.bPFlag = value;
326 this.bIsPFlagSet = true;
327 return this;
328 }
329
330 @Override
331 public Builder setIFlag(boolean value) {
332 this.bIFlag = value;
333 this.bIsIFlagSet = true;
334 return this;
335 }
336 }
337
338 @Override
339 public String toString() {
Sho SHIMIZU7cdbcf72015-09-03 14:43:05 -0700340 return MoreObjects.toStringHelper(getClass())
341 .add("SubObjects", llSubObjects)
342 .toString();
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -0700343 }
344}