162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef __BPF_UTIL__
362306a36Sopenharmony_ci#define __BPF_UTIL__
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#include <stdio.h>
662306a36Sopenharmony_ci#include <stdlib.h>
762306a36Sopenharmony_ci#include <string.h>
862306a36Sopenharmony_ci#include <errno.h>
962306a36Sopenharmony_ci#include <bpf/libbpf.h> /* libbpf_num_possible_cpus */
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_cistatic inline unsigned int bpf_num_possible_cpus(void)
1262306a36Sopenharmony_ci{
1362306a36Sopenharmony_ci	int possible_cpus = libbpf_num_possible_cpus();
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci	if (possible_cpus < 0) {
1662306a36Sopenharmony_ci		printf("Failed to get # of possible cpus: '%s'!\n",
1762306a36Sopenharmony_ci		       strerror(-possible_cpus));
1862306a36Sopenharmony_ci		exit(1);
1962306a36Sopenharmony_ci	}
2062306a36Sopenharmony_ci	return possible_cpus;
2162306a36Sopenharmony_ci}
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci/* Copy up to sz - 1 bytes from zero-terminated src string and ensure that dst
2462306a36Sopenharmony_ci * is zero-terminated string no matter what (unless sz == 0, in which case
2562306a36Sopenharmony_ci * it's a no-op). It's conceptually close to FreeBSD's strlcpy(), but differs
2662306a36Sopenharmony_ci * in what is returned. Given this is internal helper, it's trivial to extend
2762306a36Sopenharmony_ci * this, when necessary. Use this instead of strncpy inside libbpf source code.
2862306a36Sopenharmony_ci */
2962306a36Sopenharmony_cistatic inline void bpf_strlcpy(char *dst, const char *src, size_t sz)
3062306a36Sopenharmony_ci{
3162306a36Sopenharmony_ci	size_t i;
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci	if (sz == 0)
3462306a36Sopenharmony_ci		return;
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci	sz--;
3762306a36Sopenharmony_ci	for (i = 0; i < sz && src[i]; i++)
3862306a36Sopenharmony_ci		dst[i] = src[i];
3962306a36Sopenharmony_ci	dst[i] = '\0';
4062306a36Sopenharmony_ci}
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci#define __bpf_percpu_val_align	__attribute__((__aligned__(8)))
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci#define BPF_DECLARE_PERCPU(type, name)				\
4562306a36Sopenharmony_ci	struct { type v; /* padding */ } __bpf_percpu_val_align	\
4662306a36Sopenharmony_ci		name[bpf_num_possible_cpus()]
4762306a36Sopenharmony_ci#define bpf_percpu(name, cpu) name[(cpu)].v
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci#ifndef ARRAY_SIZE
5062306a36Sopenharmony_ci# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
5162306a36Sopenharmony_ci#endif
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci#ifndef sizeof_field
5462306a36Sopenharmony_ci#define sizeof_field(TYPE, MEMBER) sizeof((((TYPE *)0)->MEMBER))
5562306a36Sopenharmony_ci#endif
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci#ifndef offsetofend
5862306a36Sopenharmony_ci#define offsetofend(TYPE, MEMBER) \
5962306a36Sopenharmony_ci	(offsetof(TYPE, MEMBER)	+ sizeof_field(TYPE, MEMBER))
6062306a36Sopenharmony_ci#endif
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci#endif /* __BPF_UTIL__ */
63