blob: 37f33ddd61e5f5b8216c1e49ff93b92e8708b9f4 [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
Ray Milkey49724162019-01-25 15:59:36 -080041 public static final byte PORT_TLV_COMPONENT_SUBTYPE = 2;
DongRyeol Chace65cc02018-07-23 15:02:28 +090042 public static final byte PORT_TLV_INTERFACE_NAME_SUBTYPE = 5;
43
Jonathan Hart2a655752015-04-07 16:46:33 -070044 public static final byte TTL_TLV_TYPE = 3;
45 public static final short TTL_TLV_SIZE = 2;
46
alshabibc4901cd2014-09-05 16:50:40 -070047 protected LLDPTLV chassisId;
48 protected LLDPTLV portId;
49 protected LLDPTLV ttl;
50 protected List<LLDPTLV> optionalTLVList;
51 protected short ethType;
52
53 public LLDP() {
Jonathan Hart2a655752015-04-07 16:46:33 -070054 this.optionalTLVList = new LinkedList<>();
alshabibc4901cd2014-09-05 16:50:40 -070055 this.ethType = Ethernet.TYPE_LLDP;
56 }
57
58 /**
59 * @return the chassisId
60 */
61 public LLDPTLV getChassisId() {
62 return this.chassisId;
63 }
64
65 /**
Jian Li5fc14292015-12-04 11:30:46 -080066 * @param chassis the chassisId to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -080067 * @return this
alshabibc4901cd2014-09-05 16:50:40 -070068 */
69 public LLDP setChassisId(final LLDPTLV chassis) {
70 this.chassisId = chassis;
71 return this;
72 }
73
74 /**
75 * @return the portId
76 */
77 public LLDPTLV getPortId() {
78 return this.portId;
79 }
80
81 /**
Jian Li5fc14292015-12-04 11:30:46 -080082 * @param portId the portId to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -080083 * @return this
alshabibc4901cd2014-09-05 16:50:40 -070084 */
85 public LLDP setPortId(final LLDPTLV portId) {
86 this.portId = portId;
87 return this;
88 }
89
90 /**
91 * @return the ttl
92 */
93 public LLDPTLV getTtl() {
94 return this.ttl;
95 }
96
97 /**
Jian Li5fc14292015-12-04 11:30:46 -080098 * @param ttl the ttl to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -080099 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700100 */
101 public LLDP setTtl(final LLDPTLV ttl) {
102 this.ttl = ttl;
103 return this;
104 }
105
106 /**
107 * @return the optionalTLVList
108 */
109 public List<LLDPTLV> getOptionalTLVList() {
110 return this.optionalTLVList;
111 }
112
113 /**
Jian Li5fc14292015-12-04 11:30:46 -0800114 * @param optionalTLVList the optionalTLVList to set
Yuta HIGUCHI2281b3f2014-11-04 00:20:48 -0800115 * @return this
alshabibc4901cd2014-09-05 16:50:40 -0700116 */
117 public LLDP setOptionalTLVList(final List<LLDPTLV> optionalTLVList) {
118 this.optionalTLVList = optionalTLVList;
119 return this;
120 }
121
jaegonkim47b1b4a2017-12-04 14:08:26 +0900122 /**
123 * Adds additional TLV to optionalTLVList.
124 * @param lldptlv the optional TLV to be added
125 * @return this
126 */
127 public LLDP addOptionalTLV(final LLDPTLV lldptlv) {
128 this.optionalTLVList.add(lldptlv);
129 return this;
130 }
131
alshabibc4901cd2014-09-05 16:50:40 -0700132 @Override
133 public byte[] serialize() {
134 int length = 2 + this.chassisId.getLength() + 2
135 + this.portId.getLength() + 2 + this.ttl.getLength() + 2;
136 for (final LLDPTLV tlv : this.optionalTLVList) {
137 length += 2 + tlv.getLength();
138 }
139
140 final byte[] data = new byte[length];
141 final ByteBuffer bb = ByteBuffer.wrap(data);
142 bb.put(this.chassisId.serialize());
143 bb.put(this.portId.serialize());
144 bb.put(this.ttl.serialize());
145 for (final LLDPTLV tlv : this.optionalTLVList) {
146 bb.put(tlv.serialize());
147 }
148 bb.putShort((short) 0); // End of LLDPDU
149
150 /*
151 * if (this.parent != null && this.parent instanceof Ethernet) {
152 * ((Ethernet) this.parent).setEtherType(this.ethType); }
153 */
154
155 return data;
156 }
157
alshabibc4901cd2014-09-05 16:50:40 -0700158
159 /*
160 * (non-Javadoc)
161 *
162 * @see java.lang.Object#hashCode()
163 */
164 @Override
165 public int hashCode() {
166 final int prime = 883;
167 int result = super.hashCode();
168 result = prime * result
169 + (this.chassisId == null ? 0 : this.chassisId.hashCode());
170 result = prime * result + this.optionalTLVList.hashCode();
171 result = prime * result
172 + (this.portId == null ? 0 : this.portId.hashCode());
173 result = prime * result + (this.ttl == null ? 0 : this.ttl.hashCode());
174 return result;
175 }
176
177 /*
178 * (non-Javadoc)
179 *
180 * @see java.lang.Object#equals(java.lang.Object)
181 */
182 @Override
183 public boolean equals(final Object obj) {
184 if (this == obj) {
185 return true;
186 }
187 if (!super.equals(obj)) {
188 return false;
189 }
190 if (!(obj instanceof LLDP)) {
191 return false;
192 }
193 final LLDP other = (LLDP) obj;
194 if (this.chassisId == null) {
195 if (other.chassisId != null) {
196 return false;
197 }
198 } else if (!this.chassisId.equals(other.chassisId)) {
199 return false;
200 }
201 if (!this.optionalTLVList.equals(other.optionalTLVList)) {
202 return false;
203 }
204 if (this.portId == null) {
205 if (other.portId != null) {
206 return false;
207 }
208 } else if (!this.portId.equals(other.portId)) {
209 return false;
210 }
211 if (this.ttl == null) {
212 if (other.ttl != null) {
213 return false;
214 }
215 } else if (!this.ttl.equals(other.ttl)) {
216 return false;
217 }
218 return true;
219 }
Jonathan Hart2a655752015-04-07 16:46:33 -0700220
221 /**
222 * Deserializer function for LLDP packets.
223 *
224 * @return deserializer function
225 */
226 public static Deserializer<LLDP> deserializer() {
227 return (data, offset, length) -> {
228 checkInput(data, offset, length, 0);
229
230 LLDP lldp = new LLDP();
231
232 int currentIndex = 0;
233
234 ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
235 LLDPTLV tlv;
236 do {
237 // Each new TLV must be a minimum of 2 bytes
238 // (containing the type and length fields).
239 currentIndex += 2;
240 checkHeaderLength(length, currentIndex);
241
242 tlv = new LLDPOrganizationalTLV().deserialize(bb);
243
244 // if there was a failure to deserialize stop processing TLVs
245 if (tlv == null) {
246 break;
247 }
248 switch (tlv.getType()) {
Jian Li5fc14292015-12-04 11:30:46 -0800249 case 0x0:
250 // can throw this one away, it's just an end delimiter
251 break;
252 case 0x1:
253 lldp.chassisId = tlv;
254 break;
255 case 0x2:
256 lldp.portId = tlv;
257 break;
258 case 0x3:
259 lldp.ttl = tlv;
260 break;
261 default:
262 lldp.optionalTLVList.add(tlv);
263 break;
Jonathan Hart2a655752015-04-07 16:46:33 -0700264 }
265
266 currentIndex += tlv.getLength();
267 } while (tlv.getType() != 0);
268
269 return lldp;
270 };
271 }
272
Jian Li5fc14292015-12-04 11:30:46 -0800273 @Override
274 public String toString() {
275 return toStringHelper(getClass())
276 .add("chassisId", Arrays.toString(chassisId.getValue()))
277 .add("portId", Arrays.toString(portId.getValue()))
278 .add("ttl", Arrays.toString(ttl.getValue()))
279 .add("ethType", Short.toString(ethType))
280 .toString();
281
282 // TODO: need to handle optionalTLVList
283 }
alshabibc4901cd2014-09-05 16:50:40 -0700284}