iovisor / ubpf

Userspace eBPF VM
Apache License 2.0
814 stars 132 forks source link

What is the simplest `prog.c` can be passed to `vm/test`? #54

Open sarsanaee opened 3 years ago

sarsanaee commented 3 years ago

Hello,

I'd like to play with this tool, however, I'm not quite sure how to get started with it.

Is there a simple example to get started with? Like a simple prog.c?

Thanks, Alireza

carverdamien commented 3 years ago

Hi! What are you planning to do with ubpf ?

Example for prog.c

unsigned long int prog(char *addr) {
  if (addr)
    return 0;
  return 1;
}

Compile and run

$ clang -c prog.c -target bpf -o prog
$ vm/test prog
0x1
$ vm/test -m prog prog # addr will have the content of prog
0x0
sarsanaee commented 3 years ago

Thank you @carverdamien

I actually looked at Oko, and I realized that there are a couple of things not available in the uBPF, for example, maps. Although Oko has been built on top of uBPF.

I'd like to write complex eBPF functionalities using uBPF, isn't it possible? Imagine the following scenario for a single packet.

Wire -> NIC -> Kernel -> Userspace - Run a chain of BPF programs on the packet via uBPF -> Kernel -> NIC -> Wire

I'm also wondering what libraries I'm allowed or able to include in the uBPF programs?

carverdamien commented 3 years ago

You can call external functions in a bpf program but they must be registered first. register_functions

sarsanaee commented 3 years ago

Hi @carverdamien

I'm wondering why I couldn't call for example sqrti function in our simple prog.c file.

Here is what I did.

unsigned long int prog(char *addr) {
  sqrti(16); // here I called the registered function.
  if (addr)
    return 0;
  return 1;
}

Here is the warning generated. warning: implicit declaration of function 'sqrti' is invalid in C99 [-Wimplicit-function-declaration] sqrti(16);

When I run the program I get the following:

Failed to load code: bad relocation type 10

Probably, I'm missing something obvious here.

Thanks, Alireza

jpsamaroo commented 3 years ago

Helper calls in BPF are encoded as a call to an integer, where the integer is the index of the registered function you want to call. I think it should look something like this in C:

static int (*sqrti)(int) = (void *)1; // 1 is the index of our registered sqrti

unsigned long int prog(char *addr) {
  sqrti(16); // here I called the registered function.
  if (addr)
    return 0;
  return 1;
}

Unfortunately, I haven't been able to compile this such that vm/test is happy with it; it always results in Failed to load code: bad relocation type 1.

carverdamien commented 3 years ago

Compile with -O2

root@cda22c35d683:~# cat prog.c 
static int (*sqrti)(int) = (void *)3;
unsigned long int prog(char *addr) {
  return sqrti(16);
}
root@cda22c35d683:~# cat prog.s 
        .text
        .file   "prog.c"
        .globl  prog                    # -- Begin function prog
        .p2align        3
        .type   prog,@function
prog:                                   # @prog
# %bb.0:
        r1 = 16
        call 3
        r0 <<= 32
        r0 s>>= 32
        exit
.Lfunc_end0:
        .size   prog, .Lfunc_end0-prog
                                        # -- End function
        .addrsig
root@cda22c35d683:~# ./src/ubpf/vm/test -m prog prog
0x4
sarsanaee commented 3 years ago

Hello again,

Thanks for your time.

I have gone through the same steps. However, I'm still having troubles with Failed to load code: bad relocation type 10.

I also took a screenshot of my steps, which is similar to yours.

image

Isn't it a compiler version issue or something? Mine is "10.0.0"

carverdamien commented 3 years ago

You might be confusing prog and prog.o

sarsanaee commented 3 years ago

True, thank you :)

carverdamien commented 3 years ago

You are welcome ! :D

pchaigno commented 3 years ago

I actually looked at Oko, and I realized that there are a couple of things not available in the uBPF, for example, maps. Although Oko has been built on top of uBPF.

Oko author here :wave:

That's true, Oko supports additional features on top of ubpf, such as hash maps, arrays, and a simple verifier. I unfortunately never found the time to upstream all of those to ubpf :disappointed:

I'd like to write complex eBPF functionalities using uBPF, isn't it possible? Imagine the following scenario for a single packet. Wire -> NIC -> Kernel -> Userspace - Run a chain of BPF programs on the packet via uBPF -> Kernel -> NIC -> Wire

That is definitely possible. However, note that ubpf will only implement the actual uBPF loading and execution. To receive and send packets from userspace, you'll have to use something else, such as DPDK or Linux's AK_PACKET API.

sbates130272 commented 3 years ago

+1 to @pchaigno upstreaming those Oko changes back into this repo ;-)!