diff --git a/src/test.c b/src/test.c index db16b0bec..452a1d0a8 100644 --- a/src/test.c +++ b/src/test.c @@ -1,104 +1,105 @@ /** - * Simple UDP test client (simulator emulation) + * Some basic tests * * @author Steffen Vogel * @copyright 2014, Institute for Automation of Complex Power Systems, EONERC */ #include -#include -#include -#include -#include #include #include +#include +#include +#include +#include -#include -#include -#include - -#include "config.h" -#include "utils.h" #include "msg.h" +#include "utils.h" -int dev_id; int sd; -void quit() +void quit(int sig, siginfo_t *si, void *ptr) { - debug(1, "Goodbye"); + close(sd); exit(EXIT_SUCCESS); } -void tick() -{ - struct msg m; - - msg_random(&m, dev_id); - msg_fprint(stdout, &m); - - send(sd, &m, sizeof(struct msg), 0); -} - int main(int argc, char *argv[]) { - if (argc != 4) { - printf("Usage: test DEVID IP PORT\n"); - printf(" DEVID is the device id of this node\n"); + struct sockaddr_in sa; + + if (argc != 3) { + printf("Usage: %s TEST IP:PORT\n", argv[0]); + printf(" TEST has to be 'latency' for now\n"); printf(" IP is the destination ip of our packets\n"); - printf(" PORT is the port to recv/send from\n\n"); + printf(" PORT is the port to send to\n\n"); printf("s2ss Simulator2Simulator Server v%s\n", VERSION); printf("Copyright 2014, Institute for Automation of Complex Power Systems, EONERC\n"); exit(EXIT_FAILURE); } - dev_id = atoi(argv[1]); - int ret; + /* Setup signals */ + struct sigaction sa_quit = { + .sa_flags = SA_SIGINFO, + .sa_sigaction = quit + }; - info("Test node started on %s:%s with id=%u", argv[2], argv[3], dev_id); + sigemptyset(&sa_quit.sa_mask); + sigaction(SIGINT, &sa_quit, NULL); + /* Resolve address */ + if (resolve(argv[2], &sa, 0)) + error("Failed to resolve: %s", argv[2]); + + /* Create socket */ sd = socket(AF_INET, SOCK_DGRAM, 0); if (sd < 0) error("Failed to create socket: %s", strerror(errno)); - struct sockaddr_in sa = { - .sin_family = AF_INET, - .sin_port = htons(atoi(argv[3])) - }; - inet_pton(AF_INET, argv[2], &sa.sin_addr); + /* Bind socket */ + if (bind(sd, (struct sockaddr *) &sa, sizeof(struct sockaddr_in))) + error("Failed to bind socket: %s", strerror(errno)); - sigset_t mask; - sigemptyset(&mask); - sigaddset(&mask, SIGUSR1); - //sigprocmask(SIG_SETMASK, &mask, NULL); - sigprocmask(SIG_UNBLOCK, &mask, NULL); - - ret = bind(sd, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)); - - ret = connect(sd, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)); - if (ret < 0) + /* Connect socket */ + sa.sin_port = htons(ntohs(sa.sin_port) + 1); + if (connect(sd, (struct sockaddr *) &sa, sizeof(struct sockaddr_in))) { error("Failed to connect socket: %s", strerror(errno)); + } - struct sigevent si = { - .sigev_notify = SIGEV_SIGNAL, - .sigev_signo = SIGUSR1 - }; - struct itimerspec its = { - { 0, 250000000 }, - { 0, 500000000 } - }; + if (!strcmp(argv[1], "latency")) { + struct msg m2, m1 = { + .device = 99, + .sequence = 0 + }; + struct timespec *ts1 = (struct timespec *) &m1.data; + struct timespec *ts2 = (struct timespec *) &m2.data; + struct timespec *ts3 = malloc(sizeof(struct timespec)); - timer_t t; - timer_create(CLOCK_MONOTONIC, &si, &t); - timer_settime(t, 0, &its, NULL); + long long rtt, rtt_max = LLONG_MIN, rtt_min = LLONG_MAX; + long long run = 0, avg = 0; - signal(SIGUSR1, tick); - signal(SIGINT, quit); + while (1) { + clock_gettime(CLOCK_REALTIME, ts1); + send(sd, &m1, 8 + m1.length, 0); - while(1) pause(); + recv(sd, &m2, sizeof(struct msg), 0); + clock_gettime(CLOCK_REALTIME, ts3); - timer_delete(t); + rtt = ts3->tv_nsec - ts2->tv_nsec; + if (rtt < 0) continue; + + if (rtt > rtt_max) rtt_max = rtt; + if (rtt < rtt_min) rtt_min = rtt; + + avg += rtt; + + printf("rtt %.3f min %.3f max %.3f avg %.3f uS\n", 1e-3 * rtt, 1e-3 * rtt_min, 1e-3 * rtt_max, 1e-3 * avg / ++run); + + m1.sequence++; + usleep(1000); + } + } return 0; }