| /* |
| * 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.IPReachabilityInformationTlv; |
| import org.onosproject.bgpio.types.OspfRouteTypeTlv; |
| import org.onosproject.bgpio.types.attr.BgpAttrNodeMultiTopologyId; |
| import org.onosproject.bgpio.util.UnSupportedAttribute; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| import com.google.common.base.MoreObjects; |
| |
| /** |
| * Provides Implementation of Local node descriptors and prefix descriptors. |
| */ |
| public class BgpPrefixLSIdentifier implements Comparable<Object> { |
| |
| protected static final Logger log = LoggerFactory.getLogger(BgpPrefixLSIdentifier.class); |
| public static final int TYPE_AND_LEN = 4; |
| private NodeDescriptors localNodeDescriptors; |
| private List<BgpValueType> prefixDescriptor; |
| |
| /** |
| * Resets parameters. |
| */ |
| public BgpPrefixLSIdentifier() { |
| this.localNodeDescriptors = null; |
| this.prefixDescriptor = null; |
| } |
| |
| /** |
| * Constructor to initialize parameters. |
| * |
| * @param localNodeDescriptors Local node descriptors |
| * @param prefixDescriptor Prefix Descriptors |
| */ |
| public BgpPrefixLSIdentifier(NodeDescriptors localNodeDescriptors, List<BgpValueType> prefixDescriptor) { |
| this.localNodeDescriptors = localNodeDescriptors; |
| this.prefixDescriptor = prefixDescriptor; |
| } |
| |
| /** |
| * Reads the channel buffer and parses Prefix Identifier. |
| * |
| * @param cb ChannelBuffer |
| * @param protocolId protocol ID |
| * @return object of this class |
| * @throws BgpParseException while parsing Prefix Identifier |
| */ |
| public static BgpPrefixLSIdentifier parsePrefixIdendifier(ChannelBuffer cb, byte protocolId) |
| throws BgpParseException { |
| //Parse Local Node descriptor |
| NodeDescriptors localNodeDescriptors = new NodeDescriptors(); |
| localNodeDescriptors = parseLocalNodeDescriptors(cb, protocolId); |
| |
| //Parse Prefix descriptor |
| List<BgpValueType> prefixDescriptor = new LinkedList<>(); |
| prefixDescriptor = parsePrefixDescriptors(cb); |
| return new BgpPrefixLSIdentifier(localNodeDescriptors, prefixDescriptor); |
| } |
| |
| /** |
| * Parse local node descriptors. |
| * |
| * @param cb ChannelBuffer |
| * @param protocolId protocol identifier |
| * @return LocalNodeDescriptors |
| * @throws BgpParseException while parsing local node descriptors |
| */ |
| public static NodeDescriptors parseLocalNodeDescriptors(ChannelBuffer cb, byte protocolId) |
| throws BgpParseException { |
| ChannelBuffer tempBuf = cb.copy(); |
| short type = cb.readShort(); |
| short length = cb.readShort(); |
| if (cb.readableBytes() < length) { |
| //length + 4 implies data contains type, length and value |
| throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.OPTIONAL_ATTRIBUTE_ERROR, |
| tempBuf.readBytes(cb.readableBytes() + TYPE_AND_LEN)); |
| } |
| NodeDescriptors localNodeDescriptors = new NodeDescriptors(); |
| ChannelBuffer tempCb = cb.readBytes(length); |
| |
| if (type == NodeDescriptors.LOCAL_NODE_DES_TYPE) { |
| localNodeDescriptors = NodeDescriptors.read(tempCb, length, type, protocolId); |
| } else { |
| throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, |
| BgpErrorType.MALFORMED_ATTRIBUTE_LIST, null); |
| } |
| return localNodeDescriptors; |
| } |
| |
| /** |
| * Parse list of prefix descriptors. |
| * |
| * @param cb ChannelBuffer |
| * @return list of prefix descriptors |
| * @throws BgpParseException while parsing list of prefix descriptors |
| */ |
| public static List<BgpValueType> parsePrefixDescriptors(ChannelBuffer cb) throws BgpParseException { |
| LinkedList<BgpValueType> prefixDescriptor = new LinkedList<>(); |
| BgpValueType tlv = null; |
| boolean isIpReachInfo = false; |
| ChannelBuffer tempCb; |
| int count = 0; |
| |
| while (cb.readableBytes() > 0) { |
| ChannelBuffer tempBuf = cb.copy(); |
| short type = cb.readShort(); |
| short length = cb.readShort(); |
| if (cb.readableBytes() < length) { |
| //length + 4 implies data contains type, length and value |
| throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.OPTIONAL_ATTRIBUTE_ERROR, |
| tempBuf.readBytes(cb.readableBytes() + TYPE_AND_LEN)); |
| } |
| tempCb = cb.readBytes(length); |
| switch (type) { |
| case OspfRouteTypeTlv.TYPE: |
| tlv = OspfRouteTypeTlv.read(tempCb); |
| break; |
| case IPReachabilityInformationTlv.TYPE: |
| tlv = IPReachabilityInformationTlv.read(tempCb, length); |
| isIpReachInfo = true; |
| break; |
| case BgpAttrNodeMultiTopologyId.ATTRNODE_MULTITOPOLOGY: |
| tlv = BgpAttrNodeMultiTopologyId.read(tempCb); |
| count = count + 1; |
| 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 + TYPE_AND_LEN)); |
| } |
| break; |
| default: |
| UnSupportedAttribute.skipBytes(tempCb, length); |
| } |
| prefixDescriptor.add(tlv); |
| } |
| |
| if (!isIpReachInfo) { |
| throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.OPTIONAL_ATTRIBUTE_ERROR, |
| null); |
| } |
| return prefixDescriptor; |
| } |
| |
| /** |
| * Returns local node descriptors. |
| * |
| * @return local node descriptors |
| */ |
| public NodeDescriptors getLocalNodeDescriptors() { |
| return this.localNodeDescriptors; |
| } |
| |
| /** |
| * Returns Prefix descriptors. |
| * |
| * @return Prefix descriptors |
| */ |
| public List<BgpValueType> getPrefixdescriptor() { |
| return this.prefixDescriptor; |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hash(prefixDescriptor.hashCode(), localNodeDescriptors); |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (this == obj) { |
| return true; |
| } |
| |
| if (obj instanceof BgpPrefixLSIdentifier) { |
| int countObjSubTlv = 0; |
| int countOtherSubTlv = 0; |
| boolean isCommonSubTlv = true; |
| BgpPrefixLSIdentifier other = (BgpPrefixLSIdentifier) obj; |
| |
| Iterator<BgpValueType> objListIterator = other.prefixDescriptor.iterator(); |
| countOtherSubTlv = other.prefixDescriptor.size(); |
| countObjSubTlv = prefixDescriptor.size(); |
| if (countObjSubTlv != countOtherSubTlv) { |
| return false; |
| } else { |
| while (objListIterator.hasNext() && isCommonSubTlv) { |
| BgpValueType subTlv = objListIterator.next(); |
| if (prefixDescriptor.contains(subTlv) && other.prefixDescriptor.contains(subTlv)) { |
| isCommonSubTlv = Objects.equals(prefixDescriptor.get(prefixDescriptor.indexOf(subTlv)), |
| other.prefixDescriptor.get(other.prefixDescriptor.indexOf(subTlv))); |
| } else { |
| isCommonSubTlv = false; |
| } |
| } |
| return isCommonSubTlv && Objects.equals(this.localNodeDescriptors, other.localNodeDescriptors); |
| } |
| } |
| return false; |
| } |
| |
| @Override |
| public String toString() { |
| return MoreObjects.toStringHelper(getClass()) |
| .add("localNodeDescriptors", localNodeDescriptors) |
| .add("prefixDescriptor", prefixDescriptor) |
| .toString(); |
| } |
| |
| @Override |
| public int compareTo(Object o) { |
| if (this.equals(o)) { |
| return 0; |
| } |
| int result = this.localNodeDescriptors.compareTo(((BgpPrefixLSIdentifier) o).localNodeDescriptors); |
| boolean tlvFound = false; |
| if (result != 0) { |
| return result; |
| } else { |
| int countOtherSubTlv = ((BgpPrefixLSIdentifier) o).prefixDescriptor.size(); |
| int countObjSubTlv = prefixDescriptor.size(); |
| if (countOtherSubTlv != countObjSubTlv) { |
| if (countOtherSubTlv > countObjSubTlv) { |
| return 1; |
| } else { |
| return -1; |
| } |
| } |
| |
| ListIterator<BgpValueType> listIterator = prefixDescriptor.listIterator(); |
| while (listIterator.hasNext()) { |
| BgpValueType tlv1 = listIterator.next(); |
| for (BgpValueType tlv : ((BgpPrefixLSIdentifier) o).prefixDescriptor) { |
| if (tlv.getType() == tlv1.getType()) { |
| result = prefixDescriptor.get(prefixDescriptor.indexOf(tlv1)).compareTo( |
| ((BgpPrefixLSIdentifier) o).prefixDescriptor |
| .get(((BgpPrefixLSIdentifier) o).prefixDescriptor.indexOf(tlv))); |
| if (result != 0) { |
| return result; |
| } |
| tlvFound = true; |
| break; |
| } |
| } |
| if (!tlvFound) { |
| return 1; |
| } |
| } |
| } |
| return 0; |
| } |
| } |