/** * Some basic tests * * @author Steffen Vogel * @copyright 2014, Institute for Automation of Complex Power Systems, EONERC */ #include #include #include #include #include #include #include #include "msg.h" #include "utils.h" int sd; void quit(int sig, siginfo_t *si, void *ptr) { close(sd); exit(EXIT_SUCCESS); } int main(int argc, char *argv[]) { if (argc != 3 && argc != 4) { printf("Usage: %s TEST REMOTE [LOCAL]\n", argv[0]); printf(" TEST has to be 'latency' for now\n"); printf(" REMOTE is a IP:PORT combination of the remote host\n"); printf(" LOCAL is a IP:PORT combination of the remote host\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); } const char *test = argv[1]; const char *remote_str = argv[2]; const char *local_str = (argc == 4) ? argv[3] : NULL; /* Setup signals */ struct sigaction sa_quit = { .sa_flags = SA_SIGINFO, .sa_sigaction = quit }; sigemptyset(&sa_quit.sa_mask); sigaction(SIGTERM, &sa_quit, NULL); sigaction(SIGINT, &sa_quit, NULL); /* Resolve addresses */ struct sockaddr_in remote; struct sockaddr_in local; if (resolve(remote_str, &remote, 0)) error("Failed to resolve remote address: %s", remote_str); if (resolve(local_str, &local, 0)) error("Failed to resolve local address: %s", local_str); /* Create socket */ sd = socket(AF_INET, SOCK_DGRAM, 0); if (sd < 0) perror("Failed to create socket"); /* Bind socket */ if (bind(sd, (struct sockaddr *) &local, sizeof(struct sockaddr_in))) perror("Failed to bind to socket"); /* Connect socket */ if (connect(sd, (struct sockaddr *) &remote, sizeof(struct sockaddr_in))) perror("Failed to connect socket"); if (!strcmp(test, "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)); long long rtt, rtt_max = LLONG_MIN, rtt_min = LLONG_MAX; long long run = 0, avg = 0; while (1) { clock_gettime(CLOCK_REALTIME, ts1); send(sd, &m1, 8 + m1.length, 0); recv(sd, &m2, sizeof(struct msg), 0); clock_gettime(CLOCK_REALTIME, ts3); 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; info("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; }