Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / tools / testing / selftests / bpf / progs / test_spin_lock.c
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2019 Facebook
3 #include <linux/bpf.h>
4 #include <linux/version.h>
5 #include "bpf_helpers.h"
6
7 struct hmap_elem {
8         volatile int cnt;
9         struct bpf_spin_lock lock;
10         int test_padding;
11 };
12
13 struct {
14         __uint(type, BPF_MAP_TYPE_HASH);
15         __uint(max_entries, 1);
16         __type(key, int);
17         __type(value, struct hmap_elem);
18 } hmap SEC(".maps");
19
20 struct cls_elem {
21         struct bpf_spin_lock lock;
22         volatile int cnt;
23 };
24
25 struct {
26         __uint(type, BPF_MAP_TYPE_CGROUP_STORAGE);
27         __type(key, struct bpf_cgroup_storage_key);
28         __type(value, struct cls_elem);
29 } cls_map SEC(".maps");
30
31 struct bpf_vqueue {
32         struct bpf_spin_lock lock;
33         /* 4 byte hole */
34         unsigned long long lasttime;
35         int credit;
36         unsigned int rate;
37 };
38
39 struct {
40         __uint(type, BPF_MAP_TYPE_ARRAY);
41         __uint(max_entries, 1);
42         __type(key, int);
43         __type(value, struct bpf_vqueue);
44 } vqueue SEC(".maps");
45
46 #define CREDIT_PER_NS(delta, rate) (((delta) * rate) >> 20)
47
48 SEC("spin_lock_demo")
49 int bpf_sping_lock_test(struct __sk_buff *skb)
50 {
51         volatile int credit = 0, max_credit = 100, pkt_len = 64;
52         struct hmap_elem zero = {}, *val;
53         unsigned long long curtime;
54         struct bpf_vqueue *q;
55         struct cls_elem *cls;
56         int key = 0;
57         int err = 0;
58
59         val = bpf_map_lookup_elem(&hmap, &key);
60         if (!val) {
61                 bpf_map_update_elem(&hmap, &key, &zero, 0);
62                 val = bpf_map_lookup_elem(&hmap, &key);
63                 if (!val) {
64                         err = 1;
65                         goto err;
66                 }
67         }
68         /* spin_lock in hash map run time test */
69         bpf_spin_lock(&val->lock);
70         if (val->cnt)
71                 val->cnt--;
72         else
73                 val->cnt++;
74         if (val->cnt != 0 && val->cnt != 1)
75                 err = 1;
76         bpf_spin_unlock(&val->lock);
77
78         /* spin_lock in array. virtual queue demo */
79         q = bpf_map_lookup_elem(&vqueue, &key);
80         if (!q)
81                 goto err;
82         curtime = bpf_ktime_get_ns();
83         bpf_spin_lock(&q->lock);
84         q->credit += CREDIT_PER_NS(curtime - q->lasttime, q->rate);
85         q->lasttime = curtime;
86         if (q->credit > max_credit)
87                 q->credit = max_credit;
88         q->credit -= pkt_len;
89         credit = q->credit;
90         bpf_spin_unlock(&q->lock);
91
92         /* spin_lock in cgroup local storage */
93         cls = bpf_get_local_storage(&cls_map, 0);
94         bpf_spin_lock(&cls->lock);
95         cls->cnt++;
96         bpf_spin_unlock(&cls->lock);
97
98 err:
99         return err;
100 }
101 char _license[] SEC("license") = "GPL";