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