1 /* SPDX-License-Identifier: GPL-2.0 */
2 /* Copyright (c) 2017-2018 Covalent IO, Inc. http://covalent.io */
6 #include <linux/if_ether.h>
7 #include <linux/if_packet.h>
9 #include <linux/ipv6.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_helpers.h"
16 #include "bpf_endian.h"
18 /* Sockmap sample program connects a client and a backend together
21 * client:X <---> frontend:80 client:X <---> backend:80
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.
27 * The bpf_printk is verbose and prints information as connections
28 * are established and verdicts are decided.
31 #define bpf_printk(fmt, ...) \
33 char ____fmt[] = fmt; \
34 bpf_trace_printk(____fmt, sizeof(____fmt), \
38 struct bpf_map_def
SEC("maps") sock_map
= {
39 .type
= TEST_MAP_TYPE
,
40 .key_size
= sizeof(int),
41 .value_size
= sizeof(int),
45 struct bpf_map_def
SEC("maps") sock_map_txmsg
= {
46 .type
= TEST_MAP_TYPE
,
47 .key_size
= sizeof(int),
48 .value_size
= sizeof(int),
52 struct bpf_map_def
SEC("maps") sock_map_redir
= {
53 .type
= TEST_MAP_TYPE
,
54 .key_size
= sizeof(int),
55 .value_size
= sizeof(int),
59 struct bpf_map_def
SEC("maps") sock_apply_bytes
= {
60 .type
= BPF_MAP_TYPE_ARRAY
,
61 .key_size
= sizeof(int),
62 .value_size
= sizeof(int),
66 struct bpf_map_def
SEC("maps") sock_cork_bytes
= {
67 .type
= BPF_MAP_TYPE_ARRAY
,
68 .key_size
= sizeof(int),
69 .value_size
= sizeof(int),
73 struct bpf_map_def
SEC("maps") sock_pull_bytes
= {
74 .type
= BPF_MAP_TYPE_ARRAY
,
75 .key_size
= sizeof(int),
76 .value_size
= sizeof(int),
80 struct bpf_map_def
SEC("maps") sock_redir_flags
= {
81 .type
= BPF_MAP_TYPE_ARRAY
,
82 .key_size
= sizeof(int),
83 .value_size
= sizeof(int),
87 struct bpf_map_def
SEC("maps") sock_skb_opts
= {
88 .type
= BPF_MAP_TYPE_ARRAY
,
89 .key_size
= sizeof(int),
90 .value_size
= sizeof(int),
95 int bpf_prog1(struct __sk_buff
*skb
)
101 int bpf_prog2(struct __sk_buff
*skb
)
103 __u32 lport
= skb
->local_port
;
104 __u32 rport
= skb
->remote_port
;
105 int len
, *f
, ret
, zero
= 0;
113 len
= (__u32
)skb
->data_end
- (__u32
)skb
->data
;
114 f
= bpf_map_lookup_elem(&sock_skb_opts
, &zero
);
120 bpf_printk("sk_skb2: redirect(%iB) flags=%i\n",
123 return bpf_sk_redirect_map(skb
, &sock_map
, ret
, flags
);
125 return bpf_sk_redirect_hash(skb
, &sock_map
, &ret
, flags
);
131 int bpf_sockmap(struct bpf_sock_ops
*skops
)
134 int op
, err
= 0, index
, key
, ret
;
137 op
= (int) skops
->op
;
140 case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB
:
141 lport
= skops
->local_port
;
142 rport
= skops
->remote_port
;
144 if (lport
== 10000) {
147 err
= bpf_sock_map_update(skops
, &sock_map
, &ret
,
150 err
= bpf_sock_hash_update(skops
, &sock_map
, &ret
,
153 bpf_printk("passive(%i -> %i) map ctx update err: %d\n",
154 lport
, bpf_ntohl(rport
), err
);
157 case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB
:
158 lport
= skops
->local_port
;
159 rport
= skops
->remote_port
;
161 if (bpf_ntohl(rport
) == 10001) {
164 err
= bpf_sock_map_update(skops
, &sock_map
, &ret
,
167 err
= bpf_sock_hash_update(skops
, &sock_map
, &ret
,
170 bpf_printk("active(%i -> %i) map ctx update err: %d\n",
171 lport
, bpf_ntohl(rport
), err
);
182 int bpf_prog4(struct sk_msg_md
*msg
)
184 int *bytes
, zero
= 0, one
= 1;
187 bytes
= bpf_map_lookup_elem(&sock_apply_bytes
, &zero
);
189 bpf_msg_apply_bytes(msg
, *bytes
);
190 bytes
= bpf_map_lookup_elem(&sock_cork_bytes
, &zero
);
192 bpf_msg_cork_bytes(msg
, *bytes
);
193 start
= bpf_map_lookup_elem(&sock_pull_bytes
, &zero
);
194 end
= bpf_map_lookup_elem(&sock_pull_bytes
, &one
);
196 bpf_msg_pull_data(msg
, *start
, *end
, 0);
201 int bpf_prog5(struct sk_msg_md
*msg
)
203 int err1
= -1, err2
= -1, zero
= 0, one
= 1;
204 int *bytes
, *start
, *end
, len1
, len2
;
206 bytes
= bpf_map_lookup_elem(&sock_apply_bytes
, &zero
);
208 err1
= bpf_msg_apply_bytes(msg
, *bytes
);
209 bytes
= bpf_map_lookup_elem(&sock_cork_bytes
, &zero
);
211 err2
= bpf_msg_cork_bytes(msg
, *bytes
);
212 len1
= (__u64
)msg
->data_end
- (__u64
)msg
->data
;
213 start
= bpf_map_lookup_elem(&sock_pull_bytes
, &zero
);
214 end
= bpf_map_lookup_elem(&sock_pull_bytes
, &one
);
218 bpf_printk("sk_msg2: pull(%i:%i)\n",
219 start
? *start
: 0, end
? *end
: 0);
220 err
= bpf_msg_pull_data(msg
, *start
, *end
, 0);
222 bpf_printk("sk_msg2: pull_data err %i\n",
224 len2
= (__u64
)msg
->data_end
- (__u64
)msg
->data
;
225 bpf_printk("sk_msg2: length update %i->%i\n",
228 bpf_printk("sk_msg2: data length %i err1 %i err2 %i\n",
234 int bpf_prog6(struct sk_msg_md
*msg
)
236 int *bytes
, zero
= 0, one
= 1, key
= 0;
237 int *start
, *end
, *f
;
240 bytes
= bpf_map_lookup_elem(&sock_apply_bytes
, &zero
);
242 bpf_msg_apply_bytes(msg
, *bytes
);
243 bytes
= bpf_map_lookup_elem(&sock_cork_bytes
, &zero
);
245 bpf_msg_cork_bytes(msg
, *bytes
);
246 start
= bpf_map_lookup_elem(&sock_pull_bytes
, &zero
);
247 end
= bpf_map_lookup_elem(&sock_pull_bytes
, &one
);
249 bpf_msg_pull_data(msg
, *start
, *end
, 0);
250 f
= bpf_map_lookup_elem(&sock_redir_flags
, &zero
);
256 return bpf_msg_redirect_map(msg
, &sock_map_redir
, key
, flags
);
258 return bpf_msg_redirect_hash(msg
, &sock_map_redir
, &key
, flags
);
263 int bpf_prog7(struct sk_msg_md
*msg
)
265 int err1
= 0, err2
= 0, zero
= 0, one
= 1, key
= 0;
266 int *f
, *bytes
, *start
, *end
, len1
, len2
;
270 bytes
= bpf_map_lookup_elem(&sock_apply_bytes
, &zero
);
272 err1
= bpf_msg_apply_bytes(msg
, *bytes
);
273 bytes
= bpf_map_lookup_elem(&sock_cork_bytes
, &zero
);
275 err2
= bpf_msg_cork_bytes(msg
, *bytes
);
276 len1
= (__u64
)msg
->data_end
- (__u64
)msg
->data
;
277 start
= bpf_map_lookup_elem(&sock_pull_bytes
, &zero
);
278 end
= bpf_map_lookup_elem(&sock_pull_bytes
, &one
);
281 bpf_printk("sk_msg2: pull(%i:%i)\n",
282 start
? *start
: 0, end
? *end
: 0);
283 err
= bpf_msg_pull_data(msg
, *start
, *end
, 0);
285 bpf_printk("sk_msg2: pull_data err %i\n",
287 len2
= (__u64
)msg
->data_end
- (__u64
)msg
->data
;
288 bpf_printk("sk_msg2: length update %i->%i\n",
291 f
= bpf_map_lookup_elem(&sock_redir_flags
, &zero
);
296 bpf_printk("sk_msg3: redirect(%iB) flags=%i err=%i\n",
297 len1
, flags
, err1
? err1
: err2
);
299 err
= bpf_msg_redirect_map(msg
, &sock_map_redir
, key
, flags
);
301 err
= bpf_msg_redirect_hash(msg
, &sock_map_redir
, &key
, flags
);
303 bpf_printk("sk_msg3: err %i\n", err
);
308 int bpf_prog8(struct sk_msg_md
*msg
)
310 void *data_end
= (void *)(long) msg
->data_end
;
311 void *data
= (void *)(long) msg
->data
;
312 int ret
= 0, *bytes
, zero
= 0;
314 bytes
= bpf_map_lookup_elem(&sock_apply_bytes
, &zero
);
316 ret
= bpf_msg_apply_bytes(msg
, *bytes
);
325 int bpf_prog9(struct sk_msg_md
*msg
)
327 void *data_end
= (void *)(long) msg
->data_end
;
328 void *data
= (void *)(long) msg
->data
;
329 int ret
= 0, *bytes
, zero
= 0;
331 bytes
= bpf_map_lookup_elem(&sock_cork_bytes
, &zero
);
333 if (((__u64
)data_end
- (__u64
)data
) >= *bytes
)
335 ret
= bpf_msg_cork_bytes(msg
, *bytes
);
343 int bpf_prog10(struct sk_msg_md
*msg
)
345 int *bytes
, zero
= 0, one
= 1;
348 bytes
= bpf_map_lookup_elem(&sock_apply_bytes
, &zero
);
350 bpf_msg_apply_bytes(msg
, *bytes
);
351 bytes
= bpf_map_lookup_elem(&sock_cork_bytes
, &zero
);
353 bpf_msg_cork_bytes(msg
, *bytes
);
354 start
= bpf_map_lookup_elem(&sock_pull_bytes
, &zero
);
355 end
= bpf_map_lookup_elem(&sock_pull_bytes
, &one
);
357 bpf_msg_pull_data(msg
, *start
, *end
, 0);
362 int _version
SEC("version") = 1;
363 char _license
[] SEC("license") = "GPL";