| /* |
| * 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.BgpErrorType; |
| import org.onosproject.bgpio.types.BgpValueType; |
| import org.onosproject.bgpio.types.IPv4AddressTlv; |
| import org.onosproject.bgpio.types.IPv6AddressTlv; |
| import org.onosproject.bgpio.types.LinkLocalRemoteIdentifiersTlv; |
| import org.onosproject.bgpio.types.attr.BgpAttrNodeMultiTopologyId; |
| import org.onosproject.bgpio.util.Constants; |
| import org.onosproject.bgpio.util.UnSupportedAttribute; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| import com.google.common.base.MoreObjects; |
| import com.google.common.base.Preconditions; |
| |
| /** |
| * Implementation of local node descriptors, remote node descriptors and link descriptors. |
| */ |
| public class BgpLinkLSIdentifier implements Comparable<Object> { |
| private static final Logger log = LoggerFactory.getLogger(BgpLinkLSIdentifier.class); |
| public static final short IPV4_INTERFACE_ADDRESS_TYPE = 259; |
| public static final short IPV4_NEIGHBOR_ADDRESS_TYPE = 260; |
| public static final short IPV6_INTERFACE_ADDRESS_TYPE = 261; |
| public static final short IPV6_NEIGHBOR_ADDRESS_TYPE = 262; |
| |
| private NodeDescriptors localNodeDescriptors; |
| private NodeDescriptors remoteNodeDescriptors; |
| private List<BgpValueType> linkDescriptor; |
| |
| /** |
| * Initialize fields. |
| */ |
| public BgpLinkLSIdentifier() { |
| this.localNodeDescriptors = null; |
| this.remoteNodeDescriptors = null; |
| this.linkDescriptor = null; |
| } |
| |
| /** |
| * Constructors to initialize parameters. |
| * |
| * @param localNodeDescriptors local node descriptors |
| * @param remoteNodeDescriptors remote node descriptors |
| * @param linkDescriptor link descriptors |
| */ |
| public BgpLinkLSIdentifier(NodeDescriptors localNodeDescriptors, NodeDescriptors remoteNodeDescriptors, |
| LinkedList<BgpValueType> linkDescriptor) { |
| this.localNodeDescriptors = Preconditions.checkNotNull(localNodeDescriptors); |
| this.remoteNodeDescriptors = Preconditions.checkNotNull(remoteNodeDescriptors); |
| this.linkDescriptor = Preconditions.checkNotNull(linkDescriptor); |
| } |
| |
| /** |
| * Reads channel buffer and parses link identifier. |
| * |
| * @param cb ChannelBuffer |
| * @param protocolId in linkstate nlri |
| * @return object of BGPLinkLSIdentifier |
| * @throws BgpParseException while parsing link identifier |
| */ |
| public static BgpLinkLSIdentifier parseLinkIdendifier(ChannelBuffer cb, byte protocolId) throws BgpParseException { |
| //Parse local node descriptor |
| NodeDescriptors localNodeDescriptors = new NodeDescriptors(); |
| localNodeDescriptors = parseNodeDescriptors(cb, NodeDescriptors.LOCAL_NODE_DES_TYPE, protocolId); |
| |
| //Parse remote node descriptor |
| NodeDescriptors remoteNodeDescriptors = new NodeDescriptors(); |
| remoteNodeDescriptors = parseNodeDescriptors(cb, NodeDescriptors.REMOTE_NODE_DES_TYPE, protocolId); |
| |
| //Parse link descriptor |
| LinkedList<BgpValueType> linkDescriptor = new LinkedList<>(); |
| linkDescriptor = parseLinkDescriptors(cb); |
| return new BgpLinkLSIdentifier(localNodeDescriptors, remoteNodeDescriptors, linkDescriptor); |
| } |
| |
| /** |
| * Parses Local/Remote node descriptors. |
| * |
| * @param cb ChannelBuffer |
| * @param desType descriptor type |
| * @param protocolId protocol identifier |
| * @return object of NodeDescriptors |
| * @throws BgpParseException while parsing Local/Remote node descriptors |
| */ |
| public static NodeDescriptors parseNodeDescriptors(ChannelBuffer cb, short desType, byte protocolId) |
| throws BgpParseException { |
| log.debug("parse Node descriptors"); |
| 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() + Constants.TYPE_AND_LEN_AS_SHORT)); |
| } |
| NodeDescriptors nodeIdentifier = new NodeDescriptors(); |
| ChannelBuffer tempCb = cb.readBytes(length); |
| |
| if (type == desType) { |
| nodeIdentifier = NodeDescriptors.read(tempCb, length, desType, protocolId); |
| } else { |
| throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.MALFORMED_ATTRIBUTE_LIST, null); |
| } |
| return nodeIdentifier; |
| } |
| |
| /** |
| * Parses link descriptors. |
| * |
| * @param cb ChannelBuffer |
| * @return list of link descriptors |
| * @throws BgpParseException while parsing link descriptors |
| */ |
| public static LinkedList<BgpValueType> parseLinkDescriptors(ChannelBuffer cb) throws BgpParseException { |
| LinkedList<BgpValueType> linkDescriptor = new LinkedList<>(); |
| BgpValueType tlv = null; |
| int count = 0; |
| |
| 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() + Constants.TYPE_AND_LEN_AS_SHORT)); |
| } |
| ChannelBuffer tempCb = cb.readBytes(length); |
| switch (type) { |
| case LinkLocalRemoteIdentifiersTlv.TYPE: |
| tlv = LinkLocalRemoteIdentifiersTlv.read(tempCb); |
| break; |
| case IPV4_INTERFACE_ADDRESS_TYPE: |
| tlv = IPv4AddressTlv.read(tempCb, IPV4_INTERFACE_ADDRESS_TYPE); |
| break; |
| case IPV4_NEIGHBOR_ADDRESS_TYPE: |
| tlv = IPv4AddressTlv.read(tempCb, IPV4_NEIGHBOR_ADDRESS_TYPE); |
| break; |
| case IPV6_INTERFACE_ADDRESS_TYPE: |
| tlv = IPv6AddressTlv.read(tempCb, IPV6_INTERFACE_ADDRESS_TYPE); |
| break; |
| case IPV6_NEIGHBOR_ADDRESS_TYPE: |
| tlv = IPv6AddressTlv.read(tempCb, IPV6_NEIGHBOR_ADDRESS_TYPE); |
| break; |
| case BgpAttrNodeMultiTopologyId.ATTRNODE_MULTITOPOLOGY: |
| tlv = BgpAttrNodeMultiTopologyId.read(tempCb); |
| count = count++; |
| //MultiTopologyId TLV cannot repeat more than once |
| if (count > 1) { |
| //length + 4 implies data contains type, length and value |
| throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, |
| BgpErrorType.OPTIONAL_ATTRIBUTE_ERROR, tempBuf.readBytes(length |
| + Constants.TYPE_AND_LEN_AS_SHORT)); |
| } |
| break; |
| default: |
| UnSupportedAttribute.skipBytes(tempCb, length); |
| } |
| linkDescriptor.add(tlv); |
| } |
| return linkDescriptor; |
| } |
| |
| /** |
| * Returns local node descriptors. |
| * |
| * @return local node descriptors |
| */ |
| public NodeDescriptors localNodeDescriptors() { |
| return this.localNodeDescriptors; |
| } |
| |
| /** |
| * Returns remote node descriptors. |
| * |
| * @return remote node descriptors |
| */ |
| public NodeDescriptors remoteNodeDescriptors() { |
| return this.remoteNodeDescriptors; |
| } |
| |
| /** |
| * Returns link descriptors. |
| * |
| * @return link descriptors |
| */ |
| public List<BgpValueType> linkDescriptors() { |
| return this.linkDescriptor; |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hash(linkDescriptor, localNodeDescriptors, remoteNodeDescriptors); |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (this == obj) { |
| return true; |
| } |
| if (obj instanceof BgpLinkLSIdentifier) { |
| int countObjSubTlv = 0; |
| int countOtherSubTlv = 0; |
| boolean isCommonSubTlv = true; |
| BgpLinkLSIdentifier other = (BgpLinkLSIdentifier) obj; |
| Iterator<BgpValueType> objListIterator = other.linkDescriptor.iterator(); |
| countOtherSubTlv = other.linkDescriptor.size(); |
| countObjSubTlv = linkDescriptor.size(); |
| if (countObjSubTlv != countOtherSubTlv) { |
| return false; |
| } else { |
| while (objListIterator.hasNext() && isCommonSubTlv) { |
| BgpValueType subTlv = objListIterator.next(); |
| if (linkDescriptor.contains(subTlv) && other.linkDescriptor.contains(subTlv)) { |
| isCommonSubTlv = Objects.equals(linkDescriptor.get(linkDescriptor.indexOf(subTlv)), |
| other.linkDescriptor.get(other.linkDescriptor.indexOf(subTlv))); |
| } else { |
| isCommonSubTlv = false; |
| } |
| } |
| return isCommonSubTlv && Objects.equals(this.localNodeDescriptors, other.localNodeDescriptors) |
| && Objects.equals(this.remoteNodeDescriptors, other.remoteNodeDescriptors); |
| } |
| } |
| return false; |
| } |
| |
| @Override |
| public String toString() { |
| return MoreObjects.toStringHelper(getClass()) |
| .add("localNodeDescriptors", localNodeDescriptors) |
| .add("remoteNodeDescriptors", remoteNodeDescriptors) |
| .add("linkDescriptor", linkDescriptor) |
| .toString(); |
| } |
| |
| @Override |
| public int compareTo(Object o) { |
| if (this.equals(o)) { |
| return 0; |
| } |
| boolean tlvFound = false; |
| int result = this.localNodeDescriptors.compareTo(((BgpLinkLSIdentifier) o).localNodeDescriptors); |
| if (result != 0) { |
| return result; |
| } else if (this.remoteNodeDescriptors.compareTo(((BgpLinkLSIdentifier) o).remoteNodeDescriptors) != 0) { |
| return this.remoteNodeDescriptors.compareTo(((BgpLinkLSIdentifier) o).remoteNodeDescriptors); |
| } else { |
| int countOtherSubTlv = ((BgpLinkLSIdentifier) o).linkDescriptor.size(); |
| int countObjSubTlv = linkDescriptor.size(); |
| if (countOtherSubTlv != countObjSubTlv) { |
| if (countOtherSubTlv > countObjSubTlv) { |
| return 1; |
| } else { |
| return -1; |
| } |
| } |
| ListIterator<BgpValueType> listIterator = linkDescriptor.listIterator(); |
| while (listIterator.hasNext()) { |
| BgpValueType tlv1 = listIterator.next(); |
| for (BgpValueType tlv : ((BgpLinkLSIdentifier) o).linkDescriptor) { |
| if (tlv.getType() == tlv1.getType()) { |
| result = linkDescriptor.get(linkDescriptor.indexOf(tlv1)).compareTo( |
| ((BgpLinkLSIdentifier) o).linkDescriptor.get(((BgpLinkLSIdentifier) o).linkDescriptor |
| .indexOf(tlv))); |
| if (result != 0) { |
| return result; |
| } |
| tlvFound = true; |
| break; |
| } |
| } |
| if (!tlvFound) { |
| return 1; |
| } |
| } |
| } |
| return 0; |
| } |
| } |