Skip to content

Commit e5659e4

Browse files
Rtoaxanakryiko
authored andcommitted
samples/bpf: Fix sockex3 error: Missing BPF prog type
since commit 450b167("libbpf: clean up SEC() handling"), sec_def_matches() does not recognize "socket/xxx" as "socket", therefore, the BPF program type is not recognized. Instead of sockex3_user.c parsing section names to get the BPF program fd. We use the program array map to assign a static index to each BPF program (get inspired by selftests/bpf progs/test_prog_array_init.c). Therefore, use SEC("socket") as section name instead of SEC("socket/xxx"), so that the BPF program is parsed to SOCKET_FILTER type. The "missing BPF prog type" problem is solved. How to reproduce this error: $ cd samples/bpf $ sudo ./sockex3 libbpf: prog 'bpf_func_PARSE_IP': missing BPF prog type, check ELF section name 'socket/3' libbpf: prog 'bpf_func_PARSE_IP': failed to load: -22 libbpf: failed to load object './sockex3_kern.o' ERROR: loading BPF object file failed Signed-off-by: Rong Tao <rongtao@cestc.cn> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/bpf/tencent_EBA3C18864069E42175946973C2ACBAF5408@qq.com
1 parent e8f50c4 commit e5659e4

2 files changed

Lines changed: 63 additions & 55 deletions

File tree

samples/bpf/sockex3_kern.c

Lines changed: 53 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -17,48 +17,11 @@
1717
#define IP_MF 0x2000
1818
#define IP_OFFSET 0x1FFF
1919

20-
#define PROG(F) SEC("socket/"__stringify(F)) int bpf_func_##F
21-
22-
struct {
23-
__uint(type, BPF_MAP_TYPE_PROG_ARRAY);
24-
__uint(key_size, sizeof(u32));
25-
__uint(value_size, sizeof(u32));
26-
__uint(max_entries, 8);
27-
} jmp_table SEC(".maps");
28-
2920
#define PARSE_VLAN 1
3021
#define PARSE_MPLS 2
3122
#define PARSE_IP 3
3223
#define PARSE_IPV6 4
3324

