bharat saraswal | f7364db | 2015-08-11 13:39:31 +0530 | [diff] [blame] | 1 | /* |
| 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 | |
| 17 | package org.onosproject.pcepio.protocol.ver1; |
| 18 | |
| 19 | import java.util.LinkedList; |
| 20 | import java.util.ListIterator; |
| 21 | |
| 22 | import org.jboss.netty.buffer.ChannelBuffer; |
| 23 | import org.onosproject.pcepio.exceptions.PcepParseException; |
| 24 | import org.onosproject.pcepio.protocol.PcepIroObject; |
| 25 | import org.onosproject.pcepio.types.IPv4SubObject; |
| 26 | import org.onosproject.pcepio.types.PcepObjectHeader; |
| 27 | import org.onosproject.pcepio.types.PcepValueType; |
| 28 | import org.slf4j.Logger; |
| 29 | import org.slf4j.LoggerFactory; |
| 30 | |
| 31 | import com.google.common.base.MoreObjects; |
| 32 | |
Phanendra Manda | 51fb9c2 | 2015-09-01 16:17:41 +0530 | [diff] [blame] | 33 | /** |
| 34 | * Provides PCEP iro object. |
| 35 | */ |
| 36 | public class PcepIroObjectVer1 implements PcepIroObject { |
| 37 | |
| 38 | /* |
bharat saraswal | f7364db | 2015-08-11 13:39:31 +0530 | [diff] [blame] | 39 | 0 1 2 3 |
| 40 | 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 |
| 41 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 42 | | | |
| 43 | // (Sub-objects) // |
| 44 | | | |
| 45 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 46 | |
| 47 | The IRO Object format |
| 48 | |
| 49 | Each IPV4 suboject |
| 50 | |
| 51 | 0 1 2 3 |
| 52 | 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 |
| 53 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 54 | |L| Type | Length | IPv4 address (4 bytes) | |
| 55 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 56 | | IPv4 address (continued) | Prefix Length | Resvd | |
| 57 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
Phanendra Manda | 51fb9c2 | 2015-09-01 16:17:41 +0530 | [diff] [blame] | 58 | */ |
bharat saraswal | f7364db | 2015-08-11 13:39:31 +0530 | [diff] [blame] | 59 | protected static final Logger log = LoggerFactory.getLogger(PcepIroObjectVer1.class); |
| 60 | |
| 61 | public static final byte IRO_OBJ_TYPE = 1; |
| 62 | public static final byte IRO_OBJ_CLASS = 10; |
| 63 | public static final byte IRO_OBJECT_VERSION = 1; |
| 64 | public static final short IRO_OBJ_MINIMUM_LENGTH = 12; |
| 65 | public static final int OBJECT_HEADER_LENGTH = 4; |
| 66 | public static final int YTYPE_SHIFT_VALUE = 0x7F; |
| 67 | |
| 68 | public static final PcepObjectHeader DEFAULT_IRO_OBJECT_HEADER = new PcepObjectHeader(IRO_OBJ_CLASS, IRO_OBJ_TYPE, |
| 69 | PcepObjectHeader.REQ_OBJ_OPTIONAL_PROCESS, PcepObjectHeader.RSP_OBJ_PROCESSED, IRO_OBJ_MINIMUM_LENGTH); |
| 70 | |
| 71 | private short iroObjType = 0; |
| 72 | private byte yLength; |
| 73 | private byte yPrefixLength; |
| 74 | private byte yResvd; |
| 75 | private PcepObjectHeader iroObjHeader; |
Sho SHIMIZU | 9b8274c | 2015-09-04 15:54:24 -0700 | [diff] [blame] | 76 | private LinkedList<PcepValueType> llSubObjects = new LinkedList<>(); |
bharat saraswal | f7364db | 2015-08-11 13:39:31 +0530 | [diff] [blame] | 77 | |
| 78 | /** |
| 79 | * Default constructor. |
| 80 | */ |
| 81 | public PcepIroObjectVer1() { |
| 82 | this.iroObjHeader = null; |
| 83 | this.iroObjType = 0; |
| 84 | this.yLength = 0; |
| 85 | } |
| 86 | |
| 87 | /** |
| 88 | * Constructor to initialize member variables. |
| 89 | * |
| 90 | * @param iroObjHeader IRO object header |
| 91 | * @param llSubObjects list of sub-objects |
| 92 | */ |
| 93 | public PcepIroObjectVer1(PcepObjectHeader iroObjHeader, LinkedList<PcepValueType> llSubObjects) { |
| 94 | this.iroObjHeader = iroObjHeader; |
| 95 | this.llSubObjects = llSubObjects; |
| 96 | } |
| 97 | |
| 98 | /** |
| 99 | * Returns object header. |
| 100 | * |
| 101 | * @return iroObjHeader IRO object header |
| 102 | */ |
| 103 | public PcepObjectHeader getIroObjHeader() { |
| 104 | return this.iroObjHeader; |
| 105 | } |
| 106 | |
| 107 | /** |
| 108 | * Sets IRO Object Header. |
| 109 | * |
| 110 | * @param obj IRO object header |
| 111 | */ |
| 112 | public void setIroObjHeader(PcepObjectHeader obj) { |
| 113 | this.iroObjHeader = obj; |
| 114 | } |
| 115 | |
| 116 | @Override |
| 117 | public LinkedList<PcepValueType> getSubObjects() { |
| 118 | return this.llSubObjects; |
| 119 | } |
| 120 | |
| 121 | @Override |
| 122 | public void setSubObjects(LinkedList<PcepValueType> llSubObjects) { |
| 123 | this.llSubObjects = llSubObjects; |
| 124 | } |
| 125 | |
| 126 | /** |
| 127 | * Reads from channel buffer and return object of PcepIroObject. |
| 128 | * |
| 129 | * @param cb of type channel buffer |
| 130 | * @return object of PcepIroObject |
| 131 | * @throws PcepParseException while parsing from channel buffer |
| 132 | */ |
| 133 | public static PcepIroObject read(ChannelBuffer cb) throws PcepParseException { |
| 134 | |
| 135 | PcepObjectHeader iroObjHeader; |
| 136 | LinkedList<PcepValueType> llSubObjects; |
| 137 | |
| 138 | iroObjHeader = PcepObjectHeader.read(cb); |
| 139 | |
| 140 | //take only IroObject buffer. |
| 141 | ChannelBuffer tempCb = cb.readBytes(iroObjHeader.getObjLen() - OBJECT_HEADER_LENGTH); |
| 142 | llSubObjects = parseSubObjects(tempCb); |
| 143 | return new PcepIroObjectVer1(iroObjHeader, llSubObjects); |
| 144 | } |
| 145 | |
| 146 | /** |
| 147 | * Returns linked list of sub objects. |
| 148 | * |
| 149 | * @param cb of type channel buffer |
| 150 | * @return linked list of sub objects |
| 151 | * @throws PcepParseException while parsing subobjects from channel buffer |
| 152 | */ |
| 153 | protected static LinkedList<PcepValueType> parseSubObjects(ChannelBuffer cb) throws PcepParseException { |
| 154 | |
Sho SHIMIZU | 9b8274c | 2015-09-04 15:54:24 -0700 | [diff] [blame] | 155 | LinkedList<PcepValueType> llSubObjects = new LinkedList<>(); |
bharat saraswal | f7364db | 2015-08-11 13:39:31 +0530 | [diff] [blame] | 156 | |
| 157 | while (0 < cb.readableBytes()) { |
| 158 | |
| 159 | //check the Type of the Subobjects. |
| 160 | byte yType = cb.readByte(); |
| 161 | yType = (byte) (yType & (YTYPE_SHIFT_VALUE)); |
| 162 | byte hLength = cb.readByte(); |
| 163 | |
| 164 | PcepValueType subObj; |
| 165 | switch (yType) { |
| 166 | |
| 167 | case IPv4SubObject.TYPE: |
| 168 | subObj = IPv4SubObject.read(cb); |
| 169 | break; |
| 170 | |
| 171 | default: |
| 172 | throw new PcepParseException("Invalid sub object. Type: " + (int) yType); |
| 173 | } |
| 174 | |
| 175 | // Check for the padding |
| 176 | int pad = hLength % 4; |
| 177 | if (0 < pad) { |
| 178 | pad = 4 - pad; |
| 179 | if (pad <= cb.readableBytes()) { |
| 180 | cb.skipBytes(pad); |
| 181 | } |
| 182 | } |
| 183 | llSubObjects.add(subObj); |
| 184 | } |
| 185 | return llSubObjects; |
| 186 | } |
| 187 | |
| 188 | @Override |
| 189 | public int write(ChannelBuffer cb) throws PcepParseException { |
| 190 | //write Object header |
| 191 | int objStartIndex = cb.writerIndex(); |
| 192 | |
| 193 | int objLenIndex = iroObjHeader.write(cb); |
| 194 | |
| 195 | if (objLenIndex <= 0) { |
| 196 | throw new PcepParseException(" ObjectLength is " + objLenIndex); |
| 197 | } |
| 198 | |
| 199 | ListIterator<PcepValueType> listIterator = llSubObjects.listIterator(); |
| 200 | while (listIterator.hasNext()) { |
| 201 | listIterator.next().write(cb); |
| 202 | } |
| 203 | |
| 204 | //Update object length now |
| 205 | int length = cb.writerIndex() - objStartIndex; |
| 206 | //will be helpful during print(). |
| 207 | iroObjHeader.setObjLen((short) length); |
| 208 | // As per RFC the length of object should be |
| 209 | // multiples of 4 |
| 210 | int pad = length % 4; |
| 211 | if (pad != 0) { |
| 212 | pad = 4 - pad; |
| 213 | for (int i = 0; i < pad; i++) { |
| 214 | cb.writeByte((byte) 0); |
| 215 | } |
| 216 | length = length + pad; |
| 217 | } |
| 218 | cb.setShort(objLenIndex, (short) length); |
| 219 | objLenIndex = cb.writerIndex(); |
| 220 | return objLenIndex; |
| 221 | } |
| 222 | |
Phanendra Manda | 51fb9c2 | 2015-09-01 16:17:41 +0530 | [diff] [blame] | 223 | /** |
| 224 | * Builder class for PCEP iro object. |
| 225 | */ |
bharat saraswal | f7364db | 2015-08-11 13:39:31 +0530 | [diff] [blame] | 226 | public static class Builder implements PcepIroObject.Builder { |
| 227 | |
| 228 | private boolean bIsHeaderSet = false; |
| 229 | |
| 230 | private PcepObjectHeader iroObjHeader; |
Sho SHIMIZU | 9b8274c | 2015-09-04 15:54:24 -0700 | [diff] [blame] | 231 | LinkedList<PcepValueType> llSubObjects = new LinkedList<>(); |
bharat saraswal | f7364db | 2015-08-11 13:39:31 +0530 | [diff] [blame] | 232 | |
| 233 | private boolean bIsPFlagSet = false; |
| 234 | private boolean bPFlag; |
| 235 | |
| 236 | private boolean bIsIFlagSet = false; |
| 237 | private boolean bIFlag; |
| 238 | |
| 239 | @Override |
| 240 | public PcepIroObject build() { |
| 241 | |
| 242 | PcepObjectHeader iroObjHeader = this.bIsHeaderSet ? this.iroObjHeader : DEFAULT_IRO_OBJECT_HEADER; |
| 243 | |
| 244 | if (bIsPFlagSet) { |
| 245 | iroObjHeader.setPFlag(bPFlag); |
| 246 | } |
| 247 | |
| 248 | if (bIsIFlagSet) { |
| 249 | iroObjHeader.setIFlag(bIFlag); |
| 250 | } |
| 251 | |
| 252 | return new PcepIroObjectVer1(iroObjHeader, this.llSubObjects); |
| 253 | } |
| 254 | |
| 255 | @Override |
| 256 | public PcepObjectHeader getIroObjHeader() { |
| 257 | return this.iroObjHeader; |
| 258 | } |
| 259 | |
| 260 | @Override |
| 261 | public Builder setIroObjHeader(PcepObjectHeader obj) { |
| 262 | this.iroObjHeader = obj; |
| 263 | this.bIsHeaderSet = true; |
| 264 | return this; |
| 265 | } |
| 266 | |
| 267 | @Override |
| 268 | public LinkedList<PcepValueType> getSubObjects() { |
| 269 | return this.llSubObjects; |
| 270 | } |
| 271 | |
| 272 | @Override |
| 273 | public Builder setSubObjects(LinkedList<PcepValueType> llSubObjects) { |
| 274 | this.llSubObjects = llSubObjects; |
| 275 | return this; |
| 276 | } |
| 277 | |
| 278 | @Override |
| 279 | public Builder setPFlag(boolean value) { |
| 280 | this.bPFlag = value; |
| 281 | this.bIsPFlagSet = true; |
| 282 | return this; |
| 283 | } |
| 284 | |
| 285 | @Override |
| 286 | public Builder setIFlag(boolean value) { |
| 287 | this.bIFlag = value; |
| 288 | this.bIsIFlagSet = true; |
| 289 | return this; |
| 290 | } |
bharat saraswal | f7364db | 2015-08-11 13:39:31 +0530 | [diff] [blame] | 291 | } |
| 292 | |
| 293 | @Override |
| 294 | public String toString() { |
Sho SHIMIZU | 7cdbcf7 | 2015-09-03 14:43:05 -0700 | [diff] [blame] | 295 | return MoreObjects.toStringHelper(getClass()) |
| 296 | .add("IroObjectHeader", iroObjHeader) |
bharat saraswal | e180630 | 2015-08-21 12:16:46 +0530 | [diff] [blame] | 297 | .add("SubObjects", llSubObjects).toString(); |
bharat saraswal | f7364db | 2015-08-11 13:39:31 +0530 | [diff] [blame] | 298 | } |
| 299 | } |