1
2
3#include <linux/bpf.h>
4#include <linux/version.h>
5#include "bpf_helpers.h"
6
7struct hmap_elem {
8 volatile int cnt;
9 struct bpf_spin_lock lock;
10 int test_padding;
11};
12
13struct bpf_map_def SEC("maps") hmap = {
14 .type = BPF_MAP_TYPE_HASH,
15 .key_size = sizeof(int),
16 .value_size = sizeof(struct hmap_elem),
17 .max_entries = 1,
18};
19
20BPF_ANNOTATE_KV_PAIR(hmap, int, struct hmap_elem);
21
22
23struct cls_elem {
24 struct bpf_spin_lock lock;
25 volatile int cnt;
26};
27
28struct bpf_map_def SEC("maps") cls_map = {
29 .type = BPF_MAP_TYPE_CGROUP_STORAGE,
30 .key_size = sizeof(struct bpf_cgroup_storage_key),
31 .value_size = sizeof(struct cls_elem),
32};
33
34BPF_ANNOTATE_KV_PAIR(cls_map, struct bpf_cgroup_storage_key,
35 struct cls_elem);
36
37struct bpf_vqueue {
38 struct bpf_spin_lock lock;
39
40 unsigned long long lasttime;
41 int credit;
42 unsigned int rate;
43};
44
45struct bpf_map_def SEC("maps") vqueue = {
46 .type = BPF_MAP_TYPE_ARRAY,
47 .key_size = sizeof(int),
48 .value_size = sizeof(struct bpf_vqueue),
49 .max_entries = 1,
50};
51
52BPF_ANNOTATE_KV_PAIR(vqueue, int, struct bpf_vqueue);
53#define CREDIT_PER_NS(delta, rate) (((delta) * rate) >> 20)
54
55SEC("spin_lock_demo")
56int bpf_sping_lock_test(struct __sk_buff *skb)
57{
58 volatile int credit = 0, max_credit = 100, pkt_len = 64;
59 struct hmap_elem zero = {}, *val;
60 unsigned long long curtime;
61 struct bpf_vqueue *q;
62 struct cls_elem *cls;
63 int key = 0;
64 int err = 0;
65
66 val = bpf_map_lookup_elem(&hmap, &key);
67 if (!val) {
68 bpf_map_update_elem(&hmap, &key, &zero, 0);
69 val = bpf_map_lookup_elem(&hmap, &key);
70 if (!val) {
71 err = 1;
72 goto err;
73 }
74 }
75
76 bpf_spin_lock(&val->lock);
77 if (val->cnt)
78 val->cnt--;
79 else
80 val->cnt++;
81 if (val->cnt != 0 && val->cnt != 1)
82 err = 1;
83 bpf_spin_unlock(&val->lock);
84
85
86 q = bpf_map_lookup_elem(&vqueue, &key);
87 if (!q)
88 goto err;
89 curtime = bpf_ktime_get_ns();
90 bpf_spin_lock(&q->lock);
91 q->credit += CREDIT_PER_NS(curtime - q->lasttime, q->rate);
92 q->lasttime = curtime;
93 if (q->credit > max_credit)
94 q->credit = max_credit;
95 q->credit -= pkt_len;
96 credit = q->credit;
97 bpf_spin_unlock(&q->lock);
98
99
100 cls = bpf_get_local_storage(&cls_map, 0);
101 bpf_spin_lock(&cls->lock);
102 cls->cnt++;
103 bpf_spin_unlock(&cls->lock);
104
105err:
106 return err;
107}
108char _license[] SEC("license") = "GPL";
109