linux/tools/testing/selftests/net/fin_ack_lat.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2
   3#include <arpa/inet.h>
   4#include <errno.h>
   5#include <error.h>
   6#include <netinet/in.h>
   7#include <netinet/tcp.h>
   8#include <signal.h>
   9#include <stdio.h>
  10#include <stdlib.h>
  11#include <sys/socket.h>
  12#include <sys/time.h>
  13#include <unistd.h>
  14
  15static int child_pid;
  16
  17static unsigned long timediff(struct timeval s, struct timeval e)
  18{
  19        unsigned long s_us, e_us;
  20
  21        s_us = s.tv_sec * 1000000 + s.tv_usec;
  22        e_us = e.tv_sec * 1000000 + e.tv_usec;
  23        if (s_us > e_us)
  24                return 0;
  25        return e_us - s_us;
  26}
  27
  28static void client(int port)
  29{
  30        int sock = 0;
  31        struct sockaddr_in addr, laddr;
  32        socklen_t len = sizeof(laddr);
  33        struct linger sl;
  34        int flag = 1;
  35        int buffer;
  36        struct timeval start, end;
  37        unsigned long lat, sum_lat = 0, nr_lat = 0;
  38
  39        while (1) {
  40                gettimeofday(&start, NULL);
  41
  42                sock = socket(AF_INET, SOCK_STREAM, 0);
  43                if (sock < 0)
  44                        error(-1, errno, "socket creation");
  45
  46                sl.l_onoff = 1;
  47                sl.l_linger = 0;
  48                if (setsockopt(sock, SOL_SOCKET, SO_LINGER, &sl, sizeof(sl)))
  49                        error(-1, errno, "setsockopt(linger)");
  50
  51                if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
  52                                        &flag, sizeof(flag)))
  53                        error(-1, errno, "setsockopt(nodelay)");
  54
  55                addr.sin_family = AF_INET;
  56                addr.sin_port = htons(port);
  57
  58                if (inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr) <= 0)
  59                        error(-1, errno, "inet_pton");
  60
  61                if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
  62                        error(-1, errno, "connect");
  63
  64                send(sock, &buffer, sizeof(buffer), 0);
  65                if (read(sock, &buffer, sizeof(buffer)) == -1)
  66                        error(-1, errno, "waiting read");
  67
  68                gettimeofday(&end, NULL);
  69                lat = timediff(start, end);
  70                sum_lat += lat;
  71                nr_lat++;
  72                if (lat < 100000)
  73                        goto close;
  74
  75                if (getsockname(sock, (struct sockaddr *)&laddr, &len) == -1)
  76                        error(-1, errno, "getsockname");
  77                printf("port: %d, lat: %lu, avg: %lu, nr: %lu\n",
  78                                ntohs(laddr.sin_port), lat,
  79                                sum_lat / nr_lat, nr_lat);
  80close:
  81                fflush(stdout);
  82                close(sock);
  83        }
  84}
  85
  86static void server(int sock, struct sockaddr_in address)
  87{
  88        int accepted;
  89        int addrlen = sizeof(address);
  90        int buffer;
  91
  92        while (1) {
  93                accepted = accept(sock, (struct sockaddr *)&address,
  94                                (socklen_t *)&addrlen);
  95                if (accepted < 0)
  96                        error(-1, errno, "accept");
  97
  98                if (read(accepted, &buffer, sizeof(buffer)) == -1)
  99                        error(-1, errno, "read");
 100                close(accepted);
 101        }
 102}
 103
 104static void sig_handler(int signum)
 105{
 106        kill(SIGTERM, child_pid);
 107        exit(0);
 108}
 109
 110int main(int argc, char const *argv[])
 111{
 112        int sock;
 113        int opt = 1;
 114        struct sockaddr_in address;
 115        struct sockaddr_in laddr;
 116        socklen_t len = sizeof(laddr);
 117
 118        if (signal(SIGTERM, sig_handler) == SIG_ERR)
 119                error(-1, errno, "signal");
 120
 121        sock = socket(AF_INET, SOCK_STREAM, 0);
 122        if (sock < 0)
 123                error(-1, errno, "socket");
 124
 125        if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT,
 126                                &opt, sizeof(opt)) == -1)
 127                error(-1, errno, "setsockopt");
 128
 129        address.sin_family = AF_INET;
 130        address.sin_addr.s_addr = INADDR_ANY;
 131        /* dynamically allocate unused port */
 132        address.sin_port = 0;
 133
 134        if (bind(sock, (struct sockaddr *)&address, sizeof(address)) < 0)
 135                error(-1, errno, "bind");
 136
 137        if (listen(sock, 3) < 0)
 138                error(-1, errno, "listen");
 139
 140        if (getsockname(sock, (struct sockaddr *)&laddr, &len) == -1)
 141                error(-1, errno, "getsockname");
 142
 143        fprintf(stderr, "server port: %d\n", ntohs(laddr.sin_port));
 144        child_pid = fork();
 145        if (!child_pid)
 146                client(ntohs(laddr.sin_port));
 147        else
 148                server(sock, laddr);
 149
 150        return 0;
 151}
 152