Coverage Report

Created: 2025-02-15 06:25

/src/wireshark/epan/dissectors/packet-geneve.c
Line
Count
Source (jump to first uncovered line)
1
/* packet-geneve.c
2
 * Routines for Geneve - Generic Network Virtualization Encapsulation
3
 * https://tools.ietf.org/html/draft-ietf-nvo3-geneve
4
 *
5
 * Copyright (c) 2024 cPacket Networks, Inc. All Rights Reserved.
6
 * Author: Martin Greenberg <mgreenberg@cpacket.com>
7
 *
8
 * Copyright (c) 2014 VMware, Inc. All Rights Reserved.
9
 * Author: Jesse Gross <jesse@nicira.com>
10
 *
11
 * Copyright 2021, Atul Sharma <asharm37@ncsu.edu>
12
 *
13
 * Wireshark - Network traffic analyzer
14
 * By Gerald Combs <gerald@wireshark.org>
15
 * Copyright 1998 Gerald Combs
16
 *
17
 * SPDX-License-Identifier: GPL-2.0-or-later
18
 */
19
20
21
#include "config.h"
22
23
#include <epan/packet.h>
24
#include <epan/etypes.h>
25
#include <epan/expert.h>
26
#include <epan/value_string.h>
27
#include <epan/tfs.h>
28
#include <epan/unit_strings.h>
29
30
14
#define UDP_PORT_GENEVE  6081
31
2.22k
#define GENEVE_VER 0
32
33
2.22k
#define VER_SHIFT 6
34
2.22k
#define HDR_OPTS_LEN_MASK 0x3F
35
36
2.22k
#define FLAG_OAM (1 << 7)
37
38
1.19k
#define OPT_TYPE_CRITICAL (1 << 7)
39
1.19k
#define OPT_FLAGS_SHIFT 5
40
1.53k
#define OPT_LEN_MASK 0x1F
41
42
static const range_string class_id_names[] = {
43
    { 0, 0xFF, "Standard" },
44
    { 0x0100, 0x0100, "Linux" },
45
    { 0x0101, 0x0101, "Open vSwitch" },
46
    { 0x0102, 0x0102, "Open Virtual Networking (OVN)" },
47
    { 0x0103, 0x0103, "In-band Network Telemetry (INT)" },
48
    { 0x0104, 0x0104, "VMware" },
49
    { 0x0105, 0x0105, "Amazon.com, Inc."},
50
    { 0x0106, 0x0106, "Cisco Systems, Inc." },
51
    { 0x0107, 0x0107, "Oracle Corporation" },
52
    { 0x0108, 0x0110, "Amazon.com, Inc." },
53
    { 0x0111, 0x0118, "IBM" },
54
    { 0x0119, 0x0128, "Ericsson" },
55
    { 0x0129, 0x0129, "Oxide Computer Company" },
56
    { 0x0130, 0x0131, "Cisco Systems, Inc." },
57
    { 0x0132, 0x0135, "Google LLC" },
58
    { 0x0136, 0x0136, "InfoQuick Global Connection Tech Ltd." },
59
    { 0x0137, 0x0163, "Unssigned" },
60
    { 0x0164, 0x0164, "cPacket Networks, Inc." },
61
    { 0x0165, 0xFEFF, "Unassigned" },
62
    { 0xFFF0, 0xFFFF, "Experimental" },
63
    { 0, 0, NULL }
64
};
65
66
0
#define GENEVE_GCP_VNID     0x013201
67
0
#define GENEVE_GCP_ENDPOINT 0x013202
68
0
#define GENEVE_GCP_PROFILE  0x013203
69
0
#define GENEVE_CPACKET_METADATA  0x016400
70
71
static const val64_string option_names[] = {
72
  { GENEVE_GCP_VNID,     "GCP Virtual Network ID" },
73
  { GENEVE_GCP_ENDPOINT, "GCP Endpoint ID" },
74
  { GENEVE_GCP_PROFILE,  "GCP Profile ID" },
75
  { GENEVE_CPACKET_METADATA,  "cPacket Meta-data" },
76
  { 0, NULL }
77
};
78
79
void proto_register_geneve(void);
80
void proto_reg_handoff_geneve(void);
81
82
static dissector_handle_t geneve_handle;
83
84
static int proto_geneve;
85
86
static int hf_geneve_version;
87
static int hf_geneve_flags;
88
static int hf_geneve_flag_oam;
89
static int hf_geneve_flag_critical;
90
static int hf_geneve_flag_reserved;
91
static int hf_geneve_proto_type;
92
static int hf_geneve_vni;
93
static int hf_geneve_reserved;
94
static int hf_geneve_options;
95
static int hf_geneve_option_class;
96
static int hf_geneve_option_type;
97
static int hf_geneve_option_type_critical;
98
static int hf_geneve_option_flags;
99
static int hf_geneve_option_flags_reserved;
100
static int hf_geneve_option_length;
101
static int hf_geneve_option;
102
static int hf_geneve_opt_gcp_vnid;
103
static int hf_geneve_opt_gcp_reserved;
104
static int hf_geneve_opt_gcp_direction;
105
static int hf_geneve_opt_gcp_endpoint;
106
static int hf_geneve_opt_gcp_profile;
107
static int hf_geneve_opt_cpkt_seqnum;
108
static int hf_geneve_opt_cpkt_origlen;
109
static int hf_geneve_opt_cpkt_reserved;
110
static int hf_geneve_opt_cpkt_timestamp;
111
static int hf_geneve_opt_cpkt_ts_sec;
112
static int hf_geneve_opt_cpkt_ts_nsec;
113
static int hf_geneve_opt_cpkt_ts_fracns;
114
static int hf_geneve_opt_cpkt_version;
115
static int hf_geneve_opt_cpkt_devid;
116
static int hf_geneve_opt_cpkt_portid;
117
118
static int hf_geneve_opt_unknown_data;
119
120
static int ett_geneve;
121
static int ett_geneve_flags;
122
static int ett_geneve_opt_flags;
123
static int ett_geneve_options;
124
static int ett_geneve_opt_data;
125
126
static expert_field ei_geneve_ver_unknown;
127
static expert_field ei_geneve_opt_len_invalid;
128
129
static dissector_table_t ethertype_dissector_table;
130
131
static const struct true_false_string tfs_geneve_gcp_direction = {
132
  "Egress",
133
  "Ingress"
134
};
135
136
static const char *
137
format_option_name(wmem_allocator_t *scope, uint16_t opt_class, uint8_t opt_type)
138
1.53k
{
139
1.53k
    const char *name;
140
141
1.53k
    name = wmem_strdup_printf(scope,
142
1.53k
                              "%s, Class: %s (0x%04x) Type: 0x%02x",
143
1.53k
                              val64_to_str_const(((uint64_t)opt_class << 8) | opt_type,
144
1.53k
                                                 option_names, "Unknown"),
145
1.53k
                              rval_to_str_const(opt_class, class_id_names, "Unknown"),
146
1.53k
                              opt_class, opt_type);
147
148
1.53k
    return name;
149
1.53k
}
150
151
static void
152
dissect_option(wmem_allocator_t *scope, tvbuff_t *tvb, proto_tree *opts_tree, int offset,
153
               uint16_t opt_class, uint8_t opt_type, int len)
154
1.19k
{
155
1.19k
    proto_item *opt_item, *type_item, *hidden_item, *flag_item;
156
1.19k
    proto_tree *opt_tree, *flag_tree;
157
1.19k
    const char *critical;
158
1.19k
    uint8_t flags;
159
160
1.19k
    critical = opt_type & OPT_TYPE_CRITICAL ? "Critical" : "Non-critical";
161
162
1.19k
    opt_item = proto_tree_add_item(opts_tree, hf_geneve_option,
163
1.19k
                                   tvb, offset, len, ENC_NA);
164
1.19k
    proto_item_set_text(opt_item, "%s (%s)",
165
1.19k
                        format_option_name(scope, opt_class, opt_type),
166
1.19k
                        critical);
167
168
1.19k
    opt_tree = proto_item_add_subtree(opt_item, ett_geneve_opt_data);
169
170
1.19k
    proto_tree_add_item(opt_tree, hf_geneve_option_class, tvb,
171
1.19k
                        offset, 2, ENC_BIG_ENDIAN);
172
1.19k
    offset += 2;
173
174
1.19k
    type_item = proto_tree_add_item(opt_tree, hf_geneve_option_type, tvb,
175
1.19k
                                    offset, 1, ENC_BIG_ENDIAN);
176
1.19k
    proto_item_append_text(type_item, " (%s)", critical);
177
1.19k
    hidden_item = proto_tree_add_item(opt_tree, hf_geneve_option_type_critical,
178
1.19k
                                      tvb, offset, 1, ENC_BIG_ENDIAN);
179
1.19k
    proto_item_set_hidden(hidden_item);
180
1.19k
    offset += 1;
181
182
1.19k
    flags = tvb_get_uint8(tvb, offset) >> OPT_FLAGS_SHIFT;
183
1.19k
    flag_item = proto_tree_add_uint(opt_tree, hf_geneve_option_flags, tvb,
184
1.19k
                                    offset, 1, flags);
185
1.19k
    flag_tree = proto_item_add_subtree(flag_item, ett_geneve_opt_flags);
186
1.19k
    proto_tree_add_item(flag_tree, hf_geneve_option_flags_reserved, tvb,
187
1.19k
                        offset, 1, ENC_BIG_ENDIAN);
188
1.19k
    if (flags) {
189
309
        proto_item_append_text(flag_item, " (RSVD)");
190
884
    } else {
191
884
        proto_item_set_hidden(flag_item);
192
884
    }
193
194
1.19k
    proto_tree_add_uint(opt_tree, hf_geneve_option_length, tvb, offset, 1, len);
195
1.19k
    offset += 1;
196
197
1.19k
    switch (((uint64_t)opt_class << 8) | opt_type) {
198
0
        case GENEVE_GCP_VNID:
199
0
            proto_tree_add_bits_item(opt_tree, hf_geneve_opt_gcp_vnid, tvb, offset * 8,
200
0
                                     28, ENC_BIG_ENDIAN);
201
0
            proto_tree_add_item(opt_tree, hf_geneve_opt_gcp_direction, tvb, offset,
202
0
                                4, ENC_NA);
203
0
            proto_tree_add_item(opt_tree, hf_geneve_opt_gcp_reserved, tvb, offset,
204
0
                                4, ENC_NA);
205
0
            break;
206
0
        case GENEVE_GCP_ENDPOINT:
207
0
            proto_tree_add_item(opt_tree, hf_geneve_opt_gcp_endpoint, tvb, offset,
208
0
                                len - 4, ENC_NA);
209
0
            break;
210
0
        case GENEVE_GCP_PROFILE:
211
0
            proto_tree_add_item(opt_tree, hf_geneve_opt_gcp_profile, tvb, offset,
212
0
                                len - 4, ENC_BIG_ENDIAN);
213
0
            break;
214
0
        case GENEVE_CPACKET_METADATA:
215
0
            proto_tree_add_item(opt_tree, hf_geneve_opt_cpkt_seqnum, tvb, offset,
216
0
                                4, ENC_BIG_ENDIAN);
217
0
            offset += 4;
218
0
            proto_tree_add_item(opt_tree, hf_geneve_opt_cpkt_origlen, tvb, offset,
219
0
                                2, ENC_BIG_ENDIAN);
220
0
            offset += 2;
221
0
            proto_tree_add_item(opt_tree, hf_geneve_opt_cpkt_reserved, tvb, offset,
222
0
                                1, ENC_BIG_ENDIAN);
223
0
            offset += 1;
224
0
            proto_tree_add_item(opt_tree, hf_geneve_opt_cpkt_version, tvb, offset,
225
0
                                1, ENC_BIG_ENDIAN);
226
0
            offset += 1;
227
            // PTPv2 timestamp has more resolution than NStime supports/displays,
228
            // but parse appropriate subsection of into NStime for user convenience
229
0
            proto_tree_add_time_item(opt_tree, hf_geneve_opt_cpkt_timestamp, tvb, offset+2, 8,
230
0
                                     ENC_TIME_SECS_NSECS, NULL, NULL, NULL);
231
0
            proto_tree_add_item(opt_tree, hf_geneve_opt_cpkt_ts_sec, tvb, offset,
232
0
                                6, ENC_BIG_ENDIAN);
233
0
            offset += 6;
234
0
            proto_tree_add_item(opt_tree, hf_geneve_opt_cpkt_ts_nsec, tvb, offset,
235
0
                                4, ENC_BIG_ENDIAN);
236
0
            offset += 4;
237
0
            proto_tree_add_item(opt_tree, hf_geneve_opt_cpkt_ts_fracns, tvb, offset,
238
0
                                2, ENC_BIG_ENDIAN);
239
0
            offset += 2;
240
0
            proto_tree_add_item(opt_tree, hf_geneve_opt_cpkt_devid, tvb, offset,
241
0
                                2, ENC_BIG_ENDIAN);
242
0
            offset += 2;
243
0
            proto_tree_add_item(opt_tree, hf_geneve_opt_cpkt_portid, tvb, offset,
244
0
                                2, ENC_BIG_ENDIAN);
245
0
            break;
246
1.19k
        default:
247
1.19k
            proto_tree_add_item(opt_tree, hf_geneve_opt_unknown_data, tvb, offset,
248
1.19k
                                len - 4, ENC_NA);
249
1.19k
            break;
250
1.19k
    }
251
1.19k
}
252
253
static void
254
dissect_geneve_options(tvbuff_t *tvb, packet_info *pinfo,
255
                       proto_tree *geneve_tree, int offset, int len)
