blob: ad2cc4727667a92ef0c47e0fc115dbad149c9638 [file] [log] [blame]
/*
* Copyright 2015-present Open Networking Foundation
*
* 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.PcepReportMsg;
import org.onosproject.pcepio.protocol.PcepSrpObject;
import org.onosproject.pcepio.protocol.PcepStateReport;
import org.onosproject.pcepio.protocol.PcepType;
import org.onosproject.pcepio.protocol.PcepVersion;
import org.onosproject.pcepio.types.PcepObjectHeader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.MoreObjects;
/**
* Provides PCEP report message.
*/
class PcepReportMsgVer1 implements PcepReportMsg {
// Pcep version: 1
/*
* The format of the PCRpt message is as follows:
* <PCRpt Message> ::= <Common Header>
* <state-report-list>
*Where:
* <state-report-list> ::= <state-report>[<state-report-list>]
* <state-report> ::= [<SRP>]
* <LSP>
* <path>
* Where:
* <path> ::= <ERO><attribute-list>[<RRO>]
* 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>]
*/
private static final Logger log = LoggerFactory.getLogger(PcepReportMsgVer1.class);
public static final byte PACKET_VERSION = 1;
//PACKET_MINIMUM_LENGTH = CommonHeaderLen(4)+LspObjMinLen(8)
public static final int PACKET_MINIMUM_LENGTH = 12;
public static final PcepType MSG_TYPE = PcepType.REPORT;
public static final byte REPORT_OBJ_TYPE = 1;
//Optional TLV
private LinkedList<PcepStateReport> llStateReportList;
public static final PcepReportMsgVer1.Reader READER = new Reader();
/**
* Reader class for reading PCEP report message from channel buffer.
*/
static class Reader implements PcepMessageReader<PcepReportMsg> {
LinkedList<PcepStateReport> llStateReportList;
@Override
public PcepReportMsg readFrom(ChannelBuffer cb) throws PcepParseException {
if (cb.readableBytes() < PACKET_MINIMUM_LENGTH) {
throw new PcepParseException("Received packet size " + cb.readableBytes()
+ " is less than the expected size: " + PACKET_MINIMUM_LENGTH);
}
llStateReportList = new LinkedList<>();
byte version = cb.readByte();
version = (byte) (version >> PcepMessageVer1.SHIFT_FLAG);
if (version != PACKET_VERSION) {
throw new PcepParseException(" Invalid version: " + version);
}
byte type = cb.readByte();
if (type != MSG_TYPE.getType()) {
throw new PcepParseException("Unexpected type: " + type);
}
short length = cb.readShort();
if (length < PACKET_MINIMUM_LENGTH) {
throw new PcepParseException("Wrong length. Expected to be >= " + PACKET_MINIMUM_LENGTH + ", was: "
+ length);
}
// parse state report list
parseStateReportList(cb);
return new PcepReportMsgVer1(llStateReportList);
}
// Parse State Report list
public void parseStateReportList(ChannelBuffer cb) throws PcepParseException {
/*
<state-report-list>
Where:
<state-report-list> ::= <state-report>[<state-report-list>]
<state-report> ::= [<SRP>]
<LSP>
<path>
Where:
<path> ::= <ERO><attribute-list>[<RRO>]
Where:
<attribute-list> is defined in [RFC5440] and extended by PCEP extensions.
*/
while (0 < cb.readableBytes()) {
PcepStateReport pcestateReq = new PcepStateReportVer1();
/*
* SRP is optional
* Check whether SRP Object is available, if yes store it.
* First read common object header and check the Object Class whether it is SRP or LSP
* If it is LSP then store only LSP. So, SRP is optional. then read path and store.
* If it is SRP then store SRP and then read LSP, path and store them.
*/
//mark the reader index to reset
cb.markReaderIndex();
PcepObjectHeader tempObjHeader = PcepObjectHeader.read(cb);
byte yObjectClass = tempObjHeader.getObjClass();
byte yObjectType = tempObjHeader.getObjType();
//reset reader index
cb.resetReaderIndex();
//If SRP present then store it.
if ((PcepSrpObjectVer1.SRP_OBJ_CLASS == yObjectClass)
&& (PcepSrpObjectVer1.SRP_OBJ_TYPE == yObjectType)) {
PcepSrpObject srpObj;
srpObj = PcepSrpObjectVer1.read(cb);
pcestateReq.setSrpObject(srpObj);
}
//store LSP object
PcepLspObject lspObj;
lspObj = PcepLspObjectVer1.read(cb);
pcestateReq.setLspObject(lspObj);
if (cb.readableBytes() > 0) {
//mark the reader index to reset
cb.markReaderIndex();
tempObjHeader = PcepObjectHeader.read(cb);
yObjectClass = tempObjHeader.getObjClass();
yObjectType = tempObjHeader.getObjType();
//reset reader index
cb.resetReaderIndex();
if ((PcepEroObjectVer1.ERO_OBJ_CLASS == yObjectClass)
&& (PcepEroObjectVer1.ERO_OBJ_TYPE == yObjectType)) {
// store path
PcepStateReport.PcepMsgPath msgPath = new PcepStateReportVer1().new PcepMsgPath().read(cb);
pcestateReq.setMsgPath(msgPath);
}
}
llStateReportList.add(pcestateReq);
}
}
}
/**
* Constructor to initialize State Report List.
*
* @param llStateReportList list of type Pcep state report
*/
PcepReportMsgVer1(LinkedList<PcepStateReport> llStateReportList) {
this.llStateReportList = llStateReportList;
}
/**
* Builder class for PCEP Report message.
*/
static class Builder implements PcepReportMsg.Builder {
// Pcep report message fields
LinkedList<PcepStateReport> llStateReportList;
@Override
public PcepVersion getVersion() {
return PcepVersion.PCEP_1;
}
@Override
public PcepType getType() {
return PcepType.REPORT;
}
@Override
public PcepReportMsg build() {
return new PcepReportMsgVer1(this.llStateReportList);
}
@Override
public LinkedList<PcepStateReport> getStateReportList() {
return this.llStateReportList;
}
@Override
public Builder setStateReportList(LinkedList<PcepStateReport> ll) {
this.llStateReportList = ll;
return this;
}
}
@Override
public void writeTo(ChannelBuffer cb) throws PcepParseException {
WRITER.write(cb, this);
}
static final Writer WRITER = new Writer();
/**
* Writer class for writing PCEP report message to channel buffer.
*/
static class Writer implements PcepMessageWriter<PcepReportMsgVer1> {
@Override
public void write(ChannelBuffer cb, PcepReportMsgVer1 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<PcepStateReport> listIterator = message.llStateReportList.listIterator();
while (listIterator.hasNext()) {
PcepStateReport stateRpt = listIterator.next();
PcepSrpObject srpObj = stateRpt.getSrpObject();
//SRP object is optional
if (srpObj != null) {
srpObj.write(cb);
}
//LSP object is mandatory
PcepLspObject lspObj = stateRpt.getLspObject();
if (lspObj == null) {
throw new PcepParseException("LSP Object is mandatory object for PcRpt message.");
} else {
lspObj.write(cb);
}
//path is mandatory
PcepStateReport.PcepMsgPath msgPath = stateRpt.getMsgPath();
if (msgPath == null) {
throw new PcepParseException("Message path is mandatory object for PcRpt message.");
} else {
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<PcepStateReport> getStateReportList() {
return this.llStateReportList;
}
@Override
public void setStateReportList(LinkedList<PcepStateReport> ll) {
this.llStateReportList = ll;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("StateReportList", llStateReportList)
.toString();
}
}