Coverage Report

Created: 2026-05-14 06:28

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
0
{
350
0
    volatile int offset = 0;
351
0
    uint32_t version, subtype, tgen_payload_len = 0;
352
0
    uint64_t tgen_ctrl;
353
0
    uint32_t tgen_seq_num, sample_len, count, u32;
354
0
    volatile uint32_t i; // potentially held across vfork
355
0
    const char* str;
356
0
    uint16_t encap_proto;
357
0
    ethertype_data_t ethertype_data;
358
0
    tvbuff_t* volatile tgen_payload_tvb = NULL;
359
360
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "AVSP");
361
0
    col_clear(pinfo->cinfo, COL_INFO);
362
363
0
    proto_item* avsp_ti, * ti;
364
0
    proto_tree* avsp_tree, * avsp_48_tree = NULL, * avsp_64_tree = NULL,
365
0
        * avsp_tgen_hdr = NULL, * avsp_tgen_payload = NULL,
366
0
        * avsp_dzgre_hdr = NULL, * avsp_greent_hdr = NULL,
367
0
        * avsp_greent_sample_hdr = NULL, *header_tree = NULL;
368
369
    /* Adding Items and Values to the Protocol Tree */
370
0
    avsp_ti = proto_tree_add_item(tree, proto_avsp, tvb, 0, -1,
371
0
        ENC_NA);
372
0
    avsp_tree = proto_item_add_subtree(avsp_ti, ett_avsp);
373
374
    /* add the subtype to avsp */
375
0
    proto_tree_add_item_ret_uint(avsp_tree, hf_avsp_subtype, tvb,
376
0
        offset, 2, ENC_BIG_ENDIAN, &subtype);
377
0
    str = try_val_to_str(subtype, arista_subtypes);
378
0
    if (str) {
379
0
        proto_item_append_text(avsp_ti, ", Subtype: %s", str);
380
0
    }
381
0
    offset += 2;
382
383
    /* Based on the subtype, add the version and further custom protocol fields */
384
0
    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
0
    default:
1001
0
        expert_add_info_format(pinfo, avsp_ti, &ei_avsp_unknown_subtype,
1002
0
            "Unknown subtype: 0x%0x", subtype);
1003
0
        return tvb_captured_length(tvb);
1004
0
    }
1005
0
    return tvb_captured_length(tvb);
