mbox series

[PATCHv2,iproute2-next,0/5] iproute2: add libbpf support

Message ID 20201028132529.3763875-1-haliu@redhat.com (mailing list archive)
Headers show
Series iproute2: add libbpf support | expand

Message

Hangbin Liu Oct. 28, 2020, 1:25 p.m. UTC
This series converts iproute2 to use libbpf for loading and attaching
BPF programs when it is available. This means that iproute2 will
correctly process BTF information and support the new-style BTF-defined
maps, while keeping compatibility with the old internal map definition
syntax.

This is achieved by checking for libbpf at './configure' time, and using
it if available. By default the system libbpf will be used, but static
linking against a custom libbpf version can be achieved by passing
LIBBPF_DIR to configure. FORCE_LIBBPF can be set to force configure to
abort if no suitable libbpf is found (useful for automatic packaging
that wants to enforce the dependency).

The old iproute2 bpf code is kept and will be used if no suitable libbpf
is available. When using libbpf, wrapper code ensures that iproute2 will
still understand the old map definition format, including populating
map-in-map and tail call maps before load.

The examples in bpf/examples are kept, and a separate set of examples
are added with BTF-based map definitions for those examples where this
is possible (libbpf doesn't currently support declaratively populating
tail call maps).

At last, Thanks a lot for Toke's help on this patch set.


v2:
a) Remove self defined IS_ERR_OR_NULL and use libbpf_get_error() instead.
b) Add ipvrf with libbpf support.


Here are the test results with patched iproute2:

== setup env
# clang -O2 -Wall -g -target bpf -c bpf_graft.c -o btf_graft.o
# clang -O2 -Wall -g -target bpf -c bpf_map_in_map.c -o btf_map_in_map.o
# clang -O2 -Wall -g -target bpf -c bpf_shared.c -o btf_shared.o
# clang -O2 -Wall -g -target bpf -c legacy/bpf_cyclic.c -o bpf_cyclic.o
# clang -O2 -Wall -g -target bpf -c legacy/bpf_graft.c -o bpf_graft.o
# clang -O2 -Wall -g -target bpf -c legacy/bpf_map_in_map.c -o bpf_map_in_map.o
# clang -O2 -Wall -g -target bpf -c legacy/bpf_shared.c -o bpf_shared.o
# clang -O2 -Wall -g -target bpf -c legacy/bpf_tailcall.c -o bpf_tailcall.o
# rm -rf /sys/fs/bpf/xdp/globals
# /root/iproute2/ip/ip link add type veth
# /root/iproute2/ip/ip link set veth0 up
# /root/iproute2/ip/ip link set veth1 up


== Load objs
# /root/iproute2/ip/ip link set veth0 xdp obj bpf_graft.o sec aaa
# /root/iproute2/ip/ip link show veth0
5: veth0@veth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 xdp qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether 6a:e6:fa:2b:4e:1f brd ff:ff:ff:ff:ff:ff
    prog/xdp id 4 tag 3056d2382e53f27c jited
# ls /sys/fs/bpf/xdp/globals
jmp_tc
# bpftool map show
1: prog_array  name jmp_tc  flags 0x0
        key 4B  value 4B  max_entries 1  memlock 4096B
# bpftool prog show
4: xdp  name cls_aaa  tag 3056d2382e53f27c  gpl
        loaded_at 2020-10-22T08:04:21-0400  uid 0
        xlated 80B  jited 71B  memlock 4096B
        btf_id 5
# /root/iproute2/ip/ip link set veth0 xdp off
# /root/iproute2/ip/ip link set veth0 xdp obj bpf_map_in_map.o sec ingress
# /root/iproute2/ip/ip link show veth0
5: veth0@veth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 xdp qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether 6a:e6:fa:2b:4e:1f brd ff:ff:ff:ff:ff:ff
    prog/xdp id 8 tag 4420e72b2a601ed7 jited
# ls /sys/fs/bpf/xdp/globals
jmp_tc  map_inner  map_outer
# bpftool map show
1: prog_array  name jmp_tc  flags 0x0
        key 4B  value 4B  max_entries 1  memlock 4096B
2: array  name map_inner  flags 0x0
        key 4B  value 4B  max_entries 1  memlock 4096B
3: array_of_maps  name map_outer  flags 0x0
        key 4B  value 4B  max_entries 1  memlock 4096B
# bpftool prog show
8: xdp  name imain  tag 4420e72b2a601ed7  gpl
        loaded_at 2020-10-22T08:04:23-0400  uid 0
        xlated 336B  jited 193B  memlock 4096B  map_ids 3
        btf_id 10
# /root/iproute2/ip/ip link set veth0 xdp off
# /root/iproute2/ip/ip link set veth0 xdp obj bpf_shared.o sec ingress
# /root/iproute2/ip/ip link show veth0
5: veth0@veth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 xdp qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether 6a:e6:fa:2b:4e:1f brd ff:ff:ff:ff:ff:ff
    prog/xdp id 12 tag 9cbab549c3af3eab jited
# ls /sys/fs/bpf/xdp/7a1422e90cd81478f97bc33fbd7782bcb3b868ef /sys/fs/bpf/xdp/globals
/sys/fs/bpf/xdp/7a1422e90cd81478f97bc33fbd7782bcb3b868ef:
map_sh

/sys/fs/bpf/xdp/globals:
jmp_tc  map_inner  map_outer
# bpftool map show
1: prog_array  name jmp_tc  flags 0x0
        key 4B  value 4B  max_entries 1  memlock 4096B
2: array  name map_inner  flags 0x0
        key 4B  value 4B  max_entries 1  memlock 4096B
3: array_of_maps  name map_outer  flags 0x0
        key 4B  value 4B  max_entries 1  memlock 4096B
4: array  name map_sh  flags 0x0
        key 4B  value 4B  max_entries 1  memlock 4096B
# bpftool prog show
12: xdp  name imain  tag 9cbab549c3af3eab  gpl
        loaded_at 2020-10-22T08:04:25-0400  uid 0
        xlated 224B  jited 139B  memlock 4096B  map_ids 4
        btf_id 15
# /root/iproute2/ip/ip link set veth0 xdp off


== Load objs again to make sure maps could be reused
# /root/iproute2/ip/ip link set veth0 xdp obj bpf_graft.o sec aaa
# /root/iproute2/ip/ip link show veth0
5: veth0@veth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 xdp qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether 6a:e6:fa:2b:4e:1f brd ff:ff:ff:ff:ff:ff
    prog/xdp id 16 tag 3056d2382e53f27c jited
# ls /sys/fs/bpf/xdp/7a1422e90cd81478f97bc33fbd7782bcb3b868ef /sys/fs/bpf/xdp/globals
/sys/fs/bpf/xdp/7a1422e90cd81478f97bc33fbd7782bcb3b868ef:
map_sh

/sys/fs/bpf/xdp/globals:
jmp_tc  map_inner  map_outer
# bpftool map show
1: prog_array  name jmp_tc  flags 0x0
        key 4B  value 4B  max_entries 1  memlock 4096B
2: array  name map_inner  flags 0x0
        key 4B  value 4B  max_entries 1  memlock 4096B
3: array_of_maps  name map_outer  flags 0x0
        key 4B  value 4B  max_entries 1  memlock 4096B
4: array  name map_sh  flags 0x0
        key 4B  value 4B  max_entries 1  memlock 4096B
# bpftool prog show
16: xdp  name cls_aaa  tag 3056d2382e53f27c  gpl
        loaded_at 2020-10-22T08:04:27-0400  uid 0
        xlated 80B  jited 71B  memlock 4096B
        btf_id 20
# /root/iproute2/ip/ip link set veth0 xdp off
# /root/iproute2/ip/ip link set veth0 xdp obj bpf_map_in_map.o sec ingress
# /root/iproute2/ip/ip link show veth0
5: veth0@veth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 xdp qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether 6a:e6:fa:2b:4e:1f brd ff:ff:ff:ff:ff:ff
    prog/xdp id 20 tag 4420e72b2a601ed7 jited
# ls /sys/fs/bpf/xdp/7a1422e90cd81478f97bc33fbd7782bcb3b868ef /sys/fs/bpf/xdp/globals
/sys/fs/bpf/xdp/7a1422e90cd81478f97bc33fbd7782bcb3b868ef:
map_sh

/sys/fs/bpf/xdp/globals:
jmp_tc  map_inner  map_outer
# bpftool map show                                                                                                                                                                   [236/4518]
1: prog_array  name jmp_tc  flags 0x0
        key 4B  value 4B  max_entries 1  memlock 4096B
2: array  name map_inner  flags 0x0
        key 4B  value 4B  max_entries 1  memlock 4096B
3: array_of_maps  name map_outer  flags 0x0
        key 4B  value 4B  max_entries 1  memlock 4096B
4: array  name map_sh  flags 0x0
        key 4B  value 4B  max_entries 1  memlock 4096B
# bpftool prog show
20: xdp  name imain  tag 4420e72b2a601ed7  gpl
        loaded_at 2020-10-22T08:04:29-0400  uid 0
        xlated 336B  jited 193B  memlock 4096B  map_ids 3
        btf_id 25
# /root/iproute2/ip/ip link set veth0 xdp off
# /root/iproute2/ip/ip link set veth0 xdp obj bpf_shared.o sec ingress
# /root/iproute2/ip/ip link show veth0
5: veth0@veth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 xdp qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether 6a:e6:fa:2b:4e:1f brd ff:ff:ff:ff:ff:ff
    prog/xdp id 24 tag 9cbab549c3af3eab jited
# ls /sys/fs/bpf/xdp/7a1422e90cd81478f97bc33fbd7782bcb3b868ef /sys/fs/bpf/xdp/globals
/sys/fs/bpf/xdp/7a1422e90cd81478f97bc33fbd7782bcb3b868ef:
map_sh

/sys/fs/bpf/xdp/globals:
jmp_tc  map_inner  map_outer
# bpftool map show
1: prog_array  name jmp_tc  flags 0x0
        key 4B  value 4B  max_entries 1  memlock 4096B
2: array  name map_inner  flags 0x0
        key 4B  value 4B  max_entries 1  memlock 4096B
3: array_of_maps  name map_outer  flags 0x0
        key 4B  value 4B  max_entries 1  memlock 4096B
4: array  name map_sh  flags 0x0
        key 4B  value 4B  max_entries 1  memlock 4096B
# bpftool prog show
24: xdp  name imain  tag 9cbab549c3af3eab  gpl
        loaded_at 2020-10-22T08:04:31-0400  uid 0
        xlated 224B  jited 139B  memlock 4096B  map_ids 4
        btf_id 30
# /root/iproute2/ip/ip link set veth0 xdp off
# rm -rf /sys/fs/bpf/xdp/7a1422e90cd81478f97bc33fbd7782bcb3b868ef /sys/fs/bpf/xdp/globals

== Testing if we can load new-style objects (using xdp-filter as an example)
# /root/iproute2/ip/ip link set veth0 xdp obj /usr/lib64/bpf/xdpfilt_alw_all.o sec xdp_filter
# /root/iproute2/ip/ip link show veth0
5: veth0@veth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 xdp qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether 6a:e6:fa:2b:4e:1f brd ff:ff:ff:ff:ff:ff
    prog/xdp id 28 tag e29eeda1489a6520 jited
# ls /sys/fs/bpf/xdp/globals
filter_ethernet  filter_ipv4  filter_ipv6  filter_ports  xdp_stats_map
# bpftool map show
5: percpu_array  name xdp_stats_map  flags 0x0
        key 4B  value 16B  max_entries 5  memlock 4096B
        btf_id 35
6: percpu_array  name filter_ports  flags 0x0
        key 4B  value 8B  max_entries 65536  memlock 1576960B
        btf_id 35
7: percpu_hash  name filter_ipv4  flags 0x0
        key 4B  value 8B  max_entries 10000  memlock 1064960B
        btf_id 35
8: percpu_hash  name filter_ipv6  flags 0x0
        key 16B  value 8B  max_entries 10000  memlock 1142784B
        btf_id 35
9: percpu_hash  name filter_ethernet  flags 0x0
        key 6B  value 8B  max_entries 10000  memlock 1064960B
        btf_id 35
# bpftool prog show
28: xdp  name xdpfilt_alw_all  tag e29eeda1489a6520  gpl
        loaded_at 2020-10-22T08:04:33-0400  uid 0
        xlated 2408B  jited 1405B  memlock 4096B  map_ids 9,5,7,8,6
        btf_id 35
# /root/iproute2/ip/ip link set veth0 xdp off
# /root/iproute2/ip/ip link set veth0 xdp obj /usr/lib64/bpf/xdpfilt_alw_ip.o sec xdp_filter
# /root/iproute2/ip/ip link show veth0
5: veth0@veth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 xdp qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether 6a:e6:fa:2b:4e:1f brd ff:ff:ff:ff:ff:ff
    prog/xdp id 32 tag 2f2b9dbfb786a5a2 jited
# ls /sys/fs/bpf/xdp/globals
filter_ethernet  filter_ipv4  filter_ipv6  filter_ports  xdp_stats_map
# bpftool map show
5: percpu_array  name xdp_stats_map  flags 0x0
        key 4B  value 16B  max_entries 5  memlock 4096B
        btf_id 35
6: percpu_array  name filter_ports  flags 0x0
        key 4B  value 8B  max_entries 65536  memlock 1576960B
        btf_id 35
7: percpu_hash  name filter_ipv4  flags 0x0
        key 4B  value 8B  max_entries 10000  memlock 1064960B
        btf_id 35
8: percpu_hash  name filter_ipv6  flags 0x0
        key 16B  value 8B  max_entries 10000  memlock 1142784B
        btf_id 35
9: percpu_hash  name filter_ethernet  flags 0x0
        key 6B  value 8B  max_entries 10000  memlock 1064960B
        btf_id 35
# bpftool prog show
32: xdp  name xdpfilt_alw_ip  tag 2f2b9dbfb786a5a2  gpl
        loaded_at 2020-10-22T08:04:35-0400  uid 0
        xlated 1336B  jited 778B  memlock 4096B  map_ids 7,8,5
        btf_id 40
# /root/iproute2/ip/ip link set veth0 xdp off
# /root/iproute2/ip/ip link set veth0 xdp obj /usr/lib64/bpf/xdpfilt_alw_tcp.o sec xdp_filter
# /root/iproute2/ip/ip link show veth0
5: veth0@veth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 xdp qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether 6a:e6:fa:2b:4e:1f brd ff:ff:ff:ff:ff:ff
    prog/xdp id 36 tag 18c1bb25084030bc jited
# ls /sys/fs/bpf/xdp/globals
filter_ethernet  filter_ipv4  filter_ipv6  filter_ports  xdp_stats_map
# bpftool map show
5: percpu_array  name xdp_stats_map  flags 0x0
        key 4B  value 16B  max_entries 5  memlock 4096B
        btf_id 35
6: percpu_array  name filter_ports  flags 0x0
        key 4B  value 8B  max_entries 65536  memlock 1576960B
        btf_id 35
7: percpu_hash  name filter_ipv4  flags 0x0
        key 4B  value 8B  max_entries 10000  memlock 1064960B
        btf_id 35
8: percpu_hash  name filter_ipv6  flags 0x0
        key 16B  value 8B  max_entries 10000  memlock 1142784B
        btf_id 35
9: percpu_hash  name filter_ethernet  flags 0x0
        key 6B  value 8B  max_entries 10000  memlock 1064960B
        btf_id 35
# bpftool prog show
36: xdp  name xdpfilt_alw_tcp  tag 18c1bb25084030bc  gpl
        loaded_at 2020-10-22T08:04:37-0400  uid 0
        xlated 1128B  jited 690B  memlock 4096B  map_ids 6,5
        btf_id 45
# /root/iproute2/ip/ip link set veth0 xdp off
# rm -rf /sys/fs/bpf/xdp/globals


== Load new btf defined maps
# /root/iproute2/ip/ip link set veth0 xdp obj btf_graft.o sec aaa
# /root/iproute2/ip/ip link show veth0
5: veth0@veth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 xdp qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether 6a:e6:fa:2b:4e:1f brd ff:ff:ff:ff:ff:ff
    prog/xdp id 40 tag 3056d2382e53f27c jited
# ls /sys/fs/bpf/xdp/globals
jmp_tc
# bpftool map show
10: prog_array  name jmp_tc  flags 0x0
        key 4B  value 4B  max_entries 1  memlock 4096B
# bpftool prog show
40: xdp  name cls_aaa  tag 3056d2382e53f27c  gpl
        loaded_at 2020-10-22T08:04:39-0400  uid 0
        xlated 80B  jited 71B  memlock 4096B
        btf_id 50
# /root/iproute2/ip/ip link set veth0 xdp off
# /root/iproute2/ip/ip link set veth0 xdp obj btf_map_in_map.o sec ingress
# /root/iproute2/ip/ip link show veth0
5: veth0@veth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 xdp qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether 6a:e6:fa:2b:4e:1f brd ff:ff:ff:ff:ff:ff
    prog/xdp id 44 tag 4420e72b2a601ed7 jited
# ls /sys/fs/bpf/xdp/globals
jmp_tc  map_outer
# bpftool map show
10: prog_array  name jmp_tc  flags 0x0
        key 4B  value 4B  max_entries 1  memlock 4096B
11: array  name map_inner  flags 0x0
        key 4B  value 4B  max_entries 1  memlock 4096B
13: array_of_maps  name map_outer  flags 0x0
        key 4B  value 4B  max_entries 1  memlock 4096B
# bpftool prog show
44: xdp  name imain  tag 4420e72b2a601ed7  gpl
        loaded_at 2020-10-22T08:04:41-0400  uid 0
        xlated 336B  jited 193B  memlock 4096B  map_ids 13
        btf_id 55
# /root/iproute2/ip/ip link set veth0 xdp off
# /root/iproute2/ip/ip link set veth0 xdp obj btf_shared.o sec ingress
# /root/iproute2/ip/ip link show veth0
5: veth0@veth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 xdp qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether 6a:e6:fa:2b:4e:1f brd ff:ff:ff:ff:ff:ff
    prog/xdp id 48 tag 9cbab549c3af3eab jited
# ls /sys/fs/bpf/xdp/globals
jmp_tc  map_outer  map_sh
# bpftool map show
10: prog_array  name jmp_tc  flags 0x0
        key 4B  value 4B  max_entries 1  memlock 4096B
11: array  name map_inner  flags 0x0
        key 4B  value 4B  max_entries 1  memlock 4096B
13: array_of_maps  name map_outer  flags 0x0
        key 4B  value 4B  max_entries 1  memlock 4096B
14: array  name map_sh  flags 0x0
        key 4B  value 4B  max_entries 1  memlock 4096B
# bpftool prog show
48: xdp  name imain  tag 9cbab549c3af3eab  gpl
        loaded_at 2020-10-22T08:04:43-0400  uid 0
        xlated 224B  jited 139B  memlock 4096B  map_ids 14
        btf_id 60
# /root/iproute2/ip/ip link set veth0 xdp off
# rm -rf /sys/fs/bpf/xdp/globals


== Test load objs by tc
# /root/iproute2/tc/tc qdisc add dev veth0 ingress
# /root/iproute2/tc/tc filter add dev veth0 ingress bpf da obj bpf_cyclic.o sec 0xabccba/0
# /root/iproute2/tc/tc filter add dev veth0 parent ffff: bpf obj bpf_graft.o
# /root/iproute2/tc/tc filter add dev veth0 ingress bpf da obj bpf_tailcall.o sec 42/0
# /root/iproute2/tc/tc filter add dev veth0 ingress bpf da obj bpf_tailcall.o sec 42/1
# /root/iproute2/tc/tc filter add dev veth0 ingress bpf da obj bpf_tailcall.o sec 43/0
# /root/iproute2/tc/tc filter add dev veth0 ingress bpf da obj bpf_tailcall.o sec classifier
# /root/iproute2/ip/ip link show veth0
5: veth0@veth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether 6a:e6:fa:2b:4e:1f brd ff:ff:ff:ff:ff:ff
# ls /sys/fs/bpf/xdp/37e88cb3b9646b2ea5f99ab31069ad88db06e73d /sys/fs/bpf/xdp/fc68fe3e96378a0cba284ea6acbe17e898d8b11f /sys/fs/bpf/xdp/globals
/sys/fs/bpf/xdp/37e88cb3b9646b2ea5f99ab31069ad88db06e73d:
jmp_tc

/sys/fs/bpf/xdp/fc68fe3e96378a0cba284ea6acbe17e898d8b11f:
jmp_ex  jmp_tc  map_sh

/sys/fs/bpf/xdp/globals:
jmp_tc
# bpftool map show
15: prog_array  name jmp_tc  flags 0x0
        key 4B  value 4B  max_entries 1  memlock 4096B
        owner_prog_type sched_cls  owner jited
16: prog_array  name jmp_tc  flags 0x0
        key 4B  value 4B  max_entries 1  memlock 4096B
        owner_prog_type sched_cls  owner jited
17: prog_array  name jmp_ex  flags 0x0
        key 4B  value 4B  max_entries 1  memlock 4096B
        owner_prog_type sched_cls  owner jited
18: prog_array  name jmp_tc  flags 0x0
        key 4B  value 4B  max_entries 2  memlock 4096B
        owner_prog_type sched_cls  owner jited
19: array  name map_sh  flags 0x0
        key 4B  value 4B  max_entries 1  memlock 4096B
# bpftool prog show
52: sched_cls  name cls_loop  tag 3e98a40b04099d36  gpl
        loaded_at 2020-10-22T08:04:45-0400  uid 0
        xlated 168B  jited 133B  memlock 4096B  map_ids 15
        btf_id 65
56: sched_cls  name cls_entry  tag 0fbb4d9310a6ee26  gpl
        loaded_at 2020-10-22T08:04:45-0400  uid 0
        xlated 144B  jited 121B  memlock 4096B  map_ids 16
        btf_id 70
60: sched_cls  name cls_case1  tag e06a3bd62293d65d  gpl
        loaded_at 2020-10-22T08:04:45-0400  uid 0
        xlated 328B  jited 216B  memlock 4096B  map_ids 19,17
        btf_id 75
66: sched_cls  name cls_case1  tag e06a3bd62293d65d  gpl
        loaded_at 2020-10-22T08:04:45-0400  uid 0
        xlated 328B  jited 216B  memlock 4096B  map_ids 19,17
        btf_id 80
72: sched_cls  name cls_case1  tag e06a3bd62293d65d  gpl
        loaded_at 2020-10-22T08:04:45-0400  uid 0
        xlated 328B  jited 216B  memlock 4096B  map_ids 19,17
        btf_id 85
78: sched_cls  name cls_case1  tag e06a3bd62293d65d  gpl
        loaded_at 2020-10-22T08:04:45-0400  uid 0
        xlated 328B  jited 216B  memlock 4096B  map_ids 19,17
        btf_id 90
79: sched_cls  name cls_case2  tag ee218ff893dca823  gpl
        loaded_at 2020-10-22T08:04:45-0400  uid 0
        xlated 336B  jited 218B  memlock 4096B  map_ids 19,18
        btf_id 90
80: sched_cls  name cls_exit  tag e78a58140deed387  gpl
        loaded_at 2020-10-22T08:04:45-0400  uid 0
        xlated 288B  jited 177B  memlock 4096B  map_ids 19
        btf_id 90

I also run the following upstream kselftest with patches iproute2 and
all passed.

test_lwt_ip_encap.sh
test_xdp_redirect.sh
test_tc_redirect.sh
test_xdp_meta.sh
test_xdp_veth.sh
test_xdp_vlan.sh

Hangbin Liu (5):
  configure: add check_libbpf() for later libbpf support
  lib: rename bpf.c to bpf_legacy.c
  lib: add libbpf support
  examples/bpf: move struct bpf_elf_map defined maps to legacy folder
  examples/bpf: add bpf examples with BTF defined maps

 configure                                |  48 ++++
 examples/bpf/README                      |  18 +-
 examples/bpf/bpf_graft.c                 |  14 +-
 examples/bpf/bpf_map_in_map.c            |  37 ++-
 examples/bpf/bpf_shared.c                |  14 +-
 examples/bpf/{ => legacy}/bpf_cyclic.c   |   2 +-
 examples/bpf/legacy/bpf_graft.c          |  66 +++++
 examples/bpf/legacy/bpf_map_in_map.c     |  56 ++++
 examples/bpf/legacy/bpf_shared.c         |  53 ++++
 examples/bpf/{ => legacy}/bpf_tailcall.c |   2 +-
 include/bpf_api.h                        |  13 +
 include/bpf_util.h                       |  17 +-
 ip/ipvrf.c                               |  19 +-
 lib/Makefile                             |   6 +-
 lib/{bpf.c => bpf_legacy.c}              | 184 ++++++++++++-
 lib/bpf_libbpf.c                         | 332 +++++++++++++++++++++++
 16 files changed, 833 insertions(+), 48 deletions(-)
 rename examples/bpf/{ => legacy}/bpf_cyclic.c (95%)
 create mode 100644 examples/bpf/legacy/bpf_graft.c
 create mode 100644 examples/bpf/legacy/bpf_map_in_map.c
 create mode 100644 examples/bpf/legacy/bpf_shared.c
 rename examples/bpf/{ => legacy}/bpf_tailcall.c (98%)
 rename lib/{bpf.c => bpf_legacy.c} (94%)
 create mode 100644 lib/bpf_libbpf.c

Comments

David Ahern Oct. 28, 2020, 11:02 p.m. UTC | #1
On 10/28/20 7:25 AM, Hangbin Liu wrote:
> This series converts iproute2 to use libbpf for loading and attaching
> BPF programs when it is available. This means that iproute2 will
> correctly process BTF information and support the new-style BTF-defined
> maps, while keeping compatibility with the old internal map definition
> syntax.
> 
> This is achieved by checking for libbpf at './configure' time, and using
> it if available. By default the system libbpf will be used, but static
> linking against a custom libbpf version can be achieved by passing
> LIBBPF_DIR to configure. FORCE_LIBBPF can be set to force configure to
> abort if no suitable libbpf is found (useful for automatic packaging
> that wants to enforce the dependency).
> 
> The old iproute2 bpf code is kept and will be used if no suitable libbpf
> is available. When using libbpf, wrapper code ensures that iproute2 will
> still understand the old map definition format, including populating
> map-in-map and tail call maps before load.
> 
> The examples in bpf/examples are kept, and a separate set of examples
> are added with BTF-based map definitions for those examples where this
> is possible (libbpf doesn't currently support declaratively populating
> tail call maps).
> 
> At last, Thanks a lot for Toke's help on this patch set.
> 
> 
> v2:
> a) Remove self defined IS_ERR_OR_NULL and use libbpf_get_error() instead.
> b) Add ipvrf with libbpf support.
> 
> 

fails to compile on Ubuntu 20.10:

root@u2010-sfo3:~/iproute2.git# ./configure
TC schedulers
 ATM	yes
 IPT	using xtables
 IPSET  yes

iptables modules directory: /usr/lib/x86_64-linux-gnu/xtables
libc has setns: yes
SELinux support: yes
libbpf support: yes
ELF support: yes
libmnl support: yes
Berkeley DB: no
need for strlcpy: yes
libcap support: yes

root@u2010-sfo3:~/iproute2.git# make clean

root@u2010-sfo3:~/iproute2.git# make -j 4
...
/usr/bin/ld: ../lib/libutil.a(bpf_libbpf.o): in function `load_bpf_object':
bpf_libbpf.c:(.text+0x3cb): undefined reference to
`bpf_program__section_name'
/usr/bin/ld: bpf_libbpf.c:(.text+0x438): undefined reference to
`bpf_program__section_name'
/usr/bin/ld: bpf_libbpf.c:(.text+0x716): undefined reference to
`bpf_program__section_name'
collect2: error: ld returned 1 exit status
make[1]: *** [Makefile:27: ip] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:64: all] Error 2
Hangbin Liu Oct. 29, 2020, 2:06 a.m. UTC | #2
On Wed, Oct 28, 2020 at 05:02:34PM -0600, David Ahern wrote:
> fails to compile on Ubuntu 20.10:
> 
> root@u2010-sfo3:~/iproute2.git# ./configure
> TC schedulers
>  ATM	yes
>  IPT	using xtables
>  IPSET  yes
> 
> iptables modules directory: /usr/lib/x86_64-linux-gnu/xtables
> libc has setns: yes
> SELinux support: yes
> libbpf support: yes
> ELF support: yes
> libmnl support: yes
> Berkeley DB: no
> need for strlcpy: yes
> libcap support: yes
> 
> root@u2010-sfo3:~/iproute2.git# make clean
> 
> root@u2010-sfo3:~/iproute2.git# make -j 4
> ...
> /usr/bin/ld: ../lib/libutil.a(bpf_libbpf.o): in function `load_bpf_object':
> bpf_libbpf.c:(.text+0x3cb): undefined reference to
> `bpf_program__section_name'
> /usr/bin/ld: bpf_libbpf.c:(.text+0x438): undefined reference to
> `bpf_program__section_name'
> /usr/bin/ld: bpf_libbpf.c:(.text+0x716): undefined reference to
> `bpf_program__section_name'
> collect2: error: ld returned 1 exit status
> make[1]: *** [Makefile:27: ip] Error 1
> make[1]: *** Waiting for unfinished jobs....
> make: *** [Makefile:64: all] Error 2

You need to update libbpf to latest version.

But this also remind me that I need to add bpf_program__section_name() to
configure checking. I will see if I missed other functions' checking.

Thanks
Hangbin
David Ahern Oct. 29, 2020, 2:20 a.m. UTC | #3
On 10/28/20 8:06 PM, Hangbin Liu wrote:
> On Wed, Oct 28, 2020 at 05:02:34PM -0600, David Ahern wrote:
>> fails to compile on Ubuntu 20.10:
>>
>> root@u2010-sfo3:~/iproute2.git# ./configure
>> TC schedulers
>>  ATM	yes
>>  IPT	using xtables
>>  IPSET  yes
>>
>> iptables modules directory: /usr/lib/x86_64-linux-gnu/xtables
>> libc has setns: yes
>> SELinux support: yes
>> libbpf support: yes
>> ELF support: yes
>> libmnl support: yes
>> Berkeley DB: no
>> need for strlcpy: yes
>> libcap support: yes
>>
>> root@u2010-sfo3:~/iproute2.git# make clean
>>
>> root@u2010-sfo3:~/iproute2.git# make -j 4
>> ...
>> /usr/bin/ld: ../lib/libutil.a(bpf_libbpf.o): in function `load_bpf_object':
>> bpf_libbpf.c:(.text+0x3cb): undefined reference to
>> `bpf_program__section_name'
>> /usr/bin/ld: bpf_libbpf.c:(.text+0x438): undefined reference to
>> `bpf_program__section_name'
>> /usr/bin/ld: bpf_libbpf.c:(.text+0x716): undefined reference to
>> `bpf_program__section_name'
>> collect2: error: ld returned 1 exit status
>> make[1]: *** [Makefile:27: ip] Error 1
>> make[1]: *** Waiting for unfinished jobs....
>> make: *** [Makefile:64: all] Error 2
> 
> You need to update libbpf to latest version.

nope. you need to be able to handle this. Ubuntu 20.10 was just
released, and it has a version of libbpf. If you are going to integrate
libbpf into other packages like iproute2, it needs to just work with
that version.

> 
> But this also remind me that I need to add bpf_program__section_name() to
> configure checking. I will see if I missed other functions' checking.

This is going to be an on-going problem. iproute2 should work with
whatever version of libbpf is installed on that system.
Andrii Nakryiko Oct. 29, 2020, 2:27 a.m. UTC | #4
On Wed, Oct 28, 2020 at 7:06 PM Hangbin Liu <haliu@redhat.com> wrote:
>
> On Wed, Oct 28, 2020 at 05:02:34PM -0600, David Ahern wrote:
> > fails to compile on Ubuntu 20.10:
> >
> > root@u2010-sfo3:~/iproute2.git# ./configure
> > TC schedulers
> >  ATM  yes
> >  IPT  using xtables
> >  IPSET  yes
> >
> > iptables modules directory: /usr/lib/x86_64-linux-gnu/xtables
> > libc has setns: yes
> > SELinux support: yes
> > libbpf support: yes
> > ELF support: yes
> > libmnl support: yes
> > Berkeley DB: no
> > need for strlcpy: yes
> > libcap support: yes
> >
> > root@u2010-sfo3:~/iproute2.git# make clean
> >
> > root@u2010-sfo3:~/iproute2.git# make -j 4
> > ...
> > /usr/bin/ld: ../lib/libutil.a(bpf_libbpf.o): in function `load_bpf_object':
> > bpf_libbpf.c:(.text+0x3cb): undefined reference to
> > `bpf_program__section_name'
> > /usr/bin/ld: bpf_libbpf.c:(.text+0x438): undefined reference to
> > `bpf_program__section_name'
> > /usr/bin/ld: bpf_libbpf.c:(.text+0x716): undefined reference to
> > `bpf_program__section_name'
> > collect2: error: ld returned 1 exit status
> > make[1]: *** [Makefile:27: ip] Error 1
> > make[1]: *** Waiting for unfinished jobs....
> > make: *** [Makefile:64: all] Error 2
>
> You need to update libbpf to latest version.

Why not using libbpf from submodule?

>
> But this also remind me that I need to add bpf_program__section_name() to
> configure checking. I will see if I missed other functions' checking.
>
> Thanks
> Hangbin
>
Stephen Hemminger Oct. 29, 2020, 2:33 a.m. UTC | #5
On Thu, 29 Oct 2020 10:06:37 +0800
Hangbin Liu <haliu@redhat.com> wrote:

> On Wed, Oct 28, 2020 at 05:02:34PM -0600, David Ahern wrote:
> > fails to compile on Ubuntu 20.10:
> > 
> > root@u2010-sfo3:~/iproute2.git# ./configure
> > TC schedulers
> >  ATM	yes
> >  IPT	using xtables
> >  IPSET  yes
> > 
> > iptables modules directory: /usr/lib/x86_64-linux-gnu/xtables
> > libc has setns: yes
> > SELinux support: yes
> > libbpf support: yes
> > ELF support: yes
> > libmnl support: yes
> > Berkeley DB: no
> > need for strlcpy: yes
> > libcap support: yes
> > 
> > root@u2010-sfo3:~/iproute2.git# make clean
> > 
> > root@u2010-sfo3:~/iproute2.git# make -j 4
> > ...
> > /usr/bin/ld: ../lib/libutil.a(bpf_libbpf.o): in function `load_bpf_object':
> > bpf_libbpf.c:(.text+0x3cb): undefined reference to
> > `bpf_program__section_name'
> > /usr/bin/ld: bpf_libbpf.c:(.text+0x438): undefined reference to
> > `bpf_program__section_name'
> > /usr/bin/ld: bpf_libbpf.c:(.text+0x716): undefined reference to
> > `bpf_program__section_name'
> > collect2: error: ld returned 1 exit status
> > make[1]: *** [Makefile:27: ip] Error 1
> > make[1]: *** Waiting for unfinished jobs....
> > make: *** [Makefile:64: all] Error 2  
> 
> You need to update libbpf to latest version.
> 
> But this also remind me that I need to add bpf_program__section_name() to
> configure checking. I will see if I missed other functions' checking.
> 
> Thanks
> Hangbin
> 

Then configure needs to check for this or every distro is going to get real mad...
David Ahern Oct. 29, 2020, 2:33 a.m. UTC | #6
On 10/28/20 8:27 PM, Andrii Nakryiko wrote:
> On Wed, Oct 28, 2020 at 7:06 PM Hangbin Liu <haliu@redhat.com> wrote:
>>
>> On Wed, Oct 28, 2020 at 05:02:34PM -0600, David Ahern wrote:
>>> fails to compile on Ubuntu 20.10:
>>>
>>> root@u2010-sfo3:~/iproute2.git# ./configure
>>> TC schedulers
>>>  ATM  yes
>>>  IPT  using xtables
>>>  IPSET  yes
>>>
>>> iptables modules directory: /usr/lib/x86_64-linux-gnu/xtables
>>> libc has setns: yes
>>> SELinux support: yes
>>> libbpf support: yes
>>> ELF support: yes
>>> libmnl support: yes
>>> Berkeley DB: no
>>> need for strlcpy: yes
>>> libcap support: yes
>>>
>>> root@u2010-sfo3:~/iproute2.git# make clean
>>>
>>> root@u2010-sfo3:~/iproute2.git# make -j 4
>>> ...
>>> /usr/bin/ld: ../lib/libutil.a(bpf_libbpf.o): in function `load_bpf_object':
>>> bpf_libbpf.c:(.text+0x3cb): undefined reference to
>>> `bpf_program__section_name'
>>> /usr/bin/ld: bpf_libbpf.c:(.text+0x438): undefined reference to
>>> `bpf_program__section_name'
>>> /usr/bin/ld: bpf_libbpf.c:(.text+0x716): undefined reference to
>>> `bpf_program__section_name'
>>> collect2: error: ld returned 1 exit status
>>> make[1]: *** [Makefile:27: ip] Error 1
>>> make[1]: *** Waiting for unfinished jobs....
>>> make: *** [Makefile:64: all] Error 2
>>
>> You need to update libbpf to latest version.
> 
> Why not using libbpf from submodule?
> 

no. iproute2 does not bring in libmnl, libc, ... a submodules. libbpf is
not special. OS versions provide it and it needs to co-exist with packages.
Stephen Hemminger Oct. 29, 2020, 2:34 a.m. UTC | #7
On Wed, 28 Oct 2020 19:27:20 -0700
Andrii Nakryiko <andrii.nakryiko@gmail.com> wrote:

> On Wed, Oct 28, 2020 at 7:06 PM Hangbin Liu <haliu@redhat.com> wrote:
> >
> > On Wed, Oct 28, 2020 at 05:02:34PM -0600, David Ahern wrote:  
> > > fails to compile on Ubuntu 20.10:
> > >
> > > root@u2010-sfo3:~/iproute2.git# ./configure
> > > TC schedulers
> > >  ATM  yes
> > >  IPT  using xtables
> > >  IPSET  yes
> > >
> > > iptables modules directory: /usr/lib/x86_64-linux-gnu/xtables
> > > libc has setns: yes
> > > SELinux support: yes
> > > libbpf support: yes
> > > ELF support: yes
> > > libmnl support: yes
> > > Berkeley DB: no
> > > need for strlcpy: yes
> > > libcap support: yes
> > >
> > > root@u2010-sfo3:~/iproute2.git# make clean
> > >
> > > root@u2010-sfo3:~/iproute2.git# make -j 4
> > > ...
> > > /usr/bin/ld: ../lib/libutil.a(bpf_libbpf.o): in function `load_bpf_object':
> > > bpf_libbpf.c:(.text+0x3cb): undefined reference to
> > > `bpf_program__section_name'
> > > /usr/bin/ld: bpf_libbpf.c:(.text+0x438): undefined reference to
> > > `bpf_program__section_name'
> > > /usr/bin/ld: bpf_libbpf.c:(.text+0x716): undefined reference to
> > > `bpf_program__section_name'
> > > collect2: error: ld returned 1 exit status
> > > make[1]: *** [Makefile:27: ip] Error 1
> > > make[1]: *** Waiting for unfinished jobs....
> > > make: *** [Makefile:64: all] Error 2  
> >
> > You need to update libbpf to latest version.  
> 
> Why not using libbpf from submodule?

Because it makes it harder for people downloading tarballs and distributions.
Iproute2 has worked well by being standalone.

Want to merge libbpf into iproute2??
Hangbin Liu Oct. 29, 2020, 2:45 a.m. UTC | #8
On Wed, Oct 28, 2020 at 08:20:55PM -0600, David Ahern wrote:
> >> root@u2010-sfo3:~/iproute2.git# make -j 4
> >> ...
> >> /usr/bin/ld: ../lib/libutil.a(bpf_libbpf.o): in function `load_bpf_object':
> >> bpf_libbpf.c:(.text+0x3cb): undefined reference to
> >> `bpf_program__section_name'
> >> /usr/bin/ld: bpf_libbpf.c:(.text+0x438): undefined reference to
> >> `bpf_program__section_name'
> >> /usr/bin/ld: bpf_libbpf.c:(.text+0x716): undefined reference to
> >> `bpf_program__section_name'
> >> collect2: error: ld returned 1 exit status
> >> make[1]: *** [Makefile:27: ip] Error 1
> >> make[1]: *** Waiting for unfinished jobs....
> >> make: *** [Makefile:64: all] Error 2
> > 
> > You need to update libbpf to latest version.
> 
> nope. you need to be able to handle this. Ubuntu 20.10 was just
> released, and it has a version of libbpf. If you are going to integrate
> libbpf into other packages like iproute2, it needs to just work with
> that version.

OK, I can replace bpf_program__section_name by bpf_program__title().
> 
> > 
> > But this also remind me that I need to add bpf_program__section_name() to
> > configure checking. I will see if I missed other functions' checking.
> 
> This is going to be an on-going problem. iproute2 should work with
> whatever version of libbpf is installed on that system.

I will make it works on Ubuntu 20.10, but with whatever version of libbpf?
That looks hard, especially with old libbpf.

Thanks
Hangbin
Andrii Nakryiko Oct. 29, 2020, 2:46 a.m. UTC | #9
On Wed, Oct 28, 2020 at 7:33 PM David Ahern <dsahern@gmail.com> wrote:
>
> On 10/28/20 8:27 PM, Andrii Nakryiko wrote:
> > On Wed, Oct 28, 2020 at 7:06 PM Hangbin Liu <haliu@redhat.com> wrote:
> >>
> >> On Wed, Oct 28, 2020 at 05:02:34PM -0600, David Ahern wrote:
> >>> fails to compile on Ubuntu 20.10:
> >>>
> >>> root@u2010-sfo3:~/iproute2.git# ./configure
> >>> TC schedulers
> >>>  ATM  yes
> >>>  IPT  using xtables
> >>>  IPSET  yes
> >>>
> >>> iptables modules directory: /usr/lib/x86_64-linux-gnu/xtables
> >>> libc has setns: yes
> >>> SELinux support: yes
> >>> libbpf support: yes
> >>> ELF support: yes
> >>> libmnl support: yes
> >>> Berkeley DB: no
> >>> need for strlcpy: yes
> >>> libcap support: yes
> >>>
> >>> root@u2010-sfo3:~/iproute2.git# make clean
> >>>
> >>> root@u2010-sfo3:~/iproute2.git# make -j 4
> >>> ...
> >>> /usr/bin/ld: ../lib/libutil.a(bpf_libbpf.o): in function `load_bpf_object':
> >>> bpf_libbpf.c:(.text+0x3cb): undefined reference to
> >>> `bpf_program__section_name'
> >>> /usr/bin/ld: bpf_libbpf.c:(.text+0x438): undefined reference to
> >>> `bpf_program__section_name'
> >>> /usr/bin/ld: bpf_libbpf.c:(.text+0x716): undefined reference to
> >>> `bpf_program__section_name'
> >>> collect2: error: ld returned 1 exit status
> >>> make[1]: *** [Makefile:27: ip] Error 1
> >>> make[1]: *** Waiting for unfinished jobs....
> >>> make: *** [Makefile:64: all] Error 2
> >>
> >> You need to update libbpf to latest version.
> >
> > Why not using libbpf from submodule?
> >
>
> no. iproute2 does not bring in libmnl, libc, ... a submodules. libbpf is
> not special. OS versions provide it and it needs to co-exist with packages.

Not saying libbpf is special, but libbpf is a fast moving target right
now, so it's pragmatic to have it as submodule, because if you'd like
to use some latest functionality, you won't have to add all the
conditional compilation shenanigans to detect every single new API
you'd like to use from libbpf. And libbpf is pretty small to not worry
about saving memory through a shared library.

But it's up to you guys, of course.
Andrii Nakryiko Oct. 29, 2020, 2:50 a.m. UTC | #10
On Wed, Oct 28, 2020 at 7:34 PM Stephen Hemminger
<stephen@networkplumber.org> wrote:
>
> On Wed, 28 Oct 2020 19:27:20 -0700
> Andrii Nakryiko <andrii.nakryiko@gmail.com> wrote:
>
> > On Wed, Oct 28, 2020 at 7:06 PM Hangbin Liu <haliu@redhat.com> wrote:
> > >
> > > On Wed, Oct 28, 2020 at 05:02:34PM -0600, David Ahern wrote:
> > > > fails to compile on Ubuntu 20.10:
> > > >
> > > > root@u2010-sfo3:~/iproute2.git# ./configure
> > > > TC schedulers
> > > >  ATM  yes
> > > >  IPT  using xtables
> > > >  IPSET  yes
> > > >
> > > > iptables modules directory: /usr/lib/x86_64-linux-gnu/xtables
> > > > libc has setns: yes
> > > > SELinux support: yes
> > > > libbpf support: yes
> > > > ELF support: yes
> > > > libmnl support: yes
> > > > Berkeley DB: no
> > > > need for strlcpy: yes
> > > > libcap support: yes
> > > >
> > > > root@u2010-sfo3:~/iproute2.git# make clean
> > > >
> > > > root@u2010-sfo3:~/iproute2.git# make -j 4
> > > > ...
> > > > /usr/bin/ld: ../lib/libutil.a(bpf_libbpf.o): in function `load_bpf_object':
> > > > bpf_libbpf.c:(.text+0x3cb): undefined reference to
> > > > `bpf_program__section_name'
> > > > /usr/bin/ld: bpf_libbpf.c:(.text+0x438): undefined reference to
> > > > `bpf_program__section_name'
> > > > /usr/bin/ld: bpf_libbpf.c:(.text+0x716): undefined reference to
> > > > `bpf_program__section_name'
> > > > collect2: error: ld returned 1 exit status
> > > > make[1]: *** [Makefile:27: ip] Error 1
> > > > make[1]: *** Waiting for unfinished jobs....
> > > > make: *** [Makefile:64: all] Error 2
> > >
> > > You need to update libbpf to latest version.
> >
> > Why not using libbpf from submodule?
>
> Because it makes it harder for people downloading tarballs and distributions.

Genuinely curious, making harder how exactly? When packaging sources
as a tarball you'd check out submodules before packaging, right?

> Iproute2 has worked well by being standalone.

Again, maybe I'm missing something, but what makes it not a
standalone, if it is using a submodule? Pahole, for instance, is using
libbpf through submodule and just bypasses all the problems with
detection of features and library availability. I haven't heard anyone
complaining about it made working with pahole harder in any way.

>
> Want to merge libbpf into iproute2??

No... How did you come to this conclusion?..

>
>
David Ahern Oct. 29, 2020, 3 a.m. UTC | #11
On 10/28/20 8:45 PM, Hangbin Liu wrote:
> On Wed, Oct 28, 2020 at 08:20:55PM -0600, David Ahern wrote:
>>>> root@u2010-sfo3:~/iproute2.git# make -j 4
>>>> ...
>>>> /usr/bin/ld: ../lib/libutil.a(bpf_libbpf.o): in function `load_bpf_object':
>>>> bpf_libbpf.c:(.text+0x3cb): undefined reference to
>>>> `bpf_program__section_name'
>>>> /usr/bin/ld: bpf_libbpf.c:(.text+0x438): undefined reference to
>>>> `bpf_program__section_name'
>>>> /usr/bin/ld: bpf_libbpf.c:(.text+0x716): undefined reference to
>>>> `bpf_program__section_name'
>>>> collect2: error: ld returned 1 exit status
>>>> make[1]: *** [Makefile:27: ip] Error 1
>>>> make[1]: *** Waiting for unfinished jobs....
>>>> make: *** [Makefile:64: all] Error 2
>>>
>>> You need to update libbpf to latest version.
>>
>> nope. you need to be able to handle this. Ubuntu 20.10 was just
>> released, and it has a version of libbpf. If you are going to integrate
>> libbpf into other packages like iproute2, it needs to just work with
>> that version.
> 
> OK, I can replace bpf_program__section_name by bpf_program__title().

I believe this one can be handled through a compatability check. Looks
the rename / deprecation is fairly recent (78cdb58bdf15f from Sept 2020).


>>
>>>
>>> But this also remind me that I need to add bpf_program__section_name() to
>>> configure checking. I will see if I missed other functions' checking.
>>
>> This is going to be an on-going problem. iproute2 should work with
>> whatever version of libbpf is installed on that system.
> 
> I will make it works on Ubuntu 20.10, but with whatever version of libbpf?
> That looks hard, especially with old libbpf.
> 

I meant what comes with the OS. I believe I read that Fedora 33 was just
released as well. Does it have a version of libbpf? If so, please verify
it compiles and works with that version too. Before committing I will
also verify it compiles and links against a local version of libbpf (top
of tree) just to get a range of versions.
Hangbin Liu Oct. 29, 2020, 3:17 a.m. UTC | #12
On Wed, Oct 28, 2020 at 09:00:41PM -0600, David Ahern wrote:
> >>> You need to update libbpf to latest version.
> >>
> >> nope. you need to be able to handle this. Ubuntu 20.10 was just
> >> released, and it has a version of libbpf. If you are going to integrate
> >> libbpf into other packages like iproute2, it needs to just work with
> >> that version.
> > 
> > OK, I can replace bpf_program__section_name by bpf_program__title().
> 
> I believe this one can be handled through a compatability check. Looks

Do you mean add a check like

#ifdef has_section_name_support
	use bpf_program__section_name;
#else
	use bpf_program__title;
#endif

> the rename / deprecation is fairly recent (78cdb58bdf15f from Sept 2020).

Yeah... As Andrii said, libbpf is in fast moving..

> >>
> >>>
> >>> But this also remind me that I need to add bpf_program__section_name() to
> >>> configure checking. I will see if I missed other functions' checking.
> >>
> >> This is going to be an on-going problem. iproute2 should work with
> >> whatever version of libbpf is installed on that system.
> > 
> > I will make it works on Ubuntu 20.10, but with whatever version of libbpf?
> > That looks hard, especially with old libbpf.
> > 
> 
> I meant what comes with the OS. I believe I read that Fedora 33 was just
> released as well. Does it have a version of libbpf? If so, please verify
> it compiles and works with that version too. Before committing I will
> also verify it compiles and links against a local version of libbpf (top
> of tree) just to get a range of versions.
> 

Yes, it makes sense. I will also check the libbpf on Fedora 33.

Thanks
Hangbin
Hangbin Liu Oct. 29, 2020, 10:26 a.m. UTC | #13
On Wed, Oct 28, 2020 at 09:00:41PM -0600, David Ahern wrote:
> >> nope. you need to be able to handle this. Ubuntu 20.10 was just
> >> released, and it has a version of libbpf. If you are going to integrate
> >> libbpf into other packages like iproute2, it needs to just work with
> >> that version.
> > 
> > OK, I can replace bpf_program__section_name by bpf_program__title().
> 
> I believe this one can be handled through a compatability check. Looks
> the rename / deprecation is fairly recent (78cdb58bdf15f from Sept 2020).

Hi David,

I just come up with another way. In configure, build a temp program and update
the function checking every time is not graceful. How about just check the
libbpf version, since libbpf has exported all functions in src/libbpf.map.

Currently, only bpf_program__section_name() is added in 0.2.0, all other
needed functions are supported in 0.1.0.

So in configure, the new check would like:

check_force_libbpf()
{
    # if set FORCE_LIBBPF but no libbpf support, just exist the config
    # process to make sure we don't build without libbpf.
    if [ -n "$FORCE_LIBBPF" ]; then
        echo "FORCE_LIBBPF set, but couldn't find a usable libbpf"
        exit 1
    fi
}

check_libbpf()
{
    if ! ${PKG_CONFIG} libbpf --exists && [ -z "$LIBBPF_DIR" ] ; then
        echo "no"
        check_force_libbpf
        return
    fi

    if [ $(uname -m) == x86_64 ]; then
        local LIBSUBDIR=lib64
    else
        local LIBSUBDIR=lib
    fi

    if [ -n "$LIBBPF_DIR" ]; then
        LIBBPF_CFLAGS="-I${LIBBPF_DIR}/include -L${LIBBPF_DIR}/${LIBSUBDIR}"
        LIBBPF_LDLIBS="${LIBBPF_DIR}/${LIBSUBDIR}/libbpf.a -lz -lelf"
    else
        LIBBPF_CFLAGS=$(${PKG_CONFIG} libbpf --cflags)
        LIBBPF_LDLIBS=$(${PKG_CONFIG} libbpf --libs)
    fi

    if ${PKG_CONFIG} libbpf --atleast-version 0.1.0 || \
        PKG_CONFIG_LIBDIR=${LIBBPF_DIR}/${LIBSUBDIR}/pkgconfig \
	${PKG_CONFIG} libbpf --atleast-version 0.1.0; then
        echo "HAVE_LIBBPF:=y" >>$CONFIG
        echo 'CFLAGS += -DHAVE_LIBBPF ' $LIBBPF_CFLAGS >> $CONFIG
        echo 'LDLIBS += ' $LIBBPF_LDLIBS >>$CONFIG
        echo "yes"
    else
        echo "no"
        check_force_libbpf
	return
    fi

    # bpf_program__title() is deprecated since libbpf 0.2.0, use
    # bpf_program__section_name() instead if we support
    if ${PKG_CONFIG} libbpf --atleast-version 0.2.0 || \
        PKG_CONFIG_LIBDIR=${LIBBPF_DIR}/${LIBSUBDIR}/pkgconfig \
	${PKG_CONFIG} libbpf --atleast-version 0.2.0; then
        echo 'CFLAGS += -DHAVE_LIBBPF_SECTION_NAME ' $LIBBPF_CFLAGS >> $CONFIG
    fi
}

And in lib/bpf_libbpf.c, we add a new helper like:

static const char *get_bpf_program__section_name(const struct bpf_program *prog)
{
#ifdef HAVE_LIBBPF_SECTION_NAME
	return bpf_program__section_name(prog);
#else
	return bpf_program__title(prog, false);
#endif
}

Thanks
Hangbin
Toke Høiland-Jørgensen Oct. 29, 2020, 10:51 a.m. UTC | #14
Hangbin Liu <haliu@redhat.com> writes:

> On Wed, Oct 28, 2020 at 09:00:41PM -0600, David Ahern wrote:
>> >> nope. you need to be able to handle this. Ubuntu 20.10 was just
>> >> released, and it has a version of libbpf. If you are going to integrate
>> >> libbpf into other packages like iproute2, it needs to just work with
>> >> that version.
>> > 
>> > OK, I can replace bpf_program__section_name by bpf_program__title().
>> 
>> I believe this one can be handled through a compatability check. Looks
>> the rename / deprecation is fairly recent (78cdb58bdf15f from Sept 2020).
>
> Hi David,
>
> I just come up with another way. In configure, build a temp program and update
> the function checking every time is not graceful. How about just check the
> libbpf version, since libbpf has exported all functions in src/libbpf.map.
>
> Currently, only bpf_program__section_name() is added in 0.2.0, all other
> needed functions are supported in 0.1.0.
>
> So in configure, the new check would like:

Why is this easier than just checking for the function you need? In
xdp-tools configure we have a test like this:

check_perf_consume()
{
    cat >$TMPDIR/libbpftest.c <<EOF
#include <bpf/libbpf.h>
int main(int argc, char **argv) {
    perf_buffer__consume(NULL);
    return 0;
}
EOF
    libbpf_err=$($CC -o $TMPDIR/libbpftest $TMPDIR/libbpftest.c $LIBBPF_CFLAGS $LIBBPF_LDLIBS 2>&1)
    if [ "$?" -eq "0" ]; then
        echo "HAVE_LIBBPF_PERF_BUFFER__CONSUME:=y" >>"$CONFIG"
        echo "yes"
    else
        echo "HAVE_LIBBPF_PERF_BUFFER__CONSUME:=n" >>"$CONFIG"
        echo "no"
    fi
}

Just do that for __section_name(), and you'll also be able to work with
custom libbpf versions using LIBBPF_DIR.

> static const char *get_bpf_program__section_name(const struct bpf_program *prog)
> {
> #ifdef HAVE_LIBBPF_SECTION_NAME
> 	return bpf_program__section_name(prog);
> #else
> 	return bpf_program__title(prog, false);
> #endif
> }

This bit is fine :)

-Toke
Jesper Dangaard Brouer Oct. 29, 2020, 11:38 a.m. UTC | #15
On Wed, 28 Oct 2020 19:50:51 -0700
Andrii Nakryiko <andrii.nakryiko@gmail.com> wrote:

> On Wed, Oct 28, 2020 at 7:34 PM Stephen Hemminger
> <stephen@networkplumber.org> wrote:
> >
> > On Wed, 28 Oct 2020 19:27:20 -0700
> > Andrii Nakryiko <andrii.nakryiko@gmail.com> wrote:
> >  
> > > On Wed, Oct 28, 2020 at 7:06 PM Hangbin Liu <haliu@redhat.com> wrote:  
> > > >
> > > > On Wed, Oct 28, 2020 at 05:02:34PM -0600, David Ahern wrote:  
> > > > > fails to compile on Ubuntu 20.10:
> > > > >
[...]
> > > > You need to update libbpf to latest version.  
> > >
> > > Why not using libbpf from submodule?  
> >
> > Because it makes it harder for people downloading tarballs and distributions.  
> 
> Genuinely curious, making harder how exactly? When packaging sources
> as a tarball you'd check out submodules before packaging, right?
> 
> > Iproute2 has worked well by being standalone.  
> 
> Again, maybe I'm missing something, but what makes it not a
> standalone, if it is using a submodule? Pahole, for instance, is using
> libbpf through submodule and just bypasses all the problems with
> detection of features and library availability. I haven't heard anyone
> complaining about it made working with pahole harder in any way.

I do believe you are missing something.  I guess I can be the relay for
complains, so you will officially hear about this.  Red Hat and Fedora
security is complaining that we are packaging a library (libbpf)
directly into the individual packages.  They complain because in case
of a security issue, they have to figure out to rebuild all the software
packages that are statically compiled with this library.

Maybe you say I don't care that Distro security teams have to do more
work and update more packages.  Then security team says, we expect
customers will use this library right, and if we ship it as a dynamic
loadable (.so) file, then we can update and fix security issues in
library without asking customers to recompile. (Notice the same story
goes if we can update the base-image used by a container).
Andrii Nakryiko Oct. 29, 2020, 8:30 p.m. UTC | #16
On Thu, Oct 29, 2020 at 4:38 AM Jesper Dangaard Brouer
<brouer@redhat.com> wrote:
>
> On Wed, 28 Oct 2020 19:50:51 -0700
> Andrii Nakryiko <andrii.nakryiko@gmail.com> wrote:
>
> > On Wed, Oct 28, 2020 at 7:34 PM Stephen Hemminger
> > <stephen@networkplumber.org> wrote:
> > >
> > > On Wed, 28 Oct 2020 19:27:20 -0700
> > > Andrii Nakryiko <andrii.nakryiko@gmail.com> wrote:
> > >
> > > > On Wed, Oct 28, 2020 at 7:06 PM Hangbin Liu <haliu@redhat.com> wrote:
> > > > >
> > > > > On Wed, Oct 28, 2020 at 05:02:34PM -0600, David Ahern wrote:
> > > > > > fails to compile on Ubuntu 20.10:
> > > > > >
> [...]
> > > > > You need to update libbpf to latest version.
> > > >
> > > > Why not using libbpf from submodule?
> > >
> > > Because it makes it harder for people downloading tarballs and distributions.
> >
> > Genuinely curious, making harder how exactly? When packaging sources
> > as a tarball you'd check out submodules before packaging, right?
> >
> > > Iproute2 has worked well by being standalone.
> >
> > Again, maybe I'm missing something, but what makes it not a
> > standalone, if it is using a submodule? Pahole, for instance, is using
> > libbpf through submodule and just bypasses all the problems with
> > detection of features and library availability. I haven't heard anyone
> > complaining about it made working with pahole harder in any way.
>
> I do believe you are missing something.

I don't think I got an answer how submodules make it harder for people
downloading tarballs and distributions, and the standalone-ness issue.
Your security angle is a very different aspect.

>  I guess I can be the relay for
> complains, so you will officially hear about this.  Red Hat and Fedora
> security is complaining that we are packaging a library (libbpf)
> directly into the individual packages.  They complain because in case
> of a security issue, they have to figure out to rebuild all the software
> packages that are statically compiled with this library.

They must be having nightmares already about BCC, bpftool, pahole, as
well as perf built with libbpf statically (perf on my server is, at
least). I also wonder how many other projects do use either submodules
or static linking with libraries as well.

>
> Maybe you say I don't care that Distro security teams have to do more
> work and update more packages.  Then security team says, we expect
> customers will use this library right, and if we ship it as a dynamic
> loadable (.so) file, then we can update and fix security issues in
> library without asking customers to recompile. (Notice the same story
> goes if we can update the base-image used by a container).

It's a trade off, and everyone decides for themselves where they want
to stand on this.

On the one hand, there are security folks obsessing about hypothetical
security vulnerabilities in libbpf so bad that they will need to
update libbpf overnight.

On the other hand, extra complexity for multiple users of libbpf to do
feature detection and working around the lack of some of the APIs in
libbpf due to older versions in the system. That extra complexity
might lead to more problems, bugs, vulnerabilities in the long run.

I understand the concerns and how dynamic libraries make it easier. We
can't really know for sure which of those two aspects would lead to
more pain and problems overall. I personally choose simplicity,
though.

But as I said, it's up to iproute2 folks to decide. Was just curious
about some of the claims I cited.


>
>
> --
> Best regards,
>   Jesper Dangaard Brouer
>   MSc.CS, Principal Kernel Engineer at Red Hat
>   LinkedIn: http://www.linkedin.com/in/brouer
>