blob: e555f1fd3a40391d4e91f09d81f3ddc87c8567bc [file] [log] [blame]
Thomas Vachuska24c849c2014-10-27 09:53:05 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2014-present Open Networking Foundation
alshabibc4901cd2014-09-05 16:50:40 -07003 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07004 * 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
alshabibc4901cd2014-09-05 16:50:40 -07007 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07008 * 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.
Thomas Vachuska24c849c2014-10-27 09:53:05 -070015 */
alshabibc4901cd2014-09-05 16:50:40 -070016
17/**
18 *
19 */
20package org.onlab.packet;
21
22import java.nio.ByteBuffer;
Jian Li5fc14292015-12-04 11:30:46 -080023import java.util.Arrays;
Jonathan Hart2a655752015-04-07 16:46:33 -070024import java.util.LinkedList;
alshabibc4901cd2014-09-05 16:50:40 -070025import java.util.List;
26
Jian Li5fc14292015-12-04 11:30:46 -080027import static com.google.common.base.MoreObjects.toStringHelper;
Jonathan Hart2a655752015-04-07 16:46:33 -070028import static org.onlab.packet.PacketUtils.*;
29
alshabibc4901cd2014-09-05 16:50:40 -070030/**
Jian Li5fc14292015-12-04 11:30:46 -080031 * Representation of an LLDP Packet.
alshabibc4901cd2014-09-05 16:50:40 -070032 */
33public class LLDP extends BasePacket {
Jonathan Hart2a655752015-04-07 16:46:33 -070034 public static final byte CHASSIS_TLV_TYPE = 1;
35 public static final short CHASSIS_TLV_SIZE = 7;
36 public static final byte CHASSIS_TLV_SUBTYPE = 4;
37
38 public static final byte PORT_TLV_TYPE = 2;
39 public static final short PORT_TLV_SIZE = 5;
DongRyeol Chace65cc02018-07-23 15:02:28 +090040
41 /**
42 * @deprecated since 1.15. Use the PORT_TLV_COMPONENT_SUBTYPE instead of PORT_TLV_SUBTYPE.
43 */
44 @Deprecated
Jonathan Hart2a655752015-04-07 16:46:33 -070045 public static final byte PORT_TLV_SUBTYPE = 2;
46
DongRyeol Chace65cc02018-07-23 15:02:28 +090047 public static final byte PORT_TLV_COMPONENT_SUBTYPE = PORT_TLV_SUBTYPE;
48 public static final byte PORT_TLV_INTERFACE_NAME_SUBTYPE = 5;
49
Jonathan Hart2a655752015-04-07 16:46:33 -070050 public static final byte TTL_TLV_TYPE = 3;
51 public static final short TTL_TLV_SIZE = 2;
52
alshabibc4901cd2014-09-05 16:50:40 -070053 protected LLDPTLV chassisId;
54 protected LLDPTLV portId;
55 protected LLDPTLV ttl;
56 protected List<LLDPTLV> optionalTLVList;
57 protected short ethType;
58
59 public LLDP() {
Jonathan Hart2a655752015-04-07 16:46:33 -070060 this.optionalTLVList = new LinkedList<>();
alshabibc4901cd2014-09-05 16:50:40 -070061 this.ethType = Ethernet.TYPE_LLDP;
62 }
63
64 /**
65 * @return the chassisId
66 */
67 public LLDPTLV getChassisId() {
68 return this.chassisId;
69 }
70
71 /**
Jian Li5fc14292015-12-04 11:30:46 -080072 * @param chassis the chassisId to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -080073 * @return this
alshabibc4901cd2014-09-05 16:50:40 -070074 */
75 public LLDP setChassisId(final LLDPTLV chassis) {
76 this.chassisId = chassis;
77 return this;
78 }
79
80 /**
81 * @return the portId
82 */
83 public LLDPTLV getPortId() {
84 return this.portId;
85 }
86
87 /**
Jian Li5fc14292015-12-04 11:30:46 -080088 * @param portId the portId to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -080089 * @return this
alshabibc4901cd2014-09-05 16:50:40 -070090 */
91 public LLDP setPortId(final LLDPTLV portId) {
92 this.portId = portId;
93 return this;
94 }
95
96 /**
97 * @return the ttl
98 */
99 public LLDPTLV getTtl() {
100 return this.ttl;
101 }
102
103 /**
Jian Li5fc14292015-12-04 11:30:46 -0800104 * @param ttl the ttl to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800105 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700106 */
107 public LLDP setTtl(final LLDPTLV ttl) {
108 this.ttl = ttl;
109 return this;
110 }
111
112 /**
113 * @return the optionalTLVList
114 */
115 public List<LLDPTLV> getOptionalTLVList() {
116 return this.optionalTLVList;
117 }
118
119 /**
Jian Li5fc14292015-12-04 11:30:46 -0800120 * @param optionalTLVList the optionalTLVList to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800121 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700122 */
123 public LLDP setOptionalTLVList(final List<LLDPTLV> optionalTLVList) {
124 this.optionalTLVList = optionalTLVList;
125 return this;
126 }
127
jaegonkim47b1b4a2017-12-04 14:08:26 +0900128 /**
129 * Adds additional TLV to optionalTLVList.
130 * @param lldptlv the optional TLV to be added
131 * @return this
132 */
133 public LLDP addOptionalTLV(final LLDPTLV lldptlv) {
134 this.optionalTLVList.add(lldptlv);
135 return this;
136 }
137
alshabibc4901cd2014-09-05 16:50:40 -0700138 @Override
139 public byte[] serialize() {
140 int length = 2 + this.chassisId.getLength() + 2
141 + this.portId.getLength() + 2 + this.ttl.getLength() + 2;
142 for (final LLDPTLV tlv : this.optionalTLVList) {
143 length += 2 + tlv.getLength();
144 }
145
146 final byte[] data = new byte[length];
147 final ByteBuffer bb = ByteBuffer.wrap(data);
148 bb.put(this.chassisId.serialize());
149 bb.put(this.portId.serialize());
150 bb.put(this.ttl.serialize());
151 for (final LLDPTLV tlv : this.optionalTLVList) {
152 bb.put(tlv.serialize());
153 }
154 bb.putShort((short) 0); // End of LLDPDU
155
156 /*
157 * if (this.parent != null && this.parent instanceof Ethernet) {
158 * ((Ethernet) this.parent).setEtherType(this.ethType); }
159 */
160
161 return data;
162 }
163
alshabibc4901cd2014-09-05 16:50:40 -0700164
165 /*
166 * (non-Javadoc)
167 *
168 * @see java.lang.Object#hashCode()
169 */
170 @Override
171 public int hashCode() {
172 final int prime = 883;
173 int result = super.hashCode();
174 result = prime * result
175 + (this.chassisId == null ? 0 : this.chassisId.hashCode());
176 result = prime * result + this.optionalTLVList.hashCode();
177 result = prime * result
178 + (this.portId == null ? 0 : this.portId.hashCode());
179 result = prime * result + (this.ttl == null ? 0 : this.ttl.hashCode());
180 return result;
181 }
182
183 /*
184 * (non-Javadoc)
185 *
186 * @see java.lang.Object#equals(java.lang.Object)
187 */
188 @Override
189 public boolean equals(final Object obj) {
190 if (this == obj) {
191 return true;
192 }
193 if (!super.equals(obj)) {
194 return false;
195 }
196 if (!(obj instanceof LLDP)) {
197 return false;
198 }
199 final LLDP other = (LLDP) obj;
200 if (this.chassisId == null) {
201 if (other.chassisId != null) {
202 return false;
203 }
204 } else if (!this.chassisId.equals(other.chassisId)) {
205 return false;
206 }
207 if (!this.optionalTLVList.equals(other.optionalTLVList)) {
208 return false;
209 }
210 if (this.portId == null) {
211 if (other.portId != null) {
212 return false;
213 }
214 } else if (!this.portId.equals(other.portId)) {
215 return false;
216 }
217 if (this.ttl == null) {
218 if (other.ttl != null) {
219 return false;
220 }
221 } else if (!this.ttl.equals(other.ttl)) {
222 return false;
223 }
224 return true;
225 }
Jonathan Hart2a655752015-04-07 16:46:33 -0700226
227 /**
228 * Deserializer function for LLDP packets.
229 *
230 * @return deserializer function
231 */
232 public static Deserializer<LLDP> deserializer() {
233 return (data, offset, length) -> {
234 checkInput(data, offset, length, 0);
235
236 LLDP lldp = new LLDP();
237
238 int currentIndex = 0;
239
240 ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
241 LLDPTLV tlv;
242 do {
243 // Each new TLV must be a minimum of 2 bytes
244 // (containing the type and length fields).
245 currentIndex += 2;
246 checkHeaderLength(length, currentIndex);
247
248 tlv = new LLDPOrganizationalTLV().deserialize(bb);
249
250 // if there was a failure to deserialize stop processing TLVs
251 if (tlv == null) {
252 break;
253 }
254 switch (tlv.getType()) {
Jian Li5fc14292015-12-04 11:30:46 -0800255 case 0x0:
256 // can throw this one away, it's just an end delimiter
257 break;
258 case 0x1:
259 lldp.chassisId = tlv;
260 break;
261 case 0x2:
262 lldp.portId = tlv;
263 break;
264 case 0x3:
265 lldp.ttl = tlv;
266 break;
267 default:
268 lldp.optionalTLVList.add(tlv);
269 break;
Jonathan Hart2a655752015-04-07 16:46:33 -0700270 }
271
272 currentIndex += tlv.getLength();
273 } while (tlv.getType() != 0);
274
275 return lldp;
276 };
277 }
278
Jian Li5fc14292015-12-04 11:30:46 -0800279 @Override
280 public String toString() {
281 return toStringHelper(getClass())
282 .add("chassisId", Arrays.toString(chassisId.getValue()))
283 .add("portId", Arrays.toString(portId.getValue()))
284 .add("ttl", Arrays.toString(ttl.getValue()))
285 .add("ethType", Short.toString(ethType))
286 .toString();
287
288 // TODO: need to handle optionalTLVList
289 }
alshabibc4901cd2014-09-05 16:50:40 -0700290}