Coverage Report

Created: 2026-08-14 06:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-avsp.c
Line
Count
Source
1
/* packet-avsp.c
2
 * Arista Vendor Specific ethertype Protocol (AVSP)
3
 *
4
 * Copyright (c) 2018-2022 by Arista Networks
5
 * Author: Nikhil AP <nikhilap@arista.com>
6
 * Author: PMcL <peterm@arista.com>
7
 *
8
 * Wireshark - Network traffic analyzer
9
 * By Gerald Combs <gerald@wireshark.org>
10
 * Copyright 1999 Gerald Combs
11
 *
12
 * SPDX-License-Identifier: GPL-2.0-or-later
13
 */
14
15
 /* Arista Vendor-Specific EtherType Protocol Identifier
16
  *
17
  * Arista applied for, and received the assignment of, a vendor-specific EtherType Protocol Identifier in May of 2016. Details below:
18
  *
19
  * Ethertype number is: D28B
20
  * Issue date is: May 12, 2016
21
  *
22
  * Arista Subtype 0x0001 is a Timestamp L2 Header
23
  * Arista Subtype 0xCAFE is a TGen L2 header
24
  *
25
  * The timestamp L2 header consists of the following fields:
26
  *
27
  * Arista Vendor Specific Protocol EtherType (0xD28B)
28
  *     Two-byte protocol subtype of 0x0001
29
  *     Two-byte protocol version: 0x0010 for 64-bit timestamp and 0x0020 for 48-bit timestamp
30
  *     UTC timestamp value in IEEE 1588 time of day format (either 64-bit or 48-bit) with the lower 32-bits representing nanoseconds and upper bits representing seconds.
31
  *
32
  * The TGen L2 header consists of the following fields:
33
  *
34
  * Arista Vendor Specific Protocol EtherType (0xD28B)
35
  *     Two-byte protocol subtype of 0xCAFE
36
  *     Two-byte protocol version: 0x0001
37
  */
38
39
#include "config.h"
40
#include <epan/packet.h>
41
#include <epan/exceptions.h>
42
#include <epan/etypes.h>
43
#include <epan/expert.h>
44
#include <epan/address.h>
45
46
#include <wsutil/str_util.h>
47
48
#include "packet-eth.h"
49
50
0
#define ARISTA_SUBTYPE_TIMESTAMP 0x0001
51
52
0
#define ARISTA_TIMESTAMP_64_TAI 0x0010
53
0
#define ARISTA_TIMESTAMP_64_UTC 0x0110
54
0
#define ARISTA_TIMESTAMP_48_TAI 0x0020
55
0
#define ARISTA_TIMESTAMP_48_UTC 0x0120
56
0
#define ARISTA_TIMESTAMP_64_TAI_J2 0x0011
57
0
#define ARISTA_TIMESTAMP_64_UTC_J2 0x0111
58
0
#define ARISTA_TIMESTAMP_48_TAI_J2 0x0021
59
0
#define ARISTA_TIMESTAMP_48_UTC_J2 0x0121
60
61
0
#define ARISTA_SUBTYPE_GREENTAP 0x0003
62
63
0
#define ARISTA_GREENTAP_48_TAI 0x0020
64
0
#define ARISTA_GREENTAP_48_UTC 0x0120
65
66
0
#define ARISTA_SUBTYPE_GREENT 0x0004
67
68
0
#define ARISTA_GREENT_VER_1 0x0001
69
70
0
#define ARISTA_SUBTYPE_DZGRE_A  0x0007
71
72
0
#define ARISTA_DZGRE_A_VER_1 0x0001
73
74
0
#define ARISTA_SUBTYPE_DZGRE_B  0x0008
75
76
0
#define ARISTA_DZGRE_B_VER_1 0x0001
77
78
0
#define ARISTA_SUBTYPE_DZGRE_TS  0x0009
79
80
0
#define ARISTA_DZGRE_TS_64_TAI 0x0011
81
0
#define ARISTA_DZGRE_TS_64_UTC 0x0111
82
83
0
#define ARISTA_SUBTYPE_TGEN 0xCAFE
84
0
#define ARISTA_TGEN_VER_1 0x0001
85
86
0
#define ROUNDUP(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
87
88
void proto_reg_handoff_avsp(void);
89
void proto_register_avsp(void);
90
91
static dissector_handle_t avsp_handle;
92
static int proto_avsp;
93
94
/* sub trees */
95
static int ett_avsp;
96
static int ett_avsp_ts_48;
97
static int ett_avsp_ts_64;
98
static int ett_avsp_dzgre_a_hdr;
99
static int ett_avsp_dzgre_b_hdr;
100
static int ett_avsp_dzgre_ts_hdr;
101
static int ett_avsp_dzgre_ts_tai;
102
static int ett_avsp_dzgre_ts_utc;
103
static int ett_avsp_greent_hdr;
104
static int ett_avsp_greent_sample_hdr;
105
static int ett_avsp_greent_sample_data;
106
static int ett_avsp_tgen_hdr;
107
static int ett_avsp_tgen_hdr_ctrl;
108
static int ett_avsp_tgen_payload;
109
110
/* AVSP Timestamp subtype header fields */
111
static int hf_avsp_subtype;
112
static int hf_avsp_ts_version;
113
static int hf_avsp_ts_64_tai;
114
static int hf_avsp_ts_64_utc;
115
static int hf_avsp_ts_64_sec;
116
static int hf_avsp_ts_64_ns;
117
static int hf_avsp_ts_48_tai;
118
static int hf_avsp_ts_48_utc;
119
static int hf_avsp_ts_48_sec;
120
static int hf_avsp_ts_48_ns;
121
122
static int hf_avsp_etype;
123
static int hf_avsp_trailer;
124
125
/*
126
  GREENTAP Timestamping format
127
   0.............7...............15..............23..............31
128
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
129
  |   Protocol Subtype = 0x0003   |      Protocol Version         |
130
  +---------------+---------------+---------------+---------------+
131
  |          Session ID           |      Timestamp (seconds)      |
132
  +---------------+---------------+---------------+---------------+
133
  |0 0|                Timestamp (nanoseconds)                    |
134
  +---------------+---------------+---------------+---------------+
135
*/
136
137
/* AVSP GREENTAP subtype header fields */
138
static int hf_avsp_greentap_version;
139
static int hf_avsp_greentap_tai;
140
static int hf_avsp_greentap_utc;
141
static int hf_avsp_greentap_sec;
142
static int hf_avsp_greentap_ns;
143
144
/*
145
  GREENT subtype format
146
   0.............7...............15..............23..............31
147
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
148
  |   Protocol Subtype = 0x0004   |      Protocol Version         |
149
  +---------------+---------------+---------------+---------------+
150
  |         Session ID            |     Flags     | Sample Count  |
151
  +---------------+---------------+---------------+---------------+
152
153
  Each sample has a header of the format:
154
   0.............7...............15..............23..............31
155
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
156
  |           Length              |     IEEE 1588 TS (seconds)    |
157
  +---------------+---------------+---------------+---------------+
158
  |                   IEEE 1588 TS (nanoseconds)                  |
159
  +---------------+---------------+---------------+---------------+
160
  |                   Ingress Port (SNMP ifIndex)                 |
161
  +---------------+---------------+---------------+---------------+
162
  |                   Egress Port (SNMP ifIndex)                  |
163
  +---------------+---------------+---------------+---------------+
164
  |  Sample Rate (multiplier 1K)  |        Payload Checksum       |
165
  +---------------+---------------+---------------+---------------+
166
  |               Sample (padded to 4 byte boundary)              |
167
  +---------------+---------------+---------------+---------------+
168
*/
169
170
/* AVSP GREENT subtype header fields */
171
static int hf_avsp_greent_hdr;
172
static int hf_avsp_greent_version;
173
static int hf_avsp_greent_session;
174
static int hf_avsp_greent_flags;
175
static int hf_avsp_greent_sample_count;
176
177
/* GREENT sample header fields */
178
static int hf_avsp_greent_sample_hdr;
179
static int hf_avsp_greent_sample_len;
180
static int hf_avsp_greent_sample_sec;
181
static int hf_avsp_greent_sample_ns;
182
static int hf_avsp_greent_sample_ingress;
183
static int hf_avsp_greent_sample_egress;
184
static int hf_avsp_greent_sample_rate;
185
static int hf_avsp_greent_sample_sum;
186
static int hf_avsp_greent_sample_data;
187
188
/*
189
  DzGRE Plan A subtype format
190
   0.............7...............15..............23..............31
191
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
192
  |   Protocol Subtype = 0x0007   |      Protocol Version         |
193
  +---------------+---------------+---------------+---------------+
194
  |          Switch ID            |           Port ID             |
195
  +---------------+---------------+---------------+---------------+
196
  |          Policy ID            |           Reserved            |
197
  +---------------+---------------+---------------+---------------+
198
199
  DzGRE Plan B subtype format
200
   0.............7...............15..............23..............31
201
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
202
  |   Protocol Subtype = 0x0008   |      Protocol Version         |
203
  +---------------+---------------+---------------+---------------+
204
  |0 0 0 0|      Port ID          |0 0 0 0|     Policy ID         |
205
  +---------------+---------------+---------------+---------------+
206
207
  DzGRE with timestamping
208
   0.............7...............15..............23..............31
209
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
210
  |   Protocol Subtype = 0x0009   |      Protocol Version         |
211
  +---------------+---------------+---------------+---------------+
212
  |          Switch ID            |           Port ID             |
213
  +---------------+---------------+---------------+---------------+
214
  |          Policy ID            |           Reserved            |
215
  +---------------+---------------+---------------+---------------+
216
  |                  UTC Timestamp (seconds)                      |
217
  +---------------+---------------+---------------+---------------+
218
  |                  UTC Timestamp (nanoseconds)                  |
219
  +---------------+---------------+---------------+---------------+
220
*/
221
222
/* AVSP DzGRE header fields */
223
static int hf_avsp_dzgre_a_hdr;
224
static int hf_avsp_dzgre_a_version;
225
static int hf_avsp_dzgre_a_switch;
226
static int hf_avsp_dzgre_a_port;
227
static int hf_avsp_dzgre_a_policy;
228
static int hf_avsp_dzgre_a_reserved;
229
230
static int hf_avsp_dzgre_b_hdr;
231
static int hf_avsp_dzgre_b_version;
232
static int hf_avsp_dzgre_b_port;
233
static int hf_avsp_dzgre_b_policy;
234
235
static int hf_avsp_dzgre_ts_hdr;
236
static int hf_avsp_dzgre_ts_version;
237
static int hf_avsp_dzgre_ts_switch;
238
static int hf_avsp_dzgre_ts_port;
239
static int hf_avsp_dzgre_ts_policy;
240
static int hf_avsp_dzgre_ts_reserved;
241
static int hf_avsp_dzgre_ts_tai;
242
static int hf_avsp_dzgre_ts_utc;
243
static int hf_avsp_dzgre_ts_sec;
244
static int hf_avsp_dzgre_ts_ns;
245
246
/*
247
  TGen subtype format
248
   0.............7...............15..............23..............31
249
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
250
  |      Ethertype = 0xD28B       |   Protocol Subtype = 0xCAFE   |
251
  +---------------+---------------+---------------+---------------+
252
  |   Protocol Version = 0x0001   |      TGen Control Word        |
253
  +---------------+---------------+---------------+---------------+
254
  |     TGen Sequence Number      |      TGen Payload Length      |
255
  +---------------+---------------+---------------+---------------+
256
  |                        TGen Data Payload                      |
257
  +---------------+---------------+---------------+---------------+
258
  |                              ...                              |
259
  +---------------+---------------+---------------+---------------+
260
  |                        TGen Data Payload                      |
261
  +---------------+---------------+---------------+---------------+
262
*/
263
264
/* AVSP TGen subtype header fields */
265
static int hf_avsp_tgen_version;
266
static int hf_avsp_tgen_hdr;
267
static int hf_avsp_tgen_hdr_ctrl;
268
static int hf_avsp_tgen_hdr_ctrl_fcs_inverted;
269
static int hf_avsp_tgen_hdr_ctrl_reserved;
270
static int hf_avsp_tgen_hdr_seq_num;
271
static int hf_avsp_tgen_hdr_payload_len;
272
static int hf_avsp_tgen_payload;
273
static int hf_avsp_tgen_payload_data;
274
275
static int* const avsp_tgen_ctrl[] = {
276
    &hf_avsp_tgen_hdr_ctrl_fcs_inverted,
277
    &hf_avsp_tgen_hdr_ctrl_reserved,
278
    NULL
279
};
280
281
static dissector_handle_t ethertype_handle;
282
283
static const value_string arista_subtypes[] = {
284
    {ARISTA_SUBTYPE_TIMESTAMP, "timestamp"},
285
    {ARISTA_SUBTYPE_GREENTAP, "GRE TAP"},
286
    {ARISTA_SUBTYPE_GREENT, "Postcard"},
287
    {ARISTA_SUBTYPE_DZGRE_A, "DzGRE (plan A)"},
288
    {ARISTA_SUBTYPE_DZGRE_B, "DzGRE (plan B)"},
289
    {ARISTA_SUBTYPE_DZGRE_TS, "DzGRE (timestamped)"},
290
    {ARISTA_SUBTYPE_TGEN, "TGen"},
291
    {0, NULL}
292
};
293
294
static const value_string ts_versions[] = {
295
    {ARISTA_TIMESTAMP_64_TAI, "010"},
296
    {ARISTA_TIMESTAMP_64_UTC, "110"},
297
    {ARISTA_TIMESTAMP_48_TAI, "020"},
298
    {ARISTA_TIMESTAMP_48_UTC, "120"},
299
    {ARISTA_TIMESTAMP_64_TAI_J2, "011"},
300
    {ARISTA_TIMESTAMP_64_UTC_J2, "111"},
301
    {ARISTA_TIMESTAMP_48_TAI_J2, "021"},
302
    {ARISTA_TIMESTAMP_48_UTC_J2, "121"},
303
    {0, NULL}
304
};
305
306
static const value_string greentap_versions[] = {
307
    {ARISTA_GREENTAP_48_TAI, "48bit TAI"},
308
    {ARISTA_GREENTAP_48_UTC, "48bit UTC"},
309
    {0, NULL}
310
};
311
312
static const value_string greent_versions[] = {
313
    {ARISTA_GREENT_VER_1, "1"},
314
    {0, NULL}
315
};
316
317
static const value_string dzgre_a_versions[] = {
318
    {ARISTA_DZGRE_A_VER_1, "1"},
319
    {0, NULL}
320
};
321
322
static const value_string dzgre_b_versions[] = {
323
    {ARISTA_DZGRE_A_VER_1, "1"},
324
    {0, NULL}
325
};
326
327
static const value_string dzgre_ts_versions[] = {
328
    {ARISTA_DZGRE_TS_64_TAI, "64bit TAI"},
329
    {ARISTA_DZGRE_TS_64_UTC, "64bit UTC"},
330
    {0, NULL}
331
};
332
333
static const value_string tgen_versions[] = {
334
    {ARISTA_TGEN_VER_1, "1"},
335
    {0, NULL}
336
};
337
338
static expert_field ei_avsp_unknown_subtype;
339
static expert_field ei_avsp_ts_unknown_version;
340
static expert_field ei_avsp_greentap_unknown_version;
341
static expert_field ei_avsp_greent_unknown_version;
342
static expert_field ei_avsp_dzgre_a_unknown_version;
343
static expert_field ei_avsp_dzgre_b_unknown_version;
344
static expert_field ei_avsp_dzgre_ts_unknown_version;
345
static expert_field ei_avsp_tgen_unknown_version;
346
347
static int
348
dissect_avsp(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data _U_)
349
2
{
350
2
    volatile int offset = 0;
351
2
    uint32_t version, subtype, tgen_payload_len = 0;
352
2
    uint64_t tgen_ctrl;
353
2
    uint32_t tgen_seq_num, sample_len, count, u32;
354
2
    volatile uint32_t i; // potentially held across vfork
355
2
    const char* str;
356
2
    uint16_t encap_proto;
357
2
    ethertype_data_t ethertype_data;
358
2
    tvbuff_t* volatile tgen_payload_tvb = NULL;
359
360
2
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "AVSP");
361
2
    col_clear(pinfo->cinfo, COL_INFO);
