xdp-project / xdp-tools

Utilities and example programs for use with XDP

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

xdp-loader load xdp program with bpf tail call result in Bad file descriptor(-9)

vincentmli opened this issue · comments

Hi @tohojo

Here is a xdp with bpf tail call program I come up to test if libxdp support xdp program with bpf tail call to call another xdp program. Here is the commit for testing xdp_tailcall

#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <linux/if_ether.h>

/* tail call index */
#define DO_DROP 0

SEC("xdp")
int xdp_drop(struct xdp_md *ctx)
{
    return XDP_DROP;
}

struct {
        __uint(type, BPF_MAP_TYPE_PROG_ARRAY);
        __uint(max_entries, 2);
        __uint(key_size, sizeof(__u32));
        __uint(value_size, sizeof(__u32));
        __array(values, int (void *));
} jmp_table SEC(".maps") = {
        .values = {
                [DO_DROP] = (void *)&xdp_drop,
        },
};

SEC("xdp")
int xdp_tailcall(struct xdp_md *ctx)
{
        void *data_end = (void *)(long)ctx->data_end;
        void *data     = (void *)(long)ctx->data;

        // Only IPv4 supported for this example
        struct ethhdr *ether = data;
        if (data + sizeof(*ether) > data_end) {
                // Malformed Ethernet header
                bpf_tail_call(ctx, &jmp_table, DO_DROP);
        }

        return XDP_PASS;

}

char _license[] SEC("license") = "GPL";

the I use xdp-loader to load xdp program xdp_tailcall

 xdp-loader load -m skb -n xdp_tailcall lo xdp_tailcall.o
Couldn't attach XDP program on iface 'lo': Bad file descriptor(-9)

load the xdp_drop program works ok since it does not include bpf tailcall to another XDP program

xdp-loader load -m skb -n xdp_drop lo xdp_tailcall.o

any idea to solve this problem?

here it is, it appears libbpf: prog 'xdp_drop': skipped loading so libbpf: map 'jmp_table': failed to initialize slot [0] to prog 'xdp_drop' fd=-2: -9), I guess if xdp-loader with option to load all xdp program found object file could work around this issue?

root@r220:/home/vincent/go/src/github.com/vincentmli/xdp-tools/lib/testing# xdp-loader load -vv -m skb -n xdp_tailcall lo xdp_tailcall.o
Current rlimit 1017819136 already >= minimum 1048576
Loading 1 files on interface 'lo'.
  libbpf: loading xdp_tailcall.o
  libbpf: elf: section(3) xdp, size 96, link 0, flags 6, type=1
  libbpf: sec 'xdp': found program 'xdp_drop' at insn offset 0 (0 bytes), code size 2 insns (16 bytes)
  libbpf: sec 'xdp': found program 'xdp_tailcall' at insn offset 2 (16 bytes), code size 10 insns (80 bytes)
  libbpf: elf: section(4) .relxdp, size 16, link 26, flags 40, type=9
  libbpf: elf: section(5) .maps, size 40, link 0, flags 3, type=1
  libbpf: elf: section(6) .rel.maps, size 16, link 26, flags 40, type=9
  libbpf: elf: section(7) license, size 4, link 0, flags 3, type=1
  libbpf: license of xdp_tailcall.o is GPL
  libbpf: elf: section(17) .BTF, size 1138, link 0, flags 0, type=1
  libbpf: elf: section(19) .BTF.ext, size 184, link 0, flags 0, type=1
  libbpf: elf: section(26) .symtab, size 384, link 1, flags 0, type=2
  libbpf: looking for externs among 16 symbols...
  libbpf: collected 0 externs total
  libbpf: map 'jmp_table': at sec_idx 5, offset 0.
  libbpf: map 'jmp_table': found type = 3.
  libbpf: map 'jmp_table': found key_size = 4.
  libbpf: map 'jmp_table': found value_size = 4.
  libbpf: map 'jmp_table': found max_entries = 2.
  libbpf: sec '.relxdp': collecting relocation for section(3) 'xdp'
  libbpf: sec '.relxdp': relo #0: insn #6 against 'jmp_table'
  libbpf: prog 'xdp_tailcall': found map 0 (jmp_table, sec 5, off 0) for insn #4
  libbpf: .maps relo #0: for 12 value 0 rel->r_offset 32 name 126 ('xdp_drop')
  libbpf: .maps relo #0: map 'jmp_table' slot [0] points to prog 'xdp_drop'
 libxdp: DATASEC '.xdp_run_config' not found.
