1: /*
2: * iperf, Copyright (c) 2014-2020, The Regents of the University of
3: * California, through Lawrence Berkeley National Laboratory (subject
4: * to receipt of any required approvals from the U.S. Dept. of
5: * Energy). All rights reserved.
6: *
7: * If you have questions about your rights to use or distribute this
8: * software, please contact Berkeley Lab's Technology Transfer
9: * Department at TTD@lbl.gov.
10: *
11: * NOTICE. This software is owned by the U.S. Department of Energy.
12: * As such, the U.S. Government has been granted for itself and others
13: * acting on its behalf a paid-up, nonexclusive, irrevocable,
14: * worldwide license in the Software to reproduce, prepare derivative
15: * works, and perform publicly and display publicly. Beginning five
16: * (5) years after the date permission to assert copyright is obtained
17: * from the U.S. Department of Energy, and subject to any subsequent
18: * five (5) year renewals, the U.S. Government is granted for itself
19: * and others acting on its behalf a paid-up, nonexclusive,
20: * irrevocable, worldwide license in the Software to reproduce,
21: * prepare derivative works, distribute copies to the public, perform
22: * publicly and display publicly, and to permit others to do so.
23: *
24: * This code is distributed under a BSD style license, see the LICENSE
25: * file for complete information.
26: */
27: #ifndef __IPERF_H
28: #define __IPERF_H
29:
30: #include "iperf_config.h"
31:
32: #include <sys/time.h>
33: #include <sys/types.h>
34: #ifdef HAVE_STDINT_H
35: #include <stdint.h>
36: #endif
37: #include <sys/select.h>
38: #include <sys/socket.h>
39: #ifndef _GNU_SOURCE
40: # define _GNU_SOURCE
41: #endif
42: #ifdef HAVE_LINUX_TCP_H
43: #include <linux/tcp.h>
44: #else
45: #include <netinet/tcp.h>
46: #endif
47: #include <net/if.h> // for IFNAMSIZ
48:
49: #if defined(HAVE_CPUSET_SETAFFINITY)
50: #include <sys/param.h>
51: #include <sys/cpuset.h>
52: #endif /* HAVE_CPUSET_SETAFFINITY */
53:
54: #if defined(HAVE_INTTYPES_H)
55: # include <inttypes.h>
56: #else
57: # ifndef PRIu64
58: # if sizeof(long) == 8
59: # define PRIu64 "lu"
60: # else
61: # define PRIu64 "llu"
62: # endif
63: # endif
64: #endif
65:
66: #include "timer.h"
67: #include "queue.h"
68: #include "cjson.h"
69: #include "iperf_time.h"
70:
71: #if defined(HAVE_SSL)
72: #include <openssl/bio.h>
73: #include <openssl/evp.h>
74: #endif // HAVE_SSL
75:
76: #if !defined(__IPERF_API_H)
77: typedef uint64_t iperf_size_t;
78: #endif // __IPERF_API_H
79:
80: struct iperf_interval_results
81: {
82: iperf_size_t bytes_transferred; /* bytes transferred in this interval */
83: struct iperf_time interval_start_time;
84: struct iperf_time interval_end_time;
85: float interval_duration;
86:
87: /* for UDP */
88: int64_t interval_packet_count;
89: int64_t interval_outoforder_packets;
90: int64_t interval_cnt_error;
91: int64_t packet_count;
92: double jitter;
93: int64_t outoforder_packets;
94: int64_t cnt_error;
95:
96: int omitted;
97: #if (defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)) && \
98: defined(TCP_INFO)
99: struct tcp_info tcpInfo; /* getsockopt(TCP_INFO) for Linux, {Free,Net,Open}BSD */
100: #else
101: /* Just placeholders, never accessed. */
102: char *tcpInfo;
103: #endif
104: long interval_retrans;
105: long snd_cwnd;
106: long snd_wnd;
107: TAILQ_ENTRY(iperf_interval_results) irlistentries;
108: void *custom_data;
109: long rtt;
110: long rttvar;
111: long pmtu;
112: };
113:
114: struct iperf_stream_result
115: {
116: iperf_size_t bytes_received;
117: iperf_size_t bytes_sent;
118: iperf_size_t bytes_received_this_interval;
119: iperf_size_t bytes_sent_this_interval;
120: iperf_size_t bytes_sent_omit;
121: long stream_prev_total_retrans;
122: long stream_retrans;
123: long stream_max_rtt;
124: long stream_min_rtt;
125: long stream_sum_rtt;
126: int stream_count_rtt;
127: long stream_max_snd_cwnd;
128: long stream_max_snd_wnd;
129: struct iperf_time start_time;
130: struct iperf_time end_time;
131: struct iperf_time start_time_fixed;
132: double sender_time;
133: double receiver_time;
134: TAILQ_HEAD(irlisthead, iperf_interval_results) interval_results;
135: void *data;
136: };
137:
138: #define COOKIE_SIZE 37 /* size of an ascii uuid */
139: struct iperf_settings
140: {
141: int domain; /* AF_INET or AF_INET6 */
142: int socket_bufsize; /* window size for TCP */
143: int blksize; /* size of read/writes (-l) */
144: iperf_size_t rate; /* target data rate for application pacing*/
145: iperf_size_t bitrate_limit; /* server's maximum allowed total data rate for all streams*/
146: double bitrate_limit_interval; /* interval for averaging total data rate */
147: int bitrate_limit_stats_per_interval; /* calculated number of stats periods for averaging total data rate */
148: uint64_t fqrate; /* target data rate for FQ pacing*/
149: int pacing_timer; /* pacing timer in microseconds */
150: int burst; /* packets per burst */
151: int mss; /* for TCP MSS */
152: int ttl; /* IP TTL option */
153: int tos; /* type of service bit */
154: int flowlabel; /* IPv6 flow label */
155: iperf_size_t bytes; /* number of bytes to send */
156: iperf_size_t blocks; /* number of blocks (packets) to send */
157: char unit_format; /* -f */
158: int num_ostreams; /* SCTP initmsg settings */
159: int dont_fragment; /* Whether to set IP flag Do-Not_Fragment */
160: #if defined(HAVE_SSL)
161: char *authtoken; /* Authentication token */
162: char *client_username;
163: char *client_password;
164: EVP_PKEY *client_rsa_pubkey;
165: #endif // HAVE_SSL
166: int connect_timeout; /* socket connection timeout, in ms */
167: int idle_timeout; /* server idle time timeout */
168: unsigned int snd_timeout; /* Timeout for sending tcp messages in active mode, in us */
169: struct iperf_time rcv_timeout; /* Timeout for receiving messages in active mode, in us */
170: };
171:
172: struct iperf_test;
173:
174: struct iperf_stream
175: {
176: struct iperf_test* test;
177:
178: /* configurable members */
179: int local_port;
180: int remote_port;
181: int socket;
182: int id;
183: int sender;
184: /* XXX: is settings just a pointer to the same struct in iperf_test? if not,
185: should it be? */
186: struct iperf_settings *settings; /* pointer to structure settings */
187:
188: /* non configurable members */
189: struct iperf_stream_result *result; /* structure pointer to result */
190: Timer *send_timer;
191: int green_light;
192: int buffer_fd; /* data to send, file descriptor */
193: char *buffer; /* data to send, mmapped */
194: int pending_size; /* pending data to send */
195: int diskfile_fd; /* file to send, file descriptor */
196: int diskfile_left; /* remaining file data on disk */
197:
198: /*
199: * for udp measurements - This can be a structure outside stream, and
200: * stream can have a pointer to this
201: */
202: int64_t packet_count;
203: int64_t peer_packet_count;
204: int64_t peer_omitted_packet_count;
205: int64_t omitted_packet_count;
206: double jitter;
207: double prev_transit;
208: int64_t outoforder_packets;
209: int64_t omitted_outoforder_packets;
210: int64_t cnt_error;
211: int64_t omitted_cnt_error;
212: uint64_t target;
213:
214: struct sockaddr_storage local_addr;
215: struct sockaddr_storage remote_addr;
216:
217: int (*rcv) (struct iperf_stream * stream);
218: int (*snd) (struct iperf_stream * stream);
219:
220: /* chained send/receive routines for -F mode */
221: int (*rcv2) (struct iperf_stream * stream);
222: int (*snd2) (struct iperf_stream * stream);
223:
224: // struct iperf_stream *next;
225: SLIST_ENTRY(iperf_stream) streams;
226:
227: void *data;
228: };
229:
230: struct protocol {
231: int id;
232: char *name;
233: int (*accept)(struct iperf_test *);
234: int (*listen)(struct iperf_test *);
235: int (*connect)(struct iperf_test *);
236: int (*send)(struct iperf_stream *);
237: int (*recv)(struct iperf_stream *);
238: int (*init)(struct iperf_test *);
239: SLIST_ENTRY(protocol) protocols;
240: };
241:
242: struct iperf_textline {
243: char *line;
244: TAILQ_ENTRY(iperf_textline) textlineentries;
245: };
246:
247: struct xbind_entry {
248: char *name;
249: struct addrinfo *ai;
250: TAILQ_ENTRY(xbind_entry) link;
251: };
252:
253: enum iperf_mode {
254: SENDER = 1,
255: RECEIVER = 0,
256: BIDIRECTIONAL = -1
257: };
258:
259: enum debug_level {
260: DEBUG_LEVEL_ERROR = 1,
261: DEBUG_LEVEL_WARN = 2,
262: DEBUG_LEVEL_INFO = 3,
263: DEBUG_LEVEL_DEBUG = 4,
264: DEBUG_LEVEL_MAX = 4
265: };
266:
267:
268: struct iperf_test
269: {
270: char role; /* 'c' lient or 's' erver */
271: enum iperf_mode mode;
272: int sender_has_retransmits;
273: int other_side_has_retransmits; /* used if mode == BIDIRECTIONAL */
274: struct protocol *protocol;
275: signed char state;
276: char *server_hostname; /* -c option */
277: char *tmp_template;
278: char *bind_address; /* first -B option */
279: char *bind_dev; /* bind to network device */
280: TAILQ_HEAD(xbind_addrhead, xbind_entry) xbind_addrs; /* all -X opts */
281: int bind_port; /* --cport option */
282: int server_port;
283: int omit; /* duration of omit period (-O flag) */
284: int duration; /* total duration of test (-t flag) */
285: char *diskfile_name; /* -F option */
286: int affinity, server_affinity; /* -A option */
287: #if defined(HAVE_CPUSET_SETAFFINITY)
288: cpuset_t cpumask;
289: #endif /* HAVE_CPUSET_SETAFFINITY */
290: char *title; /* -T option */
291: char *extra_data; /* --extra-data */
292: char *congestion; /* -C option */
293: char *congestion_used; /* what was actually used */
294: char *remote_congestion_used; /* what the other side used */
295: char *pidfile; /* -P option */
296:
297: char *logfile; /* --logfile option */
298: FILE *outfile;
299:
300: int ctrl_sck;
301: int mapped_v4;
302: int listener;
303: int prot_listener;
304:
305: int ctrl_sck_mss; /* MSS for the control channel */
306:
307: #if defined(HAVE_SSL)
308: char *server_authorized_users;
309: EVP_PKEY *server_rsa_private_key;
310: int server_skew_threshold;
311: #endif // HAVE_SSL
312:
313: /* boolean variables for Options */
314: int daemon; /* -D option */
315: int one_off; /* -1 option */
316: int no_delay; /* -N option */
317: int reverse; /* -R option */
318: int bidirectional; /* --bidirectional */
319: int verbose; /* -V option - verbose mode */
320: int json_output; /* -J option - JSON output */
321: int zerocopy; /* -Z option - use sendfile */
322: int debug; /* -d option - enable debug */
323: enum debug_level debug_level; /* -d option option - level of debug messages to show */
324: int get_server_output; /* --get-server-output */
325: int udp_counters_64bit; /* --use-64-bit-udp-counters */
326: int forceflush; /* --forceflush - flushing output at every interval */
327: int multisend;
328: int repeating_payload; /* --repeating-payload */
329: int timestamps; /* --timestamps */
330: char *timestamp_format;
331:
332: char *json_output_string; /* rendered JSON output if json_output is set */
333: /* Select related parameters */
334: int max_fd;
335: fd_set read_set; /* set of read sockets */
336: fd_set write_set; /* set of write sockets */
337:
338: /* Interval related members */
339: int omitting;
340: double stats_interval;
341: double reporter_interval;
342: void (*stats_callback) (struct iperf_test *);
343: void (*reporter_callback) (struct iperf_test *);
344: Timer *omit_timer;
345: Timer *timer;
346: int done;
347: Timer *stats_timer;
348: Timer *reporter_timer;
349:
350: double cpu_util[3]; /* cpu utilization of the test - total, user, system */
351: double remote_cpu_util[3]; /* cpu utilization for the remote host/client - total, user, system */
352:
353: int num_streams; /* total streams in the test (-P) */
354:
355: iperf_size_t bytes_sent;
356: iperf_size_t blocks_sent;
357:
358: iperf_size_t bytes_received;
359: iperf_size_t blocks_received;
360:
361: iperf_size_t bitrate_limit_stats_count; /* Number of stats periods accumulated for server's total bitrate average */
362: iperf_size_t *bitrate_limit_intervals_traffic_bytes; /* Pointer to a cyclic array that includes the last interval's bytes transferred */
363: iperf_size_t bitrate_limit_last_interval_index; /* Index of the last interval traffic inserted into the cyclic array */
364: int bitrate_limit_exceeded; /* Set by callback routine when average data rate exceeded the server's bitrate limit */
365:
366: int server_last_run_rc; /* Save last server run rc for next test */
367: uint server_forced_idle_restarts_count; /* count number of forced server restarts to make sure it is not stack */
368: uint server_forced_no_msg_restarts_count; /* count number of forced server restarts to make sure it is not stack */
369: uint server_test_number; /* count number of tests performed by a server */
370:
371: char cookie[COOKIE_SIZE];
372: // struct iperf_stream *streams; /* pointer to list of struct stream */
373: SLIST_HEAD(slisthead, iperf_stream) streams;
374: struct iperf_settings *settings;
375:
376: SLIST_HEAD(plisthead, protocol) protocols;
377:
378: /* callback functions */
379: void (*on_new_stream)(struct iperf_stream *);
380: void (*on_test_start)(struct iperf_test *);
381: void (*on_connect)(struct iperf_test *);
382: void (*on_test_finish)(struct iperf_test *);
383:
384: /* cJSON handles for use when in -J mode */\
385: cJSON *json_top;
386: cJSON *json_start;
387: cJSON *json_connected;
388: cJSON *json_intervals;
389: cJSON *json_end;
390:
391: /* Server output (use on client side only) */
392: char *server_output_text;
393: cJSON *json_server_output;
394:
395: /* Server output (use on server side only) */
396: TAILQ_HEAD(iperf_textlisthead, iperf_textline) server_output_list;
397:
398: };
399:
400: /* default settings */
401: #define PORT 5201 /* default port to listen on (don't use the same port as iperf2) */
402: #define uS_TO_NS 1000
403: #define mS_TO_US 1000
404: #define SEC_TO_mS 1000
405: #define SEC_TO_US 1000000LL
406: #define UDP_RATE (1024 * 1024) /* 1 Mbps */
407: #define OMIT 0 /* seconds */
408: #define DURATION 10 /* seconds */
409:
410: #define SEC_TO_NS 1000000000LL /* too big for enum/const on some platforms */
411: #define MAX_RESULT_STRING 4096
412:
413: #define UDP_BUFFER_EXTRA 1024
414:
415: /* constants for command line arg sanity checks */
416: #define MB (1024 * 1024)
417: #define MAX_TCP_BUFFER (512 * MB)
418: #define MAX_BLOCKSIZE MB
419: /* Minimum size UDP send is the size of two 32-bit ints followed by a 64-bit int */
420: #define MIN_UDP_BLOCKSIZE (4 + 4 + 8)
421: /* Maximum size UDP send is (64K - 1) - IP and UDP header sizes */
422: #define MAX_UDP_BLOCKSIZE (65535 - 8 - 20)
423: #define MIN_INTERVAL 0.1
424: #define MAX_INTERVAL 60.0
425: #define MAX_TIME 86400
426: #define MAX_BURST 1000
427: #define MAX_MSS (9 * 1024)
428: #define MAX_STREAMS 128
429:
430: #define TIMESTAMP_FORMAT "%c "
431:
432: extern int gerror; /* error value from getaddrinfo(3), for use in internal error handling */
433:
434: /* UDP "connect" message and reply (textual value for Wireshark, etc. readability - legacy was numeric) */
435: #define UDP_CONNECT_MSG 0x36373839 // "6789" - legacy value was 123456789
436: #define UDP_CONNECT_REPLY 0x39383736 // "9876" - legacy value was 987654321
437: #define LEGACY_UDP_CONNECT_REPLY 987654321 // Old servers may still reply with the legacy value
438:
439: /* In Reverse mode, maximum number of packets to wait for "accept" response - to handle out of order packets */
440: #define MAX_REVERSE_OUT_OF_ORDER_PACKETS 2
441:
442: #endif /* !__IPERF_H */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>