xref: /openbmc/linux/samples/bpf/xdp_sample_user.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1156f886cSKumar Kartikeya Dwivedi // SPDX-License-Identifier: GPL-2.0-only
2156f886cSKumar Kartikeya Dwivedi #define _GNU_SOURCE
3156f886cSKumar Kartikeya Dwivedi 
4156f886cSKumar Kartikeya Dwivedi #include <arpa/inet.h>
5156f886cSKumar Kartikeya Dwivedi #include <bpf/bpf.h>
6156f886cSKumar Kartikeya Dwivedi #include <bpf/libbpf.h>
7156f886cSKumar Kartikeya Dwivedi #include <errno.h>
8156f886cSKumar Kartikeya Dwivedi #include <fcntl.h>
9156f886cSKumar Kartikeya Dwivedi #include <getopt.h>
10156f886cSKumar Kartikeya Dwivedi #include <linux/ethtool.h>
11156f886cSKumar Kartikeya Dwivedi #include <linux/hashtable.h>
12156f886cSKumar Kartikeya Dwivedi #include <linux/if_link.h>
13156f886cSKumar Kartikeya Dwivedi #include <linux/jhash.h>
14156f886cSKumar Kartikeya Dwivedi #include <linux/limits.h>
15156f886cSKumar Kartikeya Dwivedi #include <linux/list.h>
16156f886cSKumar Kartikeya Dwivedi #include <linux/sockios.h>
17156f886cSKumar Kartikeya Dwivedi #include <locale.h>
18156f886cSKumar Kartikeya Dwivedi #include <math.h>
19156f886cSKumar Kartikeya Dwivedi #include <net/if.h>
20156f886cSKumar Kartikeya Dwivedi #include <poll.h>
21156f886cSKumar Kartikeya Dwivedi #include <signal.h>
22156f886cSKumar Kartikeya Dwivedi #include <stdbool.h>
23156f886cSKumar Kartikeya Dwivedi #include <stdio.h>
24156f886cSKumar Kartikeya Dwivedi #include <stdlib.h>
25156f886cSKumar Kartikeya Dwivedi #include <string.h>
26156f886cSKumar Kartikeya Dwivedi #include <sys/ioctl.h>
27156f886cSKumar Kartikeya Dwivedi #include <sys/mman.h>
28156f886cSKumar Kartikeya Dwivedi #include <sys/signalfd.h>
29156f886cSKumar Kartikeya Dwivedi #include <sys/sysinfo.h>
30156f886cSKumar Kartikeya Dwivedi #include <sys/timerfd.h>
31156f886cSKumar Kartikeya Dwivedi #include <sys/utsname.h>
32156f886cSKumar Kartikeya Dwivedi #include <time.h>
33156f886cSKumar Kartikeya Dwivedi #include <unistd.h>
34156f886cSKumar Kartikeya Dwivedi 
35156f886cSKumar Kartikeya Dwivedi #include "bpf_util.h"
36156f886cSKumar Kartikeya Dwivedi #include "xdp_sample_user.h"
37156f886cSKumar Kartikeya Dwivedi 
38156f886cSKumar Kartikeya Dwivedi #define __sample_print(fmt, cond, ...)                                         \
39156f886cSKumar Kartikeya Dwivedi 	({                                                                     \
40156f886cSKumar Kartikeya Dwivedi 		if (cond)                                                      \
41156f886cSKumar Kartikeya Dwivedi 			printf(fmt, ##__VA_ARGS__);                            \
42156f886cSKumar Kartikeya Dwivedi 	})
43156f886cSKumar Kartikeya Dwivedi 
44156f886cSKumar Kartikeya Dwivedi #define print_always(fmt, ...) __sample_print(fmt, 1, ##__VA_ARGS__)
45156f886cSKumar Kartikeya Dwivedi #define print_default(fmt, ...)                                                \
46156f886cSKumar Kartikeya Dwivedi 	__sample_print(fmt, sample_log_level & LL_DEFAULT, ##__VA_ARGS__)
47156f886cSKumar Kartikeya Dwivedi #define __print_err(err, fmt, ...)                                             \
48156f886cSKumar Kartikeya Dwivedi 	({                                                                     \
49156f886cSKumar Kartikeya Dwivedi 		__sample_print(fmt, err > 0 || sample_log_level & LL_DEFAULT,  \
50156f886cSKumar Kartikeya Dwivedi 			       ##__VA_ARGS__);                                 \
51156f886cSKumar Kartikeya Dwivedi 		sample_err_exp = sample_err_exp ? true : err > 0;              \
52156f886cSKumar Kartikeya Dwivedi 	})
53156f886cSKumar Kartikeya Dwivedi #define print_err(err, fmt, ...) __print_err(err, fmt, ##__VA_ARGS__)
54156f886cSKumar Kartikeya Dwivedi 
55156f886cSKumar Kartikeya Dwivedi #define __COLUMN(x) "%'10" x " %-13s"
56156f886cSKumar Kartikeya Dwivedi #define FMT_COLUMNf __COLUMN(".0f")
57156f886cSKumar Kartikeya Dwivedi #define FMT_COLUMNd __COLUMN("d")
58156f886cSKumar Kartikeya Dwivedi #define FMT_COLUMNl __COLUMN("llu")
59156f886cSKumar Kartikeya Dwivedi #define RX(rx) rx, "rx/s"
60156f886cSKumar Kartikeya Dwivedi #define PPS(pps) pps, "pkt/s"
61156f886cSKumar Kartikeya Dwivedi #define DROP(drop) drop, "drop/s"
62156f886cSKumar Kartikeya Dwivedi #define ERR(err) err, "error/s"
63156f886cSKumar Kartikeya Dwivedi #define HITS(hits) hits, "hit/s"
64156f886cSKumar Kartikeya Dwivedi #define XMIT(xmit) xmit, "xmit/s"
65156f886cSKumar Kartikeya Dwivedi #define PASS(pass) pass, "pass/s"
66156f886cSKumar Kartikeya Dwivedi #define REDIR(redir) redir, "redir/s"
67156f886cSKumar Kartikeya Dwivedi #define NANOSEC_PER_SEC 1000000000 /* 10^9 */
68156f886cSKumar Kartikeya Dwivedi 
69156f886cSKumar Kartikeya Dwivedi #define XDP_UNKNOWN (XDP_REDIRECT + 1)
70156f886cSKumar Kartikeya Dwivedi #define XDP_ACTION_MAX (XDP_UNKNOWN + 1)
71156f886cSKumar Kartikeya Dwivedi #define XDP_REDIRECT_ERR_MAX 7
72156f886cSKumar Kartikeya Dwivedi 
73156f886cSKumar Kartikeya Dwivedi enum map_type {
74156f886cSKumar Kartikeya Dwivedi 	MAP_RX,
751d930fd2SKumar Kartikeya Dwivedi 	MAP_REDIRECT_ERR,
76d771e217SKumar Kartikeya Dwivedi 	MAP_CPUMAP_ENQUEUE,
77d771e217SKumar Kartikeya Dwivedi 	MAP_CPUMAP_KTHREAD,
7882c45080SKumar Kartikeya Dwivedi 	MAP_EXCEPTION,
79af93d58cSKumar Kartikeya Dwivedi 	MAP_DEVMAP_XMIT,
80af93d58cSKumar Kartikeya Dwivedi 	MAP_DEVMAP_XMIT_MULTI,
81156f886cSKumar Kartikeya Dwivedi 	NUM_MAP,
82156f886cSKumar Kartikeya Dwivedi };
83156f886cSKumar Kartikeya Dwivedi 
84156f886cSKumar Kartikeya Dwivedi enum log_level {
85156f886cSKumar Kartikeya Dwivedi 	LL_DEFAULT = 1U << 0,
86156f886cSKumar Kartikeya Dwivedi 	LL_SIMPLE = 1U << 1,
87156f886cSKumar Kartikeya Dwivedi 	LL_DEBUG = 1U << 2,
88156f886cSKumar Kartikeya Dwivedi };
89156f886cSKumar Kartikeya Dwivedi 
90156f886cSKumar Kartikeya Dwivedi struct record {
91156f886cSKumar Kartikeya Dwivedi 	__u64 timestamp;
92156f886cSKumar Kartikeya Dwivedi 	struct datarec total;
93156f886cSKumar Kartikeya Dwivedi 	struct datarec *cpu;
94156f886cSKumar Kartikeya Dwivedi };
95156f886cSKumar Kartikeya Dwivedi 
96156f886cSKumar Kartikeya Dwivedi struct map_entry {
97156f886cSKumar Kartikeya Dwivedi 	struct hlist_node node;
98156f886cSKumar Kartikeya Dwivedi 	__u64 pair;
99156f886cSKumar Kartikeya Dwivedi 	struct record val;
100156f886cSKumar Kartikeya Dwivedi };
101156f886cSKumar Kartikeya Dwivedi 
102156f886cSKumar Kartikeya Dwivedi struct stats_record {
103156f886cSKumar Kartikeya Dwivedi 	struct record rx_cnt;
1041d930fd2SKumar Kartikeya Dwivedi 	struct record redir_err[XDP_REDIRECT_ERR_MAX];
105d771e217SKumar Kartikeya Dwivedi 	struct record kthread;
10682c45080SKumar Kartikeya Dwivedi 	struct record exception[XDP_ACTION_MAX];
107af93d58cSKumar Kartikeya Dwivedi 	struct record devmap_xmit;
108af93d58cSKumar Kartikeya Dwivedi 	DECLARE_HASHTABLE(xmit_map, 5);
109d771e217SKumar Kartikeya Dwivedi 	struct record enq[];
110156f886cSKumar Kartikeya Dwivedi };
111156f886cSKumar Kartikeya Dwivedi 
112156f886cSKumar Kartikeya Dwivedi struct sample_output {
113156f886cSKumar Kartikeya Dwivedi 	struct {
114156f886cSKumar Kartikeya Dwivedi 		__u64 rx;
1151d930fd2SKumar Kartikeya Dwivedi 		__u64 redir;
116d771e217SKumar Kartikeya Dwivedi 		__u64 drop;
117af93d58cSKumar Kartikeya Dwivedi 		__u64 drop_xmit;
1181d930fd2SKumar Kartikeya Dwivedi 		__u64 err;
119af93d58cSKumar Kartikeya Dwivedi 		__u64 xmit;
120156f886cSKumar Kartikeya Dwivedi 	} totals;
121156f886cSKumar Kartikeya Dwivedi 	struct {
122dc14ca46SAlexander Lobakin 		union {
123156f886cSKumar Kartikeya Dwivedi 			__u64 pps;
124dc14ca46SAlexander Lobakin 			__u64 num;
125dc14ca46SAlexander Lobakin 		};
126156f886cSKumar Kartikeya Dwivedi 		__u64 drop;
127156f886cSKumar Kartikeya Dwivedi 		__u64 err;
128156f886cSKumar Kartikeya Dwivedi 	} rx_cnt;
1291d930fd2SKumar Kartikeya Dwivedi 	struct {
1301d930fd2SKumar Kartikeya Dwivedi 		__u64 suc;
1311d930fd2SKumar Kartikeya Dwivedi 		__u64 err;
1321d930fd2SKumar Kartikeya Dwivedi 	} redir_cnt;
13382c45080SKumar Kartikeya Dwivedi 	struct {
13482c45080SKumar Kartikeya Dwivedi 		__u64 hits;
13582c45080SKumar Kartikeya Dwivedi 	} except_cnt;
136af93d58cSKumar Kartikeya Dwivedi 	struct {
137af93d58cSKumar Kartikeya Dwivedi 		__u64 pps;
138af93d58cSKumar Kartikeya Dwivedi 		__u64 drop;
139af93d58cSKumar Kartikeya Dwivedi 		__u64 err;
140af93d58cSKumar Kartikeya Dwivedi 		double bavg;
141af93d58cSKumar Kartikeya Dwivedi 	} xmit_cnt;
142156f886cSKumar Kartikeya Dwivedi };
143156f886cSKumar Kartikeya Dwivedi 
144156f886cSKumar Kartikeya Dwivedi struct xdp_desc {
145156f886cSKumar Kartikeya Dwivedi 	int ifindex;
146156f886cSKumar Kartikeya Dwivedi 	__u32 prog_id;
147156f886cSKumar Kartikeya Dwivedi 	int flags;
148156f886cSKumar Kartikeya Dwivedi } sample_xdp_progs[32];
149156f886cSKumar Kartikeya Dwivedi 
150156f886cSKumar Kartikeya Dwivedi struct datarec *sample_mmap[NUM_MAP];
151156f886cSKumar Kartikeya Dwivedi struct bpf_map *sample_map[NUM_MAP];
152156f886cSKumar Kartikeya Dwivedi size_t sample_map_count[NUM_MAP];
153156f886cSKumar Kartikeya Dwivedi enum log_level sample_log_level;
154156f886cSKumar Kartikeya Dwivedi struct sample_output sample_out;
155156f886cSKumar Kartikeya Dwivedi unsigned long sample_interval;
156156f886cSKumar Kartikeya Dwivedi bool sample_err_exp;
157156f886cSKumar Kartikeya Dwivedi int sample_xdp_cnt;
158156f886cSKumar Kartikeya Dwivedi int sample_n_cpus;
159156f886cSKumar Kartikeya Dwivedi int sample_sig_fd;
160156f886cSKumar Kartikeya Dwivedi int sample_mask;
161156f886cSKumar Kartikeya Dwivedi 
1621d930fd2SKumar Kartikeya Dwivedi static const char *xdp_redirect_err_names[XDP_REDIRECT_ERR_MAX] = {
1631d930fd2SKumar Kartikeya Dwivedi 	/* Key=1 keeps unknown errors */
1641d930fd2SKumar Kartikeya Dwivedi 	"Success",
1651d930fd2SKumar Kartikeya Dwivedi 	"Unknown",
1661d930fd2SKumar Kartikeya Dwivedi 	"EINVAL",
1671d930fd2SKumar Kartikeya Dwivedi 	"ENETDOWN",
1681d930fd2SKumar Kartikeya Dwivedi 	"EMSGSIZE",
1691d930fd2SKumar Kartikeya Dwivedi 	"EOPNOTSUPP",
1701d930fd2SKumar Kartikeya Dwivedi 	"ENOSPC",
1711d930fd2SKumar Kartikeya Dwivedi };
1721d930fd2SKumar Kartikeya Dwivedi 
1731d930fd2SKumar Kartikeya Dwivedi /* Keyed from Unknown */
1741d930fd2SKumar Kartikeya Dwivedi static const char *xdp_redirect_err_help[XDP_REDIRECT_ERR_MAX - 1] = {
1751d930fd2SKumar Kartikeya Dwivedi 	"Unknown error",
1761d930fd2SKumar Kartikeya Dwivedi 	"Invalid redirection",
1771d930fd2SKumar Kartikeya Dwivedi 	"Device being redirected to is down",
1781d930fd2SKumar Kartikeya Dwivedi 	"Packet length too large for device",
1791d930fd2SKumar Kartikeya Dwivedi 	"Operation not supported",
1801d930fd2SKumar Kartikeya Dwivedi 	"No space in ptr_ring of cpumap kthread",
1811d930fd2SKumar Kartikeya Dwivedi };
1821d930fd2SKumar Kartikeya Dwivedi 
18382c45080SKumar Kartikeya Dwivedi static const char *xdp_action_names[XDP_ACTION_MAX] = {
18482c45080SKumar Kartikeya Dwivedi 	[XDP_ABORTED]  = "XDP_ABORTED",
18582c45080SKumar Kartikeya Dwivedi 	[XDP_DROP]     = "XDP_DROP",
18682c45080SKumar Kartikeya Dwivedi 	[XDP_PASS]     = "XDP_PASS",
18782c45080SKumar Kartikeya Dwivedi 	[XDP_TX]       = "XDP_TX",
18882c45080SKumar Kartikeya Dwivedi 	[XDP_REDIRECT] = "XDP_REDIRECT",
18982c45080SKumar Kartikeya Dwivedi 	[XDP_UNKNOWN]  = "XDP_UNKNOWN",
19082c45080SKumar Kartikeya Dwivedi };
19182c45080SKumar Kartikeya Dwivedi 
gettime(void)192156f886cSKumar Kartikeya Dwivedi static __u64 gettime(void)
193156f886cSKumar Kartikeya Dwivedi {
194156f886cSKumar Kartikeya Dwivedi 	struct timespec t;
195156f886cSKumar Kartikeya Dwivedi 	int res;
196156f886cSKumar Kartikeya Dwivedi 
197156f886cSKumar Kartikeya Dwivedi 	res = clock_gettime(CLOCK_MONOTONIC, &t);
198156f886cSKumar Kartikeya Dwivedi 	if (res < 0) {
199156f886cSKumar Kartikeya Dwivedi 		fprintf(stderr, "Error with gettimeofday! (%i)\n", res);
200156f886cSKumar Kartikeya Dwivedi 		return UINT64_MAX;
201156f886cSKumar Kartikeya Dwivedi 	}
202156f886cSKumar Kartikeya Dwivedi 	return (__u64)t.tv_sec * NANOSEC_PER_SEC + t.tv_nsec;
203156f886cSKumar Kartikeya Dwivedi }
204156f886cSKumar Kartikeya Dwivedi 
action2str(int action)20582c45080SKumar Kartikeya Dwivedi static const char *action2str(int action)
20682c45080SKumar Kartikeya Dwivedi {
20782c45080SKumar Kartikeya Dwivedi 	if (action < XDP_ACTION_MAX)
20882c45080SKumar Kartikeya Dwivedi 		return xdp_action_names[action];
20982c45080SKumar Kartikeya Dwivedi 	return NULL;
21082c45080SKumar Kartikeya Dwivedi }
21182c45080SKumar Kartikeya Dwivedi 
sample_print_help(int mask)212156f886cSKumar Kartikeya Dwivedi static void sample_print_help(int mask)
213156f886cSKumar Kartikeya Dwivedi {
214156f886cSKumar Kartikeya Dwivedi 	printf("Output format description\n\n"
215156f886cSKumar Kartikeya Dwivedi 	       "By default, redirect success statistics are disabled, use -s to enable.\n"
216156f886cSKumar Kartikeya Dwivedi 	       "The terse output mode is default, verbose mode can be activated using -v\n"
217156f886cSKumar Kartikeya Dwivedi 	       "Use SIGQUIT (Ctrl + \\) to switch the mode dynamically at runtime\n\n"
218156f886cSKumar Kartikeya Dwivedi 	       "Terse mode displays at most the following fields:\n"
219156f886cSKumar Kartikeya Dwivedi 	       "  rx/s        Number of packets received per second\n"
220156f886cSKumar Kartikeya Dwivedi 	       "  redir/s     Number of packets successfully redirected per second\n"
221156f886cSKumar Kartikeya Dwivedi 	       "  err,drop/s  Aggregated count of errors per second (including dropped packets)\n"
222156f886cSKumar Kartikeya Dwivedi 	       "  xmit/s      Number of packets transmitted on the output device per second\n\n"
223156f886cSKumar Kartikeya Dwivedi 	       "Output description for verbose mode:\n"
224156f886cSKumar Kartikeya Dwivedi 	       "  FIELD                 DESCRIPTION\n");
225156f886cSKumar Kartikeya Dwivedi 
226156f886cSKumar Kartikeya Dwivedi 	if (mask & SAMPLE_RX_CNT) {
227156f886cSKumar Kartikeya Dwivedi 		printf("  receive\t\tDisplays the number of packets received & errors encountered\n"
228156f886cSKumar Kartikeya Dwivedi 		       " \t\t\tWhenever an error or packet drop occurs, details of per CPU error\n"
229156f886cSKumar Kartikeya Dwivedi 		       " \t\t\tand drop statistics will be expanded inline in terse mode.\n"
230156f886cSKumar Kartikeya Dwivedi 		       " \t\t\t\tpkt/s     - Packets received per second\n"
231156f886cSKumar Kartikeya Dwivedi 		       " \t\t\t\tdrop/s    - Packets dropped per second\n"
232156f886cSKumar Kartikeya Dwivedi 		       " \t\t\t\terror/s   - Errors encountered per second\n\n");
233156f886cSKumar Kartikeya Dwivedi 	}
2341d930fd2SKumar Kartikeya Dwivedi 	if (mask & (SAMPLE_REDIRECT_CNT | SAMPLE_REDIRECT_ERR_CNT)) {
2351d930fd2SKumar Kartikeya Dwivedi 		printf("  redirect\t\tDisplays the number of packets successfully redirected\n"
2361d930fd2SKumar Kartikeya Dwivedi 		       "  \t\t\tErrors encountered are expanded under redirect_err field\n"
2371d930fd2SKumar Kartikeya Dwivedi 		       "  \t\t\tNote that passing -s to enable it has a per packet overhead\n"
2381d930fd2SKumar Kartikeya Dwivedi 		       "  \t\t\t\tredir/s   - Packets redirected successfully per second\n\n"
2391d930fd2SKumar Kartikeya Dwivedi 		       "  redirect_err\t\tDisplays the number of packets that failed redirection\n"
2401d930fd2SKumar Kartikeya Dwivedi 		       "  \t\t\tThe errno is expanded under this field with per CPU count\n"
2411d930fd2SKumar Kartikeya Dwivedi 		       "  \t\t\tThe recognized errors are:\n");
2421d930fd2SKumar Kartikeya Dwivedi 
2431d930fd2SKumar Kartikeya Dwivedi 		for (int i = 2; i < XDP_REDIRECT_ERR_MAX; i++)
2441d930fd2SKumar Kartikeya Dwivedi 			printf("\t\t\t  %s: %s\n", xdp_redirect_err_names[i],
2451d930fd2SKumar Kartikeya Dwivedi 			       xdp_redirect_err_help[i - 1]);
2461d930fd2SKumar Kartikeya Dwivedi 
2471d930fd2SKumar Kartikeya Dwivedi 		printf("  \n\t\t\t\terror/s   - Packets that failed redirection per second\n\n");
2481d930fd2SKumar Kartikeya Dwivedi 	}
24982c45080SKumar Kartikeya Dwivedi 
250d771e217SKumar Kartikeya Dwivedi 	if (mask & SAMPLE_CPUMAP_ENQUEUE_CNT) {
251d771e217SKumar Kartikeya Dwivedi 		printf("  enqueue to cpu N\tDisplays the number of packets enqueued to bulk queue of CPU N\n"
252d771e217SKumar Kartikeya Dwivedi 		       "  \t\t\tExpands to cpu:FROM->N to display enqueue stats for each CPU enqueuing to CPU N\n"
253d771e217SKumar Kartikeya Dwivedi 		       "  \t\t\tReceived packets can be associated with the CPU redirect program is enqueuing \n"
254d771e217SKumar Kartikeya Dwivedi 		       "  \t\t\tpackets to.\n"
255d771e217SKumar Kartikeya Dwivedi 		       "  \t\t\t\tpkt/s    - Packets enqueued per second from other CPU to CPU N\n"
256d771e217SKumar Kartikeya Dwivedi 		       "  \t\t\t\tdrop/s   - Packets dropped when trying to enqueue to CPU N\n"
257d771e217SKumar Kartikeya Dwivedi 		       "  \t\t\t\tbulk-avg - Average number of packets processed for each event\n\n");
258d771e217SKumar Kartikeya Dwivedi 	}
259d771e217SKumar Kartikeya Dwivedi 
260d771e217SKumar Kartikeya Dwivedi 	if (mask & SAMPLE_CPUMAP_KTHREAD_CNT) {
261d771e217SKumar Kartikeya Dwivedi 		printf("  kthread\t\tDisplays the number of packets processed in CPUMAP kthread for each CPU\n"
262d771e217SKumar Kartikeya Dwivedi 		       "  \t\t\tPackets consumed from ptr_ring in kthread, and its xdp_stats (after calling \n"
263d771e217SKumar Kartikeya Dwivedi 		       "  \t\t\tCPUMAP bpf prog) are expanded below this. xdp_stats are expanded as a total and\n"
264d771e217SKumar Kartikeya Dwivedi 		       "  \t\t\tthen per-CPU to associate it to each CPU's pinned CPUMAP kthread.\n"
265d771e217SKumar Kartikeya Dwivedi 		       "  \t\t\t\tpkt/s    - Packets consumed per second from ptr_ring\n"
266d771e217SKumar Kartikeya Dwivedi 		       "  \t\t\t\tdrop/s   - Packets dropped per second in kthread\n"
267d771e217SKumar Kartikeya Dwivedi 		       "  \t\t\t\tsched    - Number of times kthread called schedule()\n\n"
268d771e217SKumar Kartikeya Dwivedi 		       "  \t\t\txdp_stats (also expands to per-CPU counts)\n"
269d771e217SKumar Kartikeya Dwivedi 		       "  \t\t\t\tpass/s  - XDP_PASS count for CPUMAP program execution\n"
270d771e217SKumar Kartikeya Dwivedi 		       "  \t\t\t\tdrop/s  - XDP_DROP count for CPUMAP program execution\n"
271d771e217SKumar Kartikeya Dwivedi 		       "  \t\t\t\tredir/s - XDP_REDIRECT count for CPUMAP program execution\n\n");
272d771e217SKumar Kartikeya Dwivedi 	}
273d771e217SKumar Kartikeya Dwivedi 
27482c45080SKumar Kartikeya Dwivedi 	if (mask & SAMPLE_EXCEPTION_CNT) {
27582c45080SKumar Kartikeya Dwivedi 		printf("  xdp_exception\t\tDisplays xdp_exception tracepoint events\n"
27682c45080SKumar Kartikeya Dwivedi 		       "  \t\t\tThis can occur due to internal driver errors, unrecognized\n"
27782c45080SKumar Kartikeya Dwivedi 		       "  \t\t\tXDP actions and due to explicit user trigger by use of XDP_ABORTED\n"
27882c45080SKumar Kartikeya Dwivedi 		       "  \t\t\tEach action is expanded below this field with its count\n"
27982c45080SKumar Kartikeya Dwivedi 		       "  \t\t\t\thit/s     - Number of times the tracepoint was hit per second\n\n");
28082c45080SKumar Kartikeya Dwivedi 	}
28182c45080SKumar Kartikeya Dwivedi 
282af93d58cSKumar Kartikeya Dwivedi 	if (mask & SAMPLE_DEVMAP_XMIT_CNT) {
283af93d58cSKumar Kartikeya Dwivedi 		printf("  devmap_xmit\t\tDisplays devmap_xmit tracepoint events\n"
284af93d58cSKumar Kartikeya Dwivedi 		       "  \t\t\tThis tracepoint is invoked for successful transmissions on output\n"
285af93d58cSKumar Kartikeya Dwivedi 		       "  \t\t\tdevice but these statistics are not available for generic XDP mode,\n"
286af93d58cSKumar Kartikeya Dwivedi 		       "  \t\t\thence they will be omitted from the output when using SKB mode\n"
287af93d58cSKumar Kartikeya Dwivedi 		       "  \t\t\t\txmit/s    - Number of packets that were transmitted per second\n"
288af93d58cSKumar Kartikeya Dwivedi 		       "  \t\t\t\tdrop/s    - Number of packets that failed transmissions per second\n"
289af93d58cSKumar Kartikeya Dwivedi 		       "  \t\t\t\tdrv_err/s - Number of internal driver errors per second\n"
290af93d58cSKumar Kartikeya Dwivedi 		       "  \t\t\t\tbulk-avg  - Average number of packets processed for each event\n\n");
291af93d58cSKumar Kartikeya Dwivedi 	}
292156f886cSKumar Kartikeya Dwivedi }
293156f886cSKumar Kartikeya Dwivedi 
sample_usage(char * argv[],const struct option * long_options,const char * doc,int mask,bool error)294156f886cSKumar Kartikeya Dwivedi void sample_usage(char *argv[], const struct option *long_options,
295156f886cSKumar Kartikeya Dwivedi 		  const char *doc, int mask, bool error)
296156f886cSKumar Kartikeya Dwivedi {
297156f886cSKumar Kartikeya Dwivedi 	int i;
298156f886cSKumar Kartikeya Dwivedi 
299156f886cSKumar Kartikeya Dwivedi 	if (!error)
300156f886cSKumar Kartikeya Dwivedi 		sample_print_help(mask);
301156f886cSKumar Kartikeya Dwivedi 
302156f886cSKumar Kartikeya Dwivedi 	printf("\n%s\nOption for %s:\n", doc, argv[0]);
303156f886cSKumar Kartikeya Dwivedi 	for (i = 0; long_options[i].name != 0; i++) {
304156f886cSKumar Kartikeya Dwivedi 		printf(" --%-15s", long_options[i].name);
305156f886cSKumar Kartikeya Dwivedi 		if (long_options[i].flag != NULL)
306156f886cSKumar Kartikeya Dwivedi 			printf(" flag (internal value: %d)",
307156f886cSKumar Kartikeya Dwivedi 			       *long_options[i].flag);
308156f886cSKumar Kartikeya Dwivedi 		else
309156f886cSKumar Kartikeya Dwivedi 			printf("\t short-option: -%c", long_options[i].val);
310156f886cSKumar Kartikeya Dwivedi 		printf("\n");
311156f886cSKumar Kartikeya Dwivedi 	}
312156f886cSKumar Kartikeya Dwivedi 	printf("\n");
313156f886cSKumar Kartikeya Dwivedi }
314156f886cSKumar Kartikeya Dwivedi 
alloc_record_per_cpu(void)315156f886cSKumar Kartikeya Dwivedi static struct datarec *alloc_record_per_cpu(void)
316156f886cSKumar Kartikeya Dwivedi {
317156f886cSKumar Kartikeya Dwivedi 	unsigned int nr_cpus = libbpf_num_possible_cpus();
318156f886cSKumar Kartikeya Dwivedi 	struct datarec *array;
319156f886cSKumar Kartikeya Dwivedi 
320156f886cSKumar Kartikeya Dwivedi 	array = calloc(nr_cpus, sizeof(*array));
321156f886cSKumar Kartikeya Dwivedi 	if (!array) {
322156f886cSKumar Kartikeya Dwivedi 		fprintf(stderr, "Failed to allocate memory (nr_cpus: %u)\n",
323156f886cSKumar Kartikeya Dwivedi 			nr_cpus);
324156f886cSKumar Kartikeya Dwivedi 		return NULL;
325156f886cSKumar Kartikeya Dwivedi 	}
326156f886cSKumar Kartikeya Dwivedi 	return array;
327156f886cSKumar Kartikeya Dwivedi }
328156f886cSKumar Kartikeya Dwivedi 
map_entry_init(struct map_entry * e,__u64 pair)329156f886cSKumar Kartikeya Dwivedi static int map_entry_init(struct map_entry *e, __u64 pair)
330156f886cSKumar Kartikeya Dwivedi {
331156f886cSKumar Kartikeya Dwivedi 	e->pair = pair;
332156f886cSKumar Kartikeya Dwivedi 	INIT_HLIST_NODE(&e->node);
333156f886cSKumar Kartikeya Dwivedi 	e->val.timestamp = gettime();
334156f886cSKumar Kartikeya Dwivedi 	e->val.cpu = alloc_record_per_cpu();
335156f886cSKumar Kartikeya Dwivedi 	if (!e->val.cpu)
336156f886cSKumar Kartikeya Dwivedi 		return -ENOMEM;
337156f886cSKumar Kartikeya Dwivedi 	return 0;
338156f886cSKumar Kartikeya Dwivedi }
339156f886cSKumar Kartikeya Dwivedi 
map_collect_percpu(struct datarec * values,struct record * rec)340156f886cSKumar Kartikeya Dwivedi static void map_collect_percpu(struct datarec *values, struct record *rec)
341156f886cSKumar Kartikeya Dwivedi {
342156f886cSKumar Kartikeya Dwivedi 	/* For percpu maps, userspace gets a value per possible CPU */
343156f886cSKumar Kartikeya Dwivedi 	unsigned int nr_cpus = libbpf_num_possible_cpus();
344156f886cSKumar Kartikeya Dwivedi 	__u64 sum_xdp_redirect = 0;
345156f886cSKumar Kartikeya Dwivedi 	__u64 sum_processed = 0;
346156f886cSKumar Kartikeya Dwivedi 	__u64 sum_xdp_pass = 0;
347156f886cSKumar Kartikeya Dwivedi 	__u64 sum_xdp_drop = 0;
348156f886cSKumar Kartikeya Dwivedi 	__u64 sum_dropped = 0;
349156f886cSKumar Kartikeya Dwivedi 	__u64 sum_issue = 0;
350156f886cSKumar Kartikeya Dwivedi 	int i;
351156f886cSKumar Kartikeya Dwivedi 
352156f886cSKumar Kartikeya Dwivedi 	/* Get time as close as possible to reading map contents */
353156f886cSKumar Kartikeya Dwivedi 	rec->timestamp = gettime();
354156f886cSKumar Kartikeya Dwivedi 
355156f886cSKumar Kartikeya Dwivedi 	/* Record and sum values from each CPU */
356156f886cSKumar Kartikeya Dwivedi 	for (i = 0; i < nr_cpus; i++) {
357156f886cSKumar Kartikeya Dwivedi 		rec->cpu[i].processed = READ_ONCE(values[i].processed);
358156f886cSKumar Kartikeya Dwivedi 		rec->cpu[i].dropped = READ_ONCE(values[i].dropped);
359156f886cSKumar Kartikeya Dwivedi 		rec->cpu[i].issue = READ_ONCE(values[i].issue);
360156f886cSKumar Kartikeya Dwivedi 		rec->cpu[i].xdp_pass = READ_ONCE(values[i].xdp_pass);
361156f886cSKumar Kartikeya Dwivedi 		rec->cpu[i].xdp_drop = READ_ONCE(values[i].xdp_drop);
362156f886cSKumar Kartikeya Dwivedi 		rec->cpu[i].xdp_redirect = READ_ONCE(values[i].xdp_redirect);
363156f886cSKumar Kartikeya Dwivedi 
364156f886cSKumar Kartikeya Dwivedi 		sum_processed += rec->cpu[i].processed;
365156f886cSKumar Kartikeya Dwivedi 		sum_dropped += rec->cpu[i].dropped;
366156f886cSKumar Kartikeya Dwivedi 		sum_issue += rec->cpu[i].issue;
367156f886cSKumar Kartikeya Dwivedi 		sum_xdp_pass += rec->cpu[i].xdp_pass;
368156f886cSKumar Kartikeya Dwivedi 		sum_xdp_drop += rec->cpu[i].xdp_drop;
369156f886cSKumar Kartikeya Dwivedi 		sum_xdp_redirect += rec->cpu[i].xdp_redirect;
370156f886cSKumar Kartikeya Dwivedi 	}
371156f886cSKumar Kartikeya Dwivedi 
372156f886cSKumar Kartikeya Dwivedi 	rec->total.processed = sum_processed;
373156f886cSKumar Kartikeya Dwivedi 	rec->total.dropped = sum_dropped;
374156f886cSKumar Kartikeya Dwivedi 	rec->total.issue = sum_issue;
375156f886cSKumar Kartikeya Dwivedi 	rec->total.xdp_pass = sum_xdp_pass;
376156f886cSKumar Kartikeya Dwivedi 	rec->total.xdp_drop = sum_xdp_drop;
377156f886cSKumar Kartikeya Dwivedi 	rec->total.xdp_redirect = sum_xdp_redirect;
378156f886cSKumar Kartikeya Dwivedi }
379156f886cSKumar Kartikeya Dwivedi 
map_collect_percpu_devmap(int map_fd,struct stats_record * rec)380af93d58cSKumar Kartikeya Dwivedi static int map_collect_percpu_devmap(int map_fd, struct stats_record *rec)
381af93d58cSKumar Kartikeya Dwivedi {
382af93d58cSKumar Kartikeya Dwivedi 	unsigned int nr_cpus = bpf_num_possible_cpus();
383af93d58cSKumar Kartikeya Dwivedi 	__u32 batch, count = 32;
384af93d58cSKumar Kartikeya Dwivedi 	struct datarec *values;
385af93d58cSKumar Kartikeya Dwivedi 	bool init = false;
386af93d58cSKumar Kartikeya Dwivedi 	__u64 *keys;
387af93d58cSKumar Kartikeya Dwivedi 	int i, ret;
388af93d58cSKumar Kartikeya Dwivedi 
389af93d58cSKumar Kartikeya Dwivedi 	keys = calloc(count, sizeof(__u64));
390af93d58cSKumar Kartikeya Dwivedi 	if (!keys)
391af93d58cSKumar Kartikeya Dwivedi 		return -ENOMEM;
392af93d58cSKumar Kartikeya Dwivedi 	values = calloc(count * nr_cpus, sizeof(struct datarec));
393af93d58cSKumar Kartikeya Dwivedi 	if (!values) {
394af93d58cSKumar Kartikeya Dwivedi 		free(keys);
395af93d58cSKumar Kartikeya Dwivedi 		return -ENOMEM;
396af93d58cSKumar Kartikeya Dwivedi 	}
397af93d58cSKumar Kartikeya Dwivedi 
398af93d58cSKumar Kartikeya Dwivedi 	for (;;) {
399af93d58cSKumar Kartikeya Dwivedi 		bool exit = false;
400af93d58cSKumar Kartikeya Dwivedi 
401af93d58cSKumar Kartikeya Dwivedi 		ret = bpf_map_lookup_batch(map_fd, init ? &batch : NULL, &batch,
402af93d58cSKumar Kartikeya Dwivedi 					   keys, values, &count, NULL);
403af93d58cSKumar Kartikeya Dwivedi 		if (ret < 0 && errno != ENOENT)
404af93d58cSKumar Kartikeya Dwivedi 			break;
405af93d58cSKumar Kartikeya Dwivedi 		if (errno == ENOENT)
406af93d58cSKumar Kartikeya Dwivedi 			exit = true;
407af93d58cSKumar Kartikeya Dwivedi 
408af93d58cSKumar Kartikeya Dwivedi 		init = true;
409af93d58cSKumar Kartikeya Dwivedi 		for (i = 0; i < count; i++) {
410af93d58cSKumar Kartikeya Dwivedi 			struct map_entry *e, *x = NULL;
411af93d58cSKumar Kartikeya Dwivedi 			__u64 pair = keys[i];
412af93d58cSKumar Kartikeya Dwivedi 			struct datarec *arr;
413af93d58cSKumar Kartikeya Dwivedi 
414af93d58cSKumar Kartikeya Dwivedi 			arr = &values[i * nr_cpus];
415af93d58cSKumar Kartikeya Dwivedi 			hash_for_each_possible(rec->xmit_map, e, node, pair) {
416af93d58cSKumar Kartikeya Dwivedi 				if (e->pair == pair) {
417af93d58cSKumar Kartikeya Dwivedi 					x = e;
418af93d58cSKumar Kartikeya Dwivedi 					break;
419af93d58cSKumar Kartikeya Dwivedi 				}
420af93d58cSKumar Kartikeya Dwivedi 			}
421af93d58cSKumar Kartikeya Dwivedi 			if (!x) {
422af93d58cSKumar Kartikeya Dwivedi 				x = calloc(1, sizeof(*x));
423af93d58cSKumar Kartikeya Dwivedi 				if (!x)
424af93d58cSKumar Kartikeya Dwivedi 					goto cleanup;
425af93d58cSKumar Kartikeya Dwivedi 				if (map_entry_init(x, pair) < 0) {
426af93d58cSKumar Kartikeya Dwivedi 					free(x);
427af93d58cSKumar Kartikeya Dwivedi 					goto cleanup;
428af93d58cSKumar Kartikeya Dwivedi 				}
429af93d58cSKumar Kartikeya Dwivedi 				hash_add(rec->xmit_map, &x->node, pair);
430af93d58cSKumar Kartikeya Dwivedi 			}
431af93d58cSKumar Kartikeya Dwivedi 			map_collect_percpu(arr, &x->val);
432af93d58cSKumar Kartikeya Dwivedi 		}
433af93d58cSKumar Kartikeya Dwivedi 
434af93d58cSKumar Kartikeya Dwivedi 		if (exit)
435af93d58cSKumar Kartikeya Dwivedi 			break;
436af93d58cSKumar Kartikeya Dwivedi 		count = 32;
437af93d58cSKumar Kartikeya Dwivedi 	}
438af93d58cSKumar Kartikeya Dwivedi 
439af93d58cSKumar Kartikeya Dwivedi 	free(values);
440af93d58cSKumar Kartikeya Dwivedi 	free(keys);
441af93d58cSKumar Kartikeya Dwivedi 	return 0;
442af93d58cSKumar Kartikeya Dwivedi cleanup:
443af93d58cSKumar Kartikeya Dwivedi 	free(values);
444af93d58cSKumar Kartikeya Dwivedi 	free(keys);
445af93d58cSKumar Kartikeya Dwivedi 	return -ENOMEM;
446af93d58cSKumar Kartikeya Dwivedi }
447af93d58cSKumar Kartikeya Dwivedi 
alloc_stats_record(void)448156f886cSKumar Kartikeya Dwivedi static struct stats_record *alloc_stats_record(void)
449156f886cSKumar Kartikeya Dwivedi {
450156f886cSKumar Kartikeya Dwivedi 	struct stats_record *rec;
451156f886cSKumar Kartikeya Dwivedi 	int i;
452156f886cSKumar Kartikeya Dwivedi 
453156f886cSKumar Kartikeya Dwivedi 	rec = calloc(1, sizeof(*rec) + sample_n_cpus * sizeof(struct record));
454156f886cSKumar Kartikeya Dwivedi 	if (!rec) {
455156f886cSKumar Kartikeya Dwivedi 		fprintf(stderr, "Failed to allocate memory\n");
456156f886cSKumar Kartikeya Dwivedi 		return NULL;
457156f886cSKumar Kartikeya Dwivedi 	}
458156f886cSKumar Kartikeya Dwivedi 
459156f886cSKumar Kartikeya Dwivedi 	if (sample_mask & SAMPLE_RX_CNT) {
460156f886cSKumar Kartikeya Dwivedi 		rec->rx_cnt.cpu = alloc_record_per_cpu();
461156f886cSKumar Kartikeya Dwivedi 		if (!rec->rx_cnt.cpu) {
462156f886cSKumar Kartikeya Dwivedi 			fprintf(stderr,
463156f886cSKumar Kartikeya Dwivedi 				"Failed to allocate rx_cnt per-CPU array\n");
464156f886cSKumar Kartikeya Dwivedi 			goto end_rec;
465156f886cSKumar Kartikeya Dwivedi 		}
466156f886cSKumar Kartikeya Dwivedi 	}
4671d930fd2SKumar Kartikeya Dwivedi 	if (sample_mask & (SAMPLE_REDIRECT_CNT | SAMPLE_REDIRECT_ERR_CNT)) {
4681d930fd2SKumar Kartikeya Dwivedi 		for (i = 0; i < XDP_REDIRECT_ERR_MAX; i++) {
4691d930fd2SKumar Kartikeya Dwivedi 			rec->redir_err[i].cpu = alloc_record_per_cpu();
4701d930fd2SKumar Kartikeya Dwivedi 			if (!rec->redir_err[i].cpu) {
4711d930fd2SKumar Kartikeya Dwivedi 				fprintf(stderr,
4721d930fd2SKumar Kartikeya Dwivedi 					"Failed to allocate redir_err per-CPU array for "
4731d930fd2SKumar Kartikeya Dwivedi 					"\"%s\" case\n",
4741d930fd2SKumar Kartikeya Dwivedi 					xdp_redirect_err_names[i]);
4751d930fd2SKumar Kartikeya Dwivedi 				while (i--)
4761d930fd2SKumar Kartikeya Dwivedi 					free(rec->redir_err[i].cpu);
4771d930fd2SKumar Kartikeya Dwivedi 				goto end_rx_cnt;
4781d930fd2SKumar Kartikeya Dwivedi 			}
4791d930fd2SKumar Kartikeya Dwivedi 		}
4801d930fd2SKumar Kartikeya Dwivedi 	}
481d771e217SKumar Kartikeya Dwivedi 	if (sample_mask & SAMPLE_CPUMAP_KTHREAD_CNT) {
482d771e217SKumar Kartikeya Dwivedi 		rec->kthread.cpu = alloc_record_per_cpu();
483d771e217SKumar Kartikeya Dwivedi 		if (!rec->kthread.cpu) {
484d771e217SKumar Kartikeya Dwivedi 			fprintf(stderr,
485d771e217SKumar Kartikeya Dwivedi 				"Failed to allocate kthread per-CPU array\n");
486d771e217SKumar Kartikeya Dwivedi 			goto end_redir;
487d771e217SKumar Kartikeya Dwivedi 		}
488d771e217SKumar Kartikeya Dwivedi 	}
48982c45080SKumar Kartikeya Dwivedi 	if (sample_mask & SAMPLE_EXCEPTION_CNT) {
49082c45080SKumar Kartikeya Dwivedi 		for (i = 0; i < XDP_ACTION_MAX; i++) {
49182c45080SKumar Kartikeya Dwivedi 			rec->exception[i].cpu = alloc_record_per_cpu();
49282c45080SKumar Kartikeya Dwivedi 			if (!rec->exception[i].cpu) {
49382c45080SKumar Kartikeya Dwivedi 				fprintf(stderr,
49482c45080SKumar Kartikeya Dwivedi 					"Failed to allocate exception per-CPU array for "
49582c45080SKumar Kartikeya Dwivedi 					"\"%s\" case\n",
49682c45080SKumar Kartikeya Dwivedi 					action2str(i));
49782c45080SKumar Kartikeya Dwivedi 				while (i--)
49882c45080SKumar Kartikeya Dwivedi 					free(rec->exception[i].cpu);
499d771e217SKumar Kartikeya Dwivedi 				goto end_kthread;
500d771e217SKumar Kartikeya Dwivedi 			}
501d771e217SKumar Kartikeya Dwivedi 		}
502d771e217SKumar Kartikeya Dwivedi 	}
503af93d58cSKumar Kartikeya Dwivedi 	if (sample_mask & SAMPLE_DEVMAP_XMIT_CNT) {
504af93d58cSKumar Kartikeya Dwivedi 		rec->devmap_xmit.cpu = alloc_record_per_cpu();
505af93d58cSKumar Kartikeya Dwivedi 		if (!rec->devmap_xmit.cpu) {
506af93d58cSKumar Kartikeya Dwivedi 			fprintf(stderr,
507af93d58cSKumar Kartikeya Dwivedi 				"Failed to allocate devmap_xmit per-CPU array\n");
508af93d58cSKumar Kartikeya Dwivedi 			goto end_exception;
509af93d58cSKumar Kartikeya Dwivedi 		}
510af93d58cSKumar Kartikeya Dwivedi 	}
511af93d58cSKumar Kartikeya Dwivedi 	if (sample_mask & SAMPLE_DEVMAP_XMIT_CNT_MULTI)
512af93d58cSKumar Kartikeya Dwivedi 		hash_init(rec->xmit_map);
513d771e217SKumar Kartikeya Dwivedi 	if (sample_mask & SAMPLE_CPUMAP_ENQUEUE_CNT) {
514d771e217SKumar Kartikeya Dwivedi 		for (i = 0; i < sample_n_cpus; i++) {
515d771e217SKumar Kartikeya Dwivedi 			rec->enq[i].cpu = alloc_record_per_cpu();
516d771e217SKumar Kartikeya Dwivedi 			if (!rec->enq[i].cpu) {
517d771e217SKumar Kartikeya Dwivedi 				fprintf(stderr,
518d771e217SKumar Kartikeya Dwivedi 					"Failed to allocate enqueue per-CPU array for "
519d771e217SKumar Kartikeya Dwivedi 					"CPU %d\n",
520d771e217SKumar Kartikeya Dwivedi 					i);
521d771e217SKumar Kartikeya Dwivedi 				while (i--)
522d771e217SKumar Kartikeya Dwivedi 					free(rec->enq[i].cpu);
523af93d58cSKumar Kartikeya Dwivedi 				goto end_devmap_xmit;
52482c45080SKumar Kartikeya Dwivedi 			}
52582c45080SKumar Kartikeya Dwivedi 		}
52682c45080SKumar Kartikeya Dwivedi 	}
527156f886cSKumar Kartikeya Dwivedi 
528156f886cSKumar Kartikeya Dwivedi 	return rec;
5291d930fd2SKumar Kartikeya Dwivedi 
530af93d58cSKumar Kartikeya Dwivedi end_devmap_xmit:
531af93d58cSKumar Kartikeya Dwivedi 	free(rec->devmap_xmit.cpu);
532d771e217SKumar Kartikeya Dwivedi end_exception:
533d771e217SKumar Kartikeya Dwivedi 	for (i = 0; i < XDP_ACTION_MAX; i++)
534d771e217SKumar Kartikeya Dwivedi 		free(rec->exception[i].cpu);
535d771e217SKumar Kartikeya Dwivedi end_kthread:
536d771e217SKumar Kartikeya Dwivedi 	free(rec->kthread.cpu);
53782c45080SKumar Kartikeya Dwivedi end_redir:
53882c45080SKumar Kartikeya Dwivedi 	for (i = 0; i < XDP_REDIRECT_ERR_MAX; i++)
53982c45080SKumar Kartikeya Dwivedi 		free(rec->redir_err[i].cpu);
5401d930fd2SKumar Kartikeya Dwivedi end_rx_cnt:
5411d930fd2SKumar Kartikeya Dwivedi 	free(rec->rx_cnt.cpu);
542156f886cSKumar Kartikeya Dwivedi end_rec:
543156f886cSKumar Kartikeya Dwivedi 	free(rec);
544156f886cSKumar Kartikeya Dwivedi 	return NULL;
545156f886cSKumar Kartikeya Dwivedi }
546156f886cSKumar Kartikeya Dwivedi 
free_stats_record(struct stats_record * r)547156f886cSKumar Kartikeya Dwivedi static void free_stats_record(struct stats_record *r)
548156f886cSKumar Kartikeya Dwivedi {
549156f886cSKumar Kartikeya Dwivedi 	struct hlist_node *tmp;
550156f886cSKumar Kartikeya Dwivedi 	struct map_entry *e;
551156f886cSKumar Kartikeya Dwivedi 	int i;
552156f886cSKumar Kartikeya Dwivedi 
553d771e217SKumar Kartikeya Dwivedi 	for (i = 0; i < sample_n_cpus; i++)
554d771e217SKumar Kartikeya Dwivedi 		free(r->enq[i].cpu);
555af93d58cSKumar Kartikeya Dwivedi 	hash_for_each_safe(r->xmit_map, i, tmp, e, node) {
556af93d58cSKumar Kartikeya Dwivedi 		hash_del(&e->node);
557af93d58cSKumar Kartikeya Dwivedi 		free(e->val.cpu);
558af93d58cSKumar Kartikeya Dwivedi 		free(e);
559af93d58cSKumar Kartikeya Dwivedi 	}
560af93d58cSKumar Kartikeya Dwivedi 	free(r->devmap_xmit.cpu);
56182c45080SKumar Kartikeya Dwivedi 	for (i = 0; i < XDP_ACTION_MAX; i++)
56282c45080SKumar Kartikeya Dwivedi 		free(r->exception[i].cpu);
563d771e217SKumar Kartikeya Dwivedi 	free(r->kthread.cpu);
5641d930fd2SKumar Kartikeya Dwivedi 	for (i = 0; i < XDP_REDIRECT_ERR_MAX; i++)
5651d930fd2SKumar Kartikeya Dwivedi 		free(r->redir_err[i].cpu);
566156f886cSKumar Kartikeya Dwivedi 	free(r->rx_cnt.cpu);
567156f886cSKumar Kartikeya Dwivedi 	free(r);
568156f886cSKumar Kartikeya Dwivedi }
569156f886cSKumar Kartikeya Dwivedi 
calc_period(struct record * r,struct record * p)570156f886cSKumar Kartikeya Dwivedi static double calc_period(struct record *r, struct record *p)
571156f886cSKumar Kartikeya Dwivedi {
572156f886cSKumar Kartikeya Dwivedi 	double period_ = 0;
573156f886cSKumar Kartikeya Dwivedi 	__u64 period = 0;
574156f886cSKumar Kartikeya Dwivedi 
575156f886cSKumar Kartikeya Dwivedi 	period = r->timestamp - p->timestamp;
576156f886cSKumar Kartikeya Dwivedi 	if (period > 0)
577156f886cSKumar Kartikeya Dwivedi 		period_ = ((double)period / NANOSEC_PER_SEC);
578156f886cSKumar Kartikeya Dwivedi 
579156f886cSKumar Kartikeya Dwivedi 	return period_;
580156f886cSKumar Kartikeya Dwivedi }
581156f886cSKumar Kartikeya Dwivedi 
sample_round(double val)582156f886cSKumar Kartikeya Dwivedi static double sample_round(double val)
583156f886cSKumar Kartikeya Dwivedi {
584156f886cSKumar Kartikeya Dwivedi 	if (val - floor(val) < 0.5)
585156f886cSKumar Kartikeya Dwivedi 		return floor(val);
586156f886cSKumar Kartikeya Dwivedi 	return ceil(val);
587156f886cSKumar Kartikeya Dwivedi }
588156f886cSKumar Kartikeya Dwivedi 
calc_pps(struct datarec * r,struct datarec * p,double period_)589156f886cSKumar Kartikeya Dwivedi static __u64 calc_pps(struct datarec *r, struct datarec *p, double period_)
590156f886cSKumar Kartikeya Dwivedi {
591156f886cSKumar Kartikeya Dwivedi 	__u64 packets = 0;
592156f886cSKumar Kartikeya Dwivedi 	__u64 pps = 0;
593156f886cSKumar Kartikeya Dwivedi 
594156f886cSKumar Kartikeya Dwivedi 	if (period_ > 0) {
595156f886cSKumar Kartikeya Dwivedi 		packets = r->processed - p->processed;
596156f886cSKumar Kartikeya Dwivedi 		pps = sample_round(packets / period_);
597156f886cSKumar Kartikeya Dwivedi 	}
598156f886cSKumar Kartikeya Dwivedi 	return pps;
599156f886cSKumar Kartikeya Dwivedi }
600156f886cSKumar Kartikeya Dwivedi 
calc_drop_pps(struct datarec * r,struct datarec * p,double period_)601156f886cSKumar Kartikeya Dwivedi static __u64 calc_drop_pps(struct datarec *r, struct datarec *p, double period_)
602156f886cSKumar Kartikeya Dwivedi {
603156f886cSKumar Kartikeya Dwivedi 	__u64 packets = 0;
604156f886cSKumar Kartikeya Dwivedi 	__u64 pps = 0;
605156f886cSKumar Kartikeya Dwivedi 
606156f886cSKumar Kartikeya Dwivedi 	if (period_ > 0) {
607156f886cSKumar Kartikeya Dwivedi 		packets = r->dropped - p->dropped;
608156f886cSKumar Kartikeya Dwivedi 		pps = sample_round(packets / period_);
609156f886cSKumar Kartikeya Dwivedi 	}
610156f886cSKumar Kartikeya Dwivedi 	return pps;
611156f886cSKumar Kartikeya Dwivedi }
612156f886cSKumar Kartikeya Dwivedi 
calc_errs_pps(struct datarec * r,struct datarec * p,double period_)613156f886cSKumar Kartikeya Dwivedi static __u64 calc_errs_pps(struct datarec *r, struct datarec *p, double period_)
614156f886cSKumar Kartikeya Dwivedi {
615156f886cSKumar Kartikeya Dwivedi 	__u64 packets = 0;
616156f886cSKumar Kartikeya Dwivedi 	__u64 pps = 0;
617156f886cSKumar Kartikeya Dwivedi 
618156f886cSKumar Kartikeya Dwivedi 	if (period_ > 0) {
619156f886cSKumar Kartikeya Dwivedi 		packets = r->issue - p->issue;
620156f886cSKumar Kartikeya Dwivedi 		pps = sample_round(packets / period_);
621156f886cSKumar Kartikeya Dwivedi 	}
622156f886cSKumar Kartikeya Dwivedi 	return pps;
623156f886cSKumar Kartikeya Dwivedi }
624156f886cSKumar Kartikeya Dwivedi 
calc_info_pps(struct datarec * r,struct datarec * p,double period_)625156f886cSKumar Kartikeya Dwivedi static __u64 calc_info_pps(struct datarec *r, struct datarec *p, double period_)
626156f886cSKumar Kartikeya Dwivedi {
627156f886cSKumar Kartikeya Dwivedi 	__u64 packets = 0;
628156f886cSKumar Kartikeya Dwivedi 	__u64 pps = 0;
629156f886cSKumar Kartikeya Dwivedi 
630156f886cSKumar Kartikeya Dwivedi 	if (period_ > 0) {
631156f886cSKumar Kartikeya Dwivedi 		packets = r->info - p->info;
632156f886cSKumar Kartikeya Dwivedi 		pps = sample_round(packets / period_);
633156f886cSKumar Kartikeya Dwivedi 	}
634156f886cSKumar Kartikeya Dwivedi 	return pps;
635156f886cSKumar Kartikeya Dwivedi }
636156f886cSKumar Kartikeya Dwivedi 
calc_xdp_pps(struct datarec * r,struct datarec * p,double * xdp_pass,double * xdp_drop,double * xdp_redirect,double period_)637156f886cSKumar Kartikeya Dwivedi static void calc_xdp_pps(struct datarec *r, struct datarec *p, double *xdp_pass,
638156f886cSKumar Kartikeya Dwivedi 			 double *xdp_drop, double *xdp_redirect, double period_)
639156f886cSKumar Kartikeya Dwivedi {
640156f886cSKumar Kartikeya Dwivedi 	*xdp_pass = 0, *xdp_drop = 0, *xdp_redirect = 0;
641156f886cSKumar Kartikeya Dwivedi 	if (period_ > 0) {
642156f886cSKumar Kartikeya Dwivedi 		*xdp_redirect = (r->xdp_redirect - p->xdp_redirect) / period_;
643156f886cSKumar Kartikeya Dwivedi 		*xdp_pass = (r->xdp_pass - p->xdp_pass) / period_;
644156f886cSKumar Kartikeya Dwivedi 		*xdp_drop = (r->xdp_drop - p->xdp_drop) / period_;
645156f886cSKumar Kartikeya Dwivedi 	}
646156f886cSKumar Kartikeya Dwivedi }
647156f886cSKumar Kartikeya Dwivedi 
stats_get_rx_cnt(struct stats_record * stats_rec,struct stats_record * stats_prev,unsigned int nr_cpus,struct sample_output * out)648156f886cSKumar Kartikeya Dwivedi static void stats_get_rx_cnt(struct stats_record *stats_rec,
649156f886cSKumar Kartikeya Dwivedi 			     struct stats_record *stats_prev,
650156f886cSKumar Kartikeya Dwivedi 			     unsigned int nr_cpus, struct sample_output *out)
651156f886cSKumar Kartikeya Dwivedi {
652156f886cSKumar Kartikeya Dwivedi 	struct record *rec, *prev;
653156f886cSKumar Kartikeya Dwivedi 	double t, pps, drop, err;
654156f886cSKumar Kartikeya Dwivedi 	int i;
655156f886cSKumar Kartikeya Dwivedi 
656156f886cSKumar Kartikeya Dwivedi 	rec = &stats_rec->rx_cnt;
657156f886cSKumar Kartikeya Dwivedi 	prev = &stats_prev->rx_cnt;
658156f886cSKumar Kartikeya Dwivedi 	t = calc_period(rec, prev);
659156f886cSKumar Kartikeya Dwivedi 
660156f886cSKumar Kartikeya Dwivedi 	for (i = 0; i < nr_cpus; i++) {
661156f886cSKumar Kartikeya Dwivedi 		struct datarec *r = &rec->cpu[i];
662156f886cSKumar Kartikeya Dwivedi 		struct datarec *p = &prev->cpu[i];
663156f886cSKumar Kartikeya Dwivedi 		char str[64];
664156f886cSKumar Kartikeya Dwivedi 
665156f886cSKumar Kartikeya Dwivedi 		pps = calc_pps(r, p, t);
666156f886cSKumar Kartikeya Dwivedi 		drop = calc_drop_pps(r, p, t);
667156f886cSKumar Kartikeya Dwivedi 		err = calc_errs_pps(r, p, t);
668156f886cSKumar Kartikeya Dwivedi 		if (!pps && !drop && !err)
669156f886cSKumar Kartikeya Dwivedi 			continue;
670156f886cSKumar Kartikeya Dwivedi 
671156f886cSKumar Kartikeya Dwivedi 		snprintf(str, sizeof(str), "cpu:%d", i);
672156f886cSKumar Kartikeya Dwivedi 		print_default("    %-18s " FMT_COLUMNf FMT_COLUMNf FMT_COLUMNf
673156f886cSKumar Kartikeya Dwivedi 			      "\n",
674156f886cSKumar Kartikeya Dwivedi 			      str, PPS(pps), DROP(drop), ERR(err));
675156f886cSKumar Kartikeya Dwivedi 	}
676156f886cSKumar Kartikeya Dwivedi 
677156f886cSKumar Kartikeya Dwivedi 	if (out) {
678156f886cSKumar Kartikeya Dwivedi 		pps = calc_pps(&rec->total, &prev->total, t);
679156f886cSKumar Kartikeya Dwivedi 		drop = calc_drop_pps(&rec->total, &prev->total, t);
680156f886cSKumar Kartikeya Dwivedi 		err = calc_errs_pps(&rec->total, &prev->total, t);
681156f886cSKumar Kartikeya Dwivedi 
682156f886cSKumar Kartikeya Dwivedi 		out->rx_cnt.pps = pps;
683156f886cSKumar Kartikeya Dwivedi 		out->rx_cnt.drop = drop;
684156f886cSKumar Kartikeya Dwivedi 		out->rx_cnt.err = err;
685156f886cSKumar Kartikeya Dwivedi 		out->totals.rx += pps;
686156f886cSKumar Kartikeya Dwivedi 		out->totals.drop += drop;
687156f886cSKumar Kartikeya Dwivedi 		out->totals.err += err;
688156f886cSKumar Kartikeya Dwivedi 	}
689156f886cSKumar Kartikeya Dwivedi }
690156f886cSKumar Kartikeya Dwivedi 
stats_get_cpumap_enqueue(struct stats_record * stats_rec,struct stats_record * stats_prev,unsigned int nr_cpus)691d771e217SKumar Kartikeya Dwivedi static void stats_get_cpumap_enqueue(struct stats_record *stats_rec,
692d771e217SKumar Kartikeya Dwivedi 				     struct stats_record *stats_prev,
693d771e217SKumar Kartikeya Dwivedi 				     unsigned int nr_cpus)
694d771e217SKumar Kartikeya Dwivedi {
695d771e217SKumar Kartikeya Dwivedi 	struct record *rec, *prev;
696d771e217SKumar Kartikeya Dwivedi 	double t, pps, drop, err;
697d771e217SKumar Kartikeya Dwivedi 	int i, to_cpu;
698d771e217SKumar Kartikeya Dwivedi 
699d771e217SKumar Kartikeya Dwivedi 	/* cpumap enqueue stats */
700d771e217SKumar Kartikeya Dwivedi 	for (to_cpu = 0; to_cpu < sample_n_cpus; to_cpu++) {
701d771e217SKumar Kartikeya Dwivedi 		rec = &stats_rec->enq[to_cpu];
702d771e217SKumar Kartikeya Dwivedi 		prev = &stats_prev->enq[to_cpu];
703d771e217SKumar Kartikeya Dwivedi 		t = calc_period(rec, prev);
704d771e217SKumar Kartikeya Dwivedi 
705d771e217SKumar Kartikeya Dwivedi 		pps = calc_pps(&rec->total, &prev->total, t);
706d771e217SKumar Kartikeya Dwivedi 		drop = calc_drop_pps(&rec->total, &prev->total, t);
707d771e217SKumar Kartikeya Dwivedi 		err = calc_errs_pps(&rec->total, &prev->total, t);
708d771e217SKumar Kartikeya Dwivedi 
709d771e217SKumar Kartikeya Dwivedi 		if (pps > 0 || drop > 0) {
710d771e217SKumar Kartikeya Dwivedi 			char str[64];
711d771e217SKumar Kartikeya Dwivedi 
712d771e217SKumar Kartikeya Dwivedi 			snprintf(str, sizeof(str), "enqueue to cpu %d", to_cpu);
713d771e217SKumar Kartikeya Dwivedi 
714d771e217SKumar Kartikeya Dwivedi 			if (err > 0)
715d771e217SKumar Kartikeya Dwivedi 				err = pps / err; /* calc average bulk size */
716d771e217SKumar Kartikeya Dwivedi 
717d771e217SKumar Kartikeya Dwivedi 			print_err(drop,
718d771e217SKumar Kartikeya Dwivedi 				  "  %-20s " FMT_COLUMNf FMT_COLUMNf __COLUMN(
719d771e217SKumar Kartikeya Dwivedi 					  ".2f") "\n",
720d771e217SKumar Kartikeya Dwivedi 				  str, PPS(pps), DROP(drop), err, "bulk-avg");
721d771e217SKumar Kartikeya Dwivedi 		}
722d771e217SKumar Kartikeya Dwivedi 
723d771e217SKumar Kartikeya Dwivedi 		for (i = 0; i < nr_cpus; i++) {
724d771e217SKumar Kartikeya Dwivedi 			struct datarec *r = &rec->cpu[i];
725d771e217SKumar Kartikeya Dwivedi 			struct datarec *p = &prev->cpu[i];
726d771e217SKumar Kartikeya Dwivedi 			char str[64];
727d771e217SKumar Kartikeya Dwivedi 
728d771e217SKumar Kartikeya Dwivedi 			pps = calc_pps(r, p, t);
729d771e217SKumar Kartikeya Dwivedi 			drop = calc_drop_pps(r, p, t);
730d771e217SKumar Kartikeya Dwivedi 			err = calc_errs_pps(r, p, t);
731d771e217SKumar Kartikeya Dwivedi 			if (!pps && !drop && !err)
732d771e217SKumar Kartikeya Dwivedi 				continue;
733d771e217SKumar Kartikeya Dwivedi 
734d771e217SKumar Kartikeya Dwivedi 			snprintf(str, sizeof(str), "cpu:%d->%d", i, to_cpu);
735d771e217SKumar Kartikeya Dwivedi 			if (err > 0)
736d771e217SKumar Kartikeya Dwivedi 				err = pps / err; /* calc average bulk size */
737d771e217SKumar Kartikeya Dwivedi 			print_default(
738d771e217SKumar Kartikeya Dwivedi 				"    %-18s " FMT_COLUMNf FMT_COLUMNf __COLUMN(
739d771e217SKumar Kartikeya Dwivedi 					".2f") "\n",
740d771e217SKumar Kartikeya Dwivedi 				str, PPS(pps), DROP(drop), err, "bulk-avg");
741d771e217SKumar Kartikeya Dwivedi 		}
742d771e217SKumar Kartikeya Dwivedi 	}
743d771e217SKumar Kartikeya Dwivedi }
744d771e217SKumar Kartikeya Dwivedi 
stats_get_cpumap_remote(struct stats_record * stats_rec,struct stats_record * stats_prev,unsigned int nr_cpus)745d771e217SKumar Kartikeya Dwivedi static void stats_get_cpumap_remote(struct stats_record *stats_rec,
746d771e217SKumar Kartikeya Dwivedi 				    struct stats_record *stats_prev,
747d771e217SKumar Kartikeya Dwivedi 				    unsigned int nr_cpus)
748d771e217SKumar Kartikeya Dwivedi {
749d771e217SKumar Kartikeya Dwivedi 	double xdp_pass, xdp_drop, xdp_redirect;
750d771e217SKumar Kartikeya Dwivedi 	struct record *rec, *prev;
751d771e217SKumar Kartikeya Dwivedi 	double t;
752d771e217SKumar Kartikeya Dwivedi 	int i;
753d771e217SKumar Kartikeya Dwivedi 
754d771e217SKumar Kartikeya Dwivedi 	rec = &stats_rec->kthread;
755d771e217SKumar Kartikeya Dwivedi 	prev = &stats_prev->kthread;
756d771e217SKumar Kartikeya Dwivedi 	t = calc_period(rec, prev);
757d771e217SKumar Kartikeya Dwivedi 
758d771e217SKumar Kartikeya Dwivedi 	calc_xdp_pps(&rec->total, &prev->total, &xdp_pass, &xdp_drop,
759d771e217SKumar Kartikeya Dwivedi 		     &xdp_redirect, t);
760d771e217SKumar Kartikeya Dwivedi 	if (xdp_pass || xdp_drop || xdp_redirect) {
761d771e217SKumar Kartikeya Dwivedi 		print_err(xdp_drop,
762d771e217SKumar Kartikeya Dwivedi 			  "    %-18s " FMT_COLUMNf FMT_COLUMNf FMT_COLUMNf "\n",
763d771e217SKumar Kartikeya Dwivedi 			  "xdp_stats", PASS(xdp_pass), DROP(xdp_drop),
764d771e217SKumar Kartikeya Dwivedi 			  REDIR(xdp_redirect));
765d771e217SKumar Kartikeya Dwivedi 	}
766d771e217SKumar Kartikeya Dwivedi 
767d771e217SKumar Kartikeya Dwivedi 	for (i = 0; i < nr_cpus; i++) {
768d771e217SKumar Kartikeya Dwivedi 		struct datarec *r = &rec->cpu[i];
769d771e217SKumar Kartikeya Dwivedi 		struct datarec *p = &prev->cpu[i];
770d771e217SKumar Kartikeya Dwivedi 		char str[64];
771d771e217SKumar Kartikeya Dwivedi 
772d771e217SKumar Kartikeya Dwivedi 		calc_xdp_pps(r, p, &xdp_pass, &xdp_drop, &xdp_redirect, t);
773d771e217SKumar Kartikeya Dwivedi 		if (!xdp_pass && !xdp_drop && !xdp_redirect)
774d771e217SKumar Kartikeya Dwivedi 			continue;
775d771e217SKumar Kartikeya Dwivedi 
776d771e217SKumar Kartikeya Dwivedi 		snprintf(str, sizeof(str), "cpu:%d", i);
777d771e217SKumar Kartikeya Dwivedi 		print_default("      %-16s " FMT_COLUMNf FMT_COLUMNf FMT_COLUMNf
778d771e217SKumar Kartikeya Dwivedi 			      "\n",
779d771e217SKumar Kartikeya Dwivedi 			      str, PASS(xdp_pass), DROP(xdp_drop),
780d771e217SKumar Kartikeya Dwivedi 			      REDIR(xdp_redirect));
781d771e217SKumar Kartikeya Dwivedi 	}
782d771e217SKumar Kartikeya Dwivedi }
783d771e217SKumar Kartikeya Dwivedi 
stats_get_cpumap_kthread(struct stats_record * stats_rec,struct stats_record * stats_prev,unsigned int nr_cpus)784d771e217SKumar Kartikeya Dwivedi static void stats_get_cpumap_kthread(struct stats_record *stats_rec,
785d771e217SKumar Kartikeya Dwivedi 				     struct stats_record *stats_prev,
786d771e217SKumar Kartikeya Dwivedi 				     unsigned int nr_cpus)
787d771e217SKumar Kartikeya Dwivedi {
788d771e217SKumar Kartikeya Dwivedi 	struct record *rec, *prev;
789d771e217SKumar Kartikeya Dwivedi 	double t, pps, drop, err;
790d771e217SKumar Kartikeya Dwivedi 	int i;
791d771e217SKumar Kartikeya Dwivedi 
792d771e217SKumar Kartikeya Dwivedi 	rec = &stats_rec->kthread;
793d771e217SKumar Kartikeya Dwivedi 	prev = &stats_prev->kthread;
794d771e217SKumar Kartikeya Dwivedi 	t = calc_period(rec, prev);
795d771e217SKumar Kartikeya Dwivedi 
796d771e217SKumar Kartikeya Dwivedi 	pps = calc_pps(&rec->total, &prev->total, t);
797d771e217SKumar Kartikeya Dwivedi 	drop = calc_drop_pps(&rec->total, &prev->total, t);
798d771e217SKumar Kartikeya Dwivedi 	err = calc_errs_pps(&rec->total, &prev->total, t);
799d771e217SKumar Kartikeya Dwivedi 
800d771e217SKumar Kartikeya Dwivedi 	print_err(drop, "  %-20s " FMT_COLUMNf FMT_COLUMNf FMT_COLUMNf "\n",
801d771e217SKumar Kartikeya Dwivedi 		  pps ? "kthread total" : "kthread", PPS(pps), DROP(drop), err,
802d771e217SKumar Kartikeya Dwivedi 		  "sched");
803d771e217SKumar Kartikeya Dwivedi 
804d771e217SKumar Kartikeya Dwivedi 	for (i = 0; i < nr_cpus; i++) {
805d771e217SKumar Kartikeya Dwivedi 		struct datarec *r = &rec->cpu[i];
806d771e217SKumar Kartikeya Dwivedi 		struct datarec *p = &prev->cpu[i];
807d771e217SKumar Kartikeya Dwivedi 		char str[64];
808d771e217SKumar Kartikeya Dwivedi 
809d771e217SKumar Kartikeya Dwivedi 		pps = calc_pps(r, p, t);
810d771e217SKumar Kartikeya Dwivedi 		drop = calc_drop_pps(r, p, t);
811d771e217SKumar Kartikeya Dwivedi 		err = calc_errs_pps(r, p, t);
812d771e217SKumar Kartikeya Dwivedi 		if (!pps && !drop && !err)
813d771e217SKumar Kartikeya Dwivedi 			continue;
814d771e217SKumar Kartikeya Dwivedi 
815d771e217SKumar Kartikeya Dwivedi 		snprintf(str, sizeof(str), "cpu:%d", i);
816d771e217SKumar Kartikeya Dwivedi 		print_default("    %-18s " FMT_COLUMNf FMT_COLUMNf FMT_COLUMNf
817d771e217SKumar Kartikeya Dwivedi 			      "\n",
818d771e217SKumar Kartikeya Dwivedi 			      str, PPS(pps), DROP(drop), err, "sched");
819d771e217SKumar Kartikeya Dwivedi 	}
820d771e217SKumar Kartikeya Dwivedi }
821d771e217SKumar Kartikeya Dwivedi 
stats_get_redirect_cnt(struct stats_record * stats_rec,struct stats_record * stats_prev,unsigned int nr_cpus,struct sample_output * out)8221d930fd2SKumar Kartikeya Dwivedi static void stats_get_redirect_cnt(struct stats_record *stats_rec,
8231d930fd2SKumar Kartikeya Dwivedi 				   struct stats_record *stats_prev,
8241d930fd2SKumar Kartikeya Dwivedi 				   unsigned int nr_cpus,
8251d930fd2SKumar Kartikeya Dwivedi 				   struct sample_output *out)
8261d930fd2SKumar Kartikeya Dwivedi {
8271d930fd2SKumar Kartikeya Dwivedi 	struct record *rec, *prev;
8281d930fd2SKumar Kartikeya Dwivedi 	double t, pps;
8291d930fd2SKumar Kartikeya Dwivedi 	int i;
8301d930fd2SKumar Kartikeya Dwivedi 
8311d930fd2SKumar Kartikeya Dwivedi 	rec = &stats_rec->redir_err[0];
8321d930fd2SKumar Kartikeya Dwivedi 	prev = &stats_prev->redir_err[0];
8331d930fd2SKumar Kartikeya Dwivedi 	t = calc_period(rec, prev);
8341d930fd2SKumar Kartikeya Dwivedi 	for (i = 0; i < nr_cpus; i++) {
8351d930fd2SKumar Kartikeya Dwivedi 		struct datarec *r = &rec->cpu[i];
8361d930fd2SKumar Kartikeya Dwivedi 		struct datarec *p = &prev->cpu[i];
8371d930fd2SKumar Kartikeya Dwivedi 		char str[64];
8381d930fd2SKumar Kartikeya Dwivedi 
8391d930fd2SKumar Kartikeya Dwivedi 		pps = calc_pps(r, p, t);
8401d930fd2SKumar Kartikeya Dwivedi 		if (!pps)
8411d930fd2SKumar Kartikeya Dwivedi 			continue;
8421d930fd2SKumar Kartikeya Dwivedi 
8431d930fd2SKumar Kartikeya Dwivedi 		snprintf(str, sizeof(str), "cpu:%d", i);
8441d930fd2SKumar Kartikeya Dwivedi 		print_default("    %-18s " FMT_COLUMNf "\n", str, REDIR(pps));
8451d930fd2SKumar Kartikeya Dwivedi 	}
8461d930fd2SKumar Kartikeya Dwivedi 
8471d930fd2SKumar Kartikeya Dwivedi 	if (out) {
8481d930fd2SKumar Kartikeya Dwivedi 		pps = calc_pps(&rec->total, &prev->total, t);
8491d930fd2SKumar Kartikeya Dwivedi 		out->redir_cnt.suc = pps;
8501d930fd2SKumar Kartikeya Dwivedi 		out->totals.redir += pps;
8511d930fd2SKumar Kartikeya Dwivedi 	}
8521d930fd2SKumar Kartikeya Dwivedi }
8531d930fd2SKumar Kartikeya Dwivedi 
stats_get_redirect_err_cnt(struct stats_record * stats_rec,struct stats_record * stats_prev,unsigned int nr_cpus,struct sample_output * out)8541d930fd2SKumar Kartikeya Dwivedi static void stats_get_redirect_err_cnt(struct stats_record *stats_rec,
8551d930fd2SKumar Kartikeya Dwivedi 				       struct stats_record *stats_prev,
8561d930fd2SKumar Kartikeya Dwivedi 				       unsigned int nr_cpus,
8571d930fd2SKumar Kartikeya Dwivedi 				       struct sample_output *out)
8581d930fd2SKumar Kartikeya Dwivedi {
8591d930fd2SKumar Kartikeya Dwivedi 	struct record *rec, *prev;
8601d930fd2SKumar Kartikeya Dwivedi 	double t, drop, sum = 0;
8611d930fd2SKumar Kartikeya Dwivedi 	int rec_i, i;
8621d930fd2SKumar Kartikeya Dwivedi 
8631d930fd2SKumar Kartikeya Dwivedi 	for (rec_i = 1; rec_i < XDP_REDIRECT_ERR_MAX; rec_i++) {
8641d930fd2SKumar Kartikeya Dwivedi 		char str[64];
8651d930fd2SKumar Kartikeya Dwivedi 
8661d930fd2SKumar Kartikeya Dwivedi 		rec = &stats_rec->redir_err[rec_i];
8671d930fd2SKumar Kartikeya Dwivedi 		prev = &stats_prev->redir_err[rec_i];
8681d930fd2SKumar Kartikeya Dwivedi 		t = calc_period(rec, prev);
8691d930fd2SKumar Kartikeya Dwivedi 
8701d930fd2SKumar Kartikeya Dwivedi 		drop = calc_drop_pps(&rec->total, &prev->total, t);
8711d930fd2SKumar Kartikeya Dwivedi 		if (drop > 0 && !out) {
8721d930fd2SKumar Kartikeya Dwivedi 			snprintf(str, sizeof(str),
8731d930fd2SKumar Kartikeya Dwivedi 				 sample_log_level & LL_DEFAULT ? "%s total" :
8741d930fd2SKumar Kartikeya Dwivedi 								       "%s",
8751d930fd2SKumar Kartikeya Dwivedi 				 xdp_redirect_err_names[rec_i]);
8761d930fd2SKumar Kartikeya Dwivedi 			print_err(drop, "    %-18s " FMT_COLUMNf "\n", str,
8771d930fd2SKumar Kartikeya Dwivedi 				  ERR(drop));
8781d930fd2SKumar Kartikeya Dwivedi 		}
8791d930fd2SKumar Kartikeya Dwivedi 
8801d930fd2SKumar Kartikeya Dwivedi 		for (i = 0; i < nr_cpus; i++) {
8811d930fd2SKumar Kartikeya Dwivedi 			struct datarec *r = &rec->cpu[i];
8821d930fd2SKumar Kartikeya Dwivedi 			struct datarec *p = &prev->cpu[i];
8831d930fd2SKumar Kartikeya Dwivedi 			double drop;
8841d930fd2SKumar Kartikeya Dwivedi 
8851d930fd2SKumar Kartikeya Dwivedi 			drop = calc_drop_pps(r, p, t);
8861d930fd2SKumar Kartikeya Dwivedi 			if (!drop)
8871d930fd2SKumar Kartikeya Dwivedi 				continue;
8881d930fd2SKumar Kartikeya Dwivedi 
8891d930fd2SKumar Kartikeya Dwivedi 			snprintf(str, sizeof(str), "cpu:%d", i);
8901d930fd2SKumar Kartikeya Dwivedi 			print_default("       %-16s" FMT_COLUMNf "\n", str,
8911d930fd2SKumar Kartikeya Dwivedi 				      ERR(drop));
8921d930fd2SKumar Kartikeya Dwivedi 		}
8931d930fd2SKumar Kartikeya Dwivedi 
8941d930fd2SKumar Kartikeya Dwivedi 		sum += drop;
8951d930fd2SKumar Kartikeya Dwivedi 	}
8961d930fd2SKumar Kartikeya Dwivedi 
8971d930fd2SKumar Kartikeya Dwivedi 	if (out) {
8981d930fd2SKumar Kartikeya Dwivedi 		out->redir_cnt.err = sum;
8991d930fd2SKumar Kartikeya Dwivedi 		out->totals.err += sum;
9001d930fd2SKumar Kartikeya Dwivedi 	}
9011d930fd2SKumar Kartikeya Dwivedi }
9021d930fd2SKumar Kartikeya Dwivedi 
stats_get_exception_cnt(struct stats_record * stats_rec,struct stats_record * stats_prev,unsigned int nr_cpus,struct sample_output * out)90382c45080SKumar Kartikeya Dwivedi static void stats_get_exception_cnt(struct stats_record *stats_rec,
90482c45080SKumar Kartikeya Dwivedi 				    struct stats_record *stats_prev,
90582c45080SKumar Kartikeya Dwivedi 				    unsigned int nr_cpus,
90682c45080SKumar Kartikeya Dwivedi 				    struct sample_output *out)
90782c45080SKumar Kartikeya Dwivedi {
90882c45080SKumar Kartikeya Dwivedi 	double t, drop, sum = 0;
90982c45080SKumar Kartikeya Dwivedi 	struct record *rec, *prev;
91082c45080SKumar Kartikeya Dwivedi 	int rec_i, i;
91182c45080SKumar Kartikeya Dwivedi 
91282c45080SKumar Kartikeya Dwivedi 	for (rec_i = 0; rec_i < XDP_ACTION_MAX; rec_i++) {
91382c45080SKumar Kartikeya Dwivedi 		rec = &stats_rec->exception[rec_i];
91482c45080SKumar Kartikeya Dwivedi 		prev = &stats_prev->exception[rec_i];
91582c45080SKumar Kartikeya Dwivedi 		t = calc_period(rec, prev);
91682c45080SKumar Kartikeya Dwivedi 
91782c45080SKumar Kartikeya Dwivedi 		drop = calc_drop_pps(&rec->total, &prev->total, t);
91882c45080SKumar Kartikeya Dwivedi 		/* Fold out errors after heading */
91982c45080SKumar Kartikeya Dwivedi 		sum += drop;
92082c45080SKumar Kartikeya Dwivedi 
92182c45080SKumar Kartikeya Dwivedi 		if (drop > 0 && !out) {
92282c45080SKumar Kartikeya Dwivedi 			print_always("    %-18s " FMT_COLUMNf "\n",
92382c45080SKumar Kartikeya Dwivedi 				     action2str(rec_i), ERR(drop));
92482c45080SKumar Kartikeya Dwivedi 
92582c45080SKumar Kartikeya Dwivedi 			for (i = 0; i < nr_cpus; i++) {
92682c45080SKumar Kartikeya Dwivedi 				struct datarec *r = &rec->cpu[i];
92782c45080SKumar Kartikeya Dwivedi 				struct datarec *p = &prev->cpu[i];
92882c45080SKumar Kartikeya Dwivedi 				char str[64];
92982c45080SKumar Kartikeya Dwivedi 				double drop;
93082c45080SKumar Kartikeya Dwivedi 
93182c45080SKumar Kartikeya Dwivedi 				drop = calc_drop_pps(r, p, t);
93282c45080SKumar Kartikeya Dwivedi 				if (!drop)
93382c45080SKumar Kartikeya Dwivedi 					continue;
93482c45080SKumar Kartikeya Dwivedi 
93582c45080SKumar Kartikeya Dwivedi 				snprintf(str, sizeof(str), "cpu:%d", i);
93682c45080SKumar Kartikeya Dwivedi 				print_default("       %-16s" FMT_COLUMNf "\n",
93782c45080SKumar Kartikeya Dwivedi 					      str, ERR(drop));
93882c45080SKumar Kartikeya Dwivedi 			}
93982c45080SKumar Kartikeya Dwivedi 		}
94082c45080SKumar Kartikeya Dwivedi 	}
94182c45080SKumar Kartikeya Dwivedi 
94282c45080SKumar Kartikeya Dwivedi 	if (out) {
94382c45080SKumar Kartikeya Dwivedi 		out->except_cnt.hits = sum;
94482c45080SKumar Kartikeya Dwivedi 		out->totals.err += sum;
94582c45080SKumar Kartikeya Dwivedi 	}
94682c45080SKumar Kartikeya Dwivedi }
947156f886cSKumar Kartikeya Dwivedi 
stats_get_devmap_xmit(struct stats_record * stats_rec,struct stats_record * stats_prev,unsigned int nr_cpus,struct sample_output * out)948af93d58cSKumar Kartikeya Dwivedi static void stats_get_devmap_xmit(struct stats_record *stats_rec,
949af93d58cSKumar Kartikeya Dwivedi 				  struct stats_record *stats_prev,
950af93d58cSKumar Kartikeya Dwivedi 				  unsigned int nr_cpus,
951af93d58cSKumar Kartikeya Dwivedi 				  struct sample_output *out)
952af93d58cSKumar Kartikeya Dwivedi {
953af93d58cSKumar Kartikeya Dwivedi 	double pps, drop, info, err;
954af93d58cSKumar Kartikeya Dwivedi 	struct record *rec, *prev;
955af93d58cSKumar Kartikeya Dwivedi 	double t;
956af93d58cSKumar Kartikeya Dwivedi 	int i;
957af93d58cSKumar Kartikeya Dwivedi 
958af93d58cSKumar Kartikeya Dwivedi 	rec = &stats_rec->devmap_xmit;
959af93d58cSKumar Kartikeya Dwivedi 	prev = &stats_prev->devmap_xmit;
960af93d58cSKumar Kartikeya Dwivedi 	t = calc_period(rec, prev);
961af93d58cSKumar Kartikeya Dwivedi 	for (i = 0; i < nr_cpus; i++) {
962af93d58cSKumar Kartikeya Dwivedi 		struct datarec *r = &rec->cpu[i];
963af93d58cSKumar Kartikeya Dwivedi 		struct datarec *p = &prev->cpu[i];
964af93d58cSKumar Kartikeya Dwivedi 		char str[64];
965af93d58cSKumar Kartikeya Dwivedi 
966af93d58cSKumar Kartikeya Dwivedi 		pps = calc_pps(r, p, t);
967af93d58cSKumar Kartikeya Dwivedi 		drop = calc_drop_pps(r, p, t);
968af93d58cSKumar Kartikeya Dwivedi 		err = calc_errs_pps(r, p, t);
969af93d58cSKumar Kartikeya Dwivedi 
970af93d58cSKumar Kartikeya Dwivedi 		if (!pps && !drop && !err)
971af93d58cSKumar Kartikeya Dwivedi 			continue;
972af93d58cSKumar Kartikeya Dwivedi 
973af93d58cSKumar Kartikeya Dwivedi 		snprintf(str, sizeof(str), "cpu:%d", i);
974af93d58cSKumar Kartikeya Dwivedi 		info = calc_info_pps(r, p, t);
975af93d58cSKumar Kartikeya Dwivedi 		if (info > 0)
976af93d58cSKumar Kartikeya Dwivedi 			info = (pps + drop) / info; /* calc avg bulk */
977af93d58cSKumar Kartikeya Dwivedi 		print_default("     %-18s" FMT_COLUMNf FMT_COLUMNf FMT_COLUMNf
978af93d58cSKumar Kartikeya Dwivedi 				      __COLUMN(".2f") "\n",
979af93d58cSKumar Kartikeya Dwivedi 			      str, XMIT(pps), DROP(drop), err, "drv_err/s",
980af93d58cSKumar Kartikeya Dwivedi 			      info, "bulk-avg");
981af93d58cSKumar Kartikeya Dwivedi 	}
982af93d58cSKumar Kartikeya Dwivedi 	if (out) {
983af93d58cSKumar Kartikeya Dwivedi 		pps = calc_pps(&rec->total, &prev->total, t);
984af93d58cSKumar Kartikeya Dwivedi 		drop = calc_drop_pps(&rec->total, &prev->total, t);
985af93d58cSKumar Kartikeya Dwivedi 		info = calc_info_pps(&rec->total, &prev->total, t);
986af93d58cSKumar Kartikeya Dwivedi 		if (info > 0)
987af93d58cSKumar Kartikeya Dwivedi 			info = (pps + drop) / info; /* calc avg bulk */
988af93d58cSKumar Kartikeya Dwivedi 		err = calc_errs_pps(&rec->total, &prev->total, t);
989af93d58cSKumar Kartikeya Dwivedi 
990af93d58cSKumar Kartikeya Dwivedi 		out->xmit_cnt.pps = pps;
991af93d58cSKumar Kartikeya Dwivedi 		out->xmit_cnt.drop = drop;
992af93d58cSKumar Kartikeya Dwivedi 		out->xmit_cnt.bavg = info;
993af93d58cSKumar Kartikeya Dwivedi 		out->xmit_cnt.err = err;
994af93d58cSKumar Kartikeya Dwivedi 		out->totals.xmit += pps;
995af93d58cSKumar Kartikeya Dwivedi 		out->totals.drop_xmit += drop;
996af93d58cSKumar Kartikeya Dwivedi 		out->totals.err += err;
997af93d58cSKumar Kartikeya Dwivedi 	}
998af93d58cSKumar Kartikeya Dwivedi }
999af93d58cSKumar Kartikeya Dwivedi 
stats_get_devmap_xmit_multi(struct stats_record * stats_rec,struct stats_record * stats_prev,unsigned int nr_cpus,struct sample_output * out,bool xmit_total)1000af93d58cSKumar Kartikeya Dwivedi static void stats_get_devmap_xmit_multi(struct stats_record *stats_rec,
1001af93d58cSKumar Kartikeya Dwivedi 					struct stats_record *stats_prev,
1002af93d58cSKumar Kartikeya Dwivedi 					unsigned int nr_cpus,
1003af93d58cSKumar Kartikeya Dwivedi 					struct sample_output *out,
1004af93d58cSKumar Kartikeya Dwivedi 					bool xmit_total)
1005af93d58cSKumar Kartikeya Dwivedi {
1006af93d58cSKumar Kartikeya Dwivedi 	double pps, drop, info, err;
1007af93d58cSKumar Kartikeya Dwivedi 	struct map_entry *entry;
1008af93d58cSKumar Kartikeya Dwivedi 	struct record *r, *p;
1009af93d58cSKumar Kartikeya Dwivedi 	double t;
1010af93d58cSKumar Kartikeya Dwivedi 	int bkt;
1011af93d58cSKumar Kartikeya Dwivedi 
1012af93d58cSKumar Kartikeya Dwivedi 	hash_for_each(stats_rec->xmit_map, bkt, entry, node) {
1013af93d58cSKumar Kartikeya Dwivedi 		struct map_entry *e, *x = NULL;
1014af93d58cSKumar Kartikeya Dwivedi 		char ifname_from[IFNAMSIZ];
1015af93d58cSKumar Kartikeya Dwivedi 		char ifname_to[IFNAMSIZ];
1016af93d58cSKumar Kartikeya Dwivedi 		const char *fstr, *tstr;
1017af93d58cSKumar Kartikeya Dwivedi 		unsigned long prev_time;
1018af93d58cSKumar Kartikeya Dwivedi 		struct record beg = {};
1019af93d58cSKumar Kartikeya Dwivedi 		__u32 from_idx, to_idx;
1020af93d58cSKumar Kartikeya Dwivedi 		char str[128];
1021af93d58cSKumar Kartikeya Dwivedi 		__u64 pair;
1022af93d58cSKumar Kartikeya Dwivedi 		int i;
1023af93d58cSKumar Kartikeya Dwivedi 
1024af93d58cSKumar Kartikeya Dwivedi 		prev_time = sample_interval * NANOSEC_PER_SEC;
1025af93d58cSKumar Kartikeya Dwivedi 
1026af93d58cSKumar Kartikeya Dwivedi 		pair = entry->pair;
1027af93d58cSKumar Kartikeya Dwivedi 		from_idx = pair >> 32;
1028af93d58cSKumar Kartikeya Dwivedi 		to_idx = pair & 0xFFFFFFFF;
1029af93d58cSKumar Kartikeya Dwivedi 
1030af93d58cSKumar Kartikeya Dwivedi 		r = &entry->val;
1031af93d58cSKumar Kartikeya Dwivedi 		beg.timestamp = r->timestamp - prev_time;
1032af93d58cSKumar Kartikeya Dwivedi 
1033af93d58cSKumar Kartikeya Dwivedi 		/* Find matching entry from stats_prev map */
1034af93d58cSKumar Kartikeya Dwivedi 		hash_for_each_possible(stats_prev->xmit_map, e, node, pair) {
1035af93d58cSKumar Kartikeya Dwivedi 			if (e->pair == pair) {
1036af93d58cSKumar Kartikeya Dwivedi 				x = e;
1037af93d58cSKumar Kartikeya Dwivedi 				break;
1038af93d58cSKumar Kartikeya Dwivedi 			}
1039af93d58cSKumar Kartikeya Dwivedi 		}
1040af93d58cSKumar Kartikeya Dwivedi 		if (x)
1041af93d58cSKumar Kartikeya Dwivedi 			p = &x->val;
1042af93d58cSKumar Kartikeya Dwivedi 		else
1043af93d58cSKumar Kartikeya Dwivedi 			p = &beg;
1044af93d58cSKumar Kartikeya Dwivedi 		t = calc_period(r, p);
1045af93d58cSKumar Kartikeya Dwivedi 		pps = calc_pps(&r->total, &p->total, t);
1046af93d58cSKumar Kartikeya Dwivedi 		drop = calc_drop_pps(&r->total, &p->total, t);
1047af93d58cSKumar Kartikeya Dwivedi 		info = calc_info_pps(&r->total, &p->total, t);
1048af93d58cSKumar Kartikeya Dwivedi 		if (info > 0)
1049af93d58cSKumar Kartikeya Dwivedi 			info = (pps + drop) / info; /* calc avg bulk */
1050af93d58cSKumar Kartikeya Dwivedi 		err = calc_errs_pps(&r->total, &p->total, t);
1051af93d58cSKumar Kartikeya Dwivedi 
1052af93d58cSKumar Kartikeya Dwivedi 		if (out) {
1053af93d58cSKumar Kartikeya Dwivedi 			/* We are responsible for filling out totals */
1054af93d58cSKumar Kartikeya Dwivedi 			out->totals.xmit += pps;
1055af93d58cSKumar Kartikeya Dwivedi 			out->totals.drop_xmit += drop;
1056af93d58cSKumar Kartikeya Dwivedi 			out->totals.err += err;
1057af93d58cSKumar Kartikeya Dwivedi 			continue;
1058af93d58cSKumar Kartikeya Dwivedi 		}
1059af93d58cSKumar Kartikeya Dwivedi 
1060af93d58cSKumar Kartikeya Dwivedi 		fstr = tstr = NULL;
1061af93d58cSKumar Kartikeya Dwivedi 		if (if_indextoname(from_idx, ifname_from))
1062af93d58cSKumar Kartikeya Dwivedi 			fstr = ifname_from;
1063af93d58cSKumar Kartikeya Dwivedi 		if (if_indextoname(to_idx, ifname_to))
1064af93d58cSKumar Kartikeya Dwivedi 			tstr = ifname_to;
1065af93d58cSKumar Kartikeya Dwivedi 
1066af93d58cSKumar Kartikeya Dwivedi 		snprintf(str, sizeof(str), "xmit %s->%s", fstr ?: "?",
1067af93d58cSKumar Kartikeya Dwivedi 			 tstr ?: "?");
1068af93d58cSKumar Kartikeya Dwivedi 		/* Skip idle streams of redirection */
1069af93d58cSKumar Kartikeya Dwivedi 		if (pps || drop || err) {
1070af93d58cSKumar Kartikeya Dwivedi 			print_err(drop,
1071af93d58cSKumar Kartikeya Dwivedi 				  "  %-20s " FMT_COLUMNf FMT_COLUMNf FMT_COLUMNf
1072af93d58cSKumar Kartikeya Dwivedi 				  __COLUMN(".2f") "\n", str, XMIT(pps), DROP(drop),
1073af93d58cSKumar Kartikeya Dwivedi 				  err, "drv_err/s", info, "bulk-avg");
1074af93d58cSKumar Kartikeya Dwivedi 		}
1075af93d58cSKumar Kartikeya Dwivedi 
1076af93d58cSKumar Kartikeya Dwivedi 		for (i = 0; i < nr_cpus; i++) {
1077af93d58cSKumar Kartikeya Dwivedi 			struct datarec *rc = &r->cpu[i];
1078af93d58cSKumar Kartikeya Dwivedi 			struct datarec *pc, p_beg = {};
1079af93d58cSKumar Kartikeya Dwivedi 			char str[64];
1080af93d58cSKumar Kartikeya Dwivedi 
1081af93d58cSKumar Kartikeya Dwivedi 			pc = p == &beg ? &p_beg : &p->cpu[i];
1082af93d58cSKumar Kartikeya Dwivedi 
1083af93d58cSKumar Kartikeya Dwivedi 			pps = calc_pps(rc, pc, t);
1084af93d58cSKumar Kartikeya Dwivedi 			drop = calc_drop_pps(rc, pc, t);
1085af93d58cSKumar Kartikeya Dwivedi 			err = calc_errs_pps(rc, pc, t);
1086af93d58cSKumar Kartikeya Dwivedi 
1087af93d58cSKumar Kartikeya Dwivedi 			if (!pps && !drop && !err)
1088af93d58cSKumar Kartikeya Dwivedi 				continue;
1089af93d58cSKumar Kartikeya Dwivedi 
1090af93d58cSKumar Kartikeya Dwivedi 			snprintf(str, sizeof(str), "cpu:%d", i);
1091af93d58cSKumar Kartikeya Dwivedi 			info = calc_info_pps(rc, pc, t);
1092af93d58cSKumar Kartikeya Dwivedi 			if (info > 0)
1093af93d58cSKumar Kartikeya Dwivedi 				info = (pps + drop) / info; /* calc avg bulk */
1094af93d58cSKumar Kartikeya Dwivedi 
1095af93d58cSKumar Kartikeya Dwivedi 			print_default("     %-18s" FMT_COLUMNf FMT_COLUMNf FMT_COLUMNf
1096af93d58cSKumar Kartikeya Dwivedi 				      __COLUMN(".2f") "\n", str, XMIT(pps),
1097af93d58cSKumar Kartikeya Dwivedi 				      DROP(drop), err, "drv_err/s", info, "bulk-avg");
1098af93d58cSKumar Kartikeya Dwivedi 		}
1099af93d58cSKumar Kartikeya Dwivedi 	}
1100af93d58cSKumar Kartikeya Dwivedi }
1101af93d58cSKumar Kartikeya Dwivedi 
stats_print(const char * prefix,int mask,struct stats_record * r,struct stats_record * p,struct sample_output * out)1102156f886cSKumar Kartikeya Dwivedi static void stats_print(const char *prefix, int mask, struct stats_record *r,
1103156f886cSKumar Kartikeya Dwivedi 			struct stats_record *p, struct sample_output *out)
1104156f886cSKumar Kartikeya Dwivedi {
1105156f886cSKumar Kartikeya Dwivedi 	int nr_cpus = libbpf_num_possible_cpus();
1106156f886cSKumar Kartikeya Dwivedi 	const char *str;
1107156f886cSKumar Kartikeya Dwivedi 
1108156f886cSKumar Kartikeya Dwivedi 	print_always("%-23s", prefix ?: "Summary");
1109156f886cSKumar Kartikeya Dwivedi 	if (mask & SAMPLE_RX_CNT)
1110156f886cSKumar Kartikeya Dwivedi 		print_always(FMT_COLUMNl, RX(out->totals.rx));
11111d930fd2SKumar Kartikeya Dwivedi 	if (mask & SAMPLE_REDIRECT_CNT)
11121d930fd2SKumar Kartikeya Dwivedi 		print_always(FMT_COLUMNl, REDIR(out->totals.redir));
1113d771e217SKumar Kartikeya Dwivedi 	printf(FMT_COLUMNl,
1114d771e217SKumar Kartikeya Dwivedi 	       out->totals.err + out->totals.drop + out->totals.drop_xmit,
1115d771e217SKumar Kartikeya Dwivedi 	       "err,drop/s");
1116af93d58cSKumar Kartikeya Dwivedi 	if (mask & SAMPLE_DEVMAP_XMIT_CNT ||
1117af93d58cSKumar Kartikeya Dwivedi 	    mask & SAMPLE_DEVMAP_XMIT_CNT_MULTI)
1118af93d58cSKumar Kartikeya Dwivedi 		printf(FMT_COLUMNl, XMIT(out->totals.xmit));
1119156f886cSKumar Kartikeya Dwivedi 	printf("\n");
1120156f886cSKumar Kartikeya Dwivedi 
1121156f886cSKumar Kartikeya Dwivedi 	if (mask & SAMPLE_RX_CNT) {
1122156f886cSKumar Kartikeya Dwivedi 		str = (sample_log_level & LL_DEFAULT) && out->rx_cnt.pps ?
1123156f886cSKumar Kartikeya Dwivedi 				    "receive total" :
1124156f886cSKumar Kartikeya Dwivedi 				    "receive";
1125156f886cSKumar Kartikeya Dwivedi 		print_err((out->rx_cnt.err || out->rx_cnt.drop),
1126156f886cSKumar Kartikeya Dwivedi 			  "  %-20s " FMT_COLUMNl FMT_COLUMNl FMT_COLUMNl "\n",
1127156f886cSKumar Kartikeya Dwivedi 			  str, PPS(out->rx_cnt.pps), DROP(out->rx_cnt.drop),
1128156f886cSKumar Kartikeya Dwivedi 			  ERR(out->rx_cnt.err));
1129156f886cSKumar Kartikeya Dwivedi 
1130156f886cSKumar Kartikeya Dwivedi 		stats_get_rx_cnt(r, p, nr_cpus, NULL);
1131156f886cSKumar Kartikeya Dwivedi 	}
1132156f886cSKumar Kartikeya Dwivedi 
1133d771e217SKumar Kartikeya Dwivedi 	if (mask & SAMPLE_CPUMAP_ENQUEUE_CNT)
1134d771e217SKumar Kartikeya Dwivedi 		stats_get_cpumap_enqueue(r, p, nr_cpus);
1135d771e217SKumar Kartikeya Dwivedi 
1136d771e217SKumar Kartikeya Dwivedi 	if (mask & SAMPLE_CPUMAP_KTHREAD_CNT) {
1137d771e217SKumar Kartikeya Dwivedi 		stats_get_cpumap_kthread(r, p, nr_cpus);
1138d771e217SKumar Kartikeya Dwivedi 		stats_get_cpumap_remote(r, p, nr_cpus);
1139d771e217SKumar Kartikeya Dwivedi 	}
1140d771e217SKumar Kartikeya Dwivedi 
11411d930fd2SKumar Kartikeya Dwivedi 	if (mask & SAMPLE_REDIRECT_CNT) {
11421d930fd2SKumar Kartikeya Dwivedi 		str = out->redir_cnt.suc ? "redirect total" : "redirect";
11431d930fd2SKumar Kartikeya Dwivedi 		print_default("  %-20s " FMT_COLUMNl "\n", str,
11441d930fd2SKumar Kartikeya Dwivedi 			      REDIR(out->redir_cnt.suc));
11451d930fd2SKumar Kartikeya Dwivedi 
11461d930fd2SKumar Kartikeya Dwivedi 		stats_get_redirect_cnt(r, p, nr_cpus, NULL);
11471d930fd2SKumar Kartikeya Dwivedi 	}
11481d930fd2SKumar Kartikeya Dwivedi 
11491d930fd2SKumar Kartikeya Dwivedi 	if (mask & SAMPLE_REDIRECT_ERR_CNT) {
11501d930fd2SKumar Kartikeya Dwivedi 		str = (sample_log_level & LL_DEFAULT) && out->redir_cnt.err ?
11511d930fd2SKumar Kartikeya Dwivedi 				    "redirect_err total" :
11521d930fd2SKumar Kartikeya Dwivedi 				    "redirect_err";
11531d930fd2SKumar Kartikeya Dwivedi 		print_err(out->redir_cnt.err, "  %-20s " FMT_COLUMNl "\n", str,
11541d930fd2SKumar Kartikeya Dwivedi 			  ERR(out->redir_cnt.err));
11551d930fd2SKumar Kartikeya Dwivedi 
11561d930fd2SKumar Kartikeya Dwivedi 		stats_get_redirect_err_cnt(r, p, nr_cpus, NULL);
11571d930fd2SKumar Kartikeya Dwivedi 	}
11581d930fd2SKumar Kartikeya Dwivedi 
115982c45080SKumar Kartikeya Dwivedi 	if (mask & SAMPLE_EXCEPTION_CNT) {
116082c45080SKumar Kartikeya Dwivedi 		str = out->except_cnt.hits ? "xdp_exception total" :
116182c45080SKumar Kartikeya Dwivedi 						   "xdp_exception";
116282c45080SKumar Kartikeya Dwivedi 
116382c45080SKumar Kartikeya Dwivedi 		print_err(out->except_cnt.hits, "  %-20s " FMT_COLUMNl "\n", str,
116482c45080SKumar Kartikeya Dwivedi 			  HITS(out->except_cnt.hits));
116582c45080SKumar Kartikeya Dwivedi 
116682c45080SKumar Kartikeya Dwivedi 		stats_get_exception_cnt(r, p, nr_cpus, NULL);
116782c45080SKumar Kartikeya Dwivedi 	}
116882c45080SKumar Kartikeya Dwivedi 
1169af93d58cSKumar Kartikeya Dwivedi 	if (mask & SAMPLE_DEVMAP_XMIT_CNT) {
1170af93d58cSKumar Kartikeya Dwivedi 		str = (sample_log_level & LL_DEFAULT) && out->xmit_cnt.pps ?
1171af93d58cSKumar Kartikeya Dwivedi 				    "devmap_xmit total" :
1172af93d58cSKumar Kartikeya Dwivedi 				    "devmap_xmit";
1173af93d58cSKumar Kartikeya Dwivedi 
1174af93d58cSKumar Kartikeya Dwivedi 		print_err(out->xmit_cnt.err || out->xmit_cnt.drop,
1175af93d58cSKumar Kartikeya Dwivedi 			  "  %-20s " FMT_COLUMNl FMT_COLUMNl FMT_COLUMNl
1176af93d58cSKumar Kartikeya Dwivedi 				  __COLUMN(".2f") "\n",
1177af93d58cSKumar Kartikeya Dwivedi 			  str, XMIT(out->xmit_cnt.pps),
1178af93d58cSKumar Kartikeya Dwivedi 			  DROP(out->xmit_cnt.drop), out->xmit_cnt.err,
1179af93d58cSKumar Kartikeya Dwivedi 			  "drv_err/s", out->xmit_cnt.bavg, "bulk-avg");
1180af93d58cSKumar Kartikeya Dwivedi 
1181af93d58cSKumar Kartikeya Dwivedi 		stats_get_devmap_xmit(r, p, nr_cpus, NULL);
1182af93d58cSKumar Kartikeya Dwivedi 	}
1183af93d58cSKumar Kartikeya Dwivedi 
1184af93d58cSKumar Kartikeya Dwivedi 	if (mask & SAMPLE_DEVMAP_XMIT_CNT_MULTI)
1185af93d58cSKumar Kartikeya Dwivedi 		stats_get_devmap_xmit_multi(r, p, nr_cpus, NULL,
1186af93d58cSKumar Kartikeya Dwivedi 					    mask & SAMPLE_DEVMAP_XMIT_CNT);
1187af93d58cSKumar Kartikeya Dwivedi 
1188156f886cSKumar Kartikeya Dwivedi 	if (sample_log_level & LL_DEFAULT ||
1189156f886cSKumar Kartikeya Dwivedi 	    ((sample_log_level & LL_SIMPLE) && sample_err_exp)) {
1190156f886cSKumar Kartikeya Dwivedi 		sample_err_exp = false;
1191156f886cSKumar Kartikeya Dwivedi 		printf("\n");
1192156f886cSKumar Kartikeya Dwivedi 	}
1193156f886cSKumar Kartikeya Dwivedi }
1194156f886cSKumar Kartikeya Dwivedi 
sample_setup_maps(struct bpf_map ** maps)1195156f886cSKumar Kartikeya Dwivedi int sample_setup_maps(struct bpf_map **maps)
1196156f886cSKumar Kartikeya Dwivedi {
1197156f886cSKumar Kartikeya Dwivedi 	sample_n_cpus = libbpf_num_possible_cpus();
1198156f886cSKumar Kartikeya Dwivedi 
1199af93d58cSKumar Kartikeya Dwivedi 	for (int i = 0; i < MAP_DEVMAP_XMIT_MULTI; i++) {
1200156f886cSKumar Kartikeya Dwivedi 		sample_map[i] = maps[i];
1201156f886cSKumar Kartikeya Dwivedi 
1202156f886cSKumar Kartikeya Dwivedi 		switch (i) {
1203156f886cSKumar Kartikeya Dwivedi 		case MAP_RX:
1204d771e217SKumar Kartikeya Dwivedi 		case MAP_CPUMAP_KTHREAD:
1205af93d58cSKumar Kartikeya Dwivedi 		case MAP_DEVMAP_XMIT:
1206156f886cSKumar Kartikeya Dwivedi 			sample_map_count[i] = sample_n_cpus;
1207156f886cSKumar Kartikeya Dwivedi 			break;
12081d930fd2SKumar Kartikeya Dwivedi 		case MAP_REDIRECT_ERR:
12091d930fd2SKumar Kartikeya Dwivedi 			sample_map_count[i] =
12101d930fd2SKumar Kartikeya Dwivedi 				XDP_REDIRECT_ERR_MAX * sample_n_cpus;
12111d930fd2SKumar Kartikeya Dwivedi 			break;
121282c45080SKumar Kartikeya Dwivedi 		case MAP_EXCEPTION:
121382c45080SKumar Kartikeya Dwivedi 			sample_map_count[i] = XDP_ACTION_MAX * sample_n_cpus;
1214d771e217SKumar Kartikeya Dwivedi 		case MAP_CPUMAP_ENQUEUE:
1215d771e217SKumar Kartikeya Dwivedi 			sample_map_count[i] = sample_n_cpus * sample_n_cpus;
121682c45080SKumar Kartikeya Dwivedi 			break;
1217156f886cSKumar Kartikeya Dwivedi 		default:
1218156f886cSKumar Kartikeya Dwivedi 			return -EINVAL;
1219156f886cSKumar Kartikeya Dwivedi 		}
1220*61afd3daSAndrii Nakryiko 		if (bpf_map__set_max_entries(sample_map[i], sample_map_count[i]) < 0)
1221156f886cSKumar Kartikeya Dwivedi 			return -errno;
1222156f886cSKumar Kartikeya Dwivedi 	}
1223af93d58cSKumar Kartikeya Dwivedi 	sample_map[MAP_DEVMAP_XMIT_MULTI] = maps[MAP_DEVMAP_XMIT_MULTI];
1224156f886cSKumar Kartikeya Dwivedi 	return 0;
1225156f886cSKumar Kartikeya Dwivedi }
1226156f886cSKumar Kartikeya Dwivedi 
sample_setup_maps_mappings(void)1227156f886cSKumar Kartikeya Dwivedi static int sample_setup_maps_mappings(void)
1228156f886cSKumar Kartikeya Dwivedi {
1229af93d58cSKumar Kartikeya Dwivedi 	for (int i = 0; i < MAP_DEVMAP_XMIT_MULTI; i++) {
1230156f886cSKumar Kartikeya Dwivedi 		size_t size = sample_map_count[i] * sizeof(struct datarec);
1231156f886cSKumar Kartikeya Dwivedi 
1232156f886cSKumar Kartikeya Dwivedi 		sample_mmap[i] = mmap(NULL, size, PROT_READ | PROT_WRITE,
1233156f886cSKumar Kartikeya Dwivedi 				      MAP_SHARED, bpf_map__fd(sample_map[i]), 0);
1234156f886cSKumar Kartikeya Dwivedi 		if (sample_mmap[i] == MAP_FAILED)
1235156f886cSKumar Kartikeya Dwivedi 			return -errno;
1236156f886cSKumar Kartikeya Dwivedi 	}
1237156f886cSKumar Kartikeya Dwivedi 	return 0;
1238156f886cSKumar Kartikeya Dwivedi }
1239156f886cSKumar Kartikeya Dwivedi 
__sample_init(int mask)1240156f886cSKumar Kartikeya Dwivedi int __sample_init(int mask)
1241156f886cSKumar Kartikeya Dwivedi {
1242156f886cSKumar Kartikeya Dwivedi 	sigset_t st;
1243156f886cSKumar Kartikeya Dwivedi 
1244156f886cSKumar Kartikeya Dwivedi 	sigemptyset(&st);
1245156f886cSKumar Kartikeya Dwivedi 	sigaddset(&st, SIGQUIT);
1246156f886cSKumar Kartikeya Dwivedi 	sigaddset(&st, SIGINT);
1247156f886cSKumar Kartikeya Dwivedi 	sigaddset(&st, SIGTERM);
1248156f886cSKumar Kartikeya Dwivedi 
1249156f886cSKumar Kartikeya Dwivedi 	if (sigprocmask(SIG_BLOCK, &st, NULL) < 0)
1250156f886cSKumar Kartikeya Dwivedi 		return -errno;
1251156f886cSKumar Kartikeya Dwivedi 
1252156f886cSKumar Kartikeya Dwivedi 	sample_sig_fd = signalfd(-1, &st, SFD_CLOEXEC | SFD_NONBLOCK);
1253156f886cSKumar Kartikeya Dwivedi 	if (sample_sig_fd < 0)
1254156f886cSKumar Kartikeya Dwivedi 		return -errno;
1255156f886cSKumar Kartikeya Dwivedi 
1256156f886cSKumar Kartikeya Dwivedi 	sample_mask = mask;
1257156f886cSKumar Kartikeya Dwivedi 
1258156f886cSKumar Kartikeya Dwivedi 	return sample_setup_maps_mappings();
1259156f886cSKumar Kartikeya Dwivedi }
1260156f886cSKumar Kartikeya Dwivedi 
__sample_remove_xdp(int ifindex,__u32 prog_id,int xdp_flags)1261156f886cSKumar Kartikeya Dwivedi static int __sample_remove_xdp(int ifindex, __u32 prog_id, int xdp_flags)
1262156f886cSKumar Kartikeya Dwivedi {
1263156f886cSKumar Kartikeya Dwivedi 	__u32 cur_prog_id = 0;
1264156f886cSKumar Kartikeya Dwivedi 	int ret;
1265156f886cSKumar Kartikeya Dwivedi 
1266156f886cSKumar Kartikeya Dwivedi 	if (prog_id) {
1267d4e34bfcSAndrii Nakryiko 		ret = bpf_xdp_query_id(ifindex, xdp_flags, &cur_prog_id);
1268156f886cSKumar Kartikeya Dwivedi 		if (ret < 0)
1269156f886cSKumar Kartikeya Dwivedi 			return -errno;
1270156f886cSKumar Kartikeya Dwivedi 
1271156f886cSKumar Kartikeya Dwivedi 		if (prog_id != cur_prog_id) {
1272156f886cSKumar Kartikeya Dwivedi 			print_always(
1273156f886cSKumar Kartikeya Dwivedi 				"Program on ifindex %d does not match installed "
1274156f886cSKumar Kartikeya Dwivedi 				"program, skipping unload\n",
1275156f886cSKumar Kartikeya Dwivedi 				ifindex);
1276156f886cSKumar Kartikeya Dwivedi 			return -ENOENT;
1277156f886cSKumar Kartikeya Dwivedi 		}
1278156f886cSKumar Kartikeya Dwivedi 	}
1279156f886cSKumar Kartikeya Dwivedi 
1280d4e34bfcSAndrii Nakryiko 	return bpf_xdp_detach(ifindex, xdp_flags, NULL);
1281156f886cSKumar Kartikeya Dwivedi }
1282156f886cSKumar Kartikeya Dwivedi 
sample_install_xdp(struct bpf_program * xdp_prog,int ifindex,bool generic,bool force)1283156f886cSKumar Kartikeya Dwivedi int sample_install_xdp(struct bpf_program *xdp_prog, int ifindex, bool generic,
1284156f886cSKumar Kartikeya Dwivedi 		       bool force)
1285156f886cSKumar Kartikeya Dwivedi {
1286156f886cSKumar Kartikeya Dwivedi 	int ret, xdp_flags = 0;
1287156f886cSKumar Kartikeya Dwivedi 	__u32 prog_id = 0;
1288156f886cSKumar Kartikeya Dwivedi 
1289156f886cSKumar Kartikeya Dwivedi 	if (sample_xdp_cnt == 32) {
1290156f886cSKumar Kartikeya Dwivedi 		fprintf(stderr,
1291156f886cSKumar Kartikeya Dwivedi 			"Total limit for installed XDP programs in a sample reached\n");
1292156f886cSKumar Kartikeya Dwivedi 		return -ENOTSUP;
1293156f886cSKumar Kartikeya Dwivedi 	}
1294156f886cSKumar Kartikeya Dwivedi 
1295156f886cSKumar Kartikeya Dwivedi 	xdp_flags |= !force ? XDP_FLAGS_UPDATE_IF_NOEXIST : 0;
1296156f886cSKumar Kartikeya Dwivedi 	xdp_flags |= generic ? XDP_FLAGS_SKB_MODE : XDP_FLAGS_DRV_MODE;
1297d4e34bfcSAndrii Nakryiko 	ret = bpf_xdp_attach(ifindex, bpf_program__fd(xdp_prog), xdp_flags, NULL);
1298156f886cSKumar Kartikeya Dwivedi 	if (ret < 0) {
1299156f886cSKumar Kartikeya Dwivedi 		ret = -errno;
1300156f886cSKumar Kartikeya Dwivedi 		fprintf(stderr,
1301156f886cSKumar Kartikeya Dwivedi 			"Failed to install program \"%s\" on ifindex %d, mode = %s, "
1302156f886cSKumar Kartikeya Dwivedi 			"force = %s: %s\n",
1303156f886cSKumar Kartikeya Dwivedi 			bpf_program__name(xdp_prog), ifindex,
1304156f886cSKumar Kartikeya Dwivedi 			generic ? "skb" : "native", force ? "true" : "false",
1305156f886cSKumar Kartikeya Dwivedi 			strerror(-ret));
1306156f886cSKumar Kartikeya Dwivedi 		return ret;
1307156f886cSKumar Kartikeya Dwivedi 	}
1308156f886cSKumar Kartikeya Dwivedi 
1309d4e34bfcSAndrii Nakryiko 	ret = bpf_xdp_query_id(ifindex, xdp_flags, &prog_id);
1310156f886cSKumar Kartikeya Dwivedi 	if (ret < 0) {
1311156f886cSKumar Kartikeya Dwivedi 		ret = -errno;
1312156f886cSKumar Kartikeya Dwivedi 		fprintf(stderr,
1313156f886cSKumar Kartikeya Dwivedi 			"Failed to get XDP program id for ifindex %d, removing program: %s\n",
1314156f886cSKumar Kartikeya Dwivedi 			ifindex, strerror(errno));
1315156f886cSKumar Kartikeya Dwivedi 		__sample_remove_xdp(ifindex, 0, xdp_flags);
1316156f886cSKumar Kartikeya Dwivedi 		return ret;
1317156f886cSKumar Kartikeya Dwivedi 	}
1318156f886cSKumar Kartikeya Dwivedi 	sample_xdp_progs[sample_xdp_cnt++] =
1319156f886cSKumar Kartikeya Dwivedi 		(struct xdp_desc){ ifindex, prog_id, xdp_flags };
1320156f886cSKumar Kartikeya Dwivedi 
1321156f886cSKumar Kartikeya Dwivedi 	return 0;
1322156f886cSKumar Kartikeya Dwivedi }
1323156f886cSKumar Kartikeya Dwivedi 
sample_summary_print(void)1324156f886cSKumar Kartikeya Dwivedi static void sample_summary_print(void)
1325156f886cSKumar Kartikeya Dwivedi {
1326dc14ca46SAlexander Lobakin 	double num = sample_out.rx_cnt.num;
1327156f886cSKumar Kartikeya Dwivedi 
1328156f886cSKumar Kartikeya Dwivedi 	if (sample_out.totals.rx) {
1329156f886cSKumar Kartikeya Dwivedi 		double pkts = sample_out.totals.rx;
1330156f886cSKumar Kartikeya Dwivedi 
1331156f886cSKumar Kartikeya Dwivedi 		print_always("  Packets received    : %'-10llu\n",
1332156f886cSKumar Kartikeya Dwivedi 			     sample_out.totals.rx);
1333156f886cSKumar Kartikeya Dwivedi 		print_always("  Average packets/s   : %'-10.0f\n",
1334dc14ca46SAlexander Lobakin 			     sample_round(pkts / num));
1335156f886cSKumar Kartikeya Dwivedi 	}
13361d930fd2SKumar Kartikeya Dwivedi 	if (sample_out.totals.redir) {
13371d930fd2SKumar Kartikeya Dwivedi 		double pkts = sample_out.totals.redir;
13381d930fd2SKumar Kartikeya Dwivedi 
13391d930fd2SKumar Kartikeya Dwivedi 		print_always("  Packets redirected  : %'-10llu\n",
13401d930fd2SKumar Kartikeya Dwivedi 			     sample_out.totals.redir);
13411d930fd2SKumar Kartikeya Dwivedi 		print_always("  Average redir/s     : %'-10.0f\n",
1342dc14ca46SAlexander Lobakin 			     sample_round(pkts / num));
13431d930fd2SKumar Kartikeya Dwivedi 	}
1344d771e217SKumar Kartikeya Dwivedi 	if (sample_out.totals.drop)
1345d771e217SKumar Kartikeya Dwivedi 		print_always("  Rx dropped          : %'-10llu\n",
1346d771e217SKumar Kartikeya Dwivedi 			     sample_out.totals.drop);
1347af93d58cSKumar Kartikeya Dwivedi 	if (sample_out.totals.drop_xmit)
1348af93d58cSKumar Kartikeya Dwivedi 		print_always("  Tx dropped          : %'-10llu\n",
1349af93d58cSKumar Kartikeya Dwivedi 			     sample_out.totals.drop_xmit);
13501d930fd2SKumar Kartikeya Dwivedi 	if (sample_out.totals.err)
13511d930fd2SKumar Kartikeya Dwivedi 		print_always("  Errors recorded     : %'-10llu\n",
13521d930fd2SKumar Kartikeya Dwivedi 			     sample_out.totals.err);
1353af93d58cSKumar Kartikeya Dwivedi 	if (sample_out.totals.xmit) {
1354af93d58cSKumar Kartikeya Dwivedi 		double pkts = sample_out.totals.xmit;
1355af93d58cSKumar Kartikeya Dwivedi 
1356af93d58cSKumar Kartikeya Dwivedi 		print_always("  Packets transmitted : %'-10llu\n",
1357af93d58cSKumar Kartikeya Dwivedi 			     sample_out.totals.xmit);
1358af93d58cSKumar Kartikeya Dwivedi 		print_always("  Average transmit/s  : %'-10.0f\n",
1359dc14ca46SAlexander Lobakin 			     sample_round(pkts / num));
1360af93d58cSKumar Kartikeya Dwivedi 	}
1361156f886cSKumar Kartikeya Dwivedi }
1362156f886cSKumar Kartikeya Dwivedi 
sample_exit(int status)1363156f886cSKumar Kartikeya Dwivedi void sample_exit(int status)
1364156f886cSKumar Kartikeya Dwivedi {
1365156f886cSKumar Kartikeya Dwivedi 	size_t size;
1366156f886cSKumar Kartikeya Dwivedi 
1367156f886cSKumar Kartikeya Dwivedi 	for (int i = 0; i < NUM_MAP; i++) {
1368156f886cSKumar Kartikeya Dwivedi 		size = sample_map_count[i] * sizeof(**sample_mmap);
1369156f886cSKumar Kartikeya Dwivedi 		munmap(sample_mmap[i], size);
1370156f886cSKumar Kartikeya Dwivedi 	}
1371156f886cSKumar Kartikeya Dwivedi 	while (sample_xdp_cnt--) {
1372156f886cSKumar Kartikeya Dwivedi 		int i = sample_xdp_cnt, ifindex, xdp_flags;
1373156f886cSKumar Kartikeya Dwivedi 		__u32 prog_id;
1374156f886cSKumar Kartikeya Dwivedi 
1375156f886cSKumar Kartikeya Dwivedi 		prog_id = sample_xdp_progs[i].prog_id;
1376156f886cSKumar Kartikeya Dwivedi 		ifindex = sample_xdp_progs[i].ifindex;
1377156f886cSKumar Kartikeya Dwivedi 		xdp_flags = sample_xdp_progs[i].flags;
1378156f886cSKumar Kartikeya Dwivedi 
1379156f886cSKumar Kartikeya Dwivedi 		__sample_remove_xdp(ifindex, prog_id, xdp_flags);
1380156f886cSKumar Kartikeya Dwivedi 	}
1381156f886cSKumar Kartikeya Dwivedi 	sample_summary_print();
1382156f886cSKumar Kartikeya Dwivedi 	close(sample_sig_fd);
1383156f886cSKumar Kartikeya Dwivedi 	exit(status);
1384156f886cSKumar Kartikeya Dwivedi }
1385156f886cSKumar Kartikeya Dwivedi 
sample_stats_collect(struct stats_record * rec)1386156f886cSKumar Kartikeya Dwivedi static int sample_stats_collect(struct stats_record *rec)
1387156f886cSKumar Kartikeya Dwivedi {
1388156f886cSKumar Kartikeya Dwivedi 	int i;
1389156f886cSKumar Kartikeya Dwivedi 
1390156f886cSKumar Kartikeya Dwivedi 	if (sample_mask & SAMPLE_RX_CNT)
1391156f886cSKumar Kartikeya Dwivedi 		map_collect_percpu(sample_mmap[MAP_RX], &rec->rx_cnt);
1392156f886cSKumar Kartikeya Dwivedi 
13931d930fd2SKumar Kartikeya Dwivedi 	if (sample_mask & SAMPLE_REDIRECT_CNT)
13941d930fd2SKumar Kartikeya Dwivedi 		map_collect_percpu(sample_mmap[MAP_REDIRECT_ERR], &rec->redir_err[0]);
13951d930fd2SKumar Kartikeya Dwivedi 
13961d930fd2SKumar Kartikeya Dwivedi 	if (sample_mask & SAMPLE_REDIRECT_ERR_CNT) {
13971d930fd2SKumar Kartikeya Dwivedi 		for (i = 1; i < XDP_REDIRECT_ERR_MAX; i++)
13981d930fd2SKumar Kartikeya Dwivedi 			map_collect_percpu(&sample_mmap[MAP_REDIRECT_ERR][i * sample_n_cpus],
13991d930fd2SKumar Kartikeya Dwivedi 					   &rec->redir_err[i]);
14001d930fd2SKumar Kartikeya Dwivedi 	}
14011d930fd2SKumar Kartikeya Dwivedi 
1402d771e217SKumar Kartikeya Dwivedi 	if (sample_mask & SAMPLE_CPUMAP_ENQUEUE_CNT)
1403d771e217SKumar Kartikeya Dwivedi 		for (i = 0; i < sample_n_cpus; i++)
1404d771e217SKumar Kartikeya Dwivedi 			map_collect_percpu(&sample_mmap[MAP_CPUMAP_ENQUEUE][i * sample_n_cpus],
1405d771e217SKumar Kartikeya Dwivedi 					   &rec->enq[i]);
1406d771e217SKumar Kartikeya Dwivedi 
1407d771e217SKumar Kartikeya Dwivedi 	if (sample_mask & SAMPLE_CPUMAP_KTHREAD_CNT)
1408d771e217SKumar Kartikeya Dwivedi 		map_collect_percpu(sample_mmap[MAP_CPUMAP_KTHREAD],
1409d771e217SKumar Kartikeya Dwivedi 				   &rec->kthread);
1410d771e217SKumar Kartikeya Dwivedi 
141182c45080SKumar Kartikeya Dwivedi 	if (sample_mask & SAMPLE_EXCEPTION_CNT)
141282c45080SKumar Kartikeya Dwivedi 		for (i = 0; i < XDP_ACTION_MAX; i++)
141382c45080SKumar Kartikeya Dwivedi 			map_collect_percpu(&sample_mmap[MAP_EXCEPTION][i * sample_n_cpus],
141482c45080SKumar Kartikeya Dwivedi 					   &rec->exception[i]);
141582c45080SKumar Kartikeya Dwivedi 
1416af93d58cSKumar Kartikeya Dwivedi 	if (sample_mask & SAMPLE_DEVMAP_XMIT_CNT)
1417af93d58cSKumar Kartikeya Dwivedi 		map_collect_percpu(sample_mmap[MAP_DEVMAP_XMIT], &rec->devmap_xmit);
1418af93d58cSKumar Kartikeya Dwivedi 
1419af93d58cSKumar Kartikeya Dwivedi 	if (sample_mask & SAMPLE_DEVMAP_XMIT_CNT_MULTI) {
1420af93d58cSKumar Kartikeya Dwivedi 		if (map_collect_percpu_devmap(bpf_map__fd(sample_map[MAP_DEVMAP_XMIT_MULTI]), rec) < 0)
1421af93d58cSKumar Kartikeya Dwivedi 			return -EINVAL;
1422af93d58cSKumar Kartikeya Dwivedi 	}
1423156f886cSKumar Kartikeya Dwivedi 	return 0;
1424156f886cSKumar Kartikeya Dwivedi }
1425156f886cSKumar Kartikeya Dwivedi 
sample_summary_update(struct sample_output * out)1426dc14ca46SAlexander Lobakin static void sample_summary_update(struct sample_output *out)
1427156f886cSKumar Kartikeya Dwivedi {
1428156f886cSKumar Kartikeya Dwivedi 	sample_out.totals.rx += out->totals.rx;
14291d930fd2SKumar Kartikeya Dwivedi 	sample_out.totals.redir += out->totals.redir;
1430d771e217SKumar Kartikeya Dwivedi 	sample_out.totals.drop += out->totals.drop;
1431af93d58cSKumar Kartikeya Dwivedi 	sample_out.totals.drop_xmit += out->totals.drop_xmit;
14321d930fd2SKumar Kartikeya Dwivedi 	sample_out.totals.err += out->totals.err;
1433af93d58cSKumar Kartikeya Dwivedi 	sample_out.totals.xmit += out->totals.xmit;
1434dc14ca46SAlexander Lobakin 	sample_out.rx_cnt.num++;
1435156f886cSKumar Kartikeya Dwivedi }
1436156f886cSKumar Kartikeya Dwivedi 
sample_stats_print(int mask,struct stats_record * cur,struct stats_record * prev,char * prog_name)1437156f886cSKumar Kartikeya Dwivedi static void sample_stats_print(int mask, struct stats_record *cur,
1438dc14ca46SAlexander Lobakin 			       struct stats_record *prev, char *prog_name)
1439156f886cSKumar Kartikeya Dwivedi {
1440156f886cSKumar Kartikeya Dwivedi 	struct sample_output out = {};
1441156f886cSKumar Kartikeya Dwivedi 
1442156f886cSKumar Kartikeya Dwivedi 	if (mask & SAMPLE_RX_CNT)
1443156f886cSKumar Kartikeya Dwivedi 		stats_get_rx_cnt(cur, prev, 0, &out);
14441d930fd2SKumar Kartikeya Dwivedi 	if (mask & SAMPLE_REDIRECT_CNT)
14451d930fd2SKumar Kartikeya Dwivedi 		stats_get_redirect_cnt(cur, prev, 0, &out);
14461d930fd2SKumar Kartikeya Dwivedi 	if (mask & SAMPLE_REDIRECT_ERR_CNT)
14471d930fd2SKumar Kartikeya Dwivedi 		stats_get_redirect_err_cnt(cur, prev, 0, &out);
144882c45080SKumar Kartikeya Dwivedi 	if (mask & SAMPLE_EXCEPTION_CNT)
144982c45080SKumar Kartikeya Dwivedi 		stats_get_exception_cnt(cur, prev, 0, &out);
1450af93d58cSKumar Kartikeya Dwivedi 	if (mask & SAMPLE_DEVMAP_XMIT_CNT)
1451af93d58cSKumar Kartikeya Dwivedi 		stats_get_devmap_xmit(cur, prev, 0, &out);
1452af93d58cSKumar Kartikeya Dwivedi 	else if (mask & SAMPLE_DEVMAP_XMIT_CNT_MULTI)
1453af93d58cSKumar Kartikeya Dwivedi 		stats_get_devmap_xmit_multi(cur, prev, 0, &out,
1454af93d58cSKumar Kartikeya Dwivedi 					    mask & SAMPLE_DEVMAP_XMIT_CNT);
1455dc14ca46SAlexander Lobakin 	sample_summary_update(&out);
1456156f886cSKumar Kartikeya Dwivedi 
1457156f886cSKumar Kartikeya Dwivedi 	stats_print(prog_name, mask, cur, prev, &out);
1458156f886cSKumar Kartikeya Dwivedi }
1459156f886cSKumar Kartikeya Dwivedi 
sample_switch_mode(void)1460156f886cSKumar Kartikeya Dwivedi void sample_switch_mode(void)
1461156f886cSKumar Kartikeya Dwivedi {
1462156f886cSKumar Kartikeya Dwivedi 	sample_log_level ^= LL_DEBUG - 1;
1463156f886cSKumar Kartikeya Dwivedi }
1464156f886cSKumar Kartikeya Dwivedi 
sample_signal_cb(void)1465156f886cSKumar Kartikeya Dwivedi static int sample_signal_cb(void)
1466156f886cSKumar Kartikeya Dwivedi {
1467156f886cSKumar Kartikeya Dwivedi 	struct signalfd_siginfo si;
1468156f886cSKumar Kartikeya Dwivedi 	int r;
1469156f886cSKumar Kartikeya Dwivedi 
1470156f886cSKumar Kartikeya Dwivedi 	r = read(sample_sig_fd, &si, sizeof(si));
1471156f886cSKumar Kartikeya Dwivedi 	if (r < 0)
1472156f886cSKumar Kartikeya Dwivedi 		return -errno;
1473156f886cSKumar Kartikeya Dwivedi 
1474156f886cSKumar Kartikeya Dwivedi 	switch (si.ssi_signo) {
1475156f886cSKumar Kartikeya Dwivedi 	case SIGQUIT:
1476156f886cSKumar Kartikeya Dwivedi 		sample_switch_mode();
1477156f886cSKumar Kartikeya Dwivedi 		printf("\n");
1478156f886cSKumar Kartikeya Dwivedi 		break;
1479156f886cSKumar Kartikeya Dwivedi 	default:
1480156f886cSKumar Kartikeya Dwivedi 		printf("\n");
1481156f886cSKumar Kartikeya Dwivedi 		return 1;
1482156f886cSKumar Kartikeya Dwivedi 	}
1483156f886cSKumar Kartikeya Dwivedi 
1484156f886cSKumar Kartikeya Dwivedi 	return 0;
1485156f886cSKumar Kartikeya Dwivedi }
1486156f886cSKumar Kartikeya Dwivedi 
1487156f886cSKumar Kartikeya Dwivedi /* Pointer swap trick */
swap(struct stats_record ** a,struct stats_record ** b)1488156f886cSKumar Kartikeya Dwivedi static void swap(struct stats_record **a, struct stats_record **b)
1489156f886cSKumar Kartikeya Dwivedi {
1490156f886cSKumar Kartikeya Dwivedi 	struct stats_record *tmp;
1491156f886cSKumar Kartikeya Dwivedi 
1492156f886cSKumar Kartikeya Dwivedi 	tmp = *a;
1493156f886cSKumar Kartikeya Dwivedi 	*a = *b;
1494156f886cSKumar Kartikeya Dwivedi 	*b = tmp;
1495156f886cSKumar Kartikeya Dwivedi }
1496156f886cSKumar Kartikeya Dwivedi 
sample_timer_cb(int timerfd,struct stats_record ** rec,struct stats_record ** prev)1497156f886cSKumar Kartikeya Dwivedi static int sample_timer_cb(int timerfd, struct stats_record **rec,
1498dc14ca46SAlexander Lobakin 			   struct stats_record **prev)
1499156f886cSKumar Kartikeya Dwivedi {
1500156f886cSKumar Kartikeya Dwivedi 	char line[64] = "Summary";
1501156f886cSKumar Kartikeya Dwivedi 	int ret;
1502156f886cSKumar Kartikeya Dwivedi 	__u64 t;
1503156f886cSKumar Kartikeya Dwivedi 
1504156f886cSKumar Kartikeya Dwivedi 	ret = read(timerfd, &t, sizeof(t));
1505156f886cSKumar Kartikeya Dwivedi 	if (ret < 0)
1506156f886cSKumar Kartikeya Dwivedi 		return -errno;
1507156f886cSKumar Kartikeya Dwivedi 
1508156f886cSKumar Kartikeya Dwivedi 	swap(prev, rec);
1509156f886cSKumar Kartikeya Dwivedi 	ret = sample_stats_collect(*rec);
1510156f886cSKumar Kartikeya Dwivedi 	if (ret < 0)
1511156f886cSKumar Kartikeya Dwivedi 		return ret;
1512156f886cSKumar Kartikeya Dwivedi 
1513594a116bSKumar Kartikeya Dwivedi 	if (sample_xdp_cnt == 2 && !(sample_mask & SAMPLE_SKIP_HEADING)) {
1514156f886cSKumar Kartikeya Dwivedi 		char fi[IFNAMSIZ];
1515156f886cSKumar Kartikeya Dwivedi 		char to[IFNAMSIZ];
1516156f886cSKumar Kartikeya Dwivedi 		const char *f, *t;
1517156f886cSKumar Kartikeya Dwivedi 
1518156f886cSKumar Kartikeya Dwivedi 		f = t = NULL;
1519156f886cSKumar Kartikeya Dwivedi 		if (if_indextoname(sample_xdp_progs[0].ifindex, fi))
1520156f886cSKumar Kartikeya Dwivedi 			f = fi;
1521156f886cSKumar Kartikeya Dwivedi 		if (if_indextoname(sample_xdp_progs[1].ifindex, to))
1522156f886cSKumar Kartikeya Dwivedi 			t = to;
1523156f886cSKumar Kartikeya Dwivedi 
1524156f886cSKumar Kartikeya Dwivedi 		snprintf(line, sizeof(line), "%s->%s", f ?: "?", t ?: "?");
1525156f886cSKumar Kartikeya Dwivedi 	}
1526156f886cSKumar Kartikeya Dwivedi 
1527dc14ca46SAlexander Lobakin 	sample_stats_print(sample_mask, *rec, *prev, line);
1528156f886cSKumar Kartikeya Dwivedi 	return 0;
1529156f886cSKumar Kartikeya Dwivedi }
1530156f886cSKumar Kartikeya Dwivedi 
sample_run(int interval,void (* post_cb)(void *),void * ctx)1531156f886cSKumar Kartikeya Dwivedi int sample_run(int interval, void (*post_cb)(void *), void *ctx)
1532156f886cSKumar Kartikeya Dwivedi {
1533156f886cSKumar Kartikeya Dwivedi 	struct timespec ts = { interval, 0 };
1534156f886cSKumar Kartikeya Dwivedi 	struct itimerspec its = { ts, ts };
1535156f886cSKumar Kartikeya Dwivedi 	struct stats_record *rec, *prev;
1536156f886cSKumar Kartikeya Dwivedi 	struct pollfd pfd[2] = {};
1537156f886cSKumar Kartikeya Dwivedi 	int timerfd, ret;
1538156f886cSKumar Kartikeya Dwivedi 
1539156f886cSKumar Kartikeya Dwivedi 	if (!interval) {
1540156f886cSKumar Kartikeya Dwivedi 		fprintf(stderr, "Incorrect interval 0\n");
1541156f886cSKumar Kartikeya Dwivedi 		return -EINVAL;
1542156f886cSKumar Kartikeya Dwivedi 	}
1543156f886cSKumar Kartikeya Dwivedi 	sample_interval = interval;
1544156f886cSKumar Kartikeya Dwivedi 	/* Pretty print numbers */
1545156f886cSKumar Kartikeya Dwivedi 	setlocale(LC_NUMERIC, "en_US.UTF-8");
1546156f886cSKumar Kartikeya Dwivedi 
1547156f886cSKumar Kartikeya Dwivedi 	timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
1548156f886cSKumar Kartikeya Dwivedi 	if (timerfd < 0)
1549156f886cSKumar Kartikeya Dwivedi 		return -errno;
1550156f886cSKumar Kartikeya Dwivedi 	timerfd_settime(timerfd, 0, &its, NULL);
1551156f886cSKumar Kartikeya Dwivedi 
1552156f886cSKumar Kartikeya Dwivedi 	pfd[0].fd = sample_sig_fd;
1553156f886cSKumar Kartikeya Dwivedi 	pfd[0].events = POLLIN;
1554156f886cSKumar Kartikeya Dwivedi 
1555156f886cSKumar Kartikeya Dwivedi 	pfd[1].fd = timerfd;
1556156f886cSKumar Kartikeya Dwivedi 	pfd[1].events = POLLIN;
1557156f886cSKumar Kartikeya Dwivedi 
1558156f886cSKumar Kartikeya Dwivedi 	ret = -ENOMEM;
1559156f886cSKumar Kartikeya Dwivedi 	rec = alloc_stats_record();
1560156f886cSKumar Kartikeya Dwivedi 	if (!rec)
1561156f886cSKumar Kartikeya Dwivedi 		goto end;
1562156f886cSKumar Kartikeya Dwivedi 	prev = alloc_stats_record();
1563156f886cSKumar Kartikeya Dwivedi 	if (!prev)
1564156f886cSKumar Kartikeya Dwivedi 		goto end_rec;
1565156f886cSKumar Kartikeya Dwivedi 
1566156f886cSKumar Kartikeya Dwivedi 	ret = sample_stats_collect(rec);
1567156f886cSKumar Kartikeya Dwivedi 	if (ret < 0)
1568156f886cSKumar Kartikeya Dwivedi 		goto end_rec_prev;
1569156f886cSKumar Kartikeya Dwivedi 
1570156f886cSKumar Kartikeya Dwivedi 	for (;;) {
1571156f886cSKumar Kartikeya Dwivedi 		ret = poll(pfd, 2, -1);
1572156f886cSKumar Kartikeya Dwivedi 		if (ret < 0) {
1573156f886cSKumar Kartikeya Dwivedi 			if (errno == EINTR)
1574156f886cSKumar Kartikeya Dwivedi 				continue;
1575156f886cSKumar Kartikeya Dwivedi 			else
1576156f886cSKumar Kartikeya Dwivedi 				break;
1577156f886cSKumar Kartikeya Dwivedi 		}
1578156f886cSKumar Kartikeya Dwivedi 
1579156f886cSKumar Kartikeya Dwivedi 		if (pfd[0].revents & POLLIN)
1580156f886cSKumar Kartikeya Dwivedi 			ret = sample_signal_cb();
1581156f886cSKumar Kartikeya Dwivedi 		else if (pfd[1].revents & POLLIN)
1582dc14ca46SAlexander Lobakin 			ret = sample_timer_cb(timerfd, &rec, &prev);
1583156f886cSKumar Kartikeya Dwivedi 
1584156f886cSKumar Kartikeya Dwivedi 		if (ret)
1585156f886cSKumar Kartikeya Dwivedi 			break;
1586156f886cSKumar Kartikeya Dwivedi 
1587156f886cSKumar Kartikeya Dwivedi 		if (post_cb)
1588156f886cSKumar Kartikeya Dwivedi 			post_cb(ctx);
1589156f886cSKumar Kartikeya Dwivedi 	}
1590156f886cSKumar Kartikeya Dwivedi 
1591156f886cSKumar Kartikeya Dwivedi end_rec_prev:
1592156f886cSKumar Kartikeya Dwivedi 	free_stats_record(prev);
1593156f886cSKumar Kartikeya Dwivedi end_rec:
1594156f886cSKumar Kartikeya Dwivedi 	free_stats_record(rec);
1595156f886cSKumar Kartikeya Dwivedi end:
1596156f886cSKumar Kartikeya Dwivedi 	close(timerfd);
1597156f886cSKumar Kartikeya Dwivedi 
1598156f886cSKumar Kartikeya Dwivedi 	return ret;
1599156f886cSKumar Kartikeya Dwivedi }
1600156f886cSKumar Kartikeya Dwivedi 
get_driver_name(int ifindex)1601156f886cSKumar Kartikeya Dwivedi const char *get_driver_name(int ifindex)
1602156f886cSKumar Kartikeya Dwivedi {
1603156f886cSKumar Kartikeya Dwivedi 	struct ethtool_drvinfo drv = {};
1604156f886cSKumar Kartikeya Dwivedi 	char ifname[IF_NAMESIZE];
1605156f886cSKumar Kartikeya Dwivedi 	static char drvname[32];
1606156f886cSKumar Kartikeya Dwivedi 	struct ifreq ifr = {};
1607156f886cSKumar Kartikeya Dwivedi 	int fd, r = 0;
1608156f886cSKumar Kartikeya Dwivedi 
1609156f886cSKumar Kartikeya Dwivedi 	fd = socket(AF_INET, SOCK_DGRAM, 0);
1610156f886cSKumar Kartikeya Dwivedi 	if (fd < 0)
1611156f886cSKumar Kartikeya Dwivedi 		return "[error]";
1612156f886cSKumar Kartikeya Dwivedi 
1613156f886cSKumar Kartikeya Dwivedi 	if (!if_indextoname(ifindex, ifname))
1614156f886cSKumar Kartikeya Dwivedi 		goto end;
1615156f886cSKumar Kartikeya Dwivedi 
1616156f886cSKumar Kartikeya Dwivedi 	drv.cmd = ETHTOOL_GDRVINFO;
1617156f886cSKumar Kartikeya Dwivedi 	safe_strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1618156f886cSKumar Kartikeya Dwivedi 	ifr.ifr_data = (void *)&drv;
1619156f886cSKumar Kartikeya Dwivedi 
1620156f886cSKumar Kartikeya Dwivedi 	r = ioctl(fd, SIOCETHTOOL, &ifr);
1621156f886cSKumar Kartikeya Dwivedi 	if (r)
1622156f886cSKumar Kartikeya Dwivedi 		goto end;
1623156f886cSKumar Kartikeya Dwivedi 
1624156f886cSKumar Kartikeya Dwivedi 	safe_strncpy(drvname, drv.driver, sizeof(drvname));
1625156f886cSKumar Kartikeya Dwivedi 
1626156f886cSKumar Kartikeya Dwivedi 	close(fd);
1627156f886cSKumar Kartikeya Dwivedi 	return drvname;
1628156f886cSKumar Kartikeya Dwivedi 
1629156f886cSKumar Kartikeya Dwivedi end:
1630156f886cSKumar Kartikeya Dwivedi 	r = errno;
1631156f886cSKumar Kartikeya Dwivedi 	close(fd);
1632156f886cSKumar Kartikeya Dwivedi 	return r == EOPNOTSUPP ? "loopback" : "[error]";
1633156f886cSKumar Kartikeya Dwivedi }
1634156f886cSKumar Kartikeya Dwivedi 
get_mac_addr(int ifindex,void * mac_addr)1635156f886cSKumar Kartikeya Dwivedi int get_mac_addr(int ifindex, void *mac_addr)
1636156f886cSKumar Kartikeya Dwivedi {
1637156f886cSKumar Kartikeya Dwivedi 	char ifname[IF_NAMESIZE];
1638156f886cSKumar Kartikeya Dwivedi 	struct ifreq ifr = {};
1639156f886cSKumar Kartikeya Dwivedi 	int fd, r;
1640156f886cSKumar Kartikeya Dwivedi 
1641156f886cSKumar Kartikeya Dwivedi 	fd = socket(AF_INET, SOCK_DGRAM, 0);
1642156f886cSKumar Kartikeya Dwivedi 	if (fd < 0)
1643156f886cSKumar Kartikeya Dwivedi 		return -errno;
1644156f886cSKumar Kartikeya Dwivedi 
1645156f886cSKumar Kartikeya Dwivedi 	if (!if_indextoname(ifindex, ifname)) {
1646156f886cSKumar Kartikeya Dwivedi 		r = -errno;
1647156f886cSKumar Kartikeya Dwivedi 		goto end;
1648156f886cSKumar Kartikeya Dwivedi 	}
1649156f886cSKumar Kartikeya Dwivedi 
1650156f886cSKumar Kartikeya Dwivedi 	safe_strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1651156f886cSKumar Kartikeya Dwivedi 
1652156f886cSKumar Kartikeya Dwivedi 	r = ioctl(fd, SIOCGIFHWADDR, &ifr);
1653156f886cSKumar Kartikeya Dwivedi 	if (r) {
1654156f886cSKumar Kartikeya Dwivedi 		r = -errno;
1655156f886cSKumar Kartikeya Dwivedi 		goto end;
1656156f886cSKumar Kartikeya Dwivedi 	}
1657156f886cSKumar Kartikeya Dwivedi 
1658156f886cSKumar Kartikeya Dwivedi 	memcpy(mac_addr, ifr.ifr_hwaddr.sa_data, 6 * sizeof(char));
1659156f886cSKumar Kartikeya Dwivedi 
1660156f886cSKumar Kartikeya Dwivedi end:
1661156f886cSKumar Kartikeya Dwivedi 	close(fd);
1662156f886cSKumar Kartikeya Dwivedi 	return r;
1663156f886cSKumar Kartikeya Dwivedi }
1664156f886cSKumar Kartikeya Dwivedi 
sample_ctor(void)1665156f886cSKumar Kartikeya Dwivedi __attribute__((constructor)) static void sample_ctor(void)
1666156f886cSKumar Kartikeya Dwivedi {
1667156f886cSKumar Kartikeya Dwivedi 	if (libbpf_set_strict_mode(LIBBPF_STRICT_ALL) < 0) {
1668156f886cSKumar Kartikeya Dwivedi 		fprintf(stderr, "Failed to set libbpf strict mode: %s\n",
1669156f886cSKumar Kartikeya Dwivedi 			strerror(errno));
1670156f886cSKumar Kartikeya Dwivedi 		/* Just exit, nothing to cleanup right now */
1671156f886cSKumar Kartikeya Dwivedi 		exit(EXIT_FAIL_BPF);
1672156f886cSKumar Kartikeya Dwivedi 	}
1673156f886cSKumar Kartikeya Dwivedi }
1674