Coverage Report

Created: 2026-06-30 07:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-lacp.c
Line
Count
Source
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
5
 *
6
 * Copyright 2002 Steve Housley <steve_housley@3com.com>
7
 *
8
 * Wireshark - Network traffic analyzer
9
 * By Gerald Combs <gerald@wireshark.org>
10
 * Copyright 1998 Gerald Combs
11
 *
12
 * SPDX-License-Identifier: GPL-2.0-or-later
13
 */
14
15
#include "config.h"
16
17
#include <epan/etypes.h>
18
#include <epan/packet.h>
19
#include <epan/to_str.h>
20
#include <epan/expert.h>
21
#include <epan/tfs.h>
22
#include <wsutil/array.h>
23
#include "packet-slowprotocols.h"
24
25
/* General declarations */
26
void proto_register_lacp(void);
27
void proto_reg_handoff_lacp(void);
28
29
static dissector_handle_t lacp_handle;
30
31
115
#define VLACP_MAGIC_LACP 0x01010114
32
115
#define VLACP_MAGIC_MARKER 0x02010114
33
34
/* TLV Types */
35
610
#define LACPDU_TYPE_TERMINATOR      0x00
36
115
#define LACPDU_TYPE_ACTOR_INFORMATION   0x01
37
115
#define LACPDU_TYPE_PARTNER_INFORMATION   0x02
38
115
#define LACPDU_TYPE_COLLECTOR_INFORMATION 0x03
39
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 }
46
};
47
48
/* Actor and Partner Flag bits */
49
28
#define LACPDU_FLAGS_ACTIVITY           0x01
50
28
#define LACPDU_FLAGS_TIMEOUT            0x02
51
28
#define LACPDU_FLAGS_AGGREGATION        0x04
52
28
#define LACPDU_FLAGS_SYNC               0x08
53
28
#define LACPDU_FLAGS_COLLECTING         0x10
54
28
#define LACPDU_FLAGS_DISTRIB            0x20
55
28
#define LACPDU_FLAGS_DEFAULTED          0x40
56
28
#define LACPDU_FLAGS_EXPIRED            0x80
57
58
/* Initialise the protocol and registered fields */
59
static int proto_lacp;
60
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;
65
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;
82
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;
99
100
static int hf_lacp_coll_max_delay;
101
static int hf_lacp_coll_reserved;
102
103
static int hf_lacp_pad;
104
105
static int hf_lacp_vendor;
106
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;
113
114
115
/* Initialise the subtree pointers */
116
static int ett_lacp;
117
static int ett_lacp_a_flags;
118
static int ett_lacp_p_flags;
119
120
/* Expert Items */
121
static expert_field ei_lacp_wrong_tlv_type;
122
static expert_field ei_lacp_wrong_tlv_length;
123
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" };
128
129
static const char * lacp_state_flags_to_str(wmem_allocator_t *scope, uint32_t value)
130
202
{
131
202
    wmem_strbuf_t *buf = wmem_strbuf_new(scope, "");
132
202
    const unsigned int flags_count = 8;
133
202
    static const char first_letters[] = "EFDCSGSA";
134
202
    unsigned int i;
135
136
1.81k
    for (i = 0; i < flags_count; i++) {
137
1.61k
        if (((value >> (flags_count - 1 - i)) & 1)) {
138
714
            wmem_strbuf_append_c(buf, first_letters[i]);
139
902
        } else {
140
902
            wmem_strbuf_append_c(buf, '*');
141
902
        }
142
1.61k
    }
143
144
202
    return wmem_strbuf_finalize(buf);
145
202
}
146
147
/*
148
 * Name: dissect_lacp
149
 *
150
 * Description:
151
 *    This function is used to dissect the Link Aggregation Control Protocol
152
 *    defined in IEEE 802.1AX
153
 *
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).
158
 *
159
 * Return Values: None
160
 *
161
 * Notes:
162
 */
163
static int
164
dissect_lacp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
165
115
{
166
115
    int          offset = 0, length_remaining;
167
115
    unsigned     tlv_type, tlv_length;
168
115
    unsigned     version, port, key;
169
115
    const char   *sysidstr, *flagstr;
170
115
    uint32_t     protodetect;
171
115
    uint8_t      is_vlacp;
172
173
115
    proto_tree *lacp_tree;
174
115
    proto_item *lacp_item, *tlv_type_item, *tlv_length_item;
175
115
    proto_item *ti;
176
177
115
    static int * const actor_flags[] = {
178
115
        &hf_lacp_flags_a_activity,
179
115
        &hf_lacp_flags_a_timeout,
180
115
        &hf_lacp_flags_a_aggregation,
181
115
        &hf_lacp_flags_a_sync,
182
115
        &hf_lacp_flags_a_collecting,
183
115
        &hf_lacp_flags_a_distrib,
184
115
        &hf_lacp_flags_a_defaulted,
185
115
        &hf_lacp_flags_a_expired,
186
115
        NULL
187
115
    };
188
115
    static int * const partner_flags[] = {
189
115
        &hf_lacp_flags_p_activity,
190
115
        &hf_lacp_flags_p_timeout,
191
115
        &hf_lacp_flags_p_aggregation,
192
115
        &hf_lacp_flags_p_sync,
193
115
        &hf_lacp_flags_p_collecting,
194
115
        &hf_lacp_flags_p_distrib,
195
115
        &hf_lacp_flags_p_defaulted,
196
115
        &hf_lacp_flags_p_expired,
197
115
        NULL
198
115
    };
199
200
115
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "LACP");
201
115
    col_set_str(pinfo->cinfo, COL_INFO, "Link Aggregation Control Protocol");
202
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
209
     */
210
211
115
    protodetect = tvb_get_ntohl(tvb, 0);
212
115
    if ((protodetect == VLACP_MAGIC_LACP) || (protodetect == VLACP_MAGIC_MARKER)) {
213
0
      is_vlacp = 1;
214
      /* Add vLACP Heading */
215
0
      lacp_item = proto_tree_add_protocol_format(tree, proto_lacp, tvb,
216
0
                                                 0, -1, "Virtual Link Aggregation Control Protocol");
217
115
    } else {
218
115
      is_vlacp = 0;
219
      /* Add LACP Heading - Note: 1 byte for slowprotocol has been consumed already */
220
115
      lacp_item = proto_tree_add_protocol_format(tree, proto_lacp, tvb,
221
115
                                                 0, -1, "Link Aggregation Control Protocol");
222
115
    }
223
115
    lacp_tree = proto_item_add_subtree(lacp_item, ett_lacp);
224
225
115
    if (is_vlacp == 1) {
226
0
      proto_tree_add_item(lacp_tree, hf_lacp_vlacp_subtype, tvb, offset, 1, ENC_NA);
227
0
      offset += 1;
228
0
    }
229
230
    /* Version Number */
231
232
115
    proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_version, tvb, offset, 1, ENC_NA, &version);
233
115
    offset += 1;
234
235
115
    col_add_fstr(pinfo->cinfo, COL_INFO, "v%d", version);
236
237
    /* Actor */
238
239
115
    tlv_type_item = proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN, &tlv_type);
240
115
    offset += 1;
241
242
115
    tlv_length_item = proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_tlv_length, tvb, offset, 1, ENC_BIG_ENDIAN, &tlv_length);
243
115
    offset += 1;
244
245
115
    if (tlv_type != LACPDU_TYPE_ACTOR_INFORMATION) {
246
113
        expert_add_info(pinfo, tlv_type_item, &ei_lacp_wrong_tlv_type);
247
113
    }
248
115
    if (tlv_length != 20) {
249
115
        expert_add_info(pinfo, tlv_length_item, &ei_lacp_wrong_tlv_length);
250
115
    }
251
252
115
    proto_tree_add_item(lacp_tree, hf_lacp_actor_sysid_priority, tvb, offset, 2, ENC_BIG_ENDIAN);
253
115
    offset += 2;
254
255
115
    proto_tree_add_item(lacp_tree, hf_lacp_actor_sysid, tvb, offset, 6, ENC_NA);
256
115
    sysidstr = tvb_ether_to_str(pinfo->pool, tvb, offset);
