blob: 7bc4fcb3b2390394f56c6430a4a5b214b315d0fa [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.bgpio.protocol.linkstate;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Objects;
import org.jboss.netty.buffer.ChannelBuffer;
import org.onosproject.bgpio.exceptions.BgpParseException;
import org.onosproject.bgpio.types.AreaIDTlv;
import org.onosproject.bgpio.types.AutonomousSystemTlv;
import org.onosproject.bgpio.types.BgpErrorType;
import org.onosproject.bgpio.types.BgpLSIdentifierTlv;
import org.onosproject.bgpio.types.BgpValueType;
import org.onosproject.bgpio.types.IsIsNonPseudonode;
import org.onosproject.bgpio.types.IsIsPseudonode;
import org.onosproject.bgpio.types.OSPFNonPseudonode;
import org.onosproject.bgpio.types.OSPFPseudonode;
import org.onosproject.bgpio.util.UnSupportedAttribute;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.MoreObjects;
/**
* Provides Local and Remote NodeDescriptors which contains Node Descriptor Sub-TLVs.
*/
public class NodeDescriptors {
/*
*Reference :draft-ietf-idr-ls-distribution-11
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
// Node Descriptor Sub-TLVs (variable) //
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure : Local or Remote Node Descriptors TLV format
*/
private static final Logger log = LoggerFactory.getLogger(NodeDescriptors.class);
public static final short LOCAL_NODE_DES_TYPE = 256;
public static final short REMOTE_NODE_DES_TYPE = 257;
public static final short IGP_ROUTERID_TYPE = 515;
public static final short IS_IS_LEVEL_1_PROTOCOL_ID = 1;
public static final short IS_IS_LEVEL_2_PROTOCOL_ID = 2;
public static final short OSPF_V2_PROTOCOL_ID = 3;
public static final short OSPF_V3_PROTOCOL_ID = 6;
public static final int TYPE_AND_LEN = 4;
public static final int ISISNONPSEUDONODE_LEN = 6;
public static final int ISISPSEUDONODE_LEN = 7;
public static final int OSPFNONPSEUDONODE_LEN = 4;
public static final int OSPFPSEUDONODE_LEN = 8;
private List<BgpValueType> subTlvs;
private short deslength;
private short desType;
/**
* Resets parameters.
*/
public NodeDescriptors() {
this.subTlvs = null;
this.deslength = 0;
this.desType = 0;
}
/**
* Constructor to initialize parameters.
*
* @param subTlvs list of subTlvs
* @param deslength Descriptors length
* @param desType local node descriptor or remote node descriptor type
*/
public NodeDescriptors(List<BgpValueType> subTlvs, short deslength, short desType) {
this.subTlvs = subTlvs;
this.deslength = deslength;
this.desType = desType;
}
/**
* Returns list of subTlvs.
*
* @return subTlvs list of subTlvs
*/
public List<BgpValueType> getSubTlvs() {
return subTlvs;
}
@Override
public int hashCode() {
return Objects.hash(subTlvs.hashCode());
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof NodeDescriptors) {
int countObjSubTlv = 0;
int countOtherSubTlv = 0;
boolean isCommonSubTlv = true;
NodeDescriptors other = (NodeDescriptors) obj;
Iterator<BgpValueType> objListIterator = other.subTlvs.iterator();
countOtherSubTlv = other.subTlvs.size();
countObjSubTlv = subTlvs.size();
if (countObjSubTlv != countOtherSubTlv) {
return false;
} else {
while (objListIterator.hasNext() && isCommonSubTlv) {
BgpValueType subTlv = objListIterator.next();
if (subTlvs.contains(subTlv) && other.subTlvs.contains(subTlv)) {
isCommonSubTlv = Objects.equals(subTlvs.get(subTlvs.indexOf(subTlv)),
other.subTlvs.get(other.subTlvs.indexOf(subTlv)));
} else {
isCommonSubTlv = false;
}
}
return isCommonSubTlv;
}
}
return false;
}
/**
* Reads node descriptors Sub-TLVs.
*
* @param cb ChannelBuffer
* @param desLength node descriptor length
* @param desType local node descriptor or remote node descriptor type
* @param protocolId protocol ID
* @return object of NodeDescriptors
* @throws BgpParseException while parsing node descriptors
*/
public static NodeDescriptors read(ChannelBuffer cb, short desLength, short desType, byte protocolId)
throws BgpParseException {
log.debug("Read NodeDescriptor");
List<BgpValueType> subTlvs = new LinkedList<>();
BgpValueType tlv = null;
while (cb.readableBytes() > 0) {
ChannelBuffer tempBuf = cb.copy();
short type = cb.readShort();
short length = cb.readShort();
if (cb.readableBytes() < length) {
throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.OPTIONAL_ATTRIBUTE_ERROR,
tempBuf.readBytes(cb.readableBytes() + TYPE_AND_LEN));
}
ChannelBuffer tempCb = cb.readBytes(length);
switch (type) {
case AutonomousSystemTlv.TYPE:
tlv = AutonomousSystemTlv.read(tempCb);
break;
case BgpLSIdentifierTlv.TYPE:
tlv = BgpLSIdentifierTlv.read(tempCb);
break;
case AreaIDTlv.TYPE:
tlv = AreaIDTlv.read(tempCb);
break;
case IGP_ROUTERID_TYPE:
if (protocolId == IS_IS_LEVEL_1_PROTOCOL_ID || protocolId == IS_IS_LEVEL_2_PROTOCOL_ID) {
boolean isNonPseudoNode = true;
if ((length == ISISPSEUDONODE_LEN) && (tempCb.getByte(ISISPSEUDONODE_LEN - 1) != 0)) {
isNonPseudoNode = false;
}
if (isNonPseudoNode) {
tlv = IsIsNonPseudonode.read(tempCb);
} else {
tlv = IsIsPseudonode.read(tempCb);
}
} else if (protocolId == OSPF_V2_PROTOCOL_ID || protocolId == OSPF_V3_PROTOCOL_ID) {
if (length == OSPFNONPSEUDONODE_LEN) {
tlv = OSPFNonPseudonode.read(tempCb);
} else if (length == OSPFPSEUDONODE_LEN) {
tlv = OSPFPseudonode.read(tempCb);
}
}
break;
default:
UnSupportedAttribute.skipBytes(tempCb, length);
}
subTlvs.add(tlv);
}
return new NodeDescriptors(subTlvs, desLength, desType);
}
/**
* Returns node descriptors length.
*
* @return node descriptors length
*/
public short getLength() {
return this.deslength;
}
/**
* Returns node descriptors type.
*
* @return node descriptors type
*/
public short getType() {
return this.desType;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("desType", desType)
.add("deslength", deslength)
.add("subTlvs", subTlvs)
.toString();
}
/**
* Compares this and o object.
*
* @param o object to be compared with this object
* @return which object is greater
*/
public int compareTo(Object o) {
if (this.equals(o)) {
return 0;
}
ListIterator<BgpValueType> listIterator = subTlvs.listIterator();
int countOtherSubTlv = ((NodeDescriptors) o).subTlvs.size();
int countObjSubTlv = subTlvs.size();
boolean tlvFound = false;
if (countOtherSubTlv != countObjSubTlv) {
if (countOtherSubTlv > countObjSubTlv) {
return 1;
} else {
return -1;
}
} else {
while (listIterator.hasNext()) {
BgpValueType tlv1 = listIterator.next();
log.debug("NodeDescriptor compare subtlv's");
for (BgpValueType tlv : ((NodeDescriptors) o).subTlvs) {
if (tlv.getType() == tlv1.getType()) {
int result = subTlvs.get(subTlvs.indexOf(tlv1)).compareTo(
((NodeDescriptors) o).subTlvs.get(((NodeDescriptors) o).subTlvs.indexOf(tlv)));
if (result != 0) {
return result;
}
tlvFound = true;
break;
}
}
if (!tlvFound) {
return 1;
}
}
}
return 0;
}
}