| /* |
| * Copyright 2015-present Open Networking Laboratory |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.onosproject.pcepio.protocol.ver1; |
| |
| import java.util.LinkedList; |
| import java.util.ListIterator; |
| |
| import org.jboss.netty.buffer.ChannelBuffer; |
| import org.onosproject.pcepio.exceptions.PcepParseException; |
| import org.onosproject.pcepio.protocol.PcepLspObject; |
| import org.onosproject.pcepio.protocol.PcepMessageReader; |
| import org.onosproject.pcepio.protocol.PcepMessageWriter; |
| import org.onosproject.pcepio.protocol.PcepMsgPath; |
| import org.onosproject.pcepio.protocol.PcepSrpObject; |
| import org.onosproject.pcepio.protocol.PcepType; |
| import org.onosproject.pcepio.protocol.PcepUpdateMsg; |
| import org.onosproject.pcepio.protocol.PcepUpdateRequest; |
| import org.onosproject.pcepio.protocol.PcepVersion; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| import com.google.common.base.MoreObjects; |
| |
| /** |
| * Provides PCEP update message. |
| */ |
| |
| class PcepUpdateMsgVer1 implements PcepUpdateMsg { |
| |
| // Pcep version: 1 |
| |
| /* The format of the PCUpd message is as follows: |
| * <PCUpd Message> ::= <Common Header> |
| * <update-request-list> |
| * Where: |
| * <update-request-list> ::= <update-request>[<update-request-list>] |
| * <update-request> ::= <SRP> |
| * <LSP> |
| * <path> |
| * Where: |
| * <path> ::= <ERO><attribute-list> |
| * Where: |
| * <attribute-list> is defined in [RFC5440] and extended by PCEP extensions. |
| * where: |
| * <attribute-list> ::=[<LSPA>] |
| * [<BANDWIDTH>] |
| * [<metric-list>] |
| * [<IRO>] |
| * <metric-list> ::=<METRIC>[<metric-list>] |
| * |
| * 0 1 2 3 |
| * 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 |
| * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| * | Ver | Flags | Message-Type | Message-Length | |
| * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| * | | |
| * // UPDATE REQUEST LIST // |
| * | | |
| * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| * |
| * Reference:Internet-Draft-PCEP Extensions-for-Stateful-PCE-10 |
| */ |
| |
| protected static final Logger log = LoggerFactory.getLogger(PcepUpdateMsgVer1.class); |
| |
| public static final byte PACKET_VERSION = 1; |
| // UpdateMsgMinLength = SrpObjMinLentgh(12)+LspObjMinLength(8)+EroObjMinLength(12)+ CommonHeaderLength(4) |
| public static final short PACKET_MINIMUM_LENGTH = 36; |
| public static final PcepType MSG_TYPE = PcepType.UPDATE; |
| //Update Request List |
| private LinkedList<PcepUpdateRequest> llUpdateRequestList; |
| |
| public static final PcepUpdateMsgVer1.Reader READER = new Reader(); |
| |
| /** |
| * Reader reads UpdateMessage from the channel. |
| */ |
| static class Reader implements PcepMessageReader<PcepUpdateMsg> { |
| |
| LinkedList<PcepUpdateRequest> llUpdateRequestList; |
| |
| @Override |
| public PcepUpdateMsg readFrom(ChannelBuffer cb) throws PcepParseException { |
| |
| if (cb.readableBytes() < PACKET_MINIMUM_LENGTH) { |
| throw new PcepParseException("Readable bytes is less than update message minimum length"); |
| } |
| |
| llUpdateRequestList = new LinkedList<>(); |
| |
| // fixed value property version == 1 |
| byte version = cb.readByte(); |
| version = (byte) (version >> PcepMessageVer1.SHIFT_FLAG); |
| if (version != PACKET_VERSION) { |
| throw new PcepParseException("Wrong version. Expected=PcepVersion.PCEP_1(1), got=" + version); |
| } |
| // fixed value property type == 11 |
| byte type = cb.readByte(); |
| if (type != MSG_TYPE.getType()) { |
| throw new PcepParseException("Wrong type. Expected=PcepType.UPDATE(11), got=" + type); |
| } |
| short length = cb.readShort(); |
| if (length < PACKET_MINIMUM_LENGTH) { |
| throw new PcepParseException("Wrong length. Expected to be >= " + PACKET_MINIMUM_LENGTH + ", was: " |
| + length); |
| } |
| |
| log.debug("reading update message of length " + length); |
| |
| // parse Update Request list |
| if (!parseUpdateRequestList(cb)) { |
| throw new PcepParseException("parsing Update Request List Failed."); |
| } |
| |
| return new PcepUpdateMsgVer1(llUpdateRequestList); |
| } |
| |
| /** |
| * Parse update request list. |
| * |
| * @param cb of type channel buffer |
| * @return true after parsing Update Request List |
| * @throws PcepParseException while parsing update request list from channel buffer |
| */ |
| public boolean parseUpdateRequestList(ChannelBuffer cb) throws PcepParseException { |
| |
| /* <update-request-list> |
| * Where: |
| * <update-request-list> ::= <update-request>[<update-request-list>] |
| * <update-request> ::= <SRP> |
| * <LSP> |
| * <path> |
| * Where: |
| * <path> ::= <ERO><attribute-list> |
| * Where: |
| * <attribute-list> is defined in [RFC5440] and extended by PCEP extensions. |
| */ |
| |
| while (0 < cb.readableBytes()) { |
| |
| PcepUpdateRequest pceUpdateReq = new PcepUpdateRequestVer1(); |
| |
| //Read SRP Object and Store it. |
| PcepSrpObject srpObj; |
| srpObj = PcepSrpObjectVer1.read(cb); |
| pceUpdateReq.setSrpObject(srpObj); |
| |
| //Read LSP object and Store it. |
| PcepLspObject lspObj; |
| lspObj = PcepLspObjectVer1.read(cb); |
| pceUpdateReq.setLspObject(lspObj); |
| |
| // Read Msg Path and store it. |
| PcepMsgPath msgPath = new PcepMsgPathVer1().read(cb); |
| pceUpdateReq.setMsgPath(msgPath); |
| |
| llUpdateRequestList.add(pceUpdateReq); |
| } |
| return true; |
| } |
| } |
| |
| /** |
| * Constructor to initialize llUpdateRequestList. |
| * |
| * @param llUpdateRequestList list of PcepUpdateRequest. |
| */ |
| PcepUpdateMsgVer1(LinkedList<PcepUpdateRequest> llUpdateRequestList) { |
| this.llUpdateRequestList = llUpdateRequestList; |
| } |
| |
| /** |
| * Builder class for PCPE update message. |
| */ |
| static class Builder implements PcepUpdateMsg.Builder { |
| |
| // PCEP report message fields |
| LinkedList<PcepUpdateRequest> llUpdateRequestList; |
| |
| @Override |
| public PcepVersion getVersion() { |
| return PcepVersion.PCEP_1; |
| } |
| |
| @Override |
| public PcepType getType() { |
| return PcepType.UPDATE; |
| } |
| |
| @Override |
| public PcepUpdateMsg build() { |
| return new PcepUpdateMsgVer1(this.llUpdateRequestList); |
| } |
| |
| @Override |
| public LinkedList<PcepUpdateRequest> getUpdateRequestList() { |
| return this.llUpdateRequestList; |
| } |
| |
| @Override |
| public Builder setUpdateRequestList(LinkedList<PcepUpdateRequest> llUpdateRequestList) { |
| this.llUpdateRequestList = llUpdateRequestList; |
| return this; |
| } |
| |
| } |
| |
| @Override |
| public void writeTo(ChannelBuffer cb) throws PcepParseException { |
| WRITER.write(cb, this); |
| } |
| |
| static final Writer WRITER = new Writer(); |
| |
| /** |
| * Writer writes UpdateMessage to the channel buffer. |
| */ |
| static class Writer implements PcepMessageWriter<PcepUpdateMsgVer1> { |
| |
| @Override |
| public void write(ChannelBuffer cb, PcepUpdateMsgVer1 message) throws PcepParseException { |
| |
| int startIndex = cb.writerIndex(); |
| // first 3 bits set to version |
| cb.writeByte((byte) (PACKET_VERSION << PcepMessageVer1.SHIFT_FLAG)); |
| // message type |
| cb.writeByte(MSG_TYPE.getType()); |
| /* length is length of variable message, will be updated at the end |
| * Store the position of message |
| * length in buffer |
| */ |
| int msgLenIndex = cb.writerIndex(); |
| |
| cb.writeShort((short) 0); |
| ListIterator<PcepUpdateRequest> listIterator = message.llUpdateRequestList.listIterator(); |
| |
| while (listIterator.hasNext()) { |
| |
| PcepUpdateRequest updateReq = listIterator.next(); |
| |
| //SRP object is mandatory |
| PcepSrpObject srpObj = updateReq.getSrpObject(); |
| srpObj.write(cb); |
| |
| //LSP object is mandatory |
| PcepLspObject lspObj = updateReq.getLspObject(); |
| lspObj.write(cb); |
| |
| //PATH object is mandatory |
| PcepMsgPath msgPath = updateReq.getMsgPath(); |
| msgPath.write(cb); |
| } |
| |
| // update message length field |
| int length = cb.writerIndex() - startIndex; |
| cb.setShort(msgLenIndex, (short) length); |
| } |
| } |
| |
| @Override |
| public PcepVersion getVersion() { |
| return PcepVersion.PCEP_1; |
| } |
| |
| @Override |
| public PcepType getType() { |
| return MSG_TYPE; |
| } |
| |
| @Override |
| public LinkedList<PcepUpdateRequest> getUpdateRequestList() { |
| return this.llUpdateRequestList; |
| } |
| |
| @Override |
| public void setUpdateRequestList(LinkedList<PcepUpdateRequest> llUpdateRequestList) { |
| this.llUpdateRequestList = llUpdateRequestList; |
| } |
| |
| @Override |
| public String toString() { |
| return MoreObjects.toStringHelper(getClass()) |
| .add("UpdateRequestList", llUpdateRequestList) |
| .toString(); |
| } |
| } |