256
386
{
257
386
    proto_item *opts_item;
258
386
    proto_tree *opts_tree;
259
386
    uint16_t opt_class;
260
386
    uint8_t opt_type;
261
386
    uint8_t opt_len;
262
263
386
    opts_item = proto_tree_add_item(geneve_tree, hf_geneve_options, tvb,
264
386
                                    offset, len, ENC_NA);
265
386
    proto_item_set_text(opts_item, "Options: (%u bytes)", len);
266
386
    opts_tree = proto_item_add_subtree(opts_item, ett_geneve_options);
267
268
1.57k
    while (len > 0) {
269
1.53k
        opt_class = tvb_get_ntohs(tvb, offset);
270
1.53k
        opt_type = tvb_get_uint8(tvb, offset + 2);
271
1.53k
        opt_len = 4 + ((tvb_get_uint8(tvb, offset + 3) & OPT_LEN_MASK) * 4);
272
273
1.53k
        if (opt_len > len) {
274
337
            proto_tree_add_expert_format(opts_tree, pinfo,
275
337
                                         &ei_geneve_opt_len_invalid, tvb,
276
337
                                         offset + 3, 1,
277
337
                                         "%s (length of %u is past end of options)",
278
337
                                         format_option_name(pinfo->pool, opt_class, opt_type),
279
337
                                         opt_len);
280
337
            return;
281
337
        }
282
283
1.19k
        dissect_option(pinfo->pool, tvb, opts_tree, offset, opt_class, opt_type, opt_len);
284
285
1.19k
        offset += opt_len;
286
1.19k
        len -= opt_len;
287
1.19k
    };
288
49
}
289
290
static int
291
dissect_geneve(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
292
2.22k
{
293
2.22k
    proto_item *ti, *rsvd_item;
294
2.22k
    proto_tree *geneve_tree;
295
2.22k
    tvbuff_t *next_tvb;
296
2.22k
    int offset = 0;
297
2.22k
    uint8_t ver_opt;
298
2.22k
    uint8_t ver;
299
2.22k
    uint8_t flags;
300
2.22k
    uint16_t proto_type;
301
2.22k
    int opts_len;
302
2.22k
    static int * const flag_fields[] = {
303
2.22k
        &hf_geneve_flag_oam,
304
2.22k
        &hf_geneve_flag_critical,
305
2.22k
        &hf_geneve_flag_reserved,
306
2.22k
        NULL
307
2.22k
    };
308
309
2.22k
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "Geneve");
310
2.22k
    col_clear(pinfo->cinfo, COL_INFO);
311
312
2.22k
    ti = proto_tree_add_item(tree, proto_geneve, tvb, offset, -1, ENC_NA);
313
2.22k
    geneve_tree = proto_item_add_subtree(ti, ett_geneve);
314
315
    /* Version. */
316
2.22k
    ver_opt = tvb_get_uint8(tvb, offset);
317
2.22k
    ver = ver_opt >> VER_SHIFT;
318
2.22k
    proto_tree_add_uint(geneve_tree, hf_geneve_version, tvb,
319
2.22k
                        offset, 1, ver);
320
321
2.22k
    if (ver != GENEVE_VER) {
322
731
        proto_tree_add_expert_format(geneve_tree, pinfo,
323
731
                                     &ei_geneve_ver_unknown, tvb, offset, 1,
324
731
                                     "Unknown version %u", ver);
325
731
        col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown Geneve version %u", ver);
326
731
    }
327
328
    /* Option length. */
329
2.22k
    opts_len = (ver_opt & HDR_OPTS_LEN_MASK) * 4;
330
2.22k
    proto_tree_add_uint(geneve_tree, hf_geneve_option_length, tvb,
331
2.22k
                                     offset, 1, opts_len);
332
2.22k
    offset += 1;
333
334
    /* Flags. */
335
2.22k
    flags = tvb_get_uint8(tvb, offset);
336
2.22k
    proto_tree_add_bitmask(geneve_tree, tvb, offset, hf_geneve_flags, ett_geneve_flags, flag_fields, ENC_BIG_ENDIAN);
337
2.22k
    offset += 1;
338
339
    /* Protocol Type. */
340
2.22k
    proto_tree_add_item(geneve_tree, hf_geneve_proto_type, tvb,
341
2.22k
                        offset, 2, ENC_BIG_ENDIAN);
342
343
2.22k
    proto_type = tvb_get_ntohs(tvb, offset);
344
2.22k
    col_add_fstr(pinfo->cinfo, COL_INFO, "Encapsulated %s",
345
2.22k
                 val_to_str(proto_type, etype_vals, "0x%04x (unknown)"));
346
347
2.22k
    offset += 2;
348
349
    /* VNI. */
350
2.22k
    proto_tree_add_item(geneve_tree, hf_geneve_vni, tvb, offset, 3,
351
2.22k
                        ENC_BIG_ENDIAN);
352
2.22k
    proto_item_append_text(ti, ", VNI: 0x%06x%s", tvb_get_ntoh24(tvb, offset),
353
2.22k
                           flags & FLAG_OAM ? ", OAM" : "");
354
2.22k
    offset += 3;
355
356
    /* Reserved. */
357
2.22k
    rsvd_item = proto_tree_add_item(geneve_tree, hf_geneve_reserved, tvb,
358
2.22k
                                    offset, 1, ENC_BIG_ENDIAN);
359
2.22k
    if (!tvb_get_uint8(tvb, offset)) {
360
301
        proto_item_set_hidden(rsvd_item);
361
301
    }
362
2.22k
    offset += 1;
363
364
    /* Options. */
365
2.22k
    if (tree && opts_len) {
366
386
        dissect_geneve_options(tvb, pinfo, geneve_tree, offset, opts_len);
367
386
    }
368
2.22k
    offset += opts_len;
369
370
2.22k
    proto_item_set_len(ti, offset);
371
372
2.22k
    next_tvb = tvb_new_subset_remaining(tvb, offset);
373
2.22k
    if (!dissector_try_uint(ethertype_dissector_table, proto_type, next_tvb, pinfo, tree))
374
40
        call_data_dissector(next_tvb, pinfo, tree);
375
376
2.22k
    return tvb_captured_length(tvb);
377
2.22k
}
378
379
/* Register Geneve with Wireshark */
380
void
381
proto_register_geneve(void)
382
14
{
383
14
    static hf_register_info hf[] = {
384
14
        { &hf_geneve_version,
385
14
          { "Version", "geneve.version",
386
14
            FT_UINT8, BASE_DEC, NULL, 0x00,
387
14
            NULL, HFILL }
388
14
        },
389
14
        { &hf_geneve_flags,
390
14
          { "Flags", "geneve.flags",
391
14
            FT_UINT8, BASE_HEX, NULL, 0x00,
392
14
            NULL, HFILL }
393
14
        },
394
14
        { &hf_geneve_flag_oam,
395
14
          { "Operations, Administration and Management Frame", "geneve.flags.oam",
396
14
            FT_BOOLEAN, 8, NULL, 0x80,
397
14
            NULL, HFILL }
398
14
        },
399
14
        { &hf_geneve_flag_critical,
400
14
          { "Critical Options Present", "geneve.flags.critical",
401
14
            FT_BOOLEAN, 8, NULL, 0x40,
402
14
            NULL, HFILL }
403
14
        },
404
14
        { &hf_geneve_flag_reserved,
405
14
          { "Reserved", "geneve.flags.reserved",
406
14
            FT_BOOLEAN, 8, NULL, 0x3F,
407
14
            NULL, HFILL }
408
14
        },
409
14
        { &hf_geneve_proto_type,
410
14
          { "Protocol Type", "geneve.proto_type",
411
14
            FT_UINT16, BASE_HEX, VALS(etype_vals), 0x0,
412
14
            NULL, HFILL }
413
14
        },
414
14
        { &hf_geneve_vni,
415
14
          { "Virtual Network Identifier (VNI)", "geneve.vni",
416
14
            FT_UINT24, BASE_HEX_DEC, NULL, 0x0,
417
14
            NULL, HFILL }
418
14
        },
419
14
        { &hf_geneve_reserved,
420
14
          { "Reserved", "geneve.reserved",
421
14
            FT_UINT8, BASE_HEX, NULL, 0x00,
422
14
            NULL, HFILL }
423
14
        },
424
14
        { &hf_geneve_options,
425
14
          { "Geneve Options", "geneve.options",
426
14
            FT_BYTES, BASE_NONE, NULL, 0x00,
427
14
            NULL, HFILL }
428
14
        },
429
14
        { &hf_geneve_option_class,
430
14
          { "Class", "geneve.option.class",
431
14
            FT_UINT16, BASE_HEX | BASE_RANGE_STRING, RVALS(class_id_names), 0x00,
432
14
            NULL, HFILL }
433
14
        },
434
14
        { &hf_geneve_option_type,
435
14
          { "Type", "geneve.option.type",
436
14
            FT_UINT8, BASE_HEX, NULL, 0x00,
437
14
            NULL, HFILL }
438
14
        },
439
14
        { &hf_geneve_option_type_critical,
440
14
          { "Critical Option", "geneve.option.type.critical",
441
14
            FT_BOOLEAN, 8, NULL, 0x80,
442
14
            NULL, HFILL }
443
14
        },
444
14
        { &hf_geneve_option_flags,
445
14
          { "Flags", "geneve.option.flags",
446
14
            FT_UINT8, BASE_HEX, NULL, 0x00,
447
14
            NULL, HFILL }
448
14
        },
449
14
        { &hf_geneve_option_flags_reserved,
450
14
          { "Reserved", "geneve.option.flags.reserved",
451
14
            FT_BOOLEAN, 8, NULL, 0xE0,
452
14
            NULL, HFILL }
453
14
        },
454
14
        { &hf_geneve_option_length,
455
14
          { "Length", "geneve.option.length",
456
14
            FT_UINT8, BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes), 0x00,
457
14
            NULL, HFILL }
458
14
        },
459
14
        { &hf_geneve_option,
460
14
          { "Option", "geneve.option",
461
14
            FT_BYTES, BASE_NONE, NULL, 0x00,
462
14
            NULL, HFILL }
463
14
        },
464
14
        { &hf_geneve_opt_gcp_vnid,
465
14
          { "GCP Virtual Network ID", "geneve.option.gcp.vnid",
466
14
            FT_UINT32, BASE_DEC, NULL, 0x00,
467
14
            NULL, HFILL }
468
14
        },
469
14
        { &hf_geneve_opt_gcp_reserved,
470
14
          { "GCP Reserved bits", "geneve.option.gcp.reserved",
471
14
            FT_BOOLEAN, 32, NULL, 0x0000000E,
472
14
            NULL, HFILL }
473
14
        },
474
14
        { &hf_geneve_opt_gcp_direction,
475
14
          { "GCP Traffic Direction", "geneve.option.gcp.direction",
476
14
            FT_BOOLEAN, 32, TFS(&tfs_geneve_gcp_direction), 0x00000001,
477
14
            NULL, HFILL }
478
14
        },
479
14
        { &hf_geneve_opt_gcp_endpoint,
480
14
          { "GCP Endpoint ID", "geneve.option.gcp.endpoint",
481
14
            FT_BYTES, BASE_NONE, NULL, 0x00,
482
14
            NULL, HFILL }
483
14
        },
484
14
        { &hf_geneve_opt_gcp_profile,
485
14
          { "GCP Profile ID", "geneve.option.gcp.profile",
486
14
            FT_UINT64, BASE_DEC, NULL, 0x00,
487
14
            NULL, HFILL }
488
14
        },
489
14
        { &hf_geneve_opt_cpkt_seqnum,
490
14
         { "cPacket Packet ID", "geneve.option.cPacket.packetid",
491
14
           FT_UINT32, BASE_DEC, NULL, 0x00,
492
14
           NULL, HFILL }
493
14
        },
494
14
        { &hf_geneve_opt_cpkt_origlen,
495
14
         { "cPacket Original length", "geneve.option.cPacket.orig_len",
496
14
           FT_UINT16, BASE_DEC, NULL, 0x00,
497
14
           NULL, HFILL }
498
14
        },
499
14
        { &hf_geneve_opt_cpkt_reserved,
500
14
         { "cPacket Reserved", "geneve.option.cPacket.reserved",
501
14
           FT_UINT8, BASE_HEX, NULL, 0x00,
502
14
           NULL, HFILL }
503
14
        },
504
14
        { &hf_geneve_opt_cpkt_version,
505
14
         { "cPacket Metadata version", "geneve.option.cPacket.version",
506
14
           FT_UINT8, BASE_DEC, NULL, 0x00,
507
14
           NULL, HFILL }
508
14
        },
509
14
        { &hf_geneve_opt_cpkt_timestamp,
510
14
         { "cPacket Timestamp", "geneve.option.cPacket.timestamp",
511
14
           FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0x00,
512
14
           NULL, HFILL }
513
14
        },
514
14
        { &hf_geneve_opt_cpkt_ts_sec,
515
14
         { "cPacket Timestamp (s)", "geneve.option.cPacket.ts_sec",
516
14
           FT_UINT48, BASE_DEC, NULL, 0x00,
517
14
           NULL, HFILL }
518
14
        },
519
14
        { &hf_geneve_opt_cpkt_ts_nsec,
520
14
         { "cPacket Timestamp (ns)", "geneve.option.cPacket.ts_nsec",
521
14
           FT_UINT32, BASE_DEC, NULL, 0x00,
522
14
           NULL, HFILL }
523
14
        },
524
14
        { &hf_geneve_opt_cpkt_ts_fracns,
525
14
         { "cPacket Timestamp (frac. ns)", "geneve.option.cPacket.ts_fracns",
526
14
           FT_UINT16, BASE_DEC, NULL, 0x00,
527
14
           NULL, HFILL }
528
14
        },
529
14
        { &hf_geneve_opt_cpkt_devid,
530
14
         { "cPacket Device ID", "geneve.option.cPacket.device_id",
531
14
           FT_UINT16, BASE_DEC, NULL, 0x00,
532
14
           NULL, HFILL }
533
14
        },
534
14
        { &hf_geneve_opt_cpkt_portid,
535
14
         { "cPacket Port ID", "geneve.option.cPacket.port_id",
536
14
           FT_UINT16, BASE_DEC, NULL, 0x00,
537
14
           NULL, HFILL }
538
14
        },
539
14
        { &hf_geneve_opt_unknown_data,
540
14
          { "Unknown Option Data", "geneve.option.unknown.data",
541
14
            FT_BYTES, BASE_NONE, NULL, 0x00,
542
14
            NULL, HFILL }
543
14
        },
544
14
    };
