multipath-tcp / mptcp_net-next

Development version of the Upstream MultiPath TCP Linux kernel 🐧
https://mptcp.dev
Other
290 stars 41 forks source link

Implement psock_update_sk_prot, for eBPF SOCKMAP support #521

Open skeggse opened 1 month ago

skeggse commented 1 month ago

I'd like to "splice" TCP and MPTCP sockets together using an eBPF SOCKMAP in a BPF_SK_SKB_STREAM_VERDICT program.

I managed to get a program compiled and loaded that did just that, but when running it I got an obscure errno 95 ("Operation not supported").

After some hunting, I found the following in the bpf syscall implementation:

https://github.com/multipath-tcp/mptcp_net-next/blob/6aac56631831e1386b6edd3c583c8afb2abfd267/net/core/sock_map.c#L573-L576

https://github.com/multipath-tcp/mptcp_net-next/blob/6aac56631831e1386b6edd3c583c8afb2abfd267/net/core/sock_map.c#L533-L536

I couldn't find an implementation of psock_update_sk_prot for MPTCP either upstream or in this repository, so I'm guessing that's the cause of the issue I'm seeing. I really have no idea what psock_update_sk_prot is supposed to do - I'm a user, not a Kernel developer, but I'd love to be able to add my MPTCP sockets to a socket map!

Curious if there are implementation challenges to doing this, or if this is simply a yet-unimplemented method.

matttbe commented 1 month ago

Hi,

Thank you for having created this issue.

It looks like it is an important missing feature, I guess nobody took the time to implement that. Do you have a small example on how to use this feature from the user space?

skeggse commented 1 month ago

Yeah! Here's an example using Python and bcc.

import ctypes
import socket

from bcc import lib, BPF

b = BPF(
  text="""\
struct sock_key {
  u64 cookie;
};

BPF_SOCKHASH(my_hash, struct sock_key, 65535);
"""
)

map_fd = lib.bpf_table_fd(b.module, b"my_hash")

# Fairly arbitrary for this example.
class sock_key(ctypes.Structure):
  _fields_ = [("cookie", ctypes.c_uint64)]

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_MPTCP)

# Returns -95, in part due to the missing psock_update_sk_prot implementation.
lib.bpf_update_elem(map_fd, ctypes.byref(sock_key(0)), ctypes.byref(ctypes.c_int(sock.fileno())), 0)

For a more worked example, see https://github.com/skeggse/mptcp-ebpf-proxy - the above example shows some of the necessary steps, but is not sufficient because: