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.PcepCloseMsg;
25 import org.onosproject.pcepio.protocol.PcepMessageReader;
26 import org.onosproject.pcepio.protocol.PcepMessageWriter;
27 import org.onosproject.pcepio.protocol.PcepType;
28 import org.onosproject.pcepio.protocol.PcepVersion;
29 import org.onosproject.pcepio.types.PcepObjectHeader;
30 import org.onosproject.pcepio.types.PcepValueType;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
34 import com.google.common.base.MoreObjects;
37 * Provides PCEP Close Message.
39 class PcepCloseMsgVer1 implements PcepCloseMsg {
42 * RFC : 5440 , section : 6.8
43 * <Close Message> ::= <Common Header> <CLOSE>
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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
57 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
60 protected static final Logger log = LoggerFactory.getLogger(PcepCloseMsgVer1.class);
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);
75 private final PcepObjectHeader closeObjHeader;
77 private LinkedList<PcepValueType> llOptionalTlv;
79 public static final PcepCloseMsgVer1.Reader READER = new Reader();
82 * Reader class for reading close message for channel buffer.
84 static class Reader implements PcepMessageReader<PcepCloseMsg> {
85 PcepObjectHeader closeObjHeader;
88 private LinkedList<PcepValueType> llOptionalTlv;
91 public PcepCloseMsg readFrom(ChannelBuffer cb) throws PcepParseException {
93 if (cb.readableBytes() < PACKET_MINIMUM_LENGTH) {
94 throw new PcepParseException("Packet size is less than the minimum length.");
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);
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);
107 short length = cb.readShort();
108 if (length < PACKET_MINIMUM_LENGTH) {
109 throw new PcepParseException("Wrong length. Expected to be >= " + PACKET_MINIMUM_LENGTH + ", was: "
112 closeObjHeader = PcepObjectHeader.read(cb);
118 yReason = cb.readByte();
119 // parse optional TLV
120 llOptionalTlv = parseOptionalTlv(cb);
121 return new PcepCloseMsgVer1(closeObjHeader, yReason, llOptionalTlv);
126 * Parse the list of Optional Tlvs.
128 * @param cb channel buffer
129 * @return list of Optional Tlvs
130 * @throws PcepParseException when fails to parse optional tlvs
132 public static LinkedList<PcepValueType> parseOptionalTlv(ChannelBuffer cb) throws PcepParseException {
134 LinkedList<PcepValueType> llOptionalTlv = new LinkedList<>();
137 Optional TLVs may be included within the CLOSE object body. The
138 specification of such TLVs is outside the scope of this document.
140 return llOptionalTlv;
144 * constructor to initialize PCEP close Message with all the parameters.
146 * @param closeObjHeader object header for close message
147 * @param yReason reason for closing the channel
148 * @param llOptionalTlv list of optional tlvs
150 PcepCloseMsgVer1(PcepObjectHeader closeObjHeader, byte yReason, LinkedList<PcepValueType> llOptionalTlv) {
152 this.closeObjHeader = closeObjHeader;
153 this.yReason = yReason;
154 this.llOptionalTlv = llOptionalTlv;
158 * Builder class for PCEP close message.
160 static class Builder implements PcepCloseMsg.Builder {
162 // PCEP Close message fields
163 private boolean bIsHeaderSet = false;
164 private PcepObjectHeader closeObjHeader;
165 private boolean bIsReasonSet = false;
166 private byte yReason;
167 private LinkedList<PcepValueType> llOptionalTlv = new LinkedList<>();
169 private boolean bIsPFlagSet = false;
170 private boolean bPFlag;
172 private boolean bIsIFlagSet = false;
173 private boolean bIFlag;
176 public PcepVersion getVersion() {
177 return PcepVersion.PCEP_1;
181 public PcepType getType() {
182 return PcepType.CLOSE;
186 public PcepCloseMsg build() {
188 PcepObjectHeader closeObjHeader = this.bIsHeaderSet ? this.closeObjHeader : DEFAULT_CLOSE_HEADER;
189 byte yReason = this.bIsReasonSet ? this.yReason : DEFAULT_REASON;
192 closeObjHeader.setPFlag(bPFlag);
196 closeObjHeader.setIFlag(bIFlag);
198 return new PcepCloseMsgVer1(closeObjHeader, yReason, this.llOptionalTlv);
202 public PcepObjectHeader getCloseObjHeader() {
203 return this.closeObjHeader;
207 public Builder setCloseObjHeader(PcepObjectHeader obj) {
208 this.closeObjHeader = obj;
209 this.bIsHeaderSet = true;
214 public byte getReason() {
219 public Builder setReason(byte value) {
220 this.yReason = value;
221 this.bIsReasonSet = true;
226 public Builder setOptionalTlv(LinkedList<PcepValueType> llOptionalTlv) {
227 this.llOptionalTlv = llOptionalTlv;
232 public LinkedList<PcepValueType> getOptionalTlv() {
233 return this.llOptionalTlv;
237 public Builder setPFlag(boolean value) {
239 this.bIsPFlagSet = true;
244 public Builder setIFlag(boolean value) {
246 this.bIsIFlagSet = true;
252 public void writeTo(ChannelBuffer cb) throws PcepParseException {
253 WRITER.write(cb, this);
256 static final Writer WRITER = new Writer();
259 * Writer class for writing close message to channel buffer.
261 static class Writer implements PcepMessageWriter<PcepCloseMsgVer1> {
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));
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
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.");
280 // first 3 bits set to version
281 cb.writeShort(0); // Reserved
282 cb.writeByte(0); // Flags
283 cb.writeByte(message.yReason);
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
292 int pad = length % 4;
295 for (int i = 0; i < pad; i++) {
296 cb.writeByte((byte) 0);
298 length = length + pad;
300 // update message length field
301 length = cb.writerIndex() - startIndex;
302 cb.setShort(msgLenIndex, (short) length);
305 public void packOptionalTlv(ChannelBuffer cb, PcepCloseMsgVer1 message) {
307 LinkedList<PcepValueType> llOptionalTlv = message.llOptionalTlv;
308 ListIterator<PcepValueType> listIterator = llOptionalTlv.listIterator();
309 while (listIterator.hasNext()) {
310 listIterator.next().write(cb);
316 public PcepVersion getVersion() {
317 return PcepVersion.PCEP_1;
321 public PcepType getType() {
326 public byte getReason() {
331 public void setReason(byte value) {
332 this.yReason = value;
336 public LinkedList<PcepValueType> getOptionalTlv() {
337 return this.llOptionalTlv;
341 public void setOptionalTlv(LinkedList<PcepValueType> llOptionalTlv) {
342 this.llOptionalTlv = llOptionalTlv;
346 public String toString() {
347 return MoreObjects.toStringHelper(getClass())
348 .add("closeObjectHeader", closeObjHeader).add("Reason", yReason)
349 .add("OptionalTlvlist", llOptionalTlv).toString();