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 __u32 type; 15 __u32 max_entries; 16 int *key; 17 struct hmap_elem *value; 18 } hmap SEC(".maps") = { 19 .type = BPF_MAP_TYPE_HASH, 20 .max_entries = 1, 21 }; 22 23 struct cls_elem { 24 struct bpf_spin_lock lock; 25 volatile int cnt; 26 }; 27 28 struct { 29 __u32 type; 30 struct bpf_cgroup_storage_key *key; 31 struct cls_elem *value; 32 } cls_map SEC(".maps") = { 33 .type = BPF_MAP_TYPE_CGROUP_STORAGE, 34 }; 35 36 struct bpf_vqueue { 37 struct bpf_spin_lock lock; 38 /* 4 byte hole */ 39 unsigned long long lasttime; 40 int credit; 41 unsigned int rate; 42 }; 43 44 struct { 45 __u32 type; 46 __u32 max_entries; 47 int *key; 48 struct bpf_vqueue *value; 49 } vqueue SEC(".maps") = { 50 .type = BPF_MAP_TYPE_ARRAY, 51 .max_entries = 1, 52 }; 53 54 #define CREDIT_PER_NS(delta, rate) (((delta) * rate) >> 20) 55 56 SEC("spin_lock_demo") 57 int bpf_sping_lock_test(struct __sk_buff *skb) 58 { 59 volatile int credit = 0, max_credit = 100, pkt_len = 64; 60 struct hmap_elem zero = {}, *val; 61 unsigned long long curtime; 62 struct bpf_vqueue *q; 63 struct cls_elem *cls; 64 int key = 0; 65 int err = 0; 66 67 val = bpf_map_lookup_elem(&hmap, &key); 68 if (!val) { 69 bpf_map_update_elem(&hmap, &key, &zero, 0); 70 val = bpf_map_lookup_elem(&hmap, &key); 71 if (!val) { 72 err = 1; 73 goto err; 74 } 75 } 76 /* spin_lock in hash map run time test */ 77 bpf_spin_lock(&val->lock); 78 if (val->cnt) 79 val->cnt--; 80 else 81 val->cnt++; 82 if (val->cnt != 0 && val->cnt != 1) 83 err = 1; 84 bpf_spin_unlock(&val->lock); 85 86 /* spin_lock in array. virtual queue demo */ 87 q = bpf_map_lookup_elem(&vqueue, &key); 88 if (!q) 89 goto err; 90 curtime = bpf_ktime_get_ns(); 91 bpf_spin_lock(&q->lock); 92 q->credit += CREDIT_PER_NS(curtime - q->lasttime, q->rate); 93 q->lasttime = curtime; 94 if (q->credit > max_credit) 95 q->credit = max_credit; 96 q->credit -= pkt_len; 97 credit = q->credit; 98 bpf_spin_unlock(&q->lock); 99 100 /* spin_lock in cgroup local storage */ 101 cls = bpf_get_local_storage(&cls_map, 0); 102 bpf_spin_lock(&cls->lock); 103 cls->cnt++; 104 bpf_spin_unlock(&cls->lock); 105 106 err: 107 return err; 108 } 109 char _license[] SEC("license") = "GPL"; 110