257
115
    offset += 6;
258
259
115
    proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_actor_key, tvb, offset, 2, ENC_BIG_ENDIAN, &key);
260
115
    offset += 2;
261
262
115
    proto_tree_add_item(lacp_tree, hf_lacp_actor_port_priority, tvb, offset, 2, ENC_BIG_ENDIAN);
263
115
    offset += 2;
264
265
115
    proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_actor_port, tvb, offset, 2, ENC_BIG_ENDIAN, &port);
266
115
    offset += 2;
267
268
115
    proto_tree_add_bitmask_with_flags(lacp_tree, tvb, offset, hf_lacp_actor_state,
269
115
                           ett_lacp_a_flags, actor_flags, ENC_NA, BMT_NO_INT|BMT_NO_TFS|BMT_NO_FALSE);
270
115
    flagstr = lacp_state_flags_to_str(pinfo->pool, tvb_get_uint8(tvb, offset));
271
115
    ti = proto_tree_add_string(lacp_tree, hf_lacp_actor_state_str, tvb, offset, 1, flagstr);
272
115
    proto_item_set_generated(ti);
273
115
    offset += 1;
274
275
115
    proto_tree_add_item(lacp_tree, hf_lacp_actor_reserved, tvb, offset, 3, ENC_NA);
276
115
    offset += 3;
277
278
115
    col_append_fstr(pinfo->cinfo, COL_INFO, " ACTOR %s P: %d K: %d %s", sysidstr, port, key, flagstr);
279
280
    /* Partner */
281
282
115
    tlv_type_item = proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN, &tlv_type);
283
115
    offset += 1;
284
285
115
    tlv_length_item = proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_tlv_length, tvb, offset, 1, ENC_BIG_ENDIAN, &tlv_length);
286
115
    offset += 1;
287
288
115
    if (tlv_type != LACPDU_TYPE_PARTNER_INFORMATION) {
289
103
        expert_add_info(pinfo, tlv_type_item, &ei_lacp_wrong_tlv_type);
290
103
    }
291
115
    if (tlv_length != 20) {
292
104
        expert_add_info(pinfo, tlv_length_item, &ei_lacp_wrong_tlv_length);
293
104
    }
294
295
115
    proto_tree_add_item(lacp_tree, hf_lacp_partner_sysid_priority, tvb, offset, 2, ENC_BIG_ENDIAN);
296
115
    offset += 2;
297
298
115
    proto_tree_add_item(lacp_tree, hf_lacp_partner_sysid, tvb, offset, 6, ENC_NA);
299
115
    sysidstr = tvb_ether_to_str(pinfo->pool, tvb, offset);
300
115
    offset += 6;
301
302
115
    proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_partner_key, tvb, offset, 2, ENC_BIG_ENDIAN, &key);
303
115
    offset += 2;
304
305
115
    proto_tree_add_item(lacp_tree, hf_lacp_partner_port_priority, tvb, offset, 2, ENC_BIG_ENDIAN);
306
115
    offset += 2;
307
308
115
    proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_partner_port, tvb, offset, 2, ENC_BIG_ENDIAN, &port);
309
115
    offset += 2;
310
311
115
    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
115
    flagstr = lacp_state_flags_to_str(pinfo->pool, tvb_get_uint8(tvb, offset));
313
115
    ti = proto_tree_add_string(lacp_tree, hf_lacp_partner_state_str, tvb, offset, 1, flagstr);
314
115
    proto_item_set_generated(ti);
315
115
    offset += 1;
316
317
115
    proto_tree_add_item(lacp_tree, hf_lacp_partner_reserved, tvb, offset, 3, ENC_NA);
318
115
    offset += 3;
319
320
115
    col_append_fstr(pinfo->cinfo, COL_INFO, " PARTNER %s P: %d K: %d %s", sysidstr, port, key, flagstr);
321
322
    /* Collector */
323
324
115
    tlv_type_item = proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN, &tlv_type);
325
115
    offset += 1;
326
327
115
    tlv_length_item = proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_tlv_length, tvb, offset, 1, ENC_BIG_ENDIAN, &tlv_length);
328
115
    offset += 1;
