diff options
Diffstat (limited to 'framework/src/onos/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/protocol/ver1/PcepLspObjectVer1.java')
-rw-r--r-- | framework/src/onos/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/protocol/ver1/PcepLspObjectVer1.java | 575 |
1 files changed, 575 insertions, 0 deletions
diff --git a/framework/src/onos/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/protocol/ver1/PcepLspObjectVer1.java b/framework/src/onos/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/protocol/ver1/PcepLspObjectVer1.java new file mode 100644 index 00000000..2b319c12 --- /dev/null +++ b/framework/src/onos/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/protocol/ver1/PcepLspObjectVer1.java @@ -0,0 +1,575 @@ +/* + * 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.types.PcepErrorDetailInfo; +import org.onosproject.pcepio.types.PcepObjectHeader; +import org.onosproject.pcepio.types.PcepValueType; +import org.onosproject.pcepio.types.StatefulIPv4LspIdentidiersTlv; +import org.onosproject.pcepio.types.StatefulLspDbVerTlv; +import org.onosproject.pcepio.types.StatefulLspErrorCodeTlv; +import org.onosproject.pcepio.types.StatefulRsvpErrorSpecTlv; +import org.onosproject.pcepio.types.SymbolicPathNameTlv; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * Provides PCEP lsp object. + */ +public class PcepLspObjectVer1 implements PcepLspObject { + + /* + message format. + Reference : draft-ietf-pce-stateful-pce-11, section 7.3. + 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) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | PLSP-ID | Flag | O|A|R|S|D| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // TLVs // + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + The LSP Object format + */ + protected static final Logger log = LoggerFactory.getLogger(PcepLspObjectVer1.class); + + public static final byte LSP_OBJ_TYPE = 1; + public static final byte LSP_OBJ_CLASS = 32; + public static final byte LSP_OBJECT_VERSION = 1; + + // LSP_OBJ_MINIMUM_LENGTH = CommonHeaderLen(4)+ LspObjectHeaderLen(4)+TlvAssumedMinLength(8) + public static final short LSP_OBJ_MINIMUM_LENGTH = 16; + + public static final int DEFAULT_PLSPID = 0; + public static final byte DEFAULT_OFLAG = 1; + public static final boolean DEFAULT_AFLAG = false; + public static final boolean DEFAULT_RFLAG = false; + public static final boolean DEFAULT_SFLAG = false; + public static final boolean DEFAULT_DFLAG = false; + public static final int OBJECT_HEADER_LENGTH = 4; + public static final int PLSPID_SHIFT_VALUE = 12; + public static final int OFLAG_SHIFT_VALUE = 4; + public static final int AFLAG_SHIFT_VALUE = 3; + public static final int RFLAG_SHIFT_VALUE = 2; + public static final int SFLAG_SHIFT_VALUE = 1; + public static final int PLSPID_TEMP_SHIFT_VALUE = 0xFFFFF000; + public static final int OFLAG_TEMP_SHIFT_VALUE = 0x70; + public static final int AFLAG_TEMP_SHIFT_VALUE = 0x08; + public static final int RFLAG_TEMP_SHIFT_VALUE = 0x04; + public static final int SFLAG_TEMP_SHIFT_VALUE = 0x02; + public static final int DFLAG_TEMP_SHIFT_VALUE = 0x01; + public static final int BIT_SET = 1; + public static final int BIT_RESET = 0; + public static final int MINIMUM_COMMON_HEADER_LENGTH = 4; + + static final PcepObjectHeader DEFAULT_LSP_OBJECT_HEADER = new PcepObjectHeader(LSP_OBJ_CLASS, LSP_OBJ_TYPE, + PcepObjectHeader.REQ_OBJ_OPTIONAL_PROCESS, PcepObjectHeader.RSP_OBJ_PROCESSED, LSP_OBJ_MINIMUM_LENGTH); + + private PcepObjectHeader lspObjHeader; + private int iPlspId; + // 3-bits + private byte yOFlag; + private boolean bAFlag; + private boolean bRFlag; + private boolean bSFlag; + private boolean bDFlag; + + // Optional TLV + private LinkedList<PcepValueType> llOptionalTlv; + + /** + * Constructor to initialize all the member variables. + * + * @param lspObjHeader lsp object header + * @param iPlspId plsp id + * @param yOFlag O flag + * @param bAFlag A flag + * @param bRFlag R flag + * @param bSFlag S flag + * @param bDFlag D flag + * @param llOptionalTlv list of optional tlv + */ + public PcepLspObjectVer1(PcepObjectHeader lspObjHeader, int iPlspId, byte yOFlag, boolean bAFlag, boolean bRFlag, + boolean bSFlag, boolean bDFlag, LinkedList<PcepValueType> llOptionalTlv) { + + this.lspObjHeader = lspObjHeader; + this.iPlspId = iPlspId; + this.yOFlag = yOFlag; + this.bAFlag = bAFlag; + this.bRFlag = bRFlag; + this.bSFlag = bSFlag; + this.bDFlag = bDFlag; + this.llOptionalTlv = llOptionalTlv; + } + + /** + * Sets lsp Object Header. + * + * @param obj lsp object header + */ + public void setLspObjHeader(PcepObjectHeader obj) { + this.lspObjHeader = obj; + } + + @Override + public void setPlspId(int iPlspId) { + this.iPlspId = iPlspId; + } + + @Override + public void setOFlag(byte yOFlag) { + this.yOFlag = yOFlag; + } + + @Override + public void setAFlag(boolean bAFlag) { + this.bAFlag = bAFlag; + } + + @Override + public void setRFlag(boolean bRFlag) { + this.bRFlag = bRFlag; + } + + @Override + public void setSFlag(boolean bSFlag) { + this.bSFlag = bSFlag; + } + + @Override + public void setDFlag(boolean bDFlag) { + this.bDFlag = bDFlag; + } + + /** + * Returns lsp object header. + * + * @return lspObjHeader + */ + public PcepObjectHeader getLspObjHeader() { + return this.lspObjHeader; + } + + @Override + public int getPlspId() { + return this.iPlspId; + } + + @Override + public byte getOFlag() { + return this.yOFlag; + } + + @Override + public boolean getAFlag() { + return this.bAFlag; + } + + @Override + public boolean getRFlag() { + return this.bRFlag; + } + + @Override + public boolean getSFlag() { + return this.bSFlag; + } + + @Override + public boolean getDFlag() { + return this.bDFlag; + } + + @Override + public LinkedList<PcepValueType> getOptionalTlv() { + return this.llOptionalTlv; + } + + @Override + public void setOptionalTlv(LinkedList<PcepValueType> llOptionalTlv) { + this.llOptionalTlv = llOptionalTlv; + } + + /** + * Parse channel buffer and returns object of PcepLspObject. + * + * @param cb of type channel buffer + * @return object of PcepLspObject + * @throws PcepParseException when lsp object is not present in channel buffer + */ + public static PcepLspObject read(ChannelBuffer cb) throws PcepParseException { + + PcepObjectHeader lspObjHeader; + int iPlspId; + // 3-bits + byte yOFlag; + boolean bAFlag; + boolean bRFlag; + boolean bSFlag; + boolean bDFlag; + + // Optional TLV + LinkedList<PcepValueType> llOptionalTlv = new LinkedList<>(); + + lspObjHeader = PcepObjectHeader.read(cb); + + if (lspObjHeader.getObjClass() != PcepLspObjectVer1.LSP_OBJ_CLASS) { + throw new PcepParseException(PcepErrorDetailInfo.ERROR_TYPE_6, PcepErrorDetailInfo.ERROR_VALUE_8); + } + //take only LspObject buffer. + ChannelBuffer tempCb = cb.readBytes(lspObjHeader.getObjLen() - OBJECT_HEADER_LENGTH); + + Integer iTemp = tempCb.readInt(); + iPlspId = (iTemp & PLSPID_TEMP_SHIFT_VALUE) >> PLSPID_SHIFT_VALUE; + Integer iX = (iTemp & OFLAG_TEMP_SHIFT_VALUE) >> OFLAG_SHIFT_VALUE; + yOFlag = iX.byteValue(); + iX = (iTemp & AFLAG_TEMP_SHIFT_VALUE) >> AFLAG_SHIFT_VALUE; + bAFlag = iX > 0; + iX = (iTemp & RFLAG_TEMP_SHIFT_VALUE) >> RFLAG_SHIFT_VALUE; + bRFlag = iX > 0; + iX = (iTemp & SFLAG_TEMP_SHIFT_VALUE) >> SFLAG_SHIFT_VALUE; + bSFlag = iX > 0; + iX = iTemp & DFLAG_TEMP_SHIFT_VALUE; + bDFlag = iX > 0; + + // parse optional TLV + llOptionalTlv = parseOptionalTlv(tempCb); + + return new PcepLspObjectVer1(lspObjHeader, iPlspId, yOFlag, bAFlag, bRFlag, bSFlag, bDFlag, llOptionalTlv); + } + + @Override + public int write(ChannelBuffer cb) throws PcepParseException { + + //write Object header + int objStartIndex = cb.writerIndex(); + + int objLenIndex = lspObjHeader.write(cb); + + if (objLenIndex <= 0) { + throw new PcepParseException("Failed to write lsp object header. Index " + objLenIndex); + } + + int iTemp = iPlspId << PLSPID_SHIFT_VALUE; + iTemp = iTemp | (yOFlag << OFLAG_SHIFT_VALUE); + byte bFlag; + iTemp = bAFlag ? (iTemp | AFLAG_TEMP_SHIFT_VALUE) : iTemp; + + bFlag = (bRFlag) ? (byte) BIT_SET : BIT_RESET; + iTemp = iTemp | (bFlag << RFLAG_SHIFT_VALUE); + bFlag = (bSFlag) ? (byte) BIT_SET : BIT_RESET; + iTemp = iTemp | (bFlag << SFLAG_SHIFT_VALUE); + bFlag = (bDFlag) ? (byte) BIT_SET : BIT_RESET; + iTemp = iTemp | bFlag; + cb.writeInt(iTemp); + + // Add optional TLV + packOptionalTlv(cb); + + //Update object length now + int length = cb.writerIndex() - objStartIndex; + //will be helpful during print(). + lspObjHeader.setObjLen((short) length); + // As per RFC the length of object should be + // multiples of 4 + + cb.setShort(objLenIndex, (short) length); + + return length; + } + + /** + * Returns Linked list of optional tlvs. + * + * @param cb of channel buffer. + * @return list of optional tlvs + * @throws PcepParseException when unsupported tlv is received + */ + protected static LinkedList<PcepValueType> parseOptionalTlv(ChannelBuffer cb) throws PcepParseException { + + LinkedList<PcepValueType> llOutOptionalTlv; + + llOutOptionalTlv = new LinkedList<>(); + + while (MINIMUM_COMMON_HEADER_LENGTH <= cb.readableBytes()) { + + PcepValueType tlv; + short hType = cb.readShort(); + short hLength = cb.readShort(); + int iValue = 0; + + switch (hType) { + + case StatefulIPv4LspIdentidiersTlv.TYPE: + tlv = StatefulIPv4LspIdentidiersTlv.read(cb); + break; + case StatefulLspErrorCodeTlv.TYPE: + iValue = cb.readInt(); + tlv = new StatefulLspErrorCodeTlv(iValue); + break; + case StatefulRsvpErrorSpecTlv.TYPE: + tlv = StatefulRsvpErrorSpecTlv.read(cb); + break; + case SymbolicPathNameTlv.TYPE: + tlv = SymbolicPathNameTlv.read(cb, hLength); + break; + case StatefulLspDbVerTlv.TYPE: + tlv = StatefulLspDbVerTlv.read(cb); + break; + default: + throw new PcepParseException("Received unsupported TLV type :" + hType); + } + // Check for the padding + int pad = hLength % 4; + if (0 < pad) { + pad = 4 - pad; + if (pad <= cb.readableBytes()) { + cb.skipBytes(pad); + } + } + + llOutOptionalTlv.add(tlv); + } + + if (0 < cb.readableBytes()) { + + throw new PcepParseException("Optional Tlv parsing error. Extra bytes received."); + } + return llOutOptionalTlv; + } + + /** + * returns writer index. + * + * @param cb of type channel buffer + * @return length of bytes written to channel buffer + */ + protected int packOptionalTlv(ChannelBuffer cb) { + + ListIterator<PcepValueType> listIterator = llOptionalTlv.listIterator(); + int startIndex = cb.writerIndex(); + + 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 cb.writerIndex() - startIndex; + } + + /** + * Builder class for PCEP lsp Object. + */ + public static class Builder implements PcepLspObject.Builder { + + private boolean bIsHeaderSet = false; + private boolean bIsPlspIdSet = false; + private boolean bIsOFlagSet = false; + private boolean bIsRFlagSet = false; + private boolean bIsAFlagSet = false; + private boolean bIsDFlagSet = false; + private boolean bIsSFlagSet = false; + + private PcepObjectHeader lspObjHeader; + private byte yOFlag; + private boolean bAFlag; + private boolean bDFlag; + private boolean bSFlag; + private boolean bRFlag; + LinkedList<PcepValueType> llOptionalTlv = null; + + private int plspId; + + private boolean bIsPFlagSet = false; + private boolean bPFlag; + + private boolean bIsIFlagSet = false; + private boolean bIFlag; + + @Override + public PcepLspObject build() { + PcepObjectHeader lspObjHeader = this.bIsHeaderSet ? this.lspObjHeader : DEFAULT_LSP_OBJECT_HEADER; + + int plspId = this.bIsPlspIdSet ? this.plspId : DEFAULT_PLSPID; + byte yOFlag = this.bIsOFlagSet ? this.yOFlag : DEFAULT_OFLAG; + boolean bAFlag = this.bIsAFlagSet ? this.bAFlag : DEFAULT_AFLAG; + boolean bRFlag = this.bIsRFlagSet ? this.bRFlag : DEFAULT_RFLAG; + boolean bSFlag = this.bIsSFlagSet ? this.bSFlag : DEFAULT_SFLAG; + boolean bDFlag = this.bIsDFlagSet ? this.bDFlag : DEFAULT_DFLAG; + + if (bIsPFlagSet) { + lspObjHeader.setPFlag(bPFlag); + } + + if (bIsIFlagSet) { + lspObjHeader.setIFlag(bIFlag); + } + + return new PcepLspObjectVer1(lspObjHeader, plspId, yOFlag, bAFlag, bRFlag, bSFlag, bDFlag, llOptionalTlv); + } + + @Override + public PcepObjectHeader getLspObjHeader() { + return this.lspObjHeader; + } + + @Override + public Builder setLspObjHeader(PcepObjectHeader obj) { + this.lspObjHeader = obj; + this.bIsHeaderSet = true; + return this; + } + + @Override + public int getPlspId() { + return this.plspId; + } + + @Override + public Builder setPlspId(int value) { + this.plspId = value; + this.bIsPlspIdSet = true; + return this; + } + + @Override + public byte getOFlag() { + return this.yOFlag; + } + + @Override + public Builder setOFlag(byte value) { + this.yOFlag = value; + this.bIsOFlagSet = true; + return this; + } + + @Override + public boolean getAFlag() { + return this.bAFlag; + } + + @Override + public Builder setAFlag(boolean value) { + this.bAFlag = value; + this.bIsAFlagSet = true; + return this; + } + + @Override + public boolean getRFlag() { + return this.bRFlag; + } + + @Override + public Builder setRFlag(boolean value) { + this.bRFlag = value; + this.bIsRFlagSet = true; + return this; + } + + @Override + public boolean getSFlag() { + return this.bSFlag; + } + + @Override + public Builder setSFlag(boolean value) { + this.bSFlag = value; + this.bIsSFlagSet = true; + return this; + } + + @Override + public boolean getDFlag() { + return this.bDFlag; + } + + @Override + public Builder setDFlag(boolean value) { + this.bDFlag = value; + this.bIsDFlagSet = 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("PlspIDValue", iPlspId) + .add("OFlag", yOFlag) + .add("AFlag", bAFlag) + .add("RFlag", bRFlag) + .add("SFlag", bSFlag) + .add("DFlag", bDFlag) + .add("OptionalTlvList", llOptionalTlv) + .toString(); + } +} |