8 #include <netinet/in.h>
14 #include <sys/resource.h>
16 #include "../splice.h"
20 static void **buffers;
21 static int cur_buf, nr_bufs;
23 static unsigned int msg_size = 4096;
24 static int use_splice = 1;
25 static unsigned long packets = -1;
27 static unsigned long seed = 0x9e370001UL;
29 unsigned long mtime_since(struct timeval *s, struct timeval *e)
33 sec = e->tv_sec - s->tv_sec;
34 usec = e->tv_usec - s->tv_usec;
35 if (sec > 0 && usec < 0) {
45 * time warp bug on some kernels?
53 unsigned long mtime_since_now(struct timeval *s)
57 gettimeofday(&t, NULL);
58 return mtime_since(s, &t);
61 static int usage(char *name)
63 fprintf(stderr, "%s: [-s(ize)] [-p(ackets to send)] [-n(ormal send())] target port\n", name);
67 static int parse_options(int argc, char *argv[])
71 while ((c = getopt(argc, argv, "s:np:")) != -1) {
74 msg_size = atoi(optarg);
82 packets = atoi(optarg);
93 static void fill_buf(struct msg *m, unsigned int len)
106 if (left < sizeof(*val))
108 *val = rand() * seed;
110 left -= sizeof(*val);
113 m->crc32 = crc32(p, len);
116 static int splice_out(int sockfd, int pipefd, unsigned int len)
119 int ret = ssplice(pipefd, NULL, sockfd, NULL, len, 0);
122 return error("splice to network");
132 static int vmsplice_in(void *buf, int pipefd, unsigned int len)
140 int ret = svmsplice(pipefd, &iov, 1, 0);
143 return error("vmsplice");
158 * Keep four pipes of buffers, that should be enough to ensure that
161 static void setup_buffers(void)
165 nr_bufs = 4 * SPLICE_SIZE / msg_size;
167 buffers = malloc(sizeof(void *) * nr_bufs);
169 for (i = 0; i < nr_bufs; i++)
170 posix_memalign(&buffers[i], 4096, msg_size);
173 static void free_buffers(void)
177 for (i = 0; i < nr_bufs; i++)
183 static int splice_send_loop(int fd)
185 struct msg *m = NULL;
189 return error("pipe");
194 m = buffers[cur_buf];
195 if (++cur_buf == nr_bufs)
199 * fill with random data and crc sum it
201 fill_buf(m, msg_size);
204 * map data to our pipe
206 if (vmsplice_in(m, pipes[1], msg_size))
210 * then transmit pipe to network
212 if (splice_out(fd, pipes[0], msg_size))
222 static int do_send(int fd, void *buf, unsigned int len)
225 int ret = send(fd, buf, len, 0);
228 return error("send");
239 static int normal_send_loop(int fd)
243 m = malloc(msg_size);
247 * fill with random data and crc sum it
249 fill_buf(m, msg_size);
251 if (do_send(fd, m, msg_size))
259 static int send_loop(int fd)
261 struct rusage ru_s, ru_e;
262 unsigned long ut, st, rt;
263 struct timeval start;
266 gettimeofday(&start, NULL);
267 getrusage(RUSAGE_SELF, &ru_s);
270 ret = splice_send_loop(fd);
272 ret = normal_send_loop(fd);
274 getrusage(RUSAGE_SELF, &ru_e);
276 ut = mtime_since(&ru_s.ru_utime, &ru_e.ru_utime);
277 st = mtime_since(&ru_s.ru_stime, &ru_e.ru_stime);
278 rt = mtime_since_now(&start);
280 printf("usr=%lu, sys=%lu, real=%lu\n", ut, st, rt);
285 int main(int argc, char *argv[])
287 struct sockaddr_in addr;
292 return usage(argv[0]);
294 index = parse_options(argc, argv);
295 if (index == -1 || index + 1 > argc)
296 return usage(argv[0]);
298 port = atoi(argv[index + 1]);
300 memset(&addr, 0, sizeof(addr));
301 addr.sin_family = AF_INET;
302 addr.sin_port = htons(port);
304 if (inet_aton(argv[index], &addr.sin_addr) != 1) {
305 struct hostent *hent = gethostbyname(argv[index]);
308 return error("gethostbyname");
310 memcpy(&addr.sin_addr, hent->h_addr, 4);
313 printf("xmit: msg=%ukb, ", msg_size >> 10);
315 printf("vmsplice() -> splice()\n");
319 printf("Connecting to %s/%d\n", argv[index], port);
321 fd = socket(AF_INET, SOCK_STREAM, 0);
323 return error("socket");
325 if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0)
326 return error("connect");
328 return send_loop(fd);