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/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("tc") 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"; 102