Skip to content

Commit

Permalink
torvalds#267 Load Lua scripts with luaL_loadbufferx
Browse files Browse the repository at this point in the history
  • Loading branch information
VictorNogueiraRio committed Jan 16, 2021
1 parent 3884fca commit 99f9902
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 49 deletions.
4 changes: 3 additions & 1 deletion include/net/xdplua.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,21 @@

struct xdp_lua_work {
char script[XDP_LUA_MAX_SCRIPT_LEN];
size_t script_len;
struct lua_State *L;
struct sk_buff *skb;
struct work_struct work;
};

DECLARE_PER_CPU(struct xdp_lua_work, luaworks);


#define XDP_LUA_BPF_FUNC(name) BPF_FUNC_lua_##name

#define xdp_lua_get_skb() (this_cpu_ptr(&luaworks)->skb)
#define xdp_lua_set_skb(skb) (this_cpu_ptr(&luaworks)->skb = skb)

void generic_xdp_lua_install_prog(const char *script);
int generic_xdp_lua_install_prog(const char *script, size_t script_len);
void xdp_lua_init(void);

#define __BPF_LUA_MAP_0(l, m, v, ...) l
Expand Down
10 changes: 5 additions & 5 deletions net/core/rtnetlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -2638,14 +2638,14 @@ static int do_setlink(const struct sk_buff *skb,
#ifdef CONFIG_XDP_LUA
if (xdp[IFLA_XDP_LUA_PROG]) {
const char *script;
int script_len;

script = nla_data(xdp[IFLA_XDP_LUA_PROG]);
if (!script) {
err = -EINVAL;
goto errout;
}
script_len = nla_len(xdp[IFLA_XDP_LUA_PROG]);

generic_xdp_lua_install_prog(script);
err = generic_xdp_lua_install_prog(script, script_len);
if (err)
goto errout;
}
#endif /* CONFIG_XDP_LUA */
}
Expand Down
24 changes: 20 additions & 4 deletions net/core/xdplua.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,39 @@ static void per_cpu_xdp_lua_install(struct work_struct *w)
lw = container_of(w, struct xdp_lua_work, work);

local_bh_disable();
if (luaL_dostring(lw->L, lw->script)) {
pr_err(KERN_INFO "error: %s\nOn cpu: %d\n",
if (luaL_loadbufferx(lw->L, lw->script, lw->script_len, NULL, "t")) {
pr_err("error loading Lua script: %s\non cpu: %d\n",
lua_tostring(lw->L, -1), this_cpu);
lua_pop(lw->L, 1);
goto enable;
}

if (lua_pcall(lw->L, 0, LUA_MULTRET, 0)) {
pr_err("error running Lua script: %s\non cpu: %d\n",
lua_tostring(lw->L, -1), this_cpu);
lua_pop(lw->L, 1);
}

enable:
local_bh_enable();
}

void generic_xdp_lua_install_prog(const char *script)
int generic_xdp_lua_install_prog(const char *script, size_t script_len)
{
int i;

if (!script || script_len == 0)
return -EINVAL;

if (script_len > XDP_LUA_MAX_SCRIPT_LEN)
return -ENAMETOOLONG;

for_each_possible_cpu(i) {
struct xdp_lua_work *lw;

lw = per_cpu_ptr(&luaworks, i);
strncpy(lw->script, script, XDP_LUA_MAX_SCRIPT_LEN);
memcpy(lw->script, script, script_len);
lw->script_len = script_len;
schedule_work_on(i, &lw->work);
}

Expand Down
86 changes: 59 additions & 27 deletions samples/bpf/xdplua_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,22 @@ static void usage(const char *prog) {
prog);
}

static char *extract_script(const char *path)
static int try_strncpy(char *dest, const char *src, size_t n, const char *fmt) {
int srclen = strnlen(src, n);

if (srclen == n) {
int err = ENAMETOOLONG;
fprintf(stderr, fmt, strerror(err));
return -err;
}

strncpy(dest, src, n);
return srclen;
}

static char *extract_script(const char *path, size_t *script_len)
{
FILE *f;
long script_len;
size_t read;
char *script = NULL;

Expand All @@ -55,25 +67,33 @@ static char *extract_script(const char *path)
}

if (fseek(f, 0 , SEEK_END) < 0) {
perror("unable to reach end of script file");
perror("unable to reach end of file");
goto out;
}
script_len = ftell(f);
if (script_len < 0) {
perror("error while attempting to get script length");

*script_len = (size_t) ftell(f);
if (*script_len < 0) {
perror("error while attempting to get file length");
goto out;
}
rewind(f);

script = (char *) malloc(script_len + 1);
fseek(f, 0, *script_len);

if (*script_len > XDP_LUA_MAX_SCRIPT_LEN)
fprintf(stderr, "lua file can't have more than %d bytes\n",
XDP_LUA_MAX_SCRIPT_LEN);

script = (char *) malloc(sizeof(char) * (*script_len));
if (!script) {
perror("failed to alloc lua script");
goto out;
}
memset(script, 0, script_len + 1);
read = fread(script, 1, script_len, f);
if (read != script_len) {
perror("unable to read lua file");

rewind(f);

read = fread(script, sizeof(char), *script_len, f);
if (read != *script_len) {
fprintf(stderr, "unable to read file %s\n", path);
free(script);
script = NULL;
goto out;
Expand All @@ -95,11 +115,11 @@ static int do_attach_ebpf(int idx, int fd, const char *name)
return err;
}

static int do_attach_lua(const char *script)
static int do_attach_lua(const char *script, size_t script_len)
{
int err;

err = bpf_set_link_xdp_lua_script(script);
err = bpf_set_link_xdp_lua_script(script, script_len);
if (err < 0)
fprintf(stderr, "ERROR: failed to attach lua script %d\n", err);

Expand Down Expand Up @@ -138,19 +158,23 @@ static void poll(int map_fd, int interval, int duration) {
}
}

#define strncpy_err(fmt, err) fprintf(stderr, fmt, strerr(-err))

int main(int argc, char *argv[])
{
struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
char lua_filename[MAXFILENAMELEN];
char filename[MAXFILENAMELEN];
char script[XDP_LUA_MAX_SCRIPT_LEN];
size_t script_len = 0;
char ifname[IFNAMSIZ];
struct bpf_object *obj;
int opt, prog_fd;
int rx_cnt_map_fd;
int ifindex = 0;
int detach = 0, attach_lua_file = 0, attach_ebpf = 0, monitor = 0,
attach_lua_script = 0, interval = 1, duration = 1;
int err = 0;

const char *optstr = "f:p:i:dms:I:D:";
struct bpf_prog_load_attr prog_load_attr = {
Expand All @@ -163,28 +187,36 @@ int main(int argc, char *argv[])
while ((opt = getopt(argc, argv, optstr)) != -1) {
switch (opt) {
case 'f':
snprintf(lua_filename, sizeof(lua_filename), "%s", optarg);
err = try_strncpy(lua_filename, optarg, MAXFILENAMELEN, "Invalid lua filename\nerr: %s\n");
if (err < 0)
return 1;
attach_lua_file = 1;
break;
case 'p':
snprintf(filename, sizeof(filename),
"%s", optarg);
err = try_strncpy(filename, optarg, MAXFILENAMELEN, "Invalid bpf prog filename\nerr: %s");
if (err < 0)
return 1;
attach_ebpf = 1;
break;
case 'd':
detach = 1;
break;
case 'i':
snprintf(ifname, sizeof(ifname), "%s", optarg);
script_len = try_strncpy(ifname, optarg, IFNAMSIZ, "Invalid interface name\nerr: %s");
if (script_len < 0)
return 1;
ifindex = if_nametoindex(optarg);
break;
case 'm':
monitor = 1;
break;
case 's':
snprintf(script, sizeof(script), "%s", optarg);
case 's': {
err = try_strncpy(script, optarg, XDP_LUA_MAX_SCRIPT_LEN, "Invalid lua script\nerr: %s");
if (err < 0)
return 1;
attach_lua_script = 1;
break;
}
case 'I':
interval = atoi(optarg);
break;
Expand All @@ -197,7 +229,6 @@ int main(int argc, char *argv[])
}
}


if (attach_ebpf || detach) {
if (!ifindex) {
printf("ERROR: invalid interface name");
Expand Down Expand Up @@ -234,20 +265,21 @@ int main(int argc, char *argv[])
}

if (attach_lua_file) {
char *extracted_script = extract_script(lua_filename);
int ret = 0;
size_t extracted_script_len;
char *extracted_script = extract_script(lua_filename, &extracted_script_len);
if (!extracted_script)
return 1;

if (do_attach_lua(extracted_script) < 0) {
free(extracted_script);
return 1;
}
if (do_attach_lua(extracted_script, extracted_script_len) < 0)
ret = 1;

free(extracted_script);
return ret;
}

if (attach_lua_script)
if (do_attach_lua(script) < 0)
if (do_attach_lua(script, script_len) < 0)
return 1;

if (monitor) {
Expand Down
22 changes: 11 additions & 11 deletions tools/lib/bpf/bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -621,16 +621,16 @@ int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags)
}

/* #ifdef CONFIG_XDPLUA */
int bpf_set_link_xdp_lua_script(const char *script)
int bpf_set_link_xdp_lua_script(const char *script, size_t script_len)
{
struct sockaddr_nl sa;
int sock, seq = 0, len, ret = -1;
char buf[4096];
struct nlattr *nla, *nla_xdp;
struct nlattr *nla, *nla_xdp_lua;
struct {
struct nlmsghdr nh;
struct ifinfomsg ifinfo;
char attrbuf[XDP_LUA_MAX_SCRIPT_LEN + 64];
char attrbuf[XDP_LUA_MAX_SCRIPT_LEN];
} req;
struct nlmsghdr *nh;
struct nlmsgerr *err;
Expand Down Expand Up @@ -681,24 +681,24 @@ int bpf_set_link_xdp_lua_script(const char *script)
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;
/* add XDP LUA SCRIPT */
nla_xdp_lua = (struct nlattr *)((char *)nla + nla->nla_len);
nla_xdp_lua->nla_type = IFLA_XDP_LUA_PROG;
if (script) {
if (strlen(script) + 1 > XDP_LUA_MAX_SCRIPT_LEN) {
if (script_len > XDP_LUA_MAX_SCRIPT_LEN) {
fprintf(stderr, "script length cannot exceed %d bytes\n",
XDP_LUA_MAX_SCRIPT_LEN);
ret = -EINVAL;
ret = -ENAMETOOLONG;
goto cleanup;
}

nla_xdp->nla_len = NLA_HDRLEN + strlen(script) + 1;
memcpy((char *)nla_xdp + NLA_HDRLEN, script, strlen(script) + 1);
nla_xdp_lua->nla_len = NLA_HDRLEN + script_len;
memcpy((char *)nla_xdp_lua + NLA_HDRLEN, script, script_len);
} else {
ret = -EINVAL;
goto cleanup;
}
nla->nla_len += nla_xdp->nla_len;
nla->nla_len += nla_xdp_lua->nla_len;

req.nh.nlmsg_len += NLA_ALIGN(nla->nla_len);

Expand Down
2 changes: 1 addition & 1 deletion tools/lib/bpf/libbpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_script(const char *script);
int bpf_set_link_xdp_lua_script(const char *script, size_t script_len);
/* #endif CONFIG_XDP_LUA */

enum bpf_perf_event_ret {
Expand Down

0 comments on commit 99f9902

Please sign in to comment.