329
330
115
    if (tlv_type != LACPDU_TYPE_COLLECTOR_INFORMATION) {
331
75
        expert_add_info(pinfo, tlv_type_item, &ei_lacp_wrong_tlv_type);
332
75
    }
333
115
    if (tlv_length != 16) {
334
91
        expert_add_info(pinfo, tlv_length_item, &ei_lacp_wrong_tlv_length);
335
91
    }
336
337
115
    proto_tree_add_item(lacp_tree, hf_lacp_coll_max_delay, tvb, offset, 2, ENC_BIG_ENDIAN);
338
115
    offset += 2;
339
340
115
    proto_tree_add_item(lacp_tree, hf_lacp_coll_reserved, tvb, offset, 12, ENC_NA);
341
115
    offset += 12;
342
343
    /* col_append_fstr(pinfo->cinfo, COL_INFO, " COLLECTOR"); */
344
345
    /* Other TLVs (LACP version 2) */
346
347
115
    proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN, &tlv_type);
348
115
    offset += 1;
349
350
115
    tlv_length_item = proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_tlv_length, tvb, offset, 1, ENC_BIG_ENDIAN, &tlv_length);
351
115
    offset += 1;
352
353
305
    while (tlv_type != LACPDU_TYPE_TERMINATOR && tlv_length >= 2) {
354
190
        offset += (tlv_length - 2);
355
190
        proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN, &tlv_type);
356
190
        offset += 1;
357
358
190
        tlv_length_item = proto_tree_add_item_ret_uint(lacp_tree, hf_lacp_tlv_length, tvb, offset, 1, ENC_BIG_ENDIAN, &tlv_length);
359
190
        offset += 1;
360
190
    }
361
362
    /* Terminator - already handled */
363
364
115
    if (tlv_length != 0) {
365
24
        expert_add_info(pinfo, tlv_length_item, &ei_lacp_wrong_tlv_length);
366
24
    }
367
368
    /* Pad */
369
370
115
    if (offset < (128 - 1 - 18)) {  /* LACPv1 fixed size - Eth */
371
37
        proto_tree_add_item(lacp_tree, hf_lacp_pad, tvb, offset, (128 - 1 - 18)-offset, ENC_NA);
372
37
        offset += ((128 - 1 - 18)-offset);
373
37
    }
374
375
    /* HP specific stuff (in violation of standard) */
376
377
115
    length_remaining = tvb_reported_length_remaining(tvb, offset);
378
115
    if (length_remaining) {
379
380
        /* HP LACP MAD IRF, first bytes is always 0x64 and second bytes is the rest of length */
381
33
        if (length_remaining > 2 && (tvb_get_uint8(tvb, offset) == 0x64) && ((length_remaining -2) == tvb_get_uint8(tvb, offset+1)) )
382
0
        {
383
0
            proto_tree_add_item(lacp_tree, hf_lacp_vendor, tvb, offset, length_remaining, ENC_NA);
384
0
            proto_tree_add_item(lacp_tree, hf_lacp_vendor_hp_unknown, tvb, offset, 1, ENC_NA);
385
0
            offset += 1;
386
387
0
            proto_tree_add_item(lacp_tree, hf_lacp_vendor_hp_length, tvb, offset, 1, ENC_NA);
388
0
            offset += 1;
389
390
0
            proto_tree_add_item(lacp_tree, hf_lacp_vendor_hp_unknown, tvb, offset, 2, ENC_NA);
391
0
            offset += 2;
392
393
0
            proto_tree_add_item(lacp_tree, hf_lacp_vendor_hp_irf_domain, tvb, offset, 2, ENC_BIG_ENDIAN);
394
0
            offset += 2;
395
396
0
            proto_tree_add_item(lacp_tree, hf_lacp_vendor_hp_irf_mac, tvb, offset, 6, ENC_NA);
397
0
            offset += 6;
398
399
0
            proto_tree_add_item(lacp_tree, hf_lacp_vendor_hp_unknown, tvb, offset, 8, ENC_NA);
400
0
            offset += 8;
401
402
0
            proto_tree_add_item(lacp_tree, hf_lacp_vendor_hp_irf_switch, tvb, offset, 2, ENC_BIG_ENDIAN);
403
0
            offset += 2;
404
405
0
            proto_tree_add_item(lacp_tree, hf_lacp_vendor_hp_irf_port, tvb, offset, 2, ENC_BIG_ENDIAN);
406
0
            offset += 2;
407
408
0
            proto_tree_add_item(lacp_tree, hf_lacp_vendor_hp_unknown, tvb, offset, 2, ENC_NA);
409
33
        } else {
410
            /* Not the HP specific extras.  Don't claim the remaining data.  It may actually be an ethernet trailer. */
411
33
            set_actual_length(tvb, tvb_captured_length(tvb) - length_remaining);
412
33
            proto_item_set_len(lacp_item, tvb_captured_length(tvb));
413
33
        }
414
33
    }
