--- /dev/null
+#include <fcntl.h>
+#include <netinet/ip.h>
+#include <stdio.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <time.h>
+#include <unistd.h>
+
+/* Subtract the `struct timespec' values X and Y,
+ storing the result in RESULT.
+ Return 1 if the difference is negative, otherwise 0. */
+
+int
+timespec_subtract (result, x, y)
+struct timespec *result, *x, *y;
+{
+ /* Perform the carry for the later subtraction by updating Y. */
+ if (x->tv_nsec < y->tv_nsec) {
+ int nsec = (y->tv_nsec - x->tv_nsec) / 1000000000 + 1;
+ y->tv_nsec -= 1000000000 * nsec;
+ y->tv_sec += nsec;
+ }
+ if (x->tv_nsec - y->tv_nsec > 1000000000) {
+ int nsec = (x->tv_nsec - y->tv_nsec) / 1000000000;
+ y->tv_nsec += 1000000000 * nsec;
+ y->tv_sec -= nsec;
+ }
+
+ /* Compute the time remaining to wait.
+ `tv_nsec' is certainly positive. */
+ result->tv_sec = x->tv_sec - y->tv_sec;
+ result->tv_nsec = x->tv_nsec - y->tv_nsec;
+
+ /* Return 1 if result is negative. */
+ return x->tv_sec < y->tv_sec;
+}
+
+int slave(int srx)
+{
+ int ret;
+ char msgr[100];
+ struct sockaddr a;
+ socklen_t alen = sizeof(a);
+
+ while (1) {
+ ret = recvfrom(srx, msgr, sizeof(msgr), 0, &a, &alen);
+ if (ret == -1) perror("slave recvfrom");
+ ret = sendto(srx, msgr, ret, 0, &a, alen);
+ if (ret == -1) perror("slave sendto");
+ }
+}
+
+
+#define HIST_SIZE 1000
+#define HIST_MAX_US 100000
+unsigned hist[1000];
+
+int usec2hist(int usec)
+{
+ int i;
+ i = HIST_SIZE*usec/HIST_MAX_US;
+ if (i >= HIST_SIZE)
+ i = HIST_SIZE;
+ hist[i]++;
+}
+
+int main()
+{
+ int stx, srx;
+ struct sockaddr_in a;
+ struct timespec tstart, tend, t;
+ char msg[] = "asdf";
+ char msgr[100];
+ int ret;
+ int usec, max=0;
+ int i;
+ pid_t pid;
+
+ stx = socket(PF_INET, SOCK_DGRAM, 0);
+ a.sin_family = AF_INET;
+ a.sin_port = htons(1234);
+ a.sin_addr.s_addr = inet_addr("127.1.2.3");
+ srx = socket(PF_INET, SOCK_DGRAM, 0);
+ bind(srx, (struct sockaddr*)&a, sizeof(a));
+
+ pid = fork();
+ if (pid < 0)
+ perror("fork");
+ if (pid == 0) {
+ slave(srx);
+ return 0;
+ }
+ close(srx);
+
+ for (i=0; i<10000; i++) {
+ clock_gettime(CLOCK_MONOTONIC, &tstart);
+ ret = sendto(stx, msg, sizeof(msg), 0, (struct sockaddr*)&a, sizeof(a));
+ if (ret == -1) perror("main sendto");
+ ret = recv(stx, msgr, sizeof(msgr), 0);
+ if (ret == -1) perror("main recv");
+ clock_gettime(CLOCK_MONOTONIC, &tend);
+ timespec_subtract(&t, &tend, &tstart);
+
+ usec = t.tv_sec*1000000 + t.tv_nsec/1000;
+ usec2hist(usec);
+ if (usec > max) {
+ max = usec;
+ //printf("%d.%.03d\n", usec/1000, usec%1000);
+ }
+
+ }
+
+ kill(pid);
+
+ printf("Duration: %d.%.03d ms\n", max/1000, max%1000);
+
+
+ /* Draw histogram */
+ int fd[2];
+ pipe(fd);
+ pid = fork();
+ if (pid < 0) {
+ perror("fork gnuplot");
+ return 1;
+ } else if(pid == 0)
+ {
+ close(fd[1]);
+ dup2(fd[0], 0);
+/* int n = open("/dev/null", O_RDWR); */
+/* dup2(n, 1); */
+/* dup2(n, 2); */
+ execlp("gnuplot", "gnuplot", "-persist", NULL);
+ }
+ close(fd[0]);
+ FILE *f = fdopen(fd[1], "a");
+ fprintf(f, "set xlabel 'ms'\n");
+ fprintf(f, "set logscale y\n");
+ fprintf(f, "plot '-' with steps\n");
+ int j;
+ for (j=0; j<HIST_SIZE; j++) {
+ if (hist[j]) {
+ fprintf(f, "%g %d\n", j/10.0, i);
+ i -= hist[j];
+ }
+ }
+ fprintf(f, "e\n", i, hist[i]);
+ fflush(f);
+ fclose(f);
+ sleep(10);
+ wait(pid);
+ return 0;
+}