#ifndef __IPERF_H
#define __IPERF_H
#include "iperf_config.h"
#include <sys/time.h>
#include <sys/types.h>
#include <stdint.h>
#include <inttypes.h>
#include <sys/select.h>
#include <sys/socket.h>
#ifndef _GNU_SOURCE
# define _GNU_SOURCE
#endif
#ifdef HAVE_LINUX_TCP_H
#include <linux/tcp.h>
#else
#include <netinet/tcp.h>
#endif
#include <net/if.h>
#if defined(HAVE_CPUSET_SETAFFINITY)
#include <sys/param.h>
#include <sys/cpuset.h>
#endif
#include "timer.h"
#include "queue.h"
#include "cjson.h"
#include "iperf_time.h"
#include "portable_endian.h"
#if defined(HAVE_SSL)
#include <openssl/bio.h>
#include <openssl/evp.h>
#endif
#include "iperf_pthread.h"
#ifdef HAVE_STDATOMIC_H
#include <stdatomic.h>
#else
#warning "No <stdatomic.h> available."
typedef uint64_t atomic_uint_fast64_t;
#endif
#if !defined(__IPERF_API_H)
typedef uint_fast64_t iperf_size_t;
typedef atomic_uint_fast64_t atomic_iperf_size_t;
#endif
#if (defined(__vxworks)) || (defined(__VXWORKS__))
typedef unsigned int uint
#endif
struct iperf_sctp_info
{
long rtt;
long pmtu;
uint32_t wnd;
uint32_t cwnd;
};
struct iperf_interval_results
{
atomic_iperf_size_t bytes_transferred;
struct iperf_time interval_start_time;
struct iperf_time interval_end_time;
float interval_duration;
int64_t interval_packet_count;
int64_t interval_outoforder_packets;
int64_t interval_cnt_error;
int64_t packet_count;
double jitter;
int64_t outoforder_packets;
int64_t cnt_error;
int omitted;
#if (defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)) && \
defined(TCP_INFO)
struct tcp_info tcpInfo;
#elif (defined(__APPLE__) && defined(__MACH__)) && defined(TCP_CONNECTION_INFO)
struct tcp_connection_info tcpConnInfo;
#else
char *tcpInfo;
#endif
#if defined(HAVE_SCTP_H)
struct iperf_sctp_info sctp_info;
#endif
long interval_retrans;
long snd_cwnd;
long snd_wnd;
TAILQ_ENTRY(iperf_interval_results) irlistentries;
void *custom_data;
long rtt;
long rttvar;
long pmtu;
long reorder;
};
struct iperf_stream_result
{
atomic_iperf_size_t bytes_received;
atomic_iperf_size_t bytes_sent;
atomic_iperf_size_t bytes_received_this_interval;
atomic_iperf_size_t bytes_sent_this_interval;
atomic_iperf_size_t bytes_sent_omit;
long stream_prev_total_retrans;
long stream_retrans;
long stream_reorder;
long stream_max_rtt;
long stream_min_rtt;
long stream_sum_rtt;
int stream_count_rtt;
long stream_max_snd_cwnd;
long stream_max_snd_wnd;
struct iperf_time start_time;
struct iperf_time end_time;
struct iperf_time start_time_fixed;
double sender_time;
double receiver_time;
TAILQ_HEAD(irlisthead, iperf_interval_results) interval_results;
void *data;
};
#define COOKIE_SIZE 37
struct iperf_settings
{
int domain;
int socket_bufsize;
int blksize;
iperf_size_t rate;
iperf_size_t bitrate_limit;
double bitrate_limit_interval;
int bitrate_limit_stats_per_interval;
uint64_t fqrate;
int pacing_timer;
int burst;
int mss;
int ttl;
int tos;
int flowlabel;
iperf_size_t bytes;
iperf_size_t blocks;
char unit_format;
int num_ostreams;
int dont_fragment;
#if defined(HAVE_SSL)
char *authtoken;
char *client_username;
char *client_password;
EVP_PKEY *client_rsa_pubkey;
#endif int skip_rx_copy;
int connect_timeout;
int idle_timeout;
unsigned int snd_timeout;
struct iperf_time rcv_timeout;
int cntl_ka;
int cntl_ka_keepidle;
int cntl_ka_interval;
int cntl_ka_count;
int gso;
int gso_dg_size;
int gso_bf_size;
int gro;
int gro_bf_size;
};
struct iperf_test;
struct iperf_stream
{
struct iperf_test* test;
pthread_t thr;
int thread_created;
int done;
int local_port;
int remote_port;
int socket;
int id;
int sender;
struct iperf_settings *settings;
struct iperf_stream_result *result;
Timer *send_timer;
int green_light;
int buffer_fd;
char *buffer;
int pending_size;
int diskfile_fd;
int diskfile_left;
int64_t packet_count;
int64_t peer_packet_count;
int64_t peer_omitted_packet_count;
int64_t omitted_packet_count;
double jitter;
double prev_transit;
int64_t outoforder_packets;
int64_t omitted_outoforder_packets;
int64_t cnt_error;
int64_t omitted_cnt_error;
uint64_t target;
struct sockaddr_storage local_addr;
struct sockaddr_storage remote_addr;
int (*rcv) (struct iperf_stream * stream);
int (*snd) (struct iperf_stream * stream);
int (*rcv2) (struct iperf_stream * stream);
int (*snd2) (struct iperf_stream * stream);
SLIST_ENTRY(iperf_stream) streams;
void *data;
};
struct protocol {
int id;
char *name;
int (*accept)(struct iperf_test *);
int (*listen)(struct iperf_test *);
int (*connect)(struct iperf_test *);
int (*send)(struct iperf_stream *);
int (*recv)(struct iperf_stream *);
int (*init)(struct iperf_test *);
SLIST_ENTRY(protocol) protocols;
};
struct iperf_textline {
char *line;
TAILQ_ENTRY(iperf_textline) textlineentries;
};
struct xbind_entry {
char *name;
struct addrinfo *ai;
TAILQ_ENTRY(xbind_entry) link;
};
enum iperf_mode {
SENDER = 1,
RECEIVER = 0,
BIDIRECTIONAL = -1
};
enum debug_level {
DEBUG_LEVEL_ERROR = 1,
DEBUG_LEVEL_WARN = 2,
DEBUG_LEVEL_INFO = 3,
DEBUG_LEVEL_DEBUG = 4,
DEBUG_LEVEL_MAX = 4
};
struct iperf_test
{
pthread_mutex_t print_mutex;
char role;
enum iperf_mode mode;
int sender_has_retransmits;
int other_side_has_retransmits;
struct protocol *protocol;
signed char state;
char *server_hostname;
char *tmp_template;
char *bind_address;
char *bind_dev;
TAILQ_HEAD(xbind_addrhead, xbind_entry) xbind_addrs;
int bind_port;
int server_port;
int omit;
int duration;
int max_server_duration;
char *diskfile_name;
int affinity, server_affinity;
#if defined(HAVE_CPUSET_SETAFFINITY)
cpuset_t cpumask;
#endif
char *title;
char *extra_data;
char *congestion;
char *congestion_used;
char *remote_congestion_used;
char *pidfile;
char *logfile;
FILE *outfile;
int ctrl_sck;
int mapped_v4;
int listener;
int prot_listener;
int ctrl_sck_mss;
#if defined(HAVE_SSL)
char *server_authorized_users;
EVP_PKEY *server_rsa_private_key;
int server_skew_threshold;
int use_pkcs1_padding;
#endif
int daemon;
int one_off;
int no_delay;
int reverse;
int bidirectional;
int verbose;
int json_output;
int json_stream;
int json_stream_full_output;
void (*json_callback) (struct iperf_test *, char *);
int zerocopy;
int debug;
enum debug_level debug_level;
int get_server_output;
int udp_counters_64bit;
int forceflush;
int multisend;
int repeating_payload;
int timestamps;
char *timestamp_format;
int mptcp;
char *json_output_string;
int max_fd;
fd_set read_set;
fd_set write_set;
int omitting;
double stats_interval;
double reporter_interval;
void (*stats_callback) (struct iperf_test *);
void (*reporter_callback) (struct iperf_test *);
Timer *omit_timer;
Timer *timer;
int done;
Timer *stats_timer;
Timer *reporter_timer;
double cpu_util[3];
double remote_cpu_util[3];
int num_streams;
atomic_iperf_size_t bytes_sent;
atomic_iperf_size_t blocks_sent;
atomic_iperf_size_t bytes_received;
atomic_iperf_size_t blocks_received;
iperf_size_t bitrate_limit_stats_count;
iperf_size_t *bitrate_limit_intervals_traffic_bytes;
iperf_size_t bitrate_limit_last_interval_index;
int bitrate_limit_exceeded;
int server_last_run_rc;
uint server_forced_idle_restarts_count;
uint server_forced_no_msg_restarts_count;
uint server_test_number;
char cookie[COOKIE_SIZE];
SLIST_HEAD(slisthead, iperf_stream) streams;
struct iperf_settings *settings;
SLIST_HEAD(plisthead, protocol) protocols;
void (*on_new_stream)(struct iperf_stream *);
void (*on_test_start)(struct iperf_test *);
void (*on_connect)(struct iperf_test *);
void (*on_test_finish)(struct iperf_test *);
\
cJSON *json_top;
cJSON *json_start;
cJSON *json_connected;
cJSON *json_intervals;
cJSON *json_end;
char *server_output_text;
cJSON *json_server_output;
TAILQ_HEAD(iperf_textlisthead, iperf_textline) server_output_list;
};
#define PORT 5201
#define uS_TO_NS 1000
#define mS_TO_US 1000
#define SEC_TO_mS 1000
#define SEC_TO_US 1000000LL
#define UDP_RATE (1024 * 1024)
#define OMIT 0
#define DURATION 10
#define SEC_TO_NS 1000000000LL
#define MAX_RESULT_STRING 4096
#define UDP_BUFFER_EXTRA 1024
#define MAX_PARAMS_JSON_STRING 8 * 1024
#define MB (1024 * 1024)
#define MAX_TCP_BUFFER (512 * MB)
#define MAX_BLOCKSIZE MB
#define MIN_UDP_BLOCKSIZE (4 + 4 + 8)
#define MAX_UDP_BLOCKSIZE (65535 - 8 - 20)
#define MIN_INTERVAL 0.1
#define MAX_INTERVAL 60.0
#define MAX_TIME 86400
#define MAX_OMIT_TIME 600
#define MAX_BURST 1000
#define MAX_MSS (32 * 1024 - 1)
#define MAX_STREAMS 128
#define TIMESTAMP_FORMAT "%c "
extern int gerror;
#if BYTE_ORDER == BIG_ENDIAN
#define UDP_CONNECT_MSG 0x39383736
#define UDP_CONNECT_REPLY 0x36373839
#define LEGACY_UDP_CONNECT_REPLY 0xb168de3a
#else
#define UDP_CONNECT_MSG 0x36373839
#define UDP_CONNECT_REPLY 0x39383736
#define LEGACY_UDP_CONNECT_REPLY 987654321
#endif
#define MAX_REVERSE_OUT_OF_ORDER_PACKETS 2
#define GSO_BF_MAX_SIZE MAX_UDP_BLOCKSIZE
#define GRO_BF_MAX_SIZE MAX_UDP_BLOCKSIZE
#endif