18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
28c2ecf20Sopenharmony_ci
38c2ecf20Sopenharmony_ci/*
48c2ecf20Sopenharmony_ci * common eBPF ELF operations.
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org>
78c2ecf20Sopenharmony_ci * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
88c2ecf20Sopenharmony_ci * Copyright (C) 2015 Huawei Inc.
98c2ecf20Sopenharmony_ci *
108c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or
118c2ecf20Sopenharmony_ci * modify it under the terms of the GNU Lesser General Public
128c2ecf20Sopenharmony_ci * License as published by the Free Software Foundation;
138c2ecf20Sopenharmony_ci * version 2.1 of the License (not later!)
148c2ecf20Sopenharmony_ci *
158c2ecf20Sopenharmony_ci * This program is distributed in the hope that it will be useful,
168c2ecf20Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
178c2ecf20Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
188c2ecf20Sopenharmony_ci * GNU Lesser General Public License for more details.
198c2ecf20Sopenharmony_ci *
208c2ecf20Sopenharmony_ci * You should have received a copy of the GNU Lesser General Public
218c2ecf20Sopenharmony_ci * License along with this program; if not,  see <http://www.gnu.org/licenses>
228c2ecf20Sopenharmony_ci */
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci#include <stdlib.h>
258c2ecf20Sopenharmony_ci#include <string.h>
268c2ecf20Sopenharmony_ci#include <memory.h>
278c2ecf20Sopenharmony_ci#include <unistd.h>
288c2ecf20Sopenharmony_ci#include <asm/unistd.h>
298c2ecf20Sopenharmony_ci#include <errno.h>
308c2ecf20Sopenharmony_ci#include <linux/bpf.h>
318c2ecf20Sopenharmony_ci#include "bpf.h"
328c2ecf20Sopenharmony_ci#include "libbpf.h"
338c2ecf20Sopenharmony_ci#include "libbpf_internal.h"
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci/*
368c2ecf20Sopenharmony_ci * When building perf, unistd.h is overridden. __NR_bpf is
378c2ecf20Sopenharmony_ci * required to be defined explicitly.
388c2ecf20Sopenharmony_ci */
398c2ecf20Sopenharmony_ci#ifndef __NR_bpf
408c2ecf20Sopenharmony_ci# if defined(__i386__)
418c2ecf20Sopenharmony_ci#  define __NR_bpf 357
428c2ecf20Sopenharmony_ci# elif defined(__x86_64__)
438c2ecf20Sopenharmony_ci#  define __NR_bpf 321
448c2ecf20Sopenharmony_ci# elif defined(__aarch64__)
458c2ecf20Sopenharmony_ci#  define __NR_bpf 280
468c2ecf20Sopenharmony_ci# elif defined(__sparc__)
478c2ecf20Sopenharmony_ci#  define __NR_bpf 349
488c2ecf20Sopenharmony_ci# elif defined(__s390__)
498c2ecf20Sopenharmony_ci#  define __NR_bpf 351
508c2ecf20Sopenharmony_ci# elif defined(__arc__)
518c2ecf20Sopenharmony_ci#  define __NR_bpf 280
528c2ecf20Sopenharmony_ci# else
538c2ecf20Sopenharmony_ci#  error __NR_bpf not defined. libbpf does not support your arch.
548c2ecf20Sopenharmony_ci# endif
558c2ecf20Sopenharmony_ci#endif
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_cistatic inline __u64 ptr_to_u64(const void *ptr)
588c2ecf20Sopenharmony_ci{
598c2ecf20Sopenharmony_ci	return (__u64) (unsigned long) ptr;
608c2ecf20Sopenharmony_ci}
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_cistatic inline int sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr,
638c2ecf20Sopenharmony_ci			  unsigned int size)
648c2ecf20Sopenharmony_ci{
658c2ecf20Sopenharmony_ci	return syscall(__NR_bpf, cmd, attr, size);
668c2ecf20Sopenharmony_ci}
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_cistatic inline int sys_bpf_prog_load(union bpf_attr *attr, unsigned int size)
698c2ecf20Sopenharmony_ci{
708c2ecf20Sopenharmony_ci	int fd;
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci	do {
738c2ecf20Sopenharmony_ci		fd = sys_bpf(BPF_PROG_LOAD, attr, size);
748c2ecf20Sopenharmony_ci	} while (fd < 0 && errno == EAGAIN);
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci	return fd;
778c2ecf20Sopenharmony_ci}
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ciint bpf_create_map_xattr(const struct bpf_create_map_attr *create_attr)
808c2ecf20Sopenharmony_ci{
818c2ecf20Sopenharmony_ci	union bpf_attr attr;
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	memset(&attr, '\0', sizeof(attr));
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	attr.map_type = create_attr->map_type;
868c2ecf20Sopenharmony_ci	attr.key_size = create_attr->key_size;
878c2ecf20Sopenharmony_ci	attr.value_size = create_attr->value_size;
888c2ecf20Sopenharmony_ci	attr.max_entries = create_attr->max_entries;
898c2ecf20Sopenharmony_ci	attr.map_flags = create_attr->map_flags;
908c2ecf20Sopenharmony_ci	if (create_attr->name)
918c2ecf20Sopenharmony_ci		memcpy(attr.map_name, create_attr->name,
928c2ecf20Sopenharmony_ci		       min(strlen(create_attr->name), BPF_OBJ_NAME_LEN - 1));
938c2ecf20Sopenharmony_ci	attr.numa_node = create_attr->numa_node;
948c2ecf20Sopenharmony_ci	attr.btf_fd = create_attr->btf_fd;
958c2ecf20Sopenharmony_ci	attr.btf_key_type_id = create_attr->btf_key_type_id;
968c2ecf20Sopenharmony_ci	attr.btf_value_type_id = create_attr->btf_value_type_id;
978c2ecf20Sopenharmony_ci	attr.map_ifindex = create_attr->map_ifindex;
988c2ecf20Sopenharmony_ci	if (attr.map_type == BPF_MAP_TYPE_STRUCT_OPS)
998c2ecf20Sopenharmony_ci		attr.btf_vmlinux_value_type_id =
1008c2ecf20Sopenharmony_ci			create_attr->btf_vmlinux_value_type_id;
1018c2ecf20Sopenharmony_ci	else
1028c2ecf20Sopenharmony_ci		attr.inner_map_fd = create_attr->inner_map_fd;
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci	return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
1058c2ecf20Sopenharmony_ci}
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ciint bpf_create_map_node(enum bpf_map_type map_type, const char *name,
1088c2ecf20Sopenharmony_ci			int key_size, int value_size, int max_entries,
1098c2ecf20Sopenharmony_ci			__u32 map_flags, int node)
1108c2ecf20Sopenharmony_ci{
1118c2ecf20Sopenharmony_ci	struct bpf_create_map_attr map_attr = {};
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci	map_attr.name = name;
1148c2ecf20Sopenharmony_ci	map_attr.map_type = map_type;
1158c2ecf20Sopenharmony_ci	map_attr.map_flags = map_flags;
1168c2ecf20Sopenharmony_ci	map_attr.key_size = key_size;
1178c2ecf20Sopenharmony_ci	map_attr.value_size = value_size;
1188c2ecf20Sopenharmony_ci	map_attr.max_entries = max_entries;
1198c2ecf20Sopenharmony_ci	if (node >= 0) {
1208c2ecf20Sopenharmony_ci		map_attr.numa_node = node;
1218c2ecf20Sopenharmony_ci		map_attr.map_flags |= BPF_F_NUMA_NODE;
1228c2ecf20Sopenharmony_ci	}
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci	return bpf_create_map_xattr(&map_attr);
1258c2ecf20Sopenharmony_ci}
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ciint bpf_create_map(enum bpf_map_type map_type, int key_size,
1288c2ecf20Sopenharmony_ci		   int value_size, int max_entries, __u32 map_flags)
1298c2ecf20Sopenharmony_ci{
1308c2ecf20Sopenharmony_ci	struct bpf_create_map_attr map_attr = {};
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci	map_attr.map_type = map_type;
1338c2ecf20Sopenharmony_ci	map_attr.map_flags = map_flags;
1348c2ecf20Sopenharmony_ci	map_attr.key_size = key_size;
1358c2ecf20Sopenharmony_ci	map_attr.value_size = value_size;
1368c2ecf20Sopenharmony_ci	map_attr.max_entries = max_entries;
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci	return bpf_create_map_xattr(&map_attr);
1398c2ecf20Sopenharmony_ci}
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ciint bpf_create_map_name(enum bpf_map_type map_type, const char *name,
1428c2ecf20Sopenharmony_ci			int key_size, int value_size, int max_entries,
1438c2ecf20Sopenharmony_ci			__u32 map_flags)
1448c2ecf20Sopenharmony_ci{
1458c2ecf20Sopenharmony_ci	struct bpf_create_map_attr map_attr = {};
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci	map_attr.name = name;
1488c2ecf20Sopenharmony_ci	map_attr.map_type = map_type;
1498c2ecf20Sopenharmony_ci	map_attr.map_flags = map_flags;
1508c2ecf20Sopenharmony_ci	map_attr.key_size = key_size;
1518c2ecf20Sopenharmony_ci	map_attr.value_size = value_size;
1528c2ecf20Sopenharmony_ci	map_attr.max_entries = max_entries;
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci	return bpf_create_map_xattr(&map_attr);
1558c2ecf20Sopenharmony_ci}
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ciint bpf_create_map_in_map_node(enum bpf_map_type map_type, const char *name,
1588c2ecf20Sopenharmony_ci			       int key_size, int inner_map_fd, int max_entries,
1598c2ecf20Sopenharmony_ci			       __u32 map_flags, int node)
1608c2ecf20Sopenharmony_ci{
1618c2ecf20Sopenharmony_ci	union bpf_attr attr;
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci	memset(&attr, '\0', sizeof(attr));
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci	attr.map_type = map_type;
1668c2ecf20Sopenharmony_ci	attr.key_size = key_size;
1678c2ecf20Sopenharmony_ci	attr.value_size = 4;
1688c2ecf20Sopenharmony_ci	attr.inner_map_fd = inner_map_fd;
1698c2ecf20Sopenharmony_ci	attr.max_entries = max_entries;
1708c2ecf20Sopenharmony_ci	attr.map_flags = map_flags;
1718c2ecf20Sopenharmony_ci	if (name)
1728c2ecf20Sopenharmony_ci		memcpy(attr.map_name, name,
1738c2ecf20Sopenharmony_ci		       min(strlen(name), BPF_OBJ_NAME_LEN - 1));
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci	if (node >= 0) {
1768c2ecf20Sopenharmony_ci		attr.map_flags |= BPF_F_NUMA_NODE;
1778c2ecf20Sopenharmony_ci		attr.numa_node = node;
1788c2ecf20Sopenharmony_ci	}
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci	return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
1818c2ecf20Sopenharmony_ci}
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ciint bpf_create_map_in_map(enum bpf_map_type map_type, const char *name,
1848c2ecf20Sopenharmony_ci			  int key_size, int inner_map_fd, int max_entries,
1858c2ecf20Sopenharmony_ci			  __u32 map_flags)
1868c2ecf20Sopenharmony_ci{
1878c2ecf20Sopenharmony_ci	return bpf_create_map_in_map_node(map_type, name, key_size,
1888c2ecf20Sopenharmony_ci					  inner_map_fd, max_entries, map_flags,
1898c2ecf20Sopenharmony_ci					  -1);
1908c2ecf20Sopenharmony_ci}
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_cistatic void *
1938c2ecf20Sopenharmony_cialloc_zero_tailing_info(const void *orecord, __u32 cnt,
1948c2ecf20Sopenharmony_ci			__u32 actual_rec_size, __u32 expected_rec_size)
1958c2ecf20Sopenharmony_ci{
1968c2ecf20Sopenharmony_ci	__u64 info_len = (__u64)actual_rec_size * cnt;
1978c2ecf20Sopenharmony_ci	void *info, *nrecord;
1988c2ecf20Sopenharmony_ci	int i;
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci	info = malloc(info_len);
2018c2ecf20Sopenharmony_ci	if (!info)
2028c2ecf20Sopenharmony_ci		return NULL;
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci	/* zero out bytes kernel does not understand */
2058c2ecf20Sopenharmony_ci	nrecord = info;
2068c2ecf20Sopenharmony_ci	for (i = 0; i < cnt; i++) {
2078c2ecf20Sopenharmony_ci		memcpy(nrecord, orecord, expected_rec_size);
2088c2ecf20Sopenharmony_ci		memset(nrecord + expected_rec_size, 0,
2098c2ecf20Sopenharmony_ci		       actual_rec_size - expected_rec_size);
2108c2ecf20Sopenharmony_ci		orecord += actual_rec_size;
2118c2ecf20Sopenharmony_ci		nrecord += actual_rec_size;
2128c2ecf20Sopenharmony_ci	}
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci	return info;
2158c2ecf20Sopenharmony_ci}
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ciint bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr,
2188c2ecf20Sopenharmony_ci			   char *log_buf, size_t log_buf_sz)
2198c2ecf20Sopenharmony_ci{
2208c2ecf20Sopenharmony_ci	void *finfo = NULL, *linfo = NULL;
2218c2ecf20Sopenharmony_ci	union bpf_attr attr;
2228c2ecf20Sopenharmony_ci	__u32 log_level;
2238c2ecf20Sopenharmony_ci	int fd;
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci	if (!load_attr || !log_buf != !log_buf_sz)
2268c2ecf20Sopenharmony_ci		return -EINVAL;
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci	log_level = load_attr->log_level;
2298c2ecf20Sopenharmony_ci	if (log_level > (4 | 2 | 1) || (log_level && !log_buf))
2308c2ecf20Sopenharmony_ci		return -EINVAL;
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci	memset(&attr, 0, sizeof(attr));
2338c2ecf20Sopenharmony_ci	attr.prog_type = load_attr->prog_type;
2348c2ecf20Sopenharmony_ci	attr.expected_attach_type = load_attr->expected_attach_type;
2358c2ecf20Sopenharmony_ci	if (attr.prog_type == BPF_PROG_TYPE_STRUCT_OPS ||
2368c2ecf20Sopenharmony_ci	    attr.prog_type == BPF_PROG_TYPE_LSM) {
2378c2ecf20Sopenharmony_ci		attr.attach_btf_id = load_attr->attach_btf_id;
2388c2ecf20Sopenharmony_ci	} else if (attr.prog_type == BPF_PROG_TYPE_TRACING ||
2398c2ecf20Sopenharmony_ci		   attr.prog_type == BPF_PROG_TYPE_EXT) {
2408c2ecf20Sopenharmony_ci		attr.attach_btf_id = load_attr->attach_btf_id;
2418c2ecf20Sopenharmony_ci		attr.attach_prog_fd = load_attr->attach_prog_fd;
2428c2ecf20Sopenharmony_ci	} else {
2438c2ecf20Sopenharmony_ci		attr.prog_ifindex = load_attr->prog_ifindex;
2448c2ecf20Sopenharmony_ci		attr.kern_version = load_attr->kern_version;
2458c2ecf20Sopenharmony_ci	}
2468c2ecf20Sopenharmony_ci	attr.insn_cnt = (__u32)load_attr->insns_cnt;
2478c2ecf20Sopenharmony_ci	attr.insns = ptr_to_u64(load_attr->insns);
2488c2ecf20Sopenharmony_ci	attr.license = ptr_to_u64(load_attr->license);
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	attr.log_level = log_level;
2518c2ecf20Sopenharmony_ci	if (log_level) {
2528c2ecf20Sopenharmony_ci		attr.log_buf = ptr_to_u64(log_buf);
2538c2ecf20Sopenharmony_ci		attr.log_size = log_buf_sz;
2548c2ecf20Sopenharmony_ci	} else {
2558c2ecf20Sopenharmony_ci		attr.log_buf = ptr_to_u64(NULL);
2568c2ecf20Sopenharmony_ci		attr.log_size = 0;
2578c2ecf20Sopenharmony_ci	}
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci	attr.prog_btf_fd = load_attr->prog_btf_fd;
2608c2ecf20Sopenharmony_ci	attr.func_info_rec_size = load_attr->func_info_rec_size;
2618c2ecf20Sopenharmony_ci	attr.func_info_cnt = load_attr->func_info_cnt;
2628c2ecf20Sopenharmony_ci	attr.func_info = ptr_to_u64(load_attr->func_info);
2638c2ecf20Sopenharmony_ci	attr.line_info_rec_size = load_attr->line_info_rec_size;
2648c2ecf20Sopenharmony_ci	attr.line_info_cnt = load_attr->line_info_cnt;
2658c2ecf20Sopenharmony_ci	attr.line_info = ptr_to_u64(load_attr->line_info);
2668c2ecf20Sopenharmony_ci	if (load_attr->name)
2678c2ecf20Sopenharmony_ci		memcpy(attr.prog_name, load_attr->name,
2688c2ecf20Sopenharmony_ci		       min(strlen(load_attr->name), BPF_OBJ_NAME_LEN - 1));
2698c2ecf20Sopenharmony_ci	attr.prog_flags = load_attr->prog_flags;
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci	fd = sys_bpf_prog_load(&attr, sizeof(attr));
2728c2ecf20Sopenharmony_ci	if (fd >= 0)
2738c2ecf20Sopenharmony_ci		return fd;
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci	/* After bpf_prog_load, the kernel may modify certain attributes
2768c2ecf20Sopenharmony_ci	 * to give user space a hint how to deal with loading failure.
2778c2ecf20Sopenharmony_ci	 * Check to see whether we can make some changes and load again.
2788c2ecf20Sopenharmony_ci	 */
2798c2ecf20Sopenharmony_ci	while (errno == E2BIG && (!finfo || !linfo)) {
2808c2ecf20Sopenharmony_ci		if (!finfo && attr.func_info_cnt &&
2818c2ecf20Sopenharmony_ci		    attr.func_info_rec_size < load_attr->func_info_rec_size) {
2828c2ecf20Sopenharmony_ci			/* try with corrected func info records */
2838c2ecf20Sopenharmony_ci			finfo = alloc_zero_tailing_info(load_attr->func_info,
2848c2ecf20Sopenharmony_ci							load_attr->func_info_cnt,
2858c2ecf20Sopenharmony_ci							load_attr->func_info_rec_size,
2868c2ecf20Sopenharmony_ci							attr.func_info_rec_size);
2878c2ecf20Sopenharmony_ci			if (!finfo)
2888c2ecf20Sopenharmony_ci				goto done;
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci			attr.func_info = ptr_to_u64(finfo);
2918c2ecf20Sopenharmony_ci			attr.func_info_rec_size = load_attr->func_info_rec_size;
2928c2ecf20Sopenharmony_ci		} else if (!linfo && attr.line_info_cnt &&
2938c2ecf20Sopenharmony_ci			   attr.line_info_rec_size <
2948c2ecf20Sopenharmony_ci			   load_attr->line_info_rec_size) {
2958c2ecf20Sopenharmony_ci			linfo = alloc_zero_tailing_info(load_attr->line_info,
2968c2ecf20Sopenharmony_ci							load_attr->line_info_cnt,
2978c2ecf20Sopenharmony_ci							load_attr->line_info_rec_size,
2988c2ecf20Sopenharmony_ci							attr.line_info_rec_size);
2998c2ecf20Sopenharmony_ci			if (!linfo)
3008c2ecf20Sopenharmony_ci				goto done;
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci			attr.line_info = ptr_to_u64(linfo);
3038c2ecf20Sopenharmony_ci			attr.line_info_rec_size = load_attr->line_info_rec_size;
3048c2ecf20Sopenharmony_ci		} else {
3058c2ecf20Sopenharmony_ci			break;
3068c2ecf20Sopenharmony_ci		}
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci		fd = sys_bpf_prog_load(&attr, sizeof(attr));
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci		if (fd >= 0)
3118c2ecf20Sopenharmony_ci			goto done;
3128c2ecf20Sopenharmony_ci	}
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ci	if (log_level || !log_buf)
3158c2ecf20Sopenharmony_ci		goto done;
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci	/* Try again with log */
3188c2ecf20Sopenharmony_ci	attr.log_buf = ptr_to_u64(log_buf);
3198c2ecf20Sopenharmony_ci	attr.log_size = log_buf_sz;
3208c2ecf20Sopenharmony_ci	attr.log_level = 1;
3218c2ecf20Sopenharmony_ci	log_buf[0] = 0;
3228c2ecf20Sopenharmony_ci	fd = sys_bpf_prog_load(&attr, sizeof(attr));
3238c2ecf20Sopenharmony_cidone:
3248c2ecf20Sopenharmony_ci	free(finfo);
3258c2ecf20Sopenharmony_ci	free(linfo);
3268c2ecf20Sopenharmony_ci	return fd;
3278c2ecf20Sopenharmony_ci}
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ciint bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
3308c2ecf20Sopenharmony_ci		     size_t insns_cnt, const char *license,
3318c2ecf20Sopenharmony_ci		     __u32 kern_version, char *log_buf,
3328c2ecf20Sopenharmony_ci		     size_t log_buf_sz)
3338c2ecf20Sopenharmony_ci{
3348c2ecf20Sopenharmony_ci	struct bpf_load_program_attr load_attr;
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci	memset(&load_attr, 0, sizeof(struct bpf_load_program_attr));
3378c2ecf20Sopenharmony_ci	load_attr.prog_type = type;
3388c2ecf20Sopenharmony_ci	load_attr.expected_attach_type = 0;
3398c2ecf20Sopenharmony_ci	load_attr.name = NULL;
3408c2ecf20Sopenharmony_ci	load_attr.insns = insns;
3418c2ecf20Sopenharmony_ci	load_attr.insns_cnt = insns_cnt;
3428c2ecf20Sopenharmony_ci	load_attr.license = license;
3438c2ecf20Sopenharmony_ci	load_attr.kern_version = kern_version;
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_ci	return bpf_load_program_xattr(&load_attr, log_buf, log_buf_sz);
3468c2ecf20Sopenharmony_ci}
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_ciint bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns,
3498c2ecf20Sopenharmony_ci		       size_t insns_cnt, __u32 prog_flags, const char *license,
3508c2ecf20Sopenharmony_ci		       __u32 kern_version, char *log_buf, size_t log_buf_sz,
3518c2ecf20Sopenharmony_ci		       int log_level)
3528c2ecf20Sopenharmony_ci{
3538c2ecf20Sopenharmony_ci	union bpf_attr attr;
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_ci	memset(&attr, 0, sizeof(attr));
3568c2ecf20Sopenharmony_ci	attr.prog_type = type;
3578c2ecf20Sopenharmony_ci	attr.insn_cnt = (__u32)insns_cnt;
3588c2ecf20Sopenharmony_ci	attr.insns = ptr_to_u64(insns);
3598c2ecf20Sopenharmony_ci	attr.license = ptr_to_u64(license);
3608c2ecf20Sopenharmony_ci	attr.log_buf = ptr_to_u64(log_buf);
3618c2ecf20Sopenharmony_ci	attr.log_size = log_buf_sz;
3628c2ecf20Sopenharmony_ci	attr.log_level = log_level;
3638c2ecf20Sopenharmony_ci	log_buf[0] = 0;
3648c2ecf20Sopenharmony_ci	attr.kern_version = kern_version;
3658c2ecf20Sopenharmony_ci	attr.prog_flags = prog_flags;
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci	return sys_bpf_prog_load(&attr, sizeof(attr));
3688c2ecf20Sopenharmony_ci}
3698c2ecf20Sopenharmony_ci
3708c2ecf20Sopenharmony_ciint bpf_map_update_elem(int fd, const void *key, const void *value,
3718c2ecf20Sopenharmony_ci			__u64 flags)
3728c2ecf20Sopenharmony_ci{
3738c2ecf20Sopenharmony_ci	union bpf_attr attr;
3748c2ecf20Sopenharmony_ci
3758c2ecf20Sopenharmony_ci	memset(&attr, 0, sizeof(attr));
3768c2ecf20Sopenharmony_ci	attr.map_fd = fd;
3778c2ecf20Sopenharmony_ci	attr.key = ptr_to_u64(key);
3788c2ecf20Sopenharmony_ci	attr.value = ptr_to_u64(value);
3798c2ecf20Sopenharmony_ci	attr.flags = flags;
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci	return sys_bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
3828c2ecf20Sopenharmony_ci}
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ciint bpf_map_lookup_elem(int fd, const void *key, void *value)
3858c2ecf20Sopenharmony_ci{
3868c2ecf20Sopenharmony_ci	union bpf_attr attr;
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_ci	memset(&attr, 0, sizeof(attr));
3898c2ecf20Sopenharmony_ci	attr.map_fd = fd;
3908c2ecf20Sopenharmony_ci	attr.key = ptr_to_u64(key);
3918c2ecf20Sopenharmony_ci	attr.value = ptr_to_u64(value);
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci	return sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
3948c2ecf20Sopenharmony_ci}
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ciint bpf_map_lookup_elem_flags(int fd, const void *key, void *value, __u64 flags)
3978c2ecf20Sopenharmony_ci{
3988c2ecf20Sopenharmony_ci	union bpf_attr attr;
3998c2ecf20Sopenharmony_ci
4008c2ecf20Sopenharmony_ci	memset(&attr, 0, sizeof(attr));
4018c2ecf20Sopenharmony_ci	attr.map_fd = fd;
4028c2ecf20Sopenharmony_ci	attr.key = ptr_to_u64(key);
4038c2ecf20Sopenharmony_ci	attr.value = ptr_to_u64(value);
4048c2ecf20Sopenharmony_ci	attr.flags = flags;
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_ci	return sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
4078c2ecf20Sopenharmony_ci}
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ciint bpf_map_lookup_and_delete_elem(int fd, const void *key, void *value)
4108c2ecf20Sopenharmony_ci{
4118c2ecf20Sopenharmony_ci	union bpf_attr attr;
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci	memset(&attr, 0, sizeof(attr));
4148c2ecf20Sopenharmony_ci	attr.map_fd = fd;
4158c2ecf20Sopenharmony_ci	attr.key = ptr_to_u64(key);
4168c2ecf20Sopenharmony_ci	attr.value = ptr_to_u64(value);
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_ci	return sys_bpf(BPF_MAP_LOOKUP_AND_DELETE_ELEM, &attr, sizeof(attr));
4198c2ecf20Sopenharmony_ci}
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ciint bpf_map_delete_elem(int fd, const void *key)
4228c2ecf20Sopenharmony_ci{
4238c2ecf20Sopenharmony_ci	union bpf_attr attr;
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_ci	memset(&attr, 0, sizeof(attr));
4268c2ecf20Sopenharmony_ci	attr.map_fd = fd;
4278c2ecf20Sopenharmony_ci	attr.key = ptr_to_u64(key);
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_ci	return sys_bpf(BPF_MAP_DELETE_ELEM, &attr, sizeof(attr));
4308c2ecf20Sopenharmony_ci}
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ciint bpf_map_get_next_key(int fd, const void *key, void *next_key)
4338c2ecf20Sopenharmony_ci{
4348c2ecf20Sopenharmony_ci	union bpf_attr attr;
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_ci	memset(&attr, 0, sizeof(attr));
4378c2ecf20Sopenharmony_ci	attr.map_fd = fd;
4388c2ecf20Sopenharmony_ci	attr.key = ptr_to_u64(key);
4398c2ecf20Sopenharmony_ci	attr.next_key = ptr_to_u64(next_key);
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_ci	return sys_bpf(BPF_MAP_GET_NEXT_KEY, &attr, sizeof(attr));
4428c2ecf20Sopenharmony_ci}
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ciint bpf_map_freeze(int fd)
4458c2ecf20Sopenharmony_ci{
4468c2ecf20Sopenharmony_ci	union bpf_attr attr;
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_ci	memset(&attr, 0, sizeof(attr));
4498c2ecf20Sopenharmony_ci	attr.map_fd = fd;
4508c2ecf20Sopenharmony_ci
4518c2ecf20Sopenharmony_ci	return sys_bpf(BPF_MAP_FREEZE, &attr, sizeof(attr));
4528c2ecf20Sopenharmony_ci}
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_cistatic int bpf_map_batch_common(int cmd, int fd, void  *in_batch,
4558c2ecf20Sopenharmony_ci				void *out_batch, void *keys, void *values,
4568c2ecf20Sopenharmony_ci				__u32 *count,
4578c2ecf20Sopenharmony_ci				const struct bpf_map_batch_opts *opts)
4588c2ecf20Sopenharmony_ci{
4598c2ecf20Sopenharmony_ci	union bpf_attr attr;
4608c2ecf20Sopenharmony_ci	int ret;
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci	if (!OPTS_VALID(opts, bpf_map_batch_opts))
4638c2ecf20Sopenharmony_ci		return -EINVAL;
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ci	memset(&attr, 0, sizeof(attr));
4668c2ecf20Sopenharmony_ci	attr.batch.map_fd = fd;
4678c2ecf20Sopenharmony_ci	attr.batch.in_batch = ptr_to_u64(in_batch);
4688c2ecf20Sopenharmony_ci	attr.batch.out_batch = ptr_to_u64(out_batch);
4698c2ecf20Sopenharmony_ci	attr.batch.keys = ptr_to_u64(keys);
4708c2ecf20Sopenharmony_ci	attr.batch.values = ptr_to_u64(values);
4718c2ecf20Sopenharmony_ci	attr.batch.count = *count;
4728c2ecf20Sopenharmony_ci	attr.batch.elem_flags  = OPTS_GET(opts, elem_flags, 0);
4738c2ecf20Sopenharmony_ci	attr.batch.flags = OPTS_GET(opts, flags, 0);
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci	ret = sys_bpf(cmd, &attr, sizeof(attr));
4768c2ecf20Sopenharmony_ci	*count = attr.batch.count;
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_ci	return ret;
4798c2ecf20Sopenharmony_ci}
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_ciint bpf_map_delete_batch(int fd, void *keys, __u32 *count,
4828c2ecf20Sopenharmony_ci			 const struct bpf_map_batch_opts *opts)
4838c2ecf20Sopenharmony_ci{
4848c2ecf20Sopenharmony_ci	return bpf_map_batch_common(BPF_MAP_DELETE_BATCH, fd, NULL,
4858c2ecf20Sopenharmony_ci				    NULL, keys, NULL, count, opts);
4868c2ecf20Sopenharmony_ci}
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_ciint bpf_map_lookup_batch(int fd, void *in_batch, void *out_batch, void *keys,
4898c2ecf20Sopenharmony_ci			 void *values, __u32 *count,
4908c2ecf20Sopenharmony_ci			 const struct bpf_map_batch_opts *opts)
4918c2ecf20Sopenharmony_ci{
4928c2ecf20Sopenharmony_ci	return bpf_map_batch_common(BPF_MAP_LOOKUP_BATCH, fd, in_batch,
4938c2ecf20Sopenharmony_ci				    out_batch, keys, values, count, opts);
4948c2ecf20Sopenharmony_ci}
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ciint bpf_map_lookup_and_delete_batch(int fd, void *in_batch, void *out_batch,
4978c2ecf20Sopenharmony_ci				    void *keys, void *values, __u32 *count,
4988c2ecf20Sopenharmony_ci				    const struct bpf_map_batch_opts *opts)
4998c2ecf20Sopenharmony_ci{
5008c2ecf20Sopenharmony_ci	return bpf_map_batch_common(BPF_MAP_LOOKUP_AND_DELETE_BATCH,
5018c2ecf20Sopenharmony_ci				    fd, in_batch, out_batch, keys, values,
5028c2ecf20Sopenharmony_ci				    count, opts);
5038c2ecf20Sopenharmony_ci}
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_ciint bpf_map_update_batch(int fd, void *keys, void *values, __u32 *count,
5068c2ecf20Sopenharmony_ci			 const struct bpf_map_batch_opts *opts)
5078c2ecf20Sopenharmony_ci{
5088c2ecf20Sopenharmony_ci	return bpf_map_batch_common(BPF_MAP_UPDATE_BATCH, fd, NULL, NULL,
5098c2ecf20Sopenharmony_ci				    keys, values, count, opts);
5108c2ecf20Sopenharmony_ci}
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_ciint bpf_obj_pin(int fd, const char *pathname)
5138c2ecf20Sopenharmony_ci{
5148c2ecf20Sopenharmony_ci	union bpf_attr attr;
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_ci	memset(&attr, 0, sizeof(attr));
5178c2ecf20Sopenharmony_ci	attr.pathname = ptr_to_u64((void *)pathname);
5188c2ecf20Sopenharmony_ci	attr.bpf_fd = fd;
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_ci	return sys_bpf(BPF_OBJ_PIN, &attr, sizeof(attr));
5218c2ecf20Sopenharmony_ci}
5228c2ecf20Sopenharmony_ci
5238c2ecf20Sopenharmony_ciint bpf_obj_get(const char *pathname)
5248c2ecf20Sopenharmony_ci{
5258c2ecf20Sopenharmony_ci	union bpf_attr attr;
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_ci	memset(&attr, 0, sizeof(attr));
5288c2ecf20Sopenharmony_ci	attr.pathname = ptr_to_u64((void *)pathname);
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_ci	return sys_bpf(BPF_OBJ_GET, &attr, sizeof(attr));
5318c2ecf20Sopenharmony_ci}
5328c2ecf20Sopenharmony_ci
5338c2ecf20Sopenharmony_ciint bpf_prog_attach(int prog_fd, int target_fd, enum bpf_attach_type type,
5348c2ecf20Sopenharmony_ci		    unsigned int flags)
5358c2ecf20Sopenharmony_ci{
5368c2ecf20Sopenharmony_ci	DECLARE_LIBBPF_OPTS(bpf_prog_attach_opts, opts,
5378c2ecf20Sopenharmony_ci		.flags = flags,
5388c2ecf20Sopenharmony_ci	);
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci	return bpf_prog_attach_xattr(prog_fd, target_fd, type, &opts);
5418c2ecf20Sopenharmony_ci}
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ciint bpf_prog_attach_xattr(int prog_fd, int target_fd,
5448c2ecf20Sopenharmony_ci			  enum bpf_attach_type type,
5458c2ecf20Sopenharmony_ci			  const struct bpf_prog_attach_opts *opts)
5468c2ecf20Sopenharmony_ci{
5478c2ecf20Sopenharmony_ci	union bpf_attr attr;
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci	if (!OPTS_VALID(opts, bpf_prog_attach_opts))
5508c2ecf20Sopenharmony_ci		return -EINVAL;
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_ci	memset(&attr, 0, sizeof(attr));
5538c2ecf20Sopenharmony_ci	attr.target_fd	   = target_fd;
5548c2ecf20Sopenharmony_ci	attr.attach_bpf_fd = prog_fd;
5558c2ecf20Sopenharmony_ci	attr.attach_type   = type;
5568c2ecf20Sopenharmony_ci	attr.attach_flags  = OPTS_GET(opts, flags, 0);
5578c2ecf20Sopenharmony_ci	attr.replace_bpf_fd = OPTS_GET(opts, replace_prog_fd, 0);
5588c2ecf20Sopenharmony_ci
5598c2ecf20Sopenharmony_ci	return sys_bpf(BPF_PROG_ATTACH, &attr, sizeof(attr));
5608c2ecf20Sopenharmony_ci}
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ciint bpf_prog_detach(int target_fd, enum bpf_attach_type type)
5638c2ecf20Sopenharmony_ci{
5648c2ecf20Sopenharmony_ci	union bpf_attr attr;
5658c2ecf20Sopenharmony_ci
5668c2ecf20Sopenharmony_ci	memset(&attr, 0, sizeof(attr));
5678c2ecf20Sopenharmony_ci	attr.target_fd	 = target_fd;
5688c2ecf20Sopenharmony_ci	attr.attach_type = type;
5698c2ecf20Sopenharmony_ci
5708c2ecf20Sopenharmony_ci	return sys_bpf(BPF_PROG_DETACH, &attr, sizeof(attr));
5718c2ecf20Sopenharmony_ci}
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_ciint bpf_prog_detach2(int prog_fd, int target_fd, enum bpf_attach_type type)
5748c2ecf20Sopenharmony_ci{
5758c2ecf20Sopenharmony_ci	union bpf_attr attr;
5768c2ecf20Sopenharmony_ci
5778c2ecf20Sopenharmony_ci	memset(&attr, 0, sizeof(attr));
5788c2ecf20Sopenharmony_ci	attr.target_fd	 = target_fd;
5798c2ecf20Sopenharmony_ci	attr.attach_bpf_fd = prog_fd;
5808c2ecf20Sopenharmony_ci	attr.attach_type = type;
5818c2ecf20Sopenharmony_ci
5828c2ecf20Sopenharmony_ci	return sys_bpf(BPF_PROG_DETACH, &attr, sizeof(attr));
5838c2ecf20Sopenharmony_ci}
5848c2ecf20Sopenharmony_ci
5858c2ecf20Sopenharmony_ciint bpf_link_create(int prog_fd, int target_fd,
5868c2ecf20Sopenharmony_ci		    enum bpf_attach_type attach_type,
5878c2ecf20Sopenharmony_ci		    const struct bpf_link_create_opts *opts)
5888c2ecf20Sopenharmony_ci{
5898c2ecf20Sopenharmony_ci	__u32 target_btf_id, iter_info_len;
5908c2ecf20Sopenharmony_ci	union bpf_attr attr;
5918c2ecf20Sopenharmony_ci
5928c2ecf20Sopenharmony_ci	if (!OPTS_VALID(opts, bpf_link_create_opts))
5938c2ecf20Sopenharmony_ci		return -EINVAL;
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci	iter_info_len = OPTS_GET(opts, iter_info_len, 0);
5968c2ecf20Sopenharmony_ci	target_btf_id = OPTS_GET(opts, target_btf_id, 0);
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_ci	if (iter_info_len && target_btf_id)
5998c2ecf20Sopenharmony_ci		return -EINVAL;
6008c2ecf20Sopenharmony_ci
6018c2ecf20Sopenharmony_ci	memset(&attr, 0, sizeof(attr));
6028c2ecf20Sopenharmony_ci	attr.link_create.prog_fd = prog_fd;
6038c2ecf20Sopenharmony_ci	attr.link_create.target_fd = target_fd;
6048c2ecf20Sopenharmony_ci	attr.link_create.attach_type = attach_type;
6058c2ecf20Sopenharmony_ci	attr.link_create.flags = OPTS_GET(opts, flags, 0);
6068c2ecf20Sopenharmony_ci
6078c2ecf20Sopenharmony_ci	if (iter_info_len) {
6088c2ecf20Sopenharmony_ci		attr.link_create.iter_info =
6098c2ecf20Sopenharmony_ci			ptr_to_u64(OPTS_GET(opts, iter_info, (void *)0));
6108c2ecf20Sopenharmony_ci		attr.link_create.iter_info_len = iter_info_len;
6118c2ecf20Sopenharmony_ci	} else if (target_btf_id) {
6128c2ecf20Sopenharmony_ci		attr.link_create.target_btf_id = target_btf_id;
6138c2ecf20Sopenharmony_ci	}
6148c2ecf20Sopenharmony_ci
6158c2ecf20Sopenharmony_ci	return sys_bpf(BPF_LINK_CREATE, &attr, sizeof(attr));
6168c2ecf20Sopenharmony_ci}
6178c2ecf20Sopenharmony_ci
6188c2ecf20Sopenharmony_ciint bpf_link_detach(int link_fd)
6198c2ecf20Sopenharmony_ci{
6208c2ecf20Sopenharmony_ci	union bpf_attr attr;
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_ci	memset(&attr, 0, sizeof(attr));
6238c2ecf20Sopenharmony_ci	attr.link_detach.link_fd = link_fd;
6248c2ecf20Sopenharmony_ci
6258c2ecf20Sopenharmony_ci	return sys_bpf(BPF_LINK_DETACH, &attr, sizeof(attr));
6268c2ecf20Sopenharmony_ci}
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_ciint bpf_link_update(int link_fd, int new_prog_fd,
6298c2ecf20Sopenharmony_ci		    const struct bpf_link_update_opts *opts)
6308c2ecf20Sopenharmony_ci{
6318c2ecf20Sopenharmony_ci	union bpf_attr attr;
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_ci	if (!OPTS_VALID(opts, bpf_link_update_opts))
6348c2ecf20Sopenharmony_ci		return -EINVAL;
6358c2ecf20Sopenharmony_ci
6368c2ecf20Sopenharmony_ci	memset(&attr, 0, sizeof(attr));
6378c2ecf20Sopenharmony_ci	attr.link_update.link_fd = link_fd;
6388c2ecf20Sopenharmony_ci	attr.link_update.new_prog_fd = new_prog_fd;
6398c2ecf20Sopenharmony_ci	attr.link_update.flags = OPTS_GET(opts, flags, 0);
6408c2ecf20Sopenharmony_ci	attr.link_update.old_prog_fd = OPTS_GET(opts, old_prog_fd, 0);
6418c2ecf20Sopenharmony_ci
6428c2ecf20Sopenharmony_ci	return sys_bpf(BPF_LINK_UPDATE, &attr, sizeof(attr));
6438c2ecf20Sopenharmony_ci}
6448c2ecf20Sopenharmony_ci
6458c2ecf20Sopenharmony_ciint bpf_iter_create(int link_fd)
6468c2ecf20Sopenharmony_ci{
6478c2ecf20Sopenharmony_ci	union bpf_attr attr;
6488c2ecf20Sopenharmony_ci
6498c2ecf20Sopenharmony_ci	memset(&attr, 0, sizeof(attr));
6508c2ecf20Sopenharmony_ci	attr.iter_create.link_fd = link_fd;
6518c2ecf20Sopenharmony_ci
6528c2ecf20Sopenharmony_ci	return sys_bpf(BPF_ITER_CREATE, &attr, sizeof(attr));
6538c2ecf20Sopenharmony_ci}
6548c2ecf20Sopenharmony_ci
6558c2ecf20Sopenharmony_ciint bpf_prog_query(int target_fd, enum bpf_attach_type type, __u32 query_flags,
6568c2ecf20Sopenharmony_ci		   __u32 *attach_flags, __u32 *prog_ids, __u32 *prog_cnt)
6578c2ecf20Sopenharmony_ci{
6588c2ecf20Sopenharmony_ci	union bpf_attr attr;
6598c2ecf20Sopenharmony_ci	int ret;
6608c2ecf20Sopenharmony_ci
6618c2ecf20Sopenharmony_ci	memset(&attr, 0, sizeof(attr));
6628c2ecf20Sopenharmony_ci	attr.query.target_fd	= target_fd;
6638c2ecf20Sopenharmony_ci	attr.query.attach_type	= type;
6648c2ecf20Sopenharmony_ci	attr.query.query_flags	= query_flags;
6658c2ecf20Sopenharmony_ci	attr.query.prog_cnt	= *prog_cnt;
6668c2ecf20Sopenharmony_ci	attr.query.prog_ids	= ptr_to_u64(prog_ids);
6678c2ecf20Sopenharmony_ci
6688c2ecf20Sopenharmony_ci	ret = sys_bpf(BPF_PROG_QUERY, &attr, sizeof(attr));
6698c2ecf20Sopenharmony_ci	if (attach_flags)
6708c2ecf20Sopenharmony_ci		*attach_flags = attr.query.attach_flags;
6718c2ecf20Sopenharmony_ci	*prog_cnt = attr.query.prog_cnt;
6728c2ecf20Sopenharmony_ci	return ret;
6738c2ecf20Sopenharmony_ci}
6748c2ecf20Sopenharmony_ci
6758c2ecf20Sopenharmony_ciint bpf_prog_test_run(int prog_fd, int repeat, void *data, __u32 size,
6768c2ecf20Sopenharmony_ci		      void *data_out, __u32 *size_out, __u32 *retval,
6778c2ecf20Sopenharmony_ci		      __u32 *duration)
6788c2ecf20Sopenharmony_ci{
6798c2ecf20Sopenharmony_ci	union bpf_attr attr;
6808c2ecf20Sopenharmony_ci	int ret;
6818c2ecf20Sopenharmony_ci
6828c2ecf20Sopenharmony_ci	memset(&attr, 0, sizeof(attr));
6838c2ecf20Sopenharmony_ci	attr.test.prog_fd = prog_fd;
6848c2ecf20Sopenharmony_ci	attr.test.data_in = ptr_to_u64(data);
6858c2ecf20Sopenharmony_ci	attr.test.data_out = ptr_to_u64(data_out);
6868c2ecf20Sopenharmony_ci	attr.test.data_size_in = size;
6878c2ecf20Sopenharmony_ci	attr.test.repeat = repeat;
6888c2ecf20Sopenharmony_ci
6898c2ecf20Sopenharmony_ci	ret = sys_bpf(BPF_PROG_TEST_RUN, &attr, sizeof(attr));
6908c2ecf20Sopenharmony_ci	if (size_out)
6918c2ecf20Sopenharmony_ci		*size_out = attr.test.data_size_out;
6928c2ecf20Sopenharmony_ci	if (retval)
6938c2ecf20Sopenharmony_ci		*retval = attr.test.retval;
6948c2ecf20Sopenharmony_ci	if (duration)
6958c2ecf20Sopenharmony_ci		*duration = attr.test.duration;
6968c2ecf20Sopenharmony_ci	return ret;
6978c2ecf20Sopenharmony_ci}
6988c2ecf20Sopenharmony_ci
6998c2ecf20Sopenharmony_ciint bpf_prog_test_run_xattr(struct bpf_prog_test_run_attr *test_attr)
7008c2ecf20Sopenharmony_ci{
7018c2ecf20Sopenharmony_ci	union bpf_attr attr;
7028c2ecf20Sopenharmony_ci	int ret;
7038c2ecf20Sopenharmony_ci
7048c2ecf20Sopenharmony_ci	if (!test_attr->data_out && test_attr->data_size_out > 0)
7058c2ecf20Sopenharmony_ci		return -EINVAL;
7068c2ecf20Sopenharmony_ci
7078c2ecf20Sopenharmony_ci	memset(&attr, 0, sizeof(attr));
7088c2ecf20Sopenharmony_ci	attr.test.prog_fd = test_attr->prog_fd;
7098c2ecf20Sopenharmony_ci	attr.test.data_in = ptr_to_u64(test_attr->data_in);
7108c2ecf20Sopenharmony_ci	attr.test.data_out = ptr_to_u64(test_attr->data_out);
7118c2ecf20Sopenharmony_ci	attr.test.data_size_in = test_attr->data_size_in;
7128c2ecf20Sopenharmony_ci	attr.test.data_size_out = test_attr->data_size_out;
7138c2ecf20Sopenharmony_ci	attr.test.ctx_in = ptr_to_u64(test_attr->ctx_in);
7148c2ecf20Sopenharmony_ci	attr.test.ctx_out = ptr_to_u64(test_attr->ctx_out);
7158c2ecf20Sopenharmony_ci	attr.test.ctx_size_in = test_attr->ctx_size_in;
7168c2ecf20Sopenharmony_ci	attr.test.ctx_size_out = test_attr->ctx_size_out;
7178c2ecf20Sopenharmony_ci	attr.test.repeat = test_attr->repeat;
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_ci	ret = sys_bpf(BPF_PROG_TEST_RUN, &attr, sizeof(attr));
7208c2ecf20Sopenharmony_ci	test_attr->data_size_out = attr.test.data_size_out;
7218c2ecf20Sopenharmony_ci	test_attr->ctx_size_out = attr.test.ctx_size_out;
7228c2ecf20Sopenharmony_ci	test_attr->retval = attr.test.retval;
7238c2ecf20Sopenharmony_ci	test_attr->duration = attr.test.duration;
7248c2ecf20Sopenharmony_ci	return ret;
7258c2ecf20Sopenharmony_ci}
7268c2ecf20Sopenharmony_ci
7278c2ecf20Sopenharmony_ciint bpf_prog_test_run_opts(int prog_fd, struct bpf_test_run_opts *opts)
7288c2ecf20Sopenharmony_ci{
7298c2ecf20Sopenharmony_ci	union bpf_attr attr;
7308c2ecf20Sopenharmony_ci	int ret;
7318c2ecf20Sopenharmony_ci
7328c2ecf20Sopenharmony_ci	if (!OPTS_VALID(opts, bpf_test_run_opts))
7338c2ecf20Sopenharmony_ci		return -EINVAL;
7348c2ecf20Sopenharmony_ci
7358c2ecf20Sopenharmony_ci	memset(&attr, 0, sizeof(attr));
7368c2ecf20Sopenharmony_ci	attr.test.prog_fd = prog_fd;
7378c2ecf20Sopenharmony_ci	attr.test.cpu = OPTS_GET(opts, cpu, 0);
7388c2ecf20Sopenharmony_ci	attr.test.flags = OPTS_GET(opts, flags, 0);
7398c2ecf20Sopenharmony_ci	attr.test.repeat = OPTS_GET(opts, repeat, 0);
7408c2ecf20Sopenharmony_ci	attr.test.duration = OPTS_GET(opts, duration, 0);
7418c2ecf20Sopenharmony_ci	attr.test.ctx_size_in = OPTS_GET(opts, ctx_size_in, 0);
7428c2ecf20Sopenharmony_ci	attr.test.ctx_size_out = OPTS_GET(opts, ctx_size_out, 0);
7438c2ecf20Sopenharmony_ci	attr.test.data_size_in = OPTS_GET(opts, data_size_in, 0);
7448c2ecf20Sopenharmony_ci	attr.test.data_size_out = OPTS_GET(opts, data_size_out, 0);
7458c2ecf20Sopenharmony_ci	attr.test.ctx_in = ptr_to_u64(OPTS_GET(opts, ctx_in, NULL));
7468c2ecf20Sopenharmony_ci	attr.test.ctx_out = ptr_to_u64(OPTS_GET(opts, ctx_out, NULL));
7478c2ecf20Sopenharmony_ci	attr.test.data_in = ptr_to_u64(OPTS_GET(opts, data_in, NULL));
7488c2ecf20Sopenharmony_ci	attr.test.data_out = ptr_to_u64(OPTS_GET(opts, data_out, NULL));
7498c2ecf20Sopenharmony_ci
7508c2ecf20Sopenharmony_ci	ret = sys_bpf(BPF_PROG_TEST_RUN, &attr, sizeof(attr));
7518c2ecf20Sopenharmony_ci	OPTS_SET(opts, data_size_out, attr.test.data_size_out);
7528c2ecf20Sopenharmony_ci	OPTS_SET(opts, ctx_size_out, attr.test.ctx_size_out);
7538c2ecf20Sopenharmony_ci	OPTS_SET(opts, duration, attr.test.duration);
7548c2ecf20Sopenharmony_ci	OPTS_SET(opts, retval, attr.test.retval);
7558c2ecf20Sopenharmony_ci	return ret;
7568c2ecf20Sopenharmony_ci}
7578c2ecf20Sopenharmony_ci
7588c2ecf20Sopenharmony_cistatic int bpf_obj_get_next_id(__u32 start_id, __u32 *next_id, int cmd)
7598c2ecf20Sopenharmony_ci{
7608c2ecf20Sopenharmony_ci	union bpf_attr attr;
7618c2ecf20Sopenharmony_ci	int err;
7628c2ecf20Sopenharmony_ci
7638c2ecf20Sopenharmony_ci	memset(&attr, 0, sizeof(attr));
7648c2ecf20Sopenharmony_ci	attr.start_id = start_id;
7658c2ecf20Sopenharmony_ci
7668c2ecf20Sopenharmony_ci	err = sys_bpf(cmd, &attr, sizeof(attr));
7678c2ecf20Sopenharmony_ci	if (!err)
7688c2ecf20Sopenharmony_ci		*next_id = attr.next_id;
7698c2ecf20Sopenharmony_ci
7708c2ecf20Sopenharmony_ci	return err;
7718c2ecf20Sopenharmony_ci}
7728c2ecf20Sopenharmony_ci
7738c2ecf20Sopenharmony_ciint bpf_prog_get_next_id(__u32 start_id, __u32 *next_id)
7748c2ecf20Sopenharmony_ci{
7758c2ecf20Sopenharmony_ci	return bpf_obj_get_next_id(start_id, next_id, BPF_PROG_GET_NEXT_ID);
7768c2ecf20Sopenharmony_ci}
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_ciint bpf_map_get_next_id(__u32 start_id, __u32 *next_id)
7798c2ecf20Sopenharmony_ci{
7808c2ecf20Sopenharmony_ci	return bpf_obj_get_next_id(start_id, next_id, BPF_MAP_GET_NEXT_ID);
7818c2ecf20Sopenharmony_ci}
7828c2ecf20Sopenharmony_ci
7838c2ecf20Sopenharmony_ciint bpf_btf_get_next_id(__u32 start_id, __u32 *next_id)
7848c2ecf20Sopenharmony_ci{
7858c2ecf20Sopenharmony_ci	return bpf_obj_get_next_id(start_id, next_id, BPF_BTF_GET_NEXT_ID);
7868c2ecf20Sopenharmony_ci}
7878c2ecf20Sopenharmony_ci
7888c2ecf20Sopenharmony_ciint bpf_link_get_next_id(__u32 start_id, __u32 *next_id)
7898c2ecf20Sopenharmony_ci{
7908c2ecf20Sopenharmony_ci	return bpf_obj_get_next_id(start_id, next_id, BPF_LINK_GET_NEXT_ID);
7918c2ecf20Sopenharmony_ci}
7928c2ecf20Sopenharmony_ci
7938c2ecf20Sopenharmony_ciint bpf_prog_get_fd_by_id(__u32 id)
7948c2ecf20Sopenharmony_ci{
7958c2ecf20Sopenharmony_ci	union bpf_attr attr;
7968c2ecf20Sopenharmony_ci
7978c2ecf20Sopenharmony_ci	memset(&attr, 0, sizeof(attr));
7988c2ecf20Sopenharmony_ci	attr.prog_id = id;
7998c2ecf20Sopenharmony_ci
8008c2ecf20Sopenharmony_ci	return sys_bpf(BPF_PROG_GET_FD_BY_ID, &attr, sizeof(attr));
8018c2ecf20Sopenharmony_ci}
8028c2ecf20Sopenharmony_ci
8038c2ecf20Sopenharmony_ciint bpf_map_get_fd_by_id(__u32 id)
8048c2ecf20Sopenharmony_ci{
8058c2ecf20Sopenharmony_ci	union bpf_attr attr;
8068c2ecf20Sopenharmony_ci
8078c2ecf20Sopenharmony_ci	memset(&attr, 0, sizeof(attr));
8088c2ecf20Sopenharmony_ci	attr.map_id = id;
8098c2ecf20Sopenharmony_ci
8108c2ecf20Sopenharmony_ci	return sys_bpf(BPF_MAP_GET_FD_BY_ID, &attr, sizeof(attr));
8118c2ecf20Sopenharmony_ci}
8128c2ecf20Sopenharmony_ci
8138c2ecf20Sopenharmony_ciint bpf_btf_get_fd_by_id(__u32 id)
8148c2ecf20Sopenharmony_ci{
8158c2ecf20Sopenharmony_ci	union bpf_attr attr;
8168c2ecf20Sopenharmony_ci
8178c2ecf20Sopenharmony_ci	memset(&attr, 0, sizeof(attr));
8188c2ecf20Sopenharmony_ci	attr.btf_id = id;
8198c2ecf20Sopenharmony_ci
8208c2ecf20Sopenharmony_ci	return sys_bpf(BPF_BTF_GET_FD_BY_ID, &attr, sizeof(attr));
8218c2ecf20Sopenharmony_ci}
8228c2ecf20Sopenharmony_ci
8238c2ecf20Sopenharmony_ciint bpf_link_get_fd_by_id(__u32 id)
8248c2ecf20Sopenharmony_ci{
8258c2ecf20Sopenharmony_ci	union bpf_attr attr;
8268c2ecf20Sopenharmony_ci
8278c2ecf20Sopenharmony_ci	memset(&attr, 0, sizeof(attr));
8288c2ecf20Sopenharmony_ci	attr.link_id = id;
8298c2ecf20Sopenharmony_ci
8308c2ecf20Sopenharmony_ci	return sys_bpf(BPF_LINK_GET_FD_BY_ID, &attr, sizeof(attr));
8318c2ecf20Sopenharmony_ci}
8328c2ecf20Sopenharmony_ci
8338c2ecf20Sopenharmony_ciint bpf_obj_get_info_by_fd(int bpf_fd, void *info, __u32 *info_len)
8348c2ecf20Sopenharmony_ci{
8358c2ecf20Sopenharmony_ci	union bpf_attr attr;
8368c2ecf20Sopenharmony_ci	int err;
8378c2ecf20Sopenharmony_ci
8388c2ecf20Sopenharmony_ci	memset(&attr, 0, sizeof(attr));
8398c2ecf20Sopenharmony_ci	attr.info.bpf_fd = bpf_fd;
8408c2ecf20Sopenharmony_ci	attr.info.info_len = *info_len;
8418c2ecf20Sopenharmony_ci	attr.info.info = ptr_to_u64(info);
8428c2ecf20Sopenharmony_ci
8438c2ecf20Sopenharmony_ci	err = sys_bpf(BPF_OBJ_GET_INFO_BY_FD, &attr, sizeof(attr));
8448c2ecf20Sopenharmony_ci	if (!err)
8458c2ecf20Sopenharmony_ci		*info_len = attr.info.info_len;
8468c2ecf20Sopenharmony_ci
8478c2ecf20Sopenharmony_ci	return err;
8488c2ecf20Sopenharmony_ci}
8498c2ecf20Sopenharmony_ci
8508c2ecf20Sopenharmony_ciint bpf_raw_tracepoint_open(const char *name, int prog_fd)
8518c2ecf20Sopenharmony_ci{
8528c2ecf20Sopenharmony_ci	union bpf_attr attr;
8538c2ecf20Sopenharmony_ci
8548c2ecf20Sopenharmony_ci	memset(&attr, 0, sizeof(attr));
8558c2ecf20Sopenharmony_ci	attr.raw_tracepoint.name = ptr_to_u64(name);
8568c2ecf20Sopenharmony_ci	attr.raw_tracepoint.prog_fd = prog_fd;
8578c2ecf20Sopenharmony_ci
8588c2ecf20Sopenharmony_ci	return sys_bpf(BPF_RAW_TRACEPOINT_OPEN, &attr, sizeof(attr));
8598c2ecf20Sopenharmony_ci}
8608c2ecf20Sopenharmony_ci
8618c2ecf20Sopenharmony_ciint bpf_load_btf(const void *btf, __u32 btf_size, char *log_buf, __u32 log_buf_size,
8628c2ecf20Sopenharmony_ci		 bool do_log)
8638c2ecf20Sopenharmony_ci{
8648c2ecf20Sopenharmony_ci	union bpf_attr attr = {};
8658c2ecf20Sopenharmony_ci	int fd;
8668c2ecf20Sopenharmony_ci
8678c2ecf20Sopenharmony_ci	attr.btf = ptr_to_u64(btf);
8688c2ecf20Sopenharmony_ci	attr.btf_size = btf_size;
8698c2ecf20Sopenharmony_ci
8708c2ecf20Sopenharmony_ciretry:
8718c2ecf20Sopenharmony_ci	if (do_log && log_buf && log_buf_size) {
8728c2ecf20Sopenharmony_ci		attr.btf_log_level = 1;
8738c2ecf20Sopenharmony_ci		attr.btf_log_size = log_buf_size;
8748c2ecf20Sopenharmony_ci		attr.btf_log_buf = ptr_to_u64(log_buf);
8758c2ecf20Sopenharmony_ci	}
8768c2ecf20Sopenharmony_ci
8778c2ecf20Sopenharmony_ci	fd = sys_bpf(BPF_BTF_LOAD, &attr, sizeof(attr));
8788c2ecf20Sopenharmony_ci	if (fd == -1 && !do_log && log_buf && log_buf_size) {
8798c2ecf20Sopenharmony_ci		do_log = true;
8808c2ecf20Sopenharmony_ci		goto retry;
8818c2ecf20Sopenharmony_ci	}
8828c2ecf20Sopenharmony_ci
8838c2ecf20Sopenharmony_ci	return fd;
8848c2ecf20Sopenharmony_ci}
8858c2ecf20Sopenharmony_ci
8868c2ecf20Sopenharmony_ciint bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf, __u32 *buf_len,
8878c2ecf20Sopenharmony_ci		      __u32 *prog_id, __u32 *fd_type, __u64 *probe_offset,
8888c2ecf20Sopenharmony_ci		      __u64 *probe_addr)
8898c2ecf20Sopenharmony_ci{
8908c2ecf20Sopenharmony_ci	union bpf_attr attr = {};
8918c2ecf20Sopenharmony_ci	int err;
8928c2ecf20Sopenharmony_ci
8938c2ecf20Sopenharmony_ci	attr.task_fd_query.pid = pid;
8948c2ecf20Sopenharmony_ci	attr.task_fd_query.fd = fd;
8958c2ecf20Sopenharmony_ci	attr.task_fd_query.flags = flags;
8968c2ecf20Sopenharmony_ci	attr.task_fd_query.buf = ptr_to_u64(buf);
8978c2ecf20Sopenharmony_ci	attr.task_fd_query.buf_len = *buf_len;
8988c2ecf20Sopenharmony_ci
8998c2ecf20Sopenharmony_ci	err = sys_bpf(BPF_TASK_FD_QUERY, &attr, sizeof(attr));
9008c2ecf20Sopenharmony_ci	*buf_len = attr.task_fd_query.buf_len;
9018c2ecf20Sopenharmony_ci	*prog_id = attr.task_fd_query.prog_id;
9028c2ecf20Sopenharmony_ci	*fd_type = attr.task_fd_query.fd_type;
9038c2ecf20Sopenharmony_ci	*probe_offset = attr.task_fd_query.probe_offset;
9048c2ecf20Sopenharmony_ci	*probe_addr = attr.task_fd_query.probe_addr;
9058c2ecf20Sopenharmony_ci
9068c2ecf20Sopenharmony_ci	return err;
9078c2ecf20Sopenharmony_ci}
9088c2ecf20Sopenharmony_ci
9098c2ecf20Sopenharmony_ciint bpf_enable_stats(enum bpf_stats_type type)
9108c2ecf20Sopenharmony_ci{
9118c2ecf20Sopenharmony_ci	union bpf_attr attr;
9128c2ecf20Sopenharmony_ci
9138c2ecf20Sopenharmony_ci	memset(&attr, 0, sizeof(attr));
9148c2ecf20Sopenharmony_ci	attr.enable_stats.type = type;
9158c2ecf20Sopenharmony_ci
9168c2ecf20Sopenharmony_ci	return sys_bpf(BPF_ENABLE_STATS, &attr, sizeof(attr));
9178c2ecf20Sopenharmony_ci}
9188c2ecf20Sopenharmony_ci
9198c2ecf20Sopenharmony_ciint bpf_prog_bind_map(int prog_fd, int map_fd,
9208c2ecf20Sopenharmony_ci		      const struct bpf_prog_bind_opts *opts)
9218c2ecf20Sopenharmony_ci{
9228c2ecf20Sopenharmony_ci	union bpf_attr attr;
9238c2ecf20Sopenharmony_ci
9248c2ecf20Sopenharmony_ci	if (!OPTS_VALID(opts, bpf_prog_bind_opts))
9258c2ecf20Sopenharmony_ci		return -EINVAL;
9268c2ecf20Sopenharmony_ci
9278c2ecf20Sopenharmony_ci	memset(&attr, 0, sizeof(attr));
9288c2ecf20Sopenharmony_ci	attr.prog_bind_map.prog_fd = prog_fd;
9298c2ecf20Sopenharmony_ci	attr.prog_bind_map.map_fd = map_fd;
9308c2ecf20Sopenharmony_ci	attr.prog_bind_map.flags = OPTS_GET(opts, flags, 0);
9318c2ecf20Sopenharmony_ci
9328c2ecf20Sopenharmony_ci	return sys_bpf(BPF_PROG_BIND_MAP, &attr, sizeof(attr));
9338c2ecf20Sopenharmony_ci}
934