362
363
2
    proto_item* avsp_ti, * ti;
364
2
    proto_tree* avsp_tree, * avsp_48_tree = NULL, * avsp_64_tree = NULL,
365
2
        * avsp_tgen_hdr = NULL, * avsp_tgen_payload = NULL,
366
2
        * avsp_dzgre_hdr = NULL, * avsp_greent_hdr = NULL,
367
2
        * avsp_greent_sample_hdr = NULL, *header_tree = NULL;
368
369
    /* Adding Items and Values to the Protocol Tree */
370
2
    avsp_ti = proto_tree_add_item(tree, proto_avsp, tvb, 0, -1,
371
2
        ENC_NA);
372
2
    avsp_tree = proto_item_add_subtree(avsp_ti, ett_avsp);
373
374
    /* add the subtype to avsp */
375
2
    proto_tree_add_item_ret_uint(avsp_tree, hf_avsp_subtype, tvb,
376
2
        offset, 2, ENC_BIG_ENDIAN, &subtype);
377
2
    str = try_val_to_str(subtype, arista_subtypes);
378
2
    if (str) {
379
0
        proto_item_append_text(avsp_ti, ", Subtype: %s", str);
380
0
    }
381
2
    offset += 2;
382
383
    /* Based on the subtype, add the version and further custom protocol fields */
384
2
    switch (subtype) {
385
0
    case ARISTA_SUBTYPE_TIMESTAMP:
386
0
        proto_tree_add_item_ret_uint(avsp_tree, hf_avsp_ts_version, tvb, offset,
387
0
            2, ENC_BIG_ENDIAN, &version);
388
0
        str = try_val_to_str(version, ts_versions);
389
0
        if (str) {
390
0
            proto_item_append_text(avsp_ti, ", Version: %s", str);
391
0
        }
392
0
        offset += 2;
393
394
0
        switch (version) {
395
0
        case ARISTA_TIMESTAMP_64_TAI:
396
0
        case ARISTA_TIMESTAMP_64_TAI_J2:
397
0
            ti = proto_tree_add_item(avsp_tree, hf_avsp_ts_64_tai, tvb, 0, -1,
398
0
                ENC_NA);
399
0
            avsp_64_tree = proto_item_add_subtree(ti, ett_avsp);
400
0
            col_set_str(pinfo->cinfo, COL_INFO, "64bit TAI timestamp");
401
0
            proto_tree_add_item(avsp_64_tree, hf_avsp_ts_64_sec, tvb, offset,
402
0
                4, ENC_BIG_ENDIAN);
403
0
            offset += 4;
404
0
            proto_tree_add_item(avsp_64_tree, hf_avsp_ts_64_ns, tvb, offset,
405
0
                4, ENC_BIG_ENDIAN);
406
0
            offset += 4;
407
0
            break;
408
0
        case ARISTA_TIMESTAMP_64_UTC:
409
0
        case ARISTA_TIMESTAMP_64_UTC_J2:
410
0
            ti = proto_tree_add_item(avsp_tree, hf_avsp_ts_64_utc, tvb, 0, -1,
411
0
                ENC_NA);
412
0
            avsp_64_tree = proto_item_add_subtree(ti, ett_avsp);
413
0
            col_set_str(pinfo->cinfo, COL_INFO, "64bit UTC timestamp");
414
0
            proto_tree_add_item(avsp_64_tree, hf_avsp_ts_64_sec, tvb, offset,
415
0
                4, ENC_BIG_ENDIAN);
416
0
            offset += 4;
417
0
            proto_tree_add_item(avsp_64_tree, hf_avsp_ts_64_ns, tvb, offset,
418
0
                4, ENC_BIG_ENDIAN);
419
0
            offset += 4;
420
0
            break;
421
0
        case ARISTA_TIMESTAMP_48_TAI:
422
0
        case ARISTA_TIMESTAMP_48_TAI_J2:
423
0
            ti = proto_tree_add_item(avsp_tree, hf_avsp_ts_48_tai, tvb, 0, -1,
424
0
                ENC_NA);
425
0
            avsp_48_tree = proto_item_add_subtree(ti, ett_avsp);
426
0
            col_set_str(pinfo->cinfo, COL_INFO, "48bit TAI timestamp");
427
0
            proto_tree_add_item(avsp_48_tree, hf_avsp_ts_48_sec, tvb, offset,
428
0
                2, ENC_BIG_ENDIAN);
429
0
            offset += 2;
430
0
            proto_tree_add_item(avsp_48_tree, hf_avsp_ts_48_ns, tvb, offset,
431
0
                4, ENC_BIG_ENDIAN);
432
0
            offset += 4;
433
0
            break;
434
0
        case ARISTA_TIMESTAMP_48_UTC:
435
0
        case ARISTA_TIMESTAMP_48_UTC_J2:
436
0
            ti = proto_tree_add_item(avsp_tree, hf_avsp_ts_48_utc, tvb, 0, -1,
437
0
                ENC_NA);
438
0
            avsp_48_tree = proto_item_add_subtree(ti, ett_avsp);
439
0
            col_set_str(pinfo->cinfo, COL_INFO, "48bit UTC timestamp");
440
0
            proto_tree_add_item(avsp_48_tree, hf_avsp_ts_48_sec, tvb, offset,
441
0
                2, ENC_BIG_ENDIAN);
442
0
            offset += 2;
443
0
            proto_tree_add_item(avsp_48_tree, hf_avsp_ts_48_ns, tvb, offset,
444
0
                4, ENC_BIG_ENDIAN);
445
0
            offset += 4;
446
0
            break;
447
0
        default:
448
0
            expert_add_info_format(pinfo, avsp_ti, &ei_avsp_ts_unknown_version,
449
0
                "Unknown timestamp version: 0x%0x", version);
450
0
            return tvb_captured_length(tvb);
451
0
        }
452
453
0
        encap_proto = tvb_get_ntohs(tvb, offset);
454
0
        proto_tree_add_uint(avsp_tree, hf_avsp_etype, tvb, offset, 2, encap_proto);
455
0
        offset += 2;
456
457
0
        ethertype_data.etype = encap_proto;
458
0
        ethertype_data.payload_offset = offset;
459
0
        ethertype_data.fh_tree = avsp_tree;
460
0
        ethertype_data.trailer_id = hf_avsp_trailer;
461
0
        ethertype_data.fcs_len = 0;
462
463
0
        call_dissector_with_data(ethertype_handle, tvb, pinfo, tree, &ethertype_data);
464
0
        break;
465
466
0
    case ARISTA_SUBTYPE_GREENTAP:
467
0
        proto_tree_add_item_ret_uint(avsp_tree, hf_avsp_greentap_version, tvb,
468
0
            offset, 2, ENC_BIG_ENDIAN, &version);
469
0
        str = try_val_to_str(version, greentap_versions);
470
0
        if (str) {
471
0
            proto_item_append_text(avsp_ti, ", Version: %s", str);
472
0
        }
473
0
        offset += 2;
474
475
0
        switch (version) {
476
0
        case ARISTA_GREENTAP_48_TAI:
477
0
            ti = proto_tree_add_item(avsp_tree, hf_avsp_greentap_tai, tvb,
478
0
                0, -1, ENC_NA);
479
0
            avsp_48_tree = proto_item_add_subtree(ti, ett_avsp);
480
0
            col_set_str(pinfo->cinfo, COL_INFO, "48bit TAI timestamp");
481
0
            proto_tree_add_item(avsp_48_tree, hf_avsp_greentap_sec,
482
0
                tvb, offset, 2, ENC_BIG_ENDIAN);
483
0
            offset += 2;
484
0
            proto_tree_add_item(avsp_48_tree, hf_avsp_greentap_ns,
485
0
                tvb, offset, 4, ENC_BIG_ENDIAN);
486
0
            offset += 4;
487
0
            break;
488
0
        case ARISTA_GREENTAP_48_UTC:
489
0
            ti = proto_tree_add_item(avsp_tree, hf_avsp_greentap_utc, tvb,
490
0
                0, -1, ENC_NA);
491
0
            avsp_48_tree = proto_item_add_subtree(ti, ett_avsp);
492
0
            col_set_str(pinfo->cinfo, COL_INFO, "48bit TAI timestamp");
493
0
            proto_tree_add_item(avsp_48_tree, hf_avsp_greentap_sec,
494
0
                tvb, offset, 2, ENC_BIG_ENDIAN);
495
0
            offset += 2;
496
0
            proto_tree_add_item(avsp_48_tree, hf_avsp_greentap_ns,
497
0
                tvb, offset, 4, ENC_BIG_ENDIAN);
498
0
            offset += 4;
499
0
            break;
500
0
        default:
501
0
            expert_add_info_format(pinfo, avsp_ti,
502
0
                &ei_avsp_greentap_unknown_version,
503
0
                "Unknown GRE TAP version: 0x%0x", version);
504
0
            return tvb_captured_length(tvb);
505
0
        }
506
507
0
        encap_proto = tvb_get_ntohs(tvb, offset);
508
0
        proto_tree_add_uint(avsp_tree, hf_avsp_etype, tvb, offset, 2,
509
0
                encap_proto);
510
0
        offset += 2;
511
512
0
        ethertype_data.etype = encap_proto;
513
0
        ethertype_data.payload_offset = offset;
514
0
        ethertype_data.fh_tree = avsp_tree;
515
0
        ethertype_data.trailer_id = hf_avsp_trailer;
516
0
        ethertype_data.fcs_len = 0;
517
518
0
        call_dissector_with_data(ethertype_handle, tvb, pinfo, tree,
519
0
                &ethertype_data);
520
0
        break;
521
522
0
    case ARISTA_SUBTYPE_GREENT:
523
0
        proto_tree_add_item_ret_uint(avsp_tree, hf_avsp_greent_version, tvb,
524
0
            offset, 2, ENC_BIG_ENDIAN, &version);
525
0
        str = try_val_to_str(version, greent_versions);
526
0
        if (str) {
527
0
            proto_item_append_text(avsp_ti, ", Version: %s", str);
528
0
        }
529
0
        offset += 2;
530
531
0
        switch (version) {
532
0
        case ARISTA_GREENT_VER_1:
533
0
            col_set_str(pinfo->cinfo, COL_INFO, "Arista Postcard Telemetry");
534
0
            ti = proto_tree_add_item(avsp_tree, hf_avsp_greent_hdr, tvb, 0,
535
0
                -1, ENC_NA);
536
0
            avsp_greent_hdr = proto_item_add_subtree(ti, ett_avsp_greent_hdr);
537
538
            /* Session ID */
539
0
            proto_tree_add_item_ret_uint(avsp_greent_hdr,
540
0
                    hf_avsp_greent_session, tvb, offset, 2, ENC_BIG_ENDIAN,
541
0
                    &u32);
542
0
            proto_item_append_text(ti, ", Session ID: %u", u32);
543
0
            offset += 2;
544
545
            /* Flags */
546
0
            proto_tree_add_item_ret_uint(avsp_greent_hdr,
547
0
                    hf_avsp_greent_flags, tvb, offset, 1, ENC_BIG_ENDIAN,
548
0
                    &u32);
549
0
            proto_item_append_text(ti, ", Flags: 0x%02x", u32);
550
0
            offset += 1;
551
552
            /* Sample Count */
553
0
            proto_tree_add_item_ret_uint(avsp_greent_hdr,
554
0
                    hf_avsp_greent_sample_count, tvb, offset, 1, ENC_BIG_ENDIAN,
555
0
                    &count);
556
0
            proto_item_append_text(ti, ", Count: %u", count);
557
0
            offset += 1;
558
559
0
            for (i = 0; i < count; i++) {
560
0
                ti = proto_tree_add_item(avsp_greent_hdr,
561
0
                        hf_avsp_greent_sample_hdr, tvb, 0, -1, ENC_NA);
562
0
                avsp_greent_sample_hdr = proto_item_add_subtree(ti,
563
0
                        ett_avsp_greent_sample_hdr);
564
565
                /* Length */
566
0
                proto_tree_add_item_ret_uint(avsp_greent_sample_hdr,
567
0
                        hf_avsp_greent_sample_len, tvb, offset, 2,
568
0
                        ENC_BIG_ENDIAN, &sample_len);
569
0
                proto_item_append_text(ti, ", Length: %u", sample_len);
570
0
                offset += 2;
571
572
                /* Seconds */
573
0
                proto_tree_add_item_ret_uint(avsp_greent_sample_hdr,
574
0
                        hf_avsp_greent_sample_sec, tvb, offset, 2,
575
0
                        ENC_BIG_ENDIAN, &u32);
576
0
                proto_item_append_text(ti, ", Seconds: %u", u32);
577
0
                offset += 2;
578
579
                /* Nanoseconds */
580
0
                proto_tree_add_item_ret_uint(avsp_greent_sample_hdr,
581
0
                        hf_avsp_greent_sample_ns, tvb, offset, 4,
582
0
                        ENC_BIG_ENDIAN, &u32);
583
0
                proto_item_append_text(ti, ", Nanoseconds: %u", u32);
584
0
                offset += 4;
585
586
                /* Ingress */
587
0
                proto_tree_add_item_ret_uint(avsp_greent_sample_hdr,
588
0
                        hf_avsp_greent_sample_ingress, tvb, offset, 4,
589
0
                        ENC_BIG_ENDIAN, &u32);
590
0
                proto_item_append_text(ti, ", Ingress: %u", u32);
591
0
                offset += 4;
592
593
                /* Egress */
594
0
                proto_tree_add_item_ret_uint(avsp_greent_sample_hdr,
595
0
                        hf_avsp_greent_sample_egress, tvb, offset, 4,
596
0
                        ENC_BIG_ENDIAN, &u32);
597
0
                proto_item_append_text(ti, ", Egress: %u", u32);
598
0
                offset += 4;
599
600
                /* Sample Rate */
601
0
                proto_tree_add_item_ret_uint(avsp_greent_sample_hdr,
602
0
                        hf_avsp_greent_sample_rate, tvb, offset, 2,
603
0
                        ENC_BIG_ENDIAN, &u32);
604
0
                proto_item_append_text(ti, ", Rate: %u", u32);
605
0
                offset += 2;
606
607
                /* Checksum */
608
0
                proto_tree_add_item_ret_uint(avsp_greent_sample_hdr,
609
0
                        hf_avsp_greent_sample_sum, tvb, offset, 2,
610
0
                        ENC_BIG_ENDIAN, &u32);
611
0
                proto_item_append_text(ti, ", Checksum: 0x%04x", u32);
612
0
                offset += 2;
613
614
                /* Sample Data */
615
0
                ti = proto_tree_add_item(avsp_greent_sample_hdr,
616
0
                        hf_avsp_greent_sample_data, tvb, offset, sample_len,
617
0
                        ENC_NA);
618
0
                header_tree = proto_item_add_subtree(ti,
619
0
                        ett_avsp_greent_sample_data);
620
621
                /*
622
                 * We call the ethernet dissector on the sample, but since
623
                 * the sample is truncated it will likely generate errors.
624
                 * This is an attempt to isolate those errors, borrowed from
625
                 * sflow.
626
                 */
627
0
                {
628
0
                    tvbuff_t *next_tvb;
629
0
                    address save_dl_src, save_dl_dst, save_net_src,
630
0
                            save_net_dst, save_src, save_dst;
631
0
                    bool save_writable, save_in_error_pkt;
632
633
0
                    sample_len = ROUNDUP(sample_len, 4);
634
0
                    next_tvb = tvb_new_subset_length(tvb, offset, sample_len);
635
636
0
                    save_in_error_pkt = pinfo->flags.in_error_pkt;
637
0
                    pinfo->flags.in_error_pkt = true;
638
639
0
                    save_writable = col_get_writable(pinfo->cinfo, -1);
640
0
                    col_set_writable(pinfo->cinfo, -1, false);
641
0
                    copy_address_shallow(&save_dl_src, &pinfo->dl_src);
642
0
                    copy_address_shallow(&save_dl_dst, &pinfo->dl_dst);
643
0
                    copy_address_shallow(&save_net_src, &pinfo->net_src);
644
0
                    copy_address_shallow(&save_net_dst, &pinfo->net_dst);
645
0
                    copy_address_shallow(&save_src, &pinfo->src);
646
0
                    copy_address_shallow(&save_dst, &pinfo->dst);
647
648
0
                    TRY
649
0
                    {
650
                        // always ethernet for greent
651
0
                        ethertype_data.etype = ETHERTYPE_ETHBRIDGE;
652
0
                        ethertype_data.payload_offset = 0;
653
0
                        ethertype_data.fh_tree = header_tree;
654
0
                        ethertype_data.trailer_id = hf_avsp_trailer;
655
0
                        ethertype_data.fcs_len = 0;
656
657
0
                        call_dissector_with_data(ethertype_handle, next_tvb,
658
0
                                pinfo, header_tree, &ethertype_data);
659
0
                    }
660
0
                    CATCH_BOUNDS_ERRORS {
661
0
                    }
662
0
                    ENDTRY;
663
664
0
                    col_set_writable(pinfo->cinfo, -1, save_writable);
665
0
                    pinfo->flags.in_error_pkt = save_in_error_pkt;
666
0
                    copy_address_shallow(&pinfo->dl_src, &save_dl_src);
667
0
                    copy_address_shallow(&pinfo->dl_dst, &save_dl_dst);
668
0
                    copy_address_shallow(&pinfo->net_src, &save_net_src);
669
0
                    copy_address_shallow(&pinfo->net_dst, &save_net_dst);
670
0
                    copy_address_shallow(&pinfo->src, &save_src);
671
0
                    copy_address_shallow(&pinfo->dst, &save_dst);
672
0
                }
673
0
            }
674
0
            break;
675
0
        default:
676
0
            expert_add_info_format(pinfo, avsp_ti,
677
0
                    &ei_avsp_greent_unknown_version,
678
0
                "Unknown version: 0x%0x", version);
679
0
            return tvb_captured_length(tvb);
680
0
        }
681
0
        break;
682
683
0
    case ARISTA_SUBTYPE_DZGRE_A:
684
0
        proto_tree_add_item_ret_uint(avsp_tree, hf_avsp_dzgre_a_version, tvb,
685
0
            offset, 2, ENC_BIG_ENDIAN, &version);
686
0
        str = try_val_to_str(version, dzgre_a_versions);
687
0
        if (str) {
688
0
            proto_item_append_text(avsp_ti, ", Version: %s", str);
689
0
        }
690
0
        offset += 2;
691
692
0
        switch (version) {
693
0
        case ARISTA_DZGRE_A_VER_1:
694
0
            col_set_str(pinfo->cinfo, COL_INFO, "Arista DzGRE(A) Frame");
695
0
            ti = proto_tree_add_item(avsp_tree, hf_avsp_dzgre_a_hdr, tvb,
696
0
                    0, -1, ENC_NA);
697
0
            avsp_dzgre_hdr = proto_item_add_subtree(ti, ett_avsp_dzgre_a_hdr);
698
699
            /* Switch ID */
700
0
            proto_tree_add_item_ret_uint(avsp_dzgre_hdr,
701
0
                    hf_avsp_dzgre_a_switch, tvb, offset, 2, ENC_BIG_ENDIAN,
702
0
                    &u32);
703
0
            proto_item_append_text(ti, ", Switch ID: %u", u32);
704
0
            offset += 2;
705
706
            /* Port ID */
707
0
            proto_tree_add_item_ret_uint(avsp_dzgre_hdr,
708
0
                    hf_avsp_dzgre_a_port, tvb, offset, 2, ENC_BIG_ENDIAN,
709
0
                    &u32);
710
0
            proto_item_append_text(ti, ", Port ID: %u", u32);
711
0
            offset += 2;
712
713
            /* Policy ID */
714
0
            proto_tree_add_item_ret_uint(avsp_dzgre_hdr,
715
0
                    hf_avsp_dzgre_a_policy, tvb, offset, 2, ENC_BIG_ENDIAN,
716
0
                    &u32);
717
0
            proto_item_append_text(ti, ", Policy ID: %u", u32);
718
0
            offset += 2;
719
720
            /* Reserved */
721
0
            proto_tree_add_item_ret_uint(avsp_dzgre_hdr,
722
0
                    hf_avsp_dzgre_a_reserved, tvb, offset, 2, ENC_BIG_ENDIAN,
723
0
                    &u32);
724
0
            offset += 2;
725
0
            break;
726
0
        default:
727
0
            expert_add_info_format(pinfo, avsp_ti,
728
0
                    &ei_avsp_dzgre_a_unknown_version,
729
0
                "Unknown version: 0x%0x", version);
730
0
            return tvb_captured_length(tvb);
731
0
        }
732
733
0
        ethertype_data.etype = ETHERTYPE_ETHBRIDGE; // always ethernet
734
0
        ethertype_data.payload_offset = offset;
735
0
        ethertype_data.fh_tree = avsp_tree;
736
0
        ethertype_data.trailer_id = hf_avsp_trailer;
737
0
        ethertype_data.fcs_len = 0;
738
739
0
        call_dissector_with_data(ethertype_handle, tvb, pinfo, tree,
740
0
                &ethertype_data);
741
0
        break;
742
743
0
    case ARISTA_SUBTYPE_DZGRE_B:
744
0
        proto_tree_add_item_ret_uint(avsp_tree, hf_avsp_dzgre_b_version, tvb,
745
0
            offset, 2, ENC_BIG_ENDIAN, &version);
746
0
        str = try_val_to_str(version, dzgre_b_versions);
747
0
        if (str) {
748
0
            proto_item_append_text(avsp_ti, ", Version: %s", str);
749
0
        }
750
0
        offset += 2;
751
752
0
        switch (version) {
753
0
        case ARISTA_DZGRE_B_VER_1:
754
0
            col_set_str(pinfo->cinfo, COL_INFO, "Arista DzGRE(B) Frame");
755
0
            ti = proto_tree_add_item(avsp_tree, hf_avsp_dzgre_b_hdr, tvb,
756
0
                    0, -1, ENC_NA);
757
0
            avsp_dzgre_hdr = proto_item_add_subtree(ti, ett_avsp_dzgre_b_hdr);
758
759
            /* Port ID */
760
0
            proto_tree_add_item_ret_uint(avsp_dzgre_hdr,
761
0
                    hf_avsp_dzgre_b_port, tvb, offset, 2, ENC_BIG_ENDIAN,
762
0
                    &u32);
763
0
            proto_item_append_text(ti, ", Port ID: %u", u32);
764
0
            offset += 2;
765
766
            /* Policy ID */
767
0
            proto_tree_add_item_ret_uint(avsp_dzgre_hdr,
768
0
                    hf_avsp_dzgre_b_policy, tvb, offset, 2, ENC_BIG_ENDIAN,
769
0
                    &u32);
770
0
            proto_item_append_text(ti, ", Policy ID: %u", u32);
771
0
            offset += 2;
772
0
            break;
773
0
        default:
774
0
            expert_add_info_format(pinfo, avsp_ti,
775
0
                    &ei_avsp_dzgre_b_unknown_version,
776
0
                "Unknown version: 0x%0x", version);
777
0
            return tvb_captured_length(tvb);
778
0
        }
779
780
0
        ethertype_data.etype = ETHERTYPE_ETHBRIDGE; // always ethernet
781
0
        ethertype_data.payload_offset = offset;
782
0
        ethertype_data.fh_tree = avsp_tree;
783
0
        ethertype_data.trailer_id = hf_avsp_trailer;
784
0
        ethertype_data.fcs_len = 0;
785
786
0
        call_dissector_with_data(ethertype_handle, tvb, pinfo, tree,
787
0
                &ethertype_data);
788
0
        break;
789
790
0
    case ARISTA_SUBTYPE_DZGRE_TS:
791
0
        proto_tree_add_item_ret_uint(avsp_tree, hf_avsp_dzgre_ts_version, tvb,
792
0
            offset, 2, ENC_BIG_ENDIAN, &version);
793
0
        str = try_val_to_str(version, dzgre_ts_versions);
794
0
        if (str) {
795
0
            proto_item_append_text(avsp_ti, ", Version: %s", str);
796
0
        }
797
0
        offset += 2;
798
799
0
        switch (version) {
800
0
        case ARISTA_DZGRE_TS_64_TAI:
801
0
            col_set_str(pinfo->cinfo, COL_INFO, "Arista DzGRE(A) Frame");
802
0
            ti = proto_tree_add_item(avsp_tree, hf_avsp_dzgre_ts_hdr, tvb,
803
0
                    0, -1, ENC_NA);
804
0
            avsp_dzgre_hdr = proto_item_add_subtree(ti, ett_avsp_dzgre_ts_hdr);
805
806
            /* Switch ID */
807
0
            proto_tree_add_item_ret_uint(avsp_dzgre_hdr,
808
0
                    hf_avsp_dzgre_ts_switch, tvb, offset, 2, ENC_BIG_ENDIAN,
809
0
                    &u32);
810
0
            proto_item_append_text(ti, ", Switch ID: %u", u32);
811
0
            offset += 2;
812
813
            /* Port ID */
814
0
            proto_tree_add_item_ret_uint(avsp_dzgre_hdr,
815
0
                    hf_avsp_dzgre_ts_port, tvb, offset, 2, ENC_BIG_ENDIAN,
816
0
                    &u32);
817
0
            proto_item_append_text(ti, ", Port ID: %u", u32);
818
0
            offset += 2;
819
820
            /* Policy ID */
821
0
            proto_tree_add_item_ret_uint(avsp_dzgre_hdr,
822
0
                    hf_avsp_dzgre_ts_policy, tvb, offset, 2, ENC_BIG_ENDIAN,
823
0
                    &u32);
824
0
            proto_item_append_text(ti, ", Policy ID: %u", u32);
825
0
            offset += 2;
826
827
            /* Reserved */
828
0
            proto_tree_add_item_ret_uint(avsp_dzgre_hdr,
829
0
                    hf_avsp_dzgre_ts_reserved, tvb, offset, 2, ENC_BIG_ENDIAN,
830
0
                    &u32);
831
0
            offset += 2;
832
833
            /* Timestamp */
834
0
            ti = proto_tree_add_item(avsp_dzgre_hdr,
835
0
                    hf_avsp_dzgre_ts_tai, tvb, 0, -1, ENC_NA);
836
0
            avsp_64_tree = proto_item_add_subtree(ti,
837
0
                    ett_avsp_dzgre_ts_tai);
838
839
0
            col_set_str(pinfo->cinfo, COL_INFO, "64bit TAI timestamp");
840
841
0
            proto_tree_add_item(avsp_64_tree, hf_avsp_dzgre_ts_sec,
842
0
                tvb, offset, 4, ENC_BIG_ENDIAN);
843
0
            offset += 4;
844
0
            proto_tree_add_item(avsp_64_tree, hf_avsp_dzgre_ts_ns,
845
0
                tvb, offset, 4, ENC_BIG_ENDIAN);
846
0
            offset += 4;
847
0
            break;
848
0
        case ARISTA_DZGRE_TS_64_UTC:
849
0
            col_set_str(pinfo->cinfo, COL_INFO,
850
0
                    "Arista DzGRE(timestamped) Frame");
851
0
            ti = proto_tree_add_item(avsp_tree, hf_avsp_dzgre_ts_hdr, tvb,
852
0
                    0, -1, ENC_NA);
853
0
            avsp_dzgre_hdr = proto_item_add_subtree(ti, ett_avsp_dzgre_ts_hdr);
854
855
            /* Switch ID */
856
0
            proto_tree_add_item_ret_uint(avsp_dzgre_hdr,
857
0
                    hf_avsp_dzgre_ts_switch, tvb, offset, 2, ENC_BIG_ENDIAN,
858
0
                    &u32);
859
0
            proto_item_append_text(ti, ", Switch ID: 0x%u", u32);
860
0
            offset += 2;
861
862
            /* Port ID */
863
0
            proto_tree_add_item_ret_uint(avsp_dzgre_hdr,
864
0
                    hf_avsp_dzgre_ts_port, tvb, offset, 2, ENC_BIG_ENDIAN,
865
0
                    &u32);
866
0
            proto_item_append_text(ti, ", Port ID: 0x%u", u32);
867
0
            offset += 2;
868
869
            /* Policy ID */
870
0
            proto_tree_add_item_ret_uint(avsp_dzgre_hdr,
871
0
                    hf_avsp_dzgre_ts_policy, tvb, offset, 2, ENC_BIG_ENDIAN,
872
0
                    &u32);
873
0
            proto_item_append_text(ti, ", Policy ID: 0x%u", u32);
874
0
            offset += 2;
875
876
            /* Reserved */
877
0
            offset += 2;
878
879
            /* Timestamp */
880
0
            ti = proto_tree_add_item(avsp_dzgre_hdr,
881
0
                    hf_avsp_dzgre_ts_utc, tvb, 0, -1, ENC_NA);
882
0
            avsp_64_tree = proto_item_add_subtree(ti,
883
0
                    ett_avsp_dzgre_ts_utc);
884
885
0
            col_set_str(pinfo->cinfo, COL_INFO, "64bit UTC timestamp");
886
887
0
            proto_tree_add_item(avsp_64_tree, hf_avsp_dzgre_ts_sec,
888
0
                tvb, offset, 4, ENC_BIG_ENDIAN);
889
0
            offset += 4;
890
0
            proto_tree_add_item(avsp_64_tree, hf_avsp_dzgre_ts_ns,
891
0
                tvb, offset, 4, ENC_BIG_ENDIAN);
892
0
            offset += 4;
893
0
            break;
894
0
        default:
895
0
            expert_add_info_format(pinfo, avsp_ti,
896
0
                    &ei_avsp_dzgre_ts_unknown_version,
897
0
                "Unknown version: 0x%0x", version);
898
0
            return tvb_captured_length(tvb);
899
0
        }
900
901
0
        ethertype_data.etype = ETHERTYPE_ETHBRIDGE; // always ethernet
902
0
        ethertype_data.payload_offset = offset;
903
0
        ethertype_data.fh_tree = avsp_tree;
904
0
        ethertype_data.trailer_id = hf_avsp_trailer;
905
0
        ethertype_data.fcs_len = 0;
906
907
0
        call_dissector_with_data(ethertype_handle, tvb, pinfo, tree,
908
0
                &ethertype_data);
909
0
        break;
910
911
0
    case ARISTA_SUBTYPE_TGEN:
912
0
        proto_tree_add_item_ret_uint(avsp_tree, hf_avsp_tgen_version, tvb,
913
0
            offset, 2, ENC_BIG_ENDIAN, &version);
914
0
        str = try_val_to_str(version, tgen_versions);
915
0
        if (str) {
916
0
            proto_item_append_text(avsp_ti, ", Version: %s", str);
917
0
        }
918
0
        offset += 2;
919
920
0
        switch (version) {
921
0
        case ARISTA_TGEN_VER_1:
922
0
            col_set_str(pinfo->cinfo, COL_INFO, "Arista TGen Frame");
923
924
            /* Get TGen Header Control Word. */
925
0
            ti = proto_tree_add_item(avsp_tree, hf_avsp_tgen_hdr, tvb, offset, 6,
926
0
                ENC_NA);
927
0
            avsp_tgen_hdr = proto_item_add_subtree(ti, ett_avsp_tgen_hdr);
928
0
            proto_tree_add_bitmask_ret_uint64(avsp_tgen_hdr, tvb, offset,
929
0
                hf_avsp_tgen_hdr_ctrl, ett_avsp_tgen_hdr_ctrl, avsp_tgen_ctrl,
930
0
                ENC_BIG_ENDIAN, &tgen_ctrl);
931
0
            proto_item_append_text(ti, ", Control Word: 0x%04" PRIx64, tgen_ctrl);
932
0
            col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Ctrl=0x%04" PRIx64, tgen_ctrl);
933
0
            offset += 2;
934
935
            /* Get TGen Header Sequence Number*/
936
0
            proto_tree_add_item_ret_uint(avsp_tgen_hdr, hf_avsp_tgen_hdr_seq_num, tvb,
937
0
                offset, 2, ENC_BIG_ENDIAN, &tgen_seq_num);
938
0
            proto_item_append_text(ti, ", Sequence Number: %u", tgen_seq_num);
939
0
            col_append_str_uint(pinfo->cinfo, COL_INFO, "Seq", tgen_seq_num, ", ");
940
0
            offset += 2;
941
942
            /* Get TGen Header Payload Length */
943
0
            proto_tree_add_item_ret_uint(avsp_tgen_hdr,
944
0
                hf_avsp_tgen_hdr_payload_len, tvb, offset, 2, ENC_BIG_ENDIAN,
945
0
                &tgen_payload_len);
946
0
            proto_item_append_text(ti, ", Payload Length: %u", tgen_payload_len);
947
0
            col_append_str_uint(pinfo->cinfo, COL_INFO, "Len", tgen_payload_len, ", ");
948
0
            offset += 2;
949
950
            /* Try to construct a tvbuff containing only
951
                the data specified by the tgen_payload_len field. */
952
953
0
            TRY {
954
0
                tgen_payload_tvb = tvb_new_subset_length(tvb, offset, tgen_payload_len);
955
0
            }
956
0
                CATCH_BOUNDS_ERRORS {
957
                /* So:
958
                    the packet doesn't have "tgen_payload_len" bytes worth of
959
                    captured data left in it so the "tvb_new_subset_length()"
960
                    creating "payload_tvb" threw an exception
961
962
                    This means that all the data in the frame is within the
963
                    length value, so we give all the data to the payload. */
964
0
                tgen_payload_tvb = tvb_new_subset_remaining(tvb, offset);
965
0
            }
966
0
            ENDTRY;
967
968
            /* Get the TGen payload captured length. */
969
0
            uint16_t tgen_payload_captured_len = tvb_captured_length(tgen_payload_tvb);
970
971
            /* Add the TGen payload to the tree, with a heading that displays
972
               the TGgen payload captured length. */
973
0
            ti = proto_tree_add_none_format(avsp_tree, hf_avsp_tgen_payload,
974
0
                tgen_payload_tvb, 0, -1, "TGen Payload (%u byte%s)",
975
0
                tgen_payload_captured_len,
976
0
                plurality(tgen_payload_captured_len, "", "s"));
977
0
            avsp_tgen_payload = proto_item_add_subtree(ti, ett_avsp_tgen_payload);
978
0
            proto_tree_add_item(avsp_tgen_payload, hf_avsp_tgen_payload_data, tgen_payload_tvb,
979
0
                0, -1, ENC_NA);
980
981
            /* Now we know the TGen payload captured length (which may be less than
982
               that specified in the TGen header because the captured frame may have
983
               been truncated) we can set the length of the entire AVSP protocol. */
984
0
            proto_item_set_len(avsp_ti, offset + tgen_payload_captured_len);
985
986
            /* We have a length field, so set it here so that the higher level
987
             * (ethertype) dissector can add the trailer. That way the FCS
988
             * will be calculated correctly.
989
             */
990
0
            set_actual_length(tvb, offset + tgen_payload_captured_len);
991
0
            break;
992
993
0
        default:
994
0
            expert_add_info_format(pinfo, avsp_ti, &ei_avsp_tgen_unknown_version,
995
0
                "Unknown version: 0x%0x", version);
996
0
            return tvb_captured_length(tvb);
997
0
        }
998
0
        break;
999
1000
2
    default:
1001
2
        expert_add_info_format(pinfo, avsp_ti, &ei_avsp_unknown_subtype,
1002
2
            "Unknown subtype: 0x%0x", subtype);
1003
2
        return tvb_captured_length(tvb);
1004
2
    }
