diff --git a/Documentation/lkl.txt b/Documentation/lkl.txt index 631a8831f6641d..2c9d3f327ec104 100644 --- a/Documentation/lkl.txt +++ b/Documentation/lkl.txt @@ -232,6 +232,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 a4fb9f2920cc22..e3d16a80834548 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 @@ -461,6 +465,21 @@ int lkl_if_wait_ipv6_dad(int ifindex, void *addr); */ int lkl_set_fd_limit(unsigned int fd_limit); +/** + * 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(char *sysctls); + #ifdef __cplusplus } #endif diff --git a/tools/lkl/lib/hijack/init.c b/tools/lkl/lib/hijack/init.c index d003d27296d747..5f48e27b7f2894 100644 --- a/tools/lkl/lib/hijack/init.c +++ b/tools/lkl/lib/hijack/init.c @@ -219,6 +219,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) { @@ -429,6 +430,9 @@ hijack_init(void) if (mount) mount_cmds_exec(mount, lkl_mount_fs); + if (sysctls) + lkl_sysctl_parse_write(sysctls); + if (nd_ifindex >=0 && neigh_entries) add_neighbor(nd_ifindex, neigh_entries); } diff --git a/tools/lkl/lib/utils.c b/tools/lkl/lib/utils.c index b4631e09285233..c9e7a3aa1d3f52 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,56 @@ 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(char *sysctls) +{ + char *saveptr = NULL, *token = NULL; + char *key = NULL, *value = NULL; + int ret = 0; + + for (token = strtok_r(sysctls, ";", &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; + } + } +}