blob: b42d135a9b29efbce5aec4af41cefd91cb5a229d [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.types;
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.PcepVersion;
import com.google.common.base.MoreObjects;
/**
* Provides Pcep Rsvp User Error Spec.
*/
public class PcepRsvpUserErrorSpec implements PcepRsvpErrorSpec {
/*
RSVP error spec object header.
0 1 2 3
+-------------+-------------+-------------+-------------+
| Length (bytes) | Class-Num | C-Type |
+-------------+-------------+-------------+-------------+
| |
// (Object contents) //
| |
+-------------+-------------+-------------+-------------+
Ref : USER_ERROR_SPEC @ RFC5284.
USER_ERROR_SPEC object: Class = 194, C-Type = 1
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
+---------------+---------------+---------------+---------------+
| Enterprise Number |
+---------------+---------------+---------------+---------------+
| Sub Org | Err Desc Len | User Error Value |
+---------------+---------------+---------------+---------------+
| |
~ Error Description ~
| |
+---------------+---------------+---------------+---------------+
| |
~ User-Defined Subobjects ~
| |
+---------------+---------------+---------------+---------------+
*/
public static final byte CLASS_NUM = (byte) 0xc2;
public static final byte CLASS_TYPE = 0x01;
private PcepRsvpSpecObjHeader objHeader;
private int enterpriseNum;
private byte subOrg;
private byte errDescLen;
private short userErrorValue;
private byte[] errDesc;
private LinkedList<PcepValueType> llRsvpUserSpecSubObj;
/**
* Default constructor.
*
* @param objHeader pcep rsvp spec object header
* @param enterpriseNum enterprise number
* @param subOrg organization identifier value
* @param errDescLen error description length
* @param userErrorValue user error value
* @param errDesc error description
* @param llRsvpUserSpecSubObj list of subobjects
*/
public PcepRsvpUserErrorSpec(PcepRsvpSpecObjHeader objHeader, int enterpriseNum, byte subOrg, byte errDescLen,
short userErrorValue, byte[] errDesc, LinkedList<PcepValueType> llRsvpUserSpecSubObj) {
this.objHeader = objHeader;
this.enterpriseNum = enterpriseNum;
this.subOrg = subOrg;
this.errDescLen = errDescLen;
this.userErrorValue = userErrorValue;
this.errDesc = errDesc;
this.llRsvpUserSpecSubObj = llRsvpUserSpecSubObj;
}
@Override
public int write(ChannelBuffer cb) {
int objLenIndex = objHeader.write(cb);
cb.writeInt(enterpriseNum);
cb.writeByte(subOrg);
cb.writeByte(errDescLen);
cb.writeShort(userErrorValue);
cb.writeBytes(errDesc);
if (llRsvpUserSpecSubObj != null) {
ListIterator<PcepValueType> listIterator = llRsvpUserSpecSubObj.listIterator();
while (listIterator.hasNext()) {
PcepValueType tlv = listIterator.next();
if (tlv == null) {
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);
}
}
}
}
short objLen = (short) (cb.writerIndex() - objLenIndex);
cb.setShort(objLenIndex, objLen);
return objLen;
}
/**
* Reads the channel buffer and returns object of PcepRsvpErrorSpec.
*
* @param cb of type channel buffer
* @return object of PcepRsvpErrorSpec
* @throws PcepParseException when expected object is not received
*/
public static PcepRsvpErrorSpec read(ChannelBuffer cb) throws PcepParseException {
PcepRsvpSpecObjHeader objHeader;
int enterpriseNum;
byte subOrg;
byte errDescLen;
short userErrorValue;
byte[] errDesc;
LinkedList<PcepValueType> llRsvpUserSpecSubObj = null;
objHeader = PcepRsvpSpecObjHeader.read(cb);
if (objHeader.getObjClassNum() != CLASS_NUM || objHeader.getObjClassType() != CLASS_TYPE) {
throw new PcepParseException("Expected PcepRsvpUserErrorSpec object.");
}
enterpriseNum = cb.readInt();
subOrg = cb.readByte();
errDescLen = cb.readByte();
userErrorValue = cb.readShort();
errDesc = new byte[errDescLen];
cb.readBytes(errDesc, 0, errDescLen);
llRsvpUserSpecSubObj = parseErrSpecSubObj(cb);
return new PcepRsvpUserErrorSpec(objHeader, enterpriseNum, subOrg, errDescLen, userErrorValue, errDesc,
llRsvpUserSpecSubObj);
}
private static LinkedList<PcepValueType> parseErrSpecSubObj(ChannelBuffer cb) throws PcepParseException {
LinkedList<PcepValueType> llRsvpUserSpecSubObj = new LinkedList<>();
while (0 < cb.readableBytes()) {
PcepValueType tlv = null;
short hType = cb.readShort();
int iValue = 0;
//short hLength = cb.readShort();
switch (hType) {
case AutonomousSystemSubTlv.TYPE:
iValue = cb.readInt();
tlv = new AutonomousSystemSubTlv(iValue);
break;
default:
throw new PcepParseException("Unsupported Sub TLV type :" + hType);
}
llRsvpUserSpecSubObj.add(tlv);
}
return llRsvpUserSpecSubObj;
}
@Override
public PcepVersion getVersion() {
return PcepVersion.PCEP_1;
}
@Override
public short getType() {
return StatefulRsvpErrorSpecTlv.TYPE;
}
@Override
public short getLength() {
return objHeader.getObjLen();
}
@Override
public byte getClassNum() {
return CLASS_NUM;
}
@Override
public byte getClassType() {
return CLASS_TYPE;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("enterpriseNumber", enterpriseNum)
.add("subOrganization", subOrg)
.add("errDescLength", errDescLen)
.add("userErrorValue", userErrorValue)
.add("errDesc", errDesc)
.add("RsvpUserSpecSubObject", llRsvpUserSpecSubObj)
.toString();
}
}