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))
safe_strncpy(char * dst,const char * src,size_t size)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__type(skel->progs.name) != BPF_PROG_TYPE_TRACING)\
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