/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 | | */ |