Commit fab45be1 authored by Andrii Nakryiko's avatar Andrii Nakryiko Committed by Alexei Starovoitov

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: default avatarAndrii Nakryiko <andriin@fb.com>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20200903203542.15944-13-andriin@fb.com
parent d86687ae
...@@ -49,6 +49,7 @@ void test_bpf_verif_scale(void) ...@@ -49,6 +49,7 @@ void test_bpf_verif_scale(void)
{ "test_verif_scale3.o", BPF_PROG_TYPE_SCHED_CLS }, { "test_verif_scale3.o", BPF_PROG_TYPE_SCHED_CLS },
{ "pyperf_global.o", BPF_PROG_TYPE_RAW_TRACEPOINT }, { "pyperf_global.o", BPF_PROG_TYPE_RAW_TRACEPOINT },
{ "pyperf_subprogs.o", BPF_PROG_TYPE_RAW_TRACEPOINT },
/* full unroll by llvm */ /* full unroll by llvm */
{ "pyperf50.o", BPF_PROG_TYPE_RAW_TRACEPOINT }, { "pyperf50.o", BPF_PROG_TYPE_RAW_TRACEPOINT },
...@@ -86,6 +87,9 @@ void test_bpf_verif_scale(void) ...@@ -86,6 +87,9 @@ void test_bpf_verif_scale(void)
{ "strobemeta_nounroll1.o", BPF_PROG_TYPE_RAW_TRACEPOINT }, { "strobemeta_nounroll1.o", BPF_PROG_TYPE_RAW_TRACEPOINT },
{ "strobemeta_nounroll2.o", BPF_PROG_TYPE_RAW_TRACEPOINT }, { "strobemeta_nounroll2.o", BPF_PROG_TYPE_RAW_TRACEPOINT },
/* non-inlined subprogs */
{ "strobemeta_subprogs.o", BPF_PROG_TYPE_RAW_TRACEPOINT },
{ "test_sysctl_loop1.o", BPF_PROG_TYPE_CGROUP_SYSCTL }, { "test_sysctl_loop1.o", BPF_PROG_TYPE_CGROUP_SYSCTL },
{ "test_sysctl_loop2.o", BPF_PROG_TYPE_CGROUP_SYSCTL }, { "test_sysctl_loop2.o", BPF_PROG_TYPE_CGROUP_SYSCTL },
......
...@@ -80,9 +80,8 @@ static void test_l4lb(const char *file) ...@@ -80,9 +80,8 @@ static void test_l4lb(const char *file)
void test_l4lb_all(void) void test_l4lb_all(void)
{ {
const char *file1 = "./test_l4lb.o"; if (test__start_subtest("l4lb_inline"))
const char *file2 = "./test_l4lb_noinline.o"; test_l4lb("test_l4lb.o");
if (test__start_subtest("l4lb_noinline"))
test_l4lb(file1); test_l4lb("test_l4lb_noinline.o");
test_l4lb(file2);
} }
...@@ -67,7 +67,12 @@ typedef struct { ...@@ -67,7 +67,12 @@ typedef struct {
void* co_name; // PyCodeObject.co_name void* co_name; // PyCodeObject.co_name
} FrameData; } FrameData;
static __always_inline void *get_thread_state(void *tls_base, PidData *pidData) #ifdef SUBPROGS
__noinline
#else
__always_inline
#endif
static void *get_thread_state(void *tls_base, PidData *pidData)
{ {
void* thread_state; void* thread_state;
int key; int key;
...@@ -155,7 +160,9 @@ struct { ...@@ -155,7 +160,9 @@ struct {
} stackmap SEC(".maps"); } stackmap SEC(".maps");
#ifdef GLOBAL_FUNC #ifdef GLOBAL_FUNC
__attribute__((noinline)) __noinline
#elif defined(SUBPROGS)
static __noinline
#else #else
static __always_inline static __always_inline
#endif #endif
......
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2020 Facebook */
#define STACK_MAX_LEN 50
#define SUBPROGS
#include "pyperf.h"
...@@ -266,8 +266,12 @@ struct tls_index { ...@@ -266,8 +266,12 @@ struct tls_index {
uint64_t offset; uint64_t offset;
}; };
static __always_inline void *calc_location(struct strobe_value_loc *loc, #ifdef SUBPROGS
void *tls_base) __noinline
#else
__always_inline
#endif
static void *calc_location(struct strobe_value_loc *loc, void *tls_base)
{ {
/* /*
* tls_mode value is: * tls_mode value is:
...@@ -327,10 +331,15 @@ static __always_inline void *calc_location(struct strobe_value_loc *loc, ...@@ -327,10 +331,15 @@ static __always_inline void *calc_location(struct strobe_value_loc *loc,
: NULL; : NULL;
} }
static __always_inline void read_int_var(struct strobemeta_cfg *cfg, #ifdef SUBPROGS
size_t idx, void *tls_base, __noinline
struct strobe_value_generic *value, #else
struct strobemeta_payload *data) __always_inline
#endif
static void read_int_var(struct strobemeta_cfg *cfg,
size_t idx, void *tls_base,
struct strobe_value_generic *value,
struct strobemeta_payload *data)
{ {
void *location = calc_location(&cfg->int_locs[idx], tls_base); void *location = calc_location(&cfg->int_locs[idx], tls_base);
if (!location) if (!location)
...@@ -440,8 +449,13 @@ static __always_inline void *read_map_var(struct strobemeta_cfg *cfg, ...@@ -440,8 +449,13 @@ static __always_inline void *read_map_var(struct strobemeta_cfg *cfg,
* read_strobe_meta returns NULL, if no metadata was read; otherwise returns * read_strobe_meta returns NULL, if no metadata was read; otherwise returns
* pointer to *right after* payload ends * pointer to *right after* payload ends
*/ */
static __always_inline void *read_strobe_meta(struct task_struct *task, #ifdef SUBPROGS
struct strobemeta_payload *data) __noinline
#else
__always_inline
#endif
static void *read_strobe_meta(struct task_struct *task,
struct strobemeta_payload *data)
{ {
pid_t pid = bpf_get_current_pid_tgid() >> 32; pid_t pid = bpf_get_current_pid_tgid() >> 32;
struct strobe_value_generic value = {0}; struct strobe_value_generic value = {0};
......
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
// Copyright (c) 2019 Facebook
#define STROBE_MAX_INTS 2
#define STROBE_MAX_STRS 25
#define STROBE_MAX_MAPS 13
#define STROBE_MAX_MAP_ENTRIES 20
#define NO_UNROLL
#define SUBPROGS
#include "strobemeta.h"
...@@ -17,9 +17,7 @@ ...@@ -17,9 +17,7 @@
#include "test_iptunnel_common.h" #include "test_iptunnel_common.h"
#include <bpf/bpf_endian.h> #include <bpf/bpf_endian.h>
int _version SEC("version") = 1; static __always_inline __u32 rol32(__u32 word, unsigned int shift)
static __u32 rol32(__u32 word, unsigned int shift)
{ {
return (word << shift) | (word >> ((-shift) & 31)); return (word << shift) | (word >> ((-shift) & 31));
} }
...@@ -52,7 +50,7 @@ static __u32 rol32(__u32 word, unsigned int shift) ...@@ -52,7 +50,7 @@ static __u32 rol32(__u32 word, unsigned int shift)
typedef unsigned int u32; typedef unsigned int u32;
static u32 jhash(const void *key, u32 length, u32 initval) static __noinline u32 jhash(const void *key, u32 length, u32 initval)
{ {
u32 a, b, c; u32 a, b, c;
const unsigned char *k = key; const unsigned char *k = key;
...@@ -88,7 +86,7 @@ static u32 jhash(const void *key, u32 length, u32 initval) ...@@ -88,7 +86,7 @@ static u32 jhash(const void *key, u32 length, u32 initval)
return c; return c;
} }
static u32 __jhash_nwords(u32 a, u32 b, u32 c, u32 initval) static __noinline u32 __jhash_nwords(u32 a, u32 b, u32 c, u32 initval)
{ {
a += initval; a += initval;
b += initval; b += initval;
...@@ -97,7 +95,7 @@ static u32 __jhash_nwords(u32 a, u32 b, u32 c, u32 initval) ...@@ -97,7 +95,7 @@ static u32 __jhash_nwords(u32 a, u32 b, u32 c, u32 initval)
return c; return c;
} }
static u32 jhash_2words(u32 a, u32 b, u32 initval) static __noinline u32 jhash_2words(u32 a, u32 b, u32 initval)
{ {
return __jhash_nwords(a, b, 0, initval + JHASH_INITVAL + (2 << 2)); return __jhash_nwords(a, b, 0, initval + JHASH_INITVAL + (2 << 2));
} }
...@@ -200,8 +198,7 @@ struct { ...@@ -200,8 +198,7 @@ struct {
__type(value, struct ctl_value); __type(value, struct ctl_value);
} ctl_array SEC(".maps"); } ctl_array SEC(".maps");
static __u32 get_packet_hash(struct packet_description *pckt, static __noinline __u32 get_packet_hash(struct packet_description *pckt, bool ipv6)
bool ipv6)
{ {
if (ipv6) if (ipv6)
return jhash_2words(jhash(pckt->srcv6, 16, MAX_VIPS), return jhash_2words(jhash(pckt->srcv6, 16, MAX_VIPS),
...@@ -210,10 +207,10 @@ static __u32 get_packet_hash(struct packet_description *pckt, ...@@ -210,10 +207,10 @@ static __u32 get_packet_hash(struct packet_description *pckt,
return jhash_2words(pckt->src, pckt->ports, CH_RINGS_SIZE); return jhash_2words(pckt->src, pckt->ports, CH_RINGS_SIZE);
} }
static bool get_packet_dst(struct real_definition **real, static __noinline bool get_packet_dst(struct real_definition **real,
struct packet_description *pckt, struct packet_description *pckt,
struct vip_meta *vip_info, struct vip_meta *vip_info,
bool is_ipv6) bool is_ipv6)
{ {
__u32 hash = get_packet_hash(pckt, is_ipv6); __u32 hash = get_packet_hash(pckt, is_ipv6);
__u32 key = RING_SIZE * vip_info->vip_num + hash % RING_SIZE; __u32 key = RING_SIZE * vip_info->vip_num + hash % RING_SIZE;
...@@ -233,8 +230,8 @@ static bool get_packet_dst(struct real_definition **real, ...@@ -233,8 +230,8 @@ static bool get_packet_dst(struct real_definition **real,
return true; return true;
} }
static int parse_icmpv6(void *data, void *data_end, __u64 off, static __noinline int parse_icmpv6(void *data, void *data_end, __u64 off,
struct packet_description *pckt) struct packet_description *pckt)
{ {
struct icmp6hdr *icmp_hdr; struct icmp6hdr *icmp_hdr;
struct ipv6hdr *ip6h; struct ipv6hdr *ip6h;
...@@ -255,8 +252,8 @@ static int parse_icmpv6(void *data, void *data_end, __u64 off, ...@@ -255,8 +252,8 @@ static int parse_icmpv6(void *data, void *data_end, __u64 off,
return TC_ACT_UNSPEC; return TC_ACT_UNSPEC;
} }
static int parse_icmp(void *data, void *data_end, __u64 off, static __noinline int parse_icmp(void *data, void *data_end, __u64 off,
struct packet_description *pckt) struct packet_description *pckt)
{ {
struct icmphdr *icmp_hdr; struct icmphdr *icmp_hdr;
struct iphdr *iph; struct iphdr *iph;
...@@ -280,8 +277,8 @@ static int parse_icmp(void *data, void *data_end, __u64 off, ...@@ -280,8 +277,8 @@ static int parse_icmp(void *data, void *data_end, __u64 off,
return TC_ACT_UNSPEC; return TC_ACT_UNSPEC;
} }
static bool parse_udp(void *data, __u64 off, void *data_end, static __noinline bool parse_udp(void *data, __u64 off, void *data_end,
struct packet_description *pckt) struct packet_description *pckt)
{ {
struct udphdr *udp; struct udphdr *udp;
udp = data + off; udp = data + off;
...@@ -299,8 +296,8 @@ static bool parse_udp(void *data, __u64 off, void *data_end, ...@@ -299,8 +296,8 @@ static bool parse_udp(void *data, __u64 off, void *data_end,
return true; return true;
} }
static bool parse_tcp(void *data, __u64 off, void *data_end, static __noinline bool parse_tcp(void *data, __u64 off, void *data_end,
struct packet_description *pckt) struct packet_description *pckt)
{ {
struct tcphdr *tcp; struct tcphdr *tcp;
...@@ -321,8 +318,8 @@ static bool parse_tcp(void *data, __u64 off, void *data_end, ...@@ -321,8 +318,8 @@ static bool parse_tcp(void *data, __u64 off, void *data_end,
return true; return true;
} }
static int process_packet(void *data, __u64 off, void *data_end, static __noinline int process_packet(void *data, __u64 off, void *data_end,
bool is_ipv6, struct __sk_buff *skb) bool is_ipv6, struct __sk_buff *skb)
{ {
void *pkt_start = (void *)(long)skb->data; void *pkt_start = (void *)(long)skb->data;
struct packet_description pckt = {}; struct packet_description pckt = {};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment