blob: 53c66872ac2a2f744ddf1d1b1f1cf9fd37bd34e1 [file] [log] [blame]
/*
* Copyright 2015 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();
}
}