linux/tools/testing/selftests/bpf/progs/test_spin_lock.c
<<
>>
Prefs
   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
   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        /* 4 byte hole */
  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        /* spin_lock in hash map run time test */
  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        /* spin_lock in array. virtual queue demo */
  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        /* spin_lock in cgroup local storage */
 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