| /* |
| * 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.types; |
| |
| 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.pcepio.exceptions.PcepParseException; |
| import org.onosproject.pcepio.protocol.PcepVersion; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| import com.google.common.base.MoreObjects; |
| |
| /** |
| * Provides LinkAttributesTlv. |
| */ |
| public class LinkAttributesTlv implements PcepValueType { |
| |
| /* |
| * Reference :draft-dhodylee-pce-pcep-ls-01, section 9.2.8.2. |
| * 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=[TBD27] | Length | |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| | | |
| // Link Attributes Sub-TLVs (variable) // |
| | | |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| */ |
| |
| protected static final Logger log = LoggerFactory.getLogger(LinkAttributesTlv.class); |
| |
| public static final short TYPE = (short) 65286; |
| public short hLength; |
| |
| public static final int TLV_HEADER_LENGTH = 4; |
| |
| // LinkDescriptors Sub-TLVs (variable) |
| private List<PcepValueType> llLinkAttributesSubTLVs; |
| |
| /** |
| * Constructor to initialize Link Attributes Sub TLVs. |
| * |
| * @param llLinkAttributesSubTLVs linked list of PcepValueType |
| */ |
| public LinkAttributesTlv(List<PcepValueType> llLinkAttributesSubTLVs) { |
| this.llLinkAttributesSubTLVs = llLinkAttributesSubTLVs; |
| } |
| |
| /** |
| * Returns object of TE Link Attributes TLV. |
| * |
| * @param llLinkAttributesSubTLVs linked list of Link Attribute of Sub TLV |
| * @return object of LinkAttributesTlv |
| */ |
| public static LinkAttributesTlv of(final List<PcepValueType> llLinkAttributesSubTLVs) { |
| return new LinkAttributesTlv(llLinkAttributesSubTLVs); |
| } |
| |
| /** |
| * Returns linked list of Link Attribute of Sub TLV. |
| * |
| * @return llLinkAttributesSubTLVs linked list of Link Attribute of Sub TLV |
| */ |
| public List<PcepValueType> getllLinkAttributesSubTLVs() { |
| return llLinkAttributesSubTLVs; |
| } |
| |
| @Override |
| public PcepVersion getVersion() { |
| return PcepVersion.PCEP_1; |
| } |
| |
| @Override |
| public short getType() { |
| return TYPE; |
| } |
| |
| @Override |
| public short getLength() { |
| return hLength; |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hash(llLinkAttributesSubTLVs.hashCode()); |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (this == obj) { |
| return true; |
| } |
| /* |
| * Here we have a list of Tlv so to compare each sub tlv between the object |
| * we have to take a list iterator so one by one we can get each sub tlv object |
| * and can compare them. |
| * it may be possible that the size of 2 lists is not equal so we have to first check |
| * the size, if both are same then we should check for the subtlv objects otherwise |
| * we should return false. |
| */ |
| if (obj instanceof LinkAttributesTlv) { |
| int countObjSubTlv = 0; |
| int countOtherSubTlv = 0; |
| boolean isCommonSubTlv = true; |
| LinkAttributesTlv other = (LinkAttributesTlv) obj; |
| Iterator<PcepValueType> objListIterator = ((LinkAttributesTlv) obj).llLinkAttributesSubTLVs.iterator(); |
| countObjSubTlv = ((LinkAttributesTlv) obj).llLinkAttributesSubTLVs.size(); |
| countOtherSubTlv = other.llLinkAttributesSubTLVs.size(); |
| if (countObjSubTlv != countOtherSubTlv) { |
| return false; |
| } else { |
| while (objListIterator.hasNext() && isCommonSubTlv) { |
| PcepValueType subTlv = objListIterator.next(); |
| isCommonSubTlv = Objects.equals(llLinkAttributesSubTLVs.contains(subTlv), |
| other.llLinkAttributesSubTLVs.contains(subTlv)); |
| } |
| return isCommonSubTlv; |
| } |
| } |
| return false; |
| } |
| |
| @Override |
| public int write(ChannelBuffer c) { |
| int tlvStartIndex = c.writerIndex(); |
| c.writeShort(TYPE); |
| int tlvLenIndex = c.writerIndex(); |
| hLength = 0; |
| c.writeShort(hLength); |
| |
| ListIterator<PcepValueType> listIterator = llLinkAttributesSubTLVs.listIterator(); |
| |
| while (listIterator.hasNext()) { |
| PcepValueType tlv = listIterator.next(); |
| |
| if (tlv == null) { |
| log.debug("TLV is null from subTlv list"); |
| continue; |
| } |
| tlv.write(c); |
| |
| // need to take care of padding |
| int pad = tlv.getLength() % 4; |
| |
| if (0 != pad) { |
| pad = 4 - pad; |
| for (int i = 0; i < pad; ++i) { |
| c.writeByte((byte) 0); |
| } |
| } |
| } |
| |
| hLength = (short) (c.writerIndex() - tlvStartIndex); |
| c.setShort(tlvLenIndex, (hLength - TLV_HEADER_LENGTH)); |
| |
| return c.writerIndex() - tlvStartIndex; |
| } |
| |
| /** |
| * Reads channel buffer and returns object of TE Link Attributes TLV. |
| * |
| * @param c input channel buffer |
| * @param hLength length |
| * @return object of LinkAttributesTlv |
| * @throws PcepParseException if mandatory fields are missing |
| */ |
| public static PcepValueType read(ChannelBuffer c, short hLength) throws PcepParseException { |
| |
| // Node Descriptor Sub-TLVs (variable) |
| List<PcepValueType> llLinkAttributesSubTLVs = new LinkedList<>(); |
| |
| ChannelBuffer tempCb = c.readBytes(hLength); |
| |
| while (TLV_HEADER_LENGTH <= tempCb.readableBytes()) { |
| |
| PcepValueType tlv; |
| short hType = tempCb.readShort(); |
| int iValue = 0; |
| short length = tempCb.readShort(); |
| switch (hType) { |
| |
| case IPv4RouterIdOfLocalNodeSubTlv.TYPE: |
| iValue = tempCb.readInt(); |
| tlv = new IPv4RouterIdOfLocalNodeSubTlv(iValue); |
| break; |
| case IPv6RouterIdofLocalNodeSubTlv.TYPE: |
| byte[] ipv6LValue = new byte[IPv6RouterIdofLocalNodeSubTlv.VALUE_LENGTH]; |
| tempCb.readBytes(ipv6LValue, 0, IPv6RouterIdofLocalNodeSubTlv.VALUE_LENGTH); |
| tlv = new IPv6RouterIdofLocalNodeSubTlv(ipv6LValue); |
| break; |
| case IPv4RouterIdOfRemoteNodeSubTlv.TYPE: |
| iValue = tempCb.readInt(); |
| tlv = new IPv4RouterIdOfRemoteNodeSubTlv(iValue); |
| break; |
| case IPv6RouterIdofRemoteNodeSubTlv.TYPE: |
| byte[] ipv6RValue = new byte[IPv6RouterIdofRemoteNodeSubTlv.VALUE_LENGTH]; |
| tempCb.readBytes(ipv6RValue, 0, IPv6RouterIdofRemoteNodeSubTlv.VALUE_LENGTH); |
| tlv = new IPv6RouterIdofRemoteNodeSubTlv(ipv6RValue); |
| break; |
| case LinkLocalRemoteIdentifiersSubTlv.TYPE: |
| tlv = LinkLocalRemoteIdentifiersSubTlv.read(tempCb); |
| break; |
| case AdministrativeGroupSubTlv.TYPE: |
| iValue = tempCb.readInt(); |
| tlv = new AdministrativeGroupSubTlv(iValue); |
| break; |
| case MaximumLinkBandwidthSubTlv.TYPE: |
| iValue = tempCb.readInt(); |
| tlv = new MaximumLinkBandwidthSubTlv(iValue); |
| break; |
| case MaximumReservableLinkBandwidthSubTlv.TYPE: |
| iValue = tempCb.readInt(); |
| tlv = new MaximumReservableLinkBandwidthSubTlv(iValue); |
| break; |
| case UnreservedBandwidthSubTlv.TYPE: |
| iValue = tempCb.readInt(); |
| tlv = new UnreservedBandwidthSubTlv(iValue); |
| break; |
| case TEDefaultMetricSubTlv.TYPE: |
| iValue = tempCb.readInt(); |
| tlv = new TEDefaultMetricSubTlv(iValue); |
| break; |
| case LinkProtectionTypeSubTlv.TYPE: |
| tlv = LinkProtectionTypeSubTlv.read(tempCb); |
| break; |
| case MplsProtocolMaskSubTlv.TYPE: |
| byte cValue = tempCb.readByte(); |
| tlv = new MplsProtocolMaskSubTlv(cValue); |
| break; |
| case IgpMetricSubTlv.TYPE: |
| tlv = IgpMetricSubTlv.read(tempCb, length); |
| break; |
| case SharedRiskLinkGroupSubTlv.TYPE: |
| tlv = SharedRiskLinkGroupSubTlv.read(tempCb, length); |
| break; |
| case OpaqueLinkAttributeSubTlv.TYPE: |
| tlv = OpaqueLinkAttributeSubTlv.read(tempCb, length); |
| break; |
| case LinkNameAttributeSubTlv.TYPE: |
| tlv = LinkNameAttributeSubTlv.read(tempCb, length); |
| break; |
| default: |
| throw new PcepParseException("Unsupported Sub TLV type :" + hType); |
| } |
| |
| // Check for the padding |
| int pad = length % 4; |
| if (0 < pad) { |
| pad = 4 - pad; |
| if (pad <= tempCb.readableBytes()) { |
| tempCb.skipBytes(pad); |
| } |
| } |
| llLinkAttributesSubTLVs.add(tlv); |
| } |
| |
| if (0 < tempCb.readableBytes()) { |
| |
| throw new PcepParseException("Sub Tlv parsing error. Extra bytes received."); |
| } |
| |
| return new LinkAttributesTlv(llLinkAttributesSubTLVs); |
| } |
| |
| @Override |
| public String toString() { |
| return MoreObjects.toStringHelper(getClass()) |
| .add("Type", TYPE) |
| .add("Length", hLength) |
| .add("LinkAttributesSubTLVs", llLinkAttributesSubTLVs) |
| .toString(); |
| } |
| } |