144d28be2SJakub Sitnicki // SPDX-License-Identifier: GPL-2.0
244d28be2SJakub Sitnicki // Copyright (c) 2020 Cloudflare
344d28be2SJakub Sitnicki
444d28be2SJakub Sitnicki #include <errno.h>
544d28be2SJakub Sitnicki #include <stdbool.h>
644d28be2SJakub Sitnicki #include <linux/bpf.h>
744d28be2SJakub Sitnicki
844d28be2SJakub Sitnicki #include <bpf/bpf_helpers.h>
944d28be2SJakub Sitnicki
1044d28be2SJakub Sitnicki struct {
1144d28be2SJakub Sitnicki __uint(type, BPF_MAP_TYPE_SOCKMAP);
1244d28be2SJakub Sitnicki __uint(max_entries, 2);
1344d28be2SJakub Sitnicki __type(key, __u32);
1444d28be2SJakub Sitnicki __type(value, __u64);
1544d28be2SJakub Sitnicki } sock_map SEC(".maps");
1644d28be2SJakub Sitnicki
1744d28be2SJakub Sitnicki struct {
1844d28be2SJakub Sitnicki __uint(type, BPF_MAP_TYPE_SOCKHASH);
1944d28be2SJakub Sitnicki __uint(max_entries, 2);
2044d28be2SJakub Sitnicki __type(key, __u32);
2144d28be2SJakub Sitnicki __type(value, __u64);
2244d28be2SJakub Sitnicki } sock_hash SEC(".maps");
2344d28be2SJakub Sitnicki
2444d28be2SJakub Sitnicki struct {
2544d28be2SJakub Sitnicki __uint(type, BPF_MAP_TYPE_ARRAY);
2644d28be2SJakub Sitnicki __uint(max_entries, 2);
2744d28be2SJakub Sitnicki __type(key, int);
2844d28be2SJakub Sitnicki __type(value, unsigned int);
2944d28be2SJakub Sitnicki } verdict_map SEC(".maps");
3044d28be2SJakub Sitnicki
31*a4b7193dSXu Kuohai struct {
32*a4b7193dSXu Kuohai __uint(type, BPF_MAP_TYPE_ARRAY);
33*a4b7193dSXu Kuohai __uint(max_entries, 1);
34*a4b7193dSXu Kuohai __type(key, int);
35*a4b7193dSXu Kuohai __type(value, int);
36*a4b7193dSXu Kuohai } parser_map SEC(".maps");
37*a4b7193dSXu Kuohai
38256eab48SAndrii Nakryiko bool test_sockmap = false; /* toggled by user-space */
39256eab48SAndrii Nakryiko bool test_ingress = false; /* toggled by user-space */
4044d28be2SJakub Sitnicki
4144d28be2SJakub Sitnicki SEC("sk_skb/stream_parser")
prog_stream_parser(struct __sk_buff * skb)42ae8b8332SCong Wang int prog_stream_parser(struct __sk_buff *skb)
4344d28be2SJakub Sitnicki {
44*a4b7193dSXu Kuohai int *value;
45*a4b7193dSXu Kuohai __u32 key = 0;
46*a4b7193dSXu Kuohai
47*a4b7193dSXu Kuohai value = bpf_map_lookup_elem(&parser_map, &key);
48*a4b7193dSXu Kuohai if (value && *value)
49*a4b7193dSXu Kuohai return *value;
50*a4b7193dSXu Kuohai
5144d28be2SJakub Sitnicki return skb->len;
5244d28be2SJakub Sitnicki }
5344d28be2SJakub Sitnicki
5444d28be2SJakub Sitnicki SEC("sk_skb/stream_verdict")
prog_stream_verdict(struct __sk_buff * skb)55ae8b8332SCong Wang int prog_stream_verdict(struct __sk_buff *skb)
5644d28be2SJakub Sitnicki {
5744d28be2SJakub Sitnicki unsigned int *count;
5844d28be2SJakub Sitnicki __u32 zero = 0;
5944d28be2SJakub Sitnicki int verdict;
6044d28be2SJakub Sitnicki
6144d28be2SJakub Sitnicki if (test_sockmap)
6244d28be2SJakub Sitnicki verdict = bpf_sk_redirect_map(skb, &sock_map, zero, 0);
6344d28be2SJakub Sitnicki else
6444d28be2SJakub Sitnicki verdict = bpf_sk_redirect_hash(skb, &sock_hash, &zero, 0);
6544d28be2SJakub Sitnicki
6644d28be2SJakub Sitnicki count = bpf_map_lookup_elem(&verdict_map, &verdict);
6744d28be2SJakub Sitnicki if (count)
6844d28be2SJakub Sitnicki (*count)++;
6944d28be2SJakub Sitnicki
7044d28be2SJakub Sitnicki return verdict;
7144d28be2SJakub Sitnicki }
7244d28be2SJakub Sitnicki
7315669e1dSAndrii Nakryiko SEC("sk_skb")
prog_skb_verdict(struct __sk_buff * skb)74d6378af6SCong Wang int prog_skb_verdict(struct __sk_buff *skb)
75d6378af6SCong Wang {
76d6378af6SCong Wang unsigned int *count;
77d6378af6SCong Wang __u32 zero = 0;
78d6378af6SCong Wang int verdict;
79d6378af6SCong Wang
80d6378af6SCong Wang if (test_sockmap)
81d6378af6SCong Wang verdict = bpf_sk_redirect_map(skb, &sock_map, zero,
82d6378af6SCong Wang test_ingress ? BPF_F_INGRESS : 0);
83d6378af6SCong Wang else
84d6378af6SCong Wang verdict = bpf_sk_redirect_hash(skb, &sock_hash, &zero,
85d6378af6SCong Wang test_ingress ? BPF_F_INGRESS : 0);
86d6378af6SCong Wang
87d6378af6SCong Wang count = bpf_map_lookup_elem(&verdict_map, &verdict);
88d6378af6SCong Wang if (count)
89d6378af6SCong Wang (*count)++;
90d6378af6SCong Wang
91d6378af6SCong Wang return verdict;
92d6378af6SCong Wang }
93d6378af6SCong Wang
9444d28be2SJakub Sitnicki SEC("sk_msg")
prog_msg_verdict(struct sk_msg_md * msg)9544d28be2SJakub Sitnicki int prog_msg_verdict(struct sk_msg_md *msg)
9644d28be2SJakub Sitnicki {
9744d28be2SJakub Sitnicki unsigned int *count;
9844d28be2SJakub Sitnicki __u32 zero = 0;
9944d28be2SJakub Sitnicki int verdict;
10044d28be2SJakub Sitnicki
10144d28be2SJakub Sitnicki if (test_sockmap)
10244d28be2SJakub Sitnicki verdict = bpf_msg_redirect_map(msg, &sock_map, zero, 0);
10344d28be2SJakub Sitnicki else
10444d28be2SJakub Sitnicki verdict = bpf_msg_redirect_hash(msg, &sock_hash, &zero, 0);
10544d28be2SJakub Sitnicki
10644d28be2SJakub Sitnicki count = bpf_map_lookup_elem(&verdict_map, &verdict);
10744d28be2SJakub Sitnicki if (count)
10844d28be2SJakub Sitnicki (*count)++;
10944d28be2SJakub Sitnicki
11044d28be2SJakub Sitnicki return verdict;
11144d28be2SJakub Sitnicki }
11244d28be2SJakub Sitnicki
11344d28be2SJakub Sitnicki SEC("sk_reuseport")
prog_reuseport(struct sk_reuseport_md * reuse)11444d28be2SJakub Sitnicki int prog_reuseport(struct sk_reuseport_md *reuse)
11544d28be2SJakub Sitnicki {
11644d28be2SJakub Sitnicki unsigned int *count;
11744d28be2SJakub Sitnicki int err, verdict;
11844d28be2SJakub Sitnicki __u32 zero = 0;
11944d28be2SJakub Sitnicki
12044d28be2SJakub Sitnicki if (test_sockmap)
12144d28be2SJakub Sitnicki err = bpf_sk_select_reuseport(reuse, &sock_map, &zero, 0);
12244d28be2SJakub Sitnicki else
12344d28be2SJakub Sitnicki err = bpf_sk_select_reuseport(reuse, &sock_hash, &zero, 0);
12444d28be2SJakub Sitnicki verdict = err ? SK_DROP : SK_PASS;
12544d28be2SJakub Sitnicki
12644d28be2SJakub Sitnicki count = bpf_map_lookup_elem(&verdict_map, &verdict);
12744d28be2SJakub Sitnicki if (count)
12844d28be2SJakub Sitnicki (*count)++;
12944d28be2SJakub Sitnicki
13044d28be2SJakub Sitnicki return verdict;
13144d28be2SJakub Sitnicki }
13244d28be2SJakub Sitnicki
13344d28be2SJakub Sitnicki char _license[] SEC("license") = "GPL";
134