162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci#include <linux/bpf.h>
362306a36Sopenharmony_ci#include <bpf/bpf_helpers.h>
462306a36Sopenharmony_ci
562306a36Sopenharmony_cistruct {
662306a36Sopenharmony_ci	__uint(type, BPF_MAP_TYPE_ARRAY);
762306a36Sopenharmony_ci	__uint(max_entries, 1);
862306a36Sopenharmony_ci	__uint(key_size, sizeof(__u32));
962306a36Sopenharmony_ci	__uint(value_size, sizeof(__u32));
1062306a36Sopenharmony_ci} nop_table SEC(".maps");
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_cistruct {
1362306a36Sopenharmony_ci	__uint(type, BPF_MAP_TYPE_PROG_ARRAY);
1462306a36Sopenharmony_ci	__uint(max_entries, 3);
1562306a36Sopenharmony_ci	__uint(key_size, sizeof(__u32));
1662306a36Sopenharmony_ci	__uint(value_size, sizeof(__u32));
1762306a36Sopenharmony_ci} jmp_table SEC(".maps");
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ciint count = 0;
2062306a36Sopenharmony_ciint noise = 0;
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_cistatic __always_inline int subprog_noise(void)
2362306a36Sopenharmony_ci{
2462306a36Sopenharmony_ci	__u32 key = 0;
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci	bpf_map_lookup_elem(&nop_table, &key);
2762306a36Sopenharmony_ci	return 0;
2862306a36Sopenharmony_ci}
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci__noinline
3162306a36Sopenharmony_ciint subprog_tail_2(struct __sk_buff *skb)
3262306a36Sopenharmony_ci{
3362306a36Sopenharmony_ci	if (noise)
3462306a36Sopenharmony_ci		subprog_noise();
3562306a36Sopenharmony_ci	bpf_tail_call_static(skb, &jmp_table, 2);
3662306a36Sopenharmony_ci	return skb->len * 3;
3762306a36Sopenharmony_ci}
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci__noinline
4062306a36Sopenharmony_ciint subprog_tail_1(struct __sk_buff *skb)
4162306a36Sopenharmony_ci{
4262306a36Sopenharmony_ci	bpf_tail_call_static(skb, &jmp_table, 1);
4362306a36Sopenharmony_ci	return skb->len * 2;
4462306a36Sopenharmony_ci}
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci__noinline
4762306a36Sopenharmony_ciint subprog_tail(struct __sk_buff *skb)
4862306a36Sopenharmony_ci{
4962306a36Sopenharmony_ci	bpf_tail_call_static(skb, &jmp_table, 0);
5062306a36Sopenharmony_ci	return skb->len;
5162306a36Sopenharmony_ci}
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ciSEC("tc")
5462306a36Sopenharmony_ciint classifier_1(struct __sk_buff *skb)
5562306a36Sopenharmony_ci{
5662306a36Sopenharmony_ci	return subprog_tail_2(skb);
5762306a36Sopenharmony_ci}
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ciSEC("tc")
6062306a36Sopenharmony_ciint classifier_2(struct __sk_buff *skb)
6162306a36Sopenharmony_ci{
6262306a36Sopenharmony_ci	count++;
6362306a36Sopenharmony_ci	return subprog_tail_2(skb);
6462306a36Sopenharmony_ci}
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ciSEC("tc")
6762306a36Sopenharmony_ciint classifier_0(struct __sk_buff *skb)
6862306a36Sopenharmony_ci{
6962306a36Sopenharmony_ci	return subprog_tail_1(skb);
7062306a36Sopenharmony_ci}
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ciSEC("tc")
7362306a36Sopenharmony_ciint entry(struct __sk_buff *skb)
7462306a36Sopenharmony_ci{
7562306a36Sopenharmony_ci	return subprog_tail(skb);
7662306a36Sopenharmony_ci}
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_cichar __license[] SEC("license") = "GPL";
79