162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci#include <linux/bpf.h>
362306a36Sopenharmony_ci#include <linux/version.h>
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#include <bpf/bpf_helpers.h>
662306a36Sopenharmony_ci#include "netcnt_common.h"
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#define MAX_BPS	(3 * 1024 * 1024)
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#define REFRESH_TIME_NS	100000000
1162306a36Sopenharmony_ci#define NS_PER_SEC	1000000000
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_cistruct {
1462306a36Sopenharmony_ci	__uint(type, BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE);
1562306a36Sopenharmony_ci	__type(key, struct bpf_cgroup_storage_key);
1662306a36Sopenharmony_ci	__type(value, union percpu_net_cnt);
1762306a36Sopenharmony_ci} percpu_netcnt SEC(".maps");
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_cistruct {
2062306a36Sopenharmony_ci	__uint(type, BPF_MAP_TYPE_CGROUP_STORAGE);
2162306a36Sopenharmony_ci	__type(key, struct bpf_cgroup_storage_key);
2262306a36Sopenharmony_ci	__type(value, union net_cnt);
2362306a36Sopenharmony_ci} netcnt SEC(".maps");
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ciSEC("cgroup/skb")
2662306a36Sopenharmony_ciint bpf_nextcnt(struct __sk_buff *skb)
2762306a36Sopenharmony_ci{
2862306a36Sopenharmony_ci	union percpu_net_cnt *percpu_cnt;
2962306a36Sopenharmony_ci	union net_cnt *cnt;
3062306a36Sopenharmony_ci	__u64 ts, dt;
3162306a36Sopenharmony_ci	int ret;
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci	cnt = bpf_get_local_storage(&netcnt, 0);
3462306a36Sopenharmony_ci	percpu_cnt = bpf_get_local_storage(&percpu_netcnt, 0);
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci	percpu_cnt->packets++;
3762306a36Sopenharmony_ci	percpu_cnt->bytes += skb->len;
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci	if (percpu_cnt->packets > MAX_PERCPU_PACKETS) {
4062306a36Sopenharmony_ci		__sync_fetch_and_add(&cnt->packets,
4162306a36Sopenharmony_ci				     percpu_cnt->packets);
4262306a36Sopenharmony_ci		percpu_cnt->packets = 0;
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci		__sync_fetch_and_add(&cnt->bytes,
4562306a36Sopenharmony_ci				     percpu_cnt->bytes);
4662306a36Sopenharmony_ci		percpu_cnt->bytes = 0;
4762306a36Sopenharmony_ci	}
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	ts = bpf_ktime_get_ns();
5062306a36Sopenharmony_ci	dt = ts - percpu_cnt->prev_ts;
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	dt *= MAX_BPS;
5362306a36Sopenharmony_ci	dt /= NS_PER_SEC;
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	if (cnt->bytes + percpu_cnt->bytes - percpu_cnt->prev_bytes < dt)
5662306a36Sopenharmony_ci		ret = 1;
5762306a36Sopenharmony_ci	else
5862306a36Sopenharmony_ci		ret = 0;
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	if (dt > REFRESH_TIME_NS) {
6162306a36Sopenharmony_ci		percpu_cnt->prev_ts = ts;
6262306a36Sopenharmony_ci		percpu_cnt->prev_packets = cnt->packets;
6362306a36Sopenharmony_ci		percpu_cnt->prev_bytes = cnt->bytes;
6462306a36Sopenharmony_ci	}
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci	return !!ret;
6762306a36Sopenharmony_ci}
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_cichar _license[] SEC("license") = "GPL";
70