PCI: pnv_php: Add missing of_node_put()
[linux-2.6-block.git] / samples / sockmap / sockmap_kern.c
CommitLineData
69e8cc13
JF
1/* Copyright (c) 2017 Covalent IO, Inc. http://covalent.io
2 *
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of version 2 of the GNU General Public
5 * License as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful, but
8 * WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * General Public License for more details.
11 */
12#include <uapi/linux/bpf.h>
13#include <uapi/linux/if_ether.h>
14#include <uapi/linux/if_packet.h>
15#include <uapi/linux/ip.h>
16#include "../../tools/testing/selftests/bpf/bpf_helpers.h"
17#include "../../tools/testing/selftests/bpf/bpf_endian.h"
18
19/* Sockmap sample program connects a client and a backend together
20 * using cgroups.
21 *
22 * client:X <---> frontend:80 client:X <---> backend:80
23 *
24 * For simplicity we hard code values here and bind 1:1. The hard
25 * coded values are part of the setup in sockmap.sh script that
26 * is associated with this BPF program.
27 *
28 * The bpf_printk is verbose and prints information as connections
29 * are established and verdicts are decided.
30 */
31
32#define bpf_printk(fmt, ...) \
33({ \
34 char ____fmt[] = fmt; \
35 bpf_trace_printk(____fmt, sizeof(____fmt), \
36 ##__VA_ARGS__); \
37})
38
39struct bpf_map_def SEC("maps") sock_map = {
40 .type = BPF_MAP_TYPE_SOCKMAP,
41 .key_size = sizeof(int),
42 .value_size = sizeof(int),
43 .max_entries = 20,
44};
45
4c4c3c27
JF
46struct bpf_map_def SEC("maps") sock_map_txmsg = {
47 .type = BPF_MAP_TYPE_SOCKMAP,
48 .key_size = sizeof(int),
49 .value_size = sizeof(int),
50 .max_entries = 20,
51};
52
53struct bpf_map_def SEC("maps") sock_map_redir = {
54 .type = BPF_MAP_TYPE_SOCKMAP,
55 .key_size = sizeof(int),
56 .value_size = sizeof(int),
2596f64c 57 .max_entries = 20,
4c4c3c27
JF
58};
59
1c16c312
JF
60struct bpf_map_def SEC("maps") sock_apply_bytes = {
61 .type = BPF_MAP_TYPE_ARRAY,
62 .key_size = sizeof(int),
63 .value_size = sizeof(int),
64 .max_entries = 1
65};
66
468b3fde
JF
67struct bpf_map_def SEC("maps") sock_cork_bytes = {
68 .type = BPF_MAP_TYPE_ARRAY,
69 .key_size = sizeof(int),
70 .value_size = sizeof(int),
71 .max_entries = 1
72};
73
0dcbbf67
JF
74struct bpf_map_def SEC("maps") sock_pull_bytes = {
75 .type = BPF_MAP_TYPE_ARRAY,
76 .key_size = sizeof(int),
77 .value_size = sizeof(int),
78 .max_entries = 2
79};
80
2596f64c
JF
81struct bpf_map_def SEC("maps") sock_redir_flags = {
82 .type = BPF_MAP_TYPE_ARRAY,
83 .key_size = sizeof(int),
84 .value_size = sizeof(int),
85 .max_entries = 1
86};
87
2e3f6c5f
JF
88struct bpf_map_def SEC("maps") sock_skb_opts = {
89 .type = BPF_MAP_TYPE_ARRAY,
90 .key_size = sizeof(int),
91 .value_size = sizeof(int),
92 .max_entries = 1
93};
0dcbbf67 94
69e8cc13
JF
95SEC("sk_skb1")
96int bpf_prog1(struct __sk_buff *skb)
97{
98 return skb->len;
99}
100
101SEC("sk_skb2")
102int bpf_prog2(struct __sk_buff *skb)
103{
104 __u32 lport = skb->local_port;
105 __u32 rport = skb->remote_port;
2e3f6c5f
JF
106 int len, *f, ret, zero = 0;
107 __u64 flags = 0;
69e8cc13
JF
108
109 if (lport == 10000)
110 ret = 10;
111 else
112 ret = 1;
113
2e3f6c5f
JF
114 len = (__u32)skb->data_end - (__u32)skb->data;
115 f = bpf_map_lookup_elem(&sock_skb_opts, &zero);
116 if (f && *f) {
117 ret = 3;
118 flags = *f;
119 }
120
121 bpf_printk("sk_skb2: redirect(%iB) flags=%i\n",
122 len, flags);
123 return bpf_sk_redirect_map(skb, &sock_map, ret, flags);
69e8cc13
JF
124}
125
126SEC("sockops")
127int bpf_sockmap(struct bpf_sock_ops *skops)
128{
129 __u32 lport, rport;
130 int op, err = 0, index, key, ret;
131
132
133 op = (int) skops->op;
134
135 switch (op) {
136 case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB:
137 lport = skops->local_port;
138 rport = skops->remote_port;
139
140 if (lport == 10000) {
141 ret = 1;
142 err = bpf_sock_map_update(skops, &sock_map, &ret,
464bc0fd 143 BPF_NOEXIST);
69e8cc13
JF
144 bpf_printk("passive(%i -> %i) map ctx update err: %d\n",
145 lport, bpf_ntohl(rport), err);
146 }
147 break;
148 case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB:
149 lport = skops->local_port;
150 rport = skops->remote_port;
151
152 if (bpf_ntohl(rport) == 10001) {
153 ret = 10;
154 err = bpf_sock_map_update(skops, &sock_map, &ret,
464bc0fd 155 BPF_NOEXIST);
69e8cc13
JF
156 bpf_printk("active(%i -> %i) map ctx update err: %d\n",
157 lport, bpf_ntohl(rport), err);
158 }
159 break;
160 default:
161 break;
162 }
163
164 return 0;
165}
4c4c3c27
JF
166
167SEC("sk_msg1")
168int bpf_prog4(struct sk_msg_md *msg)
169{
0dcbbf67
JF
170 int *bytes, zero = 0, one = 1;
171 int *start, *end;
1c16c312
JF
172
173 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
174 if (bytes)
175 bpf_msg_apply_bytes(msg, *bytes);
468b3fde
JF
176 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
177 if (bytes)
178 bpf_msg_cork_bytes(msg, *bytes);
0dcbbf67
JF
179 start = bpf_map_lookup_elem(&sock_pull_bytes, &zero);
180 end = bpf_map_lookup_elem(&sock_pull_bytes, &one);
181 if (start && end)
182 bpf_msg_pull_data(msg, *start, *end, 0);
4c4c3c27
JF
183 return SK_PASS;
184}
185
186SEC("sk_msg2")
187int bpf_prog5(struct sk_msg_md *msg)
188{
0dcbbf67
JF
189 int err1 = -1, err2 = -1, zero = 0, one = 1;
190 int *bytes, *start, *end, len1, len2;
4c4c3c27 191
1c16c312
JF
192 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
193 if (bytes)
468b3fde
JF
194 err1 = bpf_msg_apply_bytes(msg, *bytes);
195 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
196 if (bytes)
197 err2 = bpf_msg_cork_bytes(msg, *bytes);
0dcbbf67
JF
198 len1 = (__u64)msg->data_end - (__u64)msg->data;
199 start = bpf_map_lookup_elem(&sock_pull_bytes, &zero);
200 end = bpf_map_lookup_elem(&sock_pull_bytes, &one);
201 if (start && end) {
202 int err;
203
204 bpf_printk("sk_msg2: pull(%i:%i)\n",
205 start ? *start : 0, end ? *end : 0);
206 err = bpf_msg_pull_data(msg, *start, *end, 0);
207 if (err)
208 bpf_printk("sk_msg2: pull_data err %i\n",
209 err);
210 len2 = (__u64)msg->data_end - (__u64)msg->data;
211 bpf_printk("sk_msg2: length update %i->%i\n",
212 len1, len2);
213 }
468b3fde 214 bpf_printk("sk_msg2: data length %i err1 %i err2 %i\n",
0dcbbf67 215 len1, err1, err2);
4c4c3c27
JF
216 return SK_PASS;
217}
218
219SEC("sk_msg3")
220int bpf_prog6(struct sk_msg_md *msg)
221{
2596f64c
JF
222 int *bytes, zero = 0, one = 1, key = 0;
223 int *start, *end, *f;
224 __u64 flags = 0;
4c4c3c27 225
1c16c312
JF
226 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
227 if (bytes)
228 bpf_msg_apply_bytes(msg, *bytes);
468b3fde
JF
229 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
230 if (bytes)
231 bpf_msg_cork_bytes(msg, *bytes);
0dcbbf67
JF
232 start = bpf_map_lookup_elem(&sock_pull_bytes, &zero);
233 end = bpf_map_lookup_elem(&sock_pull_bytes, &one);
234 if (start && end)
235 bpf_msg_pull_data(msg, *start, *end, 0);
2596f64c
JF
236 f = bpf_map_lookup_elem(&sock_redir_flags, &zero);
237 if (f && *f) {
238 key = 2;
239 flags = *f;
240 }
241 return bpf_msg_redirect_map(msg, &sock_map_redir, key, flags);
4c4c3c27
JF
242}
243
244SEC("sk_msg4")
245int bpf_prog7(struct sk_msg_md *msg)
246{
2596f64c
JF
247 int err1 = 0, err2 = 0, zero = 0, one = 1, key = 0;
248 int *f, *bytes, *start, *end, len1, len2;
249 __u64 flags = 0;
1c16c312 250
2596f64c 251 int err;
1c16c312
JF
252 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
253 if (bytes)
468b3fde
JF
254 err1 = bpf_msg_apply_bytes(msg, *bytes);
255 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
256 if (bytes)
257 err2 = bpf_msg_cork_bytes(msg, *bytes);
0dcbbf67
JF
258 len1 = (__u64)msg->data_end - (__u64)msg->data;
259 start = bpf_map_lookup_elem(&sock_pull_bytes, &zero);
260 end = bpf_map_lookup_elem(&sock_pull_bytes, &one);
261 if (start && end) {
0dcbbf67
JF
262
263 bpf_printk("sk_msg2: pull(%i:%i)\n",
264 start ? *start : 0, end ? *end : 0);
265 err = bpf_msg_pull_data(msg, *start, *end, 0);
266 if (err)
267 bpf_printk("sk_msg2: pull_data err %i\n",
268 err);
269 len2 = (__u64)msg->data_end - (__u64)msg->data;
270 bpf_printk("sk_msg2: length update %i->%i\n",
271 len1, len2);
272 }
2596f64c
JF
273 f = bpf_map_lookup_elem(&sock_redir_flags, &zero);
274 if (f && *f) {
275 key = 2;
276 flags = *f;
277 }
278 bpf_printk("sk_msg3: redirect(%iB) flags=%i err=%i\n",
279 len1, flags, err1 ? err1 : err2);
280 err = bpf_msg_redirect_map(msg, &sock_map_redir, key, flags);
281 bpf_printk("sk_msg3: err %i\n", err);
282 return err;
1c16c312 283}
4c4c3c27 284
1c16c312
JF
285SEC("sk_msg5")
286int bpf_prog8(struct sk_msg_md *msg)
287{
288 void *data_end = (void *)(long) msg->data_end;
289 void *data = (void *)(long) msg->data;
290 int ret = 0, *bytes, zero = 0;
291
292 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
293 if (bytes) {
294 ret = bpf_msg_apply_bytes(msg, *bytes);
295 if (ret)
296 return SK_DROP;
297 } else {
298 return SK_DROP;
299 }
300 return SK_PASS;
4c4c3c27 301}
468b3fde
JF
302SEC("sk_msg6")
303int bpf_prog9(struct sk_msg_md *msg)
304{
305 void *data_end = (void *)(long) msg->data_end;
306 void *data = (void *)(long) msg->data;
307 int ret = 0, *bytes, zero = 0;
308
309 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
310 if (bytes) {
311 if (((__u64)data_end - (__u64)data) >= *bytes)
312 return SK_PASS;
313 ret = bpf_msg_cork_bytes(msg, *bytes);
314 if (ret)
315 return SK_DROP;
316 }
317 return SK_PASS;
318}
4c4c3c27 319
e6373ce7
JF
320SEC("sk_msg7")
321int bpf_prog10(struct sk_msg_md *msg)
322{
0dcbbf67
JF
323 int *bytes, zero = 0, one = 1;
324 int *start, *end;
e6373ce7
JF
325
326 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
327 if (bytes)
328 bpf_msg_apply_bytes(msg, *bytes);
329 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
330 if (bytes)
331 bpf_msg_cork_bytes(msg, *bytes);
0dcbbf67
JF
332 start = bpf_map_lookup_elem(&sock_pull_bytes, &zero);
333 end = bpf_map_lookup_elem(&sock_pull_bytes, &one);
334 if (start && end)
335 bpf_msg_pull_data(msg, *start, *end, 0);
336
e6373ce7
JF
337 return SK_DROP;
338}
339
340
69e8cc13 341char _license[] SEC("license") = "GPL";