34-
/* Protocol dispatch routine. It tail-calls next BPF program depending
35-
* on eth proto. Note, we could have used ...
36-
*
37-
* bpf_tail_call(skb, &jmp_table, proto);
38-
*
39-
* ... but it would need large prog_array and cannot be optimised given
40-
* the map key is not static.
41-
*/
42-
static inline void parse_eth_proto(struct __sk_buff *skb, u32 proto)
43-
{
44-
switch (proto) {
45-
case ETH_P_8021Q:
46-
case ETH_P_8021AD:
47-
bpf_tail_call(skb, &jmp_table, PARSE_VLAN);
48-
break;
49-
case ETH_P_MPLS_UC:
50-
case ETH_P_MPLS_MC:
51-
bpf_tail_call(skb, &jmp_table, PARSE_MPLS);
52-
break;
53-
case ETH_P_IP:
54-
bpf_tail_call(skb, &jmp_table, PARSE_IP);
55-
break;
56-
case ETH_P_IPV6:
57-
bpf_tail_call(skb, &jmp_table, PARSE_IPV6);
58-
break;
59-
}
60-
}
61-
6225
struct vlan_hdr {
6326
__be16 h_vlan_TCI;
6427
__be16 h_vlan_encapsulated_proto;
@@ -74,6 +37,8 @@ struct flow_key_record {
7437
__u32 ip_proto;
7538
};
7639

40+
static inline void parse_eth_proto(struct __sk_buff *skb, u32 proto);
41+
7742
static inline int ip_is_fragment(struct __sk_buff *ctx, __u64 nhoff)
7843
{
7944
return load_half(ctx, nhoff + offsetof(struct iphdr, frag_off))
@@ -189,7 +154,8 @@ static __always_inline void parse_ip_proto(struct __sk_buff *skb,
189154
}
190155
}
191156

192-
PROG(PARSE_IP)(struct __sk_buff *skb)
157+
SEC("socket")
158+
int bpf_func_ip(struct __sk_buff *skb)
193159
{
194160
struct globals *g = this_cpu_globals();
195161
__u32 nhoff, verlen, ip_proto;
@@ -217,7 +183,8 @@ PROG(PARSE_IP)(struct __sk_buff *skb)
217183
return 0;
218184
}
219185

220-
PROG(PARSE_IPV6)(struct __sk_buff *skb)
186+
SEC("socket")
187+
int bpf_func_ipv6(struct __sk_buff *skb)
221188
{
222189
struct globals *g = this_cpu_globals();
223190
__u32 nhoff, ip_proto;
@@ -240,7 +207,8 @@ PROG(PARSE_IPV6)(struct __sk_buff *skb)
240207
return 0;
241208
}
242209

243-
PROG(PARSE_VLAN)(struct __sk_buff *skb)
210+
SEC("socket")
211+
int bpf_func_vlan(struct __sk_buff *skb)
244212
{
245213
__u32 nhoff, proto;
246214

@@ -256,7 +224,8 @@ PROG(PARSE_VLAN)(struct __sk_buff *skb)
256224
return 0;
257225
}
258226

259-
PROG(PARSE_MPLS)(struct __sk_buff *skb)
227+
SEC("socket")
228+
int bpf_func_mpls(struct __sk_buff *skb)
260229
{
261230
__u32 nhoff, label;
262231

@@ -279,7 +248,49 @@ PROG(PARSE_MPLS)(struct __sk_buff *skb)
279248
return 0;
280249
}
281250

282-
SEC("socket/0")
251+
struct {
252+
__uint(type, BPF_MAP_TYPE_PROG_ARRAY);
253+
__uint(key_size, sizeof(u32));
254+
__uint(max_entries, 8);
255+
__array(values, u32 (void *));
256+
} prog_array_init SEC(".maps") = {
257+
.values = {
258+
[PARSE_VLAN] = (void *)&bpf_func_vlan,
259+
[PARSE_IP] = (void *)&bpf_func_ip,
260+
[PARSE_IPV6] = (void *)&bpf_func_ipv6,
261+
[PARSE_MPLS] = (void *)&bpf_func_mpls,
262+
},
263+
};
264+
265+
/* Protocol dispatch routine. It tail-calls next BPF program depending
266+
* on eth proto. Note, we could have used ...
267+
*
268+
* bpf_tail_call(skb, &prog_array_init, proto);
269+
*
270+
* ... but it would need large prog_array and cannot be optimised given
271+
* the map key is not static.
272+
*/
273+
static inline void parse_eth_proto(struct __sk_buff *skb, u32 proto)
274+
{
275+
switch (proto) {
276+
case ETH_P_8021Q:
277+
case ETH_P_8021AD:
278+
bpf_tail_call(skb, &prog_array_init, PARSE_VLAN);
279+
break;
280+
case ETH_P_MPLS_UC:
281+
case ETH_P_MPLS_MC:
282+
bpf_tail_call(skb, &prog_array_init, PARSE_MPLS);
283+
break;
284+
case ETH_P_IP:
285+
bpf_tail_call(skb, &prog_array_init, PARSE_IP);
286+
break;
287+
case ETH_P_IPV6:
288+
bpf_tail_call(skb, &prog_array_init, PARSE_IPV6);
289+
break;
290+
}
291+
}
292+
293+
SEC("socket")
283294
int main_prog(struct __sk_buff *skb)
284295
{
285296
__u32 nhoff = ETH_HLEN;

samples/bpf/sockex3_user.c

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,9 @@ struct pair {
2424

2525
int main(int argc, char **argv)
2626
{
27-
int i, sock, key, fd, main_prog_fd, jmp_table_fd, hash_map_fd;
27+
int i, sock, fd, main_prog_fd, hash_map_fd;
2828
struct bpf_program *prog;
2929
struct bpf_object *obj;
30-
const char *section;
3130
char filename[256];
3231
FILE *f;
3332

@@ -45,26 +44,24 @@ int main(int argc, char **argv)
4544
goto cleanup;
4645
}
4746

48-
jmp_table_fd = bpf_object__find_map_fd_by_name(obj, "jmp_table");
4947
hash_map_fd = bpf_object__find_map_fd_by_name(obj, "hash_map");
50-
if (jmp_table_fd < 0 || hash_map_fd < 0) {
48+
if (hash_map_fd < 0) {
5149
fprintf(stderr, "ERROR: finding a map in obj file failed\n");
5250
goto cleanup;
5351
}
5452

53+
/* find BPF main program */
54+
main_prog_fd = 0;
5555
bpf_object__for_each_program(prog, obj) {
5656
fd = bpf_program__fd(prog);
5757

58-
section = bpf_program__section_name(prog);
59-
if (sscanf(section, "socket/%d", &key) != 1) {
60-
fprintf(stderr, "ERROR: finding prog failed\n");
61-
goto cleanup;
62-
}
63-
64-
if (key == 0)
58+
if (!strcmp(bpf_program__name(prog), "main_prog"))
6559
main_prog_fd = fd;
66-
else
67-
bpf_map_update_elem(jmp_table_fd, &key, &fd, BPF_ANY);
60+
}
61+
62+
if (main_prog_fd == 0) {
63+
fprintf(stderr, "ERROR: can't find main_prog\n");
64+
goto cleanup;
6865
}
6966

7067
sock = open_raw_sock("lo");

0 commit comments

Comments
 (0)