XDP program 0: Run prio: 50. Chain call actions: XDP_PASS
 libxdp: Generating multi-prog dispatcher for 1 programs
 libxdp: Checking for kernel frags support
 libxdp: Loading XDP program 'xdp-dispatcher.o' from embedded object file
  libbpf: loading object 'xdp-dispatcher.o' from buffer
  libbpf: elf: section(2) .text, size 528, link 0, flags 6, type=1
  libbpf: sec '.text': found program 'prog0' at insn offset 0 (0 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'prog1' at insn offset 6 (48 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'prog2' at insn offset 12 (96 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'prog3' at insn offset 18 (144 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'prog4' at insn offset 24 (192 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'prog5' at insn offset 30 (240 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'prog6' at insn offset 36 (288 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'prog7' at insn offset 42 (336 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'prog8' at insn offset 48 (384 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'prog9' at insn offset 54 (432 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'compat_test' at insn offset 60 (480 bytes), code size 6 insns (48 bytes)
  libbpf: elf: section(3) xdp, size 1200, link 0, flags 6, type=1
  libbpf: sec 'xdp': found program 'xdp_dispatcher' at insn offset 0 (0 bytes), code size 148 insns (1184 bytes)
  libbpf: sec 'xdp': found program 'xdp_pass' at insn offset 148 (1184 bytes), code size 2 insns (16 bytes)
  libbpf: elf: section(4) .relxdp, size 336, link 27, flags 40, type=9
  libbpf: elf: section(5) .rodata, size 124, link 0, flags 2, type=1
  libbpf: elf: section(6) license, size 4, link 0, flags 3, type=1
  libbpf: license of xdp-dispatcher.o is GPL
  libbpf: elf: section(7) xdp_metadata, size 8, link 0, flags 3, type=1
  libbpf: elf: skipping unrecognized data section(7) xdp_metadata
  libbpf: elf: section(18) .BTF, size 3271, link 0, flags 0, type=1
  libbpf: elf: section(20) .BTF.ext, size 2112, link 0, flags 0, type=1
  libbpf: elf: section(27) .symtab, size 1008, link 1, flags 0, type=2
  libbpf: looking for externs among 42 symbols...
  libbpf: collected 0 externs total
  libbpf: map 'xdp_disp.rodata' (global data): at sec_idx 5, offset 0, flags 80.
  libbpf: map 0 is "xdp_disp.rodata"
  libbpf: sec '.relxdp': collecting relocation for section(3) 'xdp'
  libbpf: sec '.relxdp': relo #0: insn #2 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 2
  libbpf: sec '.relxdp': relo #1: insn #7 against 'prog0'
  libbpf: sec '.relxdp': relo #2: insn #19 against 'prog1'
  libbpf: sec '.relxdp': relo #3: insn #20 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 20
  libbpf: sec '.relxdp': relo #4: insn #33 against 'prog2'
  libbpf: sec '.relxdp': relo #5: insn #34 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 34
  libbpf: sec '.relxdp': relo #6: insn #47 against 'prog3'
  libbpf: sec '.relxdp': relo #7: insn #48 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 48
  libbpf: sec '.relxdp': relo #8: insn #61 against 'prog4'
  libbpf: sec '.relxdp': relo #9: insn #62 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 62
  libbpf: sec '.relxdp': relo #10: insn #75 against 'prog5'
  libbpf: sec '.relxdp': relo #11: insn #76 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 76
  libbpf: sec '.relxdp': relo #12: insn #89 against 'prog6'
  libbpf: sec '.relxdp': relo #13: insn #90 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 90
  libbpf: sec '.relxdp': relo #14: insn #103 against 'prog7'
  libbpf: sec '.relxdp': relo #15: insn #104 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 104
  libbpf: sec '.relxdp': relo #16: insn #117 against 'prog8'
  libbpf: sec '.relxdp': relo #17: insn #118 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 118
  libbpf: sec '.relxdp': relo #18: insn #131 against 'prog9'
  libbpf: sec '.relxdp': relo #19: insn #132 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 132
  libbpf: sec '.relxdp': relo #20: insn #145 against 'compat_test'
 libxdp: DATASEC '.xdp_run_config' not found.
  libbpf: map 'xdp_disp.rodata': created successfully, fd=4
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog0'
  libbpf: prog 'xdp_dispatcher': insn #7 relocated, imm 140 points to subprog 'prog0' (now at 148 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog1'
  libbpf: prog 'xdp_dispatcher': insn #19 relocated, imm 134 points to subprog 'prog1' (now at 154 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog2'
  libbpf: prog 'xdp_dispatcher': insn #33 relocated, imm 126 points to subprog 'prog2' (now at 160 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog3'
  libbpf: prog 'xdp_dispatcher': insn #47 relocated, imm 118 points to subprog 'prog3' (now at 166 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog4'
  libbpf: prog 'xdp_dispatcher': insn #61 relocated, imm 110 points to subprog 'prog4' (now at 172 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog5'
  libbpf: prog 'xdp_dispatcher': insn #75 relocated, imm 102 points to subprog 'prog5' (now at 178 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog6'
  libbpf: prog 'xdp_dispatcher': insn #89 relocated, imm 94 points to subprog 'prog6' (now at 184 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog7'
  libbpf: prog 'xdp_dispatcher': insn #103 relocated, imm 86 points to subprog 'prog7' (now at 190 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog8'
  libbpf: prog 'xdp_dispatcher': insn #117 relocated, imm 78 points to subprog 'prog8' (now at 196 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog9'
  libbpf: prog 'xdp_dispatcher': insn #131 relocated, imm 70 points to subprog 'prog9' (now at 202 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'compat_test'
  libbpf: prog 'xdp_dispatcher': insn #145 relocated, imm 62 points to subprog 'compat_test' (now at 208 offset)
 libxdp: Loaded XDP program xdp_pass, got fd 6
 libxdp: Duplicated fd 6 to 7 for prog xdp_pass
 libxdp: Kernel supports XDP programs with frags
 libxdp: Loading XDP program 'xdp-dispatcher.o' from embedded object file
  libbpf: loading object 'xdp-dispatcher.o' from buffer
  libbpf: elf: section(2) .text, size 528, link 0, flags 6, type=1
  libbpf: sec '.text': found program 'prog0' at insn offset 0 (0 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'prog1' at insn offset 6 (48 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'prog2' at insn offset 12 (96 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'prog3' at insn offset 18 (144 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'prog4' at insn offset 24 (192 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'prog5' at insn offset 30 (240 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'prog6' at insn offset 36 (288 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'prog7' at insn offset 42 (336 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'prog8' at insn offset 48 (384 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'prog9' at insn offset 54 (432 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'compat_test' at insn offset 60 (480 bytes), code size 6 insns (48 bytes)
  libbpf: elf: section(3) xdp, size 1200, link 0, flags 6, type=1
  libbpf: sec 'xdp': found program 'xdp_dispatcher' at insn offset 0 (0 bytes), code size 148 insns (1184 bytes)
  libbpf: sec 'xdp': found program 'xdp_pass' at insn offset 148 (1184 bytes), code size 2 insns (16 bytes)
  libbpf: elf: section(4) .relxdp, size 336, link 27, flags 40, type=9
  libbpf: elf: section(5) .rodata, size 124, link 0, flags 2, type=1
  libbpf: elf: section(6) license, size 4, link 0, flags 3, type=1
  libbpf: license of xdp-dispatcher.o is GPL
  libbpf: elf: section(7) xdp_metadata, size 8, link 0, flags 3, type=1
  libbpf: elf: skipping unrecognized data section(7) xdp_metadata
  libbpf: elf: section(18) .BTF, size 3271, link 0, flags 0, type=1
  libbpf: elf: section(20) .BTF.ext, size 2112, link 0, flags 0, type=1
  libbpf: elf: section(27) .symtab, size 1008, link 1, flags 0, type=2
  libbpf: looking for externs among 42 symbols...
  libbpf: collected 0 externs total
  libbpf: map 'xdp_disp.rodata' (global data): at sec_idx 5, offset 0, flags 80.
  libbpf: map 0 is "xdp_disp.rodata"
  libbpf: sec '.relxdp': collecting relocation for section(3) 'xdp'
  libbpf: sec '.relxdp': relo #0: insn #2 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 2
  libbpf: sec '.relxdp': relo #1: insn #7 against 'prog0'
  libbpf: sec '.relxdp': relo #2: insn #19 against 'prog1'
  libbpf: sec '.relxdp': relo #3: insn #20 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 20
  libbpf: sec '.relxdp': relo #4: insn #33 against 'prog2'
  libbpf: sec '.relxdp': relo #5: insn #34 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 34
  libbpf: sec '.relxdp': relo #6: insn #47 against 'prog3'
  libbpf: sec '.relxdp': relo #7: insn #48 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 48
  libbpf: sec '.relxdp': relo #8: insn #61 against 'prog4'
  libbpf: sec '.relxdp': relo #9: insn #62 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 62
  libbpf: sec '.relxdp': relo #10: insn #75 against 'prog5'
  libbpf: sec '.relxdp': relo #11: insn #76 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 76
  libbpf: sec '.relxdp': relo #12: insn #89 against 'prog6'
  libbpf: sec '.relxdp': relo #13: insn #90 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 90
  libbpf: sec '.relxdp': relo #14: insn #103 against 'prog7'
  libbpf: sec '.relxdp': relo #15: insn #104 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 104
  libbpf: sec '.relxdp': relo #16: insn #117 against 'prog8'
  libbpf: sec '.relxdp': relo #17: insn #118 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 118
  libbpf: sec '.relxdp': relo #18: insn #131 against 'prog9'
  libbpf: sec '.relxdp': relo #19: insn #132 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 132
  libbpf: sec '.relxdp': relo #20: insn #145 against 'compat_test'
 libxdp: DATASEC '.xdp_run_config' not found.
 libxdp: At least one attached program doesn't support frags, disabling it for the dispatcher
 libxdp: Loading multiprog dispatcher for 1 programs without frags support
  libbpf: map 'xdp_disp.rodata': created successfully, fd=4
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog0'
  libbpf: prog 'xdp_dispatcher': insn #7 relocated, imm 140 points to subprog 'prog0' (now at 148 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog1'
  libbpf: prog 'xdp_dispatcher': insn #19 relocated, imm 134 points to subprog 'prog1' (now at 154 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog2'
  libbpf: prog 'xdp_dispatcher': insn #33 relocated, imm 126 points to subprog 'prog2' (now at 160 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog3'
  libbpf: prog 'xdp_dispatcher': insn #47 relocated, imm 118 points to subprog 'prog3' (now at 166 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog4'
  libbpf: prog 'xdp_dispatcher': insn #61 relocated, imm 110 points to subprog 'prog4' (now at 172 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog5'
  libbpf: prog 'xdp_dispatcher': insn #75 relocated, imm 102 points to subprog 'prog5' (now at 178 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog6'
  libbpf: prog 'xdp_dispatcher': insn #89 relocated, imm 94 points to subprog 'prog6' (now at 184 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog7'
  libbpf: prog 'xdp_dispatcher': insn #103 relocated, imm 86 points to subprog 'prog7' (now at 190 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog8'
  libbpf: prog 'xdp_dispatcher': insn #117 relocated, imm 78 points to subprog 'prog8' (now at 196 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog9'
  libbpf: prog 'xdp_dispatcher': insn #131 relocated, imm 70 points to subprog 'prog9' (now at 202 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'compat_test'
  libbpf: prog 'xdp_dispatcher': insn #145 relocated, imm 62 points to subprog 'compat_test' (now at 208 offset)
 libxdp: Loaded XDP program xdp_dispatcher, got fd 5
 libxdp: Duplicated fd 5 to 7 for prog xdp_dispatcher
 libxdp: Checking dispatcher compatibility
 libxdp: Loading XDP program 'xdp-dispatcher.o' from embedded object file
  libbpf: loading object 'xdp-dispatcher.o' from buffer
  libbpf: elf: section(2) .text, size 528, link 0, flags 6, type=1
  libbpf: sec '.text': found program 'prog0' at insn offset 0 (0 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'prog1' at insn offset 6 (48 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'prog2' at insn offset 12 (96 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'prog3' at insn offset 18 (144 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'prog4' at insn offset 24 (192 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'prog5' at insn offset 30 (240 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'prog6' at insn offset 36 (288 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'prog7' at insn offset 42 (336 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'prog8' at insn offset 48 (384 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'prog9' at insn offset 54 (432 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'compat_test' at insn offset 60 (480 bytes), code size 6 insns (48 bytes)
  libbpf: elf: section(3) xdp, size 1200, link 0, flags 6, type=1
  libbpf: sec 'xdp': found program 'xdp_dispatcher' at insn offset 0 (0 bytes), code size 148 insns (1184 bytes)
  libbpf: sec 'xdp': found program 'xdp_pass' at insn offset 148 (1184 bytes), code size 2 insns (16 bytes)
  libbpf: elf: section(4) .relxdp, size 336, link 27, flags 40, type=9
  libbpf: elf: section(5) .rodata, size 124, link 0, flags 2, type=1
  libbpf: elf: section(6) license, size 4, link 0, flags 3, type=1
  libbpf: license of xdp-dispatcher.o is GPL
  libbpf: elf: section(7) xdp_metadata, size 8, link 0, flags 3, type=1
  libbpf: elf: skipping unrecognized data section(7) xdp_metadata
  libbpf: elf: section(18) .BTF, size 3271, link 0, flags 0, type=1
  libbpf: elf: section(20) .BTF.ext, size 2112, link 0, flags 0, type=1
  libbpf: elf: section(27) .symtab, size 1008, link 1, flags 0, type=2
  libbpf: looking for externs among 42 symbols...
  libbpf: collected 0 externs total
  libbpf: map 'xdp_disp.rodata' (global data): at sec_idx 5, offset 0, flags 80.
  libbpf: map 0 is "xdp_disp.rodata"
  libbpf: sec '.relxdp': collecting relocation for section(3) 'xdp'
  libbpf: sec '.relxdp': relo #0: insn #2 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 2
  libbpf: sec '.relxdp': relo #1: insn #7 against 'prog0'
  libbpf: sec '.relxdp': relo #2: insn #19 against 'prog1'
  libbpf: sec '.relxdp': relo #3: insn #20 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 20
  libbpf: sec '.relxdp': relo #4: insn #33 against 'prog2'
  libbpf: sec '.relxdp': relo #5: insn #34 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 34
  libbpf: sec '.relxdp': relo #6: insn #47 against 'prog3'
  libbpf: sec '.relxdp': relo #7: insn #48 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 48
  libbpf: sec '.relxdp': relo #8: insn #61 against 'prog4'
  libbpf: sec '.relxdp': relo #9: insn #62 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 62
  libbpf: sec '.relxdp': relo #10: insn #75 against 'prog5'
  libbpf: sec '.relxdp': relo #11: insn #76 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 76
  libbpf: sec '.relxdp': relo #12: insn #89 against 'prog6'
  libbpf: sec '.relxdp': relo #13: insn #90 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 90
  libbpf: sec '.relxdp': relo #14: insn #103 against 'prog7'
  libbpf: sec '.relxdp': relo #15: insn #104 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 104
  libbpf: sec '.relxdp': relo #16: insn #117 against 'prog8'
  libbpf: sec '.relxdp': relo #17: insn #118 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 118
  libbpf: sec '.relxdp': relo #18: insn #131 against 'prog9'
  libbpf: sec '.relxdp': relo #19: insn #132 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 132
  libbpf: sec '.relxdp': relo #20: insn #145 against 'compat_test'
 libxdp: DATASEC '.xdp_run_config' not found.
 libxdp: Loading XDP program 'xdp-dispatcher.o' from embedded object file
  libbpf: loading object 'xdp-dispatcher.o' from buffer
  libbpf: elf: section(2) .text, size 528, link 0, flags 6, type=1
  libbpf: sec '.text': found program 'prog0' at insn offset 0 (0 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'prog1' at insn offset 6 (48 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'prog2' at insn offset 12 (96 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'prog3' at insn offset 18 (144 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'prog4' at insn offset 24 (192 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'prog5' at insn offset 30 (240 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'prog6' at insn offset 36 (288 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'prog7' at insn offset 42 (336 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'prog8' at insn offset 48 (384 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'prog9' at insn offset 54 (432 bytes), code size 6 insns (48 bytes)
  libbpf: sec '.text': found program 'compat_test' at insn offset 60 (480 bytes), code size 6 insns (48 bytes)
  libbpf: elf: section(3) xdp, size 1200, link 0, flags 6, type=1
  libbpf: sec 'xdp': found program 'xdp_dispatcher' at insn offset 0 (0 bytes), code size 148 insns (1184 bytes)
  libbpf: sec 'xdp': found program 'xdp_pass' at insn offset 148 (1184 bytes), code size 2 insns (16 bytes)
  libbpf: elf: section(4) .relxdp, size 336, link 27, flags 40, type=9
  libbpf: elf: section(5) .rodata, size 124, link 0, flags 2, type=1
  libbpf: elf: section(6) license, size 4, link 0, flags 3, type=1
  libbpf: license of xdp-dispatcher.o is GPL
  libbpf: elf: section(7) xdp_metadata, size 8, link 0, flags 3, type=1
  libbpf: elf: skipping unrecognized data section(7) xdp_metadata
  libbpf: elf: section(18) .BTF, size 3271, link 0, flags 0, type=1
  libbpf: elf: section(20) .BTF.ext, size 2112, link 0, flags 0, type=1
  libbpf: elf: section(27) .symtab, size 1008, link 1, flags 0, type=2
  libbpf: looking for externs among 42 symbols...
  libbpf: collected 0 externs total
  libbpf: map 'xdp_disp.rodata' (global data): at sec_idx 5, offset 0, flags 80.
  libbpf: map 0 is "xdp_disp.rodata"
  libbpf: sec '.relxdp': collecting relocation for section(3) 'xdp'
  libbpf: sec '.relxdp': relo #0: insn #2 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 2
  libbpf: sec '.relxdp': relo #1: insn #7 against 'prog0'
  libbpf: sec '.relxdp': relo #2: insn #19 against 'prog1'
  libbpf: sec '.relxdp': relo #3: insn #20 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 20
  libbpf: sec '.relxdp': relo #4: insn #33 against 'prog2'
  libbpf: sec '.relxdp': relo #5: insn #34 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 34
  libbpf: sec '.relxdp': relo #6: insn #47 against 'prog3'
  libbpf: sec '.relxdp': relo #7: insn #48 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 48
  libbpf: sec '.relxdp': relo #8: insn #61 against 'prog4'
  libbpf: sec '.relxdp': relo #9: insn #62 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 62
  libbpf: sec '.relxdp': relo #10: insn #75 against 'prog5'
  libbpf: sec '.relxdp': relo #11: insn #76 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 76
  libbpf: sec '.relxdp': relo #12: insn #89 against 'prog6'
  libbpf: sec '.relxdp': relo #13: insn #90 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 90
  libbpf: sec '.relxdp': relo #14: insn #103 against 'prog7'
  libbpf: sec '.relxdp': relo #15: insn #104 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 104
  libbpf: sec '.relxdp': relo #16: insn #117 against 'prog8'
  libbpf: sec '.relxdp': relo #17: insn #118 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 118
  libbpf: sec '.relxdp': relo #18: insn #131 against 'prog9'
  libbpf: sec '.relxdp': relo #19: insn #132 against '.rodata'
  libbpf: prog 'xdp_dispatcher': found data map 0 (xdp_disp.rodata, sec 5, off 0) for insn 132
  libbpf: sec '.relxdp': relo #20: insn #145 against 'compat_test'
 libxdp: DATASEC '.xdp_run_config' not found.
  libbpf: map 'xdp_disp.rodata': created successfully, fd=9
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog0'
  libbpf: prog 'xdp_dispatcher': insn #7 relocated, imm 140 points to subprog 'prog0' (now at 148 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog1'
  libbpf: prog 'xdp_dispatcher': insn #19 relocated, imm 134 points to subprog 'prog1' (now at 154 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog2'
  libbpf: prog 'xdp_dispatcher': insn #33 relocated, imm 126 points to subprog 'prog2' (now at 160 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog3'
  libbpf: prog 'xdp_dispatcher': insn #47 relocated, imm 118 points to subprog 'prog3' (now at 166 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog4'
  libbpf: prog 'xdp_dispatcher': insn #61 relocated, imm 110 points to subprog 'prog4' (now at 172 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog5'
  libbpf: prog 'xdp_dispatcher': insn #75 relocated, imm 102 points to subprog 'prog5' (now at 178 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog6'
  libbpf: prog 'xdp_dispatcher': insn #89 relocated, imm 94 points to subprog 'prog6' (now at 184 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog7'
  libbpf: prog 'xdp_dispatcher': insn #103 relocated, imm 86 points to subprog 'prog7' (now at 190 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog8'
  libbpf: prog 'xdp_dispatcher': insn #117 relocated, imm 78 points to subprog 'prog8' (now at 196 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog9'
  libbpf: prog 'xdp_dispatcher': insn #131 relocated, imm 70 points to subprog 'prog9' (now at 202 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'compat_test'
  libbpf: prog 'xdp_dispatcher': insn #145 relocated, imm 62 points to subprog 'compat_test' (now at 208 offset)
 libxdp: Loaded XDP program xdp_pass, got fd 11
 libxdp: Duplicated fd 11 to 12 for prog xdp_pass
  libbpf: map 'xdp_disp.rodata': created successfully, fd=14
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog0'
  libbpf: prog 'xdp_dispatcher': insn #7 relocated, imm 140 points to subprog 'prog0' (now at 148 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog1'
  libbpf: prog 'xdp_dispatcher': insn #19 relocated, imm 134 points to subprog 'prog1' (now at 154 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog2'
  libbpf: prog 'xdp_dispatcher': insn #33 relocated, imm 126 points to subprog 'prog2' (now at 160 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog3'
  libbpf: prog 'xdp_dispatcher': insn #47 relocated, imm 118 points to subprog 'prog3' (now at 166 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog4'
  libbpf: prog 'xdp_dispatcher': insn #61 relocated, imm 110 points to subprog 'prog4' (now at 172 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog5'
  libbpf: prog 'xdp_dispatcher': insn #75 relocated, imm 102 points to subprog 'prog5' (now at 178 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog6'
  libbpf: prog 'xdp_dispatcher': insn #89 relocated, imm 94 points to subprog 'prog6' (now at 184 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog7'
  libbpf: prog 'xdp_dispatcher': insn #103 relocated, imm 86 points to subprog 'prog7' (now at 190 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog8'
  libbpf: prog 'xdp_dispatcher': insn #117 relocated, imm 78 points to subprog 'prog8' (now at 196 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'prog9'
  libbpf: prog 'xdp_dispatcher': insn #131 relocated, imm 70 points to subprog 'prog9' (now at 202 offset)
  libbpf: prog 'xdp_dispatcher': added 6 insns from sub-prog 'compat_test'
  libbpf: prog 'xdp_dispatcher': insn #145 relocated, imm 62 points to subprog 'compat_test' (now at 208 offset)
 libxdp: Loaded XDP program xdp_pass, got fd 16
 libxdp: Duplicated fd 16 to 17 for prog xdp_pass
 libxdp: Acquired lock from /sys/fs/bpf/xdp with fd 19
 libxdp: Released lock fd 19
 libxdp: Linking prog xdp_tailcall as multiprog entry 0
  libbpf: map 'jmp_table': created successfully, fd=9
  libbpf: prog 'xdp_drop': skipped loading 
  libbpf: map 'jmp_table': failed to initialize slot [0] to prog 'xdp_drop' fd=-2: -9 
  libbpf: failed to load object 'xdp_tailcall.o'
 libxdp: Failed to load program xdp_tailcall: Bad file descriptor
Couldn't attach XDP program on iface 'lo': Bad file descriptor(-9)

if I do not give program name to xdp-loader, xdp-loader will load xdp_drop program, skip xdp_tailcall program

xdp-tools/lib/testing# xdp-loader load -vv -m skb  lo xdp_tailcall.o

 libxdp: Linking prog xdp_drop as multiprog entry 0
  libbpf: map 'jmp_table': created successfully, fd=9
  libbpf: prog 'xdp_tailcall': skipped loading
  libbpf: map 'jmp_table': slot [0] set to prog 'xdp_drop' fd=10
 libxdp: Loaded XDP program xdp_drop, got fd 10
 libxdp: Duplicated fd 10 to 11 for prog xdp_drop
 libxdp: Duplicated fd 11 to 12 for prog xdp_drop
 libxdp: DATASEC '.xdp_run_config' not found.
 libxdp: Attached prog 'xdp_drop' with priority 50 in dispatcher entry 'prog0' with fd 13
 libxdp: Acquired lock from /sys/fs/bpf/xdp with fd 14
 libxdp: Pinning multiprog fd 7 beneath /sys/fs/bpf/xdp/dispatch-1-580
 libxdp: Pinned link for prog xdp_drop at /sys/fs/bpf/xdp/dispatch-1-580/prog0-link
 libxdp: Pinned prog xdp_drop at /sys/fs/bpf/xdp/dispatch-1-580/prog0-prog
 libxdp: Released lock fd 14
 libxdp: Replacing XDP fd -1 with 7 on ifindex 1
 libxdp: Loaded 1 programs on ifindex 1 in skb mode

xdp-tools/lib/testing# xdp-loader status
CURRENT XDP PROGRAM STATUS:

Interface        Prio  Program name      Mode     ID   Tag               Chain actions
--------------------------------------------------------------------------------------
lo                     xdp_dispatcher    skb      561  90f686eb86991928 
 =>              50     xdp_drop                  570  57cd311f2e27366b  XDP_PASS
enp1s0f0               <No XDP program loaded!>
enp1s0f1               <No XDP program loaded!>
eno1                   <No XDP program loaded!>
eno2                   <No XDP program loaded!>
wg0                    <No XDP program loaded!>
virbr0                 <No XDP program loaded!>
docker0                <No XDP program loaded!>

Hmm, okay, so this would be due to 039bdea - could you please check if reverting that commit allows you to load the program including the tail call map?

ok, I reverted the commit, still xdp_tailcall is not loaded but xdp_drop, no more libbpf: prog 'xdp_tailcall': skipped loading message though


xdp-tools# ./xdp-loader/xdp-loader load -vv -m skb lo lib/testing/xdp_tailcall.o
...
 libxdp: Linking prog xdp_drop as multiprog entry 0
  libbpf: map 'jmp_table': created successfully, fd=9
  libbpf: map 'jmp_table': slot [0] set to prog 'xdp_drop' fd=10
 libxdp: Loaded XDP program xdp_drop, got fd 10
 libxdp: Duplicated fd 10 to 12 for prog xdp_drop
 libxdp: Duplicated fd 12 to 13 for prog xdp_drop
 libxdp: DATASEC '.xdp_run_config' not found.
 libxdp: Attached prog 'xdp_drop' with priority 50 in dispatcher entry 'prog0' with fd 14
 libxdp: Acquired lock from /sys/fs/bpf/xdp with fd 15
 libxdp: Pinning multiprog fd 7 beneath /sys/fs/bpf/xdp/dispatch-1-621
 libxdp: Pinned link for prog xdp_drop at /sys/fs/bpf/xdp/dispatch-1-621/prog0-link
 libxdp: Pinned prog xdp_drop at /sys/fs/bpf/xdp/dispatch-1-621/prog0-prog
 libxdp: Released lock fd 15
 libxdp: Replacing XDP fd -1 with 7 on ifindex 1
 libxdp: Loaded 1 programs on ifindex 1 in skb mode

xdp-tools# ./xdp-loader/xdp-loader status
CURRENT XDP PROGRAM STATUS:

Interface        Prio  Program name      Mode     ID   Tag               Chain actions
--------------------------------------------------------------------------------------
lo                     xdp_dispatcher    skb      621  90f686eb86991928 
 =>              50     xdp_drop                  630  57cd311f2e27366b  XDP_PASS
enp1s0f0               <No XDP program loaded!>

I see :), xdp_tailcall indeed can be loaded, but xdp_drop is not loaded, I thought both xdp_tailcall and xdp_drop should be loaded to work properly, no?

xdp-tools# ./xdp-loader/xdp-loader load -vv -m skb lo  -n xdp_drop -n xdp_tailcall  lib/testing/xdp_tailcall.o 

 libxdp: Linking prog xdp_tailcall as multiprog entry 0
  libbpf: map 'jmp_table': created successfully, fd=9
  libbpf: map 'jmp_table': slot [0] set to prog 'xdp_drop' fd=10
 libxdp: Loaded XDP program xdp_tailcall, got fd 11
 libxdp: Duplicated fd 11 to 12 for prog xdp_tailcall
 libxdp: Duplicated fd 12 to 13 for prog xdp_tailcall
 libxdp: DATASEC '.xdp_run_config' not found.
 libxdp: Attached prog 'xdp_tailcall' with priority 50 in dispatcher entry 'prog0' with fd 14
 libxdp: Acquired lock from /sys/fs/bpf/xdp with fd 15
 libxdp: Pinning multiprog fd 7 beneath /sys/fs/bpf/xdp/dispatch-1-761
 libxdp: Pinned link for prog xdp_tailcall at /sys/fs/bpf/xdp/dispatch-1-761/prog0-link
 libxdp: Pinned prog xdp_tailcall at /sys/fs/bpf/xdp/dispatch-1-761/prog0-prog
 libxdp: Released lock fd 15
 libxdp: Replacing XDP fd -1 with 7 on ifindex 1
 libxdp: Loaded 1 programs on ifindex 1 in skb mode

xdp-tools# ./xdp-loader/xdp-loader status
CURRENT XDP PROGRAM STATUS:

Interface        Prio  Program name      Mode     ID   Tag               Chain actions
--------------------------------------------------------------------------------------
lo                     xdp_dispatcher    skb      761  90f686eb86991928 
 =>              50     xdp_tailcall              771  c5f3e5873e190275  XDP_PASS

the map is empty

xdp-tools# bpftool map
265: array  name xdp_disp.rodata  flags 0x80
	key 4B  value 124B  max_entries 1  memlock 4096B
	btf_id 519  frozen
268: prog_array  name jmp_table  flags 0x0
	key 4B  value 4B  max_entries 2  memlock 4096B
	owner_prog_type xdp  owner jited
271: array  name pid_iter.rodata  flags 0x480
	key 4B  value 4B  max_entries 1  memlock 4096B
	btf_id 531  frozen
	pids bpftool(258283)
272: array  name libbpf_det_bind  flags 0x0
	key 4B  value 32B  max_entries 1  memlock 4096B

xdp-tools# bpftool map dump id 268
Found 0 elements

I think both xdp program should be loaded, the reason I say that is because I had a port with similar tail call for libbpf-bootstrap, where I see all xdp program are loaded and attached, maybe xdp-loader could accept multiple -n argument to explicitly load/attach multiple xdp program from one object file?

I understand, I used xdp-loader just for quick check if libxdp is compatible with xdp program with tail call, since my plan is to port DNS RRL xdp program which happen to use tail call to bpf-example repo, I need to write xdp-loader like user space program to load the DNS RRL xdp program.

@tohojo I added sleep in xdp-loader, indeed all xdp program are loaded and map is populated, thanks for the clue :)

xdp-tools# bpftool map
285: array  name xdp_disp.rodata  flags 0x80
	key 4B  value 124B  max_entries 1  memlock 4096B
	btf_id 554  frozen
288: prog_array  name jmp_table  flags 0x0
	key 4B  value 4B  max_entries 2  memlock 4096B
	owner_prog_type xdp  owner jited
	pids xdp-loader(259549)
291: array  name pid_iter.rodata  flags 0x480
	key 4B  value 4B  max_entries 1  memlock 4096B
	btf_id 566  frozen
	pids bpftool(259552)
292: array  name libbpf_det_bind  flags 0x0
	key 4B  value 32B  max_entries 1  memlock 4096B
xdp-tools# bpftool map dump id 288
key: 00 00 00 00  value: 35 03 00 00
Found 1 element

xdp-tools# bpftool prog

812: xdp  name xdp_dispatcher  tag 90f686eb86991928  gpl
	loaded_at 2023-12-08T14:41:54+0000  uid 0
	xlated 672B  jited 531B  memlock 4096B  map_ids 285
	btf_id 554
821: xdp  name xdp_drop  tag 57cd311f2e27366b  gpl
	loaded_at 2023-12-08T14:41:54+0000  uid 0
	xlated 16B  jited 19B  memlock 4096B
	btf_id 557
	pids xdp-loader(259549)
822: ext  name xdp_tailcall  tag c5f3e5873e190275  gpl
	loaded_at 2023-12-08T14:41:54+0000  uid 0
	xlated 80B  jited 80B  memlock 4096B  map_ids 288
	btf_id 557
	pids xdp-loader(259549)

xdp-tools# ./xdp-loader/xdp-loader status
CURRENT XDP PROGRAM STATUS:

Interface        Prio  Program name      Mode     ID   Tag               Chain actions
--------------------------------------------------------------------------------------
lo                     xdp_dispatcher    skb      848  90f686eb86991928 
 =>              50     xdp_tailcall              858  c5f3e5873e190275  XDP_PASS

sorry one more question, should I pin the xdp program or pin the program array map or both? I guess I can test to find out :)

I changed jmp_table map with pinning and gave
xdp-loader with -p argument did it

struct {
        __uint(type, BPF_MAP_TYPE_PROG_ARRAY);
        __uint(max_entries, 2);
        __uint(key_size, sizeof(__u32));
        __uint(value_size, sizeof(__u32));
        __uint(pinning, LIBBPF_PIN_BY_NAME); <===
        __array(values, int (void *));
} jmp_table SEC(".maps") = {
        .values = {
                [DO_DROP] = (void *)&xdp_drop,
        },
};

xdp-tools# ./xdp-loader/xdp-loader load  -vv -p /sys/fs/bpf/xdp_tailcall -m skb lo   -n xdp_tailcall  lib/testing/xdp_tailcall.o

 libxdp: Linking prog xdp_tailcall as multiprog entry 0
  libbpf: found no pinned map to reuse at '/sys/fs/bpf/xdp_tailcall/jmp_table'
  libbpf: map 'jmp_table': created successfully, fd=9
  libbpf: pinned map '/sys/fs/bpf/xdp_tailcall/jmp_table' <======map pinned
  libbpf: map 'jmp_table': slot [0] set to prog 'xdp_drop' fd=10
 libxdp: Loaded XDP program xdp_tailcall, got fd 11
 libxdp: Duplicated fd 11 to 12 for prog xdp_tailcall
 libxdp: Duplicated fd 12 to 13 for prog xdp_tailcall
 libxdp: DATASEC '.xdp_run_config' not found.
 libxdp: Attached prog 'xdp_tailcall' with priority 50 in dispatcher entry 'prog0' with fd 14
 libxdp: Acquired lock from /sys/fs/bpf/xdp with fd 15
 libxdp: Pinning multiprog fd 7 beneath /sys/fs/bpf/xdp/dispatch-1-1064
 libxdp: Pinned link for prog xdp_tailcall at /sys/fs/bpf/xdp/dispatch-1-1064/prog0-link
 libxdp: Pinned prog xdp_tailcall at /sys/fs/bpf/xdp/dispatch-1-1064/prog0-prog
 libxdp: Released lock fd 15
 libxdp: Replacing XDP fd -1 with 7 on ifindex 1
 libxdp: Loaded 1 programs on ifindex 1 in skb mode

xdp-tools# bpftool map dump id 400

key: 00 00 00 00  value: 31 04 00 00
Found 1 element

1064: xdp  name xdp_dispatcher  tag 90f686eb86991928  gpl
	loaded_at 2023-12-08T18:07:58+0000  uid 0
	xlated 672B  jited 531B  memlock 4096B  map_ids 397
	btf_id 771
1073: xdp  name xdp_drop  tag 57cd311f2e27366b  gpl
	loaded_at 2023-12-08T18:07:58+0000  uid 0
	xlated 16B  jited 19B  memlock 4096B
	btf_id 774
1074: ext  name xdp_tailcall  tag c5f3e5873e190275  gpl
	loaded_at 2023-12-08T18:07:58+0000  uid 0
	xlated 80B  jited 80B  memlock 4096B  map_ids 400
	btf_id 774