Re: static and dynamic linking. Was: [PATCH bpf-next v3 1/5] bpf: Support chain calling multiple BPF

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, 12 Nov 2019 at 02:51, Alexei Starovoitov
<alexei.starovoitov@xxxxxxxxx> wrote:
>
> This is static linking. The existing kernel infrastructure already supports
> such model and I think it's enough for a lot of use cases. In particular fb's
> firewall+katran XDP style will fit right in. But bpf_tail_calls are
> incompatible with bpf2bpf calls that static linking will use and I think
> cloudlfare folks expressed the interest to use them for some reason even within
> single firewall ? so we need to improve the model a bit.

We several components that we'd like to keep (logically) separate. At a high
level, our rootlet would look like this:

  sample_packets(ctx);
  if (ddos_mitigate(ctx) != XDP_PASS) {
     return XDP_DROP;
  }
  return l4lb(ctx);

I think we could statically link ddos_mitigate() together from
multiple separate .o.
It depends on how complicated our rules become. Maybe we'd use dynamic linking,
to reduce the overhead of re-verification.

The rootlet would use dynamic linking, to be able to debug / inspect
sampling, ddos
mitigation and the l4lb separately. Combined with the ability to hook
arbitrary BPF
programs at entry / exit we could probably get rid of our tail_call
use. I don't think
you have to change the model for us to fit into it.

> We can introduce dynamic linking. The second part of 'BPF trampoline' patches
> allows tracing programs to attach to other BPF programs. The idea of dynamic
> linking is to replace a program or subprogram instead of attaching to it.

Reading the rest of the thread, I'm on board with type 2 of dynamic linking
(load time linking?) However, type 1 (run time linking) I'm not so sure about.
Specifically, the callee holding onto the caller instead of vice versa.

Picking up your rootlet and fw1 example: fw1 holds the refcount on rootlet.
This means user space needs to hold the refcount on fw1 to make sure
the override is kept. This in turn means either: hold on to the file descriptor
or pin the program into a bpffs. The former implies a persistent process,
which doesn't work for tc. The latter makes  lifetime management of fw1 hard:
there is no way to have the kernel automatically deallocate it when it no longer
needed, aka when the rootlet refcount reaches zero. It also overloads close()
to automatically detach the replaced / overridden BPF, which is contrary to how
other BPF hook points work.

I'd much prefer if the API didn't require attach_prog_fd and id at
load time, and
rather have an explicit replace_sub_prog(prog_fd, btf_id, sub_prog_fd).

> [...] This rootlet.o
> can be automatically generated by libxdp.so. If in the future we figure out how
> to do two load-balancers libxdp.so will be able to accommodate that new policy.
> This firewall1.o can be developed and tested independently of other xdp
> programs. The key gotcha here is that the verifier needs to allow more than 512
> stack usage for the rootlet.o. I think that's acceptable.

How would the verifier know which programs are allowed to have larger stacks?

Lorenz

-- 
Lorenz Bauer  |  Systems Engineer
6th Floor, County Hall/The Riverside Building, SE1 7PB, UK

www.cloudflare.com



[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux