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