Open d0u9 opened 2 years ago
Can you show the definition of the map, and how it's referenced by the code?
#include "headers.h"
#include "helpers.h"
#include "defs.h"
#include "map_types/config.h"
typedef __u32 uint32_t;
struct tuple {
long packets;
long bytes;
};
#define BPF_MAP_ID_STATS 1 /* agent's map identifier */
#define BPF_MAX_MARK 256
struct bpf_elf_map SEC("maps") config_map = {
.type = BPF_MAP_TYPE_ARRAY,
.id = BPF_MAP_ID_STATS,
.size_key = sizeof(uint32_t),
.size_value = sizeof(struct tuple),
.max_elem = BPF_MAX_MARK,
.pinning = PIN_GLOBAL_NS,
};
static inline void cls_update_stats(const struct __sk_buff *skb,
uint32_t mark)
{
struct tuple *tu;
tu = bpf_map_lookup_elem(&config_map, &mark);
if (likely(tu)) {
__sync_fetch_and_add(&tu->packets, 1);
__sync_fetch_and_add(&tu->bytes, skb->len);
}
}
SEC("classifier/egress")
int cls_main(struct __sk_buff *skb)
{
uint32_t mark = skb->mark;
if (unlikely(mark >= BPF_MAX_MARK))
return 0;
cls_update_stats(skb, mark);
return TC_H_MAKE(TC_H_ROOT, mark);
}
char __license[] SEC("license") = "GPL";
This sample comes from https://man7.org/linux/man-pages/man8/tc-bpf.8.html
But the error doesn't seem to be related to that program? The function/variable names don't match
@alessandrod I have updated the code above. My bpf code is a modified version of the sample in the tc-bpf
manual in which only section names are changed.
Full error message:
RelocationError { function: "egress", error: SectionNotFound { section_index: 5, symbol_index: 6, symbol_name: Some("config_map") } }
readelf -S :
There are 10 section headers, starting at offset 0x280:
Section Headers:
[Nr] Name Type Address Off Size ES Flg Lk Inf Al
[ 0] NULL 0000000000000000 000000 000000 00 0 0 0
[ 1] .strtab STRTAB 0000000000000000 000208 000072 00 0 0 1
[ 2] .text PROGBITS 0000000000000000 000040 000000 00 AX 0 0 4
[ 3] classifier/egress PROGBITS 0000000000000000 000040 000090 00 AX 0 0 8
[ 4] .relclassifier/egress REL 0000000000000000 0001e8 000010 10 9 3 8
[ 5] maps PROGBITS 0000000000000000 0000d0 000024 00 WA 0 0 4
[ 6] license PROGBITS 0000000000000000 0000f4 000004 00 WA 0 0 1
[ 7] .eh_frame PROGBITS 0000000000000000 0000f8 000030 00 A 0 0 8
[ 8] .rel.eh_frame REL 0000000000000000 0001f8 000010 10 9 7 8
[ 9] .symtab SYMTAB 0000000000000000 000128 0000c0 18 1 5 8
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
R (retain), p (processor specific)
It works smoothly with tc command. I think the bpf side has no probelem.
@d0u9 I've reproduced this and it's not (really) an aya issue.
man tc-bpf
refers to how iproute2
handles ebpf. the important difference here appears to be that iproute2
allows you to use bpf_elf_map
for map definitions whereas libbpf
and the kernel expect bpf_map_def
. Any loader other than iproute2
will fail in a similar way - although we should probably error out sooner.
I can make the example load by replacing the map definition as follows:
struct bpf_map_def __section("maps") map_stats = {
.type = BPF_MAP_TYPE_ARRAY,
.key_size = sizeof(uint32_t),
.value_size = sizeof(struct tuple),
.max_entries = BPF_MAX_MARK,
.map_flags = 0,
};
I think the problem is that we don't handle "maps" as a valid map name (and we should)
struct bpf_elf_map SEC("maps") config_map = {
@d0u9 could you change this to be
struct bpf_elf_map SEC("maps/config_map") config_map = {
and see if that works?
@alessandrod Sorry for my late reply
see if that works?
I tested the case in which SEC("maps")
changes toSEC("maps/config_map")
. However, the map cannot be created by tc
command as wished.
It seems that tc
command only accepts the maps
section as its default searching place for valid BPF maps.
Sorry for the late ping, but
It seems that tc command only accepts the maps section as its default searching place for valid BPF maps.
I believe that's the case, hence I had used https://github.com/aquarhead/protect-the-rabbit/blob/master/Makefile.toml#L12 (in redbpf era code, but still applies here) after much painful debugging and trying random things.
Not sure what would be the best solution here (I'm out of context for a really long time xD)
The Classifier BPF source contains a hashmap in
maps
section. It is referenced by a program inegress
section as documented intc-bpf
manual.However, when loading via
Bpf::load_file(xx)
, I get anRelocationError
saying:This bpf object can be loaded via
tc filter
command successfully, and the map can be shown viabpftool map
.output of
llvm-readelf -S
: