diff --git a/Makefile b/Makefile index 5dc3a0078..d0a384176 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ TARGETS = server pipe signal test LIBS = libs2ss.so # Object files for libs2ss -LIB_OBJS = msg.o node.o checks.o list.o log.o utils.o cfg.o path.o hooks.o hist.o timing.o pool.o +LIB_OBJS = msg.o node.o linux.o list.o log.o linux.o utils.o cfg.o path.o hooks.o hist.o timing.o pool.o # Source directories VPATH = src lib diff --git a/include/checks.h b/include/linux.h similarity index 70% rename from include/checks.h rename to include/linux.h index b56629e83..64e5bde77 100644 --- a/include/checks.h +++ b/include/linux.h @@ -1,4 +1,4 @@ -/** Check system requirements. +/** Linux kernel related procedures * * @author Steffen Vogel * @copyright 2014-2016, Institute for Automation of Complex Power Systems, EONERC @@ -6,8 +6,8 @@ * Unauthorized copying of this file, via any medium is strictly prohibited. *********************************************************************************/ -#ifndef _CHECKS_H_ -#define _CHECKS_H_ +#ifndef _LINUX_H_ +#define _LINUX_H_ /** Checks for realtime (PREEMPT_RT) patched kernel. * @@ -16,7 +16,7 @@ * @retval 0 Kernel is patched. * @reval <>0 Kernel is not patched. */ -int check_kernel_rt(); +int kernel_is_rt(); /** Check if kernel command line contains "isolcpus=" option. * @@ -25,14 +25,14 @@ int check_kernel_rt(); * @retval 0 Kernel has isolated cores. * @reval <>0 Kernel has no isolated cores. */ -int check_kernel_cmdline(); +int kernel_has_cmdline(const char *substr); /** Check if kernel is version is sufficient * * @retval 0 Kernel version is sufficient. * @reval <>0 Kernel version is not sufficient. */ -int check_kernel_version(); +int kernel_has_version(int maj, int min); /** Checks if a kernel module is loaded * @@ -40,14 +40,12 @@ int check_kernel_version(); * @retval 0 Module is loaded. * @reval <>0 Module is not loaded. */ -int check_kernel_module(char *module); +int kernel_module_loaded(const char *module); -/** Check if program is running with super user (root) privileges. - * - * - * @retval 0 Permissions are sufficient. - * @reval <>0 Permissions are not sufficient. - */ -int check_root(); +/** Load kernel module via modprobe */ +int kernel_module_load(const char *module); -#endif /* _CHECKS_H_ */ +/** Set parameter of loaded kernel module */ +int kernel_module_set_param(const char *module, const char *param, const char *value); + +#endif /* _LINUX_H_ */ diff --git a/lib/gtfpga.c b/lib/gtfpga.c index f200af964..c456c77b5 100644 --- a/lib/gtfpga.c +++ b/lib/gtfpga.c @@ -18,7 +18,8 @@ #include "config.h" #include "utils.h" #include "timing.h" -#include "checks.h" +#include "utils.h" +#include "linux.h" static struct pci_access *pacc; @@ -32,7 +33,7 @@ static void gtfpga_debug(char *msg, ...) { int gtfpga_init(int argc, char * argv[], config_setting_t *cfg) { - if (check_root()) + if (getuid() != 0) error("The gtfpga node-type requires superuser privileges!"); pacc = pci_alloc(); /* Get the pci_access structure */ @@ -119,7 +120,7 @@ static int gtfpga_load_driver(struct pci_dev *d) FILE *f; char slot[16]; - if (check_kernel_module("uio_pci_generic")) + if (kernel_module_load("uio_pci_generic")) error("Missing kernel module: uio_pci_generic"); /* Prepare slot identifier */ @@ -127,7 +128,7 @@ static int gtfpga_load_driver(struct pci_dev *d) d->domain, d->bus, d->dev, d->func); /* Add new ID to uio_pci_generic */ - f = fopen(SYSFS_PATH "/bus/pci/drivers/uio_pci_generic/new_id", "w"); + f = fopen(SYSFS_PATH "/drivers/uio_pci_generic/new_id", "w"); if (!f) serror("Failed to add PCI id to uio_pci_generic driver"); diff --git a/lib/if.c b/lib/if.c index 25830270a..11df748ce 100644 --- a/lib/if.c +++ b/lib/if.c @@ -21,7 +21,7 @@ #include "nl.h" #include "socket.h" #include "utils.h" -#include "checks.h" +#include "linux.h" struct interface * if_create(struct rtnl_link *link) { @@ -72,11 +72,11 @@ int if_start(struct interface *i, int affinity) return 0; /* Check if all kernel modules are loaded */ - if (check_kernel_module("sch_prio")) + if (kernel_module_load("sch_prio")) error("Missing kernel module: sch_prio"); - if (check_kernel_module("sch_netem")) + if (kernel_module_load("sch_netem")) error("Missing kernel module: sch_netem"); - if (check_kernel_module("cls_fw")) + if (kernel_module_load("cls_fw")) error("Missing kernel module: cls_fw"); /* Replace root qdisc */ diff --git a/lib/checks.c b/lib/linux.c similarity index 51% rename from lib/checks.c rename to lib/linux.c index cefdbac2b..e6f495426 100644 --- a/lib/checks.c +++ b/lib/linux.c @@ -1,4 +1,4 @@ -/** Check system requirements. +/** kernel related procedures. * * @author Steffen Vogel * @copyright 2014-2016, Institute for Automation of Complex Power Systems, EONERC @@ -6,54 +6,67 @@ * Unauthorized copying of this file, via any medium is strictly prohibited. *********************************************************************************/ -#include #include #include #include #include #include + #include #include #include +#include +#include #include "utils.h" #include "config.h" +#include "linux.h" -int check_kernel_version() +int kernel_module_set_param(const char *module, const char *param, const char *value) { - struct utsname uts; - struct version current; - struct version required = { KERNEL_VERSION_MAJ, KERNEL_VERSION_MIN }; + FILE *f; + char fn[256]; - if (uname(&uts) < 0) - return -1; + snprintf(fn, sizeof(fn), "%s/module/%s/parameters/%s", SYSFS_PATH, module, param); + f = fopen(fn, "w"); + if (f) { + debug(5, "Set parameter %s of kernel module %s to %s", module, param, value); + fprintf(f, "%s", value); + fclose(f); + } + else + serror("Failed set parameter %s for kernel module %s to %s", module, param, value); - if (version_parse(uts.release, ¤t)) - return -1; - - return version_compare(¤t, &required) < 0; + return 0; } -int check_kernel_rt() +int kernel_module_load(const char *module) { - return access(SYSFS_PATH "/kernel/realtime", R_OK); + int ret; + + ret = kernel_module_loaded(module); + if (!ret) { + info("Kernel module %s already loaded...", module); + return 0; + } + + pid_t pid = fork(); + switch (pid) { + case -1: // error + return -1; + + case 0: // child + execlp("modprobe", "modprobe", module, (char *) 0); + _exit(-1); // exec never returns + + default: + waitpid(pid, &ret, 0); + } + + return ret; } -int check_kernel_cmdline() -{ - char cmd[512]; - - FILE *f = fopen(PROCFS_PATH "/cmdline", "r"); - if (!f) - return -1; - - if (!fgets(cmd, sizeof(cmd), f)) - return -1; - - return strstr(cmd, "isolcpus=") ? 0 : -1; -} - -int check_kernel_module(char *module) +int kernel_module_loaded(const char *module) { FILE *f; int ret = -1; @@ -77,7 +90,37 @@ int check_kernel_module(char *module) return ret; } -int check_root() + +int kernel_has_version(int maj, int min) { - return getuid(); + struct utsname uts; + struct version current; + struct version required = { maj, min }; + + if (uname(&uts) < 0) + return -1; + + if (version_parse(uts.release, ¤t)) + return -1; + + return version_compare(¤t, &required) < 0; } + +int kernel_is_rt() +{ + return access(SYSFS_PATH "/kernel/realtime", R_OK); +} + +int kernel_has_cmdline(const char *substr) +{ + char cmd[512]; + + FILE *f = fopen(PROCFS_PATH "/cmdline", "r"); + if (!f) + return -1; + + if (!fgets(cmd, sizeof(cmd), f)) + return -1; + + return strstr(cmd, substr) ? 0 : -1; +} \ No newline at end of file diff --git a/lib/socket.c b/lib/socket.c index 312768f61..fc294ea6d 100644 --- a/lib/socket.c +++ b/lib/socket.c @@ -30,7 +30,6 @@ #include "config.h" #include "utils.h" #include "socket.h" -#include "checks.h" #include "pool.h" /* Forward declartions */ @@ -41,7 +40,7 @@ struct list interfaces; int socket_init(int argc, char * argv[], config_setting_t *cfg) { - if (check_root()) + if (getuid() != 0) error("The 'socket' node-type requires superuser privileges!"); nl_init(); /* Fill link cache */ diff --git a/src/server.c b/src/server.c index 4a1518b16..4fed6eee5 100644 --- a/src/server.c +++ b/src/server.c @@ -19,7 +19,7 @@ #include "cfg.h" #include "path.h" #include "node.h" -#include "checks.h" +#include "linux.h" #ifdef ENABLE_OPAL_ASYNC #include "opal.h" @@ -60,9 +60,9 @@ static void quit() static void realtime_init() { INDENT - if (check_kernel_cmdline()) + if (kernel_has_cmdline("isolcpus")) warn("You should reserve some cores for the server (see 'isolcpus')"); - if (check_kernel_rt()) + if (kernel_is_rt()) warn("We recommend to use an PREEMPT_RT patched kernel!"); /* Use FIFO scheduler with real time priority */ @@ -138,7 +138,7 @@ int main(int argc, char *argv[]) BLD(MAG(__DATE__)), BLD(MAG(__TIME__))); /* Checks system requirements*/ - if (check_kernel_version()) + if (kernel_has_version(KERNEL_VERSION_MAJ, KERNEL_VERSION_MIN)) error("Your kernel version is to old: required >= %u.%u", KERNEL_VERSION_MAJ, KERNEL_VERSION_MIN); /* Initialize lists */