Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/bpf: Add subprogs to pyperf, strobemeta, and l4lb_noinline tests

Add use of non-inlined subprogs to few bigger selftests to excercise libbpf's
bpf2bpf handling logic. Also split l4lb_all selftest into two sub-tests.

Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20200903203542.15944-13-andriin@fb.com

authored by

Andrii Nakryiko and committed by
Alexei Starovoitov
fab45be1 d86687ae

+73 -37
+4
tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c
··· 49 49 { "test_verif_scale3.o", BPF_PROG_TYPE_SCHED_CLS }, 50 50 51 51 { "pyperf_global.o", BPF_PROG_TYPE_RAW_TRACEPOINT }, 52 + { "pyperf_subprogs.o", BPF_PROG_TYPE_RAW_TRACEPOINT }, 52 53 53 54 /* full unroll by llvm */ 54 55 { "pyperf50.o", BPF_PROG_TYPE_RAW_TRACEPOINT }, ··· 86 85 /* no unroll, tiny loops */ 87 86 { "strobemeta_nounroll1.o", BPF_PROG_TYPE_RAW_TRACEPOINT }, 88 87 { "strobemeta_nounroll2.o", BPF_PROG_TYPE_RAW_TRACEPOINT }, 88 + 89 + /* non-inlined subprogs */ 90 + { "strobemeta_subprogs.o", BPF_PROG_TYPE_RAW_TRACEPOINT }, 89 91 90 92 { "test_sysctl_loop1.o", BPF_PROG_TYPE_CGROUP_SYSCTL }, 91 93 { "test_sysctl_loop2.o", BPF_PROG_TYPE_CGROUP_SYSCTL },
+4 -5
tools/testing/selftests/bpf/prog_tests/l4lb_all.c
··· 80 80 81 81 void test_l4lb_all(void) 82 82 { 83 - const char *file1 = "./test_l4lb.o"; 84 - const char *file2 = "./test_l4lb_noinline.o"; 85 - 86 - test_l4lb(file1); 87 - test_l4lb(file2); 83 + if (test__start_subtest("l4lb_inline")) 84 + test_l4lb("test_l4lb.o"); 85 + if (test__start_subtest("l4lb_noinline")) 86 + test_l4lb("test_l4lb_noinline.o"); 88 87 }
+9 -2
tools/testing/selftests/bpf/progs/pyperf.h
··· 67 67 void* co_name; // PyCodeObject.co_name 68 68 } FrameData; 69 69 70 - static __always_inline void *get_thread_state(void *tls_base, PidData *pidData) 70 + #ifdef SUBPROGS 71 + __noinline 72 + #else 73 + __always_inline 74 + #endif 75 + static void *get_thread_state(void *tls_base, PidData *pidData) 71 76 { 72 77 void* thread_state; 73 78 int key; ··· 160 155 } stackmap SEC(".maps"); 161 156 162 157 #ifdef GLOBAL_FUNC 163 - __attribute__((noinline)) 158 + __noinline 159 + #elif defined(SUBPROGS) 160 + static __noinline 164 161 #else 165 162 static __always_inline 166 163 #endif
+5
tools/testing/selftests/bpf/progs/pyperf_subprogs.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) 2020 Facebook */ 3 + #define STACK_MAX_LEN 50 4 + #define SUBPROGS 5 + #include "pyperf.h"
+22 -8
tools/testing/selftests/bpf/progs/strobemeta.h
··· 266 266 uint64_t offset; 267 267 }; 268 268 269 - static __always_inline void *calc_location(struct strobe_value_loc *loc, 270 - void *tls_base) 269 + #ifdef SUBPROGS 270 + __noinline 271 + #else 272 + __always_inline 273 + #endif 274 + static void *calc_location(struct strobe_value_loc *loc, void *tls_base) 271 275 { 272 276 /* 273 277 * tls_mode value is: ··· 331 327 : NULL; 332 328 } 333 329 334 - static __always_inline void read_int_var(struct strobemeta_cfg *cfg, 335 - size_t idx, void *tls_base, 336 - struct strobe_value_generic *value, 337 - struct strobemeta_payload *data) 330 + #ifdef SUBPROGS 331 + __noinline 332 + #else 333 + __always_inline 334 + #endif 335 + static void read_int_var(struct strobemeta_cfg *cfg, 336 + size_t idx, void *tls_base, 337 + struct strobe_value_generic *value, 338 + struct strobemeta_payload *data) 338 339 { 339 340 void *location = calc_location(&cfg->int_locs[idx], tls_base); 340 341 if (!location) ··· 449 440 * read_strobe_meta returns NULL, if no metadata was read; otherwise returns 450 441 * pointer to *right after* payload ends 451 442 */ 452 - static __always_inline void *read_strobe_meta(struct task_struct *task, 453 - struct strobemeta_payload *data) 443 + #ifdef SUBPROGS 444 + __noinline 445 + #else 446 + __always_inline 447 + #endif 448 + static void *read_strobe_meta(struct task_struct *task, 449 + struct strobemeta_payload *data) 454 450 { 455 451 pid_t pid = bpf_get_current_pid_tgid() >> 32; 456 452 struct strobe_value_generic value = {0};
+10
tools/testing/selftests/bpf/progs/strobemeta_subprogs.c
··· 1 + // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 2 + // Copyright (c) 2019 Facebook 3 + 4 + #define STROBE_MAX_INTS 2 5 + #define STROBE_MAX_STRS 25 6 + #define STROBE_MAX_MAPS 13 7 + #define STROBE_MAX_MAP_ENTRIES 20 8 + #define NO_UNROLL 9 + #define SUBPROGS 10 + #include "strobemeta.h"
+19 -22
tools/testing/selftests/bpf/progs/test_l4lb_noinline.c
··· 17 17 #include "test_iptunnel_common.h" 18 18 #include <bpf/bpf_endian.h> 19 19 20 - int _version SEC("version") = 1; 21 - 22 - static __u32 rol32(__u32 word, unsigned int shift) 20 + static __always_inline __u32 rol32(__u32 word, unsigned int shift) 23 21 { 24 22 return (word << shift) | (word >> ((-shift) & 31)); 25 23 } ··· 50 52 51 53 typedef unsigned int u32; 52 54 53 - static u32 jhash(const void *key, u32 length, u32 initval) 55 + static __noinline u32 jhash(const void *key, u32 length, u32 initval) 54 56 { 55 57 u32 a, b, c; 56 58 const unsigned char *k = key; ··· 86 88 return c; 87 89 } 88 90 89 - static u32 __jhash_nwords(u32 a, u32 b, u32 c, u32 initval) 91 + static __noinline u32 __jhash_nwords(u32 a, u32 b, u32 c, u32 initval) 90 92 { 91 93 a += initval; 92 94 b += initval; ··· 95 97 return c; 96 98 } 97 99 98 - static u32 jhash_2words(u32 a, u32 b, u32 initval) 100 + static __noinline u32 jhash_2words(u32 a, u32 b, u32 initval) 99 101 { 100 102 return __jhash_nwords(a, b, 0, initval + JHASH_INITVAL + (2 << 2)); 101 103 } ··· 198 200 __type(value, struct ctl_value); 199 201 } ctl_array SEC(".maps"); 200 202 201 - static __u32 get_packet_hash(struct packet_description *pckt, 202 - bool ipv6) 203 + static __noinline __u32 get_packet_hash(struct packet_description *pckt, bool ipv6) 203 204 { 204 205 if (ipv6) 205 206 return jhash_2words(jhash(pckt->srcv6, 16, MAX_VIPS), ··· 207 210 return jhash_2words(pckt->src, pckt->ports, CH_RINGS_SIZE); 208 211 } 209 212 210 - static bool get_packet_dst(struct real_definition **real, 211 - struct packet_description *pckt, 212 - struct vip_meta *vip_info, 213 - bool is_ipv6) 213 + static __noinline bool get_packet_dst(struct real_definition **real, 214 + struct packet_description *pckt, 215 + struct vip_meta *vip_info, 216 + bool is_ipv6) 214 217 { 215 218 __u32 hash = get_packet_hash(pckt, is_ipv6); 216 219 __u32 key = RING_SIZE * vip_info->vip_num + hash % RING_SIZE; ··· 230 233 return true; 231 234 } 232 235 233 - static int parse_icmpv6(void *data, void *data_end, __u64 off, 234 - struct packet_description *pckt) 236 + static __noinline int parse_icmpv6(void *data, void *data_end, __u64 off, 237 + struct packet_description *pckt) 235 238 { 236 239 struct icmp6hdr *icmp_hdr; 237 240 struct ipv6hdr *ip6h; ··· 252 255 return TC_ACT_UNSPEC; 253 256 } 254 257 255 - static int parse_icmp(void *data, void *data_end, __u64 off, 256 - struct packet_description *pckt) 258 + static __noinline int parse_icmp(void *data, void *data_end, __u64 off, 259 + struct packet_description *pckt) 257 260 { 258 261 struct icmphdr *icmp_hdr; 259 262 struct iphdr *iph; ··· 277 280 return TC_ACT_UNSPEC; 278 281 } 279 282 280 - static bool parse_udp(void *data, __u64 off, void *data_end, 281 - struct packet_description *pckt) 283 + static __noinline bool parse_udp(void *data, __u64 off, void *data_end, 284 + struct packet_description *pckt) 282 285 { 283 286 struct udphdr *udp; 284 287 udp = data + off; ··· 296 299 return true; 297 300 } 298 301 299 - static bool parse_tcp(void *data, __u64 off, void *data_end, 300 - struct packet_description *pckt) 302 + static __noinline bool parse_tcp(void *data, __u64 off, void *data_end, 303 + struct packet_description *pckt) 301 304 { 302 305 struct tcphdr *tcp; 303 306 ··· 318 321 return true; 319 322 } 320 323 321 - static int process_packet(void *data, __u64 off, void *data_end, 322 - bool is_ipv6, struct __sk_buff *skb) 324 + static __noinline int process_packet(void *data, __u64 off, void *data_end, 325 + bool is_ipv6, struct __sk_buff *skb) 323 326 { 324 327 void *pkt_start = (void *)(long)skb->data; 325 328 struct packet_description pckt = {};