xref: /linux/tools/testing/selftests/bpf/progs/test_sockmap_kern.h (revision 05ee19c18c2bb3dea69e29219017367c4a77e65a)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /* Copyright (c) 2017-2018 Covalent IO, Inc. http://covalent.io */
3 #include <stddef.h>
4 #include <string.h>
5 #include <linux/bpf.h>
6 #include <linux/if_ether.h>
7 #include <linux/if_packet.h>
8 #include <linux/ip.h>
9 #include <linux/ipv6.h>
10 #include <linux/in.h>
11 #include <linux/udp.h>
12 #include <linux/tcp.h>
13 #include <linux/pkt_cls.h>
14 #include <sys/socket.h>
15 #include <bpf/bpf_helpers.h>
16 #include <bpf/bpf_endian.h>
17 
18 /* Sockmap sample program connects a client and a backend together
19  * using cgroups.
20  *
21  *    client:X <---> frontend:80 client:X <---> backend:80
22  *
23  * For simplicity we hard code values here and bind 1:1. The hard
24  * coded values are part of the setup in sockmap.sh script that
25  * is associated with this BPF program.
26  *
27  * The bpf_printk is verbose and prints information as connections
28  * are established and verdicts are decided.
29  */
30 
31 struct {
32 	__uint(type, TEST_MAP_TYPE);
33 	__uint(max_entries, 20);
34 	__uint(key_size, sizeof(int));
35 	__uint(value_size, sizeof(int));
36 } sock_map SEC(".maps");
37 
38 struct {
39 	__uint(type, TEST_MAP_TYPE);
40 	__uint(max_entries, 20);
41 	__uint(key_size, sizeof(int));
42 	__uint(value_size, sizeof(int));
43 } sock_map_txmsg SEC(".maps");
44 
45 struct {
46 	__uint(type, TEST_MAP_TYPE);
47 	__uint(max_entries, 20);
48 	__uint(key_size, sizeof(int));
49 	__uint(value_size, sizeof(int));
50 } sock_map_redir SEC(".maps");
51 
52 struct {
53 	__uint(type, BPF_MAP_TYPE_ARRAY);
54 	__uint(max_entries, 1);
55 	__type(key, int);
56 	__type(value, int);
57 } sock_apply_bytes SEC(".maps");
58 
59 struct {
60 	__uint(type, BPF_MAP_TYPE_ARRAY);
61 	__uint(max_entries, 1);
62 	__type(key, int);
63 	__type(value, int);
64 } sock_cork_bytes SEC(".maps");
65 
66 struct {
67 	__uint(type, BPF_MAP_TYPE_ARRAY);
68 	__uint(max_entries, 6);
69 	__type(key, int);
70 	__type(value, int);
71 } sock_bytes SEC(".maps");
72 
73 struct {
74 	__uint(type, BPF_MAP_TYPE_ARRAY);
75 	__uint(max_entries, 1);
76 	__type(key, int);
77 	__type(value, int);
78 } sock_redir_flags SEC(".maps");
79 
80 struct {
81 	__uint(type, BPF_MAP_TYPE_ARRAY);
82 	__uint(max_entries, 1);
83 	__type(key, int);
84 	__type(value, int);
85 } sock_skb_opts SEC(".maps");
86 
87 SEC("sk_skb1")
88 int bpf_prog1(struct __sk_buff *skb)
89 {
90 	return skb->len;
91 }
92 
93 SEC("sk_skb2")
94 int bpf_prog2(struct __sk_buff *skb)
95 {
96 	__u32 lport = skb->local_port;
97 	__u32 rport = skb->remote_port;
98 	int len, *f, ret, zero = 0;
99 	__u64 flags = 0;
100 
101 	if (lport == 10000)
102 		ret = 10;
103 	else
104 		ret = 1;
105 
106 	len = (__u32)skb->data_end - (__u32)skb->data;
107 	f = bpf_map_lookup_elem(&sock_skb_opts, &zero);
108 	if (f && *f) {
109 		ret = 3;
110 		flags = *f;
111 	}
112 
113 #ifdef SOCKMAP
114 	return bpf_sk_redirect_map(skb, &sock_map, ret, flags);
115 #else
116 	return bpf_sk_redirect_hash(skb, &sock_map, &ret, flags);
117 #endif
118 
119 }
120 
121 SEC("sockops")
122 int bpf_sockmap(struct bpf_sock_ops *skops)
123 {
124 	__u32 lport, rport;
125 	int op, err = 0, index, key, ret;
126 
127 
128 	op = (int) skops->op;
129 
130 	switch (op) {
131 	case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB:
132 		lport = skops->local_port;
133 		rport = skops->remote_port;
134 
135 		if (lport == 10000) {
136 			ret = 1;
137 #ifdef SOCKMAP
138 			err = bpf_sock_map_update(skops, &sock_map, &ret,
139 						  BPF_NOEXIST);
140 #else
141 			err = bpf_sock_hash_update(skops, &sock_map, &ret,
142 						   BPF_NOEXIST);
143 #endif
144 		}
145 		break;
146 	case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB:
147 		lport = skops->local_port;
148 		rport = skops->remote_port;
149 
150 		if (bpf_ntohl(rport) == 10001) {
151 			ret = 10;
152 #ifdef SOCKMAP
153 			err = bpf_sock_map_update(skops, &sock_map, &ret,
154 						  BPF_NOEXIST);
155 #else
156 			err = bpf_sock_hash_update(skops, &sock_map, &ret,
157 						   BPF_NOEXIST);
158 #endif
159 		}
160 		break;
161 	default:
162 		break;
163 	}
164 
165 	return 0;
166 }
167 
168 SEC("sk_msg1")
169 int bpf_prog4(struct sk_msg_md *msg)
170 {
171 	int *bytes, zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5;
172 	int *start, *end, *start_push, *end_push, *start_pop, *pop;
173 
174 	bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
175 	if (bytes)
176 		bpf_msg_apply_bytes(msg, *bytes);
177 	bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
178 	if (bytes)
179 		bpf_msg_cork_bytes(msg, *bytes);
180 	start = bpf_map_lookup_elem(&sock_bytes, &zero);
181 	end = bpf_map_lookup_elem(&sock_bytes, &one);
182 	if (start && end)
183 		bpf_msg_pull_data(msg, *start, *end, 0);
184 	start_push = bpf_map_lookup_elem(&sock_bytes, &two);
185 	end_push = bpf_map_lookup_elem(&sock_bytes, &three);
186 	if (start_push && end_push)
187 		bpf_msg_push_data(msg, *start_push, *end_push, 0);
188 	start_pop = bpf_map_lookup_elem(&sock_bytes, &four);
189 	pop = bpf_map_lookup_elem(&sock_bytes, &five);
190 	if (start_pop && pop)
191 		bpf_msg_pop_data(msg, *start_pop, *pop, 0);
192 	return SK_PASS;
193 }
194 
195 SEC("sk_msg2")
196 int bpf_prog6(struct sk_msg_md *msg)
197 {
198 	int zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5, key = 0;
199 	int *bytes, *start, *end, *start_push, *end_push, *start_pop, *pop, *f;
200 	__u64 flags = 0;
201 
202 	bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
203 	if (bytes)
204 		bpf_msg_apply_bytes(msg, *bytes);
205 	bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
206 	if (bytes)
207 		bpf_msg_cork_bytes(msg, *bytes);
208 
209 	start = bpf_map_lookup_elem(&sock_bytes, &zero);
210 	end = bpf_map_lookup_elem(&sock_bytes, &one);
211 	if (start && end)
212 		bpf_msg_pull_data(msg, *start, *end, 0);
213 
214 	start_push = bpf_map_lookup_elem(&sock_bytes, &two);
215 	end_push = bpf_map_lookup_elem(&sock_bytes, &three);
216 	if (start_push && end_push)
217 		bpf_msg_push_data(msg, *start_push, *end_push, 0);
218 
219 	start_pop = bpf_map_lookup_elem(&sock_bytes, &four);
220 	pop = bpf_map_lookup_elem(&sock_bytes, &five);
221 	if (start_pop && pop)
222 		bpf_msg_pop_data(msg, *start_pop, *pop, 0);
223 
224 	f = bpf_map_lookup_elem(&sock_redir_flags, &zero);
225 	if (f && *f) {
226 		key = 2;
227 		flags = *f;
228 	}
229 #ifdef SOCKMAP
230 	return bpf_msg_redirect_map(msg, &sock_map_redir, key, flags);
231 #else
232 	return bpf_msg_redirect_hash(msg, &sock_map_redir, &key, flags);
233 #endif
234 }
235 
236 SEC("sk_msg3")
237 int bpf_prog8(struct sk_msg_md *msg)
238 {
239 	void *data_end = (void *)(long) msg->data_end;
240 	void *data = (void *)(long) msg->data;
241 	int ret = 0, *bytes, zero = 0;
242 
243 	bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
244 	if (bytes) {
245 		ret = bpf_msg_apply_bytes(msg, *bytes);
246 		if (ret)
247 			return SK_DROP;
248 	} else {
249 		return SK_DROP;
250 	}
251 	return SK_PASS;
252 }
253 SEC("sk_msg4")
254 int bpf_prog9(struct sk_msg_md *msg)
255 {
256 	void *data_end = (void *)(long) msg->data_end;
257 	void *data = (void *)(long) msg->data;
258 	int ret = 0, *bytes, zero = 0;
259 
260 	bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
261 	if (bytes) {
262 		if (((__u64)data_end - (__u64)data) >= *bytes)
263 			return SK_PASS;
264 		ret = bpf_msg_cork_bytes(msg, *bytes);
265 		if (ret)
266 			return SK_DROP;
267 	}
268 	return SK_PASS;
269 }
270 
271 SEC("sk_msg5")
272 int bpf_prog10(struct sk_msg_md *msg)
273 {
274 	int *bytes, *start, *end, *start_push, *end_push, *start_pop, *pop;
275 	int zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5;
276 
277 	bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
278 	if (bytes)
279 		bpf_msg_apply_bytes(msg, *bytes);
280 	bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
281 	if (bytes)
282 		bpf_msg_cork_bytes(msg, *bytes);
283 	start = bpf_map_lookup_elem(&sock_bytes, &zero);
284 	end = bpf_map_lookup_elem(&sock_bytes, &one);
285 	if (start && end)
286 		bpf_msg_pull_data(msg, *start, *end, 0);
287 	start_push = bpf_map_lookup_elem(&sock_bytes, &two);
288 	end_push = bpf_map_lookup_elem(&sock_bytes, &three);
289 	if (start_push && end_push)
290 		bpf_msg_push_data(msg, *start_push, *end_push, 0);
291 	start_pop = bpf_map_lookup_elem(&sock_bytes, &four);
292 	pop = bpf_map_lookup_elem(&sock_bytes, &five);
293 	if (start_pop && pop)
294 		bpf_msg_pop_data(msg, *start_pop, *pop, 0);
295 	return SK_DROP;
296 }
297 
298 int _version SEC("version") = 1;
299 char _license[] SEC("license") = "GPL";
300