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