1006
0
}
1007
1008
void proto_reg_handoff_avsp(void)
1009
15
{
1010
15
    dissector_add_uint("ethertype", ETHERTYPE_AVSP, avsp_handle);
1011
15
    ethertype_handle = find_dissector_add_dependency("ethertype", proto_avsp);
1012
15
    dissector_add_uint("gre.proto", ETHERTYPE_AVSP, avsp_handle);
1013
15
}
1014
1015
void proto_register_avsp(void)
1016
15
{
1017
    /* Field Registration */
1018
15
    static hf_register_info hf[] = {
1019
        /* For avsp */
1020
15
        {&hf_avsp_subtype,
1021
15
            {"Subtype", "avsp.subtype",
1022
15
                FT_UINT16, BASE_HEX,
1023
15
                VALS(arista_subtypes), 0x0,
1024
15
                NULL, HFILL}
1025
15
        },
1026
15
        {&hf_avsp_ts_version,
1027
15
            {"Version", "avsp.ts.ver",
1028
15
                FT_UINT16, BASE_HEX,
1029
15
                VALS(ts_versions), 0x0,
1030
15
                NULL, HFILL}
1031
15
        },
1032
15
        {&hf_avsp_ts_64_tai,
1033
15
            {"Timestamp (TAI)", "avsp.ts.64.tai",
1034
15
                FT_NONE, BASE_NONE,
1035
15
                NULL, 0x0,
1036
15
                NULL, HFILL}
1037
15
        },
1038
15
        {&hf_avsp_ts_64_utc,
1039
15
            {"Timestamp (UTC)", "avsp.ts.64.utc",
1040
15
                FT_NONE, BASE_NONE,
1041
15
                NULL, 0x0,
1042
15
                NULL, HFILL}
1043
15
        },
1044
15
        {&hf_avsp_ts_64_sec,
1045
15
            {"Seconds", "avsp.ts.64.sec",
1046
15
                FT_UINT32, BASE_DEC,
1047
15
                NULL, 0x0,
1048
15
                NULL, HFILL}
1049
15
        },
1050
15
        {&hf_avsp_ts_64_ns,
1051
15
            {"Nanoseconds", "avsp.ts.64.ns",
1052
15
                FT_UINT32, BASE_DEC,
1053
15
                NULL, 0x0,
1054
15
                NULL, HFILL}
1055
15
        },
1056
15
        {&hf_avsp_ts_48_tai,
1057
15
            {"Timestamp (TAI)", "avsp.ts.48.tai",
1058
15
                FT_NONE, BASE_NONE,
1059
15
                NULL, 0x0,
1060
15
                NULL, HFILL}
1061
15
        },
1062
15
        {&hf_avsp_ts_48_utc,
1063
15
            {"Timestamp (UTC)", "avsp.ts.48.utc",
1064
15
                FT_NONE, BASE_NONE,
1065
15
                NULL, 0x0,
1066
15
                NULL, HFILL}
1067
15
        },
1068
15
        {&hf_avsp_ts_48_sec,
1069
15
            {"Seconds", "avsp.ts.48.sec",
1070
15
                FT_UINT16, BASE_DEC,
1071
15
                NULL, 0x0,
1072
15
                NULL, HFILL}
1073
15
        },
1074
15
        {&hf_avsp_ts_48_ns,
1075
15
            {"Nanoseconds", "avsp.ts.48.ns",
1076
15
                FT_UINT32, BASE_DEC,
1077
15
                NULL, 0x0,
1078
15
                NULL, HFILL}
1079
15
        },
1080
15
        {&hf_avsp_etype,
1081
15
            {"Type", "avsp.etype",
1082
15
                FT_UINT16, BASE_HEX,
1083
15
                VALS(etype_vals), 0x0,
1084
15
                "Ethertype", HFILL}
1085
15
        },
1086
15
        {&hf_avsp_trailer,
1087
15
            {"Trailer", "avsp.trailer",
1088
15
                FT_BYTES, BASE_NONE,
1089
15
                NULL, 0x0,
1090
15
                "AVSP Trailer", HFILL}
1091
15
        },
1092
15
        {&hf_avsp_greentap_version,
1093
15
            {"Version", "avsp.greentap.ver",
1094
15
                FT_UINT16, BASE_DEC,
1095
15
                VALS(greentap_versions), 0x0,
1096
15
                NULL, HFILL}
1097
15
        },
1098
15
        {&hf_avsp_greentap_tai,
1099
15
            {"Timestamp (TAI)", "avsp.greentap.tai",
1100
15
                FT_NONE, BASE_NONE,
1101
15
                NULL, 0x0,
1102
15
                NULL, HFILL}
1103
15
        },
1104
15
        {&hf_avsp_greentap_utc,
1105
15
            {"Timestamp (UTC)", "avsp.greentap.utc",
1106
15
                FT_NONE, BASE_NONE,
1107
15
                NULL, 0x0,
1108
15
                NULL, HFILL}
1109
15
        },
1110
15
        {&hf_avsp_greentap_sec,
1111
15
            {"Seconds", "avsp.greentap.sec",
1112
15
                FT_UINT16, BASE_DEC,
1113
15
                NULL, 0x0,
1114
15
                NULL, HFILL}
1115
15
        },
1116
15
        {&hf_avsp_greentap_ns,
1117
15
            {"Nanoseconds", "avsp.greentap.ns",
1118
15
                FT_UINT32, BASE_DEC,
1119
15
                NULL, 0x0,
1120
15
                NULL, HFILL}
1121
15
        },
1122
15
        {&hf_avsp_greent_version,
1123
15
            {"Version", "avsp.greent.ver",
1124
15
                FT_UINT16, BASE_DEC,
1125
15
                VALS(greent_versions), 0x0,
1126
15
                NULL, HFILL}
1127
15
        },
1128
15
        {&hf_avsp_greent_hdr,
1129
15
            {"GREENT Header", "avsp.greent.hdr",
1130
15
                FT_NONE, BASE_NONE,
1131
15
                NULL, 0x0,
1132
15
                NULL, HFILL}
1133
15
        },
1134
15
        {&hf_avsp_greent_session,
1135
15
            {"Session ID", "avsp.greent.session",
1136
15
                FT_UINT16, BASE_DEC,
1137
15
                NULL, 0x0,
1138
15
                NULL, HFILL}
1139
15
        },
1140
15
        {&hf_avsp_greent_flags,
1141
15
            {"Flags", "avsp.greent.flags",
1142
15
                FT_UINT8, BASE_HEX,
1143
15
                NULL, 0x0,
1144
15
                NULL, HFILL}
1145
15
        },
1146
15
        {&hf_avsp_greent_sample_count,
1147
15
            {"Sample Count", "avsp.greent.sample_count",
1148
15
                FT_UINT8, BASE_DEC,
1149
15
                NULL, 0x0,
1150
15
                NULL, HFILL}
1151
15
        },
1152
15
        {&hf_avsp_greent_sample_hdr,
1153
15
            {"Sample Header", "avsp.greent.sample.hdr",
1154
15
                FT_NONE, BASE_NONE,
1155
15
                NULL, 0x0,
1156
15
                NULL, HFILL}
1157
15
        },
1158
15
        {&hf_avsp_greent_sample_len,
1159
15
            {"Length", "avsp.greent.sample.len",
1160
15
                FT_UINT16, BASE_DEC,
1161
15
                NULL, 0x0,
1162
15
                NULL, HFILL}
1163
15
        },
1164
15
        {&hf_avsp_greent_sample_sec,
1165
15
            {"Seconds", "avsp.greent.sample.sec",
1166
15
                FT_UINT16, BASE_DEC,
1167
15
                NULL, 0x0,
1168
15
                NULL, HFILL}
1169
15
        },
1170
15
        {&hf_avsp_greent_sample_ns,
1171
15
            {"Nanoseconds", "avsp.greent.sample.ns",
1172
15
                FT_UINT32, BASE_DEC,
1173
15
                NULL, 0x0,
1174
15
                NULL, HFILL}
1175
15
        },
1176
15
        {&hf_avsp_greent_sample_ingress,
1177
15
            {"Ingress Interface", "avsp.greent.sample.ingress",
1178
15
                FT_UINT32, BASE_DEC,
1179
15
                NULL, 0x0,
1180
15
                NULL, HFILL}
1181
15
        },
1182
15
        {&hf_avsp_greent_sample_egress,
1183
15
            {"Egress Interface", "avsp.greent.sample.egress",
1184
15
                FT_UINT32, BASE_DEC,
1185
15
                NULL, 0x0,
1186
15
                NULL, HFILL}
1187
15
        },
1188
15
        {&hf_avsp_greent_sample_rate,
1189
15
            {"Rate(*1K)", "avsp.greent.sample.rate",
1190
15
                FT_UINT16, BASE_DEC,
1191
15
                NULL, 0x0,
1192
15
                NULL, HFILL}
1193
15
        },
1194
15
        {&hf_avsp_greent_sample_sum,
1195
15
            {"Checksum", "avsp.greent.sample.sum",
1196
15
                FT_UINT16, BASE_HEX,
1197
15
                NULL, 0x0,
1198
15
                NULL, HFILL}
1199
15
        },
1200
15
        {&hf_avsp_greent_sample_data,
1201
15
            {"Header of sampled packet", "avsp.greent.sample.data",
1202
15
                FT_BYTES, BASE_NONE,
1203
15
                NULL, 0x0,
1204
15
                "Data from sampled header", HFILL}
1205
15
        },
1206
15
        {&hf_avsp_dzgre_a_version,
1207
15
            {"Version", "avsp.dzgre_a.ver",
1208
15
                FT_UINT16, BASE_DEC,
1209
15
                VALS(dzgre_a_versions), 0x0,
1210
15
                NULL, HFILL}
1211
15
        },
1212
15
        {&hf_avsp_dzgre_a_hdr,
1213
15
            {"DzGRE(A) Header", "avsp.dzgre_a.hdr",
1214
15
                FT_NONE, BASE_NONE,
1215
15
                NULL, 0x0,
1216
15
                NULL, HFILL}
1217
15
        },
1218
15
        {&hf_avsp_dzgre_a_switch,
1219
15
            {"Switch ID", "avsp.dzgre_a.switch",
1220
15
                FT_UINT16, BASE_DEC,
1221
15
                NULL, 0x0,
1222
15
                NULL, HFILL}
1223
15
        },
1224
15
        {&hf_avsp_dzgre_a_port,
1225
15
            {"Port ID", "avsp.dzgre_a.port",
1226
15
                FT_UINT16, BASE_DEC,
1227
15
                NULL, 0x0,
1228
15
                NULL, HFILL}
1229
15
        },
1230
15
        {&hf_avsp_dzgre_a_policy,
1231
15
            {"Policy ID", "avsp.dzgre_a.policy",
1232
15
                FT_UINT16, BASE_DEC,
1233
15
                NULL, 0x0,
1234
15
                NULL, HFILL}
1235
15
        },
1236
15
        {&hf_avsp_dzgre_a_reserved,
1237
15
            {"Reserved", "avsp.dzgre_a.reserved",
1238
15
                FT_UINT16, BASE_HEX,
1239
15
                NULL, 0x0,
1240
15
                NULL, HFILL}
1241
15
        },
1242
15
        {&hf_avsp_dzgre_b_version,
1243
15
            {"Version", "avsp.dzgre_b.ver",
1244
15
                FT_UINT16, BASE_DEC,
1245
15
                VALS(dzgre_b_versions), 0x0,
1246
15
                NULL, HFILL}
1247
15
        },
1248
15
        {&hf_avsp_dzgre_b_hdr,
1249
15
            {"DzGRE(B) Header", "avsp.dzgre_b.hdr",
1250
15
                FT_NONE, BASE_NONE,
1251
15
                NULL, 0x0,
1252
15
                NULL, HFILL}
1253
15
        },
1254
15
        {&hf_avsp_dzgre_b_port,
1255
15
            {"Port ID", "avsp.dzgre_b.port",
1256
15
                FT_UINT16, BASE_DEC,
1257
15
                NULL, 0x0,
1258
15
                NULL, HFILL}
1259
15
        },
1260
15
        {&hf_avsp_dzgre_b_policy,
1261
15
            {"Policy ID", "avsp.dzgre_b.policy",
1262
15
                FT_UINT16, BASE_DEC,
1263
15
                NULL, 0x0,
1264
15
                NULL, HFILL}
1265
15
        },
1266
15
        {&hf_avsp_dzgre_ts_version,
1267
15
            {"Version", "avsp.dzgre_ts.ver",
1268
15
                FT_UINT16, BASE_DEC,
1269
15
                VALS(dzgre_ts_versions), 0x0,
1270
15
                NULL, HFILL}
1271
15
        },
1272
15
        {&hf_avsp_dzgre_ts_hdr,
1273
15
            {"DzGRE(B) Header", "avsp.dzgre_ts.hdr",
1274
15
                FT_NONE, BASE_NONE,
1275
15
                NULL, 0x0,
1276
15
                NULL, HFILL}
1277
15
        },
1278
15
        {&hf_avsp_dzgre_ts_switch,
1279
15
            {"Switch ID", "avsp.dzgre_ts.switch",
1280
15
                FT_UINT16, BASE_DEC,
1281
15
                NULL, 0x0,
1282
15
                NULL, HFILL}
1283
15
        },
1284
15
        {&hf_avsp_dzgre_ts_port,
1285
15
            {"Port ID", "avsp.dzgre_ts.port",
1286
15
                FT_UINT16, BASE_DEC,
1287
15
                NULL, 0x0,
1288
15
                NULL, HFILL}
1289
15
        },
1290
15
        {&hf_avsp_dzgre_ts_policy,
1291
15
            {"Policy ID", "avsp.dzgre_ts.policy",
1292
15
                FT_UINT16, BASE_DEC,
1293
15
                NULL, 0x0,
1294
15
                NULL, HFILL}
1295
15
        },
1296
15
        {&hf_avsp_dzgre_ts_reserved,
1297
15
            {"Reserved", "avsp.dzgre_ts.reserved",
1298
15
                FT_UINT16, BASE_HEX,
1299
15
                NULL, 0x0,
1300
15
                NULL, HFILL}
1301
15
        },
1302
15
        {&hf_avsp_dzgre_ts_tai,
1303
15
            {"Timestamp (TAI)", "avsp.dzgre_ts.tai",
1304
15
                FT_NONE, BASE_NONE,
1305
15
                NULL, 0x0,
1306
15
                NULL, HFILL}
1307
15
        },
1308
15
        {&hf_avsp_dzgre_ts_utc,
1309
15
            {"Timestamp (UTC)", "avsp.dzgre_ts.utc",
1310
15
                FT_NONE, BASE_NONE,
1311
15
                NULL, 0x0,
1312
15
                NULL, HFILL}
1313
15
        },
1314
15
        {&hf_avsp_dzgre_ts_sec,
1315
15
            {"Seconds", "avsp.ts.dzgre_ts.sec",
1316
15
                FT_UINT32, BASE_DEC,
1317
15
                NULL, 0x0,
1318
15
                NULL, HFILL}
1319
15
        },
1320
15
        {&hf_avsp_dzgre_ts_ns,
1321
15
            {"Nanoseconds", "avsp.dzgre_ts.48.ns",
1322
15
                FT_UINT32, BASE_DEC,
1323
15
                NULL, 0x0,
1324
15
                NULL, HFILL}
1325
15
        },
1326
15
        {&hf_avsp_tgen_version,
1327
15
            {"Version", "avsp.tgen.ver",
1328
15
                FT_UINT16, BASE_DEC,
1329
15
                VALS(tgen_versions), 0x0,
1330
15
                NULL, HFILL}
1331
15
        },
1332
15
        {&hf_avsp_tgen_hdr,
1333
15
            {"TGen Header", "avsp.tgen.hdr",
1334
15
                FT_NONE, BASE_NONE,
1335
15
                NULL, 0x0,
1336
15
                NULL, HFILL}
1337
15
        },
1338
15
        {&hf_avsp_tgen_hdr_ctrl,
1339
15
            {"Control Word", "avsp.tgen.hdr.ctrl",
1340
15
                FT_UINT16, BASE_HEX,
1341
15
                NULL, 0x0,
1342
15
                NULL, HFILL}
1343
15
        },
1344
15
        {&hf_avsp_tgen_hdr_ctrl_fcs_inverted,
1345
15
            {"FCS Inverted", "avsp.tgen.hdr.ctrl.fcs_inverted",
1346
15
                FT_BOOLEAN, 16,
1347
15
                NULL, 0x0001,
1348
15
                NULL, HFILL}
1349
15
        },
1350
15
        {&hf_avsp_tgen_hdr_ctrl_reserved,
1351
15
            {"Reserved", "avsp.tgen.hdr.ctrl.reserved",
1352
15
                FT_UINT16, BASE_HEX,
1353
15
                NULL, 0xFFFE,
1354
15
                NULL, HFILL}
1355
15
        },
1356
15
        {&hf_avsp_tgen_hdr_seq_num,
1357
15
            {"Sequence Number", "avsp.tgen.hdr.seq_num",
1358
15
                FT_UINT16, BASE_DEC,
1359
15
                NULL, 0x0,
1360
15
                NULL, HFILL}
1361
15
        },
1362
15
        {&hf_avsp_tgen_hdr_payload_len,
1363
15
            {"Payload Length", "avsp.tgen.hdr.payload_len",
1364
15
                FT_UINT16, BASE_DEC,
1365
15
                NULL, 0x0,
1366
15
                NULL, HFILL}
1367
15
        },
1368
15
        { &hf_avsp_tgen_payload,
1369
15
            {"TGen Payload", "avsp.tgen.payload",
1370
15
                FT_NONE, BASE_NONE,
1371
15
                NULL, 0x0,
1372
15
                NULL, HFILL}
1373
15
        },
1374
15
        { &hf_avsp_tgen_payload_data,
1375
15
            {"Data", "avsp.tgen.payload.data",
1376
15
                FT_BYTES, BASE_NONE,
1377
15
                NULL, 0x0,
1378
15
                NULL, HFILL}
1379
15
        },
1380
15
    };
1381
1382
    /* Setup protocol subtree array */
1383
15
    static int* ett[] = {
1384
15
        &ett_avsp,               /* main avsp tree */
1385
15
        &ett_avsp_ts_48,         /* subtree above for 48 bit timestamp */
1386
15
        &ett_avsp_ts_64,         /* subtree above for 64 bit timestamp */
1387
15
        &ett_avsp_dzgre_a_hdr,   /* subtree for DzGRE plan A */
1388
15
        &ett_avsp_dzgre_b_hdr,   /* subtree for DzGRE plan B */
1389
15
        &ett_avsp_dzgre_ts_hdr,  /* subtree for DzGRE with timestamps */
1390
15
        &ett_avsp_dzgre_ts_tai,  /* subtree for DzGRE timestamp */
1391
15
        &ett_avsp_dzgre_ts_utc,  /* subtree for DzGRE timestamp */
1392
15
        &ett_avsp_greent_hdr,    /* subtree for GREENT header */
1393
15
        &ett_avsp_greent_sample_hdr,    /* subtree for GREENT sample header */
1394
15
        &ett_avsp_greent_sample_data,   /* subtree for GREENT sample data */
1395
15
        &ett_avsp_tgen_hdr,      /* subtree for TGen header */
1396
15
        &ett_avsp_tgen_hdr_ctrl, /* subtree for TGen header control bits */
1397
15
        &ett_avsp_tgen_payload,  /* subtree for TGen payload */
1398
15
    };
1399
1400
15
    static ei_register_info ei[] = {
1401
15
        { &ei_avsp_unknown_subtype, { "avsp.unknown_subtype", PI_SEQUENCE, PI_WARN, "Unknown AVSP subtype", EXPFILL}},
1402
15
        { &ei_avsp_ts_unknown_version, { "avsp.ts.unknown_version", PI_SEQUENCE, PI_WARN, "Unknown timestamp version", EXPFILL }},
1403
15
        { &ei_avsp_greentap_unknown_version, { "avsp.greentap.unknown_version", PI_SEQUENCE, PI_WARN, "Unknown GREENTAP version", EXPFILL }},
1404
15
        { &ei_avsp_greent_unknown_version, { "avsp.greent.unknown_version", PI_SEQUENCE, PI_WARN, "Unknown GREENT version", EXPFILL }},
1405
15
        { &ei_avsp_dzgre_a_unknown_version, { "avsp.dzgre_a.unknown_version", PI_SEQUENCE, PI_WARN, "Unknown DzGRE(A) version", EXPFILL }},
1406
15
        { &ei_avsp_dzgre_b_unknown_version, { "avsp.dzgre_b.unknown_version", PI_SEQUENCE, PI_WARN, "Unknown DzGRE(B) version", EXPFILL }},
1407
15
        { &ei_avsp_dzgre_ts_unknown_version, { "avsp.dzgre_ts.unknown_version", PI_SEQUENCE, PI_WARN, "Unknown DzGRE(timestamped) version", EXPFILL }},
1408
15
        { &ei_avsp_tgen_unknown_version, { "avsp.tgen.unknown_version", PI_SEQUENCE, PI_WARN, "Unknown TGen version", EXPFILL }},
1409
15
    };
1410
1411
    /* Register the AVSP protocol. */
1412
15
    proto_avsp = proto_register_protocol("Arista Vendor Specific Protocol", "AVSP", "avsp");
1413
1414
    /* Register header fields and subtrees. */
1415
15
    proto_register_field_array(proto_avsp, hf, array_length(hf));
1416
1417
    /*  Register subtree types. */
1418
15
    proto_register_subtree_array(ett, array_length(ett));
1419
1420
    /* Register the expert module. */
1421
15
    expert_register_field_array(expert_register_protocol(proto_avsp), ei, array_length(ei));
1422
1423
    /* Register the dissector handle. */
1424
15
    avsp_handle = register_dissector("avsp", dissect_avsp, proto_avsp);
1425
15
}
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
 */