blob: 971f9a13ccf4b46132f735472d783d7c67a56d5a [file] [log] [blame]
/*
* Copyright 2016-present 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.isis.io.isispacket.pdu;
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import com.google.common.primitives.Bytes;
import org.jboss.netty.buffer.ChannelBuffer;
import org.onosproject.isis.io.isispacket.IsisHeader;
import org.onosproject.isis.io.isispacket.tlv.IsisTlv;
import org.onosproject.isis.io.isispacket.tlv.TlvFinder;
import org.onosproject.isis.io.isispacket.tlv.TlvHeader;
import org.onosproject.isis.io.isispacket.tlv.TlvType;
import org.onosproject.isis.io.isispacket.tlv.TlvsToBytes;
import org.onosproject.isis.io.util.IsisUtil;
import java.util.ArrayList;
import java.util.List;
/**
* Representation of an ISIS Link State packet.
* Each Link State packet carries a collection of TLVs
* Several TLVs may be included in a single packet.
*/
public class LsPdu extends IsisHeader {
/*
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Intra-domain Routing Protocol Discriminator |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Length Indicator |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Version/Protocol ID Extension |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ID Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| R | R | R | PDU Type |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Version |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Reserved |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Maximum area address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| PDU Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Remaining Lifetime |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| LSP ID |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| PDU Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| P | ATT | LSPDBOL | IS Type |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Variable Lengths Fields |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
LS PDU Format
REFERENCE : ISO/IECĀ 10589
*/
private int pduLength;
private int remainingLifeTime;
private String lspId;
private int sequenceNumber;
private int checkSum;
private boolean partitionRepair;
private AttachedToOtherAreas attachedToOtherAreas;
private boolean lspDbol;
private byte typeBlock;
private byte intermediateSystemType;
private List<IsisTlv> variableLengths = new ArrayList<>();
/**
* Creates an instance of Link State packet.
*
* @param isisHeader isis header details
*/
public LsPdu(IsisHeader isisHeader) {
populateHeader(isisHeader);
}
/**
* Returns the ISIS tlvs.
*
* @return tlvs
*/
public List<IsisTlv> tlvs() {
return this.variableLengths;
}
/**
* Adds the isis tlv to the list for the link state PDU.
*
* @param isisTlv isis tlv
*/
public void addTlv(IsisTlv isisTlv) {
variableLengths.add(isisTlv);
}
/**
* Returns the remaining time of the link state pdu.
* Number of seconds before LSP considered expired
*
* @return remainingTime remaining time
*/
public int remainingLifeTime() {
return remainingLifeTime;
}
/**
* Sets the remaining time for the link state pdu.
*
* @param remainingLifeTime remaining time
*/
public void setRemainingLifeTime(int remainingLifeTime) {
this.remainingLifeTime = remainingLifeTime;
}
/**
* Returns the link state database overload.
*
* @return lspdbol link state database overload
*/
public boolean lspDbol() {
return lspDbol;
}
/**
* Sets the link state database overload for this pdu.
*
* @param lspDbol link state database overload
*/
public void setLspDbol(boolean lspDbol) {
this.lspDbol = lspDbol;
}
/**
* Returns the type block.
*
* @return type block
*/
public byte typeBlock() {
return typeBlock;
}
/**
* Sets the type block.
*
* @param typeBlock type block
*/
public void setTypeBlock(byte typeBlock) {
this.typeBlock = typeBlock;
}
/**
* Returns the sequence number of LSP.
*
* @return sequenceNumber sequence number
*/
public int sequenceNumber() {
return sequenceNumber;
}
/**
* Sets the sequence nubmer for LSP.
*
* @param sequenceNumber sequence number
*/
public void setSequenceNumber(int sequenceNumber) {
this.sequenceNumber = sequenceNumber;
}
/**
* Returns the checksum of LSP from Source ID to end.
*
* @return checkSum check sum
*/
public int checkSum() {
return checkSum;
}
/**
* Sets the checksum for LSP from Source ID to end.
*
* @param checkSum check sum
*/
public void setCheckSum(int checkSum) {
this.checkSum = checkSum;
}
/**
* Returns the partition repair value of the intermediate system.
*
* @return partitionRepair partition repair
*/
public boolean partitionRepair() {
return partitionRepair;
}
/**
* Sets partition repair value for the intermediate system.
*
* @param partitionRepair partition repair
*/
public void setPartitionRepair(boolean partitionRepair) {
this.partitionRepair = partitionRepair;
}
/**
* Returns the value of intermediate system attached field.
* return values based on type Default Metric, Delay Metric, Expense Metric, Error Metric
*
* @return attachedToOtherAreas attached to other areas
*/
public AttachedToOtherAreas attachedToOtherAreas() {
return attachedToOtherAreas;
}
/**
* Sets the value for intermediate system attached field.
* it will pass values based on type Default Metric, Delay Metric, Expense Metric, Error Metric
*
* @param attachedToOtherAreas attached to other areas
*/
public void setAttachedToOtherAreas(AttachedToOtherAreas attachedToOtherAreas) {
this.attachedToOtherAreas = attachedToOtherAreas;
}
/**
* Returns the intermediate system type.
* type will be level 1 or level 2
*
* @return intermediateSystemType intermediate system type
*/
public byte intermediateSystemType() {
return intermediateSystemType;
}
/**
* Sets the value for intermediate system.
* type will be level 1 or level 2
*
* @param intermediateSystemType intermediate system type
*/
public void setIntermediateSystemType(byte intermediateSystemType) {
this.intermediateSystemType = intermediateSystemType;
}
/**
* Returns the link state ID of link state packet.
* System ID of the source of link state PDU
*
* @return lspId link state packet ID
*/
public String lspId() {
return lspId;
}
/**
* Sets the link state ID for link state packet.
* System ID of the source of link state PDU
*
* @param lspId link state packet ID
*/
public void setLspId(String lspId) {
this.lspId = lspId;
}
/**
* Returns the packet data unit length of link state packet.
* Entire length of this PDU, in octets
*
* @return pduLength packet data unit length
*/
public int pduLength() {
return pduLength;
}
/**
* Sets the packet data unit length for link state packet.
* Entire Length of this PDU, in octets
*
* @param pduLength packet data length
*/
public void setPduLength(int pduLength) {
this.pduLength = pduLength;
}
@Override
public void readFrom(ChannelBuffer channelBuffer) {
this.setPduLength(channelBuffer.readUnsignedShort());
this.setRemainingLifeTime(channelBuffer.readUnsignedShort());
//lsp id + 2 value
byte[] tempByteArray = new byte[IsisUtil.ID_PLUS_TWO_BYTE];
channelBuffer.readBytes(tempByteArray, 0, IsisUtil.ID_PLUS_TWO_BYTE);
this.setLspId(IsisUtil.systemIdPlus(tempByteArray));
//sequence number 4
this.setSequenceNumber(channelBuffer.readInt());
this.setCheckSum(channelBuffer.readUnsignedShort());
int typeTemp = channelBuffer.readUnsignedByte();
byte isTypeByte = (byte) typeTemp;
String tempValue = String.format("%8s", Integer.toBinaryString(isTypeByte & 0xFF)).replace(' ', '0');
int pBit = Integer.parseInt(new Character(tempValue.charAt(0)).toString());
if (pBit == 1) {
this.setPartitionRepair(true);
} else {
this.setPartitionRepair(false);
}
int attValue = Integer.parseInt(tempValue.substring(1, 5), 2);
switch (AttachedToOtherAreas.get(attValue)) {
case DEFAULTMETRIC:
this.setAttachedToOtherAreas(AttachedToOtherAreas.DEFAULTMETRIC);
break;
case DELAYMETRIC:
this.setAttachedToOtherAreas(AttachedToOtherAreas.DELAYMETRIC);
break;
case EXPENSEMETRIC:
this.setAttachedToOtherAreas(AttachedToOtherAreas.EXPENSEMETRIC);
break;
case ERRORMETRIC:
this.setAttachedToOtherAreas(AttachedToOtherAreas.ERRORMETRIC);
break;
case NONE:
this.setAttachedToOtherAreas(AttachedToOtherAreas.NONE);
break;
default:
break;
}
int lspdbol = Integer.parseInt(new Character(tempValue.charAt(5)).toString());
if (lspdbol == 1) {
this.setLspDbol(true);
} else {
this.setLspDbol(false);
}
int isType = Integer.parseInt(tempValue.substring(6, 8), 2);
byte isTypeByteValue = (byte) isType;
this.setIntermediateSystemType(isTypeByteValue);
//tlv here
while (channelBuffer.readableBytes() > 0) {
TlvHeader tlvHeader = new TlvHeader();
tlvHeader.setTlvType(channelBuffer.readUnsignedByte());
tlvHeader.setTlvLength(channelBuffer.readUnsignedByte());
TlvType tlvValue = TlvType.get(tlvHeader.tlvType());
if (tlvValue != null) {
IsisTlv tlv = TlvFinder.findTlv(tlvHeader, channelBuffer.readBytes(tlvHeader.tlvLength()));
if (tlv != null) {
this.variableLengths.add(tlv);
}
} else {
channelBuffer.readBytes(tlvHeader.tlvLength());
}
}
}
@Override
public byte[] asBytes() {
byte[] lspMessage = null;
byte[] helloHeader = l1l2IsisPduHeader();
byte[] lspBody = l1l2LsPduBody();
lspMessage = Bytes.concat(helloHeader, lspBody);
return lspMessage;
}
/**
* Builds ISIS PDU header from ISIS message.
*
* @return headerList ISIS PDU header
*/
public byte[] l1l2IsisPduHeader() {
List<Byte> headerList = new ArrayList<>();
headerList.add(this.irpDiscriminator());
headerList.add((byte) IsisUtil.getPduHeaderLength(this.pduType()));
headerList.add(this.version());
headerList.add(this.idLength());
headerList.add((byte) this.pduType());
headerList.add(this.version2());
headerList.add(this.reserved());
headerList.add(this.maximumAreaAddresses());
return Bytes.toArray(headerList);
}
/**
* Builds link state PDU body from ISIS message.
*
* @return bodyList link state PDU body
*/
public byte[] l1l2LsPduBody() {
List<Byte> bodyList = new ArrayList<>();
bodyList.addAll(Bytes.asList(IsisUtil.convertToTwoBytes(this.pduLength())));
bodyList.addAll(Bytes.asList(IsisUtil.convertToTwoBytes(this.remainingLifeTime())));
bodyList.addAll(IsisUtil.sourceAndLanIdToBytes(this.lspId()));
bodyList.addAll(Bytes.asList(IsisUtil.convertToFourBytes(this.sequenceNumber())));
bodyList.addAll(Bytes.asList(IsisUtil.convertToTwoBytes(this.checkSum())));
String temString = "";
if (this.partitionRepair()) {
temString = "1" + temString;
} else {
temString = "0" + temString;
}
switch (this.attachedToOtherAreas()) {
case ERRORMETRIC:
temString = temString + "1000";
break;
case EXPENSEMETRIC:
temString = temString + "0100";
break;
case DELAYMETRIC:
temString = temString + "0010";
break;
case DEFAULTMETRIC:
temString = temString + "0001";
break;
case NONE:
temString = temString + "0000";
break;
default:
break;
}
if (this.lspDbol()) {
temString = temString + "1";
} else {
temString = temString + "0";
}
String isType = Integer.toBinaryString(this.intermediateSystemType());
if (isType.length() % 2 != 0) {
isType = "0" + isType;
}
temString = temString + isType;
bodyList.add((byte) Integer.parseInt(temString, 2));
for (IsisTlv isisTlv : variableLengths) {
bodyList.addAll(TlvsToBytes.tlvToBytes(isisTlv));
}
return Bytes.toArray(bodyList);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.omitNullValues()
.add("pduLength", pduLength)
.add("remainingLifeTime", remainingLifeTime)
.add("lspId", lspId)
.add("sequenceNumber", sequenceNumber)
.add("checkSum", checkSum)
.add("partitionRepair", partitionRepair)
.add("lspDbol", lspDbol)
.add("typeBlock", typeBlock)
.add("intermediateSystemType", intermediateSystemType)
.toString();
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
LsPdu that = (LsPdu) o;
return Objects.equal(pduLength, that.pduLength) &&
Objects.equal(remainingLifeTime, that.remainingLifeTime) &&
Objects.equal(lspId, that.lspId) &&
Objects.equal(sequenceNumber, that.sequenceNumber) &&
Objects.equal(checkSum, that.checkSum) &&
Objects.equal(partitionRepair, that.partitionRepair) &&
Objects.equal(lspDbol, that.lspDbol) &&
Objects.equal(typeBlock, that.typeBlock) &&
Objects.equal(intermediateSystemType, that.intermediateSystemType);
}
@Override
public int hashCode() {
return Objects.hashCode(pduLength, remainingLifeTime, lspId, sequenceNumber,
checkSum, partitionRepair, lspDbol, typeBlock, intermediateSystemType);
}
}