Coverage Report

Created: 2025-08-04 07:15

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