xdp-project / xdp-tutorial

XDP tutorial
2.49k stars 579 forks source link

How to share eBPF between two XDP clients? #134

Closed cyanide-burnout closed 4 years ago

cyanide-burnout commented 4 years ago

How to share eBPF between two XDP clients?

tohojo commented 4 years ago

Erm, you're going to have to elaborate a bit on that question? :)

On 16 June 2020 19:31:30 CEST, Artem Prilutskiy notifications@github.com wrote:

How to share eBPF between two XDP clients?

cyanide-burnout commented 4 years ago

Ok, I have server software which mostly uses small-sized UDP packets. I coded alternative user-space stacks to receive and send UDP directly by using different methods depending on configuration (non-blocked sockets with retransmission thread, PACKET_MAP, XDP, DPDK). I wrote eBPF filter which grabs UDP packets for registered ports and passes it to user-space via XDP socket. One of the base concept of the software is event-based model with minimal amount of threads. Horizontal scaling is possible by running several instances of app on the same host on different CPU cores and IPC between instances. My eBPF filter designed to pass traffic to different sockets depending on assigned UDP ports but the problem is I didn't found the way in libbpf how to access to preloaded ePBF filter in second instance of the process.

tohojo commented 4 years ago

Artem Prilutskiy notifications@github.com writes:

Ok, I have server software which mostly uses small-sized UDP packets. I coded alternative user-space stacks to receives and sends UDP directly by using different methods depending on configuration (non-blocked sockets with retransmission thread, PACKET_MAP, XDP, DPDK).

I wrote eBPF filter which grabs UDP packets for registered ports and passes it to user-space via XDP socket. One of the base concept of the software is event-based model with minimal amount of threads. Horizontal scaling is possible by run several instances of app on the same host on different CPU cores and IPC between instances.

My eBPF filter designed to pass traffic to different sockets depending on assigned UDP ports but the problem is I didn't found the way in libbpf how to access to preloaded ePBF filter in second instance of the process.

That "eBPF filter" you're talking about is an XDP program loaded on a network interface, right? And you want that XDP program to pass the packets to different XSK sockets based on some criteria? You'd do this by putting multiple sockets into the xskmap you're referring in the XDP program; note that you need the socket configuration to match the actual hardware RXQ you're receiving the packet on for this to work.

You can pin the map fd on bpffs to get a reference to it in different applications.

cyanide-burnout commented 4 years ago

That "eBPF filter" you're talking about is an XDP program loaded on a network interface, right?

Yes, I'm talking about access to object file loaded into the kernel which does filtering and routing to AF_XDP sockets.

And you want that XDP program to pass the packets to different XSK sockets based on some criteria?

I don't want. It's already implemented and it is in production for half of the year )))

You'd do this by putting multiple sockets into the xskmap you're referring in the XDP program; note that you need the socket configuration to match the actual hardware RXQ you're receiving the packet on for this to work.

Yes, I create as many sockets as NIC has RXQ (discovered by ioctl / SIOCETHTOOL / ETHTOOL_GCHANNELS), and put it into the BPF_MAP_TYPE_XSKMAP, no issues with this.

You can pin the map fd on bpffs to get a reference to it in different applications.

Please point me how. How to access to BPF_MAP_TYPE_XSKMAP of already loaded eBPF program by another PID? I cannot find any documentation about this in libbpf or something suitable in .h-files. Is there any other way to enumerate and access to loadded program except direct loading by bpf_prog_load_xattr? It's not clear in documentation and code of libbpf what does bpf_prog_load_xattr when the program is already loaded.

tohojo commented 4 years ago

Artem Prilutskiy notifications@github.com writes:

You can pin the map fd on bpffs to get a reference to it in different applications.

Please point me how. How to access to BPF_MAP_TYPE_XSKMAP of already loaded eBPF program by another PID?

You can either pin it manually using bpf_map__pin(), or you can set the map creation attribute 'pinning' to LIBBPF_PIN_BY_NAME, in which case libbpf will automatically pin it at /sys/fs/bpf/map_name (or beneath a path you specify yourself with the pin_root_path option to bpf_object__open_file().

In both cases you get back an fd to the map by using bpf_obj_get() with the pathname it is pinned under.

You can of course also use any of the regular IPC mechanisms to pass over the fd from the original program to the second one (sockets, pipes, etc)...

cyanide-burnout commented 4 years ago

Thank you very much for hits. I preferred to create separate daemon with D-BUS interface and activation via systemd. The daemon loads eBPF program, links it with a NIC and shares all required handles with the main program.