From 6342d778873861011c3a2b12df74c92c7a6a0d81 Mon Sep 17 00:00:00 2001 From: Victor Nogueira Date: Thu, 30 Jan 2020 21:42:16 +0000 Subject: [PATCH 01/13] add Lunatik submodule --- .gitmodules | 3 +++ init/Kconfig | 6 ++++++ lib/Makefile | 4 ++++ lib/lunatik | 1 + net/core/Makefile | 2 ++ 5 files changed, 16 insertions(+) create mode 100644 .gitmodules create mode 160000 lib/lunatik diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000000000..f1d9bd02ab7ca8 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "lib/lunatik"] + path = lib/lunatik + url = https://github.com/luainkernel/lunatik.git diff --git a/init/Kconfig b/init/Kconfig index 1e234e2f1cba7a..ea5c89ce390876 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1147,6 +1147,12 @@ config HAVE_PCSPKR_PLATFORM config BPF bool +config LUNATIK + bool "Lunatik" + default n + help + Support for the Lua interpreter + menuconfig EXPERT bool "Configure standard kernel features (expert users)" # Unhide debug options, to make the on-by-default options visible diff --git a/lib/Makefile b/lib/Makefile index 42387644681094..5081250428b043 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -270,3 +270,7 @@ obj-$(CONFIG_GENERIC_LIB_LSHRDI3) += lshrdi3.o obj-$(CONFIG_GENERIC_LIB_MULDI3) += muldi3.o obj-$(CONFIG_GENERIC_LIB_CMPDI2) += cmpdi2.o obj-$(CONFIG_GENERIC_LIB_UCMPDI2) += ucmpdi2.o + +subdir-ccflags-y += -I$(srctree)/lib/lunatik/lua \ + -D_KERNEL +obj-$(CONFIG_LUNATIK) += lunatik/ diff --git a/lib/lunatik b/lib/lunatik new file mode 160000 index 00000000000000..fb7ef47c930b54 --- /dev/null +++ b/lib/lunatik @@ -0,0 +1 @@ +Subproject commit fb7ef47c930b544804f544654302dac673a6ca48 diff --git a/net/core/Makefile b/net/core/Makefile index 80175e6a2eb871..dd04a22602b56f 100644 --- a/net/core/Makefile +++ b/net/core/Makefile @@ -8,6 +8,8 @@ obj-y := sock.o request_sock.o skbuff.o datagram.o stream.o scm.o \ obj-$(CONFIG_SYSCTL) += sysctl_net_core.o +CFLAGS_dev.o = -Ilib/lunatik/lua/ -D_KERNEL +CFLAGS_filter.o = -Ilib/lunatik/lua/ -D_KERNEL obj-y += dev.o ethtool.o dev_addr_lists.o dst.o netevent.o \ neighbour.o rtnetlink.o utils.o link_watch.o filter.o \ sock_diag.o dev_ioctl.o tso.o sock_reuseport.o \ From 8d652aa928a1dbf9010b35cf7bbbfd7dd9b2c5d9 Mon Sep 17 00:00:00 2001 From: Victor Nogueira Date: Fri, 19 Jul 2019 08:04:56 -0300 Subject: [PATCH 02/13] add XDPLua --- include/linux/filter.h | 9 + include/linux/netdevice.h | 4 + include/net/xdp.h | 4 + include/uapi/linux/bpf.h | 15 +- include/uapi/linux/if_link.h | 3 + net/core/dev.c | 54 ++++++ net/core/filter.c | 203 +++++++++++++++++++++ net/core/rtnetlink.c | 18 ++ net/xdp/Kconfig | 7 + samples/bpf/Makefile | 4 + samples/bpf/xdplua_user.c | 213 ++++++++++++++++++++++ tools/include/uapi/linux/bpf.h | 15 +- tools/include/uapi/linux/if_link.h | 3 + tools/lib/bpf/bpf.c | 128 +++++++++++++ tools/lib/bpf/libbpf.h | 3 + tools/testing/selftests/bpf/bpf_helpers.h | 27 +++ 16 files changed, 708 insertions(+), 2 deletions(-) create mode 100644 samples/bpf/xdplua_user.c diff --git a/include/linux/filter.h b/include/linux/filter.h index 6791a0ac013923..c11e3095aa7147 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h @@ -1113,4 +1113,13 @@ struct bpf_sock_ops_kern { */ }; +#ifdef CONFIG_XDP_LUA +extern struct list_head lua_state_cpu_list; + +struct lua_state_cpu { + struct lua_State *L; + int cpu; + struct list_head list; +}; +#endif /* CONFIG_XDP_LUA */ #endif /* __LINUX_FILTER_H__ */ diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index d837dad24b4ce5..d2f7b0f57d4dc8 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -3587,6 +3587,10 @@ u32 __dev_xdp_query(struct net_device *dev, bpf_op_t xdp_op, enum bpf_netdev_command cmd); int xdp_umem_query(struct net_device *dev, u16 queue_id); +#ifdef CONFIG_XDP_LUA +int generic_xdp_lua_install_prog(char *lua_prog); +#endif /* CONFIG_XDP_LUA */ + int __dev_forward_skb(struct net_device *dev, struct sk_buff *skb); int dev_forward_skb(struct net_device *dev, struct sk_buff *skb); bool is_skb_forwardable(const struct net_device *dev, diff --git a/include/net/xdp.h b/include/net/xdp.h index 76b95256c26649..2887d9a5c93cec 100644 --- a/include/net/xdp.h +++ b/include/net/xdp.h @@ -70,6 +70,10 @@ struct xdp_buff { void *data_hard_start; unsigned long handle; struct xdp_rxq_info *rxq; +#ifdef CONFIG_XDP_LUA + struct sk_buff *skb; + struct lua_State *L; +#endif /* CONFIG_XDP_LUA */ }; struct xdp_frame { diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 66917a4eba2716..75ad4f93ca1a49 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -2226,7 +2226,20 @@ union bpf_attr { FN(get_current_cgroup_id), \ FN(get_local_storage), \ FN(sk_select_reuseport), \ - FN(skb_ancestor_cgroup_id), + FN(skb_ancestor_cgroup_id), \ + /* #ifdef CONFIG_XDP_LUA */ \ + FN(lua_pcall), \ + FN(lua_pop), \ + FN(lua_pushinteger), \ + FN(lua_pushlightuserdata), \ + FN(lua_pushlstring), \ + FN(lua_pushmap), \ + FN(lua_pushskb), \ + FN(lua_pushstring), \ + FN(lua_setstate), \ + FN(lua_toboolean), \ + FN(lua_tointeger), + /* #endif CONFIG_XDP_LUA */ /* integer value in 'imm' field of BPF_CALL instruction selects which helper * function eBPF program intends to call diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index 43391e2d1153ad..45a39ccb3032b2 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -945,6 +945,9 @@ enum { IFLA_XDP_DRV_PROG_ID, IFLA_XDP_SKB_PROG_ID, IFLA_XDP_HW_PROG_ID, +#ifdef CONFIG_XDP_LUA + IFLA_XDP_LUA_PROG, +#endif /* CONFIG_XDP_LUA */ __IFLA_XDP_MAX, }; diff --git a/net/core/dev.c b/net/core/dev.c index 93243479085fb1..0939ca6cf497eb 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -72,6 +72,12 @@ * - netif_rx() feedback */ +#ifdef CONFIG_XDP_LUA +#include +#include +#include +#endif /* CONFIG_XDP_LUA */ + #include #include #include @@ -164,6 +170,10 @@ static int call_netdevice_notifiers_info(unsigned long val, struct netdev_notifier_info *info); static struct napi_struct *napi_by_id(unsigned int napi_id); +#ifdef CONFIG_XDP_LUA +struct list_head lua_state_cpu_list; +#endif /* CONFIG_XDP_LUA */ + /* * The @dev_base_head list is protected by @dev_base_lock and the rtnl * semaphore. @@ -4320,6 +4330,9 @@ static u32 netif_receive_generic_xdp(struct sk_buff *skb, rxqueue = netif_get_rxqueue(skb); xdp->rxq = &rxqueue->xdp_rxq; +#ifdef CONFIG_XDP_LUA + xdp->skb = skb; +#endif /* CONFIG_XDP_LUA */ act = bpf_prog_run_xdp(xdp_prog, xdp); @@ -5088,6 +5101,22 @@ static int generic_xdp_install(struct net_device *dev, struct netdev_bpf *xdp) return ret; } +#ifdef CONFIG_XDP_LUA +int generic_xdp_lua_install_prog(char *lua_prog) +{ + struct lua_state_cpu *sc; + + list_for_each_entry(sc, &lua_state_cpu_list, list) { + if (luaL_dostring(sc->L, lua_prog)) { + pr_err(KERN_INFO "error: %s\nOn cpu: %d\n", + lua_tostring(sc->L, -1), sc->cpu); + return -EINVAL; + } + } + return 0; +} +#endif /* CONFIG_XDP_LUA */ + static int netif_receive_skb_internal(struct sk_buff *skb) { int ret; @@ -9570,6 +9599,9 @@ static struct pernet_operations __net_initdata default_device_ops = { static int __init net_dev_init(void) { int i, rc = -ENOMEM; +#ifdef CONFIG_XDP_LUA + struct lua_state_cpu *new_state_cpu; +#endif /* CONFIG_XDP_LUA */ BUG_ON(!dev_boot_phase); @@ -9584,6 +9616,9 @@ static int __init net_dev_init(void) INIT_LIST_HEAD(&ptype_base[i]); INIT_LIST_HEAD(&offload_base); +#ifdef CONFIG_XDP_LUA + INIT_LIST_HEAD(&lua_state_cpu_list); +#endif /* CONFIG_XDP_LUA */ if (register_pernet_subsys(&netdev_net_ops)) goto out; @@ -9614,6 +9649,25 @@ static int __init net_dev_init(void) init_gro_hash(&sd->backlog); sd->backlog.poll = process_backlog; sd->backlog.weight = weight_p; + +#ifdef CONFIG_XDP_LUA + new_state_cpu = (struct lua_state_cpu *) + kmalloc(sizeof(struct lua_state_cpu), GFP_ATOMIC); + if (!new_state_cpu) + continue; + + new_state_cpu->L = luaL_newstate(); + if (!new_state_cpu->L) { + kfree(new_state_cpu); + continue; + } + + luaL_openlibs(new_state_cpu->L); + lua_pop(new_state_cpu->L, 1); + new_state_cpu->cpu = i; + + list_add(&new_state_cpu->list, &lua_state_cpu_list); +#endif /* CONFIG_XDP_LUA */ } dev_boot_phase = 0; diff --git a/net/core/filter.c b/net/core/filter.c index 5e00f2b85a5681..fce7bc2b1ddcdb 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -69,6 +69,10 @@ #include #include +#ifdef CONFIG_XDP_LUA +#include +#endif /* CONFIG_XDP_LUA */ + /** * sk_filter_trim_cap - run a packet through a socket filter * @sk: sock associated with &sk_buff @@ -4787,6 +4791,181 @@ static const struct bpf_func_proto bpf_lwt_seg6_adjust_srh_proto = { }; #endif /* CONFIG_IPV6_SEG6_BPF */ +#ifdef CONFIG_XDP_LUA +BPF_CALL_4(bpf_lua_pcall, struct xdp_buff *, ctx, char *, funcname, + int, num_args, int, num_rets) { + if (lua_getglobal(ctx->L, funcname) != LUA_TFUNCTION) { + pr_err("function %s not found\n", funcname); + lua_pop(ctx->L, num_args); + return 0; + } + + lua_insert(ctx->L, 1); + if (lua_pcall(ctx->L, num_args, num_rets, 0)) { + pr_err("%s\n", lua_tostring(ctx->L, -1)); + lua_pop(ctx->L, 1); + return 0; + } + return num_rets; +} + +static const struct bpf_func_proto bpf_lua_pcall_proto = { + .func = bpf_lua_pcall, + .gpl_only = false, + .pkt_access = false, + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_CTX, + .arg2_type = ARG_ANYTHING, + .arg3_type = RET_INTEGER, + .arg4_type = RET_INTEGER, +}; + +BPF_CALL_2(bpf_lua_pop, struct xdp_buff *, ctx, int, index) { + lua_pop(ctx->L, index); + return 0; +} + +static const struct bpf_func_proto bpf_lua_pop_proto = { + .func = bpf_lua_pop, + .gpl_only = false, + .pkt_access = false, + .ret_type = RET_VOID, + .arg1_type = ARG_PTR_TO_CTX, + .arg2_type = ARG_ANYTHING, +}; + +BPF_CALL_2(bpf_lua_pushinteger, struct xdp_buff *, ctx, int, num) { + lua_pushinteger(ctx->L, num); + return 0; +} + +static const struct bpf_func_proto bpf_lua_pushinteger_proto = { + .func = bpf_lua_pushinteger, + .gpl_only = false, + .pkt_access = false, + .ret_type = RET_VOID, + .arg1_type = ARG_PTR_TO_CTX, + .arg2_type = ARG_ANYTHING, +}; + +BPF_CALL_2(bpf_lua_pushlightuserdata, struct xdp_buff *, ctx, void *, ptr) { + lua_pushlightuserdata(ctx->L, ptr); + return 0; +} + +static const struct bpf_func_proto bpf_lua_pushlightuserdata_proto = { + .func = bpf_lua_pushlightuserdata, + .gpl_only = false, + .pkt_access = false, + .ret_type = RET_VOID, + .arg1_type = ARG_PTR_TO_CTX, + .arg2_type = ARG_ANYTHING, +}; + +BPF_CALL_3(bpf_lua_pushlstring, struct xdp_buff *, ctx, const char *, str, size_t, len) { + lua_pushlstring(ctx->L, str, len); + return 0; +} + +static const struct bpf_func_proto bpf_lua_pushlstring_proto = { + .func = bpf_lua_pushlstring, + .gpl_only = false, + .pkt_access = false, + .ret_type = RET_VOID, + .arg1_type = ARG_PTR_TO_CTX, + .arg2_type = ARG_ANYTHING, + .arg3_type = ARG_ANYTHING, +}; + +BPF_CALL_2(bpf_lua_pushmap, struct xdp_buff *, ctx, struct bpf_map *, map) { + lua_pushlightuserdata(ctx->L, map); + return 0; +} + +static const struct bpf_func_proto bpf_lua_pushmap_proto = { + .func = bpf_lua_pushmap, + .gpl_only = false, + .pkt_access = false, + .ret_type = RET_VOID, + .arg1_type = ARG_PTR_TO_CTX, + .arg2_type = ARG_ANYTHING, +}; + +BPF_CALL_1(bpf_lua_pushskb, struct xdp_buff *, ctx) { + lua_pushlightuserdata(ctx->L, ctx->skb); + return 0; +} + +static const struct bpf_func_proto bpf_lua_pushskb_proto = { + .func = bpf_lua_pushskb, + .gpl_only = false, + .pkt_access = false, + .ret_type = RET_VOID, + .arg1_type = ARG_PTR_TO_CTX, +}; + +BPF_CALL_2(bpf_lua_pushstring, struct xdp_buff *, ctx, const char *, str) { + lua_pushstring(ctx->L, str); + return 0; +} + +static const struct bpf_func_proto bpf_lua_pushstring_proto = { + .func = bpf_lua_pushstring, + .gpl_only = false, + .pkt_access = false, + .ret_type = RET_VOID, + .arg1_type = ARG_PTR_TO_CTX, + .arg2_type = ARG_ANYTHING, +}; + +BPF_CALL_1(bpf_lua_setstate, struct xdp_buff *, ctx){ + struct lua_state_cpu *sc; + int cpu = smp_processor_id(); + + list_for_each_entry(sc, &lua_state_cpu_list, list) { + if (sc->cpu == cpu) { + ctx->L = sc->L; + break; + } + } + return 0; +} + +static const struct bpf_func_proto bpf_lua_setstate_proto = { + .func = bpf_lua_setstate, + .gpl_only = false, + .pkt_access = false, + .ret_type = RET_VOID, + .arg1_type = ARG_PTR_TO_CTX, +}; + +BPF_CALL_2(bpf_lua_toboolean, struct xdp_buff *, ctx, int, index) { + return lua_toboolean(ctx->L, index); +} + +static const struct bpf_func_proto bpf_lua_toboolean_proto = { + .func = bpf_lua_toboolean, + .gpl_only = false, + .pkt_access = false, + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_CTX, + .arg2_type = ARG_ANYTHING, +}; + +BPF_CALL_2(bpf_lua_tointeger, struct xdp_buff *, ctx, int, index) { + return lua_tointeger(ctx->L, index); +} + +static const struct bpf_func_proto bpf_lua_tointeger_proto = { + .func = bpf_lua_tointeger, + .gpl_only = false, + .pkt_access = false, + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_CTX, + .arg2_type = ARG_ANYTHING, +}; +#endif /* CONFIG_XDP_LUA */ + bool bpf_helper_changes_pkt_data(void *func) { if (func == bpf_skb_vlan_push || @@ -4842,6 +5021,30 @@ bpf_base_func_proto(enum bpf_func_id func_id) if (capable(CAP_SYS_ADMIN)) return bpf_get_trace_printk_proto(); /* else: fall through */ +#ifdef CONFIG_XDP_LUA + case BPF_FUNC_lua_pcall: + return &bpf_lua_pcall_proto; + case BPF_FUNC_lua_pop: + return &bpf_lua_pop_proto; + case BPF_FUNC_lua_pushinteger: + return &bpf_lua_pushinteger_proto; + case BPF_FUNC_lua_pushlightuserdata: + return &bpf_lua_pushlightuserdata_proto; + case BPF_FUNC_lua_pushlstring: + return &bpf_lua_pushlstring_proto; + case BPF_FUNC_lua_pushmap: + return &bpf_lua_pushmap_proto; + case BPF_FUNC_lua_pushskb: + return &bpf_lua_pushskb_proto; + case BPF_FUNC_lua_pushstring: + return &bpf_lua_pushstring_proto; + case BPF_FUNC_lua_setstate: + return &bpf_lua_setstate_proto; + case BPF_FUNC_lua_toboolean: + return &bpf_lua_toboolean_proto; + case BPF_FUNC_lua_tointeger: + return &bpf_lua_tointeger_proto; +#endif /* CONFIG_XDP_LUA */ default: return NULL; } diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 37c7936124e618..9b1b67995bf82b 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1790,6 +1790,9 @@ static const struct nla_policy ifla_xdp_policy[IFLA_XDP_MAX + 1] = { [IFLA_XDP_ATTACHED] = { .type = NLA_U8 }, [IFLA_XDP_FLAGS] = { .type = NLA_U32 }, [IFLA_XDP_PROG_ID] = { .type = NLA_U32 }, +#ifdef CONFIG_XDP_LUA + [IFLA_XDP_LUA_PROG] = { .type = NLA_STRING, .len = 8192 }, +#endif /* CONFIG_XDP_LUA */ }; static const struct rtnl_link_ops *linkinfo_to_kind_ops(const struct nlattr *nla) @@ -2628,6 +2631,21 @@ static int do_setlink(const struct sk_buff *skb, goto errout; status |= DO_SETLINK_NOTIFY; } + +#ifdef CONFIG_XDP_LUA + if (xdp[IFLA_XDP_LUA_PROG]) { + char *lua_prog = nla_data(xdp[IFLA_XDP_LUA_PROG]); + if (!lua_prog) { + err = -EINVAL; + goto errout; + } + + err = generic_xdp_lua_install_prog(lua_prog); + if (err) + goto errout; + } +#endif /* CONFIG_XDP_LUA */ + } errout: diff --git a/net/xdp/Kconfig b/net/xdp/Kconfig index 90e4a7152854ff..f91e344dafe76c 100644 --- a/net/xdp/Kconfig +++ b/net/xdp/Kconfig @@ -5,3 +5,10 @@ config XDP_SOCKETS help XDP sockets allows a channel between XDP programs and userspace applications. + +config XDP_LUA + bool "XDP LUA" + depends on BPF_SYSCALL && LUNATIK + default n + help + Support for Lua scripts inside XDP diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile index 36f9f41d094b2a..fce0b871260cae 100644 --- a/samples/bpf/Makefile +++ b/samples/bpf/Makefile @@ -53,6 +53,8 @@ hostprogs-y += xdpsock hostprogs-y += xdp_fwd hostprogs-y += task_fd_query hostprogs-y += xdp_sample_pkts +# CONFIG_XDP_LUA +hostprogs-y += xdplua # Libbpf dependencies LIBBPF = $(TOOLS_PATH)/lib/bpf/libbpf.a @@ -109,6 +111,8 @@ xdpsock-objs := xdpsock_user.o xdp_fwd-objs := xdp_fwd_user.o task_fd_query-objs := bpf_load.o task_fd_query_user.o $(TRACE_HELPERS) xdp_sample_pkts-objs := xdp_sample_pkts_user.o $(TRACE_HELPERS) +# CONFIG_XDPLUA +xdplua-objs := xdplua_user.o # Tell kbuild to always build the programs always := $(hostprogs-y) diff --git a/samples/bpf/xdplua_user.c b/samples/bpf/xdplua_user.c new file mode 100644 index 00000000000000..d9b5acc665e1fc --- /dev/null +++ b/samples/bpf/xdplua_user.c @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2019-2020 Victor Nogueira + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bpf/libbpf.h" +#include "bpf/bpf.h" + +#include "bpf_util.h" + +static int ifindex = 0; + +static void usage(const char *prog) { + fprintf(stderr, "usage: %s [OPTS]\n" + "\nOPTS:\n" + " -d detach program\n" + " -s lua script path\n" + " -p eBPF program path\n" + " -i iface\n" + " -m monitor\n", + prog); +} + +static char *extract_lua_prog(const char *path) +{ + FILE *f; + long prog_size; + char *lua_prog; + + f = fopen(path, "r"); + if (f == NULL) { + perror("unable to xopen lua file"); + return NULL; + } + + fseek(f, 0 , SEEK_END); + prog_size = ftell(f); + rewind(f); + + lua_prog = (char *) malloc(prog_size + 1); + memset(lua_prog, 0, prog_size + 1); + if (fread(lua_prog, 1, prog_size, f) < 0) { + perror("unable to read lua file"); + return NULL; + } + + lua_prog[prog_size] = '\0'; + fclose(f); + return lua_prog; +} + +static int do_attach_ebpf(int idx, int fd, const char *name) +{ + int err; + + err = bpf_set_link_xdp_fd(idx, fd, XDP_FLAGS_SKB_MODE); + if (err < 0) + fprintf(stderr, "ERROR: failed to attach program to %s\n", name); + + return err; +} + +static int do_attach_lua(const char *name, char *lua_prog) +{ + int err; + + err = bpf_set_link_xdp_lua_prog(lua_prog, 0); + if (err < 0) + fprintf(stderr, "ERROR: failed to attach lua script to %s\n", name); + + return err; +} + +static int do_detach(int idx, const char *name) +{ + int err; + + err = bpf_set_link_xdp_fd(idx, -1, XDP_FLAGS_SKB_MODE); + if (err < 0) + fprintf(stderr, "ERROR: failed to detach program from %s\n", name); + + return err; +} + +static void poll(int map_fd, int interval) { + long cnt; + unsigned int key = 0; + + while(1) { + bpf_map_lookup_elem(map_fd, &key, &cnt); + printf("pkt count: %lu\n", cnt); + sleep(interval); + } +} + +int main(int argc, char *argv[]) +{ + struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY}; + char lua_filename[256]; + char filename[256]; + struct bpf_object *obj; + int opt, prog_fd; + int rx_cnt_map_fd; + int detach = 0, attach_lua = 0, attach_ebpf = 0, monitor = 0; + char *lua_prog = NULL; + const char *optstr = "s:p:i:dm"; + struct bpf_prog_load_attr prog_load_attr = { + .prog_type = BPF_PROG_TYPE_XDP, + }; + struct bpf_map *map; + + memset(lua_filename, 0, 256); + memset(filename, 0, 256); + while ((opt = getopt(argc, argv, optstr)) != -1) { + switch (opt) { + case 's': + snprintf(lua_filename, sizeof(lua_filename), + "%s", optarg); + attach_lua = 1; + break; + case 'p': + snprintf(filename, sizeof(filename), + "%s", optarg); + attach_ebpf = 1; + break; + case 'd': + detach = 1; + break; + case 'i': + ifindex = if_nametoindex(optarg); + break; + case 'm': + monitor = 1; + break; + default: + usage(basename(argv[0])); + return 1; + } + } + + if (attach_ebpf || detach) { + if (!ifindex) { + printf("ERROR: invalid interface name"); + return 1; + } + } + + if (setrlimit(RLIMIT_MEMLOCK, &r)) { + perror("ERROR: setrlimit(RLIMIT_MEMLOCK)"); + return 1; + } + + if (detach) { + if (do_detach(ifindex, lua_filename) < 0) + return 1; + + return 0; + } + + if (attach_ebpf) { + prog_load_attr.file = filename; + + if (bpf_prog_load_xattr(&prog_load_attr, &obj, &prog_fd)) + return 1; + + if (!prog_fd) { + printf("ERROR: failed to load_bpf_file\n"); + return 1; + } + + if (do_attach_ebpf(ifindex, prog_fd, lua_filename) < 0) + return 1; + + } + + if (attach_lua) { + lua_prog = extract_lua_prog(lua_filename); + if (!lua_prog) + return 1; + + if (do_attach_lua(lua_filename, lua_prog) < 0) { + free(lua_prog); + return 1; + } + + free(lua_prog); + } + + if (monitor) { + map = bpf_object__find_map_by_name(obj, "rx_cnt"); + rx_cnt_map_fd = bpf_map__fd(map); + + poll(rx_cnt_map_fd, 1); + } + return 0; +} diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 66917a4eba2716..75ad4f93ca1a49 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -2226,7 +2226,20 @@ union bpf_attr { FN(get_current_cgroup_id), \ FN(get_local_storage), \ FN(sk_select_reuseport), \ - FN(skb_ancestor_cgroup_id), + FN(skb_ancestor_cgroup_id), \ + /* #ifdef CONFIG_XDP_LUA */ \ + FN(lua_pcall), \ + FN(lua_pop), \ + FN(lua_pushinteger), \ + FN(lua_pushlightuserdata), \ + FN(lua_pushlstring), \ + FN(lua_pushmap), \ + FN(lua_pushskb), \ + FN(lua_pushstring), \ + FN(lua_setstate), \ + FN(lua_toboolean), \ + FN(lua_tointeger), + /* #endif CONFIG_XDP_LUA */ /* integer value in 'imm' field of BPF_CALL instruction selects which helper * function eBPF program intends to call diff --git a/tools/include/uapi/linux/if_link.h b/tools/include/uapi/linux/if_link.h index 43391e2d1153ad..9318bac55ac60b 100644 --- a/tools/include/uapi/linux/if_link.h +++ b/tools/include/uapi/linux/if_link.h @@ -945,6 +945,9 @@ enum { IFLA_XDP_DRV_PROG_ID, IFLA_XDP_SKB_PROG_ID, IFLA_XDP_HW_PROG_ID, +/* #ifdef CONFIG_XDP_LUA */ + IFLA_XDP_LUA_PROG, +/* #endif CONFIG_XDP_LUA */ __IFLA_XDP_MAX, }; diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c index 60aa4ca8b2c51b..57cc5e26369812 100644 --- a/tools/lib/bpf/bpf.c +++ b/tools/lib/bpf/bpf.c @@ -620,6 +620,134 @@ int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags) return ret; } +/* #ifdef CONFIG_XDPLUA */ +int bpf_set_link_xdp_lua_prog(char *lua_prog, __u32 flags) +{ + struct sockaddr_nl sa; + int sock, seq = 0, len, ret = -1; + char buf[4096]; + struct nlattr *nla, *nla_xdp; + struct { + struct nlmsghdr nh; + struct ifinfomsg ifinfo; + char attrbuf[64]; + } req; + struct nlmsghdr *nh; + struct nlmsgerr *err; + socklen_t addrlen; + int one = 1; + + memset(&sa, 0, sizeof(sa)); + sa.nl_family = AF_NETLINK; + + sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); + if (sock < 0) { + return -errno; + } + + if (setsockopt(sock, SOL_NETLINK, NETLINK_EXT_ACK, + &one, sizeof(one)) < 0) { + fprintf(stderr, "Netlink error reporting not supported\n"); + } + + if (bind(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) { + ret = -errno; + goto cleanup; + } + + addrlen = sizeof(sa); + if (getsockname(sock, (struct sockaddr *)&sa, &addrlen) < 0) { + ret = -errno; + goto cleanup; + } + + if (addrlen != sizeof(sa)) { + ret = -LIBBPF_ERRNO__INTERNAL; + goto cleanup; + } + + memset(&req, 0, sizeof(req)); + req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); + req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; + req.nh.nlmsg_type = RTM_SETLINK; + req.nh.nlmsg_pid = 0; + req.nh.nlmsg_seq = ++seq; + req.ifinfo.ifi_family = AF_UNSPEC; + req.ifinfo.ifi_index = 1; + + /* started nested attribute for XDP */ + nla = (struct nlattr *)(((char *)&req) + + NLMSG_ALIGN(req.nh.nlmsg_len)); + nla->nla_type = NLA_F_NESTED | IFLA_XDP; + nla->nla_len = NLA_HDRLEN; + + /* add XDP LUA PROG */ + nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len); + nla_xdp->nla_type = IFLA_XDP_LUA_PROG; + if (lua_prog) { + nla_xdp->nla_len = NLA_HDRLEN + strlen(lua_prog) + 1; + memcpy((char *)nla_xdp + NLA_HDRLEN, lua_prog, strlen(lua_prog) + 1); + } else { + ret = -EINVAL; + goto cleanup; + } + nla->nla_len += nla_xdp->nla_len; + + /* if user passed in any flags, add those too */ + if (flags) { + nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len); + nla_xdp->nla_type = IFLA_XDP_FLAGS; + nla_xdp->nla_len = NLA_HDRLEN + sizeof(flags); + memcpy((char *)nla_xdp + NLA_HDRLEN, &flags, sizeof(flags)); + nla->nla_len += nla_xdp->nla_len; + } + + req.nh.nlmsg_len += NLA_ALIGN(nla->nla_len); + + if (send(sock, &req, req.nh.nlmsg_len, 0) < 0) { + ret = -errno; + goto cleanup; + } + + len = recv(sock, buf, sizeof(buf), 0); + if (len < 0) { + ret = -errno; + goto cleanup; + } + + for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len); + nh = NLMSG_NEXT(nh, len)) { + if (nh->nlmsg_pid != sa.nl_pid) { + ret = -LIBBPF_ERRNO__WRNGPID; + goto cleanup; + } + if (nh->nlmsg_seq != seq) { + ret = -LIBBPF_ERRNO__INVSEQ; + goto cleanup; + } + switch (nh->nlmsg_type) { + case NLMSG_ERROR: + err = (struct nlmsgerr *)NLMSG_DATA(nh); + if (!err->error) + continue; + ret = err->error; + nla_dump_errormsg(nh); + goto cleanup; + case NLMSG_DONE: + break; + default: + break; + } + } + + ret = 0; + +cleanup: + close(sock); + return ret; +} +/* #endif CONFIG_XDPLUA */ + int bpf_load_btf(void *btf, __u32 btf_size, char *log_buf, __u32 log_buf_size, bool do_log) { diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h index 96c55fac54c314..523ada3fa48b81 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h @@ -284,6 +284,9 @@ int bpf_prog_load(const char *file, enum bpf_prog_type type, struct bpf_object **pobj, int *prog_fd); int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags); +/* #ifdef CONFIG_XDP_LUA */ +int bpf_set_link_xdp_lua_prog(char *lua_prog, __u32 flags); +/* #endif CONFIG_XDP_LUA */ enum bpf_perf_event_ret { LIBBPF_PERF_EVENT_DONE = 0, diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h index e4be7730222dff..478f25688f90c8 100644 --- a/tools/testing/selftests/bpf/bpf_helpers.h +++ b/tools/testing/selftests/bpf/bpf_helpers.h @@ -144,6 +144,33 @@ static unsigned long long (*bpf_skb_cgroup_id)(void *ctx) = static unsigned long long (*bpf_skb_ancestor_cgroup_id)(void *ctx, int level) = (void *) BPF_FUNC_skb_ancestor_cgroup_id; +/* #ifdef CONFIG_XDP_LUA */ +static int (*bpf_lua_pcall)(void *ctx, char *funcname, int num_args, + int num_rets) = + (void *) BPF_FUNC_lua_pcall; +static void (*bpf_lua_pop)(void *ctx, int index) = + (void *)BPF_FUNC_lua_pop; +static void (*bpf_lua_pushinteger)(void *ctx, int num) = + (void *)BPF_FUNC_lua_pushinteger; +static void (*bpf_lua_pushlightuserdata)(void *ctx, void *ptr) = + (void *)BPF_FUNC_lua_pushlightuserdata; +static void (*bpf_lua_pushlstring)(void *ctx, const char *, + size_t len) = + (void *)BPF_FUNC_lua_pushlstring; +static void (*bpf_lua_pushmap)(void *ctx, void *map) = + (void *)BPF_FUNC_lua_pushmap; +static void (*bpf_lua_pushskb)(void *ctx) = + (void *)BPF_FUNC_lua_pushskb; +static void (*bpf_lua_pushstring)(void *ctx, const char *) = + (void *)BPF_FUNC_lua_pushstring; +static void (*bpf_lua_setstate)(void *ctx) = + (void *)BPF_FUNC_lua_setstate; +static int (*bpf_lua_toboolean)(void *ctx, int index) = + (void *)BPF_FUNC_lua_toboolean; +static int (*bpf_lua_tointeger)(void *ctx, int index) = + (void *)BPF_FUNC_lua_tointeger; +/* #endif CONFIG_XDP_LUA */ + /* llvm builtin functions that eBPF C program may use to * emit BPF_LD_ABS and BPF_LD_IND instructions */ From 287cdfd6c6c6cebc0bd7263617594e150c9506cb Mon Sep 17 00:00:00 2001 From: Victor Nogueira Date: Thu, 30 Jan 2020 21:47:55 +0000 Subject: [PATCH 03/13] add LuaData submodule --- .gitmodules | 3 ++ include/uapi/linux/bpf.h | 2 ++ lib/Makefile | 2 ++ lib/luadata | 1 + net/core/Makefile | 6 ++-- net/core/dev.c | 1 + net/core/filter.c | 39 +++++++++++++++++++++++ tools/include/uapi/linux/bpf.h | 2 ++ tools/testing/selftests/bpf/bpf_helpers.h | 4 +++ 9 files changed, 58 insertions(+), 2 deletions(-) create mode 160000 lib/luadata diff --git a/.gitmodules b/.gitmodules index f1d9bd02ab7ca8..a60359c423290d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "lib/lunatik"] path = lib/lunatik url = https://github.com/luainkernel/lunatik.git +[submodule "lib/luadata"] + path = lib/luadata + url = https://github.com/luainkernel/luadata diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 75ad4f93ca1a49..752a34a254b025 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -2228,6 +2228,8 @@ union bpf_attr { FN(sk_select_reuseport), \ FN(skb_ancestor_cgroup_id), \ /* #ifdef CONFIG_XDP_LUA */ \ + FN(lua_dataref), \ + FN(lua_dataunref), \ FN(lua_pcall), \ FN(lua_pop), \ FN(lua_pushinteger), \ diff --git a/lib/Makefile b/lib/Makefile index 5081250428b043..bff2d9cf4f7b0a 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -272,5 +272,7 @@ obj-$(CONFIG_GENERIC_LIB_CMPDI2) += cmpdi2.o obj-$(CONFIG_GENERIC_LIB_UCMPDI2) += ucmpdi2.o subdir-ccflags-y += -I$(srctree)/lib/lunatik/lua \ + -I$(srctree)/lib/luadata/ \ -D_KERNEL obj-$(CONFIG_LUNATIK) += lunatik/ +obj-$(CONFIG_LUADATA) += luadata/ diff --git a/lib/luadata b/lib/luadata new file mode 160000 index 00000000000000..21137a054a8281 --- /dev/null +++ b/lib/luadata @@ -0,0 +1 @@ +Subproject commit 21137a054a828123deea403b106a87e9e8d2795d diff --git a/net/core/Makefile b/net/core/Makefile index dd04a22602b56f..8fcceadc58a455 100644 --- a/net/core/Makefile +++ b/net/core/Makefile @@ -8,8 +8,10 @@ obj-y := sock.o request_sock.o skbuff.o datagram.o stream.o scm.o \ obj-$(CONFIG_SYSCTL) += sysctl_net_core.o -CFLAGS_dev.o = -Ilib/lunatik/lua/ -D_KERNEL -CFLAGS_filter.o = -Ilib/lunatik/lua/ -D_KERNEL +CFLAGS_dev.o = -Ilib/lunatik/lua/ -D_KERNEL \ + -Ilib/luadata/ +CFLAGS_filter.o = -Ilib/lunatik/lua/ -D_KERNEL \ + -Ilib/luadata/ obj-y += dev.o ethtool.o dev_addr_lists.o dst.o netevent.o \ neighbour.o rtnetlink.o utils.o link_watch.o filter.o \ sock_diag.o dev_ioctl.o tso.o sock_reuseport.o \ diff --git a/net/core/dev.c b/net/core/dev.c index 0939ca6cf497eb..1596be4b07f2c9 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -76,6 +76,7 @@ #include #include #include +#include #endif /* CONFIG_XDP_LUA */ #include diff --git a/net/core/filter.c b/net/core/filter.c index fce7bc2b1ddcdb..322ee2ea6f55d3 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -4792,6 +4792,41 @@ static const struct bpf_func_proto bpf_lwt_seg6_adjust_srh_proto = { #endif /* CONFIG_IPV6_SEG6_BPF */ #ifdef CONFIG_XDP_LUA +BPF_CALL_2(bpf_lua_dataref, struct xdp_buff *, ctx, int, offset) { + if (offset + ctx->data < ctx->data_end) { + int data_ref; + + data_ref = ldata_newref(ctx->L, ctx->data + offset, + ctx->data_end - ctx->data - offset); + return data_ref; + } + + return -1; +} + +static const struct bpf_func_proto bpf_lua_dataref_proto = { + .func = bpf_lua_dataref, + .gpl_only = false, + .pkt_access = false, + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_CTX, + .arg1_type = ARG_ANYTHING, +}; + +BPF_CALL_2(bpf_lua_dataunref, struct xdp_buff *, ctx, int, data_ref) { + ldata_unref(ctx->L, data_ref); + return 0; +} + +static const struct bpf_func_proto bpf_lua_dataunref_proto = { + .func = bpf_lua_dataunref, + .gpl_only = false, + .pkt_access = false, + .ret_type = RET_VOID, + .arg1_type = ARG_PTR_TO_CTX, + .arg2_type = ARG_ANYTHING, +}; + BPF_CALL_4(bpf_lua_pcall, struct xdp_buff *, ctx, char *, funcname, int, num_args, int, num_rets) { if (lua_getglobal(ctx->L, funcname) != LUA_TFUNCTION) { @@ -5022,6 +5057,10 @@ bpf_base_func_proto(enum bpf_func_id func_id) return bpf_get_trace_printk_proto(); /* else: fall through */ #ifdef CONFIG_XDP_LUA + case BPF_FUNC_lua_dataref: + return &bpf_lua_dataref_proto; + case BPF_FUNC_lua_dataunref: + return &bpf_lua_dataunref_proto; case BPF_FUNC_lua_pcall: return &bpf_lua_pcall_proto; case BPF_FUNC_lua_pop: diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 75ad4f93ca1a49..752a34a254b025 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -2228,6 +2228,8 @@ union bpf_attr { FN(sk_select_reuseport), \ FN(skb_ancestor_cgroup_id), \ /* #ifdef CONFIG_XDP_LUA */ \ + FN(lua_dataref), \ + FN(lua_dataunref), \ FN(lua_pcall), \ FN(lua_pop), \ FN(lua_pushinteger), \ diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h index 478f25688f90c8..7bd097626289f9 100644 --- a/tools/testing/selftests/bpf/bpf_helpers.h +++ b/tools/testing/selftests/bpf/bpf_helpers.h @@ -145,6 +145,10 @@ static unsigned long long (*bpf_skb_ancestor_cgroup_id)(void *ctx, int level) = (void *) BPF_FUNC_skb_ancestor_cgroup_id; /* #ifdef CONFIG_XDP_LUA */ +static int (*bpf_lua_dataref)(void *ctx, int offset) = + (void *)BPF_FUNC_lua_dataref; +static void (*bpf_lua_dataunref)(void *ctx, int data_ref) = + (void *)BPF_FUNC_lua_dataunref; static int (*bpf_lua_pcall)(void *ctx, char *funcname, int num_args, int num_rets) = (void *) BPF_FUNC_lua_pcall; From 3ae188f894f5ce1e107ea08de291e7a36127d8d3 Mon Sep 17 00:00:00 2001 From: Lourival Vieira Neto Date: Fri, 7 Feb 2020 21:00:22 +0000 Subject: [PATCH 04/13] add LuaXDP submodule --- .gitmodules | 3 +++ lib/Makefile | 1 + lib/luaxdp | 1 + 3 files changed, 5 insertions(+) create mode 160000 lib/luaxdp diff --git a/.gitmodules b/.gitmodules index a60359c423290d..ffee774e9dc8a6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "lib/luadata"] path = lib/luadata url = https://github.com/luainkernel/luadata +[submodule "lib/luaxdp"] + path = lib/luaxdp + url = https://github.com/luainkernel/luaxdp.git diff --git a/lib/Makefile b/lib/Makefile index bff2d9cf4f7b0a..3d38e8ed6d908f 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -276,3 +276,4 @@ subdir-ccflags-y += -I$(srctree)/lib/lunatik/lua \ -D_KERNEL obj-$(CONFIG_LUNATIK) += lunatik/ obj-$(CONFIG_LUADATA) += luadata/ +obj-$(CONFIG_LUAXDP) += luaxdp/ diff --git a/lib/luaxdp b/lib/luaxdp new file mode 160000 index 00000000000000..78da47e058d5b6 --- /dev/null +++ b/lib/luaxdp @@ -0,0 +1 @@ +Subproject commit 78da47e058d5b67f27a2432c5f0bc68d7f99abdf From 511213da83d4afd2cc3e84ab710538efa97efb57 Mon Sep 17 00:00:00 2001 From: Lourival Vieira Neto Date: Thu, 30 Jan 2020 23:56:16 +0000 Subject: [PATCH 05/13] add LuaRCU submodule --- .gitmodules | 3 +++ lib/Makefile | 1 + lib/luarcu | 1 + 3 files changed, 5 insertions(+) create mode 160000 lib/luarcu diff --git a/.gitmodules b/.gitmodules index ffee774e9dc8a6..d17f05c06fdfa0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "lib/luaxdp"] path = lib/luaxdp url = https://github.com/luainkernel/luaxdp.git +[submodule "lib/luarcu"] + path = lib/luarcu + url = https://github.com/luainkernel/luarcu diff --git a/lib/Makefile b/lib/Makefile index 3d38e8ed6d908f..092cb4793b228f 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -277,3 +277,4 @@ subdir-ccflags-y += -I$(srctree)/lib/lunatik/lua \ obj-$(CONFIG_LUNATIK) += lunatik/ obj-$(CONFIG_LUADATA) += luadata/ obj-$(CONFIG_LUAXDP) += luaxdp/ +obj-$(CONFIG_LUARCU) += luarcu/ diff --git a/lib/luarcu b/lib/luarcu new file mode 160000 index 00000000000000..bc563d5245afc8 --- /dev/null +++ b/lib/luarcu @@ -0,0 +1 @@ +Subproject commit bc563d5245afc8024dd3f47fd8da404a781e0215 From 58abdd050d3c185c332b46fcd21e4cb86b5f494e Mon Sep 17 00:00:00 2001 From: Victor Nogueira Date: Tue, 11 Feb 2020 00:37:47 +0000 Subject: [PATCH 06/13] add XDPLua map sample --- samples/bpf/Makefile | 4 +++- samples/bpf/map.lua | 22 +++++++++++++++++++ samples/bpf/xdplua_map_kern.c | 41 +++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 samples/bpf/map.lua create mode 100644 samples/bpf/xdplua_map_kern.c diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile index fce0b871260cae..a44e56600230b4 100644 --- a/samples/bpf/Makefile +++ b/samples/bpf/Makefile @@ -111,7 +111,7 @@ xdpsock-objs := xdpsock_user.o xdp_fwd-objs := xdp_fwd_user.o task_fd_query-objs := bpf_load.o task_fd_query_user.o $(TRACE_HELPERS) xdp_sample_pkts-objs := xdp_sample_pkts_user.o $(TRACE_HELPERS) -# CONFIG_XDPLUA +# CONFIG_XDP_LUA xdplua-objs := xdplua_user.o # Tell kbuild to always build the programs @@ -170,6 +170,8 @@ always += xdpsock_kern.o always += xdp_fwd_kern.o always += task_fd_query_kern.o always += xdp_sample_pkts_kern.o +# CONFIG_XDP_LUA +always += xdplua_map_kern.o KBUILD_HOSTCFLAGS += -I$(objtree)/usr/include KBUILD_HOSTCFLAGS += -I$(srctree)/tools/lib/ diff --git a/samples/bpf/map.lua b/samples/bpf/map.lua new file mode 100644 index 00000000000000..aa6e733424a8d2 --- /dev/null +++ b/samples/bpf/map.lua @@ -0,0 +1,22 @@ +-- +-- Copyright (C) 2019-2020 Victor Nogueira +-- +-- This program is free software; you can redistribute it and/or +-- modify it under the terms of the GNU General Public License as +-- published by the Free Software Foundation version 2. +-- +-- This program is distributed "as is" WITHOUT ANY WARRANTY of any +-- kind, whether express or implied; without even the implied warranty +-- of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +xdp = require'xdp' + +function lookup(map) + local val = xdp.map_lookup(map, 1) + print('val', val) +end + +function update(map) + xdp.map_update(map, 1, 3) +end diff --git a/samples/bpf/xdplua_map_kern.c b/samples/bpf/xdplua_map_kern.c new file mode 100644 index 00000000000000..a0a54d33032f1d --- /dev/null +++ b/samples/bpf/xdplua_map_kern.c @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2019-2020 Victor Nogueira + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#define KBUILD_MODNAME "foo" +#include +#include "bpf_helpers.h" + +struct bpf_map_def SEC("maps") test_map = { + .type = BPF_MAP_TYPE_ARRAY, + .key_size = sizeof(int), + .value_size = sizeof(int), + .max_entries = 20, +}; + +SEC("xdp_lua_test_map") +int xdp_lua_test_map_prog(struct xdp_md *ctx) +{ + char lookupname[] = "lookup"; + char updatename[] = "update"; + + bpf_lua_setstate(ctx); + + bpf_lua_pushmap(ctx, &test_map); + bpf_lua_pcall(ctx, updatename, 1, 0); + + bpf_lua_pushmap(ctx, &test_map); + bpf_lua_pcall(ctx, lookupname, 1, 0); + + return XDP_PASS; +} + +char _license[] SEC("license") = "GPL"; From fc3fe38f4eec7793126337fa8b0f828101504fbc Mon Sep 17 00:00:00 2001 From: Victor Nogueira Date: Wed, 19 Feb 2020 22:13:09 -0300 Subject: [PATCH 07/13] Fix script loading synchronization issue --- include/linux/filter.h | 9 --- include/net/xdp.h | 13 ++++ include/uapi/linux/bpf.h | 5 +- net/core/dev.c | 79 ++++++++++++++--------- net/core/filter.c | 63 ++++++++++-------- samples/bpf/xdplua_map_kern.c | 2 - tools/include/uapi/linux/bpf.h | 1 - tools/testing/selftests/bpf/bpf_helpers.h | 2 - 8 files changed, 99 insertions(+), 75 deletions(-) diff --git a/include/linux/filter.h b/include/linux/filter.h index c11e3095aa7147..6791a0ac013923 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h @@ -1113,13 +1113,4 @@ struct bpf_sock_ops_kern { */ }; -#ifdef CONFIG_XDP_LUA -extern struct list_head lua_state_cpu_list; - -struct lua_state_cpu { - struct lua_State *L; - int cpu; - struct list_head list; -}; -#endif /* CONFIG_XDP_LUA */ #endif /* __LINUX_FILTER_H__ */ diff --git a/include/net/xdp.h b/include/net/xdp.h index 2887d9a5c93cec..7e896f31feec5d 100644 --- a/include/net/xdp.h +++ b/include/net/xdp.h @@ -63,6 +63,19 @@ struct xdp_rxq_info { struct xdp_mem_info mem; } ____cacheline_aligned; /* perf critical, avoid false-sharing */ +#ifdef CONFIG_XDP_LUA +struct xdplua_create_work { + char lua_script[8192]; + struct lua_State *L; + struct work_struct work; + spinlock_t lock; + bool init; +}; + +DECLARE_PER_CPU(struct xdplua_create_work, luaworks); +#endif /* CONFIG_XDP_LUA */ + + struct xdp_buff { void *data; void *data_end; diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 752a34a254b025..c2f4fd70df174d 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -2238,9 +2238,10 @@ union bpf_attr { FN(lua_pushmap), \ FN(lua_pushskb), \ FN(lua_pushstring), \ - FN(lua_setstate), \ FN(lua_toboolean), \ - FN(lua_tointeger), + FN(lua_tointeger), \ + FN(lua_newpacket), \ + FN(lua_type), /* #endif CONFIG_XDP_LUA */ /* integer value in 'imm' field of BPF_CALL instruction selects which helper diff --git a/net/core/dev.c b/net/core/dev.c index 1596be4b07f2c9..dbe5b3797b9bd0 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -75,6 +75,7 @@ #ifdef CONFIG_XDP_LUA #include #include +#include #include #include #endif /* CONFIG_XDP_LUA */ @@ -162,6 +163,9 @@ static DEFINE_SPINLOCK(ptype_lock); static DEFINE_SPINLOCK(offload_lock); +#ifdef CONFIG_XDP_LUA +DEFINE_PER_CPU(struct xdplua_create_work, luaworks); +#endif struct list_head ptype_base[PTYPE_HASH_SIZE] __read_mostly; struct list_head ptype_all __read_mostly; /* Taps */ static struct list_head offload_base __read_mostly; @@ -171,10 +175,6 @@ static int call_netdevice_notifiers_info(unsigned long val, struct netdev_notifier_info *info); static struct napi_struct *napi_by_id(unsigned int napi_id); -#ifdef CONFIG_XDP_LUA -struct list_head lua_state_cpu_list; -#endif /* CONFIG_XDP_LUA */ - /* * The @dev_base_head list is protected by @dev_base_lock and the rtnl * semaphore. @@ -4290,6 +4290,9 @@ static u32 netif_receive_generic_xdp(struct sk_buff *skb, u32 metalen, act = XDP_DROP; int hlen, off; u32 mac_len; +#ifdef CONFIG_XDP_LUA + struct xdplua_create_work *lw; +#endif /* CONFIG_XDP_LUA */ /* Reinjected packets coming from act_mirred or similar should * not get XDP generic processing. @@ -4332,11 +4335,21 @@ static u32 netif_receive_generic_xdp(struct sk_buff *skb, rxqueue = netif_get_rxqueue(skb); xdp->rxq = &rxqueue->xdp_rxq; #ifdef CONFIG_XDP_LUA + lw = this_cpu_ptr(&luaworks); + xdp->skb = skb; + xdp->L = lw->L; #endif /* CONFIG_XDP_LUA */ act = bpf_prog_run_xdp(xdp_prog, xdp); +#ifdef CONFIG_XDP_LUA + if (lw->init) { + lw->init = false; + spin_unlock(&lw->lock); + } +#endif /* CONFIG_XDP_LUA */ + off = xdp->data - orig_data; if (off > 0) __skb_pull(skb, off); @@ -5103,16 +5116,29 @@ static int generic_xdp_install(struct net_device *dev, struct netdev_bpf *xdp) } #ifdef CONFIG_XDP_LUA -int generic_xdp_lua_install_prog(char *lua_prog) + +static void per_cpu_xdp_lua_install(struct work_struct *w) { + int this_cpu = smp_processor_id(); + struct xdplua_create_work *lw = + container_of(w, struct xdplua_create_work, work); + + spin_lock_bh(&lw->lock); + if (luaL_dostring(lw->L, lw->lua_script)) { + pr_err(KERN_INFO "error: %s\nOn cpu: %d\n", + lua_tostring(lw->L, -1), this_cpu); + } + spin_unlock_bh(&lw->lock); +} + +int generic_xdp_lua_install_prog(char *lua_script) { - struct lua_state_cpu *sc; + int cpu; + struct xdplua_create_work *lw; - list_for_each_entry(sc, &lua_state_cpu_list, list) { - if (luaL_dostring(sc->L, lua_prog)) { - pr_err(KERN_INFO "error: %s\nOn cpu: %d\n", - lua_tostring(sc->L, -1), sc->cpu); - return -EINVAL; - } + for_each_possible_cpu(cpu) { + lw = per_cpu_ptr(&luaworks, cpu); + strcpy(lw->lua_script, lua_script); + schedule_work_on(cpu, &lw->work); } return 0; } @@ -9600,9 +9626,6 @@ static struct pernet_operations __net_initdata default_device_ops = { static int __init net_dev_init(void) { int i, rc = -ENOMEM; -#ifdef CONFIG_XDP_LUA - struct lua_state_cpu *new_state_cpu; -#endif /* CONFIG_XDP_LUA */ BUG_ON(!dev_boot_phase); @@ -9617,9 +9640,6 @@ static int __init net_dev_init(void) INIT_LIST_HEAD(&ptype_base[i]); INIT_LIST_HEAD(&offload_base); -#ifdef CONFIG_XDP_LUA - INIT_LIST_HEAD(&lua_state_cpu_list); -#endif /* CONFIG_XDP_LUA */ if (register_pernet_subsys(&netdev_net_ops)) goto out; @@ -9631,6 +9651,9 @@ static int __init net_dev_init(void) for_each_possible_cpu(i) { struct work_struct *flush = per_cpu_ptr(&flush_works, i); struct softnet_data *sd = &per_cpu(softnet_data, i); +#ifdef CONFIG_XDP_LUA + struct xdplua_create_work *lw = per_cpu_ptr(&luaworks, i); +#endif INIT_WORK(flush, flush_backlog); @@ -9650,24 +9673,18 @@ static int __init net_dev_init(void) init_gro_hash(&sd->backlog); sd->backlog.poll = process_backlog; sd->backlog.weight = weight_p; - #ifdef CONFIG_XDP_LUA - new_state_cpu = (struct lua_state_cpu *) - kmalloc(sizeof(struct lua_state_cpu), GFP_ATOMIC); - if (!new_state_cpu) - continue; + lw->L = luaL_newstate(); + WARN_ON(!lw->L); - new_state_cpu->L = luaL_newstate(); - if (!new_state_cpu->L) { - kfree(new_state_cpu); + if (!lw->L) continue; - } - luaL_openlibs(new_state_cpu->L); - lua_pop(new_state_cpu->L, 1); - new_state_cpu->cpu = i; + luaL_openlibs(lw->L); + luaL_requiref(lw->L, "data", luaopen_data, 1); + lua_pop(lw->L, 1); - list_add(&new_state_cpu->list, &lua_state_cpu_list); + INIT_WORK(&lw->work, per_cpu_xdp_lua_install); #endif /* CONFIG_XDP_LUA */ } diff --git a/net/core/filter.c b/net/core/filter.c index 322ee2ea6f55d3..e263ed6e178599 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -4792,10 +4792,21 @@ static const struct bpf_func_proto bpf_lwt_seg6_adjust_srh_proto = { #endif /* CONFIG_IPV6_SEG6_BPF */ #ifdef CONFIG_XDP_LUA +static inline void verify_and_lock(void) { + struct xdplua_create_work *lw; + + lw = this_cpu_ptr(&luaworks); + if (!lw->init) { + lw->init = true; + spin_lock(&lw->lock); + } +} + BPF_CALL_2(bpf_lua_dataref, struct xdp_buff *, ctx, int, offset) { if (offset + ctx->data < ctx->data_end) { int data_ref; + verify_and_lock(); data_ref = ldata_newref(ctx->L, ctx->data + offset, ctx->data_end - ctx->data - offset); return data_ref; @@ -4814,6 +4825,7 @@ static const struct bpf_func_proto bpf_lua_dataref_proto = { }; BPF_CALL_2(bpf_lua_dataunref, struct xdp_buff *, ctx, int, data_ref) { + verify_and_lock(); ldata_unref(ctx->L, data_ref); return 0; } @@ -4828,19 +4840,28 @@ static const struct bpf_func_proto bpf_lua_dataunref_proto = { }; BPF_CALL_4(bpf_lua_pcall, struct xdp_buff *, ctx, char *, funcname, - int, num_args, int, num_rets) { + int, num_args, int, num_rets) { + int base; + + verify_and_lock(); + + base = lua_gettop(ctx->L) - num_args; if (lua_getglobal(ctx->L, funcname) != LUA_TFUNCTION) { pr_err("function %s not found\n", funcname); - lua_pop(ctx->L, num_args); - return 0; + num_rets = 0; + goto clean_state; } lua_insert(ctx->L, 1); if (lua_pcall(ctx->L, num_args, num_rets, 0)) { pr_err("%s\n", lua_tostring(ctx->L, -1)); - lua_pop(ctx->L, 1); - return 0; + num_rets = 0; + goto clean_state; } + +clean_state: + base += num_rets; + lua_settop(ctx->L, base); return num_rets; } @@ -4856,6 +4877,7 @@ static const struct bpf_func_proto bpf_lua_pcall_proto = { }; BPF_CALL_2(bpf_lua_pop, struct xdp_buff *, ctx, int, index) { + verify_and_lock(); lua_pop(ctx->L, index); return 0; } @@ -4870,6 +4892,7 @@ static const struct bpf_func_proto bpf_lua_pop_proto = { }; BPF_CALL_2(bpf_lua_pushinteger, struct xdp_buff *, ctx, int, num) { + verify_and_lock(); lua_pushinteger(ctx->L, num); return 0; } @@ -4884,6 +4907,7 @@ static const struct bpf_func_proto bpf_lua_pushinteger_proto = { }; BPF_CALL_2(bpf_lua_pushlightuserdata, struct xdp_buff *, ctx, void *, ptr) { + verify_and_lock(); lua_pushlightuserdata(ctx->L, ptr); return 0; } @@ -4898,6 +4922,7 @@ static const struct bpf_func_proto bpf_lua_pushlightuserdata_proto = { }; BPF_CALL_3(bpf_lua_pushlstring, struct xdp_buff *, ctx, const char *, str, size_t, len) { + verify_and_lock(); lua_pushlstring(ctx->L, str, len); return 0; } @@ -4913,6 +4938,7 @@ static const struct bpf_func_proto bpf_lua_pushlstring_proto = { }; BPF_CALL_2(bpf_lua_pushmap, struct xdp_buff *, ctx, struct bpf_map *, map) { + verify_and_lock(); lua_pushlightuserdata(ctx->L, map); return 0; } @@ -4927,6 +4953,7 @@ static const struct bpf_func_proto bpf_lua_pushmap_proto = { }; BPF_CALL_1(bpf_lua_pushskb, struct xdp_buff *, ctx) { + verify_and_lock(); lua_pushlightuserdata(ctx->L, ctx->skb); return 0; } @@ -4940,6 +4967,7 @@ static const struct bpf_func_proto bpf_lua_pushskb_proto = { }; BPF_CALL_2(bpf_lua_pushstring, struct xdp_buff *, ctx, const char *, str) { + verify_and_lock(); lua_pushstring(ctx->L, str); return 0; } @@ -4953,28 +4981,8 @@ static const struct bpf_func_proto bpf_lua_pushstring_proto = { .arg2_type = ARG_ANYTHING, }; -BPF_CALL_1(bpf_lua_setstate, struct xdp_buff *, ctx){ - struct lua_state_cpu *sc; - int cpu = smp_processor_id(); - - list_for_each_entry(sc, &lua_state_cpu_list, list) { - if (sc->cpu == cpu) { - ctx->L = sc->L; - break; - } - } - return 0; -} - -static const struct bpf_func_proto bpf_lua_setstate_proto = { - .func = bpf_lua_setstate, - .gpl_only = false, - .pkt_access = false, - .ret_type = RET_VOID, - .arg1_type = ARG_PTR_TO_CTX, -}; - BPF_CALL_2(bpf_lua_toboolean, struct xdp_buff *, ctx, int, index) { + verify_and_lock(); return lua_toboolean(ctx->L, index); } @@ -4988,6 +4996,7 @@ static const struct bpf_func_proto bpf_lua_toboolean_proto = { }; BPF_CALL_2(bpf_lua_tointeger, struct xdp_buff *, ctx, int, index) { + verify_and_lock(); return lua_tointeger(ctx->L, index); } @@ -5077,8 +5086,6 @@ bpf_base_func_proto(enum bpf_func_id func_id) return &bpf_lua_pushskb_proto; case BPF_FUNC_lua_pushstring: return &bpf_lua_pushstring_proto; - case BPF_FUNC_lua_setstate: - return &bpf_lua_setstate_proto; case BPF_FUNC_lua_toboolean: return &bpf_lua_toboolean_proto; case BPF_FUNC_lua_tointeger: diff --git a/samples/bpf/xdplua_map_kern.c b/samples/bpf/xdplua_map_kern.c index a0a54d33032f1d..d68d20732bb754 100644 --- a/samples/bpf/xdplua_map_kern.c +++ b/samples/bpf/xdplua_map_kern.c @@ -27,8 +27,6 @@ int xdp_lua_test_map_prog(struct xdp_md *ctx) char lookupname[] = "lookup"; char updatename[] = "update"; - bpf_lua_setstate(ctx); - bpf_lua_pushmap(ctx, &test_map); bpf_lua_pcall(ctx, updatename, 1, 0); diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 752a34a254b025..80cd8837038cee 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -2238,7 +2238,6 @@ union bpf_attr { FN(lua_pushmap), \ FN(lua_pushskb), \ FN(lua_pushstring), \ - FN(lua_setstate), \ FN(lua_toboolean), \ FN(lua_tointeger), /* #endif CONFIG_XDP_LUA */ diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h index 7bd097626289f9..4b37dca4c64e72 100644 --- a/tools/testing/selftests/bpf/bpf_helpers.h +++ b/tools/testing/selftests/bpf/bpf_helpers.h @@ -167,8 +167,6 @@ static void (*bpf_lua_pushskb)(void *ctx) = (void *)BPF_FUNC_lua_pushskb; static void (*bpf_lua_pushstring)(void *ctx, const char *) = (void *)BPF_FUNC_lua_pushstring; -static void (*bpf_lua_setstate)(void *ctx) = - (void *)BPF_FUNC_lua_setstate; static int (*bpf_lua_toboolean)(void *ctx, int index) = (void *)BPF_FUNC_lua_toboolean; static int (*bpf_lua_tointeger)(void *ctx, int index) = From 48884fcf0f785c7a7d94048b6f077b61f2f840e1 Mon Sep 17 00:00:00 2001 From: Victor Nogueira Date: Wed, 19 Feb 2020 21:14:48 -0300 Subject: [PATCH 08/13] add LuaUnpack submodule --- .gitmodules | 3 +++ include/uapi/linux/bpf.h | 3 +-- lib/Makefile | 3 ++- lib/luaunpack | 1 + net/core/Makefile | 2 +- net/core/filter.c | 22 ++++++++++++++++++++++ tools/include/uapi/linux/bpf.h | 3 ++- tools/testing/selftests/bpf/bpf_helpers.h | 2 ++ 8 files changed, 34 insertions(+), 5 deletions(-) create mode 160000 lib/luaunpack diff --git a/.gitmodules b/.gitmodules index d17f05c06fdfa0..3b57405d4b5084 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,3 +10,6 @@ [submodule "lib/luarcu"] path = lib/luarcu url = https://github.com/luainkernel/luarcu +[submodule "lib/luaunpack"] + path = lib/luaunpack + url = https://github.com/VictorNogueiraRio/luaunpack.git diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index c2f4fd70df174d..9a97cdb18ca5a0 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -2240,8 +2240,7 @@ union bpf_attr { FN(lua_pushstring), \ FN(lua_toboolean), \ FN(lua_tointeger), \ - FN(lua_newpacket), \ - FN(lua_type), + FN(lua_newpacket), /* #endif CONFIG_XDP_LUA */ /* integer value in 'imm' field of BPF_CALL instruction selects which helper diff --git a/lib/Makefile b/lib/Makefile index 092cb4793b228f..5d1cc009a5a017 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -272,9 +272,10 @@ obj-$(CONFIG_GENERIC_LIB_CMPDI2) += cmpdi2.o obj-$(CONFIG_GENERIC_LIB_UCMPDI2) += ucmpdi2.o subdir-ccflags-y += -I$(srctree)/lib/lunatik/lua \ - -I$(srctree)/lib/luadata/ \ + -I$(srctree)/lib/luadata/ -I$(srctree)/lib/luaunpack/ \ -D_KERNEL obj-$(CONFIG_LUNATIK) += lunatik/ obj-$(CONFIG_LUADATA) += luadata/ obj-$(CONFIG_LUAXDP) += luaxdp/ obj-$(CONFIG_LUARCU) += luarcu/ +obj-$(CONFIG_LUAUNPACK) += luaunpack/ diff --git a/lib/luaunpack b/lib/luaunpack new file mode 160000 index 00000000000000..0589fc254bedaa --- /dev/null +++ b/lib/luaunpack @@ -0,0 +1 @@ +Subproject commit 0589fc254bedaa648042710a539a1db8cfa3445d diff --git a/net/core/Makefile b/net/core/Makefile index 8fcceadc58a455..6193c9338ccaf4 100644 --- a/net/core/Makefile +++ b/net/core/Makefile @@ -11,7 +11,7 @@ obj-$(CONFIG_SYSCTL) += sysctl_net_core.o CFLAGS_dev.o = -Ilib/lunatik/lua/ -D_KERNEL \ -Ilib/luadata/ CFLAGS_filter.o = -Ilib/lunatik/lua/ -D_KERNEL \ - -Ilib/luadata/ + -Ilib/luadata/ -Ilib/luaunpack/ obj-y += dev.o ethtool.o dev_addr_lists.o dst.o netevent.o \ neighbour.o rtnetlink.o utils.o link_watch.o filter.o \ sock_diag.o dev_ioctl.o tso.o sock_reuseport.o \ diff --git a/net/core/filter.c b/net/core/filter.c index e263ed6e178599..a83b128301493e 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -71,6 +71,8 @@ #ifdef CONFIG_XDP_LUA #include +#include +#include #endif /* CONFIG_XDP_LUA */ /** @@ -5008,6 +5010,24 @@ static const struct bpf_func_proto bpf_lua_tointeger_proto = { .arg1_type = ARG_PTR_TO_CTX, .arg2_type = ARG_ANYTHING, }; + +BPF_CALL_2(bpf_lua_newpacket, struct xdp_buff *, ctx, int, offset) { + if (offset + ctx->data < ctx->data_end) { + return lunpack_newpacket(ctx->L, ctx->data + offset, + ctx->data_end - ctx->data - offset); + } + + return -EINVAL; +} + +static const struct bpf_func_proto bpf_lua_newpacket_proto = { + .func = bpf_lua_newpacket, + .gpl_only = false, + .pkt_access = false, + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_CTX, + .arg2_type = ARG_ANYTHING, +}; #endif /* CONFIG_XDP_LUA */ bool bpf_helper_changes_pkt_data(void *func) @@ -5090,6 +5110,8 @@ bpf_base_func_proto(enum bpf_func_id func_id) return &bpf_lua_toboolean_proto; case BPF_FUNC_lua_tointeger: return &bpf_lua_tointeger_proto; + case BPF_FUNC_lua_newpacket: + return &bpf_lua_newpacket_proto; #endif /* CONFIG_XDP_LUA */ default: return NULL; diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 80cd8837038cee..9a97cdb18ca5a0 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -2239,7 +2239,8 @@ union bpf_attr { FN(lua_pushskb), \ FN(lua_pushstring), \ FN(lua_toboolean), \ - FN(lua_tointeger), + FN(lua_tointeger), \ + FN(lua_newpacket), /* #endif CONFIG_XDP_LUA */ /* integer value in 'imm' field of BPF_CALL instruction selects which helper diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h index 4b37dca4c64e72..069794ee5fef40 100644 --- a/tools/testing/selftests/bpf/bpf_helpers.h +++ b/tools/testing/selftests/bpf/bpf_helpers.h @@ -171,6 +171,8 @@ static int (*bpf_lua_toboolean)(void *ctx, int index) = (void *)BPF_FUNC_lua_toboolean; static int (*bpf_lua_tointeger)(void *ctx, int index) = (void *)BPF_FUNC_lua_tointeger; +static int (*bpf_lua_newpacket)(void *ctx, int offset) = + (void *)BPF_FUNC_lua_newpacket; /* #endif CONFIG_XDP_LUA */ /* llvm builtin functions that eBPF C program may use to From fe1927cca36b14d41162649221cd85f194c977d3 Mon Sep 17 00:00:00 2001 From: Victor Nogueira Date: Mon, 3 Feb 2020 18:57:06 -0300 Subject: [PATCH 09/13] Add bpf_lua_tostring function --- include/uapi/linux/bpf.h | 1 + net/core/filter.c | 22 ++++++++++++++++++++++ tools/include/uapi/linux/bpf.h | 1 + tools/testing/selftests/bpf/bpf_helpers.h | 2 ++ 4 files changed, 26 insertions(+) diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 9a97cdb18ca5a0..d57c7b77024d11 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -2231,6 +2231,7 @@ union bpf_attr { FN(lua_dataref), \ FN(lua_dataunref), \ FN(lua_pcall), \ + FN(lua_tostring), \ FN(lua_pop), \ FN(lua_pushinteger), \ FN(lua_pushlightuserdata), \ diff --git a/net/core/filter.c b/net/core/filter.c index a83b128301493e..61324c4e5c6a12 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -5011,6 +5011,26 @@ static const struct bpf_func_proto bpf_lua_tointeger_proto = { .arg2_type = ARG_ANYTHING, }; +BPF_CALL_4(bpf_lua_tostring, struct xdp_buff *, ctx, char *, str, u32, size, int, index) { + if (lua_isstring(ctx->L, index)) { + strncpy(str, lua_tostring(ctx->L, index), size); + return 1; + } + + return 0; +} + +static const struct bpf_func_proto bpf_lua_tostring_proto = { + .func = bpf_lua_tostring, + .gpl_only = false, + .pkt_access = false, + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_CTX, + .arg2_type = ARG_PTR_TO_UNINIT_MEM, + .arg3_type = ARG_CONST_SIZE, + .arg4_type = ARG_ANYTHING, +}; + BPF_CALL_2(bpf_lua_newpacket, struct xdp_buff *, ctx, int, offset) { if (offset + ctx->data < ctx->data_end) { return lunpack_newpacket(ctx->L, ctx->data + offset, @@ -5108,6 +5128,8 @@ bpf_base_func_proto(enum bpf_func_id func_id) return &bpf_lua_pushstring_proto; case BPF_FUNC_lua_toboolean: return &bpf_lua_toboolean_proto; + case BPF_FUNC_lua_tostring: + return &bpf_lua_tostring_proto; case BPF_FUNC_lua_tointeger: return &bpf_lua_tointeger_proto; case BPF_FUNC_lua_newpacket: diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 9a97cdb18ca5a0..d57c7b77024d11 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -2231,6 +2231,7 @@ union bpf_attr { FN(lua_dataref), \ FN(lua_dataunref), \ FN(lua_pcall), \ + FN(lua_tostring), \ FN(lua_pop), \ FN(lua_pushinteger), \ FN(lua_pushlightuserdata), \ diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h index 069794ee5fef40..12f85abd4ce707 100644 --- a/tools/testing/selftests/bpf/bpf_helpers.h +++ b/tools/testing/selftests/bpf/bpf_helpers.h @@ -152,6 +152,8 @@ static void (*bpf_lua_dataunref)(void *ctx, int data_ref) = static int (*bpf_lua_pcall)(void *ctx, char *funcname, int num_args, int num_rets) = (void *) BPF_FUNC_lua_pcall; +static int (*bpf_lua_tostring)(void *ctx, char *sslsni, u32 size, int index) = + (void *)BPF_FUNC_lua_tostring; static void (*bpf_lua_pop)(void *ctx, int index) = (void *)BPF_FUNC_lua_pop; static void (*bpf_lua_pushinteger)(void *ctx, int num) = From e462d21b9d594ae6dc727669e1e2d043259a197c Mon Sep 17 00:00:00 2001 From: Victor Nogueira Date: Tue, 3 Mar 2020 12:22:29 -0300 Subject: [PATCH 10/13] Add bpf_lua_type function --- include/uapi/linux/bpf.h | 3 ++- net/core/filter.c | 15 +++++++++++++++ tools/include/uapi/linux/bpf.h | 3 ++- tools/testing/selftests/bpf/bpf_helpers.h | 2 ++ 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index d57c7b77024d11..8bf2fd858c3f4e 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -2241,7 +2241,8 @@ union bpf_attr { FN(lua_pushstring), \ FN(lua_toboolean), \ FN(lua_tointeger), \ - FN(lua_newpacket), + FN(lua_newpacket), \ + FN(lua_type), /* #endif CONFIG_XDP_LUA */ /* integer value in 'imm' field of BPF_CALL instruction selects which helper diff --git a/net/core/filter.c b/net/core/filter.c index 61324c4e5c6a12..5d5d3d685a4250 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -5048,6 +5048,19 @@ static const struct bpf_func_proto bpf_lua_newpacket_proto = { .arg1_type = ARG_PTR_TO_CTX, .arg2_type = ARG_ANYTHING, }; + +BPF_CALL_2(bpf_lua_type, struct xdp_buff *, ctx, int, index) { + return lua_type(ctx->L, index); +} + +static const struct bpf_func_proto bpf_lua_type_proto = { + .func = bpf_lua_type, + .gpl_only = false, + .pkt_access = false, + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_CTX, + .arg2_type = ARG_ANYTHING, +}; #endif /* CONFIG_XDP_LUA */ bool bpf_helper_changes_pkt_data(void *func) @@ -5134,6 +5147,8 @@ bpf_base_func_proto(enum bpf_func_id func_id) return &bpf_lua_tointeger_proto; case BPF_FUNC_lua_newpacket: return &bpf_lua_newpacket_proto; + case BPF_FUNC_lua_type: + return &bpf_lua_type_proto; #endif /* CONFIG_XDP_LUA */ default: return NULL; diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index d57c7b77024d11..8bf2fd858c3f4e 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -2241,7 +2241,8 @@ union bpf_attr { FN(lua_pushstring), \ FN(lua_toboolean), \ FN(lua_tointeger), \ - FN(lua_newpacket), + FN(lua_newpacket), \ + FN(lua_type), /* #endif CONFIG_XDP_LUA */ /* integer value in 'imm' field of BPF_CALL instruction selects which helper diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h index 12f85abd4ce707..0aa1c86eba7d67 100644 --- a/tools/testing/selftests/bpf/bpf_helpers.h +++ b/tools/testing/selftests/bpf/bpf_helpers.h @@ -175,6 +175,8 @@ static int (*bpf_lua_tointeger)(void *ctx, int index) = (void *)BPF_FUNC_lua_tointeger; static int (*bpf_lua_newpacket)(void *ctx, int offset) = (void *)BPF_FUNC_lua_newpacket; +static int (*bpf_lua_type)(void *ctx, int index) = + (void *)BPF_FUNC_lua_type; /* #endif CONFIG_XDP_LUA */ /* llvm builtin functions that eBPF C program may use to From caec4fa7191efc1bc2f8dfde995df117b043a5ff Mon Sep 17 00:00:00 2001 From: Victor Nogueira Date: Thu, 27 Aug 2020 13:22:45 -0300 Subject: [PATCH 11/13] fixup! add XDPLua --- net/core/filter.c | 5 +++-- samples/bpf/xdplua_user.c | 2 +- tools/lib/bpf/bpf.c | 11 +---------- tools/lib/bpf/libbpf.h | 2 +- 4 files changed, 6 insertions(+), 14 deletions(-) diff --git a/net/core/filter.c b/net/core/filter.c index 5d5d3d685a4250..42088c017338de 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -4854,15 +4854,16 @@ BPF_CALL_4(bpf_lua_pcall, struct xdp_buff *, ctx, char *, funcname, goto clean_state; } - lua_insert(ctx->L, 1); + lua_insert(ctx->L, base + 1); if (lua_pcall(ctx->L, num_args, num_rets, 0)) { pr_err("%s\n", lua_tostring(ctx->L, -1)); num_rets = 0; goto clean_state; } -clean_state: base += num_rets; + +clean_state: lua_settop(ctx->L, base); return num_rets; } diff --git a/samples/bpf/xdplua_user.c b/samples/bpf/xdplua_user.c index d9b5acc665e1fc..e6c5f9da114177 100644 --- a/samples/bpf/xdplua_user.c +++ b/samples/bpf/xdplua_user.c @@ -81,7 +81,7 @@ static int do_attach_lua(const char *name, char *lua_prog) { int err; - err = bpf_set_link_xdp_lua_prog(lua_prog, 0); + err = bpf_set_link_xdp_lua_prog(lua_prog); if (err < 0) fprintf(stderr, "ERROR: failed to attach lua script to %s\n", name); diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c index 57cc5e26369812..7af691667a961b 100644 --- a/tools/lib/bpf/bpf.c +++ b/tools/lib/bpf/bpf.c @@ -621,7 +621,7 @@ int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags) } /* #ifdef CONFIG_XDPLUA */ -int bpf_set_link_xdp_lua_prog(char *lua_prog, __u32 flags) +int bpf_set_link_xdp_lua_prog(char *lua_prog) { struct sockaddr_nl sa; int sock, seq = 0, len, ret = -1; @@ -693,15 +693,6 @@ int bpf_set_link_xdp_lua_prog(char *lua_prog, __u32 flags) } nla->nla_len += nla_xdp->nla_len; - /* if user passed in any flags, add those too */ - if (flags) { - nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len); - nla_xdp->nla_type = IFLA_XDP_FLAGS; - nla_xdp->nla_len = NLA_HDRLEN + sizeof(flags); - memcpy((char *)nla_xdp + NLA_HDRLEN, &flags, sizeof(flags)); - nla->nla_len += nla_xdp->nla_len; - } - req.nh.nlmsg_len += NLA_ALIGN(nla->nla_len); if (send(sock, &req, req.nh.nlmsg_len, 0) < 0) { diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h index 523ada3fa48b81..1b88e4b5634b74 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h @@ -285,7 +285,7 @@ int bpf_prog_load(const char *file, enum bpf_prog_type type, int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags); /* #ifdef CONFIG_XDP_LUA */ -int bpf_set_link_xdp_lua_prog(char *lua_prog, __u32 flags); +int bpf_set_link_xdp_lua_prog(char *lua_prog); /* #endif CONFIG_XDP_LUA */ enum bpf_perf_event_ret { From e16f94de50cc2a686a2242aaf66aa43a442035e3 Mon Sep 17 00:00:00 2001 From: Victor Nogueira Date: Sun, 13 Sep 2020 20:17:36 -0300 Subject: [PATCH 12/13] fixup! add XDPLua --- net/core/filter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/core/filter.c b/net/core/filter.c index 42088c017338de..af202adec86183 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -4894,9 +4894,9 @@ static const struct bpf_func_proto bpf_lua_pop_proto = { .arg2_type = ARG_ANYTHING, }; -BPF_CALL_2(bpf_lua_pushinteger, struct xdp_buff *, ctx, int, num) { +BPF_CALL_2(bpf_lua_pushinteger, struct xdp_buff *, ctx, lua_Integer, integer) { verify_and_lock(); - lua_pushinteger(ctx->L, num); + lua_pushinteger(ctx->L, integer); return 0; } From ecda2979eb7b2cd661c41dc383624ded4b449225 Mon Sep 17 00:00:00 2001 From: Victor Nogueira Date: Sun, 20 Sep 2020 22:55:28 -0300 Subject: [PATCH 13/13] fixup! add LuaXDP submodule --- lib/luaxdp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/luaxdp b/lib/luaxdp index 78da47e058d5b6..be34f8706d3c96 160000 --- a/lib/luaxdp +++ b/lib/luaxdp @@ -1 +1 @@ -Subproject commit 78da47e058d5b67f27a2432c5f0bc68d7f99abdf +Subproject commit be34f8706d3c96e1cdb61015c37bc0dd83aeb75b