545
546
14
    static int *ett[] = {
547
14
        &ett_geneve,
548
14
        &ett_geneve_flags,
549
14
        &ett_geneve_options,
550
14
        &ett_geneve_opt_flags,
551
14
        &ett_geneve_opt_data,
552
14
    };
553
554
14
    static ei_register_info ei[] = {
555
14
       { &ei_geneve_ver_unknown, { "geneve.version.unknown",
556
14
         PI_PROTOCOL, PI_WARN, "Unknown version", EXPFILL }},
557
14
       { &ei_geneve_opt_len_invalid, { "geneve.option.length.invalid",
558
14
         PI_PROTOCOL, PI_WARN, "Invalid length for option", EXPFILL }},
559
14
    };
560
561
14
    expert_module_t *expert_geneve;
562
563
    /* Register the protocol name and description */
564
14
    proto_geneve = proto_register_protocol("Generic Network Virtualization Encapsulation",
565
14
                                          "Geneve", "geneve");
566
567
14
    proto_register_field_array(proto_geneve, hf, array_length(hf));
568
14
    proto_register_subtree_array(ett, array_length(ett));
569
570
14
    expert_geneve = expert_register_protocol(proto_geneve);
571
14
    expert_register_field_array(expert_geneve, ei, array_length(ei));
572
573
14
    geneve_handle = register_dissector("geneve", dissect_geneve, proto_geneve);
574
14
}
575
576
void
577
proto_reg_handoff_geneve(void)
578
14
{
579
14
    dissector_add_uint_with_preference("udp.port", UDP_PORT_GENEVE, geneve_handle);
580
581
14
    ethertype_dissector_table = find_dissector_table("ethertype");
582
14
}
583
584
/*
585
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
586
 *
587
 * Local variables:
588
 * c-basic-offset: 4
589
 * tab-width: 8
590
 * indent-tabs-mode: nil
591
 * End:
592
 *
593
 * vi: set shiftwidth=4 tabstop=8 expandtab:
594
 * :indentSize=4:tabSize=8:noTabs=true:
595
 */