18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 28c2ecf20Sopenharmony_ci/* Copyright (c) 2019 Netronome Systems, Inc. */ 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci#include <errno.h> 58c2ecf20Sopenharmony_ci#include <fcntl.h> 68c2ecf20Sopenharmony_ci#include <string.h> 78c2ecf20Sopenharmony_ci#include <stdlib.h> 88c2ecf20Sopenharmony_ci#include <unistd.h> 98c2ecf20Sopenharmony_ci#include <net/if.h> 108c2ecf20Sopenharmony_ci#include <sys/utsname.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <linux/btf.h> 138c2ecf20Sopenharmony_ci#include <linux/filter.h> 148c2ecf20Sopenharmony_ci#include <linux/kernel.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include "bpf.h" 178c2ecf20Sopenharmony_ci#include "libbpf.h" 188c2ecf20Sopenharmony_ci#include "libbpf_internal.h" 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_cistatic bool grep(const char *buffer, const char *pattern) 218c2ecf20Sopenharmony_ci{ 228c2ecf20Sopenharmony_ci return !!strstr(buffer, pattern); 238c2ecf20Sopenharmony_ci} 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_cistatic int get_vendor_id(int ifindex) 268c2ecf20Sopenharmony_ci{ 278c2ecf20Sopenharmony_ci char ifname[IF_NAMESIZE], path[64], buf[8]; 288c2ecf20Sopenharmony_ci ssize_t len; 298c2ecf20Sopenharmony_ci int fd; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci if (!if_indextoname(ifindex, ifname)) 328c2ecf20Sopenharmony_ci return -1; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci snprintf(path, sizeof(path), "/sys/class/net/%s/device/vendor", ifname); 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci fd = open(path, O_RDONLY); 378c2ecf20Sopenharmony_ci if (fd < 0) 388c2ecf20Sopenharmony_ci return -1; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci len = read(fd, buf, sizeof(buf)); 418c2ecf20Sopenharmony_ci close(fd); 428c2ecf20Sopenharmony_ci if (len < 0) 438c2ecf20Sopenharmony_ci return -1; 448c2ecf20Sopenharmony_ci if (len >= (ssize_t)sizeof(buf)) 458c2ecf20Sopenharmony_ci return -1; 468c2ecf20Sopenharmony_ci buf[len] = '\0'; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci return strtol(buf, NULL, 0); 498c2ecf20Sopenharmony_ci} 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_cistatic int get_kernel_version(void) 528c2ecf20Sopenharmony_ci{ 538c2ecf20Sopenharmony_ci int version, subversion, patchlevel; 548c2ecf20Sopenharmony_ci struct utsname utsn; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci /* Return 0 on failure, and attempt to probe with empty kversion */ 578c2ecf20Sopenharmony_ci if (uname(&utsn)) 588c2ecf20Sopenharmony_ci return 0; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci if (sscanf(utsn.release, "%d.%d.%d", 618c2ecf20Sopenharmony_ci &version, &subversion, &patchlevel) != 3) 628c2ecf20Sopenharmony_ci return 0; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci return (version << 16) + (subversion << 8) + patchlevel; 658c2ecf20Sopenharmony_ci} 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_cistatic void 688c2ecf20Sopenharmony_ciprobe_load(enum bpf_prog_type prog_type, const struct bpf_insn *insns, 698c2ecf20Sopenharmony_ci size_t insns_cnt, char *buf, size_t buf_len, __u32 ifindex) 708c2ecf20Sopenharmony_ci{ 718c2ecf20Sopenharmony_ci struct bpf_load_program_attr xattr = {}; 728c2ecf20Sopenharmony_ci int fd; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci switch (prog_type) { 758c2ecf20Sopenharmony_ci case BPF_PROG_TYPE_CGROUP_SOCK_ADDR: 768c2ecf20Sopenharmony_ci xattr.expected_attach_type = BPF_CGROUP_INET4_CONNECT; 778c2ecf20Sopenharmony_ci break; 788c2ecf20Sopenharmony_ci case BPF_PROG_TYPE_CGROUP_SOCKOPT: 798c2ecf20Sopenharmony_ci xattr.expected_attach_type = BPF_CGROUP_GETSOCKOPT; 808c2ecf20Sopenharmony_ci break; 818c2ecf20Sopenharmony_ci case BPF_PROG_TYPE_SK_LOOKUP: 828c2ecf20Sopenharmony_ci xattr.expected_attach_type = BPF_SK_LOOKUP; 838c2ecf20Sopenharmony_ci break; 848c2ecf20Sopenharmony_ci case BPF_PROG_TYPE_KPROBE: 858c2ecf20Sopenharmony_ci xattr.kern_version = get_kernel_version(); 868c2ecf20Sopenharmony_ci break; 878c2ecf20Sopenharmony_ci case BPF_PROG_TYPE_UNSPEC: 888c2ecf20Sopenharmony_ci case BPF_PROG_TYPE_SOCKET_FILTER: 898c2ecf20Sopenharmony_ci case BPF_PROG_TYPE_SCHED_CLS: 908c2ecf20Sopenharmony_ci case BPF_PROG_TYPE_SCHED_ACT: 918c2ecf20Sopenharmony_ci case BPF_PROG_TYPE_TRACEPOINT: 928c2ecf20Sopenharmony_ci case BPF_PROG_TYPE_XDP: 938c2ecf20Sopenharmony_ci case BPF_PROG_TYPE_PERF_EVENT: 948c2ecf20Sopenharmony_ci case BPF_PROG_TYPE_CGROUP_SKB: 958c2ecf20Sopenharmony_ci case BPF_PROG_TYPE_CGROUP_SOCK: 968c2ecf20Sopenharmony_ci case BPF_PROG_TYPE_LWT_IN: 978c2ecf20Sopenharmony_ci case BPF_PROG_TYPE_LWT_OUT: 988c2ecf20Sopenharmony_ci case BPF_PROG_TYPE_LWT_XMIT: 998c2ecf20Sopenharmony_ci case BPF_PROG_TYPE_SOCK_OPS: 1008c2ecf20Sopenharmony_ci case BPF_PROG_TYPE_SK_SKB: 1018c2ecf20Sopenharmony_ci case BPF_PROG_TYPE_CGROUP_DEVICE: 1028c2ecf20Sopenharmony_ci case BPF_PROG_TYPE_SK_MSG: 1038c2ecf20Sopenharmony_ci case BPF_PROG_TYPE_RAW_TRACEPOINT: 1048c2ecf20Sopenharmony_ci case BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE: 1058c2ecf20Sopenharmony_ci case BPF_PROG_TYPE_LWT_SEG6LOCAL: 1068c2ecf20Sopenharmony_ci case BPF_PROG_TYPE_LIRC_MODE2: 1078c2ecf20Sopenharmony_ci case BPF_PROG_TYPE_SK_REUSEPORT: 1088c2ecf20Sopenharmony_ci case BPF_PROG_TYPE_FLOW_DISSECTOR: 1098c2ecf20Sopenharmony_ci case BPF_PROG_TYPE_CGROUP_SYSCTL: 1108c2ecf20Sopenharmony_ci case BPF_PROG_TYPE_TRACING: 1118c2ecf20Sopenharmony_ci case BPF_PROG_TYPE_STRUCT_OPS: 1128c2ecf20Sopenharmony_ci case BPF_PROG_TYPE_EXT: 1138c2ecf20Sopenharmony_ci case BPF_PROG_TYPE_LSM: 1148c2ecf20Sopenharmony_ci default: 1158c2ecf20Sopenharmony_ci break; 1168c2ecf20Sopenharmony_ci } 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci xattr.prog_type = prog_type; 1198c2ecf20Sopenharmony_ci xattr.insns = insns; 1208c2ecf20Sopenharmony_ci xattr.insns_cnt = insns_cnt; 1218c2ecf20Sopenharmony_ci xattr.license = "GPL"; 1228c2ecf20Sopenharmony_ci xattr.prog_ifindex = ifindex; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci fd = bpf_load_program_xattr(&xattr, buf, buf_len); 1258c2ecf20Sopenharmony_ci if (fd >= 0) 1268c2ecf20Sopenharmony_ci close(fd); 1278c2ecf20Sopenharmony_ci} 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_cibool bpf_probe_prog_type(enum bpf_prog_type prog_type, __u32 ifindex) 1308c2ecf20Sopenharmony_ci{ 1318c2ecf20Sopenharmony_ci struct bpf_insn insns[2] = { 1328c2ecf20Sopenharmony_ci BPF_MOV64_IMM(BPF_REG_0, 0), 1338c2ecf20Sopenharmony_ci BPF_EXIT_INSN() 1348c2ecf20Sopenharmony_ci }; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci if (ifindex && prog_type == BPF_PROG_TYPE_SCHED_CLS) 1378c2ecf20Sopenharmony_ci /* nfp returns -EINVAL on exit(0) with TC offload */ 1388c2ecf20Sopenharmony_ci insns[0].imm = 2; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci errno = 0; 1418c2ecf20Sopenharmony_ci probe_load(prog_type, insns, ARRAY_SIZE(insns), NULL, 0, ifindex); 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci return errno != EINVAL && errno != EOPNOTSUPP; 1448c2ecf20Sopenharmony_ci} 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ciint libbpf__load_raw_btf(const char *raw_types, size_t types_len, 1478c2ecf20Sopenharmony_ci const char *str_sec, size_t str_len) 1488c2ecf20Sopenharmony_ci{ 1498c2ecf20Sopenharmony_ci struct btf_header hdr = { 1508c2ecf20Sopenharmony_ci .magic = BTF_MAGIC, 1518c2ecf20Sopenharmony_ci .version = BTF_VERSION, 1528c2ecf20Sopenharmony_ci .hdr_len = sizeof(struct btf_header), 1538c2ecf20Sopenharmony_ci .type_len = types_len, 1548c2ecf20Sopenharmony_ci .str_off = types_len, 1558c2ecf20Sopenharmony_ci .str_len = str_len, 1568c2ecf20Sopenharmony_ci }; 1578c2ecf20Sopenharmony_ci int btf_fd, btf_len; 1588c2ecf20Sopenharmony_ci __u8 *raw_btf; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci btf_len = hdr.hdr_len + hdr.type_len + hdr.str_len; 1618c2ecf20Sopenharmony_ci raw_btf = malloc(btf_len); 1628c2ecf20Sopenharmony_ci if (!raw_btf) 1638c2ecf20Sopenharmony_ci return -ENOMEM; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci memcpy(raw_btf, &hdr, sizeof(hdr)); 1668c2ecf20Sopenharmony_ci memcpy(raw_btf + hdr.hdr_len, raw_types, hdr.type_len); 1678c2ecf20Sopenharmony_ci memcpy(raw_btf + hdr.hdr_len + hdr.type_len, str_sec, hdr.str_len); 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci btf_fd = bpf_load_btf(raw_btf, btf_len, NULL, 0, false); 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci free(raw_btf); 1728c2ecf20Sopenharmony_ci return btf_fd; 1738c2ecf20Sopenharmony_ci} 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_cistatic int load_local_storage_btf(void) 1768c2ecf20Sopenharmony_ci{ 1778c2ecf20Sopenharmony_ci const char strs[] = "\0bpf_spin_lock\0val\0cnt\0l"; 1788c2ecf20Sopenharmony_ci /* struct bpf_spin_lock { 1798c2ecf20Sopenharmony_ci * int val; 1808c2ecf20Sopenharmony_ci * }; 1818c2ecf20Sopenharmony_ci * struct val { 1828c2ecf20Sopenharmony_ci * int cnt; 1838c2ecf20Sopenharmony_ci * struct bpf_spin_lock l; 1848c2ecf20Sopenharmony_ci * }; 1858c2ecf20Sopenharmony_ci */ 1868c2ecf20Sopenharmony_ci __u32 types[] = { 1878c2ecf20Sopenharmony_ci /* int */ 1888c2ecf20Sopenharmony_ci BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ 1898c2ecf20Sopenharmony_ci /* struct bpf_spin_lock */ /* [2] */ 1908c2ecf20Sopenharmony_ci BTF_TYPE_ENC(1, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 1), 4), 1918c2ecf20Sopenharmony_ci BTF_MEMBER_ENC(15, 1, 0), /* int val; */ 1928c2ecf20Sopenharmony_ci /* struct val */ /* [3] */ 1938c2ecf20Sopenharmony_ci BTF_TYPE_ENC(15, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), 8), 1948c2ecf20Sopenharmony_ci BTF_MEMBER_ENC(19, 1, 0), /* int cnt; */ 1958c2ecf20Sopenharmony_ci BTF_MEMBER_ENC(23, 2, 32),/* struct bpf_spin_lock l; */ 1968c2ecf20Sopenharmony_ci }; 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci return libbpf__load_raw_btf((char *)types, sizeof(types), 1998c2ecf20Sopenharmony_ci strs, sizeof(strs)); 2008c2ecf20Sopenharmony_ci} 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_cibool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex) 2038c2ecf20Sopenharmony_ci{ 2048c2ecf20Sopenharmony_ci int key_size, value_size, max_entries, map_flags; 2058c2ecf20Sopenharmony_ci __u32 btf_key_type_id = 0, btf_value_type_id = 0; 2068c2ecf20Sopenharmony_ci struct bpf_create_map_attr attr = {}; 2078c2ecf20Sopenharmony_ci int fd = -1, btf_fd = -1, fd_inner; 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci key_size = sizeof(__u32); 2108c2ecf20Sopenharmony_ci value_size = sizeof(__u32); 2118c2ecf20Sopenharmony_ci max_entries = 1; 2128c2ecf20Sopenharmony_ci map_flags = 0; 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci switch (map_type) { 2158c2ecf20Sopenharmony_ci case BPF_MAP_TYPE_STACK_TRACE: 2168c2ecf20Sopenharmony_ci value_size = sizeof(__u64); 2178c2ecf20Sopenharmony_ci break; 2188c2ecf20Sopenharmony_ci case BPF_MAP_TYPE_LPM_TRIE: 2198c2ecf20Sopenharmony_ci key_size = sizeof(__u64); 2208c2ecf20Sopenharmony_ci value_size = sizeof(__u64); 2218c2ecf20Sopenharmony_ci map_flags = BPF_F_NO_PREALLOC; 2228c2ecf20Sopenharmony_ci break; 2238c2ecf20Sopenharmony_ci case BPF_MAP_TYPE_CGROUP_STORAGE: 2248c2ecf20Sopenharmony_ci case BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE: 2258c2ecf20Sopenharmony_ci key_size = sizeof(struct bpf_cgroup_storage_key); 2268c2ecf20Sopenharmony_ci value_size = sizeof(__u64); 2278c2ecf20Sopenharmony_ci max_entries = 0; 2288c2ecf20Sopenharmony_ci break; 2298c2ecf20Sopenharmony_ci case BPF_MAP_TYPE_QUEUE: 2308c2ecf20Sopenharmony_ci case BPF_MAP_TYPE_STACK: 2318c2ecf20Sopenharmony_ci key_size = 0; 2328c2ecf20Sopenharmony_ci break; 2338c2ecf20Sopenharmony_ci case BPF_MAP_TYPE_SK_STORAGE: 2348c2ecf20Sopenharmony_ci case BPF_MAP_TYPE_INODE_STORAGE: 2358c2ecf20Sopenharmony_ci btf_key_type_id = 1; 2368c2ecf20Sopenharmony_ci btf_value_type_id = 3; 2378c2ecf20Sopenharmony_ci value_size = 8; 2388c2ecf20Sopenharmony_ci max_entries = 0; 2398c2ecf20Sopenharmony_ci map_flags = BPF_F_NO_PREALLOC; 2408c2ecf20Sopenharmony_ci btf_fd = load_local_storage_btf(); 2418c2ecf20Sopenharmony_ci if (btf_fd < 0) 2428c2ecf20Sopenharmony_ci return false; 2438c2ecf20Sopenharmony_ci break; 2448c2ecf20Sopenharmony_ci case BPF_MAP_TYPE_RINGBUF: 2458c2ecf20Sopenharmony_ci key_size = 0; 2468c2ecf20Sopenharmony_ci value_size = 0; 2478c2ecf20Sopenharmony_ci max_entries = sysconf(_SC_PAGE_SIZE); 2488c2ecf20Sopenharmony_ci break; 2498c2ecf20Sopenharmony_ci case BPF_MAP_TYPE_UNSPEC: 2508c2ecf20Sopenharmony_ci case BPF_MAP_TYPE_HASH: 2518c2ecf20Sopenharmony_ci case BPF_MAP_TYPE_ARRAY: 2528c2ecf20Sopenharmony_ci case BPF_MAP_TYPE_PROG_ARRAY: 2538c2ecf20Sopenharmony_ci case BPF_MAP_TYPE_PERF_EVENT_ARRAY: 2548c2ecf20Sopenharmony_ci case BPF_MAP_TYPE_PERCPU_HASH: 2558c2ecf20Sopenharmony_ci case BPF_MAP_TYPE_PERCPU_ARRAY: 2568c2ecf20Sopenharmony_ci case BPF_MAP_TYPE_CGROUP_ARRAY: 2578c2ecf20Sopenharmony_ci case BPF_MAP_TYPE_LRU_HASH: 2588c2ecf20Sopenharmony_ci case BPF_MAP_TYPE_LRU_PERCPU_HASH: 2598c2ecf20Sopenharmony_ci case BPF_MAP_TYPE_ARRAY_OF_MAPS: 2608c2ecf20Sopenharmony_ci case BPF_MAP_TYPE_HASH_OF_MAPS: 2618c2ecf20Sopenharmony_ci case BPF_MAP_TYPE_DEVMAP: 2628c2ecf20Sopenharmony_ci case BPF_MAP_TYPE_DEVMAP_HASH: 2638c2ecf20Sopenharmony_ci case BPF_MAP_TYPE_SOCKMAP: 2648c2ecf20Sopenharmony_ci case BPF_MAP_TYPE_CPUMAP: 2658c2ecf20Sopenharmony_ci case BPF_MAP_TYPE_XSKMAP: 2668c2ecf20Sopenharmony_ci case BPF_MAP_TYPE_SOCKHASH: 2678c2ecf20Sopenharmony_ci case BPF_MAP_TYPE_REUSEPORT_SOCKARRAY: 2688c2ecf20Sopenharmony_ci case BPF_MAP_TYPE_STRUCT_OPS: 2698c2ecf20Sopenharmony_ci default: 2708c2ecf20Sopenharmony_ci break; 2718c2ecf20Sopenharmony_ci } 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci if (map_type == BPF_MAP_TYPE_ARRAY_OF_MAPS || 2748c2ecf20Sopenharmony_ci map_type == BPF_MAP_TYPE_HASH_OF_MAPS) { 2758c2ecf20Sopenharmony_ci /* TODO: probe for device, once libbpf has a function to create 2768c2ecf20Sopenharmony_ci * map-in-map for offload 2778c2ecf20Sopenharmony_ci */ 2788c2ecf20Sopenharmony_ci if (ifindex) 2798c2ecf20Sopenharmony_ci return false; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci fd_inner = bpf_create_map(BPF_MAP_TYPE_HASH, 2828c2ecf20Sopenharmony_ci sizeof(__u32), sizeof(__u32), 1, 0); 2838c2ecf20Sopenharmony_ci if (fd_inner < 0) 2848c2ecf20Sopenharmony_ci return false; 2858c2ecf20Sopenharmony_ci fd = bpf_create_map_in_map(map_type, NULL, sizeof(__u32), 2868c2ecf20Sopenharmony_ci fd_inner, 1, 0); 2878c2ecf20Sopenharmony_ci close(fd_inner); 2888c2ecf20Sopenharmony_ci } else { 2898c2ecf20Sopenharmony_ci /* Note: No other restriction on map type probes for offload */ 2908c2ecf20Sopenharmony_ci attr.map_type = map_type; 2918c2ecf20Sopenharmony_ci attr.key_size = key_size; 2928c2ecf20Sopenharmony_ci attr.value_size = value_size; 2938c2ecf20Sopenharmony_ci attr.max_entries = max_entries; 2948c2ecf20Sopenharmony_ci attr.map_flags = map_flags; 2958c2ecf20Sopenharmony_ci attr.map_ifindex = ifindex; 2968c2ecf20Sopenharmony_ci if (btf_fd >= 0) { 2978c2ecf20Sopenharmony_ci attr.btf_fd = btf_fd; 2988c2ecf20Sopenharmony_ci attr.btf_key_type_id = btf_key_type_id; 2998c2ecf20Sopenharmony_ci attr.btf_value_type_id = btf_value_type_id; 3008c2ecf20Sopenharmony_ci } 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci fd = bpf_create_map_xattr(&attr); 3038c2ecf20Sopenharmony_ci } 3048c2ecf20Sopenharmony_ci if (fd >= 0) 3058c2ecf20Sopenharmony_ci close(fd); 3068c2ecf20Sopenharmony_ci if (btf_fd >= 0) 3078c2ecf20Sopenharmony_ci close(btf_fd); 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci return fd >= 0; 3108c2ecf20Sopenharmony_ci} 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_cibool bpf_probe_helper(enum bpf_func_id id, enum bpf_prog_type prog_type, 3138c2ecf20Sopenharmony_ci __u32 ifindex) 3148c2ecf20Sopenharmony_ci{ 3158c2ecf20Sopenharmony_ci struct bpf_insn insns[2] = { 3168c2ecf20Sopenharmony_ci BPF_EMIT_CALL(id), 3178c2ecf20Sopenharmony_ci BPF_EXIT_INSN() 3188c2ecf20Sopenharmony_ci }; 3198c2ecf20Sopenharmony_ci char buf[4096] = {}; 3208c2ecf20Sopenharmony_ci bool res; 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci probe_load(prog_type, insns, ARRAY_SIZE(insns), buf, sizeof(buf), 3238c2ecf20Sopenharmony_ci ifindex); 3248c2ecf20Sopenharmony_ci res = !grep(buf, "invalid func ") && !grep(buf, "unknown func "); 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci if (ifindex) { 3278c2ecf20Sopenharmony_ci switch (get_vendor_id(ifindex)) { 3288c2ecf20Sopenharmony_ci case 0x19ee: /* Netronome specific */ 3298c2ecf20Sopenharmony_ci res = res && !grep(buf, "not supported by FW") && 3308c2ecf20Sopenharmony_ci !grep(buf, "unsupported function id"); 3318c2ecf20Sopenharmony_ci break; 3328c2ecf20Sopenharmony_ci default: 3338c2ecf20Sopenharmony_ci break; 3348c2ecf20Sopenharmony_ci } 3358c2ecf20Sopenharmony_ci } 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci return res; 3388c2ecf20Sopenharmony_ci} 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci/* 3418c2ecf20Sopenharmony_ci * Probe for availability of kernel commit (5.3): 3428c2ecf20Sopenharmony_ci * 3438c2ecf20Sopenharmony_ci * c04c0d2b968a ("bpf: increase complexity limit and maximum program size") 3448c2ecf20Sopenharmony_ci */ 3458c2ecf20Sopenharmony_cibool bpf_probe_large_insn_limit(__u32 ifindex) 3468c2ecf20Sopenharmony_ci{ 3478c2ecf20Sopenharmony_ci struct bpf_insn insns[BPF_MAXINSNS + 1]; 3488c2ecf20Sopenharmony_ci int i; 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci for (i = 0; i < BPF_MAXINSNS; i++) 3518c2ecf20Sopenharmony_ci insns[i] = BPF_MOV64_IMM(BPF_REG_0, 1); 3528c2ecf20Sopenharmony_ci insns[BPF_MAXINSNS] = BPF_EXIT_INSN(); 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci errno = 0; 3558c2ecf20Sopenharmony_ci probe_load(BPF_PROG_TYPE_SCHED_CLS, insns, ARRAY_SIZE(insns), NULL, 0, 3568c2ecf20Sopenharmony_ci ifindex); 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci return errno != E2BIG && errno != EINVAL; 3598c2ecf20Sopenharmony_ci} 360