I am trying to use BPF_MAP_TYPE_ARRAY
for tracking new connections and want to maintain a map with tuples and new connection details. I am using libbpf
framework However, the map creation does not work when either of the key or value is a user-defined struct as shown below:
Note: Have gone through this post, but my code does not run at all!
struct network_tuple
{
__u32 saddr;
__u32 daddr;
__u16 sport;
__u16 dport;
__u8 l4_proto;
};
struct syn_event
{
__u64 time_ns;
__u32 tcp_seq;
struct network_tuple flow_key;
};
#define MAX_ENTRIES_FLOW 1
// does not work
struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__type(key, struct network_tuple);
__type(value, struct syn_event);
__uint(max_entries, MAX_ENTRIES_FLOW);
} flow_table SEC(".maps");
// works
struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__type(key, __u32);
__type(value, __u32);
__uint(max_entries, MAX_ENTRIES_FLOW);
} flow_table SEC(".maps");
Code compiles fine but does not get loaded. Output when code is run:
libbpf: Error in bpf_create_map_xattr(flow_table):Invalid argument(-22). Retrying without BTF.
libbpf: map 'flow_table': failed to create: Invalid argument(-22)
libbpf: failed to load object 'tp_bpf'
libbpf: failed to load BPF skeleton 'tp_bpf': -22
In the minimal_legacy.bpf.c code of libbpf-bootstrap repo the comment says "Create an array with 1 entry instead of a global variable which does not work with older kernels", however, with the key and value as __u32 more than 1 max_entries work, but with key and value as network_tuple and syn_event, it does not work even with max_entries equal to 1.
Working on:
OS: Ubuntu 22.04.2 LTS
kernel version: 5.15.0-77-generic
Any idea how can I solve this problem?
The BPF_MAP_TYPE_ARRAY
map type is as the name suggests an array. So the key type of that map must be a 4 byte value (__u32
). If you want a map with a struct network_tuple
as key you must use a BPF_MAP_TYPE_HASH
instead.
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__type(key, struct network_tuple);
__type(value, struct syn_event);
__uint(max_entries, MAX_ENTRIES_FLOW);
} flow_table SEC(".maps");