blob: 10e672e5d176fd945f28e12170573f88ef345c1f [file] [log] [blame]
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -07001/*
2 * Copyright 2015 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.pcepio.types;
17
18import java.util.Iterator;
19import java.util.LinkedList;
20import java.util.ListIterator;
21import java.util.Objects;
22
23import org.jboss.netty.buffer.ChannelBuffer;
24import org.onosproject.pcepio.exceptions.PcepParseException;
25import org.onosproject.pcepio.protocol.PcepVersion;
26import org.slf4j.Logger;
27import org.slf4j.LoggerFactory;
28
29import com.google.common.base.MoreObjects;
30
31/**
32 * Provides TELinkAttributesTlv.
33 */
34public class TELinkAttributesTlv implements PcepValueType {
35
36 /*
37 * Reference :PCEP Extension for Transporting TE Data draft-dhodylee-pce-pcep-te-data-extn-02
38 * 0 1 2 3
39 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
40 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
41 | Type=[TBD27] | Length |
42 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
43 | |
44 // Link Attributes Sub-TLVs (variable) //
45 | |
46 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
47 */
48
49 protected static final Logger log = LoggerFactory.getLogger(TELinkAttributesTlv.class);
50
51 public static final short TYPE = 1897; //TODD:change this TBD27
52 public short hLength;
53
54 public static final int TLV_HEADER_LENGTH = 4;
55
56 // LinkDescriptors Sub-TLVs (variable)
57 private LinkedList<PcepValueType> llLinkAttributesSubTLVs;
58
59 /**
60 * Constructor to initialize Link Attributes Sub TLVs.
61 *
62 * @param llLinkAttributesSubTLVs linked list of PcepValueType
63 */
64 public TELinkAttributesTlv(LinkedList<PcepValueType> llLinkAttributesSubTLVs) {
65 this.llLinkAttributesSubTLVs = llLinkAttributesSubTLVs;
66 }
67
68 /**
69 * Returns object of TE Link Attributes TLV.
70 *
71 * @param llLinkAttributesSubTLVs linked list of Link Attribute of Sub TLV
72 * @return object of TELinkAttributesTlv
73 */
74 public static TELinkAttributesTlv of(final LinkedList<PcepValueType> llLinkAttributesSubTLVs) {
75 return new TELinkAttributesTlv(llLinkAttributesSubTLVs);
76 }
77
78 /**
79 * Returns linked list of Link Attribute of Sub TLV.
80 *
81 * @return llLinkAttributesSubTLVs linked list of Link Attribute of Sub TLV
82 */
83 public LinkedList<PcepValueType> getllLinkAttributesSubTLVs() {
84 return llLinkAttributesSubTLVs;
85 }
86
87 @Override
88 public PcepVersion getVersion() {
89 return PcepVersion.PCEP_1;
90 }
91
92 @Override
93 public short getType() {
94 return TYPE;
95 }
96
97 @Override
98 public short getLength() {
99 return hLength;
100 }
101
102 @Override
103 public int hashCode() {
104 return Objects.hash(llLinkAttributesSubTLVs.hashCode());
105 }
106
107 @Override
108 public boolean equals(Object obj) {
109 if (this == obj) {
110 return true;
111 }
112 /*
113 * Here we have a list of Tlv so to compare each sub tlv between the object
114 * we have to take a list iterator so one by one we can get each sub tlv object
115 * and can compare them.
116 * it may be possible that the size of 2 lists is not equal so we have to first check
117 * the size, if both are same then we should check for the subtlv objects otherwise
118 * we should return false.
119 */
120 if (obj instanceof TELinkAttributesTlv) {
121 int countObjSubTlv = 0;
122 int countOtherSubTlv = 0;
123 boolean isCommonSubTlv = true;
124 TELinkAttributesTlv other = (TELinkAttributesTlv) obj;
125 Iterator<PcepValueType> objListIterator = ((TELinkAttributesTlv) obj).llLinkAttributesSubTLVs.iterator();
126 countObjSubTlv = ((TELinkAttributesTlv) obj).llLinkAttributesSubTLVs.size();
127 countOtherSubTlv = other.llLinkAttributesSubTLVs.size();
128 if (countObjSubTlv != countOtherSubTlv) {
129 return false;
130 } else {
131 while (objListIterator.hasNext() && isCommonSubTlv) {
132 PcepValueType subTlv = objListIterator.next();
133 isCommonSubTlv = Objects.equals(llLinkAttributesSubTLVs.contains(subTlv),
134 other.llLinkAttributesSubTLVs.contains(subTlv));
135 }
136 return isCommonSubTlv;
137 }
138 }
139 return false;
140 }
141
142 @Override
143 public int write(ChannelBuffer c) {
144 int tlvStartIndex = c.writerIndex();
145 c.writeShort(TYPE);
146 int tlvLenIndex = c.writerIndex();
147 hLength = 0;
148 c.writeShort(hLength);
149
150 ListIterator<PcepValueType> listIterator = llLinkAttributesSubTLVs.listIterator();
151
152 while (listIterator.hasNext()) {
153 PcepValueType tlv = listIterator.next();
154
Sho SHIMIZUde09fa02015-09-03 09:39:52 -0700155 if (tlv == null) {
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -0700156 log.debug("TLV is null from subTlv list");
157 continue;
158 }
159 tlv.write(c);
160
161 // need to take care of padding
162 int pad = tlv.getLength() % 4;
163
164 if (0 != pad) {
165 pad = 4 - pad;
166 for (int i = 0; i < pad; ++i) {
167 c.writeByte((byte) 0);
168 }
169 }
170 }
171
172 hLength = (short) (c.writerIndex() - tlvStartIndex);
173 c.setShort(tlvLenIndex, (hLength - TLV_HEADER_LENGTH));
174
175 return c.writerIndex() - tlvStartIndex;
176 }
177
178 /**
179 * Reads channel buffer and returns object of TE Link Attributes TLV.
180 *
181 * @param c input channel buffer
182 * @param hLength length
183 * @return object of TELinkAttributesTlv
184 * @throws PcepParseException if mandatory fields are missing
185 */
186 public static PcepValueType read(ChannelBuffer c, short hLength) throws PcepParseException {
187
188 // Node Descriptor Sub-TLVs (variable)
Sho SHIMIZU9b8274c2015-09-04 15:54:24 -0700189 LinkedList<PcepValueType> llLinkAttributesSubTLVs = new LinkedList<>();
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -0700190
191 ChannelBuffer tempCb = c.readBytes(hLength);
192
193 while (TLV_HEADER_LENGTH <= tempCb.readableBytes()) {
194
195 PcepValueType tlv;
196 short hType = tempCb.readShort();
197 int iValue = 0;
198 short length = tempCb.readShort();
199 switch (hType) {
200
201 case IPv4TERouterIdOfLocalNodeTlv.TYPE:
202 iValue = tempCb.readInt();
203 tlv = new IPv4TERouterIdOfLocalNodeTlv(iValue);
204 break;
205 case IPv6TERouterIdofLocalNodeTlv.TYPE:
206 byte[] ipv6LValue = new byte[IPv6TERouterIdofLocalNodeTlv.VALUE_LENGTH];
207 tempCb.readBytes(ipv6LValue, 0, IPv6TERouterIdofLocalNodeTlv.VALUE_LENGTH);
208 tlv = new IPv6TERouterIdofLocalNodeTlv(ipv6LValue);
209 break;
210 case IPv4TERouterIdOfRemoteNodeTlv.TYPE:
211 iValue = tempCb.readInt();
212 tlv = new IPv4TERouterIdOfRemoteNodeTlv(iValue);
213 break;
214 case IPv6TERouterIdofRemoteNodeTlv.TYPE:
215 byte[] ipv6RValue = new byte[IPv6TERouterIdofRemoteNodeTlv.VALUE_LENGTH];
216 tempCb.readBytes(ipv6RValue, 0, IPv6TERouterIdofRemoteNodeTlv.VALUE_LENGTH);
217 tlv = new IPv6TERouterIdofRemoteNodeTlv(ipv6RValue);
218 break;
219 case LinkLocalRemoteIdentifiersTlv.TYPE:
220 tlv = LinkLocalRemoteIdentifiersTlv.read(tempCb);
221 break;
222 case AdministrativeGroupTlv.TYPE:
223 iValue = tempCb.readInt();
224 tlv = new AdministrativeGroupTlv(iValue);
225 break;
226 case MaximumLinkBandwidthTlv.TYPE:
227 iValue = tempCb.readInt();
228 tlv = new MaximumLinkBandwidthTlv(iValue);
229 break;
230 case MaximumReservableLinkBandwidthTlv.TYPE:
231 iValue = tempCb.readInt();
232 tlv = new MaximumReservableLinkBandwidthTlv(iValue);
233 break;
234 case UnreservedBandwidthTlv.TYPE:
235 iValue = tempCb.readInt();
236 tlv = new UnreservedBandwidthTlv(iValue);
237 break;
238 case TEDefaultMetricTlv.TYPE:
239 iValue = tempCb.readInt();
240 tlv = new TEDefaultMetricTlv(iValue);
241 break;
242 case LinkProtectionTypeTlv.TYPE:
243 tlv = LinkProtectionTypeTlv.read(tempCb);
244 break;
Jonathan Hart51539b82015-10-29 09:53:04 -0700245 case MplsProtocolMaskTlv.TYPE:
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -0700246 byte cValue = tempCb.readByte();
Jonathan Hart51539b82015-10-29 09:53:04 -0700247 tlv = new MplsProtocolMaskTlv(cValue);
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -0700248 break;
Jonathan Hart51539b82015-10-29 09:53:04 -0700249 case IgpMetricTlv.TYPE:
250 tlv = IgpMetricTlv.read(tempCb, length);
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -0700251 break;
252 case SharedRiskLinkGroupTlv.TYPE:
253 tlv = SharedRiskLinkGroupTlv.read(tempCb, length);
254 break;
255 case OpaqueLinkAttributeTlv.TYPE:
256 tlv = OpaqueLinkAttributeTlv.read(tempCb, length);
257 break;
258 case LinkNameTlv.TYPE:
259 tlv = LinkNameTlv.read(tempCb, length);
260 break;
261 default:
262 throw new PcepParseException("Unsupported Sub TLV type :" + hType);
263 }
264
265 // Check for the padding
266 int pad = length % 4;
267 if (0 < pad) {
268 pad = 4 - pad;
269 if (pad <= tempCb.readableBytes()) {
270 tempCb.skipBytes(pad);
271 }
272 }
273 llLinkAttributesSubTLVs.add(tlv);
274 }
275
276 if (0 < tempCb.readableBytes()) {
277
278 throw new PcepParseException("Sub Tlv parsing error. Extra bytes received.");
279 }
280
281 return new TELinkAttributesTlv(llLinkAttributesSubTLVs);
282 }
283
284 @Override
285 public String toString() {
Sho SHIMIZU7cdbcf72015-09-03 14:43:05 -0700286 return MoreObjects.toStringHelper(getClass())
287 .add("Type", TYPE)
288 .add("Length", hLength)
289 .add("LinkAttributesSubTLVs", llLinkAttributesSubTLVs)
290 .toString();
Sho SHIMIZUe81e4db2015-09-03 09:44:38 -0700291 }
292}