12 #define NETPERF_CMD "netperf"
13 #define NETPERF_PATH "/usr/local/bin/" NETPERF_CMD
16 #define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var))
19 struct netperf_child
{
24 usage(const char *cmd
)
26 fprintf(stderr
, "%s -H host [-l len_s] [-i instances] [-m msgsz] "
27 "[-S sockbuf] [-r|-s]\n", cmd
);
32 main(int argc
, char *argv
[])
34 struct netperf_child
*instance
;
37 const char *host
, *msgsz
, *sockbuf
;
38 volatile int ninst
, set_minmax
= 0;
41 volatile int reverse
= 0, sfile
= 0;
42 double result
, res_max
, res_min
, jain
;
50 while ((opt
= getopt(argc
, argv
, "H:S:i:l:m:rs")) != -1) {
61 ninst
= strtoul(optarg
, NULL
, 10);
65 len
= strtoul(optarg
, NULL
, 10);
86 if (ninst
<= 0 || host
== NULL
|| len
<= 0)
89 snprintf(len_str
, sizeof(len_str
), "%d", len
);
92 args
[i
++] = __DECONST(char *, NETPERF_CMD
);
93 args
[i
++] = __DECONST(char *, "-P0");
94 args
[i
++] = __DECONST(char *, "-H");
95 args
[i
++] = __DECONST(char *, host
);
96 args
[i
++] = __DECONST(char *, "-l");
97 args
[i
++] = __DECONST(char *, len_str
);
98 args
[i
++] = __DECONST(char *, "-t");
100 args
[i
++] = __DECONST(char *, "TCP_MAERTS");
102 args
[i
++] = __DECONST(char *, "TCP_SENDFILE");
104 args
[i
++] = __DECONST(char *, "TCP_STREAM");
105 if (msgsz
!= NULL
|| sockbuf
!= NULL
) {
106 args
[i
++] = __DECONST(char *, "--");
108 args
[i
++] = __DECONST(char *, "-m");
109 args
[i
++] = __DECONST(char *, msgsz
);
111 if (sockbuf
!= NULL
) {
114 snprintf(buf_str
, sizeof(buf_str
), "%s,%s",
116 args
[i
++] = __DECONST(char *, "-s");
117 args
[i
++] = __DECONST(char *, buf_str
);
118 args
[i
++] = __DECONST(char *, "-S");
119 args
[i
++] = __DECONST(char *, buf_str
);
124 instance
= calloc(ninst
, sizeof(struct netperf_child
));
125 if (instance
== NULL
)
126 err(1, "calloc failed");
128 null_fd
= open("/dev/null", O_RDWR
);
130 err(1, "open null failed");
132 for (i
= 0; i
< ninst
; ++i
) {
133 if (pipe(instance
[i
].pipes
) < 0)
134 err(1, "pipe %dth failed", i
);
137 for (i
= 0; i
< ninst
; ++i
) {
144 dup2(instance
[i
].pipes
[1], STDOUT_FILENO
);
145 dup2(null_fd
, STDERR_FILENO
);
146 ret
= execv(NETPERF_PATH
, args
);
148 warn("execv %d failed", i
);
153 } else if (pid
< 0) {
154 err(1, "vfork %d failed", i
);
156 close(instance
[i
].pipes
[1]);
157 instance
[i
].pipes
[1] = -1;
161 while (ninst_done
< ninst
) {
164 pid
= waitpid(-1, NULL
, 0);
166 err(1, "waitpid failed");
174 for (i
= 0; i
< ninst
; ++i
) {
178 fp
= fdopen(instance
[i
].pipes
[0], "r");
180 err(1, "fdopen %dth failed", i
);
182 while (fgets(line
, sizeof(line
), fp
) != NULL
) {
183 int n
, arg1
, arg2
, arg3
;
186 n
= sscanf(line
, "%d%d%d%lf%lf",
187 &arg1
, &arg2
, &arg3
, &arg4
, &res
);
208 jain
= (result
* result
) / jain
;
210 printf("%s %.2f Mbps\n", reverse
? "TCP_MAERTS" : "TCP_STREAM", result
);
211 printf("min/max (jain) %.2f Mbps/%.2f Mbps (%f)\n",
212 res_min
, res_max
, jain
);