summaryrefslogtreecommitdiff
path: root/tools/testing/selftests/bpf/progs/test_sockmap_listen.c
blob: 464d35bd57c708a748163d71089ee329a76b56e1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2020 Cloudflare

#include <errno.h>
#include <stdbool.h>
#include <linux/bpf.h>

#include <bpf/bpf_helpers.h>

struct {
	__uint(type, BPF_MAP_TYPE_SOCKMAP);
	__uint(max_entries, 2);
	__type(key, __u32);
	__type(value, __u64);
} sock_map SEC(".maps");

struct {
	__uint(type, BPF_MAP_TYPE_SOCKHASH);
	__uint(max_entries, 2);
	__type(key, __u32);
	__type(value, __u64);
} sock_hash SEC(".maps");

struct {
	__uint(type, BPF_MAP_TYPE_ARRAY);
	__uint(max_entries, 2);
	__type(key, int);
	__type(value, unsigned int);
} verdict_map SEC(".maps");

struct {
	__uint(type, BPF_MAP_TYPE_ARRAY);
	__uint(max_entries, 1);
	__type(key, int);
	__type(value, int);
} parser_map SEC(".maps");

bool test_sockmap = false; /* toggled by user-space */
bool test_ingress = false; /* toggled by user-space */

SEC("sk_skb/stream_parser")
int prog_stream_parser(struct __sk_buff *skb)
{
	int *value;
	__u32 key = 0;

	value = bpf_map_lookup_elem(&parser_map, &key);
	if (value && *value)
		return *value;

	return skb->len;
}

SEC("sk_skb/stream_verdict")
int prog_stream_verdict(struct __sk_buff *skb)
{
	unsigned int *count;
	__u32 zero = 0;
	int verdict;

	if (test_sockmap)
		verdict = bpf_sk_redirect_map(skb, &sock_map, zero, 0);
	else
		verdict = bpf_sk_redirect_hash(skb, &sock_hash, &zero, 0);

	count = bpf_map_lookup_elem(&verdict_map, &verdict);
	if (count)
		(*count)++;

	return verdict;
}

SEC("sk_skb")
int prog_skb_verdict(struct __sk_buff *skb)
{
	unsigned int *count;
	__u32 zero = 0;
	int verdict;

	if (test_sockmap)
		verdict = bpf_sk_redirect_map(skb, &sock_map, zero,
					      test_ingress ? BPF_F_INGRESS : 0);
	else
		verdict = bpf_sk_redirect_hash(skb, &sock_hash, &zero,
					       test_ingress ? BPF_F_INGRESS : 0);

	count = bpf_map_lookup_elem(&verdict_map, &verdict);
	if (count)
		(*count)++;

	return verdict;
}

SEC("sk_msg")
int prog_msg_verdict(struct sk_msg_md *msg)
{
	unsigned int *count;
	__u32 zero = 0;
	int verdict;

	if (test_sockmap)
		verdict = bpf_msg_redirect_map(msg, &sock_map, zero, 0);
	else
		verdict = bpf_msg_redirect_hash(msg, &sock_hash, &zero, 0);

	count = bpf_map_lookup_elem(&verdict_map, &verdict);
	if (count)
		(*count)++;

	return verdict;
}

SEC("sk_reuseport")
int prog_reuseport(struct sk_reuseport_md *reuse)
{
	unsigned int *count;
	int err, verdict;
	__u32 zero = 0;

	if (test_sockmap)
		err = bpf_sk_select_reuseport(reuse, &sock_map, &zero, 0);
	else
		err = bpf_sk_select_reuseport(reuse, &sock_hash, &zero, 0);
	verdict = err ? SK_DROP : SK_PASS;

	count = bpf_map_lookup_elem(&verdict_map, &verdict);
	if (count)
		(*count)++;

	return verdict;
}

char _license[] SEC("license") = "GPL";