170 lines · c
1// SPDX-License-Identifier: GPL-2.02// Copyright (c) 2019 Facebook3#include <linux/bpf.h>4#include <linux/version.h>5#include <bpf/bpf_helpers.h>6#include "bpf_misc.h"7 8struct hmap_elem {9 volatile int cnt;10 struct bpf_spin_lock lock;11 int test_padding;12};13 14struct {15 __uint(type, BPF_MAP_TYPE_HASH);16 __uint(max_entries, 1);17 __type(key, int);18 __type(value, struct hmap_elem);19} hmap SEC(".maps");20 21struct cls_elem {22 struct bpf_spin_lock lock;23 volatile int cnt;24};25 26struct {27 __uint(type, BPF_MAP_TYPE_CGROUP_STORAGE);28 __type(key, struct bpf_cgroup_storage_key);29 __type(value, struct cls_elem);30} cls_map SEC(".maps");31 32struct bpf_vqueue {33 struct bpf_spin_lock lock;34 /* 4 byte hole */35 unsigned long long lasttime;36 int credit;37 unsigned int rate;38};39 40struct {41 __uint(type, BPF_MAP_TYPE_ARRAY);42 __uint(max_entries, 1);43 __type(key, int);44 __type(value, struct bpf_vqueue);45} vqueue SEC(".maps");46 47#define CREDIT_PER_NS(delta, rate) (((delta) * rate) >> 20)48 49SEC("cgroup_skb/ingress")50int bpf_spin_lock_test(struct __sk_buff *skb)51{52 volatile int credit = 0, max_credit = 100, pkt_len = 64;53 struct hmap_elem zero = {}, *val;54 unsigned long long curtime;55 struct bpf_vqueue *q;56 struct cls_elem *cls;57 int key = 0;58 int err = 0;59 60 val = bpf_map_lookup_elem(&hmap, &key);61 if (!val) {62 bpf_map_update_elem(&hmap, &key, &zero, 0);63 val = bpf_map_lookup_elem(&hmap, &key);64 if (!val) {65 err = 1;66 goto err;67 }68 }69 /* spin_lock in hash map run time test */70 bpf_spin_lock(&val->lock);71 if (val->cnt)72 val->cnt--;73 else74 val->cnt++;75 if (val->cnt != 0 && val->cnt != 1)76 err = 1;77 bpf_spin_unlock(&val->lock);78 79 /* spin_lock in array. virtual queue demo */80 q = bpf_map_lookup_elem(&vqueue, &key);81 if (!q)82 goto err;83 curtime = bpf_ktime_get_ns();84 bpf_spin_lock(&q->lock);85 q->credit += CREDIT_PER_NS(curtime - q->lasttime, q->rate);86 q->lasttime = curtime;87 if (q->credit > max_credit)88 q->credit = max_credit;89 q->credit -= pkt_len;90 credit = q->credit;91 bpf_spin_unlock(&q->lock);92 93 __sink(credit);94 95 /* spin_lock in cgroup local storage */96 cls = bpf_get_local_storage(&cls_map, 0);97 bpf_spin_lock(&cls->lock);98 cls->cnt++;99 bpf_spin_unlock(&cls->lock);100 101err:102 return err;103}104 105struct bpf_spin_lock lockA __hidden SEC(".data.A");106 107__noinline108static int static_subprog(struct __sk_buff *ctx)109{110 volatile int ret = 0;111 112 if (ctx->protocol)113 return ret;114 return ret + ctx->len;115}116 117__noinline118static int static_subprog_lock(struct __sk_buff *ctx)119{120 volatile int ret = 0;121 122 ret = static_subprog(ctx);123 bpf_spin_lock(&lockA);124 return ret + ctx->len;125}126 127__noinline128static int static_subprog_unlock(struct __sk_buff *ctx)129{130 volatile int ret = 0;131 132 ret = static_subprog(ctx);133 bpf_spin_unlock(&lockA);134 return ret + ctx->len;135}136 137SEC("tc")138int lock_static_subprog_call(struct __sk_buff *ctx)139{140 int ret = 0;141 142 bpf_spin_lock(&lockA);143 if (ctx->mark == 42)144 ret = static_subprog(ctx);145 bpf_spin_unlock(&lockA);146 return ret;147}148 149SEC("tc")150int lock_static_subprog_lock(struct __sk_buff *ctx)151{152 int ret = 0;153 154 ret = static_subprog_lock(ctx);155 bpf_spin_unlock(&lockA);156 return ret;157}158 159SEC("tc")160int lock_static_subprog_unlock(struct __sk_buff *ctx)161{162 int ret = 0;163 164 bpf_spin_lock(&lockA);165 ret = static_subprog_unlock(ctx);166 return ret;167}168 169char _license[] SEC("license") = "GPL";170