2 * Routines for iPerf dissection
3 * By Anish Bhatt <anish@gatech.edu>
5 * Updates for iperf 2.1.9
6 * By Andrii Vladyka <a.vladyka@ukr.net>
7 * By Robert McMahon <rjmcmahon@rjmcmahon.com>
8 * TODO: server-side packets (pending clarifications form Bob)
10 * Wireshark - Network traffic analyzer
11 * By Gerald Combs <gerald@wireshark.org>
12 * Copyright 1998 Gerald Combs
14 * SPDX-License-Identifier: GPL-2.0-or-later
18 #include <epan/packet.h>
19 #include <epan/tvbparse.h>
21 #define IPERF2_UDP_HDR_SIZE 160
23 void proto_register_iperf2(void);
24 void proto_reg_handoff_iperf2(void);
26 static int proto_iperf2
;
28 static int hf_iperf2_sequence
;
29 static int hf_iperf2_sec
;
30 static int hf_iperf2_usec
;
31 static int hf_iperf2_timestamp
;
32 static int hf_iperf2_sequence_upper
;
33 static int hf_iperf2_flags
;
34 static int hf_iperf2_num_threads
;
35 static int hf_iperf2_mport
;
36 static int hf_iperf2_bufferlen
;
37 static int hf_iperf2_mwinband
;
38 static int hf_iperf2_mamount
;
39 static int hf_iperf2_type
;
40 static int hf_iperf2_length
;
41 static int hf_iperf2_up_flags
;
42 static int hf_iperf2_low_flags
;
43 static int hf_iperf2_version_major
;
44 static int hf_iperf2_version_minor
;
45 static int hf_iperf2_version
;
46 static int hf_iperf2_reserved
;
47 static int hf_iperf2_tos
;
48 static int hf_iperf2_rate
;
49 static int hf_iperf2_rate_units
;
50 static int hf_iperf2_realtime
;
51 static int hf_iperf2_permit_key_len
;
52 static int hf_iperf2_permit_key
;
53 static int hf_iperf2_isoch_burst_period
;
54 static int hf_iperf2_isoch_start_ts_s
;
55 static int hf_iperf2_isoch_start_ts_us
;
56 static int hf_iperf2_isoch_start_ts
;
57 static int hf_iperf2_isoch_prev_frameid
;
58 static int hf_iperf2_isoch_frameid
;
59 static int hf_iperf2_isoch_burstsize
;
60 static int hf_iperf2_isoch_bytes_remaining
;
61 static int hf_iperf2_isoch_reserved
;
62 static int hf_iperf2_reserved2
;
63 static int hf_iperf2_start_tv_sec
;
64 static int hf_iperf2_start_tv_usec
;
65 static int hf_iperf2_start_tv
;
66 static int hf_iperf2_fq_ratel
;
67 static int hf_iperf2_fq_rateu
;
68 static int hf_iperf2_fpsl
;
69 static int hf_iperf2_fpsu
;
70 static int hf_iperf2_meanl
;
71 static int hf_iperf2_meanu
;
72 static int hf_iperf2_variancel
;
73 static int hf_iperf2_varianceu
;
74 static int hf_iperf2_burstipgl
;
75 static int hf_iperf2_burstipg
;
76 static int hf_iperf2_cca_len
;
77 static int hf_iperf2_cca_value
;
78 static int hf_iperf2_bb_size
;
79 static int hf_iperf2_bb_id
;
80 static int hf_iperf2_bb_flags
;
81 static int hf_iperf2_bb_tos
;
82 static int hf_iperf2_bb_run_time
;
83 static int hf_iperf2_bb_clienttx_ts_sec
;
84 static int hf_iperf2_bb_clienttx_ts_usec
;
85 static int hf_iperf2_bb_clienttx_ts
;
86 static int hf_iperf2_bb_serverrx_ts_sec
;
87 static int hf_iperf2_bb_serverrx_ts_usec
;
88 static int hf_iperf2_bb_serverrx_ts
;
89 static int hf_iperf2_bb_servertx_ts_sec
;
90 static int hf_iperf2_bb_servertx_ts_usec
;
91 static int hf_iperf2_bb_servertx_ts
;
92 static int hf_iperf2_bb_hold
;
93 static int hf_iperf2_bb_rtt
;
94 static int hf_iperf2_bb_read_ts_sec
;
95 static int hf_iperf2_bb_read_ts_usec
;
96 static int hf_iperf2_bb_read_ts
;
97 static int hf_iperf2_bb_reply_size
;
99 // Flags definition for hf_iperf2_flags. See include/Listener.hpp in iperf2 source code
100 #define HEADER_VERSION1 0x80000000
101 #define HEADER_EXTEND 0x40000000
102 #define HEADER_UDPTESTS 0x20000000
103 #define HEADER_SEQNO64B 0x08000000
104 #define HEADER_VERSION2 0x04000000
105 #define HEADER_V2PEERDETECT 0x02000000
106 #define HEADER_UDPAVOID2 0x02000000
107 #define HEADER_UDPAVOID1 0x01000000
108 #define HEADER_BOUNCEBACK 0x00800000
109 #define HEADER32_SMALL_TRIPTIMES 0x00020000
110 #define HEADER_LEN_BIT 0x00010000
111 #define HEADER_LEN_MASK 0x000001FE
112 #define RUN_NOW 0x00000001
113 #define HEADER16_SMALL_TRIPTIMES 0x00020000
115 #define HEADER_ISOCH 0x0001
116 #define HEADER_L2ETHPIPV6 0x0002
117 #define HEADER_L2LENCHECK 0x0004
118 #define HEADER_NOUDPFIN 0x0008
119 #define HEADER_TRIPTIME 0x0010
120 #define HEADER_UNUSED2 0x0020
121 #define HEADER_ISOCH_SETTINGS 0x0040
122 #define HEADER_UNITS_PPS 0x0080
123 #define HEADER_BWSET 0x0100
124 #define HEADER_FQRATESET 0x0200
125 #define HEADER_REVERSE 0x0400
126 #define HEADER_FULLDUPLEX 0x0800
127 #define HEADER_EPOCH_START 0x1000
128 #define HEADER_PERIODICBURST 0x2000
129 #define HEADER_WRITEPREFETCH 0x4000
130 #define HEADER_TCPQUICKACK 0x8000
132 #define HEADER_BBQUICKACK 0x8000
133 #define HEADER_BBCLOCKSYNCED 0x4000
134 #define HEADER_BBTOS 0x2000
135 #define HEADER_BBSTOP 0x1000
136 #define HEADER_BBREPLYSIZE 0x0800
138 // lower flags (16 bit)
139 #define HEADER_CCA 0x8000
141 // Flags fields declarations for hf_iperf2_flags
142 static int hf_iperf2_flag_header_version1
;
143 static int hf_iperf2_flag_header_extend
;
144 static int hf_iperf2_header_udptests
;
145 static int hf_iperf2_header_seqno64b
;
146 static int hf_iperf2_header_version2
;
147 static int hf_iperf2_header_v2peerdetect
;
148 static int hf_iperf2_header_udpavoid
;
149 static int hf_iperf2_header_bounceback
;
150 static int hf_iperf2_header_len_bit
;
151 static int hf_iperf2_header_len_mask
;
152 static int hf_iperf2_run_now
;
153 static int hf_iperf2_header16_small_triptimes
;
154 static int hf_iperf2_payload
;
156 static int * const iperf2_flags
[] = {
157 &hf_iperf2_flag_header_version1
,
158 &hf_iperf2_flag_header_extend
,
159 &hf_iperf2_header_udptests
,
160 &hf_iperf2_header_seqno64b
,
161 &hf_iperf2_header_version2
,
162 &hf_iperf2_header_v2peerdetect
,
163 &hf_iperf2_header_udpavoid
,
164 &hf_iperf2_header_bounceback
,
165 &hf_iperf2_header_len_mask
,
166 &hf_iperf2_header16_small_triptimes
,
167 &hf_iperf2_header_len_bit
,
172 // Flags fields declarations for iperf2_upper_flags
173 static int hf_iperf2_upper_header_isoch
;
174 static int hf_iperf2_upper_header_l2ethpipv6
;
175 static int hf_iperf2_upper_header_l2lencheck
;
176 static int hf_iperf2_upper_header_noudpfin
;
177 static int hf_iperf2_upper_header_triptime
;
178 static int hf_iperf2_upper_header_unused2
;
179 static int hf_iperf2_upper_header_isoch_settings
;
180 static int hf_iperf2_upper_header_units_pps
;
181 static int hf_iperf2_upper_header_bwset
;
182 static int hf_iperf2_upper_header_fqrateset
;
183 static int hf_iperf2_upper_header_reverse
;
184 static int hf_iperf2_upper_header_fullduplex
;
185 static int hf_iperf2_upper_header_epoch_start
;
186 static int hf_iperf2_upper_header_periodicburst
;
187 static int hf_iperf2_upper_header_writeprefetch
;
188 static int hf_iperf2_upper_header_tcpquickack
;
190 static int * const iperf2_upper_flags
[] = {
191 &hf_iperf2_upper_header_tcpquickack
,
192 &hf_iperf2_upper_header_writeprefetch
,
193 &hf_iperf2_upper_header_periodicburst
,
194 &hf_iperf2_upper_header_epoch_start
,
195 &hf_iperf2_upper_header_fullduplex
,
196 &hf_iperf2_upper_header_reverse
,
197 &hf_iperf2_upper_header_fqrateset
,
198 &hf_iperf2_upper_header_bwset
,
199 &hf_iperf2_upper_header_units_pps
,
200 &hf_iperf2_upper_header_isoch_settings
,
201 &hf_iperf2_upper_header_unused2
,
202 &hf_iperf2_upper_header_triptime
,
203 &hf_iperf2_upper_header_noudpfin
,
204 &hf_iperf2_upper_header_l2lencheck
,
205 &hf_iperf2_upper_header_l2ethpipv6
,
206 &hf_iperf2_upper_header_isoch
,
210 // Flags fields declarations for iperf2_lower_flags
211 static int hf_iperf2_lower_header_cca
;
213 static int * const iperf2_lower_flags
[] = {
214 &hf_iperf2_lower_header_cca
,
218 // Flags fields declarations for iperf2_bb_flags
219 static int hf_iperf2_header_bbquickack
;
220 static int hf_iperf2_header_bbclocksynced
;
221 static int hf_iperf2_header_bbtos
;
222 static int hf_iperf2_header_bbstop
;
223 static int hf_iperf2_header_bbreplysize
;
225 static int * const iperf2_bb_flags
[] = {
226 &hf_iperf2_header_bbquickack
,
227 &hf_iperf2_header_bbclocksynced
,
228 &hf_iperf2_header_bbtos
,
229 &hf_iperf2_header_bbstop
,
230 &hf_iperf2_header_bbreplysize
,
234 static int ett_iperf2_udp
;
235 static int ett_iperf2_tcp
;
236 static int ett_udphdr
;
237 static int ett_clienthdr
;
238 static int ett_bbhdr
;
239 static int ett_extendedhdr
;
240 static int ett_permit_key
;
241 static int ett_client_upper_flags
;
242 static int ett_client_lower_flags
;
243 static int ett_isochhdr
;
244 static int ett_fqhdr
;
245 static int ett_ext_isochhdr
;
246 static int ett_client_hdr
;
247 static int ett_client_hdr_flags
;
248 static int ett_cca_hdr
;
249 static int ett_bb_hdr_flags
;
250 static int ett_bbclienttx_ts
;
251 static int ett_bbserverrx_ts
;
252 static int ett_bbservertx_ts
;
253 static int ett_bbread_ts
;
256 /* parser definitions for iperf2 payload */
257 static tvbparse_wanted_t
*want
;
258 static tvbparse_wanted_t
*want_trailing
;
260 static dissector_handle_t iperf2_handle_tcp
;
261 static dissector_handle_t iperf2_handle_udp
;
264 bool first_packet_processed
;
265 bool second_packet_processed
;
266 } iperf2_conversation_t
;
269 format_version(char *buf
, uint32_t value
) {
270 snprintf(buf
, ITEM_LABEL_LENGTH
, "%d.%d", (value
& 0xFFFF0000) >> 16, (value
& 0xFFFF));
274 format_version_long(char *buf
, uint64_t value
) {
275 snprintf(buf
, ITEM_LABEL_LENGTH
, "%d.%d.%d.%d",
276 (uint32_t)((value
& 0xFFFF000000000000) >> 48), (uint32_t)((value
& 0xFFFF00000000) >> 32),
277 (uint32_t)((value
& 0xFFFF0000) >> 16), (uint32_t)(value
& 0xFFFF));
281 dissect_iperf2_payload(tvbuff_t
*tvb
, proto_tree
*tree
, uint32_t offset
)
283 proto_tree
*data_tree
;
285 data_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, tvb_reported_length(tvb
) - offset
, ett_data
, NULL
, "iPerf2 Payload");
286 proto_tree_add_item(data_tree
, hf_iperf2_payload
, tvb
, offset
, tvb_reported_length(tvb
) - offset
, ENC_NA
);
287 offset
= tvb_reported_length(tvb
);
293 dissect_iperf2_client_header(tvbuff_t
*tvb
, proto_tree
*tree
, uint32_t offset
, bool is_udp
)
295 uint32_t small_packets
= 0;
296 uint32_t initial_offset
= offset
;
297 int client_header_size
= 24;
298 proto_tree
*client_tree
;
301 small_packets
= tvb_get_uint32(tvb
, offset
, ENC_BIG_ENDIAN
);
302 if (small_packets
& HEADER32_SMALL_TRIPTIMES
) {
303 client_header_size
= 4;
307 client_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, client_header_size
, ett_clienthdr
, NULL
, "iPerf2 Client Header");
308 proto_tree_add_bitmask(client_tree
, tvb
, offset
, hf_iperf2_flags
, ett_client_hdr_flags
, iperf2_flags
, ENC_BIG_ENDIAN
);
312 if (small_packets
& HEADER32_SMALL_TRIPTIMES
) {
313 if ((tvb_reported_length(tvb
) - offset
) > 0) {
314 return dissect_iperf2_payload(tvb
, tree
, offset
);
316 return offset
- initial_offset
;
321 proto_tree_add_item(client_tree
, hf_iperf2_num_threads
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
323 proto_tree_add_item(client_tree
, hf_iperf2_mport
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
325 proto_tree_add_item(client_tree
, hf_iperf2_bufferlen
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
327 proto_tree_add_item(client_tree
, hf_iperf2_mwinband
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
329 proto_tree_add_item(client_tree
, hf_iperf2_mamount
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
332 return offset
- initial_offset
;
336 dissect_iperf2_extended_header(tvbuff_t
*tvb
, proto_tree
*tree
, uint32_t offset
)
338 uint32_t initial_offset
= offset
, permit_key_len
= 0;
339 proto_tree
*extended_tree
, *permit_key_tree
;
342 extended_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, 36, ett_extendedhdr
, NULL
, "iPerf2 Extended Header");
343 proto_tree_add_item(extended_tree
, hf_iperf2_type
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
345 proto_tree_add_item(extended_tree
, hf_iperf2_length
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
347 proto_tree_add_bitmask(extended_tree
, tvb
, offset
, hf_iperf2_up_flags
, ett_client_upper_flags
, iperf2_upper_flags
, ENC_BIG_ENDIAN
);
349 proto_tree_add_bitmask(extended_tree
, tvb
, offset
, hf_iperf2_low_flags
, ett_client_lower_flags
, iperf2_lower_flags
, ENC_BIG_ENDIAN
);
351 proto_tree_add_item(extended_tree
, hf_iperf2_version_major
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
353 proto_tree_add_item(extended_tree
, hf_iperf2_version_minor
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
355 ti
= proto_tree_add_item(extended_tree
, hf_iperf2_version
, tvb
, offset
- 8, 8, ENC_BIG_ENDIAN
);
356 proto_item_set_generated(ti
);
357 proto_tree_add_item(extended_tree
, hf_iperf2_reserved
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
359 proto_tree_add_item(extended_tree
, hf_iperf2_tos
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
361 proto_tree_add_item(extended_tree
, hf_iperf2_rate
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
363 proto_tree_add_item(extended_tree
, hf_iperf2_rate_units
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
365 proto_tree_add_item(extended_tree
, hf_iperf2_realtime
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
368 // There may be an optional permit key at the end of this header. Flags are not reliable - do some heuristics here instead.
369 if (tvb_reported_length(tvb
) - offset
>= 2) {
370 permit_key_len
= tvb_get_uint16(tvb
, offset
, ENC_BIG_ENDIAN
);
371 if ((permit_key_len
!= 0) && (permit_key_len
<= (tvb_reported_length(tvb
) - offset
- 2))) {
372 permit_key_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, permit_key_len
+ 2, ett_permit_key
, NULL
, "iPerf2 Permit Key");
373 proto_tree_add_item(permit_key_tree
, hf_iperf2_permit_key_len
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
375 proto_tree_add_item(permit_key_tree
, hf_iperf2_permit_key
, tvb
, offset
, permit_key_len
, ENC_ASCII
);
376 offset
+= permit_key_len
;
379 return offset
- initial_offset
;
383 dissect_iperf2_isoch_header(tvbuff_t
*tvb
, proto_tree
*tree
, uint32_t offset
)
385 uint32_t initial_offset
= offset
;
386 proto_tree
*ext_isoch_tree
;
388 ext_isoch_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, 32, ett_ext_isochhdr
, NULL
, "iPerf2 Extended Isochronous Header");
389 proto_tree_add_item(ext_isoch_tree
, hf_iperf2_fpsl
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
391 proto_tree_add_item(ext_isoch_tree
, hf_iperf2_fpsu
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
393 proto_tree_add_item(ext_isoch_tree
, hf_iperf2_meanl
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
395 proto_tree_add_item(ext_isoch_tree
, hf_iperf2_meanu
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
397 proto_tree_add_item(ext_isoch_tree
, hf_iperf2_variancel
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
399 proto_tree_add_item(ext_isoch_tree
, hf_iperf2_varianceu
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
401 proto_tree_add_item(ext_isoch_tree
, hf_iperf2_burstipgl
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
403 proto_tree_add_item(ext_isoch_tree
, hf_iperf2_burstipg
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
406 return offset
- initial_offset
;
410 dissect_iperf2_isoch_payload_header(tvbuff_t
*tvb
, proto_tree
*tree
, uint32_t offset
)
413 uint32_t initial_offset
= offset
;
414 proto_tree
*isoch_tree
;
415 nstime_t isoch_timestamp
;
416 unsigned isoch_ts_sec
= 0;
417 unsigned isoch_ts_usec
= 0;
419 isoch_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, 32, ett_isochhdr
, NULL
, "iPerf2 Isochronous Header");
420 proto_tree_add_item(isoch_tree
, hf_iperf2_isoch_burst_period
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
422 proto_tree_add_item_ret_uint(isoch_tree
, hf_iperf2_isoch_start_ts_s
, tvb
, offset
, 4, ENC_BIG_ENDIAN
, &isoch_ts_sec
);
424 proto_tree_add_item_ret_uint(isoch_tree
, hf_iperf2_isoch_start_ts_us
, tvb
, offset
, 4, ENC_BIG_ENDIAN
, &isoch_ts_usec
);
426 isoch_timestamp
.secs
= (time_t)isoch_ts_sec
;
427 isoch_timestamp
.nsecs
= (int)isoch_ts_usec
* 1000;
428 ti
= proto_tree_add_time(isoch_tree
, hf_iperf2_isoch_start_ts
, tvb
, offset
- 8, 8, &isoch_timestamp
);
429 proto_item_set_generated(ti
);
430 proto_tree_add_item(isoch_tree
, hf_iperf2_isoch_prev_frameid
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
432 proto_tree_add_item(isoch_tree
, hf_iperf2_isoch_frameid
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
434 proto_tree_add_item(isoch_tree
, hf_iperf2_isoch_burstsize
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
436 proto_tree_add_item(isoch_tree
, hf_iperf2_isoch_bytes_remaining
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
438 proto_tree_add_item(isoch_tree
, hf_iperf2_isoch_reserved
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
441 return offset
- initial_offset
;
445 dissect_iperf2_fq_start_time_header(tvbuff_t
*tvb
, proto_tree
*tree
, uint32_t offset
)
448 uint32_t initial_offset
= offset
;
450 unsigned fq_ts_sec
= 0;
451 unsigned fq_ts_usec
= 0;
452 nstime_t fq_timestamp
;
454 fq_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, 20, ett_fqhdr
, NULL
, "iPerf2 Fair Queue Start Time Header");
455 proto_tree_add_item(fq_tree
, hf_iperf2_reserved2
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
457 proto_tree_add_item_ret_uint(fq_tree
, hf_iperf2_start_tv_sec
, tvb
, offset
, 4, ENC_BIG_ENDIAN
, &fq_ts_sec
);
459 proto_tree_add_item_ret_uint(fq_tree
, hf_iperf2_start_tv_usec
, tvb
, offset
, 4, ENC_BIG_ENDIAN
, &fq_ts_usec
);
461 fq_timestamp
.secs
= (time_t)fq_ts_sec
;
462 fq_timestamp
.nsecs
= (int)fq_ts_usec
* 1000;
463 ti
= proto_tree_add_time(fq_tree
, hf_iperf2_start_tv
, tvb
, offset
- 8, 8, &fq_timestamp
);
464 proto_item_set_generated(ti
);
465 proto_tree_add_item(fq_tree
, hf_iperf2_fq_ratel
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
467 proto_tree_add_item(fq_tree
, hf_iperf2_fq_rateu
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
470 return offset
- initial_offset
;
474 dissect_iperf2_cca_header(tvbuff_t
*tvb
, proto_tree
*tree
, uint32_t offset
)
476 uint32_t initial_offset
= offset
;
477 unsigned cca_payload_len
;
478 proto_tree
*cca_tree
;
480 cca_payload_len
= tvb_get_uint16(tvb
, offset
, ENC_BIG_ENDIAN
);
481 cca_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, cca_payload_len
+ 2, ett_cca_hdr
, NULL
, "iPerf2 CCA Header");
482 proto_tree_add_item(cca_tree
, hf_iperf2_cca_len
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
484 proto_tree_add_item(cca_tree
, hf_iperf2_cca_value
, tvb
, offset
, cca_payload_len
, ENC_ASCII
);
485 offset
+= cca_payload_len
;
487 return offset
- initial_offset
;
491 dissect_iperf2_bounceback_header(tvbuff_t
*tvb
, proto_tree
*tree
, uint32_t offset
)
493 proto_tree
*bb_tree
, *bb_tree_clienttx_ts
, *bb_tree_serverrx_ts
, *bb_tree_servertx_ts
, *bb_tree_read_ts
;
495 unsigned ts_sec
= 0, ts_usec
= 0;
496 nstime_t clienttx_ts
, serverrx_ts
, servertx_ts
, read_ts
;
498 bb_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, 64, ett_bbhdr
, NULL
, "iPerf2 Bounceback Header");
499 proto_tree_add_bitmask(bb_tree
, tvb
, offset
, hf_iperf2_flags
, ett_client_hdr_flags
, iperf2_flags
, ENC_BIG_ENDIAN
);
501 proto_tree_add_item(bb_tree
, hf_iperf2_bb_size
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
503 proto_tree_add_item(bb_tree
, hf_iperf2_bb_id
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
505 proto_tree_add_bitmask(bb_tree
, tvb
, offset
, hf_iperf2_bb_flags
, ett_bb_hdr_flags
, iperf2_bb_flags
, ENC_BIG_ENDIAN
);
507 proto_tree_add_item(bb_tree
, hf_iperf2_bb_tos
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
509 unsigned bb_run_time
= 0;
510 ti
= proto_tree_add_item_ret_uint(bb_tree
, hf_iperf2_bb_run_time
, tvb
, offset
, 4, ENC_BIG_ENDIAN
, &bb_run_time
);
511 proto_item_append_text(ti
, "%d ms", bb_run_time
* 10);
514 bb_tree_clienttx_ts
= proto_tree_add_subtree(bb_tree
, tvb
, offset
, 8, ett_bbclienttx_ts
, NULL
, "Client Tx Timestamp");
515 proto_tree_add_item_ret_uint(bb_tree_clienttx_ts
, hf_iperf2_bb_clienttx_ts_sec
, tvb
, offset
, 4, ENC_BIG_ENDIAN
, &ts_sec
);
517 proto_tree_add_item_ret_uint(bb_tree_clienttx_ts
, hf_iperf2_bb_clienttx_ts_usec
, tvb
, offset
, 4, ENC_BIG_ENDIAN
, &ts_usec
);
519 clienttx_ts
.secs
= (time_t)ts_sec
;
520 clienttx_ts
.nsecs
= (int)ts_usec
* 1000;
521 ti
= proto_tree_add_time(bb_tree_clienttx_ts
, hf_iperf2_bb_clienttx_ts
, tvb
, offset
- 8, 8, &clienttx_ts
);
522 proto_item_set_generated(ti
);
524 bb_tree_serverrx_ts
= proto_tree_add_subtree(bb_tree
, tvb
, offset
, 8, ett_bbserverrx_ts
, NULL
, "Server Rx Timestamp");
525 proto_tree_add_item_ret_uint(bb_tree_serverrx_ts
, hf_iperf2_bb_serverrx_ts_sec
, tvb
, offset
, 4, ENC_BIG_ENDIAN
, &ts_sec
);
527 proto_tree_add_item_ret_uint(bb_tree_serverrx_ts
, hf_iperf2_bb_serverrx_ts_usec
, tvb
, offset
, 4, ENC_BIG_ENDIAN
, &ts_usec
);
529 serverrx_ts
.secs
= (time_t)ts_sec
;
530 serverrx_ts
.nsecs
= (int)ts_usec
* 1000;
531 ti
= proto_tree_add_time(bb_tree_serverrx_ts
, hf_iperf2_bb_serverrx_ts
, tvb
, offset
- 8, 8, &serverrx_ts
);
532 proto_item_set_generated(ti
);
534 bb_tree_servertx_ts
= proto_tree_add_subtree(bb_tree
, tvb
, offset
, 8, ett_bbservertx_ts
, NULL
, "Server Tx Timestamp");
535 proto_tree_add_item_ret_uint(bb_tree_servertx_ts
, hf_iperf2_bb_servertx_ts_sec
, tvb
, offset
, 4, ENC_BIG_ENDIAN
, &ts_sec
);
537 proto_tree_add_item_ret_uint(bb_tree_servertx_ts
, hf_iperf2_bb_servertx_ts_usec
, tvb
, offset
, 4, ENC_BIG_ENDIAN
, &ts_usec
);
539 servertx_ts
.secs
= (time_t)ts_sec
;
540 servertx_ts
.nsecs
= (int)ts_usec
* 1000;
541 ti
= proto_tree_add_time(bb_tree_servertx_ts
, hf_iperf2_bb_servertx_ts
, tvb
, offset
- 8, 8, &servertx_ts
);
542 proto_item_set_generated(ti
);
544 proto_tree_add_item(bb_tree
, hf_iperf2_bb_hold
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
546 proto_tree_add_item(bb_tree
, hf_iperf2_bb_rtt
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
549 bb_tree_read_ts
= proto_tree_add_subtree(bb_tree
, tvb
, offset
, 8, ett_bbread_ts
, NULL
, "Read Timestamp");
550 proto_tree_add_item_ret_uint(bb_tree_read_ts
, hf_iperf2_bb_read_ts_sec
, tvb
, offset
, 4, ENC_BIG_ENDIAN
, &ts_sec
);
552 proto_tree_add_item_ret_uint(bb_tree_read_ts
, hf_iperf2_bb_read_ts_usec
, tvb
, offset
, 4, ENC_BIG_ENDIAN
, &ts_usec
);
554 read_ts
.secs
= (time_t)ts_sec
;
555 read_ts
.nsecs
= (int)ts_usec
* 1000;
556 ti
= proto_tree_add_time(bb_tree_read_ts
, hf_iperf2_bb_read_ts
, tvb
, offset
- 8, 8, &read_ts
);
557 proto_item_set_generated(ti
);
559 proto_tree_add_item(bb_tree
, hf_iperf2_bb_reply_size
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
565 dissect_iperf2_tcp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void * data _U_
)
567 proto_item
*ti
= NULL
;
568 proto_tree
*iperf2_tree
= NULL
;
569 uint32_t offset
= 0, flags
= 0, upper_flags
= 0, lower_flags
= 0, pdu_len
= 24;
573 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "iPerf2");
574 col_clear(pinfo
->cinfo
, COL_INFO
);
576 // Is it the TCP first write with test information
577 if ((tvb_reported_length(tvb
) - offset
) < pdu_len
) { // We don't have enough data to decode the header
578 offset
+= tvb_reported_length(tvb
);
579 pinfo
->desegment_offset
= offset
;
580 pinfo
->desegment_len
= pdu_len
- offset
;
581 return tvb_reported_length(tvb
);
584 flags
= tvb_get_uint32(tvb
, offset
, ENC_BIG_ENDIAN
);
585 ti
= proto_tree_add_item(tree
, proto_iperf2
, tvb
, offset
, pdu_len
, ENC_NA
);
586 iperf2_tree
= proto_item_add_subtree(ti
, ett_iperf2_tcp
);
588 // Check if we got iPerf2 payload
589 // First, check if the first 10 bytes look like payload
590 tt
= tvbparse_init(pinfo
->pool
, tvb
, offset
, 10, NULL
, NULL
);
591 if (tvbparse_get(tt
, want
)) { // Okay, the first 10 bytes follow the pattern, continue...
592 tvbparse_reset(tt
, offset
+ 10, tvb_reported_length(tvb
) - 10);
593 while(tvbparse_curr_offset(tt
) < tvb_reported_length(tvb
)) {
594 if(tvbparse_get(tt
, want
) == NULL
)
597 // Special case for the trailing payload bytes less than 10 bytes of length
598 if ((tvb_reported_length(tvb
) - tvbparse_curr_offset(tt
)) <= 10) {
599 tvbparse_get(tt
, want_trailing
);
601 if (tvbparse_curr_offset(tt
) == tvb_reported_length(tvb
)) {
602 col_set_str(pinfo
->cinfo
, COL_INFO
, "Payload only");
603 offset
+= dissect_iperf2_payload(tvb
, iperf2_tree
, offset
);
604 proto_item_set_len(ti
, tvb_reported_length(tvb
));
608 /* Here we try to understand what extra headers are present. The options are:
609 - client_hdrext (36 bytes)
610 - may contain permitKey (up to 130 bytes)
611 - client_hdrext_starttime_fq (20 bytes)
612 - client_hdrext_isoch_settings (40 bytes)
613 - cca_field (34 bytes)
614 - Combinations of the above
615 - OR a bounnceback header (64 bytes in total)
617 We do two pass analysis to avoid code duplication:
618 - First, we collect the total headers length
619 - Second, we confirm that TCP buffer provided enough bytes to decode all headers
620 - If needed, stop decoding and ask TCP for more data */
621 for (int pass
= 1; pass
<= 2; pass
++) {
622 if (flags
& HEADER_BOUNCEBACK
) {
623 (pass
== 1) ? (pdu_len
= 64) : (offset
+= dissect_iperf2_bounceback_header(tvb
, iperf2_tree
, offset
));
624 col_set_str(pinfo
->cinfo
, COL_INFO
, "Bounceback");
627 offset
+= dissect_iperf2_client_header(tvb
, iperf2_tree
, offset
, false);
628 if (flags
& HEADER_EXTEND
) {
632 upper_flags
= tvb_get_uint16(tvb
, offset
+ 8, ENC_BIG_ENDIAN
);
633 lower_flags
= tvb_get_uint16(tvb
, offset
+ 10, ENC_BIG_ENDIAN
);
634 offset
+= dissect_iperf2_extended_header(tvb
, iperf2_tree
, offset
);
637 // If CCA header is present, the the previous two headers are also present, though the flags may not be set
638 if (lower_flags
& HEADER_CCA
) {
640 cca_len
= tvb_get_uint16(tvb
, offset
+ 20 + 40, ENC_BIG_ENDIAN
) + 2;
641 pdu_len
+= 20 + 40 + cca_len
;
644 offset
+= dissect_iperf2_fq_start_time_header(tvb
, iperf2_tree
, offset
);
645 offset
+= dissect_iperf2_isoch_header(tvb
, iperf2_tree
, offset
);
646 offset
+= dissect_iperf2_cca_header(tvb
, iperf2_tree
, offset
);
649 if (upper_flags
& HEADER_TRIPTIME
|| upper_flags
& HEADER_FQRATESET
||
650 upper_flags
& HEADER_ISOCH_SETTINGS
|| upper_flags
& HEADER_EPOCH_START
) {
651 (pass
== 1) ? (pdu_len
+= 20) : (offset
+= dissect_iperf2_fq_start_time_header(tvb
, iperf2_tree
, offset
));
653 if (upper_flags
& HEADER_FULLDUPLEX
|| upper_flags
& HEADER_REVERSE
|| upper_flags
& HEADER_PERIODICBURST
) {
654 (pass
== 1) ? (pdu_len
+= 40) : (offset
+= dissect_iperf2_isoch_header(tvb
, iperf2_tree
, offset
));
658 if ((pass
== 1) && (tvb_reported_length(tvb
) - offset
) < pdu_len
) { // We don't have enough data to decode all headers
659 offset
+= tvb_reported_length(tvb
);
660 pinfo
->desegment_offset
= offset
;
661 pinfo
->desegment_len
= pdu_len
- offset
;
662 proto_item_set_len(ti
, tvb_reported_length(tvb
));
663 return tvb_reported_length(tvb
);
666 if ((tvb_reported_length(tvb
) - offset
) > 0) {
667 offset
+= dissect_iperf2_payload(tvb
, iperf2_tree
, offset
);
669 proto_item_set_len(ti
, offset
);
674 dissect_iperf2_udp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void * data _U_
)
677 uint32_t ext_header
= 0;
679 proto_tree
*iperf2_tree
, *udp_tree
;
681 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "iPerf2");
682 /* Clear out stuff in the info column */
683 col_clear(pinfo
->cinfo
, COL_INFO
);
685 ti
= proto_tree_add_item(tree
, proto_iperf2
, tvb
, offset
, IPERF2_UDP_HDR_SIZE
, ENC_NA
);
686 iperf2_tree
= proto_item_add_subtree(ti
, ett_iperf2_udp
);
688 udp_tree
= proto_tree_add_subtree(iperf2_tree
, tvb
, offset
, 16, ett_udphdr
, NULL
, "iPerf2 UDP Header");
689 proto_tree_add_item(udp_tree
, hf_iperf2_sequence
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
692 proto_tree_add_item_ret_uint(udp_tree
, hf_iperf2_sec
, tvb
, offset
, 4, ENC_BIG_ENDIAN
, &ts_sec
);
694 unsigned ts_usec
= 0;
695 proto_tree_add_item_ret_uint(udp_tree
, hf_iperf2_usec
, tvb
, offset
, 4, ENC_BIG_ENDIAN
, &ts_usec
);
698 timestamp
.secs
= (time_t)ts_sec
;
699 timestamp
.nsecs
= (int)ts_usec
* 1000;
700 ti
= proto_tree_add_time(udp_tree
, hf_iperf2_timestamp
, tvb
, offset
- 8, 8, ×tamp
);
701 proto_item_set_generated(ti
);
702 proto_tree_add_item(udp_tree
, hf_iperf2_sequence_upper
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
704 ext_header
= tvb_get_uint32(tvb
, offset
, ENC_BIG_ENDIAN
);
706 offset
+= dissect_iperf2_client_header(tvb
, iperf2_tree
, offset
, true);
708 if (tvb_reported_length(tvb
) == offset
) {
711 //Check is Extended header flag is set, if it's not - do no add more subheaders
712 if (!(ext_header
& HEADER_EXTEND
)) {
713 return dissect_iperf2_payload(tvb
, iperf2_tree
, offset
);
716 offset
+= dissect_iperf2_extended_header(tvb
, iperf2_tree
, offset
);
718 offset
+= dissect_iperf2_isoch_payload_header(tvb
, iperf2_tree
, offset
);
720 offset
+= dissect_iperf2_fq_start_time_header(tvb
, iperf2_tree
, offset
);
722 offset
+= dissect_iperf2_isoch_header(tvb
, iperf2_tree
, offset
);
724 if ((tvb_reported_length(tvb
) - offset
) > 0) {
725 return dissect_iperf2_payload(tvb
, iperf2_tree
, offset
);
732 proto_register_iperf2(void)
734 /* Setup list of header fields */
735 static hf_register_info hf
[] = {
736 { &hf_iperf2_sequence
,
737 { "Sequence Number", "iperf2.udp.sequence", FT_INT32
, BASE_DEC
,
738 NULL
, 0, NULL
, HFILL
}
741 { "Start Time (sec)", "iperf2.udp.sec", FT_UINT32
, BASE_DEC
,
742 NULL
, 0, NULL
, HFILL
}
745 { "Start Time (usec)", "iperf2.udp.usec", FT_UINT32
, BASE_DEC
,
746 NULL
, 0, NULL
, HFILL
}
748 { &hf_iperf2_timestamp
,
749 { "Start Time", "iperf2.udp.timestamp", FT_ABSOLUTE_TIME
, ABSOLUTE_TIME_LOCAL
,
750 NULL
, 0, NULL
, HFILL
}
752 { &hf_iperf2_sequence_upper
,
753 { "Upper Sequence Number", "iperf2.udp.sequence_upper", FT_INT32
, BASE_DEC
,
754 NULL
, 0, NULL
, HFILL
}
757 { "Flags", "iperf2.client.flags", FT_UINT32
, BASE_HEX
,
758 NULL
, 0, NULL
, HFILL
}
760 { &hf_iperf2_flag_header_version1
,
761 { "Header Valid", "iperf2.client.flags_version1", FT_BOOLEAN
, 32,
762 NULL
, HEADER_VERSION1
, NULL
, HFILL
}
764 { &hf_iperf2_flag_header_extend
,
765 { "Extended Version", "iperf2.client.flags_extend", FT_BOOLEAN
, 32,
766 NULL
, HEADER_EXTEND
, NULL
, HFILL
}
768 { &hf_iperf2_header_udptests
,
769 { "UDP Tests", "iperf2.client.flags_udp_tests", FT_BOOLEAN
, 32,
770 NULL
, HEADER_UDPTESTS
, NULL
, HFILL
}
772 { &hf_iperf2_header_seqno64b
,
773 { "64 Bit Seq Num", "iperf2.client.flags_seqno64b", FT_BOOLEAN
, 32,
774 NULL
, HEADER_SEQNO64B
, "64-bits sequence numbers are used", HFILL
}
776 { &hf_iperf2_header_version2
,
777 { "Version 2", "iperf2.client.flags_version2", FT_BOOLEAN
, 32,
778 NULL
, HEADER_VERSION2
, NULL
, HFILL
}
780 { &hf_iperf2_header_v2peerdetect
,
781 { "Version 2 Peer Detect", "iperf2.client.flags_version2_peerdetect", FT_BOOLEAN
, 32,
782 NULL
, HEADER_V2PEERDETECT
, NULL
, HFILL
}
784 { &hf_iperf2_header_udpavoid
,
785 { "Don't use for UDP", "iperf2.client.flags_udpavoid", FT_BOOLEAN
, 32,
786 NULL
, HEADER_UDPAVOID1
, "Don't use these bits for UDP", HFILL
}
788 { &hf_iperf2_header_bounceback
,
789 { "Bounceback", "iperf2.client.flags_bounceback", FT_BOOLEAN
, 32,
790 NULL
, HEADER_BOUNCEBACK
, NULL
, HFILL
}
792 { &hf_iperf2_header_len_bit
,
793 { "Length Bit", "iperf2.client.flags_len_bit", FT_BOOLEAN
, 32,
794 NULL
, HEADER_LEN_BIT
, NULL
, HFILL
}
796 { &hf_iperf2_header_len_mask
,
797 { "Length Mask", "iperf2.client.flags_len_mask", FT_UINT32
, BASE_HEX
,
798 NULL
, HEADER_LEN_MASK
, NULL
, HFILL
}
800 { &hf_iperf2_run_now
,
801 { "Run Now", "iperf2.client.flags_run_now", FT_BOOLEAN
, 32,
802 NULL
, RUN_NOW
, NULL
, HFILL
}
804 { &hf_iperf2_header16_small_triptimes
,
805 { "Small Triptimes", "iperf2.client.flags_small_triptimes", FT_BOOLEAN
, 32,
806 NULL
, HEADER16_SMALL_TRIPTIMES
, "Don't decode other fields in this packet", HFILL
}
808 { &hf_iperf2_num_threads
,
809 { "Number of Threads", "iperf2.client.numthreads", FT_UINT32
, BASE_DEC
,
810 NULL
, 0, NULL
, HFILL
}
813 { "Port", "iperf2.client.port", FT_UINT32
, BASE_DEC
,
814 NULL
, 0, NULL
, HFILL
}
816 { &hf_iperf2_bufferlen
,
817 { "Buffer Length", "iperf2.client.bufferlen", FT_UINT32
, BASE_DEC
,
818 NULL
, 0, NULL
, HFILL
}
820 { &hf_iperf2_mwinband
,
821 { "Bandwidth", "iperf2.client.bandwidth", FT_UINT32
, BASE_DEC
,
822 NULL
, 0, NULL
, HFILL
}
824 { &hf_iperf2_mamount
,
825 { "Amount (Time or Bytes)", "iperf2.client.num_bytes", FT_INT32
, BASE_DEC
,
826 NULL
, 0, NULL
, HFILL
}
829 { "Type", "iperf2.client.type", FT_UINT32
, BASE_DEC
,
830 NULL
, 0, NULL
, HFILL
}
833 { "Length", "iperf2.client.length", FT_UINT32
, BASE_DEC
,
834 NULL
, 0, NULL
, HFILL
}
836 { &hf_iperf2_up_flags
,
837 { "Upper Flags", "iperf2.client.up_flags", FT_UINT16
, BASE_HEX
,
838 NULL
, 0, NULL
, HFILL
}
840 { &hf_iperf2_upper_header_isoch
,
841 { "Isochronous Header", "iperf2.client.upper_header_isoch", FT_BOOLEAN
, 16,
842 NULL
, HEADER_ISOCH
, NULL
, HFILL
}
844 { &hf_iperf2_upper_header_l2ethpipv6
,
845 { "L2 ETH IPv6", "iperf2.client.upper_header_l2ethpipv6", FT_BOOLEAN
, 16,
846 NULL
, HEADER_L2ETHPIPV6
, NULL
, HFILL
}
848 { &hf_iperf2_upper_header_l2lencheck
,
849 { "L2 Length Check", "iperf2.client.upper_header_l2lencheck", FT_BOOLEAN
, 16,
850 NULL
, HEADER_L2LENCHECK
, NULL
, HFILL
}
852 { &hf_iperf2_upper_header_noudpfin
,
853 { "No UDP Fin", "iperf2.client.upper_header_noudpfin", FT_BOOLEAN
, 16,
854 NULL
, HEADER_NOUDPFIN
, NULL
, HFILL
}
856 { &hf_iperf2_upper_header_triptime
,
857 { "Trip Time", "iperf2.client.upper_header_triptime", FT_BOOLEAN
, 16,
858 NULL
, HEADER_TRIPTIME
, NULL
, HFILL
}
860 { &hf_iperf2_upper_header_unused2
,
861 { "Unused", "iperf2.client.upper_header_unused2", FT_BOOLEAN
, 16,
862 NULL
, HEADER_UNUSED2
, NULL
, HFILL
}
864 { &hf_iperf2_upper_header_isoch_settings
,
865 { "Isochronous Settings", "iperf2.client.upper_header_isoch_settings", FT_BOOLEAN
, 16,
866 NULL
, HEADER_ISOCH_SETTINGS
, NULL
, HFILL
}
868 { &hf_iperf2_upper_header_units_pps
,
869 { "Units PPS", "iperf2.client.upper_header_units_pps", FT_BOOLEAN
, 16,
870 NULL
, HEADER_UNITS_PPS
, NULL
, HFILL
}
872 { &hf_iperf2_upper_header_bwset
,
873 { "Header BW Set", "iperf2.client.upper_header_bwset", FT_BOOLEAN
, 16,
874 NULL
, HEADER_BWSET
, NULL
, HFILL
}
876 { &hf_iperf2_upper_header_fqrateset
,
877 { "Fair Queue Rate Set", "iperf2.client.upper_header_fqrateset", FT_BOOLEAN
, 16,
878 NULL
, HEADER_FQRATESET
, NULL
, HFILL
}
880 { &hf_iperf2_upper_header_reverse
,
881 { "Reverse", "iperf2.client.upper_header_reverse", FT_BOOLEAN
, 16,
882 NULL
, HEADER_REVERSE
, NULL
, HFILL
}
884 { &hf_iperf2_upper_header_fullduplex
,
885 { "Full Duplex", "iperf2.client.upper_header_fullduplex", FT_BOOLEAN
, 16,
886 NULL
, HEADER_FULLDUPLEX
, NULL
, HFILL
}
888 { &hf_iperf2_upper_header_epoch_start
,
889 { "Epoch Start", "iperf2.client.upper_header_epoch_start", FT_BOOLEAN
, 16,
890 NULL
, HEADER_EPOCH_START
, NULL
, HFILL
}
892 { &hf_iperf2_upper_header_periodicburst
,
893 { "Periodic Burst", "iperf2.client.upper_header_periodicburst", FT_BOOLEAN
, 16,
894 NULL
, HEADER_PERIODICBURST
, NULL
, HFILL
}
896 { &hf_iperf2_upper_header_writeprefetch
,
897 { "Write Prefetch", "iperf2.client.upper_header_writeprefetch", FT_BOOLEAN
, 16,
898 NULL
, HEADER_WRITEPREFETCH
, NULL
, HFILL
}
900 { &hf_iperf2_upper_header_tcpquickack
,
901 { "TCP Quick Ack", "iperf2.client.upper_header_tcpquickack", FT_BOOLEAN
, 16,
902 NULL
, HEADER_TCPQUICKACK
, NULL
, HFILL
}
904 { &hf_iperf2_low_flags
,
905 { "Lower Flags", "iperf2.client.low_flags", FT_UINT16
, BASE_HEX
,
906 NULL
, 0, NULL
, HFILL
}
908 { &hf_iperf2_lower_header_cca
,
909 { "CCA", "iperf2.client.lower_header_cca", FT_BOOLEAN
, 16,
910 NULL
, HEADER_CCA
, NULL
, HFILL
}
912 { &hf_iperf2_version_major
,
913 { "Major Version", "iperf2.client.version_major", FT_UINT32
, BASE_CUSTOM
,
914 CF_FUNC(format_version
), 0, NULL
, HFILL
}
916 { &hf_iperf2_version_minor
,
917 { "Minor Version", "iperf2.client.version_minor", FT_UINT32
, BASE_CUSTOM
,
918 CF_FUNC(format_version
), 0, NULL
, HFILL
}
920 { &hf_iperf2_version
,
921 { "Iperf2 Version", "iperf2.client.version", FT_UINT64
, BASE_CUSTOM
,
922 CF_FUNC(format_version_long
), 0, NULL
, HFILL
}
924 { &hf_iperf2_reserved
,
925 { "Reserved", "iperf2.client.reserved", FT_UINT16
, BASE_HEX
,
926 NULL
, 0, NULL
, HFILL
}
929 { "TOS", "iperf2.client.tos", FT_UINT16
, BASE_HEX
,
930 NULL
, 0, NULL
, HFILL
}
933 { "Rate", "iperf2.client.rate", FT_UINT32
, BASE_DEC
,
934 NULL
, 0, NULL
, HFILL
}
936 { &hf_iperf2_rate_units
,
937 { "Rate Units", "iperf2.client.rate_units", FT_UINT32
, BASE_DEC
,
938 NULL
, 0, NULL
, HFILL
}
940 { &hf_iperf2_realtime
,
941 { "TCP Realtime", "iperf2.client.realtime", FT_UINT32
, BASE_DEC
,
942 NULL
, 0, NULL
, HFILL
}
944 { &hf_iperf2_permit_key_len
,
945 { "Permit Key Length", "iperf2.client.permit_key_length", FT_UINT16
, BASE_DEC
,
946 NULL
, 0, NULL
, HFILL
}
948 { &hf_iperf2_permit_key
,
949 { "Permit Key", "iperf2.client.permit_key", FT_STRING
, BASE_NONE
,
950 NULL
, 0, NULL
, HFILL
}
952 { &hf_iperf2_isoch_burst_period
,
953 { "Burst Period", "iperf2.client.isoch_burst_period", FT_UINT32
, BASE_DEC
,
954 NULL
, 0, NULL
, HFILL
}
956 { &hf_iperf2_isoch_start_ts_s
,
957 { "Start Timestamp (s)", "iperf2.client.isoch_start_ts_s", FT_UINT32
, BASE_DEC
,
958 NULL
, 0, NULL
, HFILL
}
960 { &hf_iperf2_isoch_start_ts_us
,
961 { "Start Timestamp (us)", "iperf2.client.isoch_start_ts_us", FT_UINT32
, BASE_DEC
,
962 NULL
, 0, NULL
, HFILL
}
964 { &hf_iperf2_isoch_start_ts
,
965 { "Start Timestamp", "iperf2.client.isoch_start_ts", FT_ABSOLUTE_TIME
, ABSOLUTE_TIME_LOCAL
,
966 NULL
, 0, NULL
, HFILL
}
968 { &hf_iperf2_isoch_prev_frameid
,
969 { "Previous Frame ID", "iperf2.client.isoch_prev_frameid", FT_UINT32
, BASE_DEC
,
970 NULL
, 0, NULL
, HFILL
}
972 { &hf_iperf2_isoch_frameid
,
973 { "Frame ID", "iperf2.client.isoch_frameid", FT_UINT32
, BASE_DEC
,
974 NULL
, 0, NULL
, HFILL
}
976 { &hf_iperf2_isoch_burstsize
,
977 { "Burst Size", "iperf2.client.isoch_burstsize", FT_UINT32
, BASE_DEC
,
978 NULL
, 0, NULL
, HFILL
}
980 { &hf_iperf2_isoch_bytes_remaining
,
981 { "Bytes Remaining", "iperf2.client.isoch_bytes_remaining", FT_UINT32
, BASE_DEC
,
982 NULL
, 0, NULL
, HFILL
}
984 { &hf_iperf2_isoch_reserved
,
985 { "Reserved", "iperf2.client.isoch_reserved", FT_UINT32
, BASE_HEX
,
986 NULL
, 0, NULL
, HFILL
}
988 { &hf_iperf2_reserved2
,
989 { "Reserved", "iperf2.client.reserved2", FT_UINT32
, BASE_HEX
,
990 NULL
, 0, NULL
, HFILL
}
992 { &hf_iperf2_start_tv_sec
,
993 { "Start TV (s)", "iperf2.client.start_tv_sec", FT_UINT32
, BASE_DEC
,
994 NULL
, 0, NULL
, HFILL
}
996 { &hf_iperf2_start_tv_usec
,
997 { "Start TV (us)", "iperf2.client.start_tv_usec", FT_UINT32
, BASE_DEC
,
998 NULL
, 0, NULL
, HFILL
}
1000 { &hf_iperf2_start_tv
,
1001 { "Start TV", "iperf2.client.start_tv", FT_ABSOLUTE_TIME
, ABSOLUTE_TIME_LOCAL
,
1002 NULL
, 0, NULL
, HFILL
}
1004 { &hf_iperf2_fq_ratel
,
1005 { "Fair-Queuing Rate Lower", "iperf2.client.fq_ratel", FT_UINT32
, BASE_DEC
,
1006 NULL
, 0, NULL
, HFILL
}
1008 { &hf_iperf2_fq_rateu
,
1009 { "Fair-Queuing Rate Upper", "iperf2.client.fq_rateu", FT_UINT32
, BASE_DEC
,
1010 NULL
, 0, NULL
, HFILL
}
1013 { "FPS Lower", "iperf2.client.fpsl", FT_UINT32
, BASE_DEC
,
1014 NULL
, 0, NULL
, HFILL
}
1017 { "FPS Upper", "iperf2.client.fpsu", FT_UINT32
, BASE_DEC
,
1018 NULL
, 0, NULL
, HFILL
}
1021 { "Mean Lower", "iperf2.client.meanl", FT_UINT32
, BASE_DEC
,
1022 NULL
, 0, NULL
, HFILL
}
1025 { "Mean Upper", "iperf2.client.meanu", FT_UINT32
, BASE_DEC
,
1026 NULL
, 0, NULL
, HFILL
}
1028 { &hf_iperf2_variancel
,
1029 { "Variance Lower", "iperf2.client.variancel", FT_UINT32
, BASE_DEC
,
1030 NULL
, 0, NULL
, HFILL
}
1032 { &hf_iperf2_varianceu
,
1033 { "Variance Upper", "iperf2.client.varianceu", FT_UINT32
, BASE_DEC
,
1034 NULL
, 0, NULL
, HFILL
}
1036 { &hf_iperf2_burstipgl
,
1037 { "Burst Inter-packet Gap Lower", "iperf2.client.burstipgl", FT_UINT32
, BASE_DEC
,
1038 NULL
, 0, NULL
, HFILL
}
1040 { &hf_iperf2_burstipg
,
1041 { "Burst Inter-packet Gap", "iperf2.client.burstipg", FT_UINT32
, BASE_DEC
,
1042 NULL
, 0, NULL
, HFILL
}
1044 { &hf_iperf2_cca_len
,
1045 { "CCA Length", "iperf2.client.cca_len", FT_UINT16
, BASE_DEC
,
1046 NULL
, 0, NULL
, HFILL
}
1048 { &hf_iperf2_cca_value
,
1049 { "CCA Value", "iperf2.client.cca_value", FT_STRING
, BASE_NONE
,
1050 NULL
, 0, NULL
, HFILL
}
1052 { &hf_iperf2_bb_size
,
1053 { "Bounceback Size", "iperf2.client.bb_size", FT_UINT32
, BASE_DEC
,
1054 NULL
, 0, NULL
, HFILL
}
1057 { "Bounceback ID", "iperf2.client.bb_id", FT_UINT32
, BASE_DEC
,
1058 NULL
, 0, NULL
, HFILL
}
1060 { &hf_iperf2_bb_flags
,
1061 { "Bounceback Flags", "iperf2.client.bb_flags", FT_UINT16
, BASE_HEX
,
1062 NULL
, 0, NULL
, HFILL
}
1064 { &hf_iperf2_header_bbquickack
,
1065 { "Quick Ack", "iperf2.client.bb_flags_quickack", FT_BOOLEAN
, 16,
1066 NULL
, HEADER_BBQUICKACK
, NULL
, HFILL
}
1068 { &hf_iperf2_header_bbclocksynced
,
1069 { "Clock Synced", "iperf2.client.bb_flags_clock_synced", FT_BOOLEAN
, 16,
1070 NULL
, HEADER_BBCLOCKSYNCED
, NULL
, HFILL
}
1072 { &hf_iperf2_header_bbtos
,
1073 { "ToS", "iperf2.client.bb_flags_tos", FT_BOOLEAN
, 16,
1074 NULL
, HEADER_BBTOS
, NULL
, HFILL
}
1076 { &hf_iperf2_header_bbstop
,
1077 { "Stop", "iperf2.client.bb_flags_stop", FT_BOOLEAN
, 16,
1078 NULL
, HEADER_BBSTOP
, NULL
, HFILL
}
1080 { &hf_iperf2_header_bbreplysize
,
1081 { "Reply Size", "iperf2.client.bb_flags_reply_size", FT_BOOLEAN
, 16,
1082 NULL
, HEADER_BBREPLYSIZE
, NULL
, HFILL
}
1084 { &hf_iperf2_bb_tos
,
1085 { "Bounceback ToS", "iperf2.client.bb_tos", FT_UINT16
, BASE_HEX
,
1086 NULL
, 0, NULL
, HFILL
}
1088 { &hf_iperf2_bb_run_time
,
1089 { "Bounceback Run Time", "iperf2.client.bb_run_time", FT_UINT32
, BASE_DEC
,
1090 NULL
, 0, NULL
, HFILL
}
1092 { &hf_iperf2_bb_clienttx_ts_sec
,
1093 { "Client TX Timestamp (s)", "iperf2.client.bb_clienttx_ts_sec", FT_UINT32
, BASE_DEC
,
1094 NULL
, 0, NULL
, HFILL
}
1096 { &hf_iperf2_bb_clienttx_ts_usec
,
1097 { "Client TX Timestamp (us)", "iperf2.client.bb_clienttx_ts_usec", FT_UINT32
, BASE_DEC
,
1098 NULL
, 0, NULL
, HFILL
}
1100 { &hf_iperf2_bb_clienttx_ts
,
1101 { "Client TX Timestamp", "iperf2.client.bb_clienttx_ts", FT_ABSOLUTE_TIME
, ABSOLUTE_TIME_LOCAL
,
1102 NULL
, 0, NULL
, HFILL
}
1104 { &hf_iperf2_bb_serverrx_ts_sec
,
1105 { "Server RX Timestamp (s)", "iperf2.client.bb_serverrx_ts_sec", FT_UINT32
, BASE_DEC
,
1106 NULL
, 0, NULL
, HFILL
}
1108 { &hf_iperf2_bb_serverrx_ts_usec
,
1109 { "Server RX Timestamp (us)", "iperf2.client.bb_serverrx_ts_usec", FT_UINT32
, BASE_DEC
,
1110 NULL
, 0, NULL
, HFILL
}
1112 { &hf_iperf2_bb_serverrx_ts
,
1113 { "Server RX Timestamp", "iperf2.client.bb_serverrx_ts", FT_ABSOLUTE_TIME
, ABSOLUTE_TIME_LOCAL
,
1114 NULL
, 0, NULL
, HFILL
}
1116 { &hf_iperf2_bb_servertx_ts_sec
,
1117 { "Server TX Timestamp (s)", "iperf2.client.bb_servertx_ts_sec", FT_UINT32
, BASE_DEC
,
1118 NULL
, 0, NULL
, HFILL
}
1120 { &hf_iperf2_bb_servertx_ts_usec
,
1121 { "Server TX Timestamp (us)", "iperf2.client.bb_servertx_ts_usec", FT_UINT32
, BASE_DEC
,
1122 NULL
, 0, NULL
, HFILL
}
1124 { &hf_iperf2_bb_servertx_ts
,
1125 { "Server TX Timestamp", "iperf2.client.bb_servertx_ts", FT_ABSOLUTE_TIME
, ABSOLUTE_TIME_LOCAL
,
1126 NULL
, 0, NULL
, HFILL
}
1128 { &hf_iperf2_bb_hold
,
1129 { "Bounceback Hold", "iperf2.client.bb_hold", FT_UINT32
, BASE_DEC
,
1130 NULL
, 0, NULL
, HFILL
}
1132 { &hf_iperf2_bb_rtt
,
1133 { "Bounceback RTT", "iperf2.client.bb_rtt", FT_UINT32
, BASE_DEC
,
1134 NULL
, 0, NULL
, HFILL
}
1136 { &hf_iperf2_bb_read_ts_sec
,
1137 { "Read Timestamp (s)", "iperf2.client.bb_read_ts_sec", FT_UINT32
, BASE_DEC
,
1138 NULL
, 0, NULL
, HFILL
}
1140 { &hf_iperf2_bb_read_ts_usec
,
1141 { "Read Timestamp (us)", "iperf2.client.bb_read_ts_usec", FT_UINT32
, BASE_DEC
,
1142 NULL
, 0, NULL
, HFILL
}
1144 { &hf_iperf2_bb_read_ts
,
1145 { "Read Timestamp", "iperf2.client.bb_read_ts", FT_ABSOLUTE_TIME
, ABSOLUTE_TIME_LOCAL
,
1146 NULL
, 0, NULL
, HFILL
}
1148 { &hf_iperf2_bb_reply_size
,
1149 { "Bounceback Reply Size", "iperf2.client.bb_reply_size", FT_UINT32
, BASE_DEC
,
1150 NULL
, 0, NULL
, HFILL
}
1152 { &hf_iperf2_payload
,
1153 { "Data", "iperf2.client.payload", FT_BYTES
, BASE_NONE
,
1154 NULL
, 0, NULL
, HFILL
}
1158 /* Setup protocol subtree array */
1159 static int *ett
[] = {
1167 &ett_client_upper_flags
,
1168 &ett_client_lower_flags
,
1173 &ett_client_hdr_flags
,
1183 /* Register the protocol name and description */
1184 proto_iperf2
= proto_register_protocol("iPerf2 Packet Data", "iPerf2", "iperf2");
1186 proto_register_field_array(proto_iperf2
, hf
, array_length(hf
));
1187 proto_register_subtree_array(ett
, array_length(ett
));
1189 /* Set up string templates for iperf2 payload */
1190 want
= tvbparse_set_oneof(0, NULL
, NULL
, NULL
,
1191 tvbparse_string(-1,"0123456789",NULL
,NULL
,NULL
),
1192 tvbparse_string(-1,"1234567890",NULL
,NULL
,NULL
),
1193 tvbparse_string(-1,"2345678901",NULL
,NULL
,NULL
),
1194 tvbparse_string(-1,"3456789012",NULL
,NULL
,NULL
),
1195 tvbparse_string(-1,"4567890123",NULL
,NULL
,NULL
),
1196 tvbparse_string(-1,"5678901234",NULL
,NULL
,NULL
),
1197 tvbparse_string(-1,"6789012345",NULL
,NULL
,NULL
),
1198 tvbparse_string(-1,"7890123456",NULL
,NULL
,NULL
),
1199 tvbparse_string(-1,"8901234567",NULL
,NULL
,NULL
),
1200 tvbparse_string(-1,"9012345678",NULL
,NULL
,NULL
),
1202 want_trailing
= tvbparse_chars(-1, 1, 0, "0123456789", NULL
, NULL
, NULL
);
1204 iperf2_handle_tcp
= register_dissector("iperf2_tcp", dissect_iperf2_tcp
, proto_iperf2
);
1205 iperf2_handle_udp
= register_dissector("iperf2_udp", dissect_iperf2_udp
, proto_iperf2
);
1209 proto_reg_handoff_iperf2(void)
1211 dissector_add_for_decode_as_with_preference("tcp.port", iperf2_handle_tcp
);
1212 dissector_add_for_decode_as_with_preference("udp.port", iperf2_handle_udp
);
1216 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1221 * indent-tabs-mode: nil
1224 * vi: set shiftwidth=4 tabstop=8 expandtab:
1225 * :indentSize=4:tabSize=8:noTabs=true: