Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

merging support for LuaJIT to BPF compiler #626

Closed
vavrusa opened this issue Jul 23, 2016 · 12 comments
Closed

merging support for LuaJIT to BPF compiler #626

vavrusa opened this issue Jul 23, 2016 · 12 comments

Comments

@vavrusa
Copy link
Contributor

vavrusa commented Jul 23, 2016

This is a tire kicking ticket to see if it gathers some interest. Right now bcc compiles C, P4 (and maybe something else) to BPF bytecode and provides frontend in Python and Lua(JIT).
I'm working on (time permitting) vavrusa/luajit-bpf, a pure LuaJIT project to compile LuaJIT bytecode to BPF bytecode - so another supported language besides C and P4.

It has several components where it overlaps bcc (ELF scanner, some Lua front-end, test cases and kernel interface headers, perf interfaces), several things that I'd like to have (eBPF VM for testing), and there is already someone interested in LJ front-end. As for me, it'd be terrific if I didn't have to reimplement and maintain these things. Instead I'd like to incorporate LuaJIT support to bcc project and be able to reuse common things.

Having pure LJ backend has several benefits summarised in the README - most notably things like maps can be shared freely between kernel-side and user-side part of the script, and filter functions can be recompiled on runtime (if parameters changes for example) for more efficient filtering (as in examples/uprobe-tailkt where the branches get optimised out as they're known on script run-time). This is for example something C-to-BPF compilers can't do without sed-ing or preprocessing the sources somehow.

Would that make sense or not at all?

@4ast
Copy link
Member

4ast commented Jul 30, 2016

@vmg @brendangregg
This looks very useful! Being able to write both kernel and user space parts of the script in lua is unbeatable. Please do not delay sending a PR :)
Since I'm not versed in lua, the comments in the examples were really appreciated.
Do we always need 'local req = ffi.cast('struct pt_regs', ptregs)' and other ffi.cast ?
Could you convert one of the tools like offcputime.lua completely into lua?
Some more complex scripts would need bpf_perf_event_output() support first, right?

@vavrusa
Copy link
Contributor Author

vavrusa commented Jul 30, 2016

Awesome, I wanted to hack on it this weekend anyway, it's been a while.

Do we always need 'local req = ffi.cast('struct pt_regs', ptregs)' and other ffi.cast ?

Yes and no. The BPF program is compiled immediately after Lua function is declared, where it doesn't know yet if it's uprobe, socket filter program or something else. So arg has to be typecasted somehow, and this is just the the basic way how it is done in LJ. The language is however very flexible when it comes to syntactic sugar. I thought about auto typecasting based on function parameter name, ptregs would be casted to struct pt_regs, skb to struct sk_buff (that's already done) etc. Typecasting registers like ptregs.ax I don't know, these are untyped by default and the function would need to know function signature somehow to do autotyping. I think it might be possible to read traced function annotation from comment, something like:

prog = bpf(function(this, kbuf) -- bool accept(char *, const char *)
    -- Automatically mapped `ptregs.ax -> char *this`
    -- Automatically mapped `ptregs.bx -> const char *kbuf`
end)

Could you convert one of the tools like offcputime.lua completely into lua?

Yup, I need to add support for stack traces and bpf_perf_event_output() first though.

Some more complex scripts would need bpf_perf_event_output() support first, right?

Right, I have added support to perf event reading in ljsyscall PR#191 already, but not sugar coating and kernel-side helper.

@4ast
Copy link
Member

4ast commented Jul 30, 2016

-- bool accept(char *, const char *)

interesting idea about the comments... I think we can adopt it for C as well.
The comments don't have structure, but could be quite useful.
@drzaeus77

@vavrusa
Copy link
Contributor Author

vavrusa commented Aug 2, 2016

I've merged rudimentary support for bpf_perf_event_output(), I'll do the BPF_STACK_TRACE next to get offcputime example and finally prepare the PR.

@4ast
Copy link
Member

4ast commented Aug 2, 2016

table.insert(events, line) -- Write buffer to perf event map

is not intuitive. May be possible to introduce another builtin with explicit perf_event_output name ?
Other than that it looks good.

@vavrusa
Copy link
Contributor Author

vavrusa commented Aug 2, 2016

I agree, I think adding either perf_event_output builtin or bcc style map:perf_submit(val) map method would be a good idea.

@vavrusa
Copy link
Contributor Author

vavrusa commented Aug 9, 2016

Added support for STACK_TRACE maps, composed map values, 4.7 tracepoints with automagic argument parsing and casting and finally the offcputime example. There are some dodgy things, like parsing kallsyms, but I'm not going to reinvent that :)

$ sudo luajit examples/tracepoint-offcputime.lua 
    0x401d3b50 nil    -                vminfo        570
    0x4111e880 nil    -                rcu_sched        303
    0x4111f570 nil    -                kworker/u2:2        133
    0x41120268 nil    -                ksoftirqd/0        2
    0x41120f60 nil    -                dbus-daemon        144
    0x41121c58 nil    -                automount        13
    0x41122948 nil    -                luajit        42485
    0x41123608 nil    -                sshd        154071

@4ast
Copy link
Member

4ast commented Aug 9, 2016

looking forward to a PR

@vavrusa
Copy link
Contributor Author

vavrusa commented Aug 9, 2016

So I've read the contribute guide, but I'm not 100% clear on what would be the best way to approach this.

My idea is:

  • moving the library to src/lua/bpf (so that it can still require and use bcc Lua library for things like symbol demangling, ditch my simple elf parser)
  • moving the examples to examples/lua
  • moving the tests (and start new ones) in tests/lua

Since src/lua is going to be used both for current front-end and now back-end as well, it's going to be a bit messy, but it's already like that with C, so maybe it's not a big deal.

Would that be a way forward? CC @vmg

@vmg
Copy link
Contributor

vmg commented Aug 9, 2016

I've just found this thread! This looks amazing!! I actually tried to implement this earlier using direct Lua bytecode to BPF translations, but that didn't quite work out. I love how much you've gotten done here!

I think sticking the library into src/lua/bpf is perfectly fine. It can always be slightly moved around. Can't wait to look at the PR. :)

@4ast
Copy link
Member

4ast commented Aug 9, 2016

the proposed layout of directories makes sense to me.
contribution guide is mainly for the scripts.

@vavrusa
Copy link
Contributor Author

vavrusa commented Aug 12, 2016

Continuing in #652

@vavrusa vavrusa closed this as completed Aug 12, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants