From 842d02fe56c8dd8eaf27e7701c3c3ccdd68d4744 Mon Sep 17 00:00:00 2001 From: Motomu Utsumi Date: Sat, 14 Oct 2017 23:23:20 +0900 Subject: [PATCH] lkl: Support json configuration and multiple interfaces This change allows user to configure lkl with json file. This change still supports configuration using environment variable. Also allows lkl to have multiple interfaces. Reviewed-by: Hajime Tazaki Signed-off-by: Motomu Utsumi --- Documentation/lkl.txt | 336 +++++++++++++++++------ tools/lkl/lib/Build | 2 + tools/lkl/lib/config.c | 390 +++++++++++++++++++++++++++ tools/lkl/lib/config.h | 53 ++++ tools/lkl/lib/hijack/init.c | 475 +++++++++++++++++++-------------- tools/lkl/tests/hijack-test.sh | 472 ++++++++++++++++++++++++++------ tools/lkl/tests/run_netperf.sh | 28 +- 7 files changed, 1388 insertions(+), 368 deletions(-) create mode 100644 tools/lkl/lib/config.c create mode 100644 tools/lkl/lib/config.h diff --git a/Documentation/lkl.txt b/Documentation/lkl.txt index 221ea8905f02aa..34517e68209533 100644 --- a/Documentation/lkl.txt +++ b/Documentation/lkl.txt @@ -134,129 +134,309 @@ LKL hijack library LKL hijack library (liblkl-hijack.so) is used to replace system calls used by an application on the fly so that the application can use LKL instead of the kernel -of host operating system. LD_PRELOAD is used to dynamically override system calls -with this library when you execute a program. +of host operating system. LD_PRELOAD is used to dynamically override system +calls with this library when you execute a program. You can usually use this library via a wrapper script. $ cd tools/lkl $ ./bin/lkl-hijack.sh ip address show -There are environmental variables to configure the behavior of LKL. The followings -are the list of those variable for your environment. +In order to configure the behavior of LKL, a json file can be used. You can +specify json file with environmental variables (LKL_HIJACK_CONFIG_FILE). If +there is nothing specified, LKL tries to find with the name 'lkl-hijack.json' +for the configuration file. You can also use the old-style configuration with +environmental variables (e.g., LKL_HIJACK_NET_IFTYPE) but those are overridden +if a json file is specified. -* LKL_HIJACK_NET_IFTYPE - - The interface type in host operating system to connect to LKL. - The following example specifies a tap interface. ``` - $ LKL_HIJACK_NET_IFTYPE=tap LKL_HIJACK_NET_IFPARAMS=tap0 lkl-hijack.sh ip address show + $ cat conf.json + { + "gateway":"192.168.0.1", + "gateway6":"2001:db8:0:f101::1", + "debug":"1", + "singlecpu":"1", + "sysctl":"net.ipv4.tcp_wmem=4096 87380 2147483647", + "boot_cmdline":"ip=dhcp", + "interfaces":[ + { + "mac":"12:34:56:78:9a:bc", + "type":"tap", + "param":"tap7", + "ip":"192.168.0.2", + "masklen":"24", + "ifgateway":"192.168.0.1", + "ipv6":"2001:db8:0:f101::2", + "masklen6":"64", + "ifgateway6":"2001:db8:0:f101::1", + "offload":"0xc803" + }, + { + "mac":"12:34:56:78:9a:bd", + "type":"tap", + "param":"tap77", + "ip":"192.168.1.2", + "masklen":"24", + "ifgateway":"192.168.1.1", + "ipv6":"2001:db8:0:f102::2", + "masklen6":"64", + "ifgateway6":"2001:db8:0:f102::1", + "offload":"0xc803" + } + ] + } + $ LKL_HIJACK_CONFIG_FILE="conf.json" lkl-hijack.sh ip addr s ``` -* LKL_HIJACK_NET_IFPARAMS - Additional configuration parameters for the interface specified by LKL_HIJACK_NET_IFTYPE. - The parameters depend on the interface type (LKL_HIJACK_NET_IFTYPE). -``` - $ LKL_HIJACK_NET_IFTYPE=tap LKL_HIJACK_NET_IFPARAMS=tap0 lkl-hijack.sh ip address show -``` -* LKL_HIJACK_NET_IP - - the IP address of the interface specified by LKL_HIJACK_NET_TAP. -``` - $ LKL_HIJACK_NET_IP=198.51.100.5 lkl-hijack.sh ip address show -``` +The following are the list of keys to describe a JSON file. - If you want to use DHCP for the IP address assignment, use - LKL_HIJACK_BOOT_CMDLINE with "ip=dhcp" option. -``` - $ LKL_HIJACK_BOOT_CMDLINE="ip=dhcp" LKL_HIJACK_NET_IFTYPE=tap \ - LKL_HIJACK_NET_IFPARAMS=tap0 lkl-hijack.sh ip address -``` +* IPv4 gateway address -* LKL_HIJACK_NET_NETMASK_LEN + key: "gateway" + value type: string - the network mask length of the interface specified by LKL_HIJACK_NET_TAP. + the gateway IPv4 address of LKL network stack. ``` - $ LKL_HIJACK_NET_IP=198.51.100.5 LKL_HIJACK_NET_NETMASK_LEN=24 lkl-hijack.sh ip address show + "gateway":"192.168.0.1" ``` -* LKL_HIJACK_NET_MAC - the MAC address of the interface specified by LKL_HIJACK_NET_TAP. -``` - $ LKL_HIJACK_NET_MAC="aa:bb:cc:dd:ee:ff" lkl-hijack.sh ip address show -``` -* LKL_HIJACK_NET_GATEWAY +* IPv6 gateway address - the gateway IP address of LKL network stack. -``` - $ LKL_HIJACK_NET_GATEWAY=198.51.100.5 lkl-hijack.sh ip address show -``` -* LKL_HIJACK_NET_MTU + key: "gateway6" + value type: string - the MTU size of the interface specified by LKL_HIJACK_NET_TAP. + the gateway IPv6 address of LKL network stack. ``` - $ LKL_HIJACK_NET_MTU=1280 lkl-hijack.sh ip address show + "gateway6":"2001:db8:0:f101::1" ``` -* LKL_HIJACK_NET_NEIGHBOR - Add a list of permanent neighbor entries in the form of "ip|mac;ip|mac;...". ipv6 are supported -``` - $ LKL_HIJACK_NET_NEIGHBOR="192.168.13.100|12:34:56:78:9a:bc;2001:db8:0:f101::3|12:34:56:78:9a:be" - lkl-hijack.sh ip neighbor show -``` -* LKL_HIJACK_NET_QDISC +* Debug - Add a qdisc entry in the form of "root|type;root|type;...". -``` - $ LKL_HIJACK_NET_QDISC="root|fq" lkl-hijack.sh tc qdisc -``` -* LKL_HIJACK_DEBUG + key: "debug" + value type: string Setting it causes some debug information (both from the kernel and the LKL library) to be enabled. It is also used as a bit mask to turn on specific debugging facilities. - E.g., setting it to 0x100 ("export LKL_HIJACK_DEBUG=0x100") will cause - the LKL kernel to pause after the hijack'ed app exits. This allows one - to debug or collect info from the LKL kernel before it quits. + E.g., setting it to "0x100" will cause the LKL kernel to pause after + the hijack'ed app exits. This allows one to debug or collect info from + the LKL kernel before it quits. ``` - $ LKL_HIJACK_DEBUG=1 lkl-hijack.sh ip address show + "debug":"1" ``` -* LKL_HIJACK_SINGLE_CPU - Pin LKL kernel threads on to a single host cpu. LKL_HIJACK_SINGLE_CPU=1 pins - only LKL kernel threads while LKL_HIJACK_SINGLE_CPU=2 also pins polling +* Single CPU pinning + + key: "singlecpu" + value type: string + + Pin LKL kernel threads on to a single host cpu. value "1" pins + only LKL kernel threads while value "2" also pins polling threads. ``` - $ LKL_HIJACK_SINGLE_CPU=1 lkl-hijack.sh ip address show + "singlecpu":"1" ``` -* LKL_HIJACK_OFFLOAD - Work as a bit mask to enable selective device offload features. E.g., - to enable "mergeable RX buffer" (LKL_VIRTIO_NET_F_MRG_RXBUF) + - "guest csum" (LKL_VIRTIO_NET_F_GUEST_CSUM) device features, simply set - it to 0x8002. +* SYSCTL - See virtio_net.h for a list of offload features and their bit masks. -``` - $ LKL_HIJACK_OFFLOAD=0x8002 lkl-hijack.sh ./netserver -D -f -``` -* LKL_HIJACK_SYSCTL + key: "sysctl" + value type: string 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 + "sysctl":"net.ipv4.tcp_wmem=4096 87380 2147483647" ``` -* LKL_HIJACK_BOOT_CMDLINE + +* Boot command line + + key: "boot_cmdline" + value type: string Specify the command line to the kernel boot so that change the configuration on a kernel instance. For instance, you can change the memory size with below. ``` - $ LKL_HIJACK_BOOT_CMDLINE="mem=1G" LKL_HIJACK_DEBUG=1 lkl-hijack.sh ip add + "boot_cmdline": "mem=1G" ``` +* Mount + + key: "mount" + value type: string + +``` + "mount": "proc,sysfs" +``` + +* Network Interface Configuration + + key: "interfaces" + value type: array of objects + + This key takes a set of sub-keys to configure a single interface. Each key is defined as follows. + ``` + "interfaces":[{....},{....}] + ``` + + + * Interface type + + key: "type" + value type: string + + The interface type in host operating system to connect to LKL. + The following example specifies a tap interface. + ``` + "type":"tap" + ``` + + * Interface parameter + + key: "param" + value type: string + + Additional configuration parameters for the interface specified by Interface type (type). + The parameters depend on the interface type. + ``` + "type":"tap", + "param":"tap0" + ``` + + * Interface MTU size + + key: "mtu" + value type: string + + the MTU size of the interface. + ``` + "mtu":"1280" + ``` + + * Interface IPv4 address + + key: "ip" + value type: string + + the IPv4 address of the interface. + If you want to use DHCP for the IP address assignment, + use "boot_cmdline" with "ip=dhcp" option. + ``` + "ip":"192.168.0.2" + ``` + ``` + "boot_cmdline":"ip=dhcp" + ``` + + * Interface IPv4 netmask length + + key: "masklen" + value type: string + + the network mask length of the interface. + ``` + "ip":"192.168.0.2", + "masklen":"24" + ``` + + * Interface IPv4 gateway on routing policy table + + key: "ifgateway" + value type: string + + If you specify this parameter, LKL adds routing policy table. + And then LKL creates link local and gateway route on this table. + Table SELECTOR is "from" and PREFIX is address you assigned to this interface. + Table id is 2 * (interface index). + This parameter could be used to configure LKL for mptcp, for example. + + ``` + "ip":"192.168.0.2", + "masklen":"24", + "ifgateway":"192.168.0.1" + ``` + + * Interface IPv6 address + + key: "ipv6" + value type: string + + the IPv6 address of the interface. + ``` + "ipv6":"2001:db8:0:f101::2" + ``` + + * Interface IPv6 netmask length + + key: "masklen6" + value type: string + + the network mask length of the interface. + ``` + "ipv6":"2001:db8:0:f101::2", + "masklen":"64" + ``` + + * Interface IPv6 gateway on routing policy table + + key: "ifgateway6" + value type: string + + If you specify this parameter, LKL adds routing policy table. + And then LKL creates link local and gateway route on this table. + Table SELECTOR is "from" and PREFIX is address you assigned to this interface. + Table id is 2 * (interface index) + 1. + This parameter could be used to configure LKL for mptcp, for example. + ``` + "ipv6":"2001:db8:0:f101::2", + "masklen":"64" + "ifgateway6":"2001:db8:0:f101::1", + ``` + + * Interface MAC address + + key: "mac" + value type: string + + the MAC address of the interface. + ``` + "mac":"12:34:56:78:9a:bc" + ``` + + * Interfac neighbor entries + + key: "neigh" + value type: string + + Add a list of permanent neighbor entries in the form of "ip|mac;ip|mac;...". ipv6 are supported + ``` + "neigh":"192.168.0.1|12:34:56:78:9a:bc;2001:db8:0:f101::1|12:34:56:78:9a:be" + ``` + + * Interface qdisc entries + + key: "qdisc" + value type: string + + Add a qdisc entry in the form of "root|type;root|type;...". + ``` + "qdisc":"root|fq" + ``` + + * Interface offload + + key: "offload" + value type: string + + Work as a bit mask to enable selective device offload features. E.g., + to enable "mergeable RX buffer" (LKL_VIRTIO_NET_F_MRG_RXBUF) + + "guest csum" (LKL_VIRTIO_NET_F_GUEST_CSUM) device features, simply set + it to 0x8002. + See virtio_net.h for a list of offload features and their bit masks. + ``` + "offload":"0x8002" + ``` + FAQ === @@ -276,5 +456,3 @@ A: LibOS re-implements high-level kernel APIs for timers, softirqs, scheduling, sysctl, SLAB/SLUB, etc. LKL behaves like any arch port, implementing the arch level operations requested by the Linux kernel. LKL also offers a host interface so that support for multiple hosts can be implemented. - - diff --git a/tools/lkl/lib/Build b/tools/lkl/lib/Build index c146596a7a6c6f..b3ed0d4f1f5890 100644 --- a/tools/lkl/lib/Build +++ b/tools/lkl/lib/Build @@ -21,3 +21,5 @@ lkl-$(CONFIG_AUTO_LKL_POSIX_HOST) += virtio_net_macvtap.o lkl-$(CONFIG_AUTO_LKL_POSIX_HOST) += virtio_net_dpdk.o lkl-$(CONFIG_AUTO_LKL_POSIX_HOST) += virtio_net_vde.o lkl-$(CONFIG_AUTO_LKL_POSIX_HOST) += virtio_net_pipe.o +lkl-y += ../../perf/pmu-events/jsmn.o +lkl-y += config.o diff --git a/tools/lkl/lib/config.c b/tools/lkl/lib/config.c new file mode 100644 index 00000000000000..c26046cfc1945b --- /dev/null +++ b/tools/lkl/lib/config.c @@ -0,0 +1,390 @@ +#include +#include +#include +#include + +#include "config.h" +#include "../../perf/pmu-events/jsmn.h" + +static int jsoneq(const char *json, jsmntok_t *tok, const char *s) +{ + if (tok->type == JSMN_STRING && + (int) strlen(s) == tok->end - tok->start && + strncmp(json + tok->start, s, tok->end - tok->start) == 0) { + return 0; + } + return -1; +} + +static int cfgcpy(char **to, char *from) +{ + if (!from) + return 0; + if (*to) + free(*to); + *to = (char *)malloc((strlen(from) + 1) * sizeof(char)); + if (*to == NULL) { + lkl_printf("malloc failed\n"); + return -1; + } + strcpy(*to, from); + return 0; +} + +static int cfgncpy(char **to, char *from, int len) +{ + if (!from) + return 0; + if (*to) + free(*to); + *to = (char *)malloc((len + 1) * sizeof(char)); + if (*to == NULL) { + lkl_printf("malloc failed\n"); + return -1; + } + strncpy(*to, from, len + 1); + (*to)[len] = '\0'; + return 0; +} + +static int parse_ifarr(struct lkl_config *cfg, + jsmntok_t *toks, char *jstr, int startpos) +{ + int ifidx, pos, posend, ret; + char **cfgptr; + + if (!cfg || !toks || !jstr) + return -1; + pos = startpos; + pos++; + if (toks[pos].type != JSMN_ARRAY) { + lkl_printf("unexpected json type, json array expected\n"); + return -1; + } + cfg->ifnum = toks[pos].size; + if (cfg->ifnum >= LKL_IF_MAX) { + lkl_printf("exceeded max number of interface (%d)\n", + LKL_IF_MAX); + return -1; + } + pos++; + for (ifidx = 0; ifidx < cfg->ifnum; ifidx++) { + if (toks[pos].type != JSMN_OBJECT) { + lkl_printf("object json type expected\n"); + return -1; + } + posend = pos + toks[pos].size; + pos++; + for (; pos < posend; pos += 2) { + if (toks[pos].type != JSMN_STRING) { + lkl_printf("object json type expected\n"); + return -1; + } + if (jsoneq(jstr, &toks[pos], "type") == 0) { + cfgptr = &cfg->iftype[ifidx]; + } else if (jsoneq(jstr, &toks[pos], "param") == 0) { + cfgptr = &cfg->ifparams[ifidx]; + } else if (jsoneq(jstr, &toks[pos], "mtu") == 0) { + cfgptr = &cfg->ifmtu_str[ifidx]; + } else if (jsoneq(jstr, &toks[pos], "ip") == 0) { + cfgptr = &cfg->ifip[ifidx]; + } else if (jsoneq(jstr, &toks[pos], "ipv6") == 0) { + cfgptr = &cfg->ifipv6[ifidx]; + } else if (jsoneq(jstr, &toks[pos], "ifgateway") == 0) { + cfgptr = &cfg->ifgateway[ifidx]; + } else if (jsoneq(jstr, &toks[pos], + "ifgateway6") == 0) { + cfgptr = &cfg->ifgateway6[ifidx]; + } else if (jsoneq(jstr, &toks[pos], "mac") == 0) { + cfgptr = &cfg->ifmac_str[ifidx]; + } else if (jsoneq(jstr, &toks[pos], "masklen") == 0) { + cfgptr = &cfg->ifnetmask_len[ifidx]; + } else if (jsoneq(jstr, &toks[pos], "masklen6") == 0) { + cfgptr = &cfg->ifnetmask6_len[ifidx]; + } else if (jsoneq(jstr, &toks[pos], "neigh") == 0) { + cfgptr = &cfg->ifneigh_entries[ifidx]; + } else if (jsoneq(jstr, &toks[pos], "qdisc") == 0) { + cfgptr = &cfg->ifqdisc_entries[ifidx]; + } else if (jsoneq(jstr, &toks[pos], "offload") == 0) { + cfgptr = &cfg->ifoffload_str[ifidx]; + } else { + lkl_printf("unexpected key: %.*s\n", + toks[pos].end-toks[pos].start, + jstr + toks[pos].start); + return -1; + } + ret = cfgncpy(cfgptr, jstr + toks[pos+1].start, + toks[pos+1].end-toks[pos+1].start); + if (ret < 0) + return ret; + } + } + return pos - startpos; +} + +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) + +int load_config_json(struct lkl_config *cfg, char *jstr) +{ + int pos, ret; + char **cfgptr; + jsmn_parser jp; + jsmntok_t toks[LKL_CONFIG_JSON_TOKEN_MAX]; + + if (!cfg || !jstr) + return -1; + jsmn_init(&jp); + ret = jsmn_parse(&jp, jstr, strlen(jstr), toks, ARRAY_SIZE(toks)); + if (ret != JSMN_SUCCESS) { + lkl_printf("failed to parse json\n"); + return -1; + } + if (toks[0].type != JSMN_OBJECT) { + lkl_printf("object json type expected\n"); + return -1; + } + for (pos = 1; pos < jp.toknext; pos++) { + if (toks[pos].type != JSMN_STRING) { + lkl_printf("string json type expected\n"); + return -1; + } + if (jsoneq(jstr, &toks[pos], "interfaces") == 0) { + ret = parse_ifarr(cfg, toks, jstr, pos); + if (ret < 0) + return ret; + pos += ret; + pos--; + continue; + } + if (jsoneq(jstr, &toks[pos], "gateway") == 0) { + cfgptr = &cfg->gateway; + } else if (jsoneq(jstr, &toks[pos], "gateway6") == 0) { + cfgptr = &cfg->gateway6; + } else if (jsoneq(jstr, &toks[pos], "debug") == 0) { + cfgptr = &cfg->debug; + } else if (jsoneq(jstr, &toks[pos], "mount") == 0) { + cfgptr = &cfg->mount; + } else if (jsoneq(jstr, &toks[pos], "singlecpu") == 0) { + cfgptr = &cfg->single_cpu; + } else if (jsoneq(jstr, &toks[pos], "sysctl") == 0) { + cfgptr = &cfg->sysctls; + } else if (jsoneq(jstr, &toks[pos], "boot_cmdline") == 0) { + cfgptr = &cfg->boot_cmdline; + } else if (jsoneq(jstr, &toks[pos], "dump") == 0) { + cfgptr = &cfg->dump; + } else { + lkl_printf("unexpected key in json %.*s\n", + toks[pos].end-toks[pos].start, + jstr + toks[pos].start); + return -1; + } + pos++; + ret = cfgncpy(cfgptr, jstr + toks[pos].start, + toks[pos].end-toks[pos].start); + if (ret < 0) + return ret; + } + return 0; +} + +void show_config(struct lkl_config *cfg) +{ + int i; + + if (!cfg) + return; + lkl_printf("gateway: %s\n", cfg->gateway); + lkl_printf("gateway6: %s\n", cfg->gateway6); + lkl_printf("debug: %s\n", cfg->debug); + lkl_printf("mount: %s\n", cfg->mount); + lkl_printf("singlecpu: %s\n", cfg->single_cpu); + lkl_printf("sysctl: %s\n", cfg->sysctls); + lkl_printf("cmdlien: %s\n", cfg->boot_cmdline); + lkl_printf("dump: %s\n", cfg->dump); + for (i = 0; i < cfg->ifnum; i++) { + lkl_printf("ifmac[%d] = %s\n", i, cfg->ifmac_str[i]); + lkl_printf("ifmtu[%d] = %s\n", i, cfg->ifmtu_str[i]); + lkl_printf("iftype[%d] = %s\n", i, cfg->iftype[i]); + lkl_printf("ifparam[%d] = %s\n", i, cfg->ifparams[i]); + lkl_printf("ifip[%d] = %s\n", i, cfg->ifip[i]); + lkl_printf("ifmasklen[%d] = %s\n", i, cfg->ifnetmask_len[i]); + lkl_printf("ifgateway[%d] = %s\n", i, cfg->ifgateway[i]); + lkl_printf("ifip6[%d] = %s\n", i, cfg->ifipv6[i]); + lkl_printf("ifmasklen6[%d] = %s\n", i, cfg->ifnetmask6_len[i]); + lkl_printf("ifgateway6[%d] = %s\n", i, cfg->ifgateway6[i]); + lkl_printf("ifoffload[%d] = %s\n", i, cfg->ifoffload_str[i]); + lkl_printf("ifneigh[%d] = %s\n", i, cfg->ifneigh_entries[i]); + lkl_printf("ifqdisk[%d] = %s\n", i, cfg->ifqdisc_entries[i]); + } +} + +int load_config_env(struct lkl_config *cfg) +{ + int ret; + char *envtap = getenv("LKL_HIJACK_NET_TAP"); + char *enviftype = getenv("LKL_HIJACK_NET_IFTYPE"); + char *envifparams = getenv("LKL_HIJACK_NET_IFPARAMS"); + char *envmtu_str = getenv("LKL_HIJACK_NET_MTU"); + char *envip = getenv("LKL_HIJACK_NET_IP"); + char *envipv6 = getenv("LKL_HIJACK_NET_IPV6"); + char *envifgateway = getenv("LKL_HIJACK_NET_IFGATEWAY"); + char *envifgateway6 = getenv("LKL_HIJACK_NET_IFGATEWAY6"); + char *envmac_str = getenv("LKL_HIJACK_NET_MAC"); + char *envnetmask_len = getenv("LKL_HIJACK_NET_NETMASK_LEN"); + char *envnetmask6_len = getenv("LKL_HIJACK_NET_NETMASK6_LEN"); + char *envgateway = getenv("LKL_HIJACK_NET_GATEWAY"); + char *envgateway6 = getenv("LKL_HIJACK_NET_GATEWAY6"); + char *envdebug = getenv("LKL_HIJACK_DEBUG"); + char *envmount = getenv("LKL_HIJACK_MOUNT"); + char *envneigh_entries = getenv("LKL_HIJACK_NET_NEIGHBOR"); + char *envqdisc_entries = getenv("LKL_HIJACK_NET_QDISC"); + char *envsingle_cpu = getenv("LKL_HIJACK_SINGLE_CPU"); + char *envoffload_str = getenv("LKL_HIJACK_OFFLOAD"); + char *envsysctls = getenv("LKL_HIJACK_SYSCTL"); + char *envboot_cmdline = getenv("LKL_HIJACK_BOOT_CMDLINE") ? : ""; + char *envdump = getenv("LKL_HIJACK_DUMP"); + + if (!cfg) + return -1; + if (envtap || enviftype) + cfg->ifnum = 1; + ret = cfgcpy(&cfg->iftap[0], envtap); + if (ret < 0) + return ret; + ret = cfgcpy(&cfg->iftype[0], enviftype); + if (ret < 0) + return ret; + ret = cfgcpy(&cfg->ifparams[0], envifparams); + if (ret < 0) + return ret; + ret = cfgcpy(&cfg->ifmtu_str[0], envmtu_str); + if (ret < 0) + return ret; + ret = cfgcpy(&cfg->ifip[0], envip); + if (ret < 0) + return ret; + ret = cfgcpy(&cfg->ifipv6[0], envipv6); + if (ret < 0) + return ret; + ret = cfgcpy(&cfg->ifgateway[0], envifgateway); + if (ret < 0) + return ret; + ret = cfgcpy(&cfg->ifgateway6[0], envifgateway6); + if (ret < 0) + return ret; + ret = cfgcpy(&cfg->ifmac_str[0], envmac_str); + if (ret < 0) + return ret; + ret = cfgcpy(&cfg->ifnetmask_len[0], envnetmask_len); + if (ret < 0) + return ret; + ret = cfgcpy(&cfg->ifnetmask6_len[0], envnetmask6_len); + if (ret < 0) + return ret; + ret = cfgcpy(&cfg->ifoffload_str[0], envoffload_str); + if (ret < 0) + return ret; + ret = cfgcpy(&cfg->ifneigh_entries[0], envneigh_entries); + if (ret < 0) + return ret; + ret = cfgcpy(&cfg->ifqdisc_entries[0], envqdisc_entries); + if (ret < 0) + return ret; + ret = cfgcpy(&cfg->gateway, envgateway); + if (ret < 0) + return ret; + ret = cfgcpy(&cfg->gateway6, envgateway6); + if (ret < 0) + return ret; + ret = cfgcpy(&cfg->debug, envdebug); + if (ret < 0) + return ret; + ret = cfgcpy(&cfg->mount, envmount); + if (ret < 0) + return ret; + ret = cfgcpy(&cfg->single_cpu, envsingle_cpu); + if (ret < 0) + return ret; + ret = cfgcpy(&cfg->sysctls, envsysctls); + if (ret < 0) + return ret; + ret = cfgcpy(&cfg->boot_cmdline, envboot_cmdline); + if (ret < 0) + return ret; + ret = cfgcpy(&cfg->dump, envdump); + if (ret < 0) + return ret; + return 0; +} + +int init_config(struct lkl_config *cfg) +{ + int i; + + if (!cfg) + return -1; + for (i = 0; i < LKL_IF_MAX; i++) { + cfg->iftap[i] = NULL; + cfg->iftype[i] = NULL; + cfg->ifparams[i] = NULL; + cfg->ifmtu_str[i] = NULL; + cfg->ifip[i] = NULL; + cfg->ifipv6[i] = NULL; + cfg->ifgateway[i] = NULL; + cfg->ifgateway6[i] = NULL; + cfg->ifmac_str[i] = NULL; + cfg->ifnetmask_len[i] = NULL; + cfg->ifnetmask6_len[i] = NULL; + cfg->ifoffload_str[i] = NULL; + cfg->ifneigh_entries[i] = NULL; + cfg->ifqdisc_entries[i] = NULL; + } + cfg->gateway = NULL; + cfg->gateway6 = NULL; + cfg->debug = NULL; + cfg->mount = NULL; + cfg->single_cpu = NULL; + cfg->sysctls = NULL; + cfg->boot_cmdline = NULL; + cfg->dump = NULL; + return 0; +} + +static void free_cfgparam(char *cfgparam) +{ + if (cfgparam) + free(cfgparam); +} + +int clean_config(struct lkl_config *cfg) +{ + int i; + + if (!cfg) + return -1; + for (i = 0; i < LKL_IF_MAX; i++) { + free_cfgparam(cfg->iftap[i]); + free_cfgparam(cfg->iftype[i]); + free_cfgparam(cfg->ifparams[i]); + free_cfgparam(cfg->ifmtu_str[i]); + free_cfgparam(cfg->ifip[i]); + free_cfgparam(cfg->ifipv6[i]); + free_cfgparam(cfg->ifgateway[i]); + free_cfgparam(cfg->ifgateway6[i]); + free_cfgparam(cfg->ifmac_str[i]); + free_cfgparam(cfg->ifnetmask_len[i]); + free_cfgparam(cfg->ifnetmask6_len[i]); + free_cfgparam(cfg->ifoffload_str[i]); + free_cfgparam(cfg->ifneigh_entries[i]); + free_cfgparam(cfg->ifqdisc_entries[i]); + } + free_cfgparam(cfg->gateway); + free_cfgparam(cfg->gateway6); + free_cfgparam(cfg->debug); + free_cfgparam(cfg->mount); + free_cfgparam(cfg->single_cpu); + free_cfgparam(cfg->sysctls); + free_cfgparam(cfg->boot_cmdline); + free_cfgparam(cfg->dump); + return 0; +} diff --git a/tools/lkl/lib/config.h b/tools/lkl/lib/config.h new file mode 100644 index 00000000000000..e21285f2a4f7c8 --- /dev/null +++ b/tools/lkl/lib/config.h @@ -0,0 +1,53 @@ +#ifndef _LKL_LIB_CONFIG_H +#define _LKL_LIB_CONFIG_H + +#define LKL_CONFIG_JSON_TOKEN_MAX 300 +/* TODO dynamically allocate interface info arr */ +#define LKL_IF_MAX 16 + +struct lkl_config { + int ifnum; + /* OBSOLETE: should use IFTYPE and IFPARAMS */ + char *iftap[LKL_IF_MAX]; + char *iftype[LKL_IF_MAX]; + char *ifparams[LKL_IF_MAX]; + char *ifmtu_str[LKL_IF_MAX]; + char *ifip[LKL_IF_MAX]; + char *ifipv6[LKL_IF_MAX]; + char *ifgateway[LKL_IF_MAX]; + char *ifgateway6[LKL_IF_MAX]; + char *ifmac_str[LKL_IF_MAX]; + char *ifnetmask_len[LKL_IF_MAX]; + char *ifnetmask6_len[LKL_IF_MAX]; + char *ifoffload_str[LKL_IF_MAX]; + char *ifneigh_entries[LKL_IF_MAX]; + char *ifqdisc_entries[LKL_IF_MAX]; + + char *gateway; + char *gateway6; + char *debug; + char *mount; + /* single_cpu mode: + * 0: Don't pin to single CPU (default). + * 1: Pin only LKL kernel threads to single CPU. + * 2: Pin all LKL threads to single CPU including all LKL kernel threads + * and device polling threads. Avoid this mode if having busy polling + * threads. + * + * mode 2 can achieve better TCP_RR but worse TCP_STREAM than mode 1. + * You should choose the best for your application and virtio device + * type. + */ + char *single_cpu; + char *sysctls; + char *boot_cmdline; + char *dump; +}; + +int init_config(struct lkl_config *cfg); +int load_config_json(struct lkl_config *cfg, char *jstr); +int load_config_env(struct lkl_config *cfg); +int clean_config(struct lkl_config *cfg); +void show_config(struct lkl_config *cfg); + +#endif /* _LKL_LIB_CONFIG_H */ diff --git a/tools/lkl/lib/hijack/init.c b/tools/lkl/lib/hijack/init.c index 99f902ef8d6c02..10b90feb5aeecf 100644 --- a/tools/lkl/lib/hijack/init.c +++ b/tools/lkl/lib/hijack/init.c @@ -25,6 +25,7 @@ #include #include "xlate.h" +#include "../config.h" #define __USE_GNU #include @@ -178,61 +179,251 @@ static void PinToFirstCpu(const cpu_set_t* cpus) int lkl_debug, lkl_running; -static int nd_id = -1; -static struct lkl_netdev *nd; +static int nd_id[LKL_IF_MAX]; +static struct lkl_netdev *nd[LKL_IF_MAX]; +static struct lkl_config *cfg; + +static int config_load(void) +{ + int len, ret = -1; + char *buf; + int fd; + char *path = getenv("LKL_HIJACK_CONFIG_FILE"); + + cfg = (struct lkl_config *)malloc(sizeof(struct lkl_config)); + if (!cfg) { + perror("config malloc"); + return -1; + } + init_config(cfg); + + ret = load_config_env(cfg); + if (ret < 0) + return ret; + + if (path) + fd = open(path, O_RDONLY, 0); + else if (access("lkl-hijack.json", R_OK) == 0) + fd = open("lkl-hijack.json", O_RDONLY, 0); + else + return 0; + if (fd < 0) { + fprintf(stderr, "config_file open %s: %s\n", + path, strerror(errno)); + return -1; + } + len = lseek(fd, 0, SEEK_END); + lseek(fd, 0, SEEK_SET); + if (len < 0) { + perror("config size check (lseek)"); + return -1; + } else if (len == 0) { + return 0; + } + buf = (char *)malloc(len * sizeof(char) + 1); + if (!buf) { + perror("config buf malloc"); + return -1; + } + ret = read(fd, buf, len); + if (ret < 0) { + perror("config file read"); + free(buf); + return -1; + } + ret = load_config_json(cfg, buf); + free(buf); + return ret; +} + +static int lkl_hijack_netdev_create(struct lkl_config *cfg, int ifidx) +{ + int ret, offload = 0; + struct lkl_netdev_args nd_args; + __lkl__u8 mac[LKL_ETH_ALEN] = {0}; + + if (cfg->ifoffload_str[ifidx]) + offload = strtol(cfg->ifoffload_str[ifidx], NULL, 0); + memset(&nd_args, 0, sizeof(struct lkl_netdev_args)); + if (cfg->iftap[ifidx]) { + fprintf(stderr, "WARN: LKL_HIJACK_NET_TAP is now obsoleted.\n"); + fprintf(stderr, "use LKL_HIJACK_NET_IFTYPE and PARAMS\n"); + nd[ifidx] = lkl_netdev_tap_create(cfg->iftap[ifidx], offload); + } + + if (!nd[ifidx] && cfg->iftype[ifidx] && cfg->ifparams[ifidx]) { + if ((strcmp(cfg->iftype[ifidx], "tap") == 0)) { + nd[ifidx] = + lkl_netdev_tap_create(cfg->ifparams[ifidx], + offload); + } else if ((strcmp(cfg->iftype[ifidx], "macvtap") == 0)) { + nd[ifidx] = + lkl_netdev_macvtap_create(cfg->ifparams[ifidx], + offload); + } else if ((strcmp(cfg->iftype[ifidx], "dpdk") == 0)) { + nd[ifidx] = + lkl_netdev_dpdk_create(cfg->ifparams[ifidx], + offload, mac); + } else if ((strcmp(cfg->iftype[ifidx], "pipe") == 0)) { + nd[ifidx] = + lkl_netdev_pipe_create(cfg->ifparams[ifidx], + offload); + } else { + if (offload) { + fprintf(stderr, + "WARN: %s isn't supported on %s\n", + "LKL_HIJACK_OFFLOAD", + cfg->iftype[ifidx]); + fprintf(stderr, + "WARN: Disabling offload features.\n"); + } + offload = 0; + } + if (strcmp(cfg->iftype[ifidx], "vde") == 0) + nd[ifidx] = lkl_netdev_vde_create(cfg->ifparams[ifidx]); + if (strcmp(cfg->iftype[ifidx], "raw") == 0) + nd[ifidx] = lkl_netdev_raw_create(cfg->ifparams[ifidx]); + } + + if (nd[ifidx]) { + if ((mac[0] != 0) || (mac[1] != 0) || + (mac[2] != 0) || (mac[3] != 0) || + (mac[4] != 0) || (mac[5] != 0)) { + nd_args.mac = mac; + } else { + ret = parse_mac_str(cfg->ifmac_str[ifidx], mac); + + if (ret < 0) { + fprintf(stderr, "failed to parse mac\n"); + return -1; + } else if (ret > 0) { + nd_args.mac = mac; + } else { + nd_args.mac = NULL; + } + } + + nd_args.offload = offload; + ret = lkl_netdev_add(nd[ifidx], &nd_args); + if (ret < 0) { + fprintf(stderr, "failed to add netdev: %s\n", + lkl_strerror(ret)); + return -1; + } + nd_id[ifidx] = ret; + } + return 0; +} + +static int lkl_hijack_netdev_configure(struct lkl_config *cfg, int ifidx) +{ + int ret, nd_ifindex = -1; + + if (nd_id[ifidx] >= 0) { + nd_ifindex = lkl_netdev_get_ifindex(nd_id[ifidx]); + if (nd_ifindex > 0) + lkl_if_up(nd_ifindex); + else + fprintf(stderr, + "failed to get ifindex for netdev id %d: %s\n", + nd_id[ifidx], lkl_strerror(nd_ifindex)); + } + + if (nd_ifindex >= 0 && cfg->ifmtu_str[ifidx]) { + int mtu = atoi(cfg->ifmtu_str[ifidx]); + + ret = lkl_if_set_mtu(nd_ifindex, mtu); + if (ret < 0) + fprintf(stderr, "failed to set MTU: %s\n", + lkl_strerror(ret)); + } + + if (nd_ifindex >= 0 && cfg->ifip[ifidx] && cfg->ifnetmask_len[ifidx]) { + unsigned int addr = inet_addr(cfg->ifip[ifidx]); + int nmlen = atoi(cfg->ifnetmask_len[ifidx]); + + if (addr != INADDR_NONE && nmlen > 0 && nmlen < 32) { + ret = lkl_if_set_ipv4(nd_ifindex, addr, nmlen); + if (ret < 0) + fprintf(stderr, + "failed to set IPv4 address: %s\n", + lkl_strerror(ret)); + } + if (cfg->ifgateway[ifidx]) { + unsigned int gwaddr = inet_addr(cfg->ifgateway[ifidx]); + + if (gwaddr != INADDR_NONE) { + ret = lkl_if_set_ipv4_gateway(nd_ifindex, + addr, nmlen, gwaddr); + if (ret < 0) + fprintf(stderr, + "failed to set v4 if gw: %s\n", + lkl_strerror(ret)); + } + } + } + + if (nd_ifindex >= 0 && cfg->ifipv6[ifidx] && + cfg->ifnetmask6_len[ifidx]) { + struct in6_addr addr; + unsigned int pflen = atoi(cfg->ifnetmask6_len[ifidx]); + + if (inet_pton(AF_INET6, cfg->ifipv6[ifidx], &addr) != 1) { + fprintf(stderr, "Invalid ipv6 addr: %s\n", + cfg->ifipv6[ifidx]); + } else { + ret = lkl_if_set_ipv6(nd_ifindex, &addr, pflen); + if (ret < 0) + fprintf(stderr, + "failed to set IPv6 address: %s\n", + lkl_strerror(ret)); + } + if (cfg->ifgateway6[ifidx]) { + char gwaddr[16]; + + if (inet_pton(AF_INET6, cfg->ifgateway6[ifidx], + gwaddr) != 1) { + fprintf(stderr, "Invalid ipv6 gateway: %s\n", + cfg->ifgateway6[ifidx]); + } else { + ret = lkl_if_set_ipv6_gateway(nd_ifindex, + &addr, pflen, gwaddr); + if (ret < 0) + fprintf(stderr, + "failed to set v6 if gw: %s\n", + lkl_strerror(ret)); + } + } + } + + if (nd_ifindex >= 0 && cfg->ifneigh_entries[ifidx]) + add_neighbor(nd_ifindex, cfg->ifneigh_entries[ifidx]); + + if (nd_ifindex >= 0 && cfg->ifqdisc_entries[ifidx]) + lkl_qdisc_parse_add(nd_ifindex, cfg->ifqdisc_entries[ifidx]); + + return 0; +} void __attribute__((constructor)) hijack_init(void) { - int ret, i, dev_null, nd_ifindex = -1; - /* OBSOLETE: should use IFTYPE and IFPARAMS */ - char *tap = getenv("LKL_HIJACK_NET_TAP"); - char *iftype = getenv("LKL_HIJACK_NET_IFTYPE"); - char *ifparams = getenv("LKL_HIJACK_NET_IFPARAMS"); - char *mtu_str = getenv("LKL_HIJACK_NET_MTU"); - __lkl__u8 mac[LKL_ETH_ALEN] = {0}; - char *ip = getenv("LKL_HIJACK_NET_IP"); - char *ipv6 = getenv("LKL_HIJACK_NET_IPV6"); - char *mac_str = getenv("LKL_HIJACK_NET_MAC"); - char *netmask_len = getenv("LKL_HIJACK_NET_NETMASK_LEN"); - char *netmask6_len = getenv("LKL_HIJACK_NET_NETMASK6_LEN"); - char *ifgateway = getenv("LKL_HIJACK_NET_IFGATEWAY"); - char *ifgateway6 = getenv("LKL_HIJACK_NET_IFGATEWAY6"); - char *gateway = getenv("LKL_HIJACK_NET_GATEWAY"); - char *gateway6 = getenv("LKL_HIJACK_NET_GATEWAY6"); - char *debug = getenv("LKL_HIJACK_DEBUG"); - char *mount = getenv("LKL_HIJACK_MOUNT"); - struct lkl_netdev_args nd_args; - char *neigh_entries = getenv("LKL_HIJACK_NET_NEIGHBOR"); - char *qdisc_entries = getenv("LKL_HIJACK_NET_QDISC"); - /* single_cpu mode: - * 0: Don't pin to single CPU (default). - * 1: Pin only LKL kernel threads to single CPU. - * 2: Pin all LKL threads to single CPU including all LKL kernel threads - * and device polling threads. Avoid this mode if having busy polling - * threads. - * - * mode 2 can achieve better TCP_RR but worse TCP_STREAM than mode 1. - * You should choose the best for your application and virtio device - * type. - */ - char *single_cpu= getenv("LKL_HIJACK_SINGLE_CPU"); + int ret, i, dev_null; int single_cpu_mode = 0; + int ifidx; cpu_set_t ori_cpu; - char *offload1 = getenv("LKL_HIJACK_OFFLOAD"); - int offload = 0; - char *sysctls = getenv("LKL_HIJACK_SYSCTL"); - char *boot_cmdline = getenv("LKL_HIJACK_BOOT_CMDLINE") ? : ""; - memset(&nd_args, 0, sizeof(struct lkl_netdev_args)); - if (!debug) { + ret = config_load(); + if (ret < 0) + return; + for (i = 0; i < LKL_IF_MAX; i++) + nd_id[i] = -1; + if (!cfg->debug) { lkl_host_ops.print = NULL; } else { lkl_register_dbg_handler(); - lkl_debug = strtol(debug, NULL, 0); + lkl_debug = strtol(cfg->debug, NULL, 0); } - if (offload1) - offload = strtol(offload1, NULL, 0); if (lkl_debug & 0x200) { char c; @@ -243,8 +434,8 @@ hijack_init(void) return; } } - if (single_cpu) { - single_cpu_mode = atoi(single_cpu); + if (cfg->single_cpu) { + single_cpu_mode = atoi(cfg->single_cpu); switch (single_cpu_mode) { case 0: case 1: @@ -269,65 +460,10 @@ hijack_init(void) if (single_cpu_mode == 2) PinToFirstCpu(&ori_cpu); - if (tap) { - fprintf(stderr, - "WARN: variable LKL_HIJACK_NET_TAP is now obsoleted.\n" - " please use LKL_HIJACK_NET_IFTYPE and " - "LKL_HIJACK_NET_IFPARAMS instead.\n"); - nd = lkl_netdev_tap_create(tap, offload); - } - - if (!nd && iftype && ifparams) { - if ((strcmp(iftype, "tap") == 0)) { - nd = lkl_netdev_tap_create(ifparams, offload); - } else if ((strcmp(iftype, "macvtap") == 0)) { - nd = lkl_netdev_macvtap_create(ifparams, offload); - } else if ((strcmp(iftype, "dpdk") == 0)) { - nd = lkl_netdev_dpdk_create(ifparams, offload, mac); - } else if ((strcmp(iftype, "pipe") == 0)) { - nd = lkl_netdev_pipe_create(ifparams, offload); - } else { - if (offload) { - fprintf(stderr, - "WARN: %s isn't supported on %s\n", - "LKL_HIJACK_OFFLOAD", iftype); - fprintf(stderr, - "WARN: Disabling offload features.\n"); - } - offload = 0; - if (strcmp(iftype, "vde") == 0) - nd = lkl_netdev_vde_create(ifparams); - else if (strcmp(iftype, "raw") == 0) - nd = lkl_netdev_raw_create(ifparams); - } - } - - if (nd) { - if ((mac[0] != 0) || (mac[1] != 0) || (mac[2] != 0) || - (mac[3] != 0) || (mac[4] != 0) || (mac[5] != 0)) { - nd_args.mac = mac; - } else { - ret = parse_mac_str(mac_str, mac); - - if (ret < 0) { - fprintf(stderr, "failed to parse mac\n"); - return; - } else if (ret > 0) { - nd_args.mac = mac; - } else { - nd_args.mac = NULL; - } - } - - nd_args.offload = offload; - ret = lkl_netdev_add(nd, &nd_args); - - if (ret < 0) { - fprintf(stderr, "failed to add netdev: %s\n", - lkl_strerror(ret)); + for (ifidx = 0; ifidx < cfg->ifnum; ifidx++) { + ret = lkl_hijack_netdev_create(cfg, ifidx); + if (ret < 0) return; - } - nd_id = ret; } if (single_cpu_mode == 1) @@ -344,7 +480,7 @@ hijack_init(void) } #endif - ret = lkl_start_kernel(&lkl_host_ops, boot_cmdline); + ret = lkl_start_kernel(&lkl_host_ops, cfg->boot_cmdline); if (ret) { fprintf(stderr, "can't start kernel: %s\n", lkl_strerror(ret)); return; @@ -365,7 +501,8 @@ hijack_init(void) ret = lkl_sys_mknod("/dev_null", LKL_S_IFCHR | 0600, LKL_MKDEV(1, 3)); dev_null = lkl_sys_open("/dev_null", LKL_O_RDONLY, 0); if (dev_null < 0) { - fprintf(stderr, "failed to open /dev/null: %s\n", lkl_strerror(dev_null)); + fprintf(stderr, "failed to open /dev/null: %s\n", + lkl_strerror(dev_null)); return; } @@ -375,49 +512,14 @@ hijack_init(void) /* lo iff_up */ lkl_if_up(1); - if (nd_id >= 0) { - nd_ifindex = lkl_netdev_get_ifindex(nd_id); - if (nd_ifindex > 0) - lkl_if_up(nd_ifindex); - else - fprintf(stderr, "failed to get ifindex for netdev id %d: %s\n", - nd_id, lkl_strerror(nd_ifindex)); - } - - if (nd_ifindex >= 0 && mtu_str) { - int mtu = atoi(mtu_str); - - ret = lkl_if_set_mtu(nd_ifindex, mtu); + for (ifidx = 0; ifidx < cfg->ifnum; ifidx++) { + ret = lkl_hijack_netdev_configure(cfg, ifidx); if (ret < 0) - fprintf(stderr, "failed to set MTU: %s\n", lkl_strerror(ret)); - } - - if (nd_ifindex >= 0 && ip && netmask_len) { - unsigned int addr = inet_addr(ip); - int nmlen = atoi(netmask_len); - - if (addr != INADDR_NONE && nmlen > 0 && nmlen < 32) { - ret = lkl_if_set_ipv4(nd_ifindex, addr, nmlen); - if (ret < 0) - fprintf(stderr, "failed to set IPv4 address: %s\n", - lkl_strerror(ret)); - } - if (ifgateway) { - unsigned int gwaddr = inet_addr(ifgateway); - - if (gwaddr != INADDR_NONE) { - ret = lkl_if_set_ipv4_gateway(nd_ifindex, - addr, nmlen, gwaddr); - if (ret < 0) - fprintf(stderr, - "failed to set v4 if gw: %s\n", - lkl_strerror(ret)); - } - } + return; } - if (nd_ifindex >= 0 && gateway) { - unsigned int gwaddr = inet_addr(gateway); + if (cfg->gateway) { + unsigned int gwaddr = inet_addr(cfg->gateway); if (gwaddr != INADDR_NONE) { ret = lkl_set_ipv4_gateway(gwaddr); @@ -427,66 +529,32 @@ hijack_init(void) } } - if (nd_ifindex >= 0 && ipv6 && netmask6_len) { - struct in6_addr addr; - unsigned int pflen = atoi(netmask6_len); - - if (inet_pton(AF_INET6, ipv6, &addr) != 1) { - fprintf(stderr, "Invalid ipv6 addr: %s\n", ipv6); - } else { - ret = lkl_if_set_ipv6(nd_ifindex, &addr, pflen); - if (ret < 0) - fprintf(stderr, "failed to set IPv6address: %s\n", - lkl_strerror(ret)); - } - if (ifgateway6) { - char gwaddr[16]; - - if (inet_pton(AF_INET6, ifgateway6, gwaddr) != 1) { - fprintf(stderr, "Invalid ipv6 gateway: %s\n", - ifgateway6); - } else { - ret = lkl_if_set_ipv6_gateway(nd_ifindex, - &addr, pflen, gwaddr); - if (ret < 0) - fprintf(stderr, - "failed to set v6 if gw: %s\n", - lkl_strerror(ret)); - } - } - } - - if (nd_ifindex >= 0 && gateway6) { - char gwaddr[16]; + if (cfg->gateway6) { + char gw[16]; - if (inet_pton(AF_INET6, gateway6, gwaddr) != 1) { - fprintf(stderr, "Invalid ipv6 gateway: %s\n", gateway6); + if (inet_pton(AF_INET6, cfg->gateway6, gw) != 1) { + fprintf(stderr, "Invalid ipv6 gateway: %s\n", + cfg->gateway6); } else { - ret = lkl_set_ipv6_gateway(gwaddr); + ret = lkl_set_ipv6_gateway(gw); if (ret < 0) - fprintf(stderr, "failed to set IPv6 gateway: %s\n", + fprintf(stderr, + "failed to set IPv6 gateway: %s\n", lkl_strerror(ret)); } } - if (mount) - mount_cmds_exec(mount, lkl_mount_fs); - - if (nd_ifindex >= 0 && neigh_entries) - add_neighbor(nd_ifindex, neigh_entries); + if (cfg->mount) + mount_cmds_exec(cfg->mount, lkl_mount_fs); - if (nd_ifindex >= 0 && qdisc_entries) - lkl_qdisc_parse_add(nd_ifindex, qdisc_entries); - - if (sysctls) - lkl_sysctl_parse_write(sysctls); + if (cfg->sysctls) + lkl_sysctl_parse_write(cfg->sysctls); } void __attribute__((destructor)) hijack_fini(void) { int i; - char *dump = getenv("LKL_HIJACK_DUMP"); int err; /* The following pauses the kernel before exiting allowing one @@ -496,18 +564,25 @@ hijack_fini(void) while (1) pause(); } - if (dump) - mount_cmds_exec(dump, dump_file); + + if (cfg) { + if (cfg->dump) + mount_cmds_exec(cfg->dump, dump_file); + for (i = 0; i < cfg->ifnum; i++) + if (nd_id[i] >= 0) + lkl_netdev_remove(nd_id[i]); + for (i = 0; i < cfg->ifnum; i++) + if (nd[i]) + lkl_netdev_free(nd[i]); + clean_config(cfg); + free(cfg); + } + if (!lkl_running) + return; for (i = 0; i < LKL_FD_OFFSET; i++) lkl_sys_close(i); - if (nd_id >= 0) - lkl_netdev_remove(nd_id); - - if (nd) - lkl_netdev_free(nd); - err = lkl_sys_halt(); if (err) fprintf(stderr, "lkl_sys_halt: %s\n", lkl_strerror(err)); diff --git a/tools/lkl/tests/hijack-test.sh b/tools/lkl/tests/hijack-test.sh index 93a6603eb3a1a4..395ee37eaee53a 100755 --- a/tools/lkl/tests/hijack-test.sh +++ b/tools/lkl/tests/hijack-test.sh @@ -20,6 +20,8 @@ function clear_work_dir { rm -rf ${work_dir} sudo ip link set dev lkl_ptt0 down &> /dev/null || true sudo ip tuntap del dev lkl_ptt0 mode tap &> /dev/null || true + sudo ip link set dev lkl_ptt1 down &> /dev/null || true + sudo ip tuntap del dev lkl_ptt1 mode tap &> /dev/null || true } trap clear_work_dir EXIT @@ -43,10 +45,18 @@ ${hijack_script} ./ping6 -c 1 ::1 rm ./ping6 echo "== Mount/dump tests ==" +cfgjson=${work_dir}/hijack-test.conf + +cat << EOF > ${cfgjson} +{ + "mount":"proc,sysfs", + "dump":"/sysfs/class/net/lo/mtu,/sysfs/class/net/lo/dev_id", + "debug":"1" +} +EOF + # Need to say || true because ip -h returns < 0 -ans=$(LKL_HIJACK_MOUNT=proc,sysfs\ - LKL_HIJACK_DUMP=/sysfs/class/net/lo/mtu,/sysfs/class/net/lo/dev_id\ - LKL_HIJACK_DEBUG=1\ +ans=$(LKL_HIJACK_CONFIG_FILE=$cfgjson\ ${hijack_script} ip -h) || true # Need to grab the end because something earlier on prints out this # number @@ -62,8 +72,15 @@ fi # boot_cmdline test echo "== boot command line tests ==" -ans=$(LKL_HIJACK_DEBUG=1\ - LKL_HIJACK_BOOT_CMDLINE="mem=100M" ${hijack_script} ip ad) + +cat << EOF > ${cfgjson} +{ + "debug":"1", + "boot_cmdline":"mem=100M" +} +EOF + +ans=$(LKL_HIJACK_CONFIG_FILE=$cfgjson ${hijack_script} ip ad) if [ -z ${CROSS_COMPILE} ] ; then echo "$ans" | grep "100752k" elif [ "${CROSS_COMPILE}" = "arm-linux-androideabi-" ] ; then @@ -82,13 +99,22 @@ fifo2=${work_dir}/fifo2 mkfifo ${fifo1} mkfifo ${fifo2} +cat << EOF > ${cfgjson} +{ + "interfaces":[ + { + "type":"pipe", + "param":"${fifo1}|${fifo2}", + "ip":"192.168.13.2", + "masklen":"24", + "mac":"aa:bb:cc:dd:ee:ff", + } + ] +} +EOF + # Make sure our device has the addresses we expect -addr=$(LKL_HIJACK_NET_IFTYPE=pipe \ - LKL_HIJACK_NET_IFPARAMS="${fifo1}|${fifo2}" \ - LKL_HIJACK_NET_IP=192.168.13.2 \ - LKL_HIJACK_NET_NETMASK_LEN=24 \ - LKL_HIJACK_NET_MAC="aa:bb:cc:dd:ee:ff" \ - ${hijack_script} ip addr) +addr=$(LKL_HIJACK_CONFIG_FILE=$cfgjson ${hijack_script} ip addr) echo "$addr" | grep eth0 echo "$addr" | grep 192.168.13.2 echo "$addr" | grep "aa:bb:cc:dd:ee:ff" @@ -97,40 +123,51 @@ echo "$addr" | grep "aa:bb:cc:dd:ee:ff" cp $(which ping) . cp $(which ping6) . -# Ping receiver -LKL_HIJACK_NET_IFTYPE=pipe \ - LKL_HIJACK_NET_IFPARAMS="${fifo1}|${fifo2}" \ - LKL_HIJACK_NET_IP=192.168.13.1 \ - LKL_HIJACK_NET_NETMASK_LEN=24 \ - LKL_HIJACK_NET_GATEWAY=192.168.13.2 \ - LKL_HIJACK_NET_IPV6=fc03::1 \ - LKL_HIJACK_NET_NETMASK6_LEN=64\ - LKL_HIJACK_NET_GATEWAY6=fc03::2 \ - ${hijack_script} sleep 10 & +cat << EOF > ${cfgjson} +{ + "gateway":"192.168.13.2", + "gateway6":"fc03::2", + "interfaces":[ + { + "type":"pipe", + "param":"${fifo1}|${fifo2}", + "ip":"192.168.13.1", + "masklen":"24", + "mac":"aa:bb:cc:dd:ee:ff", + "ipv6":"fc03::1", + "masklen6":"64" + } + ] +} +EOF + +LKL_HIJACK_CONFIG_FILE=$cfgjson ${hijack_script} sleep 10 & sleep 5 +cat << EOF > ${cfgjson} +{ + "gateway":"192.168.13.1", + "gateway6":"fc03::1", + "interfaces":[ + { + "type":"pipe", + "param":"${fifo2}|${fifo1}", + "ip":"192.168.13.2", + "masklen":"24", + "mac":"aa:bb:cc:dd:ee:ff", + "ipv6":"fc03::2", + "masklen6":"64" + } + ] +} +EOF + # Ping under LKL -sudo LKL_HIJACK_NET_IFTYPE=pipe \ - LKL_HIJACK_NET_IFPARAMS="${fifo2}|${fifo1}" \ - LKL_HIJACK_NET_IP=192.168.13.2 \ - LKL_HIJACK_NET_NETMASK_LEN=24 \ - LKL_HIJACK_NET_GATEWAY=192.168.13.1 \ - LKL_HIJACK_NET_IPV6=fc03::2 \ - LKL_HIJACK_NET_NETMASK6_LEN=64\ - LKL_HIJACK_NET_GATEWAY6=fc03::1 \ - ${hijack_script} ./ping 192.168.13.1 -c 1 +sudo LKL_HIJACK_CONFIG_FILE=$cfgjson ${hijack_script} ./ping 192.168.13.1 -c 1 # Ping 6 under LKL -sudo LKL_HIJACK_NET_IFTYPE=pipe \ - LKL_HIJACK_NET_IFPARAMS="${fifo2}|${fifo1}" \ - LKL_HIJACK_NET_IP=192.168.13.2 \ - LKL_HIJACK_NET_NETMASK_LEN=24 \ - LKL_HIJACK_NET_GATEWAY=192.168.13.1 \ - LKL_HIJACK_NET_IPV6=fc03::2 \ - LKL_HIJACK_NET_NETMASK6_LEN=64\ - LKL_HIJACK_NET_GATEWAY6=fc03::1 \ - ${hijack_script} ./ping6 fc03::1 -c 1 +sudo LKL_HIJACK_CONFIG_FILE=$cfgjson ${hijack_script} ./ping6 fc03::1 -c 1 wait rm ./ping @@ -143,15 +180,6 @@ if [ ! -c /dev/net/tun ]; then exit 0 fi -export LKL_HIJACK_NET_IFTYPE=tap -export LKL_HIJACK_NET_IFPARAMS=lkl_ptt0 -export LKL_HIJACK_NET_IP=192.168.13.2 -export LKL_HIJACK_NET_NETMASK_LEN=24 -export LKL_HIJACK_NET_GATEWAY=192.168.13.1 -export LKL_HIJACK_NET_IPV6=fc03::2 -export LKL_HIJACK_NET_NETMASK6_LEN=64 -export LKL_HIJACK_NET_GATEWAY6=fc03::1 - # Set up the TAP device we'd like to use sudo ip tuntap del dev lkl_ptt0 mode tap || true sudo ip tuntap add dev lkl_ptt0 mode tap user $USER @@ -159,9 +187,26 @@ sudo ip link set dev lkl_ptt0 up sudo ip addr add dev lkl_ptt0 192.168.13.1/24 sudo ip -6 addr add dev lkl_ptt0 fc03::1/64 +cat << EOF > ${cfgjson} +{ + "gateway":"192.168.13.1", + "gateway6":"fc03::1", + "interfaces":[ + { + "type":"tap", + "param":"lkl_ptt0", + "ip":"192.168.13.2", + "masklen":"24", + "ipv6":"fc03::2", + "masklen6":"64" + } + ] +} +EOF + # Make sure our device has the addresses we expect -addr=$(LKL_HIJACK_DEBUG=1\ - LKL_HIJACK_NET_MAC="aa:bb:cc:dd:ee:ff" ${hijack_script} ip addr) +addr=$(LKL_HIJACK_DEBUG=1 LKL_HIJACK_NET_MAC="aa:bb:cc:dd:ee:ff" \ + LKL_HIJACK_CONFIG_FILE=$cfgjson ${hijack_script} ip addr) echo "$addr" | grep eth0 echo "$addr" | grep 192.168.13.2 echo "$addr" | grep "aa:bb:cc:dd:ee:ff" @@ -173,8 +218,8 @@ cp `which ping` . cp `which ping6` . # Make sure we can ping the host from inside LKL -${hijack_script} ./ping 192.168.13.1 -c 1 -${hijack_script} ./ping6 fc03::1 -c 1 +LKL_HIJACK_CONFIG_FILE=$cfgjson ${hijack_script} ./ping 192.168.13.1 -c 1 +LKL_HIJACK_CONFIG_FILE=$cfgjson ${hijack_script} ./ping6 fc03::1 -c 1 rm ./ping ./ping6 # Now let's check that the host can see LKL. @@ -182,60 +227,311 @@ sudo ip -6 neigh del fc03::2 dev lkl_ptt0 sudo ip neigh del 192.168.13.2 dev lkl_ptt0 sudo ping -i 0.01 -c 65 192.168.13.2 & sudo ping6 -i 0.01 -c 65 fc03::2 & -${hijack_script} sleep 3 +LKL_HIJACK_CONFIG_FILE=$cfgjson ${hijack_script} sleep 3 + +neigh1="192.168.13.100|12:34:56:78:9a:bc" +neigh2="fc03::100|12:34:56:78:9a:be" + +cat << EOF > ${cfgjson} +{ + "gateway":"192.168.13.1", + "gateway6":"fc03::1", + "interfaces":[ + { + "type":"tap", + "param":"lkl_ptt0", + "ip":"192.168.13.2", + "masklen":"24", + "ipv6":"fc03::2", + "masklen6":"64", + "neigh":"${neigh1};${neigh2}" + } + ] +} +EOF # add neighbor entries -ans=$(LKL_HIJACK_NET_NEIGHBOR="192.168.13.100|12:34:56:78:9a:bc;fc03::100|12:34:56:78:9a:be"\ - ${hijack_script} ip neighbor show) || true +ans=$(LKL_HIJACK_CONFIG_FILE=$cfgjson ${hijack_script} ip neighbor show) || true echo "$ans" | tail -n 15 | grep "12:34:56:78:9a:bc" echo "$ans" | tail -n 15 | grep "12:34:56:78:9a:be" # gateway -ans=$(${hijack_script} ip route show) || true +ans=$(LKL_HIJACK_CONFIG_FILE=$cfgjson ${hijack_script} ip route show) || true echo "$ans" | tail -n 15 | grep "192.168.13.1" # gateway v6 -ans=$(${hijack_script} ip -6 route show) || true +ans=$(LKL_HIJACK_CONFIG_FILE=$cfgjson ${hijack_script} ip -6 route show) || true echo "$ans" | tail -n 15 | grep "fc03::1" +# offload # LKL_VIRTIO_NET_F_HOST_TSO4 && LKL_VIRTIO_NET_F_GUEST_TSO4 # LKL_VIRTIO_NET_F_CSUM && LKL_VIRTIO_NET_F_GUEST_CSUM -LKL_HIJACK_OFFLOAD=0x883 sh ${script_dir}/run_netperf.sh 192.168.13.1 1 0 TCP_STREAM -LKL_HIJACK_OFFLOAD=0x883 sh ${script_dir}/run_netperf.sh 192.168.13.1 1 0 TCP_MAERTS +cat << EOF > ${cfgjson} +{ + "gateway":"192.168.13.1", + "gateway6":"fc03::1", + "interfaces":[ + { + "offload":"0x883", + "type":"tap", + "param":"lkl_ptt0", + "ip":"192.168.13.2", + "masklen":"24", + "ipv6":"fc03::2", + "masklen6":"64" + } + ] +} +EOF +LKL_HIJACK_CONFIG_FILE=$cfgjson sh \ + ${script_dir}/run_netperf.sh 192.168.13.1 1 0 TCP_STREAM +LKL_HIJACK_CONFIG_FILE=$cfgjson sh \ + ${script_dir}/run_netperf.sh 192.168.13.1 1 0 TCP_MAERTS + +# offload # LKL_VIRTIO_NET_F_HOST_TSO4 && LKL_VIRTIO_NET_F_MRG_RXBUF # LKL_VIRTIO_NET_F_CSUM && LKL_VIRTIO_NET_F_GUEST_CSUM -LKL_HIJACK_OFFLOAD=0x8803 sh ${script_dir}/run_netperf.sh 192.168.13.1 1 0 TCP_MAERTS -sh ${script_dir}/run_netperf.sh 192.168.13.1 1 0 TCP_RR -sh ${script_dir}/run_netperf.sh fc03::1 1 0 TCP_STREAM +cat << EOF > ${cfgjson} +{ + "gateway":"192.168.13.1", + "gateway6":"fc03::1", + "interfaces":[ + { + "offload":"0x8803", + "type":"tap", + "param":"lkl_ptt0", + "ip":"192.168.13.2", + "masklen":"24", + "ipv6":"fc03::2", + "masklen6":"64" + } + ] +} +EOF + +LKL_HIJACK_CONFIG_FILE=$cfgjson sh \ + ${script_dir}/run_netperf.sh 192.168.13.1 1 0 TCP_MAERTS + +cat << EOF > ${cfgjson} +{ + "gateway":"192.168.13.1", + "gateway6":"fc03::1", + "interfaces":[ + { + "type":"tap", + "param":"lkl_ptt0", + "ip":"192.168.13.2", + "masklen":"24", + "ipv6":"fc03::2", + "masklen6":"64" + } + ] +} +EOF + +LKL_HIJACK_CONFIG_FILE=$cfgjson sh \ + ${script_dir}/run_netperf.sh 192.168.13.1 1 0 TCP_RR +LKL_HIJACK_CONFIG_FILE=$cfgjson sh \ + ${script_dir}/run_netperf.sh fc03::1 1 0 TCP_STREAM # QDISC test -qdisc=$(LKL_HIJACK_NET_QDISC="root|fq" ${hijack_script} tc -s -d qdisc show) +cat << EOF > ${cfgjson} +{ + "gateway":"192.168.13.1", + "gateway6":"fc03::1", + "interfaces":[ + { + "type":"tap", + "param":"lkl_ptt0", + "ip":"192.168.13.2", + "masklen":"24", + "ipv6":"fc03::2", + "masklen6":"64", + "mac":"aa:bb:cc:dd:ee:ff", + "qdisc":"root|fq" + } + ] +} +EOF + +qdisc=$(LKL_HIJACK_CONFIG_FILE=$cfgjson ${hijack_script} tc -s -d qdisc show) echo "$qdisc" echo "$qdisc" | grep "qdisc fq" > /dev/null echo "$qdisc" | grep throttled > /dev/null +echo "== Multiple interfaces with TAP tests==" +# Set up 2nd TAP device we'd like to use +sudo ip tuntap del dev lkl_ptt1 mode tap || true +sudo ip tuntap add dev lkl_ptt1 mode tap user $USER +sudo ip link set dev lkl_ptt1 up +sudo ip addr add dev lkl_ptt1 192.168.14.1/24 +sudo ip -6 addr add dev lkl_ptt1 fc04::1/64 + +cat << EOF > ${cfgjson} +{ + "gateway":"192.168.13.1", + "gateway6":"fc03::1", + "interfaces":[ + { + "type":"tap", + "param":"lkl_ptt0", + "ip":"192.168.13.2", + "masklen":"24", + "ipv6":"fc03::2", + "masklen6":"64", + "mac":"aa:bb:cc:dd:ee:ff" + }, + { + "type":"tap", + "param":"lkl_ptt1", + "ip":"192.168.14.2", + "masklen":"24", + "ipv6":"fc04::2", + "masklen6":"64", + "mac":"aa:bb:cc:dd:ee:aa" + } + ] +} +EOF + +# Make sure our device has the addresses we expect +addr=$(LKL_HIJACK_DEBUG=1 \ + LKL_HIJACK_CONFIG_FILE=$cfgjson ${hijack_script} ip addr) +echo "$addr" | grep eth0 +echo "$addr" | grep 192.168.13.2 +echo "$addr" | grep "aa:bb:cc:dd:ee:ff" +echo "$addr" | grep "fc03::2" +echo "$addr" | grep eth1 +echo "$addr" | grep 192.168.14.2 +echo "$addr" | grep "aa:bb:cc:dd:ee:aa" +echo "$addr" | grep "fc04::2" +! echo "$addr" | grep "WARN: failed to free" + +# Copy ping so we're allowed to run it under LKL +cp `which ping` . +cp `which ping6` . + +# Make sure we can ping the host from inside LKL +LKL_HIJACK_CONFIG_FILE=$cfgjson ${hijack_script} ./ping 192.168.13.1 -c 1 +LKL_HIJACK_CONFIG_FILE=$cfgjson ${hijack_script} ./ping6 fc03::1 -c 1 +LKL_HIJACK_CONFIG_FILE=$cfgjson ${hijack_script} ./ping 192.168.14.1 -c 1 +LKL_HIJACK_CONFIG_FILE=$cfgjson ${hijack_script} ./ping6 fc04::1 -c 1 +rm ./ping ./ping6 + +neigh1="192.168.13.100|12:34:56:78:9a:bc" +neigh2="fc03::100|12:34:56:78:9a:be" +neigh3="192.168.14.100|12:34:56:78:9a:bd" +neigh4="fc04::100|12:34:56:78:9a:bf" + +cat << EOF > ${cfgjson} +{ + "gateway":"192.168.13.1", + "gateway6":"fc03::1", + "interfaces":[ + { + "type":"tap", + "param":"lkl_ptt0", + "ip":"192.168.13.2", + "masklen":"24", + "ipv6":"fc03::2", + "masklen6":"64", + "mac":"aa:bb:cc:dd:ee:ff", + "neigh":"${neigh1};${neigh2}" + }, + { + "type":"tap", + "param":"lkl_ptt1", + "ip":"192.168.14.2", + "masklen":"24", + "ipv6":"fc04::2", + "masklen6":"64", + "mac":"aa:bb:cc:dd:ee:aa", + "neigh":"${neigh3};${neigh4}" + } + ] +} +EOF + +# add neighbor entries +ans=$(LKL_HIJACK_CONFIG_FILE=$cfgjson ${hijack_script} ip neighbor show) || true +echo "$ans" | tail -n 15 | grep "12:34:56:78:9a:bc" +echo "$ans" | tail -n 15 | grep "12:34:56:78:9a:be" +echo "$ans" | tail -n 15 | grep "12:34:56:78:9a:bd" +echo "$ans" | tail -n 15 | grep "12:34:56:78:9a:bf" + +# gateway +ans=$(LKL_HIJACK_CONFIG_FILE=$cfgjson ${hijack_script} ip route show) || true +echo "$ans" | tail -n 15 | grep "192.168.13.1" + +# gateway v6 +ans=$(LKL_HIJACK_CONFIG_FILE=$cfgjson ${hijack_script} ip -6 route show) || true +echo "$ans" | tail -n 15 | grep "fc03::1" + +echo "== multiple table tests ==" + +cat << EOF > ${cfgjson} +{ + "gateway":"192.168.13.1", + "gateway6":"fc03::1", + "interfaces":[ + { + "type":"tap", + "param":"lkl_ptt0", + "ip":"192.168.13.2", + "masklen":"24", + "ifgateway":"192.168.13.1", + "ipv6":"fc03::2", + "masklen6":"64", + "ifgateway6":"fc03::1", + "mac":"aa:bb:cc:dd:ee:ff", + "neigh":"${neigh1};${neigh2}" + }, + { + "type":"tap", + "param":"lkl_ptt1", + "ip":"192.168.14.2", + "masklen":"24", + "ifgateway":"192.168.14.1", + "ipv6":"fc04::2", + "masklen6":"64", + "ifgateway6":"fc04::1", + "mac":"aa:bb:cc:dd:ee:aa", + "neigh":"${neigh3};${neigh4}" + } + ] +} +EOF + # Make sure our device has ipv4 rule we expect -addr=$(LKL_HIJACK_NET_IFGATEWAY=192.168.13.5 \ - ${hijack_script} ip rule show) +addr=$(LKL_HIJACK_CONFIG_FILE=$cfgjson ${hijack_script} ip rule show) echo "$addr" | grep 192.168.13.2 +echo "$addr" | grep 192.168.14.2 # Make sure our device has ipv6 rule we expect -addr=$(LKL_HIJACK_NET_IFGATEWAY6=fc03::5 \ - ${hijack_script} ip -6 rule show) +addr=$(LKL_HIJACK_CONFIG_FILE=$cfgjson ${hijack_script} ip -6 rule show) echo "$addr" | grep fc03::2 +echo "$addr" | grep fc04::2 # Make sure our device has ipv4 rule table -addr=$(LKL_HIJACK_NET_IFGATEWAY=192.168.13.5 \ - ${hijack_script} ip route show table 4) -echo "$addr" | grep 192.168.13.5 -echo "$addr" | grep 192.168.13.0 +addr=$(LKL_HIJACK_CONFIG_FILE=$cfgjson ${hijack_script} ip route show table 4) +echo "$addr" | grep 192.168.13.1 # Make sure our device has ipv6 rule table -addr=$(LKL_HIJACK_NET_IFGATEWAY6=fc03::5 \ - ${hijack_script} ip -6 route show table 5) -echo "$addr" | grep fc03::5 +addr=$(LKL_HIJACK_CONFIG_FILE=$cfgjson \ + ${hijack_script} ip -6 route show table 5) echo "$addr" | grep fc03:: +echo "$addr" | grep fc03::1 + +# Make sure our device has ipv4 rule table +addr=$(LKL_HIJACK_CONFIG_FILE=$cfgjson ${hijack_script} ip route show table 6) +echo "$addr" | grep 192.168.14.1 + +# Make sure our device has ipv6 rule table +addr=$(LKL_HIJACK_CONFIG_FILE=$cfgjson \ + ${hijack_script} ip -6 route show table 7) +echo "$addr" | grep fc04:: +echo "$addr" | grep fc04::1 if [ -z "`printenv CONFIG_AUTO_LKL_VIRTIO_NET_VDE`" ]; then exit 0 @@ -248,10 +544,24 @@ if [ ! -x "$(which vde_switch)" ]; then fi VDESWITCH=${work_dir}/vde_switch -export LKL_HIJACK_NET_IFTYPE=vde -export LKL_HIJACK_NET_IFPARAMS=${VDESWITCH} -export LKL_HIJACK_NET_IP=192.168.13.2 -export LKL_HIJACK_NET_NETMASK_LEN=24 +cat << EOF > ${cfgjson} +{ + "gateway":"192.168.13.1", + "gateway6":"fc03::1", + "interfaces":[ + { + "type":"vde", + "param":"${VDESWITCH}", + "ip":"192.168.13.2", + "masklen":"24", + "ipv6":"fc03::2", + "masklen6":"64", + "mac":"aa:bb:cc:dd:ee:ff", + "neigh":"${neigh1};${neigh2}" + } + ] +} +EOF sudo ip link set dev lkl_ptt0 down &> /dev/null || true sudo ip link del dev lkl_ptt0 &> /dev/null || true @@ -263,7 +573,7 @@ sleep 2 vde_switch -d -t lkl_ptt0 -s ${VDESWITCH} -p ${VDESWITCH}.pid # Make sure our device has the addresses we expect -addr=$(LKL_HIJACK_NET_MAC="aa:bb:cc:dd:ee:ff" ${hijack_script} ip addr) +addr=$(LKL_HIJACK_CONFIG_FILE=$cfgjson ${hijack_script} ip addr) echo "$addr" | grep eth0 echo "$addr" | grep 192.168.13.2 echo "$addr" | grep "aa:bb:cc:dd:ee:ff" @@ -272,10 +582,10 @@ echo "$addr" | grep "aa:bb:cc:dd:ee:ff" cp $(which ping) . # Make sure we can ping the host from inside LKL -${hijack_script} ./ping 192.168.13.1 -c 1 +LKL_HIJACK_CONFIG_FILE=$cfgjson ${hijack_script} ./ping 192.168.13.1 -c 1 rm ./ping # Now let's check that the host can see LKL. sudo arp -d 192.168.13.2 sudo ping -i 0.01 -c 65 192.168.13.2 & -${hijack_script} sleep 3 +LKL_HIJACK_CONFIG_FILE=$cfgjson ${hijack_script} sleep 3 diff --git a/tools/lkl/tests/run_netperf.sh b/tools/lkl/tests/run_netperf.sh index 570555ed5689db..2624cebbb1259c 100644 --- a/tools/lkl/tests/run_netperf.sh +++ b/tools/lkl/tests/run_netperf.sh @@ -61,6 +61,7 @@ clean() { } clean_with_tap() { + rm -rf ${work_dir} sudo ip link set dev $LKL_HIJACK_NET_IFPARAMS down &> /dev/null || true sudo ip tuntap del dev $LKL_HIJACK_NET_IFPARAMS mode tap &> /dev/null || true clean @@ -68,17 +69,28 @@ clean_with_tap() { trap clean EXIT -# LKL_HIJACK_NET_IFTYPE is not set, which means it's not called from +# LKL_HIJACK_CONFIG_FILE is not set, which means it's not called from # hijack-test.sh. Needs to set up things first. -if [ -z ${LKL_HIJACK_NET_IFTYPE+x} ] +if [ -z ${LKL_HIJACK_CONFIG_FILE+x} ] then # Setting up environmental vars and TAP - export LKL_HIJACK_NET_IFTYPE=tap - export LKL_HIJACK_NET_IFPARAMS=lkl_ptt0 - export LKL_HIJACK_NET_IP=192.168.13.2 - export LKL_HIJACK_NET_NETMASK_LEN=24 - export LKL_HIJACK_NET_IPV6=fc03::2 - export LKL_HIJACK_NET_NETMASK6_LEN=64 + work_dir=$(mktemp -d) + cfgjson=${work_dir}/hijack-test.conf + echo \ + "{" \ + "\"gateway\":\"192.168.13.1\"," \ + "\"gateway6\":\"fc03::1\"," \ + "\"interfaces\":[" \ + "{" \ + "\"type\":\"tap\"" \ + "\"param\":\"lkl_ptt0\"" \ + "\"ip\":\"192.168.13.2\"" \ + "\"masklen\":\"24\"" \ + "\"ipv6\":\"fc03::2\"" \ + "\"masklen6\":\"64\"" \ + "}" \ + "]" \ + "}" > ${cfgjson} sudo ip tuntap del dev $LKL_HIJACK_NET_IFPARAMS mode tap || true sudo ip tuntap add dev $LKL_HIJACK_NET_IFPARAMS mode tap user $USER