2 * Routines for Link Aggregation Control Protocol dissection.
5 * Copyright 2002 Steve Housley <steve_housley@3com.com>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 #include <epan/packet.h>
29 #include <epan/slow_protocol_subtypes.h>
31 /* General declarations */
32 void proto_register_lacp(void);
33 void proto_reg_handoff_lacp(void);
35 /* Actor and Partner Flag bits */
36 #define LACPDU_FLAGS_ACTIVITY 0x01
37 #define LACPDU_FLAGS_TIMEOUT 0x02
38 #define LACPDU_FLAGS_AGGREGATION 0x04
39 #define LACPDU_FLAGS_SYNC 0x08
40 #define LACPDU_FLAGS_COLLECTING 0x10
41 #define LACPDU_FLAGS_DISTRIB 0x20
42 #define LACPDU_FLAGS_DEFAULTED 0x40
43 #define LACPDU_FLAGS_EXPIRED 0x80
45 /* Initialise the protocol and registered fields */
46 static int proto_lacp = -1;
48 static int hf_lacp_version_number = -1;
49 static int hf_lacp_actor_type = -1;
50 static int hf_lacp_actor_info_len = -1;
51 static int hf_lacp_actor_sys_priority = -1;
52 static int hf_lacp_actor_sys = -1;
53 static int hf_lacp_actor_key = -1;
54 static int hf_lacp_actor_port_priority = -1;
55 static int hf_lacp_actor_port = -1;
56 static int hf_lacp_actor_state = -1;
57 static int hf_lacp_flags_a_activity = -1;
58 static int hf_lacp_flags_a_timeout = -1;
59 static int hf_lacp_flags_a_aggregation = -1;
60 static int hf_lacp_flags_a_sync = -1;
61 static int hf_lacp_flags_a_collecting = -1;
62 static int hf_lacp_flags_a_distrib = -1;
63 static int hf_lacp_flags_a_defaulted = -1;
64 static int hf_lacp_flags_a_expired = -1;
65 static int hf_lacp_actor_reserved = -1;
67 static int hf_lacp_partner_type = -1;
68 static int hf_lacp_partner_info_len = -1;
69 static int hf_lacp_partner_sys_priority = -1;
70 static int hf_lacp_partner_sys = -1;
71 static int hf_lacp_partner_key = -1;
72 static int hf_lacp_partner_port_priority = -1;
73 static int hf_lacp_partner_port = -1;
74 static int hf_lacp_partner_state = -1;
75 static int hf_lacp_flags_p_activity = -1;
76 static int hf_lacp_flags_p_timeout = -1;
77 static int hf_lacp_flags_p_aggregation = -1;
78 static int hf_lacp_flags_p_sync = -1;
79 static int hf_lacp_flags_p_collecting = -1;
80 static int hf_lacp_flags_p_distrib = -1;
81 static int hf_lacp_flags_p_defaulted = -1;
82 static int hf_lacp_flags_p_expired = -1;
83 static int hf_lacp_partner_reserved = -1;
85 static int hf_lacp_coll_type = -1;
86 static int hf_lacp_coll_info_len = -1;
87 static int hf_lacp_coll_max_delay = -1;
88 static int hf_lacp_coll_reserved = -1;
90 static int hf_lacp_term_type = -1;
91 static int hf_lacp_term_len = -1;
92 static int hf_lacp_term_reserved = -1;
94 /* Initialise the subtree pointers */
96 static gint ett_lacp = -1;
97 static gint ett_lacp_a_flags = -1;
98 static gint ett_lacp_p_flags = -1;
104 * This function is used to dissect the Link Aggregation Control Protocol
105 * defined in IEEE 802.1AX
108 * tvb: buffer associated with the rcv packet (see tvbuff.h).
109 * pinfo: structure associated with the rcv packet (see packet_info.h).
110 * tree: the protocol tree associated with the rcv packet (see proto.h).
112 * Return Values: None
117 dissect_lacp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
123 proto_tree *lacpdu_tree;
124 proto_item *lacpdu_item;
125 static const int * actor_flags[] = {
126 &hf_lacp_flags_a_activity,
127 &hf_lacp_flags_a_timeout,
128 &hf_lacp_flags_a_aggregation,
129 &hf_lacp_flags_a_sync,
130 &hf_lacp_flags_a_collecting,
131 &hf_lacp_flags_a_distrib,
132 &hf_lacp_flags_a_defaulted,
133 &hf_lacp_flags_a_expired,
136 static const int * partner_flags[] = {
137 &hf_lacp_flags_p_activity,
138 &hf_lacp_flags_p_timeout,
139 &hf_lacp_flags_p_aggregation,
140 &hf_lacp_flags_p_sync,
141 &hf_lacp_flags_p_collecting,
142 &hf_lacp_flags_p_distrib,
143 &hf_lacp_flags_p_defaulted,
144 &hf_lacp_flags_p_expired,
148 col_set_str(pinfo->cinfo, COL_PROTOCOL, "LACP");
149 col_set_str(pinfo->cinfo, COL_INFO, "Link Aggregation Control Protocol");
151 /* Add LACP Heading */
152 lacpdu_item = proto_tree_add_protocol_format(tree, proto_lacp, tvb,
153 0, -1, "Link Aggregation Control Protocol");
154 lacpdu_tree = proto_item_add_subtree(lacpdu_item, ett_lacp);
158 raw_octet = tvb_get_guint8(tvb, offset);
159 col_append_fstr(pinfo->cinfo, COL_INFO, "Version %d. ", raw_octet);
160 proto_tree_add_uint(lacpdu_tree, hf_lacp_version_number, tvb,
161 offset, 1, raw_octet);
166 proto_tree_add_item(lacpdu_tree, hf_lacp_actor_type, tvb,
167 offset, 1, ENC_BIG_ENDIAN);
170 /* Actor Info Length */
172 proto_tree_add_item(lacpdu_tree, hf_lacp_actor_info_len, tvb,
173 offset, 1, ENC_BIG_ENDIAN);
176 /* Actor System Priority */
178 proto_tree_add_item(lacpdu_tree, hf_lacp_actor_sys_priority, tvb,
179 offset, 2, ENC_BIG_ENDIAN);
184 proto_tree_add_item(lacpdu_tree, hf_lacp_actor_sys, tvb,
190 proto_tree_add_item(lacpdu_tree, hf_lacp_actor_key, tvb,
191 offset, 2, ENC_BIG_ENDIAN);
194 /* Actor Port Priority */
196 proto_tree_add_item(lacpdu_tree, hf_lacp_actor_port_priority, tvb,
197 offset, 2, ENC_BIG_ENDIAN);
202 raw_word = tvb_get_ntohs(tvb, offset);
203 col_append_fstr(pinfo->cinfo, COL_INFO, "Actor Port = %d ", raw_word);
204 proto_tree_add_uint(lacpdu_tree, hf_lacp_actor_port, tvb,
205 offset, 2, raw_word);
209 proto_tree_add_bitmask_with_flags(lacpdu_tree, tvb, offset, hf_lacp_actor_state,
210 ett_lacp_a_flags, actor_flags, ENC_NA, BMT_NO_INT|BMT_NO_TFS|BMT_NO_FALSE);
215 proto_tree_add_item(lacpdu_tree, hf_lacp_actor_reserved, tvb,
221 proto_tree_add_item(lacpdu_tree, hf_lacp_partner_type, tvb,
222 offset, 1, ENC_BIG_ENDIAN);
225 /* Partner Info Length */
227 proto_tree_add_item(lacpdu_tree, hf_lacp_partner_info_len, tvb,
228 offset, 1, ENC_BIG_ENDIAN);
231 /* Partner System Priority */
233 proto_tree_add_item(lacpdu_tree, hf_lacp_partner_sys_priority, tvb,
234 offset, 2, ENC_BIG_ENDIAN);
239 proto_tree_add_item(lacpdu_tree, hf_lacp_partner_sys, tvb,
245 proto_tree_add_item(lacpdu_tree, hf_lacp_partner_key, tvb,
246 offset, 2, ENC_BIG_ENDIAN);
249 /* Partner Port Priority */
251 proto_tree_add_item(lacpdu_tree, hf_lacp_partner_port_priority, tvb,
252 offset, 2, ENC_BIG_ENDIAN);
257 raw_word = tvb_get_ntohs(tvb, offset);
258 col_append_fstr(pinfo->cinfo, COL_INFO, "Partner Port = %d ", raw_word);
259 proto_tree_add_uint(lacpdu_tree, hf_lacp_partner_port, tvb,
260 offset, 2, raw_word);
265 proto_tree_add_bitmask_with_flags(lacpdu_tree, tvb, offset, hf_lacp_partner_state,
266 ett_lacp_p_flags, partner_flags, ENC_NA, BMT_NO_INT|BMT_NO_TFS|BMT_NO_FALSE);
270 /* Partner Reserved */
272 proto_tree_add_item(lacpdu_tree, hf_lacp_partner_reserved, tvb,
278 proto_tree_add_item(lacpdu_tree, hf_lacp_coll_type, tvb,
279 offset, 1, ENC_BIG_ENDIAN);
282 /* Collector Info Length */
284 proto_tree_add_item(lacpdu_tree, hf_lacp_coll_info_len, tvb,
285 offset, 1, ENC_BIG_ENDIAN);
288 /* Collector Max Delay */
290 proto_tree_add_item(lacpdu_tree, hf_lacp_coll_max_delay, tvb,
291 offset, 2, ENC_BIG_ENDIAN);
294 /* Collector Reserved */
296 proto_tree_add_item(lacpdu_tree, hf_lacp_coll_reserved, tvb,
300 /* Terminator Type */
302 proto_tree_add_item(lacpdu_tree, hf_lacp_term_type, tvb,
303 offset, 1, ENC_BIG_ENDIAN);
306 /* Terminator Info Length */
308 proto_tree_add_item(lacpdu_tree, hf_lacp_term_len, tvb,
309 offset, 1, ENC_BIG_ENDIAN);
312 /* Terminator Reserved */
314 proto_tree_add_item(lacpdu_tree, hf_lacp_term_reserved, tvb,
319 /* Register the protocol with Wireshark */
321 proto_register_lacp(void)
323 /* Setup list of header fields */
325 static hf_register_info hf[] = {
326 { &hf_lacp_version_number,
327 { "LACP Version Number", "lacp.version",
328 FT_UINT8, BASE_HEX, NULL, 0x0,
329 "Identifies the LACP version", HFILL }},
331 { &hf_lacp_actor_type,
332 { "Actor Information", "lacp.actorInfo",
333 FT_UINT8, BASE_HEX, NULL, 0x0,
334 "TLV type = Actor", HFILL }},
336 { &hf_lacp_actor_info_len,
337 { "Actor Information Length", "lacp.actorInfoLen",
338 FT_UINT8, BASE_HEX, NULL, 0x0,
339 "The length of the Actor TLV", HFILL }},
341 { &hf_lacp_actor_sys_priority,
342 { "Actor System Priority", "lacp.actorSysPriority",
343 FT_UINT16, BASE_DEC, NULL, 0x0,
344 "The priority assigned to this System by management or admin", HFILL }},
346 { &hf_lacp_actor_sys,
347 { "Actor System", "lacp.actorSystem",
348 FT_ETHER, BASE_NONE, NULL, 0x0,
349 "The Actor's System ID encoded as a MAC address", HFILL }},
351 { &hf_lacp_actor_key,
352 { "Actor Key", "lacp.actorKey",
353 FT_UINT16, BASE_DEC, NULL, 0x0,
354 "The operational Key value assigned to the port by the Actor", HFILL }},
356 { &hf_lacp_actor_port_priority,
357 { "Actor Port Priority", "lacp.actorPortPriority",
358 FT_UINT16, BASE_DEC, NULL, 0x0,
359 "The priority assigned to the port by the Actor (via Management or Admin)", HFILL }},
361 { &hf_lacp_actor_port,
362 { "Actor Port", "lacp.actorPort",
363 FT_UINT16, BASE_DEC, NULL, 0x0,
364 "The port number assigned to the port by the Actor (via Management or Admin)", HFILL }},
366 { &hf_lacp_actor_state,
367 { "Actor State", "lacp.actorState",
368 FT_UINT8, BASE_HEX, NULL, 0x0,
369 "The Actor's state variables for the port, encoded as bits within a single octet", HFILL }},
371 { &hf_lacp_flags_a_activity,
372 { "LACP Activity", "lacp.actorState.activity",
373 FT_BOOLEAN, 8, TFS(&tfs_yes_no), LACPDU_FLAGS_ACTIVITY,
374 "Activity control value for this link. Active = 1, Passive = 0", HFILL }},
376 { &hf_lacp_flags_a_timeout,
377 { "LACP Timeout", "lacp.actorState.timeout",
378 FT_BOOLEAN, 8, TFS(&tfs_yes_no), LACPDU_FLAGS_TIMEOUT,
379 "Timeout control value for this link. Short Timeout = 1, Long Timeout = 0", HFILL }},
381 { &hf_lacp_flags_a_aggregation,
382 { "Aggregation", "lacp.actorState.aggregation",
383 FT_BOOLEAN, 8, TFS(&tfs_yes_no), LACPDU_FLAGS_AGGREGATION,
384 "Aggregatable = 1, Individual = 0", HFILL }},
386 { &hf_lacp_flags_a_sync,
387 { "Synchronization", "lacp.actorState.synchronization",
388 FT_BOOLEAN, 8, TFS(&tfs_yes_no), LACPDU_FLAGS_SYNC,
389 "In Sync = 1, Out of Sync = 0", HFILL }},
391 { &hf_lacp_flags_a_collecting,
392 { "Collecting", "lacp.actorState.collecting",
393 FT_BOOLEAN, 8, TFS(&tfs_yes_no), LACPDU_FLAGS_COLLECTING,
394 "Collection of incoming frames is: Enabled = 1, Disabled = 0", HFILL }},
396 { &hf_lacp_flags_a_distrib,
397 { "Distributing", "lacp.actorState.distributing",
398 FT_BOOLEAN, 8, TFS(&tfs_yes_no), LACPDU_FLAGS_DISTRIB,
399 "Distribution of outgoing frames is: Enabled = 1, Disabled = 0", HFILL }},
401 { &hf_lacp_flags_a_defaulted,
402 { "Defaulted", "lacp.actorState.defaulted",
403 FT_BOOLEAN, 8, TFS(&tfs_yes_no), LACPDU_FLAGS_DEFAULTED,
404 "1 = Actor Rx machine is using DEFAULT Partner info, 0 = using info in Rx'd LACPDU", HFILL }},
406 { &hf_lacp_flags_a_expired,
407 { "Expired", "lacp.actorState.expired",
408 FT_BOOLEAN, 8, TFS(&tfs_yes_no), LACPDU_FLAGS_EXPIRED,
409 "1 = Actor Rx machine is EXPIRED, 0 = is NOT EXPIRED", HFILL }},
411 { &hf_lacp_actor_reserved,
412 { "Reserved", "lacp.reserved",
413 FT_BYTES, BASE_NONE, NULL, 0x0,
416 { &hf_lacp_partner_type,
417 { "Partner Information", "lacp.partnerInfo",
418 FT_UINT8, BASE_HEX, NULL, 0x0,
419 "TLV type = Partner", HFILL }},
421 { &hf_lacp_partner_info_len,
422 { "Partner Information Length", "lacp.partnerInfoLen",
423 FT_UINT8, BASE_HEX, NULL, 0x0,
424 "The length of the Partner TLV", HFILL }},
426 { &hf_lacp_partner_sys_priority,
427 { "Partner System Priority", "lacp.partnerSysPriority",
428 FT_UINT16, BASE_DEC, NULL, 0x0,
429 "The priority assigned to the Partner System by management or admin", HFILL }},
431 { &hf_lacp_partner_sys,
432 { "Partner System", "lacp.partnerSystem",
433 FT_ETHER, BASE_NONE, NULL, 0x0,
434 "The Partner's System ID encoded as a MAC address", HFILL }},
436 { &hf_lacp_partner_key,
437 { "Partner Key", "lacp.partnerKey",
438 FT_UINT16, BASE_DEC, NULL, 0x0,
439 "The operational Key value assigned to the port associated with this link by the Partner", HFILL }},
441 { &hf_lacp_partner_port_priority,
442 { "Partner Port Priority", "lacp.partnerPortPriority",
443 FT_UINT16, BASE_DEC, NULL, 0x0,
444 "The priority assigned to the port by the Partner (via Management or Admin)", HFILL }},
446 { &hf_lacp_partner_port,
447 { "Partner Port", "lacp.partnerPort",
448 FT_UINT16, BASE_DEC, NULL, 0x0,
449 "The port number associated with this link assigned to the port by the Partner (via Management or Admin)", HFILL }},
451 { &hf_lacp_partner_state,
452 { "Partner State", "lacp.partnerState",
453 FT_UINT8, BASE_HEX, NULL, 0x0,
454 "The Partner's state variables for the port, encoded as bits within a single octet", HFILL }},
456 { &hf_lacp_flags_p_activity,
457 { "LACP Activity", "lacp.partnerState.activity",
458 FT_BOOLEAN, 8, TFS(&tfs_yes_no), LACPDU_FLAGS_ACTIVITY,
459 "Activity control value for this link. Active = 1, Passive = 0", HFILL }},
461 { &hf_lacp_flags_p_timeout,
462 { "LACP Timeout", "lacp.partnerState.timeout",
463 FT_BOOLEAN, 8, TFS(&tfs_yes_no), LACPDU_FLAGS_TIMEOUT,
464 "Timeout control value for this link. Short Timeout = 1, Long Timeout = 0", HFILL }},
466 { &hf_lacp_flags_p_aggregation,
467 { "Aggregation", "lacp.partnerState.aggregation",
468 FT_BOOLEAN, 8, TFS(&tfs_yes_no), LACPDU_FLAGS_AGGREGATION,
469 "Aggregatable = 1, Individual = 0", HFILL }},
471 { &hf_lacp_flags_p_sync,
472 { "Synchronization", "lacp.partnerState.synchronization",
473 FT_BOOLEAN, 8, TFS(&tfs_yes_no), LACPDU_FLAGS_SYNC,
474 "In Sync = 1, Out of Sync = 0", HFILL }},
476 { &hf_lacp_flags_p_collecting,
477 { "Collecting", "lacp.partnerState.collecting",
478 FT_BOOLEAN, 8, TFS(&tfs_yes_no), LACPDU_FLAGS_COLLECTING,
479 "Collection of incoming frames is: Enabled = 1, Disabled = 0", HFILL }},
481 { &hf_lacp_flags_p_distrib,
482 { "Distributing", "lacp.partnerState.distributing",
483 FT_BOOLEAN, 8, TFS(&tfs_yes_no), LACPDU_FLAGS_DISTRIB,
484 "Distribution of outgoing frames is: Enabled = 1, Disabled = 0", HFILL }},
486 { &hf_lacp_flags_p_defaulted,
487 { "Defaulted", "lacp.partnerState.defaulted",
488 FT_BOOLEAN, 8, TFS(&tfs_yes_no), LACPDU_FLAGS_DEFAULTED,
489 "1 = Actor Rx machine is using DEFAULT Partner info, 0 = using info in Rx'd LACPDU", HFILL }},
491 { &hf_lacp_flags_p_expired,
492 { "Expired", "lacp.partnerState.expired",
493 FT_BOOLEAN, 8, TFS(&tfs_yes_no), LACPDU_FLAGS_EXPIRED,
494 "1 = Actor Rx machine is EXPIRED, 0 = is NOT EXPIRED", HFILL }},
496 { &hf_lacp_partner_reserved,
497 { "Reserved", "lacp.reserved",
498 FT_BYTES, BASE_NONE, NULL, 0x0,
501 { &hf_lacp_coll_type,
502 { "Collector Information", "lacp.collectorInfo",
503 FT_UINT8, BASE_HEX, NULL, 0x0,
504 "TLV type = Collector", HFILL }},
506 { &hf_lacp_coll_info_len,
507 { "Collector Information Length", "lacp.collectorInfoLen",
508 FT_UINT8, BASE_HEX, NULL, 0x0,
509 "The length of the Collector TLV", HFILL }},
511 { &hf_lacp_coll_max_delay,
512 { "Collector Max Delay", "lacp.collectorMaxDelay",
513 FT_UINT16, BASE_DEC, NULL, 0x0,
514 "The max delay of the station tx'ing the LACPDU (in tens of usecs)", HFILL }},
516 { &hf_lacp_coll_reserved,
517 { "Reserved", "lacp.coll_reserved",
518 FT_BYTES, BASE_NONE, NULL, 0x0,
521 { &hf_lacp_term_type,
522 { "Terminator Information", "lacp.termInfo",
523 FT_UINT8, BASE_HEX, NULL, 0x0,
524 "TLV type = Terminator", HFILL }},
527 { "Terminator Length", "lacp.termLen",
528 FT_UINT8, BASE_HEX, NULL, 0x0,
529 "The length of the Terminator TLV", HFILL }},
531 { &hf_lacp_term_reserved,
532 { "Reserved", "lacp.term_reserved",
533 FT_BYTES, BASE_NONE, NULL, 0x0,
537 /* Setup protocol subtree array */
539 static gint *ett[] = {
545 /* Register the protocol name and description */
547 proto_lacp = proto_register_protocol("LACP", "Link Aggregation Control Protocol", "lacp");
549 /* Required function calls to register the header fields and subtrees used */
551 proto_register_field_array(proto_lacp, hf, array_length(hf));
552 proto_register_subtree_array(ett, array_length(ett));
556 proto_reg_handoff_lacp(void)
558 dissector_handle_t lacp_handle;
560 lacp_handle = create_dissector_handle(dissect_lacp, proto_lacp);
561 dissector_add_uint("slow.subtype", LACP_SUBTYPE, lacp_handle);
565 * Editor modelines - http://www.wireshark.org/tools/modelines.html
570 * indent-tabs-mode: nil
573 * vi: set shiftwidth=4 tabstop=8 expandtab:
574 * :indentSize=4:tabSize=8:noTabs=true: