0001
0002
0003 #include <linux/bpf.h>
0004 #include <linux/version.h>
0005 #include <bpf/bpf_helpers.h>
0006
0007 struct hmap_elem {
0008 volatile int cnt;
0009 struct bpf_spin_lock lock;
0010 int test_padding;
0011 };
0012
0013 struct {
0014 __uint(type, BPF_MAP_TYPE_HASH);
0015 __uint(max_entries, 1);
0016 __type(key, int);
0017 __type(value, struct hmap_elem);
0018 } hmap SEC(".maps");
0019
0020 struct cls_elem {
0021 struct bpf_spin_lock lock;
0022 volatile int cnt;
0023 };
0024
0025 struct {
0026 __uint(type, BPF_MAP_TYPE_CGROUP_STORAGE);
0027 __type(key, struct bpf_cgroup_storage_key);
0028 __type(value, struct cls_elem);
0029 } cls_map SEC(".maps");
0030
0031 struct bpf_vqueue {
0032 struct bpf_spin_lock lock;
0033
0034 unsigned long long lasttime;
0035 int credit;
0036 unsigned int rate;
0037 };
0038
0039 struct {
0040 __uint(type, BPF_MAP_TYPE_ARRAY);
0041 __uint(max_entries, 1);
0042 __type(key, int);
0043 __type(value, struct bpf_vqueue);
0044 } vqueue SEC(".maps");
0045
0046 #define CREDIT_PER_NS(delta, rate) (((delta) * rate) >> 20)
0047
0048 SEC("tc")
0049 int bpf_sping_lock_test(struct __sk_buff *skb)
0050 {
0051 volatile int credit = 0, max_credit = 100, pkt_len = 64;
0052 struct hmap_elem zero = {}, *val;
0053 unsigned long long curtime;
0054 struct bpf_vqueue *q;
0055 struct cls_elem *cls;
0056 int key = 0;
0057 int err = 0;
0058
0059 val = bpf_map_lookup_elem(&hmap, &key);
0060 if (!val) {
0061 bpf_map_update_elem(&hmap, &key, &zero, 0);
0062 val = bpf_map_lookup_elem(&hmap, &key);
0063 if (!val) {
0064 err = 1;
0065 goto err;
0066 }
0067 }
0068
0069 bpf_spin_lock(&val->lock);
0070 if (val->cnt)
0071 val->cnt--;
0072 else
0073 val->cnt++;
0074 if (val->cnt != 0 && val->cnt != 1)
0075 err = 1;
0076 bpf_spin_unlock(&val->lock);
0077
0078
0079 q = bpf_map_lookup_elem(&vqueue, &key);
0080 if (!q)
0081 goto err;
0082 curtime = bpf_ktime_get_ns();
0083 bpf_spin_lock(&q->lock);
0084 q->credit += CREDIT_PER_NS(curtime - q->lasttime, q->rate);
0085 q->lasttime = curtime;
0086 if (q->credit > max_credit)
0087 q->credit = max_credit;
0088 q->credit -= pkt_len;
0089 credit = q->credit;
0090 bpf_spin_unlock(&q->lock);
0091
0092
0093 cls = bpf_get_local_storage(&cls_map, 0);
0094 bpf_spin_lock(&cls->lock);
0095 cls->cnt++;
0096 bpf_spin_unlock(&cls->lock);
0097
0098 err:
0099 return err;
0100 }
0101 char _license[] SEC("license") = "GPL";