blob: 9c1c167408ae82930ab0f2a02a3ae0f20959155b [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.PcepSrpObject;
import org.onosproject.pcepio.types.PathSetupTypeTlv;
import org.onosproject.pcepio.types.PcepObjectHeader;
import org.onosproject.pcepio.types.PcepValueType;
import org.onosproject.pcepio.types.SymbolicPathNameTlv;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.MoreObjects;
/**
* Provides PCEP SRP obejct.
*/
public class PcepSrpObjectVer1 implements PcepSrpObject {
/*
* ref : draft-ietf-pce-stateful-pce-10, section : 7.2
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Object-Class | OT |Res|P|I| Object Length (bytes) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Flags |R|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| SRP-ID-number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
// Optional TLVs //
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
protected static final Logger log = LoggerFactory.getLogger(PcepSrpObjectVer1.class);
public static final byte SRP_OBJ_TYPE = 1;
public static final byte SRP_OBJ_CLASS = 33;
public static final byte SRP_OBJECT_VERSION = 1;
public static final short SRP_OBJ_MINIMUM_LENGTH = 12;
public static final int MINIMUM_COMMON_HEADER_LENGTH = 4;
public static final boolean DEFAULT_RFLAG = false;
static final PcepObjectHeader DEFAULT_SRP_OBJECT_HEADER = new PcepObjectHeader(SRP_OBJ_CLASS, SRP_OBJ_TYPE,
PcepObjectHeader.REQ_OBJ_OPTIONAL_PROCESS, PcepObjectHeader.RSP_OBJ_PROCESSED, SRP_OBJ_MINIMUM_LENGTH);
private PcepObjectHeader srpObjHeader;
private static int flags;
private boolean bRFlag;
private int srpId;
//Optional TLV
private LinkedList<PcepValueType> llOptionalTlv;
public static final byte BBIT_SET = 1;
public static final byte BBIT_RESET = 0;
/**
* Constructor to initialize member variables.
*
* @param srpObjHeader srp object header
* @param bRFlag R flag
* @param srpID srp Id
* @param llOptionalTlv list of optional tlv
*/
public PcepSrpObjectVer1(PcepObjectHeader srpObjHeader, boolean bRFlag, int srpID,
LinkedList<PcepValueType> llOptionalTlv) {
this.srpObjHeader = srpObjHeader;
this.bRFlag = bRFlag;
this.srpId = srpID;
this.llOptionalTlv = llOptionalTlv;
}
/**
* sets the SRP object header.
*
* @param obj srp object header
*/
public void setSrpObjHeader(PcepObjectHeader obj) {
this.srpObjHeader = obj;
}
@Override
public void setSrpID(int srpID) {
this.srpId = srpID;
}
@Override
public void setRFlag(boolean bRFlag) {
this.bRFlag = bRFlag;
}
/**
* Returns SRP object header.
*
* @return srpObjHeader
*/
public PcepObjectHeader getSrpObjHeader() {
return this.srpObjHeader;
}
@Override
public int getSrpID() {
return this.srpId;
}
@Override
public boolean getRFlag() {
return this.bRFlag;
}
@Override
public void setOptionalTlv(LinkedList<PcepValueType> llOptionalTlv) {
this.llOptionalTlv = llOptionalTlv;
}
@Override
public LinkedList<PcepValueType> getOptionalTlv() {
return this.llOptionalTlv;
}
/**
* Reads from channel buffer and returns instance of PCEP SRP object.
*
* @param cb of channel buffer.
* @return PCEP SRP object
* @throws PcepParseException when srp object is not received in channel buffer
*/
public static PcepSrpObject read(ChannelBuffer cb) throws PcepParseException {
log.debug("SrpObject::read");
PcepObjectHeader srpObjHeader;
boolean bRFlag;
int srpID;
int flags;
LinkedList<PcepValueType> llOptionalTlv = new LinkedList<>();
srpObjHeader = PcepObjectHeader.read(cb);
if (srpObjHeader.getObjClass() != SRP_OBJ_CLASS) {
throw new PcepParseException("SRP object expected. But received " + srpObjHeader.getObjClass());
}
//take only SrpObject buffer.
ChannelBuffer tempCb = cb.readBytes(srpObjHeader.getObjLen() - MINIMUM_COMMON_HEADER_LENGTH);
flags = tempCb.readInt();
bRFlag = 0 < flags;
srpID = tempCb.readInt();
llOptionalTlv = parseOptionalTlv(tempCb);
return new PcepSrpObjectVer1(srpObjHeader, bRFlag, srpID, llOptionalTlv);
}
@Override
public int write(ChannelBuffer cb) throws PcepParseException {
int objStartIndex = cb.writerIndex();
//write common header
int objLenIndex = srpObjHeader.write(cb);
//write Flags
byte bFlag;
bFlag = (bRFlag) ? BBIT_SET : BBIT_RESET;
cb.writeInt(bFlag);
//write SrpId
cb.writeInt(srpId);
// Add optional TLV
if (!packOptionalTlv(cb)) {
throw new PcepParseException("Failed to write srp tlv to channel buffer.");
}
//now write SRP Object Length
cb.setShort(objLenIndex, (short) (cb.writerIndex() - objStartIndex));
return cb.writerIndex();
}
/**
* Parse Optional TLvs from the channel buffer.
*
* @param cb of type channel buffer
* @return list of optional tlvs
* @throws PcepParseException when unsupported tlv is received in srp object
*/
public static LinkedList<PcepValueType> parseOptionalTlv(ChannelBuffer cb) throws PcepParseException {
LinkedList<PcepValueType> llOutOptionalTlv = new LinkedList<>();
while (MINIMUM_COMMON_HEADER_LENGTH <= cb.readableBytes()) {
PcepValueType tlv;
short hType = cb.readShort();
short hLength = cb.readShort();
switch (hType) {
case SymbolicPathNameTlv.TYPE:
if (cb.readableBytes() < hLength) {
throw new PcepParseException("Length is not valid in SymbolicPathNameTlv");
}
tlv = SymbolicPathNameTlv.read(cb, hLength);
break;
case PathSetupTypeTlv.TYPE:
if (cb.readableBytes() != PathSetupTypeTlv.LENGTH) {
throw new PcepParseException("Length is not valid in PathSetupTypeTlv");
}
tlv = PathSetupTypeTlv.of(cb.readInt());
break;
default:
throw new PcepParseException("Unsupported TLV received in SRP Object.");
}
// Check for the padding
int pad = hLength % 4;
if (0 < pad) {
pad = 4 - pad;
if (pad <= cb.readableBytes()) {
cb.skipBytes(pad);
}
}
llOutOptionalTlv.add(tlv);
}
return llOutOptionalTlv;
}
/**
* Writes optional tlvs to channel buffer.
*
* @param cb of type channel buffer
* @return true if writing optional tlv to channel buffer is success.
*/
protected boolean packOptionalTlv(ChannelBuffer cb) {
ListIterator<PcepValueType> listIterator = llOptionalTlv.listIterator();
while (listIterator.hasNext()) {
PcepValueType tlv = listIterator.next();
if (tlv == null) {
log.debug("tlv is null from OptionalTlv list");
continue;
}
tlv.write(cb);
// need to take care of padding
int pad = tlv.getLength() % 4;
if (0 != pad) {
pad = 4 - pad;
for (int i = 0; i < pad; ++i) {
cb.writeByte((byte) 0);
}
}
}
return true;
}
/**
* Builder class for PCEP srp Object.
*/
public static class Builder implements PcepSrpObject.Builder {
private boolean bIsHeaderSet = false;
private boolean bIsSrpIdset = false;
private boolean bIsRFlagSet = false;
private PcepObjectHeader srpObjHeader;
private int srpId;
private boolean bRFlag;
LinkedList<PcepValueType> llOptionalTlv = new LinkedList<>();
private boolean bIsPFlagSet = false;
private boolean bPFlag;
private boolean bIsIFlagSet = false;
private boolean bIFlag;
@Override
public PcepSrpObject build() throws PcepParseException {
PcepObjectHeader srpObjHeader = this.bIsHeaderSet ? this.srpObjHeader : DEFAULT_SRP_OBJECT_HEADER;
boolean bRFlag = this.bIsRFlagSet ? this.bRFlag : DEFAULT_RFLAG;
if (!this.bIsSrpIdset) {
throw new PcepParseException("SrpID not set while building SRP Object.");
}
if (bIsPFlagSet) {
srpObjHeader.setPFlag(bPFlag);
}
if (bIsIFlagSet) {
srpObjHeader.setIFlag(bIFlag);
}
return new PcepSrpObjectVer1(srpObjHeader, bRFlag, this.srpId, this.llOptionalTlv);
}
@Override
public PcepObjectHeader getSrpObjHeader() {
return this.srpObjHeader;
}
@Override
public Builder setSrpObjHeader(PcepObjectHeader obj) {
this.srpObjHeader = obj;
this.bIsHeaderSet = true;
return this;
}
@Override
public int getSrpID() {
return this.srpId;
}
@Override
public Builder setSrpID(int srpID) {
this.srpId = srpID;
this.bIsSrpIdset = true;
return this;
}
@Override
public boolean getRFlag() {
return this.bRFlag;
}
@Override
public Builder setRFlag(boolean bRFlag) {
this.bRFlag = bRFlag;
this.bIsRFlagSet = true;
return this;
}
@Override
public Builder setOptionalTlv(LinkedList<PcepValueType> llOptionalTlv) {
this.llOptionalTlv = llOptionalTlv;
return this;
}
@Override
public LinkedList<PcepValueType> getOptionalTlv() {
return this.llOptionalTlv;
}
@Override
public Builder setPFlag(boolean value) {
this.bPFlag = value;
this.bIsPFlagSet = true;
return this;
}
@Override
public Builder setIFlag(boolean value) {
this.bIFlag = value;
this.bIsIFlagSet = true;
return this;
}
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("RFlag", bRFlag)
.add("SRPID", srpId)
.add("OptionalTlvList", llOptionalTlv)
.toString();
}
}