mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-21 08:46:49 +07:00
371e4fcc9d
This commit adds a bpf kselftest, which demonstrates how percpu and shared cgroup local storage can be used for efficient lookup-free network accounting. Cgroup local storage provides generic memory area with a very efficient lookup free access. To avoid expensive atomic operations for each packet, per-cpu cgroup local storage is used. Each packet is initially charged to a per-cpu counter, and only if the counter reaches certain value (32 in this case), the charge is moved into the global atomic counter. This allows to amortize atomic operations, keeping reasonable accuracy. The test also implements a naive network traffic throttling, mostly to demonstrate the possibility of bpf cgroup--based network bandwidth control. Expected output: ./test_netcnt test_netcnt:PASS Signed-off-by: Roman Gushchin <guro@fb.com> Acked-by: Song Liu <songliubraving@fb.com> Cc: Daniel Borkmann <daniel@iogearbox.net> Cc: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
72 lines
1.6 KiB
C
72 lines
1.6 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
#include <linux/bpf.h>
|
|
#include <linux/version.h>
|
|
|
|
#include "bpf_helpers.h"
|
|
#include "netcnt_common.h"
|
|
|
|
#define MAX_BPS (3 * 1024 * 1024)
|
|
|
|
#define REFRESH_TIME_NS 100000000
|
|
#define NS_PER_SEC 1000000000
|
|
|
|
struct bpf_map_def SEC("maps") percpu_netcnt = {
|
|
.type = BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE,
|
|
.key_size = sizeof(struct bpf_cgroup_storage_key),
|
|
.value_size = sizeof(struct percpu_net_cnt),
|
|
};
|
|
|
|
struct bpf_map_def SEC("maps") netcnt = {
|
|
.type = BPF_MAP_TYPE_CGROUP_STORAGE,
|
|
.key_size = sizeof(struct bpf_cgroup_storage_key),
|
|
.value_size = sizeof(struct net_cnt),
|
|
};
|
|
|
|
SEC("cgroup/skb")
|
|
int bpf_nextcnt(struct __sk_buff *skb)
|
|
{
|
|
struct percpu_net_cnt *percpu_cnt;
|
|
char fmt[] = "%d %llu %llu\n";
|
|
struct net_cnt *cnt;
|
|
__u64 ts, dt;
|
|
int ret;
|
|
|
|
cnt = bpf_get_local_storage(&netcnt, 0);
|
|
percpu_cnt = bpf_get_local_storage(&percpu_netcnt, 0);
|
|
|
|
percpu_cnt->packets++;
|
|
percpu_cnt->bytes += skb->len;
|
|
|
|
if (percpu_cnt->packets > MAX_PERCPU_PACKETS) {
|
|
__sync_fetch_and_add(&cnt->packets,
|
|
percpu_cnt->packets);
|
|
percpu_cnt->packets = 0;
|
|
|
|
__sync_fetch_and_add(&cnt->bytes,
|
|
percpu_cnt->bytes);
|
|
percpu_cnt->bytes = 0;
|
|
}
|
|
|
|
ts = bpf_ktime_get_ns();
|
|
dt = ts - percpu_cnt->prev_ts;
|
|
|
|
dt *= MAX_BPS;
|
|
dt /= NS_PER_SEC;
|
|
|
|
if (cnt->bytes + percpu_cnt->bytes - percpu_cnt->prev_bytes < dt)
|
|
ret = 1;
|
|
else
|
|
ret = 0;
|
|
|
|
if (dt > REFRESH_TIME_NS) {
|
|
percpu_cnt->prev_ts = ts;
|
|
percpu_cnt->prev_packets = cnt->packets;
|
|
percpu_cnt->prev_bytes = cnt->bytes;
|
|
}
|
|
|
|
return !!ret;
|
|
}
|
|
|
|
char _license[] SEC("license") = "GPL";
|
|
__u32 _version SEC("version") = LINUX_VERSION_CODE;
|