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