diff --git a/server/Makefile.mk b/server/Makefile.mk new file mode 100644 index 000000000..cad32cf05 --- /dev/null +++ b/server/Makefile.mk @@ -0,0 +1,52 @@ +TARGETS = server send random receive test + +# Common dependencies for all binaries +OBJS = socket.o if.o utils.o msg.o node.o cfg.o tc.o hooks.o list.o path.o hist.o + +VPATH = src + +# Default debug level +V ?= 2 + +# Compiler and linker flags +LDLIBS = -pthread -lrt -lm -lconfig +CFLAGS = -std=gnu99 -Iinclude/ -MMD -Wall +CFLAGS += -D_XOPEN_SOURCE=500 -D_GNU_SOURCE -DV=$(V) +CFLAGS += -D__GIT_REV__='"-$(shell git rev-parse --short HEAD 2> /dev/null)"' + + +# Conditional flags +ifdef DEBUG + CFLAGS += -O0 -g -D_DEBUG +else + CFLAGS += -O3 +endif + +# Enable OPAL-RT Asynchronous Process support +OPALDIR = /usr/opalrt/common +ifneq (,$(wildcard $(OPALDIR)/include_target/AsyncApi.h)) + CFLAGS += -m32 -DENABLE_OPAL_ASYNC -I$(OPALDIR)/include_target + LDFLAGS += -m32 + LDLIBS += $(addprefix $(OPALDIR)/lib/redhawk/, libOpalAsyncApiCore.a libOpalCore.a libOpalUtils.a libirc.a) + OBJS += opal.o +endif + +.PHONY: all clean + +# Default target: build everything +all: $(TARGETS) + chmod 777 $(TARGETS) + +# Dependencies for individual binaries +server: server.o $(OBJS) +send: send.o $(OBJS) +receive: receive.o $(OBJS) +random: random.o $(OBJS) +test: test.o $(OBJS) + +clean: + $(RM) *~ *.o *.d + $(RM) $(TARGETS) + +# Include auto-generated dependencies +-include $(wildcard *.d) diff --git a/server/etc/opal-shmem.conf b/server/etc/opal-shmem.conf new file mode 100644 index 000000000..aa816dc0b --- /dev/null +++ b/server/etc/opal-shmem.conf @@ -0,0 +1,28 @@ +# Example configuration file for the s2ss server + +affinity = 0x01; # Mask of cores the server should run on +priority = 99; # Scheduler priority for the server +debug = 5; # The level of verbosity for debug messages +stats = 1; # The interval in seconds for path statistics + +nodes = { + opal = { + type = "opal"; + send_id = 1; + recv_id = 1; + }, + acs-s2ss = { + type = "udp"; + local = "*:12000"; + remote = "134.130.169.31:12000"; + } +}; + +paths = ( + { + in = "opal"; + out = "acs-s2ss"; + reverse = true; + hook = "print"; + } +); diff --git a/server/include/config.h b/server/include/config.h index c48558105..f5e306078 100644 --- a/server/include/config.h +++ b/server/include/config.h @@ -12,6 +12,7 @@ #define _CONFIG_H_ /** The version number of the s2ss server */ + #define VERSION "v0.4" __GIT_REV__ /** Maximum number of double values in a struct msg */ diff --git a/server/include/hist.h b/server/include/hist.h index 59a16e131..ecf8eca9e 100644 --- a/server/include/hist.h +++ b/server/include/hist.h @@ -76,4 +76,4 @@ void hist_dump(struct hist *h, char *buf, int len); /** Prints Matlab struct containing all infos to file. */ void hist_matlab(struct hist *h, FILE *f); -#endif /* _HIST_H_ */ \ No newline at end of file +#endif /* _HIST_H_ */ diff --git a/server/include/if.h b/server/include/if.h index a236e6bd3..1abe6e405 100644 --- a/server/include/if.h +++ b/server/include/if.h @@ -17,6 +17,10 @@ #define IF_NAME_MAX IFNAMSIZ /**< Maximum length of an interface name */ #define IF_IRQ_MAX 3 /**< Maxmimal number of IRQs of an interface */ +#ifndef SO_MARK +#define SO_MARK 36 /**< Workaround: add missing constant for OPAL-RT Redhawk target */ +#endif + struct socket; /** Interface data structure */ diff --git a/server/include/list.h b/server/include/list.h index 999365833..269404094 100644 --- a/server/include/list.h +++ b/server/include/list.h @@ -67,4 +67,4 @@ void list_push(struct list *l, void *p); struct list_elm * list_search(struct list *l, int (*cmp)(void *)); -#endif /* _LIST_H_ */ \ No newline at end of file +#endif /* _LIST_H_ */ diff --git a/server/include/utils.h b/server/include/utils.h index d20c5500b..9f4e34c7f 100644 --- a/server/include/utils.h +++ b/server/include/utils.h @@ -21,23 +21,41 @@ #endif /* Some color escape codes for pretty log messages */ -#define GRY(str) "\e[30m" str "\e[0m" /**< Print str in gray */ -#define RED(str) "\e[31m" str "\e[0m" /**< Print str in red */ -#define GRN(str) "\e[32m" str "\e[0m" /**< Print str in green */ -#define YEL(str) "\e[33m" str "\e[0m" /**< Print str in yellow */ -#define BLU(str) "\e[34m" str "\e[0m" /**< Print str in blue */ -#define MAG(str) "\e[35m" str "\e[0m" /**< Print str in magenta */ -#define CYN(str) "\e[36m" str "\e[0m" /**< Print str in cyan */ -#define WHT(str) "\e[37m" str "\e[0m" /**< Print str in white */ -#define BLD(str) "\e[1m" str "\e[0m" /**< Print str in bold */ +#ifndef ENABLE_OPAL_ASYNC + #define GRY(str) "\e[30m" str "\e[0m" /**< Print str in gray */ + #define RED(str) "\e[31m" str "\e[0m" /**< Print str in red */ + #define GRN(str) "\e[32m" str "\e[0m" /**< Print str in green */ + #define YEL(str) "\e[33m" str "\e[0m" /**< Print str in yellow */ + #define BLU(str) "\e[34m" str "\e[0m" /**< Print str in blue */ + #define MAG(str) "\e[35m" str "\e[0m" /**< Print str in magenta */ + #define CYN(str) "\e[36m" str "\e[0m" /**< Print str in cyan */ + #define WHT(str) "\e[37m" str "\e[0m" /**< Print str in white */ + #define BLD(str) "\e[1m" str "\e[0m" /**< Print str in bold */ -#define GFX(chr) "\e(0" chr "\e(B" -#define UP(n) "\e[" ## n ## "A" -#define DOWN(n) "\e[" ## n ## "B" -#define RIGHT(n) "\e[" ## n ## "C" -#define LEFT(n) "\e[" ## n ## "D" + #define GFX(chr) "\e(0" chr "\e(B" + #define UP(n) "\e[" ## n ## "A" + #define DOWN(n) "\e[" ## n ## "B" + #define RIGHT(n) "\e[" ## n ## "C" + #define LEFT(n) "\e[" ## n ## "D" +#else + #define GRY(str) str + #define RED(str) str + #define GRN(str) str + #define YEL(str) str + #define BLU(str) str + #define MAG(str) str + #define CYN(str) str + #define WHT(str) str + #define BLD(str) str -#define ARRAY_LEN(a) ( sizeof a / sizeof a[0] ) + #define GFX(chr) " " + #define UP(n) "" + #define DOWN(n) "" + #define RIGHT(n) "" + #define LEFT(n) "" +#endif + +#define ARRAY_LEN(a) ( sizeof (a) / sizeof (a)[0] ) #define SWAP(a, b) do { \ __typeof__(a) tmp = a; \ diff --git a/server/src/cfg.c b/server/src/cfg.c index 3060b3a56..632ce69b8 100644 --- a/server/src/cfg.c +++ b/server/src/cfg.c @@ -27,19 +27,16 @@ int config_parse(const char *filename, config_t *cfg, struct settings *set, { config_set_auto_convert(cfg, 1); - FILE *file = (strcmp("-", filename)) ? fopen(filename, "r") : stdin; - if (!file) - error("Failed to open configuration file: %s", filename); + int ret = strcmp("-", filename) ? config_read_file(cfg, filename) + : config_read(cfg, stdin); - if (!config_read(cfg, file)) + if (ret != CONFIG_TRUE) error("Failed to parse configuration: %s in %s:%d", - config_error_text(cfg), filename, + config_error_text(cfg), + config_error_file(cfg) ? config_error_file(cfg) : filename, config_error_line(cfg) ); - - if (file != stdin) - fclose(file); - + config_setting_t *cfg_root = config_root_setting(cfg); /* Parse global settings */ @@ -74,7 +71,7 @@ int config_parse(const char *filename, config_t *cfg, struct settings *set, } } - return CONFIG_TRUE; + return 0; } int config_parse_global(config_setting_t *cfg, struct settings *set) @@ -88,7 +85,7 @@ int config_parse_global(config_setting_t *cfg, struct settings *set) set->cfg = cfg; - return CONFIG_TRUE; + return 0; } int config_parse_path(config_setting_t *cfg, @@ -108,7 +105,7 @@ int config_parse_path(config_setting_t *cfg, in = config_setting_get_string(cfg_in); p->in = node_lookup_name(in, *nodes); if (!p->in) - cerror(cfg_in, "Invalid input node '%s", in); + cerror(cfg_in, "Invalid input node '%s'", in); /* Output node(s) */ struct config_setting_t *cfg_out = config_setting_get_member(cfg, "out"); @@ -257,7 +254,8 @@ int config_parse_node(config_setting_t *cfg, struct node **nodes) ret = n->vt->parse(cfg, n); - list_add(*nodes, n); + if (!ret) + list_add(*nodes, n); return ret; } @@ -268,7 +266,7 @@ extern struct opal_global *og; int config_parse_opal(config_setting_t *cfg, struct node *n) { if (!og) { - warn("Skipping this node, because this server is not running as an OPAL Async process!"); + warn("Skipping node '%s', because this server is not running as an OPAL Async process!", n->name); return -1; } @@ -279,7 +277,7 @@ int config_parse_opal(config_setting_t *cfg, struct node *n) memset(o, 0, sizeof(struct opal)); config_setting_lookup_int(cfg, "send_id", &o->send_id); - config_setting_lookup_int(cfg, "recv_id", &o->send_id); + config_setting_lookup_int(cfg, "recv_id", &o->recv_id); config_setting_lookup_bool(cfg, "reply", &o->reply); /* Search for valid send and recv ids */ @@ -292,7 +290,7 @@ int config_parse_opal(config_setting_t *cfg, struct node *n) if (!sfound) cerror(config_setting_get_member(cfg, "send_id"), "Invalid send_id '%u' for node '%s'", o->send_id, n->name); if (!rfound) - cerror(config_setting_get_member(cfg, "send_id"), "Invalid send_id '%u' for node '%s'", o->send_id, n->name); + cerror(config_setting_get_member(cfg, "recv_id"), "Invalid recv_id '%u' for node '%s'", o->recv_id, n->name); n->opal = o; n->opal->global = og; @@ -340,7 +338,7 @@ int config_parse_socket(config_setting_t *cfg, struct node *n) n->socket = s; - return CONFIG_TRUE; + return 0; } int config_parse_netem(config_setting_t *cfg, struct netem *em) @@ -362,5 +360,5 @@ int config_parse_netem(config_setting_t *cfg, struct netem *em) /** @todo Validate netem config values */ - return CONFIG_TRUE; + return 0; } diff --git a/server/src/opal.c b/server/src/opal.c index 44fb41a4a..24bc21d10 100644 --- a/server/src/opal.c +++ b/server/src/opal.c @@ -22,11 +22,7 @@ int opal_init(int argc, char *argv[]) if (argc != 4) return -1; - struct opal_global *g = (struct opal_global *) malloc(sizeof(struct opal_global)); - if (!g) - error("Failed to allocate memory for global OPAL settings"); - - memset(g, 0, sizeof(struct opal_global)); + struct opal_global *g = (struct opal_global *) alloc(sizeof(struct opal_global)); pthread_mutex_init(&g->lock, NULL); @@ -48,20 +44,20 @@ int opal_init(int argc, char *argv[]) /* Get list of Send and RecvIDs */ if ((err = OpalGetNbAsyncSendIcon(&g->send_icons)) != EOK) error("Failed to get number of send blocks (%d)", err); - if ((err = OpalGetNbAsyncRecvIcon(&g->recv_icons)) != EOK); + if ((err = OpalGetNbAsyncRecvIcon(&g->recv_icons)) != EOK) error("Failed to get number of recv blocks (%d)", err); - g->send_ids = (int *) malloc(g->send_icons * sizeof(int)); - g->recv_ids = (int *) malloc(g->recv_icons * sizeof(int)); - if (!g->send_ids || !g->recv_ids) - error("Failed to allocate memory for OPAL AsyncApi ID list."); + g->send_ids = alloc(g->send_icons * sizeof(int)); + g->recv_ids = alloc(g->recv_icons * sizeof(int)); - if ((err = OpalGetAsyncSendIDList(g->send_ids, g->send_icons)) != EOK) + if ((err = OpalGetAsyncSendIDList(g->send_ids, g->send_icons * sizeof(int))) != EOK) error("Failed to get list of send ids (%d)", err); - if ((err = OpalGetAsyncRecvIDList(g->recv_ids, g->recv_icons)) != EOK) + if ((err = OpalGetAsyncRecvIDList(g->recv_ids, g->recv_icons * sizeof(int))) != EOK) error("Failed to get list of recv ids (%d)", err); - info("Started as OPAL async process:"); + info("Started as OPAL Asynchronous process"); + info("This is Simulator2Simulator Server (S2SS) %s (built on %s, %s, debug=%d)", + VERSION, __DATE__, __TIME__, _debug); opal_print_global(g); og = g; @@ -73,18 +69,22 @@ int opal_deinit() { int err; - if (og) { - if ((err = OpalCloseAsyncMem(og->async_shmem_size, og->async_shmem_name)) != EOK) - error("Failed to close shared memory area (%d)", err); - if ((err = OpalSystemCtrl_UnRegister(og->print_shmem_name)) != EOK) - error("Failed to close shared memory for system control (%d)", err); + if (!og) + return 0; + + if ((err = OpalCloseAsyncMem(og->async_shmem_size, og->async_shmem_name)) != EOK) + error("Failed to close shared memory area (%d)", err); + + debug(4, "Closing OPAL shared memory mapping"); + + if ((err = OpalSystemCtrl_UnRegister(og->print_shmem_name)) != EOK) + error("Failed to close shared memory for system control (%d)", err); - free(og->send_ids); - free(og->recv_ids); - free(og); + free(og->send_ids); + free(og->recv_ids); + free(og); - og = NULL; - } + og = NULL; return 0; } @@ -99,15 +99,15 @@ int opal_print_global(struct opal_global *g) for (int i=0; irecv_icons; i++) strap(rbuf, sizeof(rbuf), "%u ", g->recv_ids[i]); - debug(4, "Controller ID: %u", g->params.controllerID); - debug(4, "Send Blocks: %s", sbuf); - debug(4, "Receive Blocks: %s", rbuf); + debug(2, "Controller ID: %u", g->params.controllerID); + debug(2, "Send Blocks: %s", sbuf); + debug(2, "Receive Blocks: %s", rbuf); - debug(4, "Control Block Parameters:"); + debug(2, "Control Block Parameters:"); for (int i=0; iparams.FloatParam[i]); + debug(2, "FloatParam[]%u] = %f", i, g->params.FloatParam[i]); for (int i=0; iparams.StringParam[i]); + debug(2, "StringParam[%u] = %s", i, g->params.StringParam[i]); return 0; } @@ -151,9 +151,9 @@ int opal_read(struct node *n, struct msg *m) do { if ((ret = OpalWaitForAsyncSendRequest(&id)) != EOK) { state = OpalGetAsyncModelState(); - if ((state != STATE_RESET) && (state != STATE_STOP)) { - OpalSetAsyncSendIconError(ret, id); - info("OpalWaitForAsyncSendRequest(), errno %d", ret); + if ((state == STATE_RESET) || (state == STATE_STOP)) { + info("OpalGetAsyncModelState(): Model stopped or resetted!"); + exit(0); } return -1; // FIXME: correct return value @@ -193,8 +193,10 @@ int opal_read(struct node *n, struct msg *m) /* Before continuing, we make sure that the real-time model * has not been stopped. If it has, we quit. */ state = OpalGetAsyncModelState(); - if ((state == STATE_RESET) || (state == STATE_STOP)) - error("OpalGetAsyncModelState(): Model stopped or resetted!"); // TODO: fixme + if ((state == STATE_RESET) || (state == STATE_STOP)) { + info("OpalGetAsyncModelState(): Model stopped or resetted!"); + exit(0); + } return 0; } @@ -209,8 +211,10 @@ int opal_write(struct node *n, struct msg *m) double data[MSG_VALUES] = { NAN }; state = OpalGetAsyncModelState(); - if ((state == STATE_RESET) || (state == STATE_STOP)) - return -1; + if ((state == STATE_RESET) || (state == STATE_STOP)) { + info("OpalGetAsyncModelState(): Model stopped or resetted!"); + exit(0); + } OpalSetAsyncRecvIconStatus(m->sequence, o->recv_id); /* Set the Status to the message ID */ OpalSetAsyncRecvIconError(0, o->recv_id); /* Set the Error to 0 */ diff --git a/server/src/server.c b/server/src/server.c index 9513ca02e..68d5116b6 100644 --- a/server/src/server.c +++ b/server/src/server.c @@ -56,6 +56,10 @@ static void quit() } /** @todo Free nodes */ + +#ifdef ENABLE_OPAL_ASYNC + opal_deinit(); +#endif config_destroy(&config); @@ -71,11 +75,11 @@ void realtime_init() else info("Server is running on a realtime patched kernel"); - /* Use FIFO scheduler with realtime priority */ + /* Use FIFO scheduler with real time priority */ if (settings.priority) { struct sched_param param = { .sched_priority = settings.priority }; if (sched_setscheduler(0, SCHED_FIFO, ¶m)) - serror("Failed to set realtime priority"); + serror("Failed to set real time priority"); else debug(3, "Set task priority to %u", settings.priority); } @@ -130,10 +134,8 @@ int main(int argc, char *argv[]) usage(argv[0]); epoch_reset(); - info("This is Simulator2Simulator Server (S2SS) %s (built on %s, %s)", - BLD(YEL(VERSION)), BLD(MAG(__DATE__)), BLD(MAG(__TIME__))); - - char *configfile = argv[1]; + info("This is Simulator2Simulator Server (S2SS) %s (built on %s, %s, debug=%d)", + BLD(YEL(VERSION)), BLD(MAG(__DATE__)), BLD(MAG(__TIME__)), _debug); /* Check priviledges */ if (getuid() != 0) @@ -150,6 +152,11 @@ int main(int argc, char *argv[]) #ifdef ENABLE_OPAL_ASYNC /* Check if called as asynchronous process from RT-LAB */ opal_init(argc, argv); + + char *configfile = "opal-shmem.conf"; +#else + + char *configfile = argv[1]; #endif /* Parse configuration and create nodes/paths */ diff --git a/server/src/socket.c b/server/src/socket.c index bfab7155e..0d9271a29 100644 --- a/server/src/socket.c +++ b/server/src/socket.c @@ -230,7 +230,7 @@ int socket_parse_addr(const char *addr, struct sockaddr *sa, enum node_type type else { /* Format: "192.168.0.10:12001" */ struct addrinfo hint = { .ai_flags = flags, - .ai_family = AF_UNSPEC + .ai_family = AF_INET }; /* Split string */ diff --git a/server/src/test.c b/server/src/test.c index 594732f36..d7a40021f 100644 --- a/server/src/test.c +++ b/server/src/test.c @@ -48,7 +48,7 @@ double high = 2e-4; /** Histogram resolution. */ double res = 1e-5; -#define CLOCK_ID CLOCK_MONOTONIC_RAW +#define CLOCK_ID CLOCK_MONOTONIC /* Prototypes */ void test_rtt(); diff --git a/server/src/utils.c b/server/src/utils.c index cfdbf0486..42798e420 100644 --- a/server/src/utils.c +++ b/server/src/utils.c @@ -16,6 +16,7 @@ #include #ifdef ENABLE_OPAL_ASYNC +#define RTLAB #include #endif @@ -89,10 +90,9 @@ void print(enum log_level lvl, const char *fmt, ...) /* Output */ #ifdef ENABLE_OPAL_ASYNC - OpalPrint("%s\n", buf); -#else - fprintf(stderr, "%s\n", buf); + OpalPrint("S2SS: %s\n", buf); #endif + fprintf(stderr, "%s\n", buf); } cpu_set_t to_cpu_set(int set)