1005
0
    return tvb_captured_length(tvb);
1006
2
}
1007
1008
void proto_reg_handoff_avsp(void)
1009
16
{
1010
16
    dissector_add_uint("ethertype", ETHERTYPE_AVSP, avsp_handle);
1011
16
    ethertype_handle = find_dissector_add_dependency("ethertype", proto_avsp);
1012
16
    dissector_add_uint("gre.proto", ETHERTYPE_AVSP, avsp_handle);
1013
16
}
1014
1015
void proto_register_avsp(void)
1016
16
{
1017
    /* Field Registration */
1018
16
    static hf_register_info hf[] = {
1019
        /* For avsp */
1020
16
        {&hf_avsp_subtype,
1021
16
            {"Subtype", "avsp.subtype",
1022
16
                FT_UINT16, BASE_HEX,
1023
16
                VALS(arista_subtypes), 0x0,
1024
16
                NULL, HFILL}
1025
16
        },
1026
16
        {&hf_avsp_ts_version,
1027
16
            {"Version", "avsp.ts.ver",
1028
16
                FT_UINT16, BASE_HEX,
1029
16
                VALS(ts_versions), 0x0,
1030
16
                NULL, HFILL}
1031
16
        },
1032
16
        {&hf_avsp_ts_64_tai,
1033
16
            {"Timestamp (TAI)", "avsp.ts.64.tai",
1034
16
                FT_NONE, BASE_NONE,
1035
16
                NULL, 0x0,
1036
16
                NULL, HFILL}
1037
16
        },
1038
16
        {&hf_avsp_ts_64_utc,
1039
16
            {"Timestamp (UTC)", "avsp.ts.64.utc",
1040
16
                FT_NONE, BASE_NONE,
1041
16
                NULL, 0x0,
1042
16
                NULL, HFILL}
1043
16
        },
1044
16
        {&hf_avsp_ts_64_sec,
1045
16
            {"Seconds", "avsp.ts.64.sec",
1046
16
                FT_UINT32, BASE_DEC,
1047
16
                NULL, 0x0,
1048
16
                NULL, HFILL}
1049
16
        },
1050
16
        {&hf_avsp_ts_64_ns,
1051
16
            {"Nanoseconds", "avsp.ts.64.ns",
1052
16
                FT_UINT32, BASE_DEC,
1053
16
                NULL, 0x0,
1054
16
                NULL, HFILL}
1055
16
        },
1056
16
        {&hf_avsp_ts_48_tai,
1057
16
            {"Timestamp (TAI)", "avsp.ts.48.tai",
1058
16
                FT_NONE, BASE_NONE,
1059
16
                NULL, 0x0,
1060
16
                NULL, HFILL}
1061
16
        },
1062
16
        {&hf_avsp_ts_48_utc,
1063
16
            {"Timestamp (UTC)", "avsp.ts.48.utc",
1064
16
                FT_NONE, BASE_NONE,
1065
16
                NULL, 0x0,
1066
16
                NULL, HFILL}
1067
16
        },
1068
16
        {&hf_avsp_ts_48_sec,
1069
16
            {"Seconds", "avsp.ts.48.sec",
1070
16
                FT_UINT16, BASE_DEC,
1071
16
                NULL, 0x0,
1072
16
                NULL, HFILL}
1073
16
        },
1074
16
        {&hf_avsp_ts_48_ns,
1075
16
            {"Nanoseconds", "avsp.ts.48.ns",
1076
16
                FT_UINT32, BASE_DEC,
1077
16
                NULL, 0x0,
1078
16
                NULL, HFILL}
1079
16
        },
1080
16
        {&hf_avsp_etype,
1081
16
            {"Type", "avsp.etype",
1082
16
                FT_UINT16, BASE_HEX,
1083
16
                VALS(etype_vals), 0x0,
1084
16
                "Ethertype", HFILL}
1085
16
        },
1086
16
        {&hf_avsp_trailer,
1087
16
            {"Trailer", "avsp.trailer",
1088
16
                FT_BYTES, BASE_NONE,
1089
16
                NULL, 0x0,
1090
16
                "AVSP Trailer", HFILL}
1091
16
        },
1092
16
        {&hf_avsp_greentap_version,
1093
16
            {"Version", "avsp.greentap.ver",
1094
16
                FT_UINT16, BASE_DEC,
1095
16
                VALS(greentap_versions), 0x0,
1096
16
                NULL, HFILL}
1097
16
        },
1098
16
        {&hf_avsp_greentap_tai,
1099
16
            {"Timestamp (TAI)", "avsp.greentap.tai",
1100
16
                FT_NONE, BASE_NONE,
1101
16
                NULL, 0x0,
1102
16
                NULL, HFILL}
1103
16
        },
1104
16
        {&hf_avsp_greentap_utc,
1105
16
            {"Timestamp (UTC)", "avsp.greentap.utc",
1106
16
                FT_NONE, BASE_NONE,
1107
16
                NULL, 0x0,
1108
16
                NULL, HFILL}
1109
16
        },
1110
16
        {&hf_avsp_greentap_sec,
1111
16
            {"Seconds", "avsp.greentap.sec",
1112
16
                FT_UINT16, BASE_DEC,
1113
16
                NULL, 0x0,
1114
16
                NULL, HFILL}
1115
16
        },
1116
16
        {&hf_avsp_greentap_ns,
1117
16
            {"Nanoseconds", "avsp.greentap.ns",
1118
16
                FT_UINT32, BASE_DEC,
1119
16
                NULL, 0x0,
1120
16
                NULL, HFILL}
1121
16
        },
1122
16
        {&hf_avsp_greent_version,
1123
16
            {"Version", "avsp.greent.ver",
1124
16
                FT_UINT16, BASE_DEC,
1125
16
                VALS(greent_versions), 0x0,
1126
16
                NULL, HFILL}
1127
16
        },
1128
16
        {&hf_avsp_greent_hdr,
1129
16
            {"GREENT Header", "avsp.greent.hdr",
1130
16
                FT_NONE, BASE_NONE,
1131
16
                NULL, 0x0,
1132
16
                NULL, HFILL}
1133
16
        },
1134
16
        {&hf_avsp_greent_session,
1135
16
            {"Session ID", "avsp.greent.session",
1136
16
                FT_UINT16, BASE_DEC,
1137
16
                NULL, 0x0,
1138
16
                NULL, HFILL}
1139
16
        },
1140
16
        {&hf_avsp_greent_flags,
1141
16
            {"Flags", "avsp.greent.flags",
1142
16
                FT_UINT8, BASE_HEX,
1143
16
                NULL, 0x0,
1144
16
                NULL, HFILL}
1145
16
        },
1146
16
        {&hf_avsp_greent_sample_count,
1147
16
            {"Sample Count", "avsp.greent.sample_count",
1148
16
                FT_UINT8, BASE_DEC,
1149
16
                NULL, 0x0,
1150
16
                NULL, HFILL}
1151
16
        },
1152
16
        {&hf_avsp_greent_sample_hdr,
1153
16
            {"Sample Header", "avsp.greent.sample.hdr",
1154
16
                FT_NONE, BASE_NONE,
1155
16
                NULL, 0x0,
1156
16
                NULL, HFILL}
1157
16
        },
1158
16
        {&hf_avsp_greent_sample_len,
1159
16
            {"Length", "avsp.greent.sample.len",
1160
16
                FT_UINT16, BASE_DEC,
1161
16
                NULL, 0x0,
1162
16
                NULL, HFILL}
1163
16
        },
1164
16
        {&hf_avsp_greent_sample_sec,
1165
16
            {"Seconds", "avsp.greent.sample.sec",
1166
16
                FT_UINT16, BASE_DEC,
1167
16
                NULL, 0x0,
1168
16
                NULL, HFILL}
1169
16
        },
1170
16
        {&hf_avsp_greent_sample_ns,
1171
16
            {"Nanoseconds", "avsp.greent.sample.ns",
1172
16
                FT_UINT32, BASE_DEC,
1173
16
                NULL, 0x0,
1174
16
                NULL, HFILL}
1175
16
        },
1176
16
        {&hf_avsp_greent_sample_ingress,
1177
16
            {"Ingress Interface", "avsp.greent.sample.ingress",
1178
16
                FT_UINT32, BASE_DEC,
1179
16
                NULL, 0x0,
1180
16
                NULL, HFILL}
1181
16
        },
1182
16
        {&hf_avsp_greent_sample_egress,
1183
16
            {"Egress Interface", "avsp.greent.sample.egress",
1184
16
                FT_UINT32, BASE_DEC,
1185
16
                NULL, 0x0,
1186
16
                NULL, HFILL}
1187
16
        },
1188
16
        {&hf_avsp_greent_sample_rate,
1189
16
            {"Rate(*1K)", "avsp.greent.sample.rate",
1190
16
                FT_UINT16, BASE_DEC,
1191
16
                NULL, 0x0,
1192
16
                NULL, HFILL}
1193
16
        },
1194
16
        {&hf_avsp_greent_sample_sum,
1195
16
            {"Checksum", "avsp.greent.sample.sum",
1196
16
                FT_UINT16, BASE_HEX,
1197
16
                NULL, 0x0,
1198
16
                NULL, HFILL}
1199
16
        },
1200
16
        {&hf_avsp_greent_sample_data,
1201
16
            {"Header of sampled packet", "avsp.greent.sample.data",
1202
16
                FT_BYTES, BASE_NONE,
1203
16
                NULL, 0x0,
1204
16
                "Data from sampled header", HFILL}
1205
16
        },
1206
16
        {&hf_avsp_dzgre_a_version,
1207
16
            {"Version", "avsp.dzgre_a.ver",
1208
16
                FT_UINT16, BASE_DEC,
1209
16
                VALS(dzgre_a_versions), 0x0,
1210
16
                NULL, HFILL}
1211
16
        },
1212
16
        {&hf_avsp_dzgre_a_hdr,
1213
16
            {"DzGRE(A) Header", "avsp.dzgre_a.hdr",
1214
16
                FT_NONE, BASE_NONE,
1215
16
                NULL, 0x0,
1216
16
                NULL, HFILL}
1217
16
        },
1218
16
        {&hf_avsp_dzgre_a_switch,
1219
16
            {"Switch ID", "avsp.dzgre_a.switch",
1220
16
                FT_UINT16, BASE_DEC,
1221
16
                NULL, 0x0,
1222
16
                NULL, HFILL}
1223
16
        },
1224
16
        {&hf_avsp_dzgre_a_port,
1225
16
            {"Port ID", "avsp.dzgre_a.port",
1226
16
                FT_UINT16, BASE_DEC,
1227
16
                NULL, 0x0,
1228
16
                NULL, HFILL}
1229
16
        },
1230
16
        {&hf_avsp_dzgre_a_policy,
1231
16
            {"Policy ID", "avsp.dzgre_a.policy",
1232
16
                FT_UINT16, BASE_DEC,
1233
16
                NULL, 0x0,
1234
16
                NULL, HFILL}
1235
16
        },
1236
16
        {&hf_avsp_dzgre_a_reserved,
1237
16
            {"Reserved", "avsp.dzgre_a.reserved",
1238
16
                FT_UINT16, BASE_HEX,
1239
16
                NULL, 0x0,
1240
16
                NULL, HFILL}
1241
16
        },
1242
16
        {&hf_avsp_dzgre_b_version,
1243
16
            {"Version", "avsp.dzgre_b.ver",
1244
16
                FT_UINT16, BASE_DEC,
1245
16
                VALS(dzgre_b_versions), 0x0,
1246
16
                NULL, HFILL}
1247
16
        },
1248
16
        {&hf_avsp_dzgre_b_hdr,
1249
16
            {"DzGRE(B) Header", "avsp.dzgre_b.hdr",
1250
16
                FT_NONE, BASE_NONE,
1251
16
                NULL, 0x0,
1252
16
                NULL, HFILL}
1253
16
        },
1254
16
        {&hf_avsp_dzgre_b_port,
1255
16
            {"Port ID", "avsp.dzgre_b.port",
1256
16
                FT_UINT16, BASE_DEC,
1257
16
                NULL, 0x0,
1258
16
                NULL, HFILL}
1259
16
        },
1260
16
        {&hf_avsp_dzgre_b_policy,
1261
16
            {"Policy ID", "avsp.dzgre_b.policy",
1262
16
                FT_UINT16, BASE_DEC,
1263
16
                NULL, 0x0,
1264
16
                NULL, HFILL}
1265
16
        },
1266
16
        {&hf_avsp_dzgre_ts_version,
1267
16
            {"Version", "avsp.dzgre_ts.ver",
1268
16
                FT_UINT16, BASE_DEC,
1269
16
                VALS(dzgre_ts_versions), 0x0,
1270
16
                NULL, HFILL}
1271
16
        },
1272
16
        {&hf_avsp_dzgre_ts_hdr,
1273
16
            {"DzGRE(B) Header", "avsp.dzgre_ts.hdr",
1274
16
                FT_NONE, BASE_NONE,
1275
16
                NULL, 0x0,
1276
16
                NULL, HFILL}
1277
16
        },
1278
16
        {&hf_avsp_dzgre_ts_switch,
1279
16
            {"Switch ID", "avsp.dzgre_ts.switch",
1280
16
                FT_UINT16, BASE_DEC,
1281
16
                NULL, 0x0,
1282
16
                NULL, HFILL}
1283
16
        },
1284
16
        {&hf_avsp_dzgre_ts_port,
1285
16
            {"Port ID", "avsp.dzgre_ts.port",
1286
16
                FT_UINT16, BASE_DEC,
1287
16
                NULL, 0x0,
1288
16
                NULL, HFILL}
1289
16
        },
1290
16
        {&hf_avsp_dzgre_ts_policy,
1291
16
            {"Policy ID", "avsp.dzgre_ts.policy",
1292
16
                FT_UINT16, BASE_DEC,
1293
16
                NULL, 0x0,
1294
16
                NULL, HFILL}
1295
16
        },
1296
16
        {&hf_avsp_dzgre_ts_reserved,
1297
16
            {"Reserved", "avsp.dzgre_ts.reserved",
1298
16
                FT_UINT16, BASE_HEX,
1299
16
                NULL, 0x0,
1300
16
                NULL, HFILL}
1301
16
        },
1302
16
        {&hf_avsp_dzgre_ts_tai,
1303
16
            {"Timestamp (TAI)", "avsp.dzgre_ts.tai",
1304
16
                FT_NONE, BASE_NONE,
1305
16
                NULL, 0x0,
1306
16
                NULL, HFILL}
1307
16
        },
1308
16
        {&hf_avsp_dzgre_ts_utc,
1309
16
            {"Timestamp (UTC)", "avsp.dzgre_ts.utc",
1310
16
                FT_NONE, BASE_NONE,
1311
16
                NULL, 0x0,
1312
16
                NULL, HFILL}
1313
16
        },
1314
16
        {&hf_avsp_dzgre_ts_sec,
1315
16
            {"Seconds", "avsp.ts.dzgre_ts.sec",
1316
16
                FT_UINT32, BASE_DEC,
1317
16
                NULL, 0x0,
1318
16
                NULL, HFILL}
1319
16
        },
1320
16
        {&hf_avsp_dzgre_ts_ns,
1321
16
            {"Nanoseconds", "avsp.dzgre_ts.48.ns",
1322
16
                FT_UINT32, BASE_DEC,
1323
16
                NULL, 0x0,
1324
16
                NULL, HFILL}
1325
16
        },
1326
16
        {&hf_avsp_tgen_version,
1327
16
            {"Version", "avsp.tgen.ver",
1328
16
                FT_UINT16, BASE_DEC,
1329
16
                VALS(tgen_versions), 0x0,
1330
16
                NULL, HFILL}
1331
16
        },
1332
16
        {&hf_avsp_tgen_hdr,
1333
16
            {"TGen Header", "avsp.tgen.hdr",
1334
16
                FT_NONE, BASE_NONE,
1335
16
                NULL, 0x0,
1336
16
                NULL, HFILL}
1337
16
        },
1338
16
        {&hf_avsp_tgen_hdr_ctrl,
1339
16
            {"Control Word", "avsp.tgen.hdr.ctrl",
1340
16
                FT_UINT16, BASE_HEX,
1341
16
                NULL, 0x0,
1342
16
                NULL, HFILL}
1343
16
        },
1344
16
        {&hf_avsp_tgen_hdr_ctrl_fcs_inverted,
1345
16
            {"FCS Inverted", "avsp.tgen.hdr.ctrl.fcs_inverted",
1346
16
                FT_BOOLEAN, 16,
1347
16
                NULL, 0x0001,
1348
16
                NULL, HFILL}
1349
16
        },
1350
16
        {&hf_avsp_tgen_hdr_ctrl_reserved,
1351
16
            {"Reserved", "avsp.tgen.hdr.ctrl.reserved",
1352
16
                FT_UINT16, BASE_HEX,
1353
16
                NULL, 0xFFFE,
1354
16
                NULL, HFILL}
1355
16
        },
1356
16
        {&hf_avsp_tgen_hdr_seq_num,
1357
16
            {"Sequence Number", "avsp.tgen.hdr.seq_num",
1358
16
                FT_UINT16, BASE_DEC,
1359
16
                NULL, 0x0,
1360
16
                NULL, HFILL}
1361
16
        },
1362
16
        {&hf_avsp_tgen_hdr_payload_len,
1363
16
            {"Payload Length", "avsp.tgen.hdr.payload_len",
1364
16
                FT_UINT16, BASE_DEC,
1365
16
                NULL, 0x0,
1366
16
                NULL, HFILL}
1367
16
        },
1368
16
        { &hf_avsp_tgen_payload,
1369
16
            {"TGen Payload", "avsp.tgen.payload",
1370
16
                FT_NONE, BASE_NONE,
1371
16
                NULL, 0x0,
1372
16
                NULL, HFILL}
1373
16
        },
1374
16
        { &hf_avsp_tgen_payload_data,
1375
16
            {"Data", "avsp.tgen.payload.data",
1376
16
                FT_BYTES, BASE_NONE,
1377
16
                NULL, 0x0,
1378
16
                NULL, HFILL}
1379
16
        },
1380
16
    };
1381
1382
    /* Setup protocol subtree array */
1383
16
    static int* ett[] = {
1384
16
        &ett_avsp,               /* main avsp tree */
1385
16
        &ett_avsp_ts_48,         /* subtree above for 48 bit timestamp */
1386
16
        &ett_avsp_ts_64,         /* subtree above for 64 bit timestamp */
1387
16
        &ett_avsp_dzgre_a_hdr,   /* subtree for DzGRE plan A */
1388
16
        &ett_avsp_dzgre_b_hdr,   /* subtree for DzGRE plan B */
1389
16
        &ett_avsp_dzgre_ts_hdr,  /* subtree for DzGRE with timestamps */
1390
16
        &ett_avsp_dzgre_ts_tai,  /* subtree for DzGRE timestamp */
1391
16
        &ett_avsp_dzgre_ts_utc,  /* subtree for DzGRE timestamp */
1392
16
        &ett_avsp_greent_hdr,    /* subtree for GREENT header */
1393
16
        &ett_avsp_greent_sample_hdr,    /* subtree for GREENT sample header */
1394
16
        &ett_avsp_greent_sample_data,   /* subtree for GREENT sample data */
1395
16
        &ett_avsp_tgen_hdr,      /* subtree for TGen header */
1396
16
        &ett_avsp_tgen_hdr_ctrl, /* subtree for TGen header control bits */
1397
16
        &ett_avsp_tgen_payload,  /* subtree for TGen payload */
1398
16
    };
1399
1400
16
    static ei_register_info ei[] = {
1401
16
        { &ei_avsp_unknown_subtype, { "avsp.unknown_subtype", PI_SEQUENCE, PI_WARN, "Unknown AVSP subtype", EXPFILL}},
1402
16
        { &ei_avsp_ts_unknown_version, { "avsp.ts.unknown_version", PI_SEQUENCE, PI_WARN, "Unknown timestamp version", EXPFILL }},
1403
16
        { &ei_avsp_greentap_unknown_version, { "avsp.greentap.unknown_version", PI_SEQUENCE, PI_WARN, "Unknown GREENTAP version", EXPFILL }},
1404
16
        { &ei_avsp_greent_unknown_version, { "avsp.greent.unknown_version", PI_SEQUENCE, PI_WARN, "Unknown GREENT version", EXPFILL }},
1405
16
        { &ei_avsp_dzgre_a_unknown_version, { "avsp.dzgre_a.unknown_version", PI_SEQUENCE, PI_WARN, "Unknown DzGRE(A) version", EXPFILL }},
1406
16
        { &ei_avsp_dzgre_b_unknown_version, { "avsp.dzgre_b.unknown_version", PI_SEQUENCE, PI_WARN, "Unknown DzGRE(B) version", EXPFILL }},
1407
16
        { &ei_avsp_dzgre_ts_unknown_version, { "avsp.dzgre_ts.unknown_version", PI_SEQUENCE, PI_WARN, "Unknown DzGRE(timestamped) version", EXPFILL }},
1408
16
        { &ei_avsp_tgen_unknown_version, { "avsp.tgen.unknown_version", PI_SEQUENCE, PI_WARN, "Unknown TGen version", EXPFILL }},
1409
16
    };
1410
1411
    /* Register the AVSP protocol. */
1412
16
    proto_avsp = proto_register_protocol("Arista Vendor Specific Protocol", "AVSP", "avsp");
1413
1414
    /* Register header fields and subtrees. */
1415
16
    proto_register_field_array(proto_avsp, hf, array_length(hf));
1416
1417
    /*  Register subtree types. */
1418
16
    proto_register_subtree_array(ett, array_length(ett));
1419
1420
    /* Register the expert module. */
1421
16
    expert_register_field_array(expert_register_protocol(proto_avsp), ei, array_length(ei));
1422
1423
    /* Register the dissector handle. */
1424
16
    avsp_handle = register_dissector("avsp", dissect_avsp, proto_avsp);
1425
16
}
1426
1427
/*
1428
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1429
 *
1430
 * Local variables:
1431
 * c-basic-offset: 4
1432
 * tab-width: 8
1433
 * indent-tabs-mode: nil
1434
 * End:
1435
 *
1436
 * vi: set shiftwidth=4 tabstop=8 expandtab:
1437
 * :indentSize=4:tabSize=8:noTabs=true:
1438
 */