415
115
    return tvb_captured_length(tvb);
416
115
}
417
418
/* Register the protocol with Wireshark */
419
void
420
proto_register_lacp(void)
421
14
{
422
/* Setup list of header fields */
423
424
14
    static hf_register_info hf[] = {
425
14
        { &hf_lacp_vlacp_subtype,
426
14
          { "vLACP subtype",          "lacp.vlacp_subtype",
427
14
            FT_UINT8,    BASE_DEC,    NULL,    0x0,
428
14
            "Avaya vlacp unused lacp subtype byte", HFILL }},
429
430
14
        { &hf_lacp_version,
431
14
          { "LACP Version",          "lacp.version",
432
14
            FT_UINT8,    BASE_HEX,    NULL,    0x0,
433
14
            NULL, HFILL }},
434
435
14
        { &hf_lacp_tlv_type,
436
14
          { "TLV Type",               "lacp.tlv_type",
437
14
            FT_UINT8,    BASE_HEX,    VALS(lacp_type_vals),    0x0,
438
14
            NULL, HFILL }},
439
440
14
        { &hf_lacp_tlv_length,
441
14
          { "TLV Length",             "lacp.tlv_length",
442
14
            FT_UINT8,    BASE_HEX,    NULL,    0x0,
443
14
            NULL, HFILL }},
444
445
14
        { &hf_lacp_actor_sysid_priority,
446
14
          { "Actor System Priority",  "lacp.actor.sys_priority",
447
14
            FT_UINT16,    BASE_DEC,    NULL,    0x0,
448
14
            NULL, HFILL }},
449
450
14
        { &hf_lacp_actor_sysid,
451
14
          { "Actor System ID",         "lacp.actor.sysid",
452
14
            FT_ETHER,    BASE_NONE,    NULL,    0x0,
453
14
            NULL, HFILL }},
454
455
14
        { &hf_lacp_actor_key,
456
14
          { "Actor Key",            "lacp.actor.key",
457
14
            FT_UINT16,    BASE_DEC,    NULL,    0x0,
458
14
            NULL, HFILL }},
459
460
14
        { &hf_lacp_actor_port_priority,
461
14
          { "Actor Port Priority",            "lacp.actor.port_priority",
462
14
            FT_UINT16,    BASE_DEC,    NULL,    0x0,
463
14
            NULL, HFILL }},
464
465
14
        { &hf_lacp_actor_port,
466
14
          { "Actor Port",            "lacp.actor.port",
467
14
            FT_UINT16,    BASE_DEC,    NULL,    0x0,
468
14
            NULL, HFILL }},
469
470
14
        { &hf_lacp_actor_state,
471
14
          { "Actor State",            "lacp.actor.state",
472
14
            FT_UINT8,    BASE_HEX,    NULL,    0x0,
473
14
            NULL, HFILL }},
474
475
14
        { &hf_lacp_actor_state_str,
476
14
          { "Actor State Flags",            "lacp.actor.state_str",
477
14
            FT_STRING,    BASE_NONE,    NULL,    0x0,
478
14
            NULL, HFILL }},
479
480
14
        { &hf_lacp_flags_a_activity,
481
14
          { "LACP Activity",        "lacp.actor.state.activity",
482
14
            FT_BOOLEAN,    8,        TFS(&tfs_active_passive),    LACPDU_FLAGS_ACTIVITY,
483
14
            NULL, HFILL }},
484
485
14
        { &hf_lacp_flags_a_timeout,
486
14
          { "LACP Timeout",        "lacp.actor.state.timeout",
487
14
            FT_BOOLEAN,    8,        TFS(&tfs_short_long_timeout),    LACPDU_FLAGS_TIMEOUT,
488
14
            NULL, HFILL }},
489
490
14
        { &hf_lacp_flags_a_aggregation,
491
14
          { "Aggregation",        "lacp.actor.state.aggregation",
492
14
            FT_BOOLEAN,    8,        TFS(&tfs_aggregatable_individual),    LACPDU_FLAGS_AGGREGATION,
493
14
            NULL, HFILL }},
494
495
14
        { &hf_lacp_flags_a_sync,
496
14
          { "Synchronization",        "lacp.actor.state.synchronization",
497
14
            FT_BOOLEAN,    8,        TFS(&tfs_in_sync_out_sync),    LACPDU_FLAGS_SYNC,
498
14
            NULL, HFILL }},
499
500
14
        { &hf_lacp_flags_a_collecting,
501
14
          { "Collecting",        "lacp.actor.state.collecting",
502
14
            FT_BOOLEAN,    8,        TFS(&tfs_enabled_disabled),    LACPDU_FLAGS_COLLECTING,
503
14
            NULL, HFILL }},
504
505
14
        { &hf_lacp_flags_a_distrib,
506
14
          { "Distributing",        "lacp.actor.state.distributing",
507
14
            FT_BOOLEAN,    8,        TFS(&tfs_enabled_disabled),    LACPDU_FLAGS_DISTRIB,
508
14
            NULL, HFILL }},
509
510
14
        { &hf_lacp_flags_a_defaulted,
511
14
          { "Defaulted",        "lacp.actor.state.defaulted",
512
14
            FT_BOOLEAN,    8,        TFS(&tfs_yes_no),    LACPDU_FLAGS_DEFAULTED,
513
14
            "1 = Actor Rx machine is using DEFAULT Partner info, 0 = using info in Rx'd LACPDU", HFILL }},
514
515
14
        { &hf_lacp_flags_a_expired,
516
14
          { "Expired",        "lacp.actor.state.expired",
517
14
            FT_BOOLEAN,    8,        TFS(&tfs_yes_no),    LACPDU_FLAGS_EXPIRED,
518
14
            NULL, HFILL }},
519
520
14
        { &hf_lacp_actor_reserved,
521
14
          { "Reserved",        "lacp.actor.reserved",
522
14
            FT_BYTES,    BASE_NONE,    NULL,    0x0,
523
14
            NULL, HFILL }},
524
525
14
        { &hf_lacp_partner_sysid_priority,
526
14
          { "Partner System Priority",  "lacp.partner.sys_priority",
527
14
            FT_UINT16,    BASE_DEC,    NULL,    0x0,
528
14
            NULL, HFILL }},
529
530
14
        { &hf_lacp_partner_sysid,
531
14
          { "Partner System",            "lacp.partner.sysid",
532
14
            FT_ETHER,    BASE_NONE,    NULL,    0x0,
533
14
            NULL, HFILL }},
534
535
14
        { &hf_lacp_partner_key,
536
14
          { "Partner Key",            "lacp.partner.key",
537
14
            FT_UINT16,    BASE_DEC,    NULL,    0x0,
538
14
            NULL, HFILL }},
539
540
14
        { &hf_lacp_partner_port_priority,
541
14
          { "Partner Port Priority",            "lacp.partner.port_priority",
542
14
            FT_UINT16,    BASE_DEC,    NULL,    0x0,
543
14
            NULL, HFILL }},
544
545
14
        { &hf_lacp_partner_port,
546
14
          { "Partner Port",            "lacp.partner.port",
547
14
            FT_UINT16,    BASE_DEC,    NULL,    0x0,
548
14
            "The port number associated with this link assigned to the port by the Partner (via Management or Admin)", HFILL }},
549
550
14
        { &hf_lacp_partner_state,
551
14
          { "Partner State",            "lacp.partner.state",
552
14
            FT_UINT8,    BASE_HEX,    NULL,    0x0,
553
14
            NULL, HFILL }},
554
555
14
        { &hf_lacp_partner_state_str,
556
14
          { "Partner State Flags",            "lacp.partner.state_str",
557
14
            FT_STRING,    BASE_NONE,    NULL,    0x0,
558
14
            NULL, HFILL }},
559
560
14
        { &hf_lacp_flags_p_activity,
561
14
          { "LACP Activity",        "lacp.partner.state.activity",
562
14
            FT_BOOLEAN,    8,        TFS(&tfs_active_passive),    LACPDU_FLAGS_ACTIVITY,
563
14
            NULL, HFILL }},
564
565
14
        { &hf_lacp_flags_p_timeout,
566
14
          { "LACP Timeout",        "lacp.partner.state.timeout",
567
14
            FT_BOOLEAN,    8,        TFS(&tfs_short_long_timeout),    LACPDU_FLAGS_TIMEOUT,
568
14
            NULL, HFILL }},
569
570
14
        { &hf_lacp_flags_p_aggregation,
571
14
          { "Aggregation",        "lacp.partner.state.aggregation",
572
14
            FT_BOOLEAN,    8,        TFS(&tfs_aggregatable_individual),    LACPDU_FLAGS_AGGREGATION,
573
14
            NULL, HFILL }},
574
575
14
        { &hf_lacp_flags_p_sync,
576
14
          { "Synchronization",        "lacp.partner.state.synchronization",
577
14
            FT_BOOLEAN,    8,        TFS(&tfs_in_sync_out_sync),    LACPDU_FLAGS_SYNC,
578
14
            NULL, HFILL }},
579
580
14
        { &hf_lacp_flags_p_collecting,
581
14
          { "Collecting",        "lacp.partner.state.collecting",
582
14
            FT_BOOLEAN,    8,        TFS(&tfs_enabled_disabled),    LACPDU_FLAGS_COLLECTING,
583
14
            NULL, HFILL }},
584
585
14
        { &hf_lacp_flags_p_distrib,
586
14
          { "Distributing",        "lacp.partner.state.distributing",
587
14
            FT_BOOLEAN,    8,        TFS(&tfs_enabled_disabled),    LACPDU_FLAGS_DISTRIB,
588
14
            NULL, HFILL }},
589
590
14
        { &hf_lacp_flags_p_defaulted,
591
14
          { "Defaulted",        "lacp.partner.state.defaulted",
592
14
            FT_BOOLEAN,    8,        TFS(&tfs_yes_no),    LACPDU_FLAGS_DEFAULTED,
593
14
            "1 = Actor Rx machine is using DEFAULT Partner info, 0 = using info in Rx'd LACPDU", HFILL }},
594
595
14
        { &hf_lacp_flags_p_expired,
596
14
          { "Expired",        "lacp.partner.state.expired",
597
14
            FT_BOOLEAN,    8,        TFS(&tfs_yes_no),    LACPDU_FLAGS_EXPIRED,
598
14
            NULL, HFILL }},
599
600
14
        { &hf_lacp_partner_reserved,
601
14
          { "Reserved",        "lacp.partner.reserved",
602
14
            FT_BYTES,    BASE_NONE,    NULL,    0x0,
603
14
            NULL, HFILL }},
604
605
14
        { &hf_lacp_coll_max_delay,
606
14
          { "Collector Max Delay",  "lacp.collector.max_delay",
607
14
            FT_UINT16,    BASE_DEC,    NULL,    0x0,
608
14
            "The max delay of the station sending the LACPDU (in tens of usecs)", HFILL }},
609
610
14
        { &hf_lacp_coll_reserved,
611
14
          { "Reserved",        "lacp.coll_reserved",
612
14
            FT_BYTES,    BASE_NONE,    NULL,    0x0,
613
14
            NULL, HFILL }},
614
615
14
        { &hf_lacp_pad,
616
14
          { "Pad",        "lacp.pad",
617
14
            FT_BYTES,    BASE_NONE,    NULL,    0x0,
618
14
            NULL, HFILL }},
619
620
14
        { &hf_lacp_vendor,
621
14
          { "Unknown vendor",        "lacp.vendor",
622
14
            FT_BYTES,    BASE_NONE,    NULL,    0x0,
623
14
            "Some extra bytes (Vendor Specific ?)", HFILL }},
624
625
        /* HP IRF MAD LACP */
626
14
        { &hf_lacp_vendor_hp_length,
627
14
          { "Length",        "lacp.vendor.hp.length",
628
14
            FT_UINT8,    BASE_DEC,    NULL,    0x0,
629
14
            "The length of HP TLV", HFILL }},
630
14
        { &hf_lacp_vendor_hp_irf_domain,
631
14
          { "IRF Domain",        "lacp.vendor.hp.irf_domain",
632
14
            FT_UINT16,    BASE_DEC,    NULL,    0x0,
633
14
            NULL, HFILL }},
634
14
        { &hf_lacp_vendor_hp_irf_mac,
635
14
          { "IRF MAC",        "lacp.vendor.hp.irf_mac",
636
14
            FT_ETHER,    BASE_NONE,    NULL,    0x0,
637
14
            NULL, HFILL }},
638
14
        { &hf_lacp_vendor_hp_irf_switch,
639
14
          { "IRF Switch",        "lacp.vendor.hp.irf_switch",
640
14
            FT_UINT16,    BASE_DEC,    NULL,    0x0,
641
14
            "Number of switch on the IRF stack", HFILL }},
642
14
        { &hf_lacp_vendor_hp_irf_port,
643
14
          { "IRF Port",        "lacp.vendor.hp.irf_port",
644
14
            FT_UINT16,    BASE_DEC,    NULL,    0x0,
645
14
            "Stack ID where the LACP is attached", HFILL }},
646
14
        { &hf_lacp_vendor_hp_unknown,
647
14
          { "Unknown",        "lacp.vendor.hp.unknown",
648
14
            FT_BYTES,    BASE_NONE,    NULL,    0x0,
649
14
            NULL, HFILL }},
650
14
    };
651
652
    /* Setup protocol subtree array */
653
654
14
    static int *ett[] = {
655
14
        &ett_lacp,
656
14
        &ett_lacp_a_flags,
657
14
        &ett_lacp_p_flags,
658
14
    };
659
660
14
    static ei_register_info ei[] = {
661
14
    { &ei_lacp_wrong_tlv_type,   { "lacp.wrong_tlv_type",   PI_MALFORMED, PI_ERROR, "TLV is not expected type",   EXPFILL }},
662
14
    { &ei_lacp_wrong_tlv_length, { "lacp.wrong_tlv_length", PI_MALFORMED, PI_ERROR, "TLV is not expected length", EXPFILL }},
663
14
    };
664
665
14
    expert_module_t* expert_lacp;
666
667
668
    /* Register the protocol name and description */
669
670
14
    proto_lacp = proto_register_protocol("Link Aggregation Control Protocol", "LACP", "lacp");
671
672
    /* Required function calls to register the header fields and subtrees used */
673
674
14
    proto_register_field_array(proto_lacp, hf, array_length(hf));
675
14
    proto_register_subtree_array(ett, array_length(ett));
676
14
    expert_lacp = expert_register_protocol(proto_lacp);
677
14
    expert_register_field_array(expert_lacp, ei, array_length(ei));
678
679
14
    lacp_handle = register_dissector("lacp", dissect_lacp, proto_lacp);
680
14
}
681
682
void
683
proto_reg_handoff_lacp(void)
684
14
{
685
14
    dissector_add_uint("slow.subtype", LACP_SUBTYPE, lacp_handle);
686
14
    dissector_add_uint("ethertype", ETHERTYPE_VLACP, lacp_handle);
687
14
}
688
689
/*
690
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
691
 *
692
 * Local variables:
693
 * c-basic-offset: 4
694
 * tab-width: 8
695
 * indent-tabs-mode: nil
696
 * End:
697
 *
698
 * vi: set shiftwidth=4 tabstop=8 expandtab:
699
 * :indentSize=4:tabSize=8:noTabs=true:
700
 */