blob: fe6bc92ac6563f9e4c8005bb014f32857bf0c2c9 [file] [log] [blame]
bharat saraswalf7364db2015-08-11 13:39:31 +05301/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
bharat saraswalf7364db2015-08-11 13:39:31 +05303 *
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.PcepCloseMsg;
25import org.onosproject.pcepio.protocol.PcepMessageReader;
26import org.onosproject.pcepio.protocol.PcepMessageWriter;
27import org.onosproject.pcepio.protocol.PcepType;
28import org.onosproject.pcepio.protocol.PcepVersion;
29import org.onosproject.pcepio.types.PcepObjectHeader;
30import org.onosproject.pcepio.types.PcepValueType;
31import org.slf4j.Logger;
32import org.slf4j.LoggerFactory;
33
34import com.google.common.base.MoreObjects;
35
Phanendra Manda51fb9c22015-09-01 16:17:41 +053036/**
37 * Provides PCEP Close Message.
bharat saraswalf7364db2015-08-11 13:39:31 +053038 */
39class PcepCloseMsgVer1 implements PcepCloseMsg {
40
Phanendra Manda51fb9c22015-09-01 16:17:41 +053041 /*
42 * RFC : 5440 , section : 6.8
43 * <Close Message> ::= <Common Header> <CLOSE>
44 *
45 0 1 2 3
46 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
47 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
48 | Ver | Flags | Message-Type | Message-Length |
49 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
50 | Object-Class | OT |Res|P|I| Object Length (bytes) |
51 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
52 | Reserved | Flags | Reason |
53 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
54 | |
55 // Optional TLVs //
56 | |
57 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
58 */
59
bharat saraswalf7364db2015-08-11 13:39:31 +053060 protected static final Logger log = LoggerFactory.getLogger(PcepCloseMsgVer1.class);
61
62 // Pcep version: 1
63 public static final byte PACKET_VERSION = 1;
64 public static final int PACKET_MINIMUM_LENGTH = 12;
65 public static final PcepType MSG_TYPE = PcepType.CLOSE;
66 public static final byte CLOSE_OBJ_TYPE = 1;
67 public static final byte CLOSE_OBJ_CLASS = 15;
68 public static final byte CLOSE_OBJECT_VERSION = 1;
69 public static final byte DEFAULT_REASON = 1; // Default reason to close
70 public static final short CLOSE_OBJ_MINIMUM_LENGTH = 8;
71 public static final int SHIFT_FLAG = 5;
72 static final PcepObjectHeader DEFAULT_CLOSE_HEADER = new PcepObjectHeader(CLOSE_OBJ_CLASS, CLOSE_OBJ_TYPE,
73 PcepObjectHeader.REQ_OBJ_OPTIONAL_PROCESS, PcepObjectHeader.RSP_OBJ_PROCESSED, CLOSE_OBJ_MINIMUM_LENGTH);
74
75 private final PcepObjectHeader closeObjHeader;
76 private byte yReason;
77 private LinkedList<PcepValueType> llOptionalTlv;
78
79 public static final PcepCloseMsgVer1.Reader READER = new Reader();
80
Phanendra Manda51fb9c22015-09-01 16:17:41 +053081 /**
82 * Reader class for reading close message for channel buffer.
83 */
bharat saraswalf7364db2015-08-11 13:39:31 +053084 static class Reader implements PcepMessageReader<PcepCloseMsg> {
85 PcepObjectHeader closeObjHeader;
86 byte yReason;
87 // Optional TLV
88 private LinkedList<PcepValueType> llOptionalTlv;
89
90 @Override
91 public PcepCloseMsg readFrom(ChannelBuffer cb) throws PcepParseException {
92
93 if (cb.readableBytes() < PACKET_MINIMUM_LENGTH) {
94 throw new PcepParseException("Packet size is less than the minimum length.");
95 }
96 // fixed value property version == 1
97 byte version = cb.readByte();
98 version = (byte) (version >> SHIFT_FLAG);
99 if (version != PACKET_VERSION) {
100 throw new PcepParseException("Wrong version. Expected=PcepVersion.PCEP_1(1), got=" + version);
101 }
102 // fixed value property type == 7
103 byte type = cb.readByte();
104 if (type != MSG_TYPE.getType()) {
105 throw new PcepParseException("Wrong type. Expected=PcepType.CLOSE(7), got=" + type);
106 }
107 short length = cb.readShort();
108 if (length < PACKET_MINIMUM_LENGTH) {
109 throw new PcepParseException("Wrong length. Expected to be >= " + PACKET_MINIMUM_LENGTH + ", was: "
110 + length);
111 }
112 closeObjHeader = PcepObjectHeader.read(cb);
113 // Reserved
114 cb.readShort();
115 // Flags
116 cb.readByte();
117 // Reason
118 yReason = cb.readByte();
119 // parse optional TLV
120 llOptionalTlv = parseOptionalTlv(cb);
121 return new PcepCloseMsgVer1(closeObjHeader, yReason, llOptionalTlv);
122 }
123 }
124
125 /**
126 * Parse the list of Optional Tlvs.
127 *
128 * @param cb channel buffer
129 * @return list of Optional Tlvs
130 * @throws PcepParseException when fails to parse optional tlvs
131 */
132 public static LinkedList<PcepValueType> parseOptionalTlv(ChannelBuffer cb) throws PcepParseException {
133
Sho SHIMIZU9b8274c2015-09-04 15:54:24 -0700134 LinkedList<PcepValueType> llOptionalTlv = new LinkedList<>();
bharat saraswalf7364db2015-08-11 13:39:31 +0530135 /*
136 rfc 5440:
137 Optional TLVs may be included within the CLOSE object body. The
138 specification of such TLVs is outside the scope of this document.
139 */
140 return llOptionalTlv;
141 }
142
143 /**
144 * constructor to initialize PCEP close Message with all the parameters.
145 *
146 * @param closeObjHeader object header for close message
147 * @param yReason reason for closing the channel
148 * @param llOptionalTlv list of optional tlvs
149 */
150 PcepCloseMsgVer1(PcepObjectHeader closeObjHeader, byte yReason, LinkedList<PcepValueType> llOptionalTlv) {
151
152 this.closeObjHeader = closeObjHeader;
153 this.yReason = yReason;
154 this.llOptionalTlv = llOptionalTlv;
155 }
156
157 /**
158 * Builder class for PCEP close message.
159 */
160 static class Builder implements PcepCloseMsg.Builder {
161
162 // PCEP Close message fields
163 private boolean bIsHeaderSet = false;
164 private PcepObjectHeader closeObjHeader;
165 private boolean bIsReasonSet = false;
166 private byte yReason;
Sho SHIMIZU9b8274c2015-09-04 15:54:24 -0700167 private LinkedList<PcepValueType> llOptionalTlv = new LinkedList<>();
bharat saraswalf7364db2015-08-11 13:39:31 +0530168
169 private boolean bIsPFlagSet = false;
170 private boolean bPFlag;
171
172 private boolean bIsIFlagSet = false;
173 private boolean bIFlag;
174
175 @Override
176 public PcepVersion getVersion() {
177 return PcepVersion.PCEP_1;
178 }
179
180 @Override
181 public PcepType getType() {
182 return PcepType.CLOSE;
183 }
184
185 @Override
186 public PcepCloseMsg build() {
187
188 PcepObjectHeader closeObjHeader = this.bIsHeaderSet ? this.closeObjHeader : DEFAULT_CLOSE_HEADER;
189 byte yReason = this.bIsReasonSet ? this.yReason : DEFAULT_REASON;
190
191 if (bIsPFlagSet) {
192 closeObjHeader.setPFlag(bPFlag);
193 }
194
195 if (bIsIFlagSet) {
196 closeObjHeader.setIFlag(bIFlag);
197 }
198 return new PcepCloseMsgVer1(closeObjHeader, yReason, this.llOptionalTlv);
199 }
200
201 @Override
202 public PcepObjectHeader getCloseObjHeader() {
203 return this.closeObjHeader;
204 }
205
206 @Override
207 public Builder setCloseObjHeader(PcepObjectHeader obj) {
208 this.closeObjHeader = obj;
209 this.bIsHeaderSet = true;
210 return this;
211 }
212
213 @Override
214 public byte getReason() {
215 return this.yReason;
216 }
217
218 @Override
219 public Builder setReason(byte value) {
220 this.yReason = value;
221 this.bIsReasonSet = true;
222 return this;
223 }
224
225 @Override
226 public Builder setOptionalTlv(LinkedList<PcepValueType> llOptionalTlv) {
227 this.llOptionalTlv = llOptionalTlv;
228 return this;
229 }
230
231 @Override
232 public LinkedList<PcepValueType> getOptionalTlv() {
233 return this.llOptionalTlv;
234 }
235
236 @Override
237 public Builder setPFlag(boolean value) {
238 this.bPFlag = value;
239 this.bIsPFlagSet = true;
240 return this;
241 }
242
243 @Override
244 public Builder setIFlag(boolean value) {
245 this.bIFlag = value;
246 this.bIsIFlagSet = true;
247 return this;
248 }
249 }
250
251 @Override
252 public void writeTo(ChannelBuffer cb) throws PcepParseException {
253 WRITER.write(cb, this);
254 }
255
256 static final Writer WRITER = new Writer();
257
Phanendra Manda51fb9c22015-09-01 16:17:41 +0530258 /**
259 * Writer class for writing close message to channel buffer.
260 */
bharat saraswalf7364db2015-08-11 13:39:31 +0530261 static class Writer implements PcepMessageWriter<PcepCloseMsgVer1> {
262
263 @Override
264 public void write(ChannelBuffer cb, PcepCloseMsgVer1 message) throws PcepParseException {
265 int startIndex = cb.writerIndex();
266 // first 3 bits set to version
267 cb.writeByte((byte) (PACKET_VERSION << SHIFT_FLAG));
268 // message type
269 cb.writeByte(MSG_TYPE.getType());
270 // length is length of variable message, will be updated at the end
271 // Store the position of message
272 // length in buffer
273 int msgLenIndex = cb.writerIndex();
274 cb.writeShort((short) 0);
275 int objStartIndex = cb.writerIndex();
276 int objLenIndex = message.closeObjHeader.write(cb);
277 if (objLenIndex <= 0) {
278 throw new PcepParseException("Failed to write Close object header.");
279 }
280 // first 3 bits set to version
281 cb.writeShort(0); // Reserved
282 cb.writeByte(0); // Flags
283 cb.writeByte(message.yReason);
284 // Pack optional TLV
285 packOptionalTlv(cb, message);
286 int length = cb.writerIndex() - objStartIndex;
287 cb.setShort(objLenIndex, (short) length);
288 // will be helpful during print().
289 message.closeObjHeader.setObjLen((short) length);
290 // As per RFC the length of object should be
291 // multiples of 4
292 int pad = length % 4;
293 if (pad != 0) {
294 pad = 4 - pad;
295 for (int i = 0; i < pad; i++) {
296 cb.writeByte((byte) 0);
297 }
298 length = length + pad;
299 }
300 // update message length field
301 length = cb.writerIndex() - startIndex;
302 cb.setShort(msgLenIndex, (short) length);
303 }
304
305 public void packOptionalTlv(ChannelBuffer cb, PcepCloseMsgVer1 message) {
306
307 LinkedList<PcepValueType> llOptionalTlv = message.llOptionalTlv;
308 ListIterator<PcepValueType> listIterator = llOptionalTlv.listIterator();
309 while (listIterator.hasNext()) {
310 listIterator.next().write(cb);
311 }
312 }
313 }
314
315 @Override
316 public PcepVersion getVersion() {
317 return PcepVersion.PCEP_1;
318 }
319
320 @Override
321 public PcepType getType() {
322 return MSG_TYPE;
323 }
324
325 @Override
326 public byte getReason() {
327 return this.yReason;
328 }
329
330 @Override
331 public void setReason(byte value) {
332 this.yReason = value;
333 }
334
335 @Override
336 public LinkedList<PcepValueType> getOptionalTlv() {
337 return this.llOptionalTlv;
338 }
339
340 @Override
341 public void setOptionalTlv(LinkedList<PcepValueType> llOptionalTlv) {
342 this.llOptionalTlv = llOptionalTlv;
343 }
344
345 @Override
bharat saraswalf7364db2015-08-11 13:39:31 +0530346 public String toString() {
Sho SHIMIZU7cdbcf72015-09-03 14:43:05 -0700347 return MoreObjects.toStringHelper(getClass())
348 .add("closeObjectHeader", closeObjHeader).add("Reason", yReason)
bharat saraswale1806302015-08-21 12:16:46 +0530349 .add("OptionalTlvlist", llOptionalTlv).toString();
bharat saraswalf7364db2015-08-11 13:39:31 +0530350 }
351}