From 40badbcf0d8908ad5050f1455af96a5df395960a Mon Sep 17 00:00:00 2001 From: Hajime Tazaki Date: Fri, 10 Feb 2017 08:57:44 +0900 Subject: [PATCH] lkl: add LKL_HIJACK_SYSCTL to configure sysctl values This variable can be used like this: $ LKL_HIJACK_SYSCTL="net.ipv4.tcp_wmem=4096 87380 2147483647" \ ./bin/lkl-hijack.sh sleep 1000 Signed-off-by: Hajime Tazaki --- Documentation/lkl.txt | 8 ++++++ tools/lkl/include/lkl.h | 19 +++++++++++++ tools/lkl/lib/hijack/init.c | 3 ++ tools/lkl/lib/utils.c | 56 +++++++++++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+) diff --git a/Documentation/lkl.txt b/Documentation/lkl.txt index 54e8ab5f854ddd3..074b0ae951c3a4d 100644 --- a/Documentation/lkl.txt +++ b/Documentation/lkl.txt @@ -238,6 +238,14 @@ are the list of those variable for your environment. ``` $ LKL_HIJACK_OFFLOAD=0x8002 lkl-hijack.sh ./netserver -D -f ``` +* LKL_HIJACK_SYSCTL + + Configure sysctl values of the booted kernel via the hijack library. Multiple + entries can be specified. +``` + $ LKL_HIJACK_SYSCTL="net.ipv4.tcp_wmem=4096 87380 2147483647" + ./bin/lkl-hijack.sh ip address show +``` FAQ === diff --git a/tools/lkl/include/lkl.h b/tools/lkl/include/lkl.h index c831facaedea645..16a2caa7f5b1f3a 100644 --- a/tools/lkl/include/lkl.h +++ b/tools/lkl/include/lkl.h @@ -15,6 +15,10 @@ extern "C" { #undef class #endif +#if defined(__MINGW32__) +#define strtok_r strtok_s +#endif + #if __LKL__BITS_PER_LONG == 64 #define lkl_sys_stat lkl_sys_newstat #define lkl_sys_lstat lkl_sys_newlstat @@ -479,6 +483,21 @@ int lkl_qdisc_add(int ifindex, char *root, char *type); */ void lkl_qdisc_parse_add(int ifindex, char *entries); +/** + * lkl_sysctl - write a sysctl value + * + * @path - the path to an sysctl entry (e.g., "net.ipv4.tcp_wmem"); + * @value - the value of the sysctl (e.g., "4096 87380 2147483647") + */ +int lkl_sysctl(const char *path, const char *value); + +/** + * lkl_sysctl_parse_write - Configure sysctl parameters with strings + * + * @sysctls - Configure sysctl parameters as the form of "key=value;..." + */ +void lkl_sysctl_parse_write(const char *sysctls); + #ifdef __cplusplus } #endif diff --git a/tools/lkl/lib/hijack/init.c b/tools/lkl/lib/hijack/init.c index e3d6181f99ea8d9..c03ee4665df5785 100644 --- a/tools/lkl/lib/hijack/init.c +++ b/tools/lkl/lib/hijack/init.c @@ -220,6 +220,7 @@ hijack_init(void) char *offload1 = getenv("LKL_HIJACK_OFFLOAD"); int offload = 0; char boot_cmdline[256] = "\0"; + char *sysctls = getenv("LKL_HIJACK_SYSCTL"); memset(&nd_args, 0, sizeof(struct lkl_netdev_args)); if (!debug) { @@ -436,6 +437,8 @@ hijack_init(void) if (nd_ifindex >= 0 && qdisc_entries) lkl_qdisc_parse_add(nd_ifindex, qdisc_entries); + if (sysctls) + lkl_sysctl_parse_write(sysctls); } void __attribute__((destructor)) diff --git a/tools/lkl/lib/utils.c b/tools/lkl/lib/utils.c index b4631e092852330..af69b1511356d18 100644 --- a/tools/lkl/lib/utils.c +++ b/tools/lkl/lib/utils.c @@ -1,5 +1,6 @@ #include #include +#include #include static const char * const lkl_err_strings[] = { @@ -205,3 +206,58 @@ void lkl_bug(const char *fmt, ...) lkl_host_ops.panic(); } + +int lkl_sysctl(const char *path, const char *value) +{ + int ret; + int fd; + char *delim, *p; + char full_path[256]; + + lkl_mount_fs("proc"); + + snprintf(full_path, sizeof(full_path), "/proc/sys/%s", path); + p = full_path; + while ((delim = strstr(p, "."))) { + *delim = '/'; + p = delim + 1; + } + + fd = lkl_sys_open(full_path, LKL_O_WRONLY | LKL_O_CREAT, 0); + if (fd < 0) { + lkl_printf("lkl_sys_open %s: %s\n", + full_path, lkl_strerror(fd)); + return -1; + } + ret = lkl_sys_write(fd, value, strlen(value)); + if (ret < 0) { + lkl_printf("lkl_sys_write %s: %s\n", + full_path, lkl_strerror(fd)); + } + + lkl_sys_close(fd); + + return 0; +} + +/* Configure sysctl parameters as the form of "key=value;key=value;..." */ +void lkl_sysctl_parse_write(const char *sysctls) +{ + char *saveptr = NULL, *token = NULL; + char *key = NULL, *value = NULL; + char strings[256]; + int ret = 0; + + strcpy(strings, sysctls); + for (token = strtok_r(strings, ";", &saveptr); token; + token = strtok_r(NULL, ";", &saveptr)) { + key = strtok(token, "="); + value = strtok(NULL, "="); + ret = lkl_sysctl(key, value); + if (ret) { + lkl_printf("Failed to configure sysctl entries: %s\n", + lkl_strerror(ret)); + return; + } + } +}