diff --git a/server/src/random.c b/server/src/random.c index 6556753ed..7e3849cd6 100644 --- a/server/src/random.c +++ b/server/src/random.c @@ -38,7 +38,8 @@ int main(int argc, char *argv[]) printf(" VALUES is the number of values a message contains\n"); printf(" RATE how many messages per second\n\n"); printf("Simulator2Simulator Server %s (built on %s %s)\n", BLU(VERSION), MAG(__DATE__), MAG(__TIME__)); - printf("Copyright 2014, Institute for Automation of Complex Power Systems, EONERC\n"); + printf(" Copyright 2014, Institute for Automation of Complex Power Systems, EONERC\n"); + printf(" Steffen Vogel \n"); exit(EXIT_FAILURE); } diff --git a/server/src/receive.c b/server/src/receive.c index 92a3d285e..e96c5e286 100644 --- a/server/src/receive.c +++ b/server/src/receive.c @@ -17,32 +17,37 @@ #include #include "config.h" +#include "cfg.h" #include "utils.h" #include "node.h" #include "msg.h" -int sd; +static struct settings set; +static struct msg msg = MSG_INIT(0); +extern struct node *nodes; +static struct node *node; void quit(int sig, siginfo_t *si, void *ptr) { - close(sd); + node_stop(node); exit(EXIT_SUCCESS); } int main(int argc, char *argv[]) { + struct config_t config; + if (argc != 2) { - printf("Usage: %s LOCAL\n", argv[0]); - printf(" LOCAL is a IP:PORT combination of the local host\n\n"); + printf("Usage: %s CONFIG NODE\n", argv[0]); + printf(" CONFIG path to a configuration file\n"); + printf(" NODE name of the node which shoud be used\n\n"); printf("Simulator2Simulator Server %s (built on %s %s)\n", BLU(VERSION), MAG(__DATE__), MAG(__TIME__)); - printf("Copyright 2014, Institute for Automation of Complex Power Systems, EONERC\n"); + printf(" Copyright 2014, Institute for Automation of Complex Power Systems, EONERC\n"); + printf(" Steffen Vogel \n"); exit(EXIT_FAILURE); } - struct node n = NODE_INIT("remote"); - struct msg m; - /* Setup signals */ struct sigaction sa_quit = { .sa_flags = SA_SIGINFO, @@ -53,22 +58,25 @@ int main(int argc, char *argv[]) sigaction(SIGTERM, &sa_quit, NULL); sigaction(SIGINT, &sa_quit, NULL); - /* Resolve addresses */ - int ret = resolve_addr(argv[1], &n.local, 0); - if (ret) - error("Failed to resolve local address '%s': %s", argv[1], gai_strerror(ret)); + config_init(&config); + config_parse(argv[1], &config, &set, &nodes, NULL); + + node = node_lookup_name(argv[2], nodes); + if (!node) + error("There's no node with the name '%s'", argv[2]); - node_connect(&n); + node_start(node); + node_start_defer(node); /* Print header */ fprintf(stderr, "# %-6s %-8s %-12s\n", "dev_id", "seq_no", "data"); while (1) { - msg_recv(&m, &n); + node_read(node, &msg); - if (m.version != MSG_VERSION) + if (msg.version != MSG_VERSION) continue; - if (m.type != MSG_TYPE_DATA) + if (msg.type != MSG_TYPE_DATA) continue; #if 1 @@ -77,7 +85,7 @@ int main(int argc, char *argv[]) fprintf(stdout, "%17.6f", ts.tv_sec + ts.tv_nsec / 1e9); #endif - msg_fprint(stdout, &m); + msg_fprint(stdout, &msg); } return 0; diff --git a/server/src/send.c b/server/src/send.c index 6d3eaf0a2..51db9cc99 100644 --- a/server/src/send.c +++ b/server/src/send.c @@ -18,33 +18,38 @@ #include #include "config.h" +#include "cfg.h" #include "utils.h" #include "node.h" #include "msg.h" +#include "socket.h" -int sd; +static struct settings set; +static struct msg msg = MSG_INIT(0); +static struct node *node; +extern struct node *nodes; void quit(int sig, siginfo_t *si, void *ptr) { - close(sd); + node_stop(node); exit(EXIT_SUCCESS); } int main(int argc, char *argv[]) { - if (argc != 2 && argc != 3) { - printf("Usage: %s REMOTE [LOCAL]\n", argv[0]); - printf(" REMOTE is a IP:PORT combination of the remote host\n"); - printf(" LOCAL is an optional IP:PORT combination of the local host\n"); + struct config_t config; + + if (argc != 3) { + printf("Usage: %s CONFIG NODE\n", argv[0]); + printf(" CONFIG path to a configuration file\n"); + printf(" NODE name of the node which shoud be used\n\n"); printf("Simulator2Simulator Server %s (built on %s %s)\n", BLU(VERSION), MAG(__DATE__), MAG(__TIME__)); - printf("Copyright 2014, Institute for Automation of Complex Power Systems, EONERC\n"); + printf(" Copyright 2014, Institute for Automation of Complex Power Systems, EONERC\n"); + printf(" Steffen Vogel \n"); exit(EXIT_FAILURE); } - struct node n = NODE_INIT("remote"); - struct msg m = MSG_INIT(0); - /* Setup signals */ struct sigaction sa_quit = { .sa_flags = SA_SIGINFO, @@ -55,26 +60,18 @@ int main(int argc, char *argv[]) sigaction(SIGTERM, &sa_quit, NULL); sigaction(SIGINT, &sa_quit, NULL); - /* Resolve addresses */ - int ret = resolve_addr(argv[1], &n.remote, 0); - if (ret) - error("Failed to resolve remote address '%s': %s", argv[1], gai_strerror(ret)); + config_init(&config); + config_parse(argv[1], &config, &set, &nodes, NULL); + + node = node_lookup_name(argv[2], nodes); + if (!node) + error("There's no node with the name '%s'", argv[2]); - if (argc == 3) { - ret = resolve_addr(argv[2], &n.local, AI_PASSIVE); - if (ret) - error("Failed to resolve local address '%s': %s", argv[2], gai_strerror(ret)); - } - else { - n.local.sin_family = AF_INET; - n.local.sin_addr.s_addr = INADDR_ANY; /* all local interfaces */ - n.local.sin_port = 0; /* random port */ - } - - node_connect(&n); + node_start(node); + node_start_defer(node); while (!feof(stdin)) { - msg_fscan(stdin, &m); + msg_fscan(stdin, &msg); #if 1 /* Preprend timestamp */ struct timespec ts; @@ -82,8 +79,8 @@ int main(int argc, char *argv[]) fprintf(stdout, "%17.3f\t", ts.tv_sec + ts.tv_nsec / 1e9); #endif - msg_fprint(stdout, &m); - msg_send(&m, &n); + msg_fprint(stdout, &msg); + node_write(node, &msg); } return 0; diff --git a/server/src/server.c b/server/src/server.c index 20fb0e53f..fb9d77485 100644 --- a/server/src/server.c +++ b/server/src/server.c @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -22,129 +23,32 @@ #include "node.h" /** Linked list of nodes */ -static struct node *nodes; +extern struct node *nodes; /** Linked list of paths */ -static struct path *paths; +extern struct path *paths; /** Linked list of interfaces */ -static struct interface *interfaces; +extern struct interface *interfaces; /** The global configuration */ -static struct settings settings; -static config_t config; - -static void start() -{ - /* Connect and bind nodes to their sockets, set socket options */ - for (struct node *n = nodes; n; n = n->next) { - if (!n->refcnt) continue; - - /* Determine outgoing interface */ - int index = if_getegress(&n->remote); - if (index < 0) - error("Failed to get egress interface for node '%s'", n->name); - - n->interface = if_lookup_index(index, interfaces); - - /* Create new interface */ - if (!n->interface) { - struct interface *i = malloc(sizeof(struct interface)); - if (!i) - error("Failed to allocate memory for interface"); - else - memset(i, 0, sizeof(struct interface)); - - i->index = index; - if_indextoname(index, i->name); - - debug(3, "Setup interface '%s'", i->name, - i->index, i->refcnt); - - /* Set affinity for network interfaces */ - if (settings.affinity && i->index) { - if_getirqs(i); - if_setaffinity(i, settings.affinity); - } - - list_add(interfaces, i); - n->interface = i; - } - - node_connect(n); - - /* Set fwmark for outgoing packets */ - if (n->netem) { - n->mark = 1 + n->interface->refcnt++; - - if (setsockopt(n->sd, SOL_SOCKET, SO_MARK, &n->mark, sizeof(n->mark))) - perror("Failed to set fwmark for outgoing packets"); - else - debug(4, "Set fwmark of outgoing packets of node '%s' to %u", - n->name, n->mark); - } - -#if 0 /* Set QoS or TOS IP options */ - int prio = SOCKET_PRIO; - if (setsockopt(n->sd, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio))) - perror("Failed to set socket priority"); - else - debug(4, "Set socket priority for node '%s' to %u", n->name, prio); -#else - int tos = IPTOS_LOWDELAY; - if (setsockopt(n->sd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos))) - perror("Failed to set type of service (QoS)"); - else - debug(4, "Set QoS/TOS IP option for node '%s' to %#x", n->name, tos); -#endif - } - - /* Setup network emulation */ - for (struct interface *i = interfaces; i; i = i->next) { - if (!i->refcnt) continue; - - tc_prio(i, TC_HDL(4000, 0), i->refcnt); - } - - for (struct node *n = nodes; n; n = n->next) { - if (n->netem) { - tc_mark(n->interface, TC_HDL(4000, n->mark), n->mark); - tc_netem(n->interface, TC_HDL(4000, n->mark), n->netem); - } - } - - /* Start on thread per path for asynchronous processing */ - for (struct path *p = paths; p; p = p->next) { - path_start(p); - - info("Path started: %12s " GRN("=>") " %-12s", - p->in->name, p->out->name); - } -} - -static void stop() -{ - /* Join all threads and print statistics */ - for (struct path *p = paths; p; p = p->next) { - path_stop(p); - - info("Path stopped: %12s " RED("=>") " %-12s", - p->in->name, p->out->name); - } - - /* Close all sockets we listen on */ - for (struct node *n = nodes; n; n = n->next) { - node_disconnect(n); - } - - /* Reset interface queues and affinity */ - for (struct interface *i = interfaces; i; i = i->next) { - if_setaffinity(i, -1); - tc_reset(i); - } -} +struct settings settings; +config_t config; static void quit() -{ - stop(); +{ _indent = 0; + info("Stopping paths:"); + for (struct path *p = paths; p; p = p->next) { INDENT + path_stop(p); + } + + info("Stopping nodes:"); + for (struct node *n = nodes; n; n = n->next) { INDENT + node_stop(n); + } + + info("Stopping interfaces:"); + for (struct interface *i = interfaces; i; i = i->next) { INDENT + if_stop(i); + } /** @todo Free nodes and paths */ @@ -153,42 +57,8 @@ static void quit() _exit(EXIT_SUCCESS); } -int main(int argc, char *argv[]) -{ - /* Check arguments */ - if (argc != 2) { - printf("Usage: %s CONFIG\n", argv[0]); - printf(" CONFIG is a required path to a configuration file\n\n"); - printf("Simulator2Simulator Server %s (built on %s, %s)\n", - BLU(VERSION), MAG(__DATE__), MAG(__TIME__)); - printf(" Copyright 2014, Institute for Automation of Complex Power Systems, EONERC\n"); - printf(" Steffen Vogel \n"); - exit(EXIT_FAILURE); - } - - info("This is %s %s", BLU("s2ss"), BLU(VERSION)); - - /* Setup exit handler */ - 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); - atexit(&quit); - - /* Parse configuration file */ - config_init(&config); - config_parse(argv[1], &config, &settings, &nodes, &paths); - - debug(1, "Running with debug level: %u", settings.debug); - - /* Check priviledges */ - if (getuid() != 0) - error("The server requires superuser privileges!"); - +void realtime_init() +{ INDENT /* Check for realtime kernel patch */ struct stat st; if (stat("/sys/kernel/realtime", &st)) @@ -213,10 +83,75 @@ int main(int argc, char *argv[]) else debug(3, "Set affinity to %#x", settings.affinity); } +} + +/* Setup exit handler */ +void signals_init() +{ INDENT + 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); + atexit(&quit); +} + +void usage(const char *name) +{ + printf("Usage: %s CONFIG\n", name); + printf(" CONFIG is a required path to a configuration file\n\n"); + printf("Simulator2Simulator Server %s (built on %s, %s)\n", + BLU(VERSION), MAG(__DATE__), MAG(__TIME__)); + + exit(EXIT_FAILURE); +} + +int main(int argc, char *argv[]) +{ + epoch_reset(); + info("This is Simulator2Simulator Server (S2SS) %s (built on %s, %s)", + BLD(YEL(VERSION)), BLD(MAG(__DATE__)), BLD(MAG(__TIME__))); + + /* Check arguments */ + if (argc != 2) + usage(argv[0]); + + /* Check priviledges */ + if (getuid() != 0) + error("The server requires superuser privileges!"); + + /* Start initialization */ + info("Initialize realtime system:"); + realtime_init(); + info("Setup signals:"); + signals_init(); + info("Parsing configuration:"); + config_init(&config); + + /* Parse configuration and create nodes/paths */ + config_parse(argv[1], &config, &settings, &nodes, &paths); + /* Connect all nodes and start one thread per path */ - start(); + info("Starting nodes:"); + for (struct node *n = nodes; n; n = n->next) { INDENT + node_start(n); + } + info("Starting interfaces:"); + for (struct interface *i = interfaces; i; i = i->next) { INDENT + if_start(i, settings.affinity); + } + + info("Starting pathes:"); + for (struct path *p = paths; p; p = p->next) { INDENT + path_start(p); + } + + /* Run! */ if (settings.stats > 0) { struct path *p = paths; @@ -235,5 +170,7 @@ int main(int argc, char *argv[]) else pause(); + /* Note: quit() is called by exit handler! */ + return 0; } diff --git a/server/src/test.c b/server/src/test.c index eafb9dc2b..9fa826c89 100644 --- a/server/src/test.c +++ b/server/src/test.c @@ -15,11 +15,15 @@ #include #include "config.h" +#include "cfg.h" #include "msg.h" #include "node.h" #include "utils.h" -int sd; +static struct settings set; +static struct node *node; +extern struct node *nodes; + int running = 1; #define CLOCK_ID CLOCK_MONOTONIC_RAW @@ -36,19 +40,19 @@ void quit(int sig, siginfo_t *si, void *ptr) int main(int argc, char *argv[]) { + config_t config; + if (argc != 4) { - printf("Usage: %s TEST LOCAL REMOTE\n", argv[0]); - printf(" TEST has to be 'rtt' for now\n"); - printf(" LOCAL is a IP:PORT combination of the local host\n"); - printf(" REMOTE is a IP:PORT combination of the remote host\n\n"); + printf("Usage: %s CONFIG NODE\n", argv[0]); + printf(" CONFIG path to a configuration file\n"); + printf(" NODE name of the node which shoud be used\n\n"); printf("Simulator2Simulator Server %s (built on %s %s)\n", BLU(VERSION), MAG(__DATE__), MAG(__TIME__)); - printf("Copyright 2014, Institute for Automation of Complex Power Systems, EONERC\n"); + printf(" Copyright 2014, Institute for Automation of Complex Power Systems, EONERC\n"); + printf(" Steffen Vogel \n"); exit(EXIT_FAILURE); } - struct node n = NODE_INIT("remote"); - /* Setup signals */ struct sigaction sa_quit = { .sa_flags = SA_SIGINFO, @@ -59,16 +63,15 @@ int main(int argc, char *argv[]) sigaction(SIGTERM, &sa_quit, NULL); sigaction(SIGINT, &sa_quit, NULL); - /* Resolve addresses */ - int ret = resolve_addr(argv[2], &n.local, AI_PASSIVE); - if (ret) - error("Failed to resolve local address '%s': %s", argv[1], gai_strerror(ret)); + config_init(&config); + config_parse(argv[1], &config, &set, &nodes, NULL); + + node = node_lookup_name(argv[2], nodes); + if (!node) + error("There's no node with the name '%s'", argv[2]); - ret = resolve_addr(argv[3], &n.remote, 0); - if (ret) - error("Failed to resolve remote address '%s': %s", argv[1], gai_strerror(ret)); - - node_connect(&n); + node_start(node); + node_start_defer(node); if (!strcmp(argv[1], "rtt")) { struct msg m = MSG_INIT(sizeof(struct timespec) / sizeof(float)); @@ -91,10 +94,9 @@ int main(int argc, char *argv[]) fprintf(stdout, "%5s%10s%10s%10s%10s\n", "seq", "rtt", "min", "max", "avg"); while (running) { - clock_gettime(CLOCK_ID, ts1); - msg_send(&m, &n); - msg_recv(&m, &n); + node_write(node, &m); + node_read(node, &m); clock_gettime(CLOCK_ID, ts2); rtt = timespec_delta(ts1, ts2); @@ -127,7 +129,7 @@ int main(int argc, char *argv[]) hist_dump(hist, RTT_HIST); } - close(sd); + node_stop(node); return 0; }