1 #include <sys/types.h> 2 #include <sys/stat.h> 3 #include <sys/wait.h> 4 5 #include <err.h> 6 #include <fcntl.h> 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <unistd.h> 10 11 #define NETPERF_CMD "netperf" 12 #define NETPERF_PATH "/usr/local/bin/" NETPERF_CMD 13 14 struct netperf_child { 15 int pipes[2]; 16 }; 17 18 static void 19 usage(const char *cmd) 20 { 21 fprintf(stderr, "%s -H host [-l len_s] [-i instances]\n", cmd); 22 exit(1); 23 } 24 25 int 26 main(int argc, char *argv[]) 27 { 28 struct netperf_child *instance; 29 char len_str[32]; 30 char *args[32]; 31 const char *host; 32 volatile int ninst; 33 int len, ninst_done; 34 int opt, i, null_fd; 35 double result; 36 37 host = NULL; 38 ninst = 2; 39 len = 10; 40 41 while ((opt = getopt(argc, argv, "i:H:l:")) != -1) { 42 switch (opt) { 43 case 'i': 44 ninst = strtoul(optarg, NULL, 10); 45 break; 46 47 case 'H': 48 host = optarg; 49 break; 50 51 case 'l': 52 len = strtoul(optarg, NULL, 10); 53 break; 54 55 default: 56 usage(argv[0]); 57 } 58 } 59 if (ninst <= 0 || host == NULL || len <= 0) 60 usage(argv[0]); 61 62 snprintf(len_str, sizeof(len_str), "%d", len); 63 64 i = 0; 65 args[i++] = __DECONST(char *, NETPERF_CMD); 66 args[i++] = __DECONST(char *, "-P0"); 67 args[i++] = __DECONST(char *, "-H"); 68 args[i++] = __DECONST(char *, host); 69 args[i++] = __DECONST(char *, "-l"); 70 args[i++] = __DECONST(char *, len_str); 71 args[i++] = __DECONST(char *, "-t"); 72 args[i++] = __DECONST(char *, "TCP_CC"); 73 args[i] = NULL; 74 75 instance = calloc(ninst, sizeof(struct netperf_child)); 76 if (instance == NULL) 77 err(1, "calloc failed"); 78 79 null_fd = open("/dev/null", O_RDWR); 80 if (null_fd < 0) 81 err(1, "open null failed"); 82 83 for (i = 0; i < ninst; ++i) { 84 if (pipe(instance[i].pipes) < 0) 85 err(1, "pipe %dth failed", i); 86 } 87 88 for (i = 0; i < ninst; ++i) { 89 pid_t pid; 90 91 pid = vfork(); 92 if (pid == 0) { 93 int ret; 94 95 dup2(instance[i].pipes[1], STDOUT_FILENO); 96 dup2(null_fd, STDERR_FILENO); 97 ret = execv(NETPERF_PATH, args); 98 if (ret < 0) { 99 warn("execv %d failed", i); 100 _exit(1); 101 } 102 /* Never reached */ 103 abort(); 104 } else if (pid < 0) { 105 err(1, "vfork %d failed", i); 106 } 107 close(instance[i].pipes[1]); 108 instance[i].pipes[1] = -1; 109 } 110 111 ninst_done = 0; 112 while (ninst_done < ninst) { 113 pid_t pid; 114 115 pid = waitpid(-1, NULL, 0); 116 if (pid < 0) 117 err(1, "waitpid failed"); 118 ++ninst_done; 119 } 120 121 result = 0.0; 122 for (i = 0; i < ninst; ++i) { 123 char line[128]; 124 FILE *fp; 125 126 fp = fdopen(instance[i].pipes[0], "r"); 127 if (fp == NULL) 128 err(1, "fdopen %dth failed\n", i); 129 130 while (fgets(line, sizeof(line), fp) != NULL) { 131 int n, arg1, arg2, arg3, arg4; 132 double res, arg5; 133 134 n = sscanf(line, "%d%d%d%d%lf%lf", 135 &arg1, &arg2, &arg3, &arg4, &arg5, &res); 136 if (n == 6) { 137 result += res; 138 break; 139 } 140 } 141 fclose(fp); 142 } 143 printf("TCP_CC %.2f conns/s\n", result); 144 145 exit(0); 146 } 147