1 // SPDX-License-Identifier: GPL-2.0-only 2 #ifndef XDP_SAMPLE_USER_H 3 #define XDP_SAMPLE_USER_H 4 5 #include <bpf/libbpf.h> 6 #include <linux/compiler.h> 7 8 #include "xdp_sample_shared.h" 9 10 enum stats_mask { 11 _SAMPLE_REDIRECT_MAP = 1U << 0, 12 SAMPLE_RX_CNT = 1U << 1, 13 SAMPLE_REDIRECT_ERR_CNT = 1U << 2, 14 SAMPLE_CPUMAP_ENQUEUE_CNT = 1U << 3, 15 SAMPLE_CPUMAP_KTHREAD_CNT = 1U << 4, 16 SAMPLE_EXCEPTION_CNT = 1U << 5, 17 SAMPLE_DEVMAP_XMIT_CNT = 1U << 6, 18 SAMPLE_REDIRECT_CNT = 1U << 7, 19 SAMPLE_REDIRECT_MAP_CNT = SAMPLE_REDIRECT_CNT | _SAMPLE_REDIRECT_MAP, 20 SAMPLE_REDIRECT_ERR_MAP_CNT = SAMPLE_REDIRECT_ERR_CNT | _SAMPLE_REDIRECT_MAP, 21 SAMPLE_DEVMAP_XMIT_CNT_MULTI = 1U << 8, 22 SAMPLE_SKIP_HEADING = 1U << 9, 23 }; 24 25 /* Exit return codes */ 26 #define EXIT_OK 0 27 #define EXIT_FAIL 1 28 #define EXIT_FAIL_OPTION 2 29 #define EXIT_FAIL_XDP 3 30 #define EXIT_FAIL_BPF 4 31 #define EXIT_FAIL_MEM 5 32 33 int sample_setup_maps(struct bpf_map **maps); 34 int __sample_init(int mask); 35 void sample_exit(int status); 36 int sample_run(int interval, void (*post_cb)(void *), void *ctx); 37 38 void sample_switch_mode(void); 39 int sample_install_xdp(struct bpf_program *xdp_prog, int ifindex, bool generic, 40 bool force); 41 void sample_usage(char *argv[], const struct option *long_options, 42 const char *doc, int mask, bool error); 43 44 const char *get_driver_name(int ifindex); 45 int get_mac_addr(int ifindex, void *mac_addr); 46 47 #pragma GCC diagnostic push 48 #ifndef __clang__ 49 #pragma GCC diagnostic ignored "-Wstringop-truncation" 50 #endif 51 __attribute__((unused)) 52 static inline char *safe_strncpy(char *dst, const char *src, size_t size) 53 { 54 if (!size) 55 return dst; 56 strncpy(dst, src, size - 1); 57 dst[size - 1] = '\0'; 58 return dst; 59 } 60 #pragma GCC diagnostic pop 61 62 #define __attach_tp(name) \ 63 ({ \ 64 if (!bpf_program__is_tracing(skel->progs.name)) \ 65 return -EINVAL; \ 66 skel->links.name = bpf_program__attach(skel->progs.name); \ 67 if (!skel->links.name) \ 68 return -errno; \ 69 }) 70 71 #define sample_init_pre_load(skel) \ 72 ({ \ 73 skel->rodata->nr_cpus = libbpf_num_possible_cpus(); \ 74 sample_setup_maps((struct bpf_map *[]){ \ 75 skel->maps.rx_cnt, skel->maps.redir_err_cnt, \ 76 skel->maps.cpumap_enqueue_cnt, \ 77 skel->maps.cpumap_kthread_cnt, \ 78 skel->maps.exception_cnt, skel->maps.devmap_xmit_cnt, \ 79 skel->maps.devmap_xmit_cnt_multi }); \ 80 }) 81 82 #define DEFINE_SAMPLE_INIT(name) \ 83 static int sample_init(struct name *skel, int mask) \ 84 { \ 85 int ret; \ 86 ret = __sample_init(mask); \ 87 if (ret < 0) \ 88 return ret; \ 89 if (mask & SAMPLE_REDIRECT_MAP_CNT) \ 90 __attach_tp(tp_xdp_redirect_map); \ 91 if (mask & SAMPLE_REDIRECT_CNT) \ 92 __attach_tp(tp_xdp_redirect); \ 93 if (mask & SAMPLE_REDIRECT_ERR_MAP_CNT) \ 94 __attach_tp(tp_xdp_redirect_map_err); \ 95 if (mask & SAMPLE_REDIRECT_ERR_CNT) \ 96 __attach_tp(tp_xdp_redirect_err); \ 97 if (mask & SAMPLE_CPUMAP_ENQUEUE_CNT) \ 98 __attach_tp(tp_xdp_cpumap_enqueue); \ 99 if (mask & SAMPLE_CPUMAP_KTHREAD_CNT) \ 100 __attach_tp(tp_xdp_cpumap_kthread); \ 101 if (mask & SAMPLE_EXCEPTION_CNT) \ 102 __attach_tp(tp_xdp_exception); \ 103 if (mask & SAMPLE_DEVMAP_XMIT_CNT) \ 104 __attach_tp(tp_xdp_devmap_xmit); \ 105 if (mask & SAMPLE_DEVMAP_XMIT_CNT_MULTI) \ 106 __attach_tp(tp_xdp_devmap_xmit_multi); \ 107 return 0; \ 108 } 109 110 #endif 111