2 * Copyright 2015 Open Networking Laboratory
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package org.onosproject.pcepio.protocol.ver1;
19 import java.util.LinkedList;
20 import java.util.ListIterator;
22 import org.jboss.netty.buffer.ChannelBuffer;
23 import org.onosproject.pcepio.exceptions.PcepParseException;
24 import org.onosproject.pcepio.protocol.PcepRroObject;
25 import org.onosproject.pcepio.types.IPv4SubObject;
26 import org.onosproject.pcepio.types.IPv6SubObject;
27 import org.onosproject.pcepio.types.LabelSubObject;
28 import org.onosproject.pcepio.types.PcepObjectHeader;
29 import org.onosproject.pcepio.types.PcepValueType;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
33 import com.google.common.base.MoreObjects;
36 * Provides PCEP RRO object.
38 public class PcepRroObjectVer1 implements PcepRroObject {
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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
50 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
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.
57 An empty RRO with no subobjects is considered illegal.
58 Three kinds of subobjects are currently defined.
60 Subobject 1: IPv4 address
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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
70 Subobject 2: IPv6 address
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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
97 protected static final Logger log = LoggerFactory.getLogger(PcepRroObjectVer1.class);
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;
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);
109 private short rroObjType = 0;
111 private byte prefixLength;
113 PcepObjectHeader rroObjHeader;
114 private LinkedList<PcepValueType> llSubObjects = new LinkedList<>();
119 public PcepRroObjectVer1() {
120 this.rroObjHeader = null;
126 * constructor to initialize parameters for RRO object.
128 * @param rroObjHeader RRO object header
129 * @param llSubObjects list of sub objects
131 public PcepRroObjectVer1(PcepObjectHeader rroObjHeader, LinkedList<PcepValueType> llSubObjects) {
132 this.rroObjHeader = rroObjHeader;
133 this.llSubObjects = llSubObjects;
137 * Returns PCEP RRO Object Header.
139 * @return rroObjHeader RRO Object header
141 public PcepObjectHeader getRroObjHeader() {
142 return this.rroObjHeader;
146 * Sets PCEP RRO Object Header.
148 * @param obj Object header
150 public void setRroObjHeader(PcepObjectHeader obj) {
151 this.rroObjHeader = obj;
155 public LinkedList<PcepValueType> getSubObjects() {
156 return this.llSubObjects;
160 public void setSubObjects(LinkedList<PcepValueType> llSubObjects) {
161 this.llSubObjects = llSubObjects;
165 * Reads the channel buffer and returns object of PcepRroObject.
167 * @param cb of type channel buffer
168 * @return object of PcepRroObject
169 * @throws PcepParseException when fails to read from channel buffer
171 public static PcepRroObject read(ChannelBuffer cb) throws PcepParseException {
173 PcepObjectHeader rroObjHeader;
174 LinkedList<PcepValueType> llSubObjects;
175 rroObjHeader = PcepObjectHeader.read(cb);
177 //take only RroObject buffer.
178 ChannelBuffer tempCb = cb.readBytes(rroObjHeader.getObjLen() - OBJECT_HEADER_LENGTH);
179 llSubObjects = parseSubObjects(tempCb);
181 return new PcepRroObjectVer1(rroObjHeader, llSubObjects);
185 * Returns list of sub objects.
187 * @param cb of type channel buffer
188 * @return list of sub objects
189 * @throws PcepParseException when fails to parse list of sub objects
191 protected static LinkedList<PcepValueType> parseSubObjects(ChannelBuffer cb) throws PcepParseException {
193 LinkedList<PcepValueType> llSubObjects = new LinkedList<>();
195 while (0 < cb.readableBytes()) {
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();
202 PcepValueType subObj;
206 case IPv4SubObject.TYPE:
207 subObj = IPv4SubObject.read(cb);
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);
214 case LabelSubObject.TYPE:
215 subObj = LabelSubObject.read(cb);
218 throw new PcepParseException(" Unexpected sub object. Type: " + (int) yType);
220 // Check for the padding
221 int pad = hLength % 4;
224 if (pad <= cb.readableBytes()) {
228 llSubObjects.add(subObj);
235 public int write(ChannelBuffer cb) throws PcepParseException {
236 //write Object header
237 int objStartIndex = cb.writerIndex();
239 int objLenIndex = rroObjHeader.write(cb);
241 if (objLenIndex <= 0) {
242 throw new PcepParseException(" object Length Index" + objLenIndex);
245 ListIterator<PcepValueType> listIterator = llSubObjects.listIterator();
247 while (listIterator.hasNext()) {
248 listIterator.next().write(cb);
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);
257 //As per RFC the length of object should be multiples of 4
258 int pad = length % 4;
262 for (int i = 0; i < pad; i++) {
263 cb.writeByte((byte) 0);
265 length = length + pad;
267 objLenIndex = cb.writerIndex();
272 * Builder class for PCEP RRO object.
274 public static class Builder implements PcepRroObject.Builder {
275 private boolean bIsHeaderSet = false;
277 private PcepObjectHeader rroObjHeader;
278 LinkedList<PcepValueType> llSubObjects = new LinkedList<>();
280 private boolean bIsPFlagSet = false;
281 private boolean bPFlag;
283 private boolean bIsIFlagSet = false;
284 private boolean bIFlag;
287 public PcepRroObject build() {
289 PcepObjectHeader rroObjHeader = this.bIsHeaderSet ? this.rroObjHeader : DEFAULT_RRO_OBJECT_HEADER;
292 rroObjHeader.setPFlag(bPFlag);
296 rroObjHeader.setIFlag(bIFlag);
298 return new PcepRroObjectVer1(rroObjHeader, this.llSubObjects);
302 public PcepObjectHeader getRroObjHeader() {
303 return this.rroObjHeader;
307 public Builder setRroObjHeader(PcepObjectHeader obj) {
308 this.rroObjHeader = obj;
309 this.bIsHeaderSet = true;
314 public LinkedList<PcepValueType> getSubObjects() {
315 return this.llSubObjects;
319 public Builder setSubObjects(LinkedList<PcepValueType> llSubObjects) {
320 this.llSubObjects = llSubObjects;
325 public Builder setPFlag(boolean value) {
327 this.bIsPFlagSet = true;
332 public Builder setIFlag(boolean value) {
334 this.bIsIFlagSet = true;
340 public String toString() {
341 return MoreObjects.toStringHelper(getClass())
342 .add("SubObjects", llSubObjects)