1

I'm doing BPF programming and I want to add a socket to socket map. The code is as follows

When it detects a listen/connect, the socket is added to a socket map

__section("sockops")
int bpf_sockmap(struct bpf_sock_ops *skops)
{
    switch (skops->op) {
        case BPF_SOCK_OPS_TCP_LISTEN_CB:
            if (skops->family == 2) {
                bpf_sock_ops_ipv4(skops);
            }
            break;
        case BPF_SOCK_OPS_TCP_CONNECT_CB:
            if (skops->family == 2) {
                bpf_sock_ops_ipv4(skops);
            }
            break;
        default:
            break;
    }
    return 0;
}

The bpf_sock_ops_ipv4() is

void bpf_sock_ops_ipv4(struct bpf_sock_ops *skops)
{
    struct sock_key key = {};
    int ret;

    extract_key4_from_ops(skops, &key); // extract some field from skops to form the key structure

    ret = sock_hash_update(skops, &sock_ops_map, &key, BPF_ANY);
    if (ret != 0) {
        printk("sock_hash_update() failed, ret: %d\n", ret);
    }

    printk("sockmap: op %d, port %d --> %d\n",
            skops->op, skops->local_port, bpf_ntohl(skops->remote_port));
}

The map structure

struct bpf_map_def __section("maps") sock_ops_map = {
    .type           = BPF_MAP_TYPE_SOCKHASH,
    .key_size       = sizeof(struct sock_key),
    .value_size     = sizeof(int),
    .max_entries    = 65535,
    .map_flags      = 0,
};

The key structure

struct sock_key {
    __u32 ops;
    __u32 sip4;
    __u32 dip4;
    __u8  family;
    __u8  pad1;
    __u16 pad2;
    __u32 pad3;
    __u32 sport;
    __u32 dport;
} __attribute__((packed));

When I load it and init a server using sudo socat TCP4-LISTEN:1001,fork exec:cat, The update fails

sudo cat /sys/kernel/debug/tracing/trace_pipe 
           socat-1239  [002] ....  2020.217663: 0: sock_hash_update() failed, ret: -95
           socat-1239  [002] ....  2020.217682: 0: sockmap: op 11, port 1001 --> 0
1t3a
  • 31
  • 3
  • What socket type are you using, any chance you're working with a raw socket? From a quick look at the kernel code, it looks like the helper returns -95 (a.k.a `-EOPNOTSUPP`) if the socket is not TCP or UDP (see [the check in the helper](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/core/sock_map.c?h=v5.11#n639), and the definition for [`sock_map_sk_is_suitable()`](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/core/sock_map.c?h=v5.11#n550). – Qeole Mar 15 '21 at 09:43

0 Answers0