TODO drsuapi compressed
[wireshark-sm.git] / epan / dissectors / packet-avsp.c
blob7190579ed503cd6bfc5d890985c38a4b92a43599
1 /* packet-avsp.c
2 * Arista Vendor Specific ethertype Protocol (AVSP)
4 * Copyright (c) 2018-2022 by Arista Networks
5 * Author: Nikhil AP <nikhilap@arista.com>
6 * Author: PMcL <peterm@arista.com>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1999 Gerald Combs
12 * SPDX-License-Identifier: GPL-2.0-or-later
15 /* Arista Vendor-Specific EtherType Protocol Identifier
17 * Arista applied for, and received the assignment of, a vendor-specific EtherType Protocol Identifier in May of 2016. Details below:
19 * Ethertype number is: D28B
20 * Issue date is: May 12, 2016
22 * Arista Subtype 0x0001 is a Timestamp L2 Header
23 * Arista Subtype 0xCAFE is a TGen L2 header
25 * The timestamp L2 header consists of the following fields:
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.
32 * The TGen L2 header consists of the following fields:
34 * Arista Vendor Specific Protocol EtherType (0xD28B)
35 * Two-byte protocol subtype of 0xCAFE
36 * Two-byte protocol version: 0x0001
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>
46 #include <wsutil/str_util.h>
48 #include "packet-eth.h"
50 #define ARISTA_SUBTYPE_TIMESTAMP 0x0001
52 #define ARISTA_TIMESTAMP_64_TAI 0x0010
53 #define ARISTA_TIMESTAMP_64_UTC 0x0110
54 #define ARISTA_TIMESTAMP_48_TAI 0x0020
55 #define ARISTA_TIMESTAMP_48_UTC 0x0120
56 #define ARISTA_TIMESTAMP_64_TAI_J2 0x0011
57 #define ARISTA_TIMESTAMP_64_UTC_J2 0x0111
58 #define ARISTA_TIMESTAMP_48_TAI_J2 0x0021
59 #define ARISTA_TIMESTAMP_48_UTC_J2 0x0121
61 #define ARISTA_SUBTYPE_GREENTAP 0x0003
63 #define ARISTA_GREENTAP_48_TAI 0x0020
64 #define ARISTA_GREENTAP_48_UTC 0x0120
66 #define ARISTA_SUBTYPE_GREENT 0x0004
68 #define ARISTA_GREENT_VER_1 0x0001
70 #define ARISTA_SUBTYPE_DZGRE_A 0x0007
72 #define ARISTA_DZGRE_A_VER_1 0x0001
74 #define ARISTA_SUBTYPE_DZGRE_B 0x0008
76 #define ARISTA_DZGRE_B_VER_1 0x0001
78 #define ARISTA_SUBTYPE_DZGRE_TS 0x0009
80 #define ARISTA_DZGRE_TS_64_TAI 0x0011
81 #define ARISTA_DZGRE_TS_64_UTC 0x0111
83 #define ARISTA_SUBTYPE_TGEN 0xCAFE
84 #define ARISTA_TGEN_VER_1 0x0001
86 #define ROUNDUP(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
88 void proto_reg_handoff_avsp(void);
89 void proto_register_avsp(void);
91 static dissector_handle_t avsp_handle;
92 static int proto_avsp;
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;
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;
122 static int hf_avsp_etype;
123 static int hf_avsp_trailer;
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 +---------------+---------------+---------------+---------------+
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;
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 +---------------+---------------+---------------+---------------+
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 +---------------+---------------+---------------+---------------+
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;
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;
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 +---------------+---------------+---------------+---------------+
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 +---------------+---------------+---------------+---------------+
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 +---------------+---------------+---------------+---------------+
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;
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;
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;
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 +---------------+---------------+---------------+---------------+
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;
275 static int* const avsp_tgen_ctrl[] = {
276 &hf_avsp_tgen_hdr_ctrl_fcs_inverted,
277 &hf_avsp_tgen_hdr_ctrl_reserved,
278 NULL
281 static dissector_handle_t ethertype_handle;
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 (timesamped)"},
290 {ARISTA_SUBTYPE_TGEN, "TGen"},
291 {0, NULL}
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}
306 static const value_string greentap_versions[] = {
307 {ARISTA_GREENTAP_48_TAI, "48bit TAI"},
308 {ARISTA_GREENTAP_48_UTC, "48bit UTC"},
309 {0, NULL}
312 static const value_string greent_versions[] = {
313 {ARISTA_GREENT_VER_1, "1"},
314 {0, NULL}
317 static const value_string dzgre_a_versions[] = {
318 {ARISTA_DZGRE_A_VER_1, "1"},
319 {0, NULL}
322 static const value_string dzgre_b_versions[] = {
323 {ARISTA_DZGRE_A_VER_1, "1"},
324 {0, NULL}
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}
333 static const value_string tgen_versions[] = {
334 {ARISTA_TGEN_VER_1, "1"},
335 {0, NULL}
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;
347 static int
348 dissect_avsp(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data _U_)
350 volatile int offset = 0;
351 uint32_t version, subtype, tgen_payload_len = 0;
352 uint64_t tgen_ctrl;
353 uint32_t tgen_seq_num, sample_len, count, u32;
354 volatile uint32_t i; // potentially held across vfork
355 const char* str;
356 uint16_t encap_proto;
357 ethertype_data_t ethertype_data;
358 tvbuff_t* volatile tgen_payload_tvb = NULL;
360 col_set_str(pinfo->cinfo, COL_PROTOCOL, "AVSP");
361 col_clear(pinfo->cinfo, COL_INFO);
363 proto_item* avsp_ti, * ti;
364 proto_tree* avsp_tree, * avsp_48_tree = NULL, * avsp_64_tree = NULL,
365 * avsp_tgen_hdr = NULL, * avsp_tgen_payload = NULL,
366 * avsp_dzgre_hdr = NULL, * avsp_dzgre_ts_utc = NULL,
367 * avsp_dzgre_ts_tai = NULL, * avsp_greent_hdr = NULL,
368 * avsp_greent_sample_hdr = NULL, *header_tree = NULL;
370 /* Adding Items and Values to the Protocol Tree */
371 avsp_ti = proto_tree_add_item(tree, proto_avsp, tvb, 0, -1,
372 ENC_NA);
373 avsp_tree = proto_item_add_subtree(avsp_ti, ett_avsp);
375 /* add the subtype to avsp */
376 proto_tree_add_item_ret_uint(avsp_tree, hf_avsp_subtype, tvb,
377 offset, 2, ENC_BIG_ENDIAN, &subtype);
378 str = try_val_to_str(subtype, arista_subtypes);
379 if (str) {
380 proto_item_append_text(avsp_ti, ", Subtype: %s", str);
382 offset += 2;
384 /* Based on the subtype, add the version and further custom protocol fields */
385 switch (subtype) {
386 case ARISTA_SUBTYPE_TIMESTAMP:
387 proto_tree_add_item_ret_uint(avsp_tree, hf_avsp_ts_version, tvb, offset,
388 2, ENC_BIG_ENDIAN, &version);
389 str = try_val_to_str(version, ts_versions);
390 if (str) {
391 proto_item_append_text(avsp_ti, ", Version: %s", str);
393 offset += 2;
395 switch (version) {
396 case ARISTA_TIMESTAMP_64_TAI:
397 case ARISTA_TIMESTAMP_64_TAI_J2:
398 ti = proto_tree_add_item(avsp_tree, hf_avsp_ts_64_tai, tvb, 0, -1,
399 ENC_NA);
400 avsp_64_tree = proto_item_add_subtree(ti, ett_avsp);
401 col_set_str(pinfo->cinfo, COL_INFO, "64bit TAI timestamp");
402 proto_tree_add_item(avsp_64_tree, hf_avsp_ts_64_sec, tvb, offset,
403 4, ENC_BIG_ENDIAN);
404 offset += 4;
405 proto_tree_add_item(avsp_64_tree, hf_avsp_ts_64_ns, tvb, offset,
406 4, ENC_BIG_ENDIAN);
407 offset += 4;
408 break;
409 case ARISTA_TIMESTAMP_64_UTC:
410 case ARISTA_TIMESTAMP_64_UTC_J2:
411 ti = proto_tree_add_item(avsp_tree, hf_avsp_ts_64_utc, tvb, 0, -1,
412 ENC_NA);
413 avsp_64_tree = proto_item_add_subtree(ti, ett_avsp);
414 col_set_str(pinfo->cinfo, COL_INFO, "64bit UTC timestamp");
415 proto_tree_add_item(avsp_64_tree, hf_avsp_ts_64_sec, tvb, offset,
416 4, ENC_BIG_ENDIAN);
417 offset += 4;
418 proto_tree_add_item(avsp_64_tree, hf_avsp_ts_64_ns, tvb, offset,
419 4, ENC_BIG_ENDIAN);
420 offset += 4;
421 break;
422 case ARISTA_TIMESTAMP_48_TAI:
423 case ARISTA_TIMESTAMP_48_TAI_J2:
424 ti = proto_tree_add_item(avsp_tree, hf_avsp_ts_48_tai, tvb, 0, -1,
425 ENC_NA);
426 avsp_48_tree = proto_item_add_subtree(ti, ett_avsp);
427 col_set_str(pinfo->cinfo, COL_INFO, "48bit TAI timestamp");
428 proto_tree_add_item(avsp_48_tree, hf_avsp_ts_48_sec, tvb, offset,
429 2, ENC_BIG_ENDIAN);
430 offset += 2;
431 proto_tree_add_item(avsp_48_tree, hf_avsp_ts_48_ns, tvb, offset,
432 4, ENC_BIG_ENDIAN);
433 offset += 4;
434 break;
435 case ARISTA_TIMESTAMP_48_UTC:
436 case ARISTA_TIMESTAMP_48_UTC_J2:
437 ti = proto_tree_add_item(avsp_tree, hf_avsp_ts_48_utc, tvb, 0, -1,
438 ENC_NA);
439 avsp_48_tree = proto_item_add_subtree(ti, ett_avsp);
440 col_set_str(pinfo->cinfo, COL_INFO, "48bit UTC timestamp");
441 proto_tree_add_item(avsp_48_tree, hf_avsp_ts_48_sec, tvb, offset,
442 2, ENC_BIG_ENDIAN);
443 offset += 2;
444 proto_tree_add_item(avsp_48_tree, hf_avsp_ts_48_ns, tvb, offset,
445 4, ENC_BIG_ENDIAN);
446 offset += 4;
447 break;
448 default:
449 expert_add_info_format(pinfo, avsp_ti, &ei_avsp_ts_unknown_version,
450 "Unknown timestamp version: 0x%0x", version);
451 return tvb_captured_length(tvb);
454 encap_proto = tvb_get_ntohs(tvb, offset);
455 proto_tree_add_uint(avsp_tree, hf_avsp_etype, tvb, offset, 2, encap_proto);
456 offset += 2;
458 ethertype_data.etype = encap_proto;
459 ethertype_data.payload_offset = offset;
460 ethertype_data.fh_tree = avsp_tree;
461 ethertype_data.trailer_id = hf_avsp_trailer;
462 ethertype_data.fcs_len = 0;
464 call_dissector_with_data(ethertype_handle, tvb, pinfo, tree, &ethertype_data);
465 break;
467 case ARISTA_SUBTYPE_GREENTAP:
468 proto_tree_add_item_ret_uint(avsp_tree, hf_avsp_greentap_version, tvb,
469 offset, 2, ENC_BIG_ENDIAN, &version);
470 str = try_val_to_str(version, greentap_versions);
471 if (str) {
472 proto_item_append_text(avsp_ti, ", Version: %s", str);
474 offset += 2;
476 switch (version) {
477 case ARISTA_GREENTAP_48_TAI:
478 ti = proto_tree_add_item(avsp_tree, hf_avsp_greentap_tai, tvb,
479 0, -1, ENC_NA);
480 avsp_48_tree = proto_item_add_subtree(ti, ett_avsp);
481 col_set_str(pinfo->cinfo, COL_INFO, "48bit TAI timestamp");
482 proto_tree_add_item(avsp_48_tree, hf_avsp_greentap_sec,
483 tvb, offset, 2, ENC_BIG_ENDIAN);
484 offset += 2;
485 proto_tree_add_item(avsp_48_tree, hf_avsp_greentap_ns,
486 tvb, offset, 4, ENC_BIG_ENDIAN);
487 offset += 4;
488 break;
489 case ARISTA_GREENTAP_48_UTC:
490 ti = proto_tree_add_item(avsp_tree, hf_avsp_greentap_utc, tvb,
491 0, -1, ENC_NA);
492 avsp_48_tree = proto_item_add_subtree(ti, ett_avsp);
493 col_set_str(pinfo->cinfo, COL_INFO, "48bit TAI timestamp");
494 proto_tree_add_item(avsp_48_tree, hf_avsp_greentap_sec,
495 tvb, offset, 2, ENC_BIG_ENDIAN);
496 offset += 2;
497 proto_tree_add_item(avsp_48_tree, hf_avsp_greentap_ns,
498 tvb, offset, 4, ENC_BIG_ENDIAN);
499 offset += 4;
500 break;
501 default:
502 expert_add_info_format(pinfo, avsp_ti,
503 &ei_avsp_greentap_unknown_version,
504 "Unknown GRE TAP version: 0x%0x", version);
505 return tvb_captured_length(tvb);
508 encap_proto = tvb_get_ntohs(tvb, offset);
509 proto_tree_add_uint(avsp_tree, hf_avsp_etype, tvb, offset, 2,
510 encap_proto);
511 offset += 2;
513 ethertype_data.etype = encap_proto;
514 ethertype_data.payload_offset = offset;
515 ethertype_data.fh_tree = avsp_tree;
516 ethertype_data.trailer_id = hf_avsp_trailer;
517 ethertype_data.fcs_len = 0;
519 call_dissector_with_data(ethertype_handle, tvb, pinfo, tree,
520 &ethertype_data);
521 break;
523 case ARISTA_SUBTYPE_GREENT:
524 proto_tree_add_item_ret_uint(avsp_tree, hf_avsp_greent_version, tvb,
525 offset, 2, ENC_BIG_ENDIAN, &version);
526 str = try_val_to_str(version, greent_versions);
527 if (str) {
528 proto_item_append_text(avsp_ti, ", Version: %s", str);
530 offset += 2;
532 switch (version) {
533 case ARISTA_GREENT_VER_1:
534 col_set_str(pinfo->cinfo, COL_INFO, "Arista Postcard Telemetry");
535 ti = proto_tree_add_item(avsp_tree, hf_avsp_greent_hdr, tvb, 0,
536 -1, ENC_NA);
537 avsp_greent_hdr = proto_item_add_subtree(ti, ett_avsp_greent_hdr);
539 /* Session ID */
540 proto_tree_add_item_ret_uint(avsp_greent_hdr,
541 hf_avsp_greent_session, tvb, offset, 2, ENC_BIG_ENDIAN,
542 &u32);
543 proto_item_append_text(ti, ", Session ID: %u", u32);
544 offset += 2;
546 /* Flags */
547 proto_tree_add_item_ret_uint(avsp_greent_hdr,
548 hf_avsp_greent_flags, tvb, offset, 1, ENC_BIG_ENDIAN,
549 &u32);
550 proto_item_append_text(ti, ", Flags: 0x%02x", u32);
551 offset += 1;
553 /* Sample Count */
554 proto_tree_add_item_ret_uint(avsp_greent_hdr,
555 hf_avsp_greent_sample_count, tvb, offset, 1, ENC_BIG_ENDIAN,
556 &count);
557 proto_item_append_text(ti, ", Count: %u", count);
558 offset += 1;
560 for (i = 0; i < count; i++) {
561 ti = proto_tree_add_item(avsp_greent_hdr,
562 hf_avsp_greent_sample_hdr, tvb, 0, -1, ENC_NA);
563 avsp_greent_sample_hdr = proto_item_add_subtree(ti,
564 ett_avsp_greent_sample_hdr);
566 /* Length */
567 proto_tree_add_item_ret_uint(avsp_greent_sample_hdr,
568 hf_avsp_greent_sample_len, tvb, offset, 2,
569 ENC_BIG_ENDIAN, &sample_len);
570 proto_item_append_text(ti, ", Length: %u", sample_len);
571 offset += 2;
573 /* Seconds */
574 proto_tree_add_item_ret_uint(avsp_greent_sample_hdr,
575 hf_avsp_greent_sample_sec, tvb, offset, 2,
576 ENC_BIG_ENDIAN, &u32);
577 proto_item_append_text(ti, ", Seconds: %u", u32);
578 offset += 2;
580 /* Nanoseconds */
581 proto_tree_add_item_ret_uint(avsp_greent_sample_hdr,
582 hf_avsp_greent_sample_ns, tvb, offset, 4,
583 ENC_BIG_ENDIAN, &u32);
584 proto_item_append_text(ti, ", Nanoseconds: %u", u32);
585 offset += 4;
587 /* Ingress */
588 proto_tree_add_item_ret_uint(avsp_greent_sample_hdr,
589 hf_avsp_greent_sample_ingress, tvb, offset, 4,
590 ENC_BIG_ENDIAN, &u32);
591 proto_item_append_text(ti, ", Ingress: %u", u32);
592 offset += 4;
594 /* Egress */
595 proto_tree_add_item_ret_uint(avsp_greent_sample_hdr,
596 hf_avsp_greent_sample_egress, tvb, offset, 4,
597 ENC_BIG_ENDIAN, &u32);
598 proto_item_append_text(ti, ", Egress: %u", u32);
599 offset += 4;
601 /* Sample Rate */
602 proto_tree_add_item_ret_uint(avsp_greent_sample_hdr,
603 hf_avsp_greent_sample_rate, tvb, offset, 2,
604 ENC_BIG_ENDIAN, &u32);
605 proto_item_append_text(ti, ", Rate: %u", u32);
606 offset += 2;
608 /* Checksum */
609 proto_tree_add_item_ret_uint(avsp_greent_sample_hdr,
610 hf_avsp_greent_sample_sum, tvb, offset, 2,
611 ENC_BIG_ENDIAN, &u32);
612 proto_item_append_text(ti, ", Checksum: 0x%04x", u32);
613 offset += 2;
615 /* Sample Data */
616 ti = proto_tree_add_item(avsp_greent_sample_hdr,
617 hf_avsp_greent_sample_data, tvb, offset, sample_len,
618 ENC_NA);
619 header_tree = proto_item_add_subtree(ti,
620 ett_avsp_greent_sample_data);
623 * We call the ethernet dissector on the sample, but since
624 * the sample is truncated it will likely generate errors.
625 * This is an attempt to isolate those errors, borrowed from
626 * sflow.
629 tvbuff_t *next_tvb;
630 address save_dl_src, save_dl_dst, save_net_src,
631 save_net_dst, save_src, save_dst;
632 bool save_writable, save_in_error_pkt;;
634 sample_len = ROUNDUP(sample_len, 4);
635 next_tvb = tvb_new_subset_length(tvb, offset, sample_len);
637 save_in_error_pkt = pinfo->flags.in_error_pkt;
638 pinfo->flags.in_error_pkt = true;
640 save_writable = col_get_writable(pinfo->cinfo, -1);
641 col_set_writable(pinfo->cinfo, -1, false);
642 copy_address_shallow(&save_dl_src, &pinfo->dl_src);
643 copy_address_shallow(&save_dl_dst, &pinfo->dl_dst);
644 copy_address_shallow(&save_net_src, &pinfo->net_src);
645 copy_address_shallow(&save_net_dst, &pinfo->net_dst);
646 copy_address_shallow(&save_src, &pinfo->src);
647 copy_address_shallow(&save_dst, &pinfo->dst);
651 // always ethernet for greent
652 ethertype_data.etype = ETHERTYPE_ETHBRIDGE;
653 ethertype_data.payload_offset = 0;
654 ethertype_data.fh_tree = header_tree;
655 ethertype_data.trailer_id = hf_avsp_trailer;
656 ethertype_data.fcs_len = 0;
658 call_dissector_with_data(ethertype_handle, next_tvb,
659 pinfo, header_tree, &ethertype_data);
661 CATCH_BOUNDS_ERRORS {
663 ENDTRY;
665 col_set_writable(pinfo->cinfo, -1, save_writable);
666 pinfo->flags.in_error_pkt = save_in_error_pkt;
667 copy_address_shallow(&pinfo->dl_src, &save_dl_src);
668 copy_address_shallow(&pinfo->dl_dst, &save_dl_dst);
669 copy_address_shallow(&pinfo->net_src, &save_net_src);
670 copy_address_shallow(&pinfo->net_dst, &save_net_dst);
671 copy_address_shallow(&pinfo->src, &save_src);
672 copy_address_shallow(&pinfo->dst, &save_dst);
675 break;
676 default:
677 expert_add_info_format(pinfo, avsp_ti,
678 &ei_avsp_greent_unknown_version,
679 "Unknown version: 0x%0x", version);
680 return tvb_captured_length(tvb);
682 break;
684 case ARISTA_SUBTYPE_DZGRE_A:
685 proto_tree_add_item_ret_uint(avsp_tree, hf_avsp_dzgre_a_version, tvb,
686 offset, 2, ENC_BIG_ENDIAN, &version);
687 str = try_val_to_str(version, dzgre_a_versions);
688 if (str) {
689 proto_item_append_text(avsp_ti, ", Version: %s", str);
691 offset += 2;
693 switch (version) {
694 case ARISTA_DZGRE_A_VER_1:
695 col_set_str(pinfo->cinfo, COL_INFO, "Arista DzGRE(A) Frame");
696 ti = proto_tree_add_item(avsp_tree, hf_avsp_dzgre_a_hdr, tvb,
697 0, -1, ENC_NA);
698 avsp_dzgre_hdr = proto_item_add_subtree(ti, ett_avsp_dzgre_a_hdr);
700 /* Switch ID */
701 proto_tree_add_item_ret_uint(avsp_dzgre_hdr,
702 hf_avsp_dzgre_a_switch, tvb, offset, 2, ENC_BIG_ENDIAN,
703 &u32);
704 proto_item_append_text(ti, ", Switch ID: %u", u32);
705 offset += 2;
707 /* Port ID */
708 proto_tree_add_item_ret_uint(avsp_dzgre_hdr,
709 hf_avsp_dzgre_a_port, tvb, offset, 2, ENC_BIG_ENDIAN,
710 &u32);
711 proto_item_append_text(ti, ", Port ID: %u", u32);
712 offset += 2;
714 /* Policy ID */
715 proto_tree_add_item_ret_uint(avsp_dzgre_hdr,
716 hf_avsp_dzgre_a_policy, tvb, offset, 2, ENC_BIG_ENDIAN,
717 &u32);
718 proto_item_append_text(ti, ", Policy ID: %u", u32);
719 offset += 2;
721 /* Reserved */
722 proto_tree_add_item_ret_uint(avsp_dzgre_hdr,
723 hf_avsp_dzgre_a_reserved, tvb, offset, 2, ENC_BIG_ENDIAN,
724 &u32);
725 offset += 2;
726 break;
727 default:
728 expert_add_info_format(pinfo, avsp_ti,
729 &ei_avsp_dzgre_a_unknown_version,
730 "Unknown version: 0x%0x", version);
731 return tvb_captured_length(tvb);
734 ethertype_data.etype = ETHERTYPE_ETHBRIDGE; // always ethernet
735 ethertype_data.payload_offset = offset;
736 ethertype_data.fh_tree = avsp_tree;
737 ethertype_data.trailer_id = hf_avsp_trailer;
738 ethertype_data.fcs_len = 0;
740 call_dissector_with_data(ethertype_handle, tvb, pinfo, tree,
741 &ethertype_data);
742 break;
744 case ARISTA_SUBTYPE_DZGRE_B:
745 proto_tree_add_item_ret_uint(avsp_tree, hf_avsp_dzgre_b_version, tvb,
746 offset, 2, ENC_BIG_ENDIAN, &version);
747 str = try_val_to_str(version, dzgre_b_versions);
748 if (str) {
749 proto_item_append_text(avsp_ti, ", Version: %s", str);
751 offset += 2;
753 switch (version) {
754 case ARISTA_DZGRE_B_VER_1:
755 col_set_str(pinfo->cinfo, COL_INFO, "Arista DzGRE(B) Frame");
756 ti = proto_tree_add_item(avsp_tree, hf_avsp_dzgre_b_hdr, tvb,
757 0, -1, ENC_NA);
758 avsp_dzgre_hdr = proto_item_add_subtree(ti, ett_avsp_dzgre_b_hdr);
760 /* Port ID */
761 proto_tree_add_item_ret_uint(avsp_dzgre_hdr,
762 hf_avsp_dzgre_b_port, tvb, offset, 2, ENC_BIG_ENDIAN,
763 &u32);
764 proto_item_append_text(ti, ", Port ID: %u", u32);
765 offset += 2;
767 /* Policy ID */
768 proto_tree_add_item_ret_uint(avsp_dzgre_hdr,
769 hf_avsp_dzgre_b_policy, tvb, offset, 2, ENC_BIG_ENDIAN,
770 &u32);
771 proto_item_append_text(ti, ", Policy ID: %u", u32);
772 offset += 2;
773 break;
774 default:
775 expert_add_info_format(pinfo, avsp_ti,
776 &ei_avsp_dzgre_b_unknown_version,
777 "Unknown version: 0x%0x", version);
778 return tvb_captured_length(tvb);
781 ethertype_data.etype = ETHERTYPE_ETHBRIDGE; // always ethernet
782 ethertype_data.payload_offset = offset;
783 ethertype_data.fh_tree = avsp_tree;
784 ethertype_data.trailer_id = hf_avsp_trailer;
785 ethertype_data.fcs_len = 0;
787 call_dissector_with_data(ethertype_handle, tvb, pinfo, tree,
788 &ethertype_data);
789 break;
791 case ARISTA_SUBTYPE_DZGRE_TS:
792 proto_tree_add_item_ret_uint(avsp_tree, hf_avsp_dzgre_ts_version, tvb,
793 offset, 2, ENC_BIG_ENDIAN, &version);
794 str = try_val_to_str(version, dzgre_ts_versions);
795 if (str) {
796 proto_item_append_text(avsp_ti, ", Version: %s", str);
798 offset += 2;
800 switch (version) {
801 case ARISTA_DZGRE_TS_64_TAI:
802 col_set_str(pinfo->cinfo, COL_INFO, "Arista DzGRE(A) Frame");
803 ti = proto_tree_add_item(avsp_tree, hf_avsp_dzgre_ts_hdr, tvb,
804 0, -1, ENC_NA);
805 avsp_dzgre_hdr = proto_item_add_subtree(ti, ett_avsp_dzgre_ts_hdr);
807 /* Switch ID */
808 proto_tree_add_item_ret_uint(avsp_dzgre_hdr,
809 hf_avsp_dzgre_ts_switch, tvb, offset, 2, ENC_BIG_ENDIAN,
810 &u32);
811 proto_item_append_text(ti, ", Switch ID: %u", u32);
812 offset += 2;
814 /* Port ID */
815 proto_tree_add_item_ret_uint(avsp_dzgre_hdr,
816 hf_avsp_dzgre_ts_port, tvb, offset, 2, ENC_BIG_ENDIAN,
817 &u32);
818 proto_item_append_text(ti, ", Port ID: %u", u32);
819 offset += 2;
821 /* Policy ID */
822 proto_tree_add_item_ret_uint(avsp_dzgre_hdr,
823 hf_avsp_dzgre_ts_policy, tvb, offset, 2, ENC_BIG_ENDIAN,
824 &u32);
825 proto_item_append_text(ti, ", Policy ID: %u", u32);
826 offset += 2;
828 /* Reserved */
829 proto_tree_add_item_ret_uint(avsp_dzgre_hdr,
830 hf_avsp_dzgre_ts_reserved, tvb, offset, 2, ENC_BIG_ENDIAN,
831 &u32);
832 offset += 2;
834 /* Timestamp */
835 ti = proto_tree_add_item(avsp_dzgre_ts_tai,
836 hf_avsp_dzgre_ts_tai, tvb, 0, -1, ENC_NA);
837 avsp_48_tree = proto_item_add_subtree(ti,
838 ett_avsp_dzgre_ts_tai);
840 col_set_str(pinfo->cinfo, COL_INFO, "48bit TAI timestamp");
842 proto_tree_add_item(avsp_48_tree, hf_avsp_dzgre_ts_sec,
843 tvb, offset, 2, ENC_BIG_ENDIAN);
844 offset += 2;
845 proto_tree_add_item(avsp_48_tree, hf_avsp_dzgre_ts_ns,
846 tvb, offset, 4, ENC_BIG_ENDIAN);
847 offset += 4;
848 break;
849 case ARISTA_DZGRE_TS_64_UTC:
850 col_set_str(pinfo->cinfo, COL_INFO,
851 "Arista DzGRE(timestamped) Frame");
852 ti = proto_tree_add_item(avsp_tree, hf_avsp_dzgre_ts_hdr, tvb,
853 0, -1, ENC_NA);
854 avsp_dzgre_hdr = proto_item_add_subtree(ti, ett_avsp_dzgre_ts_hdr);
856 /* Switch ID */
857 proto_tree_add_item_ret_uint(avsp_dzgre_hdr,
858 hf_avsp_dzgre_ts_switch, tvb, offset, 2, ENC_BIG_ENDIAN,
859 &u32);
860 proto_item_append_text(ti, ", Switch ID: 0x%u", u32);
861 offset += 2;
863 /* Port ID */
864 proto_tree_add_item_ret_uint(avsp_dzgre_hdr,
865 hf_avsp_dzgre_ts_port, tvb, offset, 2, ENC_BIG_ENDIAN,
866 &u32);
867 proto_item_append_text(ti, ", Port ID: 0x%u", u32);
868 offset += 2;
870 /* Policy ID */
871 proto_tree_add_item_ret_uint(avsp_dzgre_hdr,
872 hf_avsp_dzgre_ts_policy, tvb, offset, 2, ENC_BIG_ENDIAN,
873 &u32);
874 proto_item_append_text(ti, ", Policy ID: 0x%u", u32);
875 offset += 2;
877 /* Reserved */
878 offset += 2;
880 /* Timestamp */
881 ti = proto_tree_add_item(avsp_dzgre_ts_utc,
882 hf_avsp_dzgre_ts_utc, tvb, 0, -1, ENC_NA);
883 avsp_48_tree = proto_item_add_subtree(ti,
884 ett_avsp_dzgre_ts_utc);
886 col_set_str(pinfo->cinfo, COL_INFO, "48bit UTC timestamp");
888 proto_tree_add_item(avsp_48_tree, hf_avsp_dzgre_ts_sec,
889 tvb, offset, 2, ENC_BIG_ENDIAN);
890 offset += 2;
891 proto_tree_add_item(avsp_48_tree, hf_avsp_dzgre_ts_ns,
892 tvb, offset, 4, ENC_BIG_ENDIAN);
893 offset += 4;
894 break;
895 default:
896 expert_add_info_format(pinfo, avsp_ti,
897 &ei_avsp_dzgre_ts_unknown_version,
898 "Unknown version: 0x%0x", version);
899 return tvb_captured_length(tvb);
902 ethertype_data.etype = ETHERTYPE_ETHBRIDGE; // always ethernet
903 ethertype_data.payload_offset = offset;
904 ethertype_data.fh_tree = avsp_tree;
905 ethertype_data.trailer_id = hf_avsp_trailer;
906 ethertype_data.fcs_len = 0;
908 call_dissector_with_data(ethertype_handle, tvb, pinfo, tree,
909 &ethertype_data);
910 break;
912 case ARISTA_SUBTYPE_TGEN:
913 proto_tree_add_item_ret_uint(avsp_tree, hf_avsp_tgen_version, tvb,
914 offset, 2, ENC_BIG_ENDIAN, &version);
915 str = try_val_to_str(version, tgen_versions);
916 if (str) {
917 proto_item_append_text(avsp_ti, ", Version: %s", str);
919 offset += 2;
921 switch (version) {
922 case ARISTA_TGEN_VER_1:
923 col_set_str(pinfo->cinfo, COL_INFO, "Arista TGen Frame");
925 /* Get TGen Header Control Word. */
926 ti = proto_tree_add_item(avsp_tree, hf_avsp_tgen_hdr, tvb, offset, 6,
927 ENC_NA);
928 avsp_tgen_hdr = proto_item_add_subtree(ti, ett_avsp_tgen_hdr);
929 proto_tree_add_bitmask_ret_uint64(avsp_tgen_hdr, tvb, offset,
930 hf_avsp_tgen_hdr_ctrl, ett_avsp_tgen_hdr_ctrl, avsp_tgen_ctrl,
931 ENC_BIG_ENDIAN, &tgen_ctrl);
932 proto_item_append_text(ti, ", Control Word: 0x%04" PRIx64, tgen_ctrl);
933 col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Ctrl=0x%04" PRIx64, tgen_ctrl);
934 offset += 2;
936 /* Get TGen Header Sequence Number*/
937 proto_tree_add_item_ret_uint(avsp_tgen_hdr, hf_avsp_tgen_hdr_seq_num, tvb,
938 offset, 2, ENC_BIG_ENDIAN, &tgen_seq_num);
939 proto_item_append_text(ti, ", Sequence Number: %u", tgen_seq_num);
940 col_append_str_uint(pinfo->cinfo, COL_INFO, "Seq", tgen_seq_num, ", ");
941 offset += 2;
943 /* Get TGen Header Payload Length */
944 proto_tree_add_item_ret_uint(avsp_tgen_hdr,
945 hf_avsp_tgen_hdr_payload_len, tvb, offset, 2, ENC_BIG_ENDIAN,
946 &tgen_payload_len);
947 proto_item_append_text(ti, ", Payload Length: %u", tgen_payload_len);
948 col_append_str_uint(pinfo->cinfo, COL_INFO, "Len", tgen_payload_len, ", ");
949 offset += 2;
951 /* Try to construct a tvbuff containing only
952 the data specified by the tgen_payload_len field. */
954 TRY {
955 tgen_payload_tvb = tvb_new_subset_length(tvb, offset, tgen_payload_len);
957 CATCH_BOUNDS_ERRORS {
958 /* So:
959 the packet doesn't have "tgen_payload_len" bytes worth of
960 captured data left in it so the "tvb_new_subset_length()"
961 creating "payload_tvb" threw an exception
963 This means that all the data in the frame is within the
964 length value, so we give all the data to the payload. */
965 tgen_payload_tvb = tvb_new_subset_remaining(tvb, offset);
967 ENDTRY;
969 /* Get the TGen payload captured length. */
970 uint16_t tgen_payload_captured_len = tvb_captured_length(tgen_payload_tvb);
972 /* Add the TGen payload to the tree, with a heading that displays
973 the TGgen payload captured length. */
974 ti = proto_tree_add_none_format(avsp_tree, hf_avsp_tgen_payload,
975 tgen_payload_tvb, 0, -1, "TGen Payload (%u byte%s)",
976 tgen_payload_captured_len,
977 plurality(tgen_payload_captured_len, "", "s"));
978 avsp_tgen_payload = proto_item_add_subtree(ti, ett_avsp_tgen_payload);
979 proto_tree_add_item(avsp_tgen_payload, hf_avsp_tgen_payload_data, tgen_payload_tvb,
980 0, -1, ENC_NA);
982 /* Now we know the TGen payload captured length (which may be less than
983 that specified in the TGen header because the captured frame may have
984 been truncated) we can set the length of the entire AVSP protocol. */
985 proto_item_set_len(avsp_ti, offset + tgen_payload_captured_len);
987 /* We have a length field, so set it here so that the higher level
988 * (ethertype) dissector can add the trailer. That way the FCS
989 * will be calculated correctly.
991 set_actual_length(tvb, offset + tgen_payload_captured_len);
992 break;
994 default:
995 expert_add_info_format(pinfo, avsp_ti, &ei_avsp_tgen_unknown_version,
996 "Unknown version: 0x%0x", version);
997 return tvb_captured_length(tvb);
999 break;
1001 default:
1002 expert_add_info_format(pinfo, avsp_ti, &ei_avsp_unknown_subtype,
1003 "Unknown subtype: 0x%0x", subtype);
1004 return tvb_captured_length(tvb);
1006 return tvb_captured_length(tvb);
1009 void proto_reg_handoff_avsp(void)
1011 dissector_add_uint("ethertype", ETHERTYPE_AVSP, avsp_handle);
1012 ethertype_handle = find_dissector_add_dependency("ethertype", proto_avsp);
1013 dissector_add_uint("gre.proto", ETHERTYPE_AVSP, avsp_handle);
1016 void proto_register_avsp(void)
1018 /* Field Registration */
1019 static hf_register_info hf[] = {
1020 /* For avsp */
1021 {&hf_avsp_subtype,
1022 {"Subtype", "avsp.subtype",
1023 FT_UINT16, BASE_HEX,
1024 VALS(arista_subtypes), 0x0,
1025 NULL, HFILL}
1027 {&hf_avsp_ts_version,
1028 {"Version", "avsp.ts.ver",
1029 FT_UINT16, BASE_HEX,
1030 VALS(ts_versions), 0x0,
1031 NULL, HFILL}
1033 {&hf_avsp_ts_64_tai,
1034 {"Timestamp (TAI)", "avsp.ts.64.tai",
1035 FT_NONE, BASE_NONE,
1036 NULL, 0x0,
1037 NULL, HFILL}
1039 {&hf_avsp_ts_64_utc,
1040 {"Timestamp (UTC)", "avsp.ts.64.utc",
1041 FT_NONE, BASE_NONE,
1042 NULL, 0x0,
1043 NULL, HFILL}
1045 {&hf_avsp_ts_64_sec,
1046 {"Seconds", "avsp.ts.64.sec",
1047 FT_UINT32, BASE_DEC,
1048 NULL, 0x0,
1049 NULL, HFILL}
1051 {&hf_avsp_ts_64_ns,
1052 {"Nanoseconds", "avsp.ts.64.ns",
1053 FT_UINT32, BASE_DEC,
1054 NULL, 0x0,
1055 NULL, HFILL}
1057 {&hf_avsp_ts_48_tai,
1058 {"Timestamp (TAI)", "avsp.ts.48.tai",
1059 FT_NONE, BASE_NONE,
1060 NULL, 0x0,
1061 NULL, HFILL}
1063 {&hf_avsp_ts_48_utc,
1064 {"Timestamp (UTC)", "avsp.ts.48.utc",
1065 FT_NONE, BASE_NONE,
1066 NULL, 0x0,
1067 NULL, HFILL}
1069 {&hf_avsp_ts_48_sec,
1070 {"Seconds", "avsp.ts.48.sec",
1071 FT_UINT16, BASE_DEC,
1072 NULL, 0x0,
1073 NULL, HFILL}
1075 {&hf_avsp_ts_48_ns,
1076 {"Nanoseconds", "avsp.ts.48.ns",
1077 FT_UINT32, BASE_DEC,
1078 NULL, 0x0,
1079 NULL, HFILL}
1081 {&hf_avsp_etype,
1082 {"Type", "avsp.etype",
1083 FT_UINT16, BASE_HEX,
1084 VALS(etype_vals), 0x0,
1085 "Ethertype", HFILL}
1087 {&hf_avsp_trailer,
1088 {"Trailer", "avsp.trailer",
1089 FT_BYTES, BASE_NONE,
1090 NULL, 0x0,
1091 "AVSP Trailer", HFILL}
1093 {&hf_avsp_greentap_version,
1094 {"Version", "avsp.greentap.ver",
1095 FT_UINT16, BASE_DEC,
1096 VALS(greentap_versions), 0x0,
1097 NULL, HFILL}
1099 {&hf_avsp_greentap_tai,
1100 {"Timestamp (TAI)", "avsp.greentap.tai",
1101 FT_NONE, BASE_NONE,
1102 NULL, 0x0,
1103 NULL, HFILL}
1105 {&hf_avsp_greentap_utc,
1106 {"Timestamp (UTC)", "avsp.greentap.utc",
1107 FT_NONE, BASE_NONE,
1108 NULL, 0x0,
1109 NULL, HFILL}
1111 {&hf_avsp_greentap_sec,
1112 {"Seconds", "avsp.greentap.sec",
1113 FT_UINT16, BASE_DEC,
1114 NULL, 0x0,
1115 NULL, HFILL}
1117 {&hf_avsp_greentap_ns,
1118 {"Nanoseconds", "avsp.greentap.ns",
1119 FT_UINT32, BASE_DEC,
1120 NULL, 0x0,
1121 NULL, HFILL}
1123 {&hf_avsp_greent_version,
1124 {"Version", "avsp.greent.ver",
1125 FT_UINT16, BASE_DEC,
1126 VALS(greent_versions), 0x0,
1127 NULL, HFILL}
1129 {&hf_avsp_greent_hdr,
1130 {"GREENT Header", "avsp.greent.hdr",
1131 FT_NONE, BASE_NONE,
1132 NULL, 0x0,
1133 NULL, HFILL}
1135 {&hf_avsp_greent_session,
1136 {"Session ID", "avsp.greent.session",
1137 FT_UINT16, BASE_DEC,
1138 NULL, 0x0,
1139 NULL, HFILL}
1141 {&hf_avsp_greent_flags,
1142 {"Flags", "avsp.greent.flags",
1143 FT_UINT8, BASE_HEX,
1144 NULL, 0x0,
1145 NULL, HFILL}
1147 {&hf_avsp_greent_sample_count,
1148 {"Sample Count", "avsp.greent.sample_count",
1149 FT_UINT8, BASE_DEC,
1150 NULL, 0x0,
1151 NULL, HFILL}
1153 {&hf_avsp_greent_sample_hdr,
1154 {"Sample Header", "avsp.greent.sample.hdr",
1155 FT_NONE, BASE_NONE,
1156 NULL, 0x0,
1157 NULL, HFILL}
1159 {&hf_avsp_greent_sample_len,
1160 {"Length", "avsp.greent.sample.len",
1161 FT_UINT16, BASE_DEC,
1162 NULL, 0x0,
1163 NULL, HFILL}
1165 {&hf_avsp_greent_sample_sec,
1166 {"Seconds", "avsp.greent.sample.sec",
1167 FT_UINT16, BASE_DEC,
1168 NULL, 0x0,
1169 NULL, HFILL}
1171 {&hf_avsp_greent_sample_ns,
1172 {"Nanoseconds", "avsp.greent.sample.ns",
1173 FT_UINT32, BASE_DEC,
1174 NULL, 0x0,
1175 NULL, HFILL}
1177 {&hf_avsp_greent_sample_ingress,
1178 {"Ingress Interface", "avsp.greent.sample.ingress",
1179 FT_UINT32, BASE_DEC,
1180 NULL, 0x0,
1181 NULL, HFILL}
1183 {&hf_avsp_greent_sample_egress,
1184 {"Egress Interface", "avsp.greent.sample.egress",
1185 FT_UINT32, BASE_DEC,
1186 NULL, 0x0,
1187 NULL, HFILL}
1189 {&hf_avsp_greent_sample_rate,
1190 {"Rate(*1K)", "avsp.greent.sample.rate",
1191 FT_UINT16, BASE_DEC,
1192 NULL, 0x0,
1193 NULL, HFILL}
1195 {&hf_avsp_greent_sample_sum,
1196 {"Checksum", "avsp.greent.sample.sum",
1197 FT_UINT16, BASE_HEX,
1198 NULL, 0x0,
1199 NULL, HFILL}
1201 {&hf_avsp_greent_sample_data,
1202 {"Header of sampled packet", "avsp.greent.sample.data",
1203 FT_BYTES, BASE_NONE,
1204 NULL, 0x0,
1205 "Data from sampled header", HFILL}
1207 {&hf_avsp_dzgre_a_version,
1208 {"Version", "avsp.dzgre_a.ver",
1209 FT_UINT16, BASE_DEC,
1210 VALS(dzgre_a_versions), 0x0,
1211 NULL, HFILL}
1213 {&hf_avsp_dzgre_a_hdr,
1214 {"DzGRE(A) Header", "avsp.dzgre_a.hdr",
1215 FT_NONE, BASE_NONE,
1216 NULL, 0x0,
1217 NULL, HFILL}
1219 {&hf_avsp_dzgre_a_switch,
1220 {"Switch ID", "avsp.dzgre_a.switch",
1221 FT_UINT16, BASE_DEC,
1222 NULL, 0x0,
1223 NULL, HFILL}
1225 {&hf_avsp_dzgre_a_port,
1226 {"Port ID", "avsp.dzgre_a.port",
1227 FT_UINT16, BASE_DEC,
1228 NULL, 0x0,
1229 NULL, HFILL}
1231 {&hf_avsp_dzgre_a_policy,
1232 {"Policy ID", "avsp.dzgre_a.policy",
1233 FT_UINT16, BASE_DEC,
1234 NULL, 0x0,
1235 NULL, HFILL}
1237 {&hf_avsp_dzgre_a_reserved,
1238 {"Reserved", "avsp.dzgre_a.reserved",
1239 FT_UINT16, BASE_HEX,
1240 NULL, 0x0,
1241 NULL, HFILL}
1243 {&hf_avsp_dzgre_b_version,
1244 {"Version", "avsp.dzgre_b.ver",
1245 FT_UINT16, BASE_DEC,
1246 VALS(dzgre_b_versions), 0x0,
1247 NULL, HFILL}
1249 {&hf_avsp_dzgre_b_hdr,
1250 {"DzGRE(B) Header", "avsp.dzgre_b.hdr",
1251 FT_NONE, BASE_NONE,
1252 NULL, 0x0,
1253 NULL, HFILL}
1255 {&hf_avsp_dzgre_b_port,
1256 {"Port ID", "avsp.dzgre_b.port",
1257 FT_UINT16, BASE_DEC,
1258 NULL, 0x0,
1259 NULL, HFILL}
1261 {&hf_avsp_dzgre_b_policy,
1262 {"Policy ID", "avsp.dzgre_b.policy",
1263 FT_UINT16, BASE_DEC,
1264 NULL, 0x0,
1265 NULL, HFILL}
1267 {&hf_avsp_dzgre_ts_version,
1268 {"Version", "avsp.dzgre_ts.ver",
1269 FT_UINT16, BASE_DEC,
1270 VALS(dzgre_b_versions), 0x0,
1271 NULL, HFILL}
1273 {&hf_avsp_dzgre_ts_hdr,
1274 {"DzGRE(B) Header", "avsp.dzgre_ts.hdr",
1275 FT_NONE, BASE_NONE,
1276 NULL, 0x0,
1277 NULL, HFILL}
1279 {&hf_avsp_dzgre_ts_switch,
1280 {"Switch ID", "avsp.dzgre_ts.switch",
1281 FT_UINT16, BASE_DEC,
1282 NULL, 0x0,
1283 NULL, HFILL}
1285 {&hf_avsp_dzgre_ts_port,
1286 {"Port ID", "avsp.dzgre_ts.port",
1287 FT_UINT16, BASE_DEC,
1288 NULL, 0x0,
1289 NULL, HFILL}
1291 {&hf_avsp_dzgre_ts_policy,
1292 {"Policy ID", "avsp.dzgre_ts.policy",
1293 FT_UINT16, BASE_DEC,
1294 NULL, 0x0,
1295 NULL, HFILL}
1297 {&hf_avsp_dzgre_ts_reserved,
1298 {"Reserved", "avsp.dzgre_ts.reserved",
1299 FT_UINT16, BASE_HEX,
1300 NULL, 0x0,
1301 NULL, HFILL}
1303 {&hf_avsp_dzgre_ts_tai,
1304 {"Timestamp (TAI)", "avsp.dzgre_ts.tai",
1305 FT_NONE, BASE_NONE,
1306 NULL, 0x0,
1307 NULL, HFILL}
1309 {&hf_avsp_dzgre_ts_utc,
1310 {"Timestamp (UTC)", "avsp.dzgre_ts.utc",
1311 FT_NONE, BASE_NONE,
1312 NULL, 0x0,
1313 NULL, HFILL}
1315 {&hf_avsp_dzgre_ts_sec,
1316 {"Seconds", "avsp.ts.dzgre_ts.sec",
1317 FT_UINT16, BASE_DEC,
1318 NULL, 0x0,
1319 NULL, HFILL}
1321 {&hf_avsp_dzgre_ts_ns,
1322 {"Nanoseconds", "avsp.dzgre_ts.48.ns",
1323 FT_UINT32, BASE_DEC,
1324 NULL, 0x0,
1325 NULL, HFILL}
1327 {&hf_avsp_tgen_version,
1328 {"Version", "avsp.tgen.ver",
1329 FT_UINT16, BASE_DEC,
1330 VALS(tgen_versions), 0x0,
1331 NULL, HFILL}
1333 {&hf_avsp_tgen_hdr,
1334 {"TGen Header", "avsp.tgen.hdr",
1335 FT_NONE, BASE_NONE,
1336 NULL, 0x0,
1337 NULL, HFILL}
1339 {&hf_avsp_tgen_hdr_ctrl,
1340 {"Control Word", "avsp.tgen.hdr.ctrl",
1341 FT_UINT16, BASE_HEX,
1342 NULL, 0x0,
1343 NULL, HFILL}
1345 {&hf_avsp_tgen_hdr_ctrl_fcs_inverted,
1346 {"FCS Inverted", "avsp.tgen.hdr.ctrl.fcs_inverted",
1347 FT_BOOLEAN, 16,
1348 NULL, 0x0001,
1349 NULL, HFILL}
1351 {&hf_avsp_tgen_hdr_ctrl_reserved,
1352 {"Reserved", "avsp.tgen.hdr.ctrl.reserved",
1353 FT_UINT16, BASE_HEX,
1354 NULL, 0xFFFE,
1355 NULL, HFILL}
1357 {&hf_avsp_tgen_hdr_seq_num,
1358 {"Sequence Number", "avsp.tgen.hdr.seq_num",
1359 FT_UINT16, BASE_DEC,
1360 NULL, 0x0,
1361 NULL, HFILL}
1363 {&hf_avsp_tgen_hdr_payload_len,
1364 {"Payload Length", "avsp.tgen.hdr.payload_len",
1365 FT_UINT16, BASE_DEC,
1366 NULL, 0x0,
1367 NULL, HFILL}
1369 { &hf_avsp_tgen_payload,
1370 {"TGen Payload", "avsp.tgen.payload",
1371 FT_NONE, BASE_NONE,
1372 NULL, 0x0,
1373 NULL, HFILL}
1375 { &hf_avsp_tgen_payload_data,
1376 {"Data", "avsp.tgen.payload.data",
1377 FT_BYTES, BASE_NONE,
1378 NULL, 0x0,
1379 NULL, HFILL}
1383 /* Setup protocol subtree array */
1384 static int* ett[] = {
1385 &ett_avsp, /* main avsp tree */
1386 &ett_avsp_ts_48, /* subtree above for 48 bit timestamp */
1387 &ett_avsp_ts_64, /* subtree above for 64 bit timestamp */
1388 &ett_avsp_dzgre_a_hdr, /* subtree for DzGRE plan A */
1389 &ett_avsp_dzgre_b_hdr, /* subtree for DzGRE plan B */
1390 &ett_avsp_dzgre_ts_hdr, /* subtree for DzGRE with timestamps */
1391 &ett_avsp_dzgre_ts_tai, /* subrtee for DzGRE timestamp */
1392 &ett_avsp_dzgre_ts_utc, /* subrtee for DzGRE timestamp */
1393 &ett_avsp_greent_hdr, /* subtee for GREENT header */
1394 &ett_avsp_greent_sample_hdr, /* subtree for GREENT sample header */
1395 &ett_avsp_greent_sample_data, /* subtree for GREENT sample data */
1396 &ett_avsp_tgen_hdr, /* subtree for TGen header */
1397 &ett_avsp_tgen_hdr_ctrl, /* subtree for TGen header control bits */
1398 &ett_avsp_tgen_payload, /* subtree for TGen payload */
1401 static ei_register_info ei[] = {
1402 { &ei_avsp_unknown_subtype, { "avsp.unknown_subtype", PI_SEQUENCE, PI_WARN, "Unknown AVSP subtype", EXPFILL}},
1403 { &ei_avsp_ts_unknown_version, { "avsp.ts.unknown_version", PI_SEQUENCE, PI_WARN, "Unknown timestamp version", EXPFILL }},
1404 { &ei_avsp_greentap_unknown_version, { "avsp.greentap.unknown_version", PI_SEQUENCE, PI_WARN, "Unknown GREENTAP version", EXPFILL }},
1405 { &ei_avsp_greent_unknown_version, { "avsp.greent.unknown_version", PI_SEQUENCE, PI_WARN, "Unknown GREENT version", EXPFILL }},
1406 { &ei_avsp_dzgre_a_unknown_version, { "avsp.dzgre_a.unknown_version", PI_SEQUENCE, PI_WARN, "Unknown DzGRE(A) version", EXPFILL }},
1407 { &ei_avsp_dzgre_b_unknown_version, { "avsp.dzgre_b.unknown_version", PI_SEQUENCE, PI_WARN, "Unknown DzGRE(B) version", EXPFILL }},
1408 { &ei_avsp_dzgre_ts_unknown_version, { "avsp.dzgre_ts.unknown_version", PI_SEQUENCE, PI_WARN, "Unknown DzGRE(timestamped) version", EXPFILL }},
1409 { &ei_avsp_tgen_unknown_version, { "avsp.tgen.unknown_version", PI_SEQUENCE, PI_WARN, "Unknown TGen version", EXPFILL }},
1412 /* Register the AVSP protocol. */
1413 proto_avsp = proto_register_protocol("Arista Vendor Specific Protocol", "AVSP", "avsp");
1415 /* Register header fields and subtrees. */
1416 proto_register_field_array(proto_avsp, hf, array_length(hf));
1418 /* Register subtree types. */
1419 proto_register_subtree_array(ett, array_length(ett));
1421 /* Register the expert module. */
1422 expert_register_field_array(expert_register_protocol(proto_avsp), ei, array_length(ei));
1424 /* Register the dissector handle. */
1425 avsp_handle = register_dissector("avsp", dissect_avsp, proto_avsp);
1429 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1431 * Local variables:
1432 * c-basic-offset: 4
1433 * tab-width: 8
1434 * indent-tabs-mode: nil
1435 * End:
1437 * vi: set shiftwidth=4 tabstop=8 expandtab:
1438 * :indentSize=4:tabSize=8:noTabs=true: