Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-lacp.c
blob4ed9ceeee771ce834a6897a66f0d6923893bb9f7
1 /* packet-lacp.c
2 * Routines for Link Aggregation Control Protocol dissection.
3 * IEEE Std 802.1AX-2014 Section 6.4.2.3
4 * Split from IEEE Std 802.3-2005 and named IEEE 802.3ad before that
6 * Copyright 2002 Steve Housley <steve_housley@3com.com>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * SPDX-License-Identifier: GPL-2.0-or-later
15 #include "config.h"
17 #include <epan/etypes.h>
18 #include <epan/packet.h>
19 #include <epan/to_str.h>
20 #include <epan/expert.h>
21 #include <epan/slow_protocol_subtypes.h>
22 #include <epan/tfs.h>
23 #include <wsutil/array.h>
25 /* General declarations */
26 void proto_register_lacp(void);
27 void proto_reg_handoff_lacp(void);
29 static dissector_handle_t lacp_handle;
31 #define VLACP_MAGIC_LACP 0x01010114
32 #define VLACP_MAGIC_MARKER 0x02010114
34 /* TLV Types */
35 #define LACPDU_TYPE_TERMINATOR 0x00
36 #define LACPDU_TYPE_ACTOR_INFORMATION 0x01
37 #define LACPDU_TYPE_PARTNER_INFORMATION 0x02
38 #define LACPDU_TYPE_COLLECTOR_INFORMATION 0x03
40 static const value_string lacp_type_vals[] = {
41 { LACPDU_TYPE_TERMINATOR, "Terminator" },
42 { LACPDU_TYPE_ACTOR_INFORMATION, "Actor Information" },
43 { LACPDU_TYPE_PARTNER_INFORMATION, "Partner Information" },
44 { LACPDU_TYPE_COLLECTOR_INFORMATION, "Collector Information" },
45 { 0, NULL }
48 /* Actor and Partner Flag bits */
49 #define LACPDU_FLAGS_ACTIVITY 0x01
50 #define LACPDU_FLAGS_TIMEOUT 0x02
51 #define LACPDU_FLAGS_AGGREGATION 0x04
52 #define LACPDU_FLAGS_SYNC 0x08
53 #define LACPDU_FLAGS_COLLECTING 0x10
54 #define LACPDU_FLAGS_DISTRIB 0x20
55 #define LACPDU_FLAGS_DEFAULTED 0x40
56 #define LACPDU_FLAGS_EXPIRED 0x80
58 /* Initialise the protocol and registered fields */
59 static int proto_lacp;
61 static int hf_lacp_vlacp_subtype;
62 static int hf_lacp_version;
63 static int hf_lacp_tlv_type;
64 static int hf_lacp_tlv_length;
66 static int hf_lacp_actor_sysid_priority;
67 static int hf_lacp_actor_sysid;
68 static int hf_lacp_actor_key;
69 static int hf_lacp_actor_port_priority;
70 static int hf_lacp_actor_port;
71 static int hf_lacp_actor_state;
72 static int hf_lacp_actor_state_str;
73 static int hf_lacp_flags_a_activity;
74 static int hf_lacp_flags_a_timeout;
75 static int hf_lacp_flags_a_aggregation;
76 static int hf_lacp_flags_a_sync;
77 static int hf_lacp_flags_a_collecting;
78 static int hf_lacp_flags_a_distrib;
79 static int hf_lacp_flags_a_defaulted;
80 static int hf_lacp_flags_a_expired;
81 static int hf_lacp_actor_reserved;
83 static int hf_lacp_partner_sysid_priority;
84 static int hf_lacp_partner_sysid;
85 static int hf_lacp_partner_key;
86 static int hf_lacp_partner_port_priority;
87 static int hf_lacp_partner_port;
88 static int hf_lacp_partner_state;
89 static int hf_lacp_partner_state_str;
90 static int hf_lacp_flags_p_activity;
91 static int hf_lacp_flags_p_timeout;
92 static int hf_lacp_flags_p_aggregation;
93 static int hf_lacp_flags_p_sync;
94 static int hf_lacp_flags_p_collecting;
95 static int hf_lacp_flags_p_distrib;
96 static int hf_lacp_flags_p_defaulted;
97 static int hf_lacp_flags_p_expired;
98 static int hf_lacp_partner_reserved;
100 static int hf_lacp_coll_max_delay;
101 static int hf_lacp_coll_reserved;
103 static int hf_lacp_pad;
105 static int hf_lacp_vendor;
107 static int hf_lacp_vendor_hp_length;
108 static int hf_lacp_vendor_hp_irf_domain;
109 static int hf_lacp_vendor_hp_irf_mac;
110 static int hf_lacp_vendor_hp_irf_switch;
111 static int hf_lacp_vendor_hp_irf_port;
112 static int hf_lacp_vendor_hp_unknown;
115 /* Initialise the subtree pointers */
116 static int ett_lacp;
117 static int ett_lacp_a_flags;
118 static int ett_lacp_p_flags;
120 /* Expert Items */
121 static expert_field ei_lacp_wrong_tlv_type;
122 static expert_field ei_lacp_wrong_tlv_length;
124 static const true_false_string tfs_active_passive = { "Active", "Passive" };
125 static const true_false_string tfs_short_long_timeout = { "Short Timeout", "Long Timeout" };
126 static const true_false_string tfs_aggregatable_individual = { "Aggregatable", "Individual" };
127 static const true_false_string tfs_in_sync_out_sync = { "In Sync", "Out of Sync" };
129 static const char * lacp_state_flags_to_str(wmem_allocator_t *scope, uint32_t value)
131 wmem_strbuf_t *buf = wmem_strbuf_new(scope, "");
132 const unsigned int flags_count = 8;
133 static const char first_letters[] = "EFDCSGSA";
134 unsigned int i;
136 for (i = 0; i < flags_count; i++) {
137 if (((value >> (flags_count - 1 - i)) & 1)) {
138 wmem_strbuf_append_c(buf, first_letters[i]);
139 } else {
140 wmem_strbuf_append_c(buf, '*');
144 return wmem_strbuf_finalize(buf);
148 * Name: dissect_lacp
150 * Description:
151 * This function is used to dissect the Link Aggregation Control Protocol
152 * defined in IEEE 802.1AX
154 * Input Arguments:
155 * tvb: buffer associated with the rcv packet (see tvbuff.h).
156 * pinfo: structure associated with the rcv packet (see packet_info.h).
157 * tree: the protocol tree associated with the rcv packet (see proto.h).
159 * Return Values: None
161 * Notes:
163 static int
164 dissect_lacp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
166 int offset = 0, length_remaining;
167 unsigned tlv_type, tlv_length;
168 unsigned version, port, key;
169 const char *sysidstr, *flagstr;
170 uint32_t protodetect;
171 uint8_t is_vlacp;
173 proto_tree *lacp_tree;
174 proto_item *lacp_item, *tlv_type_item, *tlv_length_item;
175 proto_item *ti;
177 static int * const actor_flags[] = {
178 &hf_lacp_flags_a_activity,
179 &hf_lacp_flags_a_timeout,
180 &hf_lacp_flags_a_aggregation,
181 &hf_lacp_flags_a_sync,
182 &hf_lacp_flags_a_collecting,
183 &hf_lacp_flags_a_distrib,
184 &hf_lacp_flags_a_defaulted,
185 &hf_lacp_flags_a_expired,
186 NULL
188 static int * const partner_flags[] = {
189 &hf_lacp_flags_p_activity,
190 &hf_lacp_flags_p_timeout,
191 &hf_lacp_flags_p_aggregation,
192 &hf_lacp_flags_p_sync,
193 &hf_lacp_flags_p_collecting,
194 &hf_lacp_flags_p_distrib,
195 &hf_lacp_flags_p_defaulted,
196 &hf_lacp_flags_p_expired,
197 NULL
200 col_set_str(pinfo->cinfo, COL_PROTOCOL, "LACP");
201 col_set_str(pinfo->cinfo, COL_INFO, "Link Aggregation Control Protocol");
203 /* FIXME
204 * Validate that the destination MAC address is one of the following
205 * (IEEE 802.1AX-2014 6.2.11.2):
206 * 01-80-C2-00-00-00: Nearest Customer Bridge group address
207 * 01-80-C2-00-00-02: IEEE 802.3 Slow_Protocols_Mulitcast group address
208 * 01-80-C2-00-00-03: Nearest non-TPMR Bridge group address
211 protodetect = tvb_get_ntohl(tvb, 0);
212 if ((protodetect == VLACP_MAGIC_LACP) || (protodetect == VLACP_MAGIC_MARKER)) {
213 is_vlacp = 1;
214 /* Add vLACP Heading */
215 lacp_item = proto_tree_add_protocol_format(tree, proto_lacp, tvb,
216 0, -1, "Virtual Link Aggregation Control Protocol");
217 } else {
218 is_vlacp = 0;
219 /* Add LACP Heading - Note: 1 byte for slowprotocol has been consumed already */
220 lacp_item = proto_tree_add_protocol_format(tree, proto_lacp, tvb,
221 0, -1, "Link Aggregation Control Protocol");
223 lacp_tree = proto_item_add_subtree(lacp_item, ett_lacp);
225 if (is_vlacp == 1) {
226 proto_tree_add_item(lacp_tree, hf_lacp_vlacp_subtype, tvb, offset, 1, ENC_NA);
227 offset += 1;
230 /* Version Number */
232 proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_version, tvb, offset, 1, ENC_NA, &version);
233 offset += 1;
235 col_add_fstr(pinfo->cinfo, COL_INFO, "v%d", version);
237 /* Actor */
239 tlv_type_item = proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN, &tlv_type);
240 offset += 1;
242 tlv_length_item = proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_tlv_length, tvb, offset, 1, ENC_BIG_ENDIAN, &tlv_length);
243 offset += 1;
245 if (tlv_type != LACPDU_TYPE_ACTOR_INFORMATION) {
246 expert_add_info(pinfo, tlv_type_item, &ei_lacp_wrong_tlv_type);
248 if (tlv_length != 20) {
249 expert_add_info(pinfo, tlv_length_item, &ei_lacp_wrong_tlv_length);
252 proto_tree_add_item(lacp_tree, hf_lacp_actor_sysid_priority, tvb, offset, 2, ENC_BIG_ENDIAN);
253 offset += 2;
255 proto_tree_add_item(lacp_tree, hf_lacp_actor_sysid, tvb, offset, 6, ENC_NA);
256 sysidstr = tvb_ether_to_str(pinfo->pool, tvb, offset);
257 offset += 6;
259 proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_actor_key, tvb, offset, 2, ENC_BIG_ENDIAN, &key);
260 offset += 2;
262 proto_tree_add_item(lacp_tree, hf_lacp_actor_port_priority, tvb, offset, 2, ENC_BIG_ENDIAN);
263 offset += 2;
265 proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_actor_port, tvb, offset, 2, ENC_BIG_ENDIAN, &port);
266 offset += 2;
268 proto_tree_add_bitmask_with_flags(lacp_tree, tvb, offset, hf_lacp_actor_state,
269 ett_lacp_a_flags, actor_flags, ENC_NA, BMT_NO_INT|BMT_NO_TFS|BMT_NO_FALSE);
270 flagstr = lacp_state_flags_to_str(pinfo->pool, tvb_get_uint8(tvb, offset));
271 ti = proto_tree_add_string(lacp_tree, hf_lacp_actor_state_str, tvb, offset, 1, flagstr);
272 proto_item_set_generated(ti);
273 offset += 1;
275 proto_tree_add_item(lacp_tree, hf_lacp_actor_reserved, tvb, offset, 3, ENC_NA);
276 offset += 3;
278 col_append_fstr(pinfo->cinfo, COL_INFO, " ACTOR %s P: %d K: %d %s", sysidstr, port, key, flagstr);
280 /* Partner */
282 tlv_type_item = proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN, &tlv_type);
283 offset += 1;
285 tlv_length_item = proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_tlv_length, tvb, offset, 1, ENC_BIG_ENDIAN, &tlv_length);
286 offset += 1;
288 if (tlv_type != LACPDU_TYPE_PARTNER_INFORMATION) {
289 expert_add_info(pinfo, tlv_type_item, &ei_lacp_wrong_tlv_type);
291 if (tlv_length != 20) {
292 expert_add_info(pinfo, tlv_length_item, &ei_lacp_wrong_tlv_length);
295 proto_tree_add_item(lacp_tree, hf_lacp_partner_sysid_priority, tvb, offset, 2, ENC_BIG_ENDIAN);
296 offset += 2;
298 proto_tree_add_item(lacp_tree, hf_lacp_partner_sysid, tvb, offset, 6, ENC_NA);
299 sysidstr = tvb_ether_to_str(pinfo->pool, tvb, offset);
300 offset += 6;
302 proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_partner_key, tvb, offset, 2, ENC_BIG_ENDIAN, &key);
303 offset += 2;
305 proto_tree_add_item(lacp_tree, hf_lacp_partner_port_priority, tvb, offset, 2, ENC_BIG_ENDIAN);
306 offset += 2;
308 proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_partner_port, tvb, offset, 2, ENC_BIG_ENDIAN, &port);
309 offset += 2;
311 proto_tree_add_bitmask_with_flags(lacp_tree, tvb, offset, hf_lacp_partner_state, ett_lacp_p_flags, partner_flags, ENC_NA, BMT_NO_INT|BMT_NO_TFS|BMT_NO_FALSE);
312 flagstr = lacp_state_flags_to_str(pinfo->pool, tvb_get_uint8(tvb, offset));
313 ti = proto_tree_add_string(lacp_tree, hf_lacp_partner_state_str, tvb, offset, 1, flagstr);
314 proto_item_set_generated(ti);
315 offset += 1;
317 proto_tree_add_item(lacp_tree, hf_lacp_partner_reserved, tvb, offset, 3, ENC_NA);
318 offset += 3;
320 col_append_fstr(pinfo->cinfo, COL_INFO, " PARTNER %s P: %d K: %d %s", sysidstr, port, key, flagstr);
322 /* Collector */
324 tlv_type_item = proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN, &tlv_type);
325 offset += 1;
327 tlv_length_item = proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_tlv_length, tvb, offset, 1, ENC_BIG_ENDIAN, &tlv_length);
328 offset += 1;
330 if (tlv_type != LACPDU_TYPE_COLLECTOR_INFORMATION) {
331 expert_add_info(pinfo, tlv_type_item, &ei_lacp_wrong_tlv_type);
333 if (tlv_length != 16) {
334 expert_add_info(pinfo, tlv_length_item, &ei_lacp_wrong_tlv_length);
337 proto_tree_add_item(lacp_tree, hf_lacp_coll_max_delay, tvb, offset, 2, ENC_BIG_ENDIAN);
338 offset += 2;
340 proto_tree_add_item(lacp_tree, hf_lacp_coll_reserved, tvb, offset, 12, ENC_NA);
341 offset += 12;
343 /* col_append_fstr(pinfo->cinfo, COL_INFO, " COLLECTOR"); */
345 /* Other TLVs (LACP version 2) */
347 proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN, &tlv_type);
348 offset += 1;
350 tlv_length_item = proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_tlv_length, tvb, offset, 1, ENC_BIG_ENDIAN, &tlv_length);
351 offset += 1;
353 while (tlv_type != LACPDU_TYPE_TERMINATOR && tlv_length >= 2) {
354 offset += (tlv_length - 2);
355 proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN, &tlv_type);
356 offset += 1;
358 tlv_length_item = proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_tlv_length, tvb, offset, 1, ENC_BIG_ENDIAN, &tlv_length);
359 offset += 1;
362 /* Terminator - already handled */
364 if (tlv_length != 0) {
365 expert_add_info(pinfo, tlv_length_item, &ei_lacp_wrong_tlv_length);
368 /* Pad */
370 if (offset < (128 - 1 - 18)) { /* LACPv1 fixed size - Eth */
371 proto_tree_add_item(lacp_tree, hf_lacp_pad, tvb, offset, (128 - 1 - 18)-offset, ENC_NA);
372 offset += ((128 - 1 - 18)-offset);
375 /* HP specific stuff (in violation of standard) */
377 length_remaining = tvb_reported_length_remaining(tvb, offset);
378 if (length_remaining) {
380 /* HP LACP MAD IRF, first bytes is always 0x64 and second bytes is the rest of length */
381 if (length_remaining > 2 && (tvb_get_uint8(tvb, offset) == 0x64) && ((length_remaining -2) == tvb_get_uint8(tvb, offset+1)) )
383 proto_tree_add_item(lacp_tree, hf_lacp_vendor, tvb, offset, length_remaining, ENC_NA);
384 proto_tree_add_item(lacp_tree, hf_lacp_vendor_hp_unknown, tvb, offset, 1, ENC_NA);
385 offset += 1;
387 proto_tree_add_item(lacp_tree, hf_lacp_vendor_hp_length, tvb, offset, 1, ENC_NA);
388 offset += 1;
390 proto_tree_add_item(lacp_tree, hf_lacp_vendor_hp_unknown, tvb, offset, 2, ENC_NA);
391 offset += 2;
393 proto_tree_add_item(lacp_tree, hf_lacp_vendor_hp_irf_domain, tvb, offset, 2, ENC_NA);
394 offset += 2;
396 proto_tree_add_item(lacp_tree, hf_lacp_vendor_hp_irf_mac, tvb, offset, 6, ENC_NA);
397 offset += 6;
399 proto_tree_add_item(lacp_tree, hf_lacp_vendor_hp_unknown, tvb, offset, 8, ENC_NA);
400 offset += 8;
402 proto_tree_add_item(lacp_tree, hf_lacp_vendor_hp_irf_switch, tvb, offset, 2, ENC_NA);
403 offset += 2;
405 proto_tree_add_item(lacp_tree, hf_lacp_vendor_hp_irf_port, tvb, offset, 2, ENC_NA);
406 offset += 2;
408 proto_tree_add_item(lacp_tree, hf_lacp_vendor_hp_unknown, tvb, offset, 2, ENC_NA);
409 } else {
410 /* Not the HP specific extras. Don't claim the remaining data. It may actually be an ethernet trailer. */
411 set_actual_length(tvb, tvb_captured_length(tvb) - length_remaining);
412 proto_item_set_len(lacp_item, tvb_captured_length(tvb));
415 return tvb_captured_length(tvb);
418 /* Register the protocol with Wireshark */
419 void
420 proto_register_lacp(void)
422 /* Setup list of header fields */
424 static hf_register_info hf[] = {
425 { &hf_lacp_vlacp_subtype,
426 { "vLACP subtype", "lacp.vlacp_subtype",
427 FT_UINT8, BASE_DEC, NULL, 0x0,
428 "Avaya vlacp unused lacp subtype byte", HFILL }},
430 { &hf_lacp_version,
431 { "LACP Version", "lacp.version",
432 FT_UINT8, BASE_HEX, NULL, 0x0,
433 NULL, HFILL }},
435 { &hf_lacp_tlv_type,
436 { "TLV Type", "lacp.tlv_type",
437 FT_UINT8, BASE_HEX, VALS(lacp_type_vals), 0x0,
438 NULL, HFILL }},
440 { &hf_lacp_tlv_length,
441 { "TLV Length", "lacp.tlv_length",
442 FT_UINT8, BASE_HEX, NULL, 0x0,
443 NULL, HFILL }},
445 { &hf_lacp_actor_sysid_priority,
446 { "Actor System Priority", "lacp.actor.sys_priority",
447 FT_UINT16, BASE_DEC, NULL, 0x0,
448 NULL, HFILL }},
450 { &hf_lacp_actor_sysid,
451 { "Actor System ID", "lacp.actor.sysid",
452 FT_ETHER, BASE_NONE, NULL, 0x0,
453 NULL, HFILL }},
455 { &hf_lacp_actor_key,
456 { "Actor Key", "lacp.actor.key",
457 FT_UINT16, BASE_DEC, NULL, 0x0,
458 NULL, HFILL }},
460 { &hf_lacp_actor_port_priority,
461 { "Actor Port Priority", "lacp.actor.port_priority",
462 FT_UINT16, BASE_DEC, NULL, 0x0,
463 NULL, HFILL }},
465 { &hf_lacp_actor_port,
466 { "Actor Port", "lacp.actor.port",
467 FT_UINT16, BASE_DEC, NULL, 0x0,
468 NULL, HFILL }},
470 { &hf_lacp_actor_state,
471 { "Actor State", "lacp.actor.state",
472 FT_UINT8, BASE_HEX, NULL, 0x0,
473 NULL, HFILL }},
475 { &hf_lacp_actor_state_str,
476 { "Actor State Flags", "lacp.actor.state_str",
477 FT_STRING, BASE_NONE, NULL, 0x0,
478 NULL, HFILL }},
480 { &hf_lacp_flags_a_activity,
481 { "LACP Activity", "lacp.actor.state.activity",
482 FT_BOOLEAN, 8, TFS(&tfs_active_passive), LACPDU_FLAGS_ACTIVITY,
483 NULL, HFILL }},
485 { &hf_lacp_flags_a_timeout,
486 { "LACP Timeout", "lacp.actor.state.timeout",
487 FT_BOOLEAN, 8, TFS(&tfs_short_long_timeout), LACPDU_FLAGS_TIMEOUT,
488 NULL, HFILL }},
490 { &hf_lacp_flags_a_aggregation,
491 { "Aggregation", "lacp.actor.state.aggregation",
492 FT_BOOLEAN, 8, TFS(&tfs_aggregatable_individual), LACPDU_FLAGS_AGGREGATION,
493 NULL, HFILL }},
495 { &hf_lacp_flags_a_sync,
496 { "Synchronization", "lacp.actor.state.synchronization",
497 FT_BOOLEAN, 8, TFS(&tfs_in_sync_out_sync), LACPDU_FLAGS_SYNC,
498 NULL, HFILL }},
500 { &hf_lacp_flags_a_collecting,
501 { "Collecting", "lacp.actor.state.collecting",
502 FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled), LACPDU_FLAGS_COLLECTING,
503 NULL, HFILL }},
505 { &hf_lacp_flags_a_distrib,
506 { "Distributing", "lacp.actor.state.distributing",
507 FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled), LACPDU_FLAGS_DISTRIB,
508 NULL, HFILL }},
510 { &hf_lacp_flags_a_defaulted,
511 { "Defaulted", "lacp.actor.state.defaulted",
512 FT_BOOLEAN, 8, TFS(&tfs_yes_no), LACPDU_FLAGS_DEFAULTED,
513 "1 = Actor Rx machine is using DEFAULT Partner info, 0 = using info in Rx'd LACPDU", HFILL }},
515 { &hf_lacp_flags_a_expired,
516 { "Expired", "lacp.actor.state.expired",
517 FT_BOOLEAN, 8, TFS(&tfs_yes_no), LACPDU_FLAGS_EXPIRED,
518 NULL, HFILL }},
520 { &hf_lacp_actor_reserved,
521 { "Reserved", "lacp.actor.reserved",
522 FT_BYTES, BASE_NONE, NULL, 0x0,
523 NULL, HFILL }},
525 { &hf_lacp_partner_sysid_priority,
526 { "Partner System Priority", "lacp.partner.sys_priority",
527 FT_UINT16, BASE_DEC, NULL, 0x0,
528 NULL, HFILL }},
530 { &hf_lacp_partner_sysid,
531 { "Partner System", "lacp.partner.sysid",
532 FT_ETHER, BASE_NONE, NULL, 0x0,
533 NULL, HFILL }},
535 { &hf_lacp_partner_key,
536 { "Partner Key", "lacp.partner.key",
537 FT_UINT16, BASE_DEC, NULL, 0x0,
538 NULL, HFILL }},
540 { &hf_lacp_partner_port_priority,
541 { "Partner Port Priority", "lacp.partner.port_priority",
542 FT_UINT16, BASE_DEC, NULL, 0x0,
543 NULL, HFILL }},
545 { &hf_lacp_partner_port,
546 { "Partner Port", "lacp.partner.port",
547 FT_UINT16, BASE_DEC, NULL, 0x0,
548 "The port number associated with this link assigned to the port by the Partner (via Management or Admin)", HFILL }},
550 { &hf_lacp_partner_state,
551 { "Partner State", "lacp.partner.state",
552 FT_UINT8, BASE_HEX, NULL, 0x0,
553 NULL, HFILL }},
555 { &hf_lacp_partner_state_str,
556 { "Partner State Flags", "lacp.partner.state_str",
557 FT_STRING, BASE_NONE, NULL, 0x0,
558 NULL, HFILL }},
560 { &hf_lacp_flags_p_activity,
561 { "LACP Activity", "lacp.partner.state.activity",
562 FT_BOOLEAN, 8, TFS(&tfs_active_passive), LACPDU_FLAGS_ACTIVITY,
563 NULL, HFILL }},
565 { &hf_lacp_flags_p_timeout,
566 { "LACP Timeout", "lacp.partner.state.timeout",
567 FT_BOOLEAN, 8, TFS(&tfs_short_long_timeout), LACPDU_FLAGS_TIMEOUT,
568 NULL, HFILL }},
570 { &hf_lacp_flags_p_aggregation,
571 { "Aggregation", "lacp.partner.state.aggregation",
572 FT_BOOLEAN, 8, TFS(&tfs_aggregatable_individual), LACPDU_FLAGS_AGGREGATION,
573 NULL, HFILL }},
575 { &hf_lacp_flags_p_sync,
576 { "Synchronization", "lacp.partner.state.synchronization",
577 FT_BOOLEAN, 8, TFS(&tfs_in_sync_out_sync), LACPDU_FLAGS_SYNC,
578 NULL, HFILL }},
580 { &hf_lacp_flags_p_collecting,
581 { "Collecting", "lacp.partner.state.collecting",
582 FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled), LACPDU_FLAGS_COLLECTING,
583 NULL, HFILL }},
585 { &hf_lacp_flags_p_distrib,
586 { "Distributing", "lacp.partner.state.distributing",
587 FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled), LACPDU_FLAGS_DISTRIB,
588 NULL, HFILL }},
590 { &hf_lacp_flags_p_defaulted,
591 { "Defaulted", "lacp.partner.state.defaulted",
592 FT_BOOLEAN, 8, TFS(&tfs_yes_no), LACPDU_FLAGS_DEFAULTED,
593 "1 = Actor Rx machine is using DEFAULT Partner info, 0 = using info in Rx'd LACPDU", HFILL }},
595 { &hf_lacp_flags_p_expired,
596 { "Expired", "lacp.partner.state.expired",
597 FT_BOOLEAN, 8, TFS(&tfs_yes_no), LACPDU_FLAGS_EXPIRED,
598 NULL, HFILL }},
600 { &hf_lacp_partner_reserved,
601 { "Reserved", "lacp.partner.reserved",
602 FT_BYTES, BASE_NONE, NULL, 0x0,
603 NULL, HFILL }},
605 { &hf_lacp_coll_max_delay,
606 { "Collector Max Delay", "lacp.collector.max_delay",
607 FT_UINT16, BASE_DEC, NULL, 0x0,
608 "The max delay of the station sending the LACPDU (in tens of usecs)", HFILL }},
610 { &hf_lacp_coll_reserved,
611 { "Reserved", "lacp.coll_reserved",
612 FT_BYTES, BASE_NONE, NULL, 0x0,
613 NULL, HFILL }},
615 { &hf_lacp_pad,
616 { "Pad", "lacp.pad",
617 FT_BYTES, BASE_NONE, NULL, 0x0,
618 NULL, HFILL }},
620 { &hf_lacp_vendor,
621 { "Unknown vendor", "lacp.vendor",
622 FT_BYTES, BASE_NONE, NULL, 0x0,
623 "Some extra bytes (Vendor Specific ?)", HFILL }},
625 /* HP IRF MAD LACP */
626 { &hf_lacp_vendor_hp_length,
627 { "Length", "lacp.vendor.hp.length",
628 FT_UINT16, BASE_DEC, NULL, 0x0,
629 "The length of HP TLV", HFILL }},
630 { &hf_lacp_vendor_hp_irf_domain,
631 { "IRF Domain", "lacp.vendor.hp.irf_domain",
632 FT_UINT16, BASE_DEC, NULL, 0x0,
633 NULL, HFILL }},
634 { &hf_lacp_vendor_hp_irf_mac,
635 { "IRF MAC", "lacp.vendor.hp.irf_mac",
636 FT_ETHER, BASE_NONE, NULL, 0x0,
637 NULL, HFILL }},
638 { &hf_lacp_vendor_hp_irf_switch,
639 { "IRF Switch", "lacp.vendor.hp.irf_switch",
640 FT_UINT16, BASE_DEC, NULL, 0x0,
641 "Number of switch on the IRF stack", HFILL }},
642 { &hf_lacp_vendor_hp_irf_port,
643 { "IRF Port", "lacp.vendor.hp.irf_port",
644 FT_UINT16, BASE_DEC, NULL, 0x0,
645 "Stack ID where the LACP is attached", HFILL }},
646 { &hf_lacp_vendor_hp_unknown,
647 { "Unknown", "lacp.vendor.hp.unknown",
648 FT_BYTES, BASE_NONE, NULL, 0x0,
649 NULL, HFILL }},
652 /* Setup protocol subtree array */
654 static int *ett[] = {
655 &ett_lacp,
656 &ett_lacp_a_flags,
657 &ett_lacp_p_flags,
660 static ei_register_info ei[] = {
661 { &ei_lacp_wrong_tlv_type, { "lacp.wrong_tlv_type", PI_MALFORMED, PI_ERROR, "TLV is not expected type", EXPFILL }},
662 { &ei_lacp_wrong_tlv_length, { "lacp.wrong_tlv_length", PI_MALFORMED, PI_ERROR, "TLV is not expected length", EXPFILL }},
665 expert_module_t* expert_lacp;
668 /* Register the protocol name and description */
670 proto_lacp = proto_register_protocol("Link Aggregation Control Protocol", "LACP", "lacp");
672 /* Required function calls to register the header fields and subtrees used */
674 proto_register_field_array(proto_lacp, hf, array_length(hf));
675 proto_register_subtree_array(ett, array_length(ett));
676 expert_lacp = expert_register_protocol(proto_lacp);
677 expert_register_field_array(expert_lacp, ei, array_length(ei));
679 lacp_handle = register_dissector("lacp", dissect_lacp, proto_lacp);
682 void
683 proto_reg_handoff_lacp(void)
685 dissector_add_uint("slow.subtype", LACP_SUBTYPE, lacp_handle);
686 dissector_add_uint("ethertype", ETHERTYPE_VLACP, lacp_handle);
690 * Editor modelines - https://www.wireshark.org/tools/modelines.html
692 * Local variables:
693 * c-basic-offset: 4
694 * tab-width: 8
695 * indent-tabs-mode: nil
696 * End:
698 * vi: set shiftwidth=4 tabstop=8 expandtab:
699 * :indentSize=4:tabSize=8:noTabs=true: