diff mbox series

[bpf-next,v4,07/22] samples: bpf: Add xdp_exception tracepoint statistics support

Message ID 20210821002010.845777-8-memxor@gmail.com (mailing list archive)
State Accepted
Delegated to: BPF
Headers show
Series Improve XDP samples usability and output | expand

Checks

Context Check Description
netdev/cover_letter success Link
netdev/fixes_present success Link
netdev/patch_count fail Series longer than 15 patches
netdev/tree_selection success Clearly marked for bpf-next
netdev/subject_prefix success Link
netdev/cc_maintainers warning 8 maintainers not CCed: kafai@fb.com yhs@fb.com davem@davemloft.net songliubraving@fb.com hawk@kernel.org kuba@kernel.org kpsingh@kernel.org john.fastabend@gmail.com
netdev/source_inline success Was 0 now: 0
netdev/verify_signedoff success Link
netdev/module_param success Was 0 now: 0
netdev/build_32bit success Errors and warnings before: 0 this patch: 0
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/verify_fixes success Link
netdev/checkpatch warning WARNING: line length of 81 exceeds 80 columns WARNING: line length of 86 exceeds 80 columns WARNING: line length of 90 exceeds 80 columns WARNING: quoted string split across lines
netdev/build_allmodconfig_warn success Errors and warnings before: 0 this patch: 0
netdev/header_inline success Link
bpf/vmtest success Kernel LATEST + selftests

Commit Message

Kumar Kartikeya Dwivedi Aug. 21, 2021, 12:19 a.m. UTC
This implements the retrieval and printing, as well the help output.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
---
 samples/bpf/xdp_sample_user.c | 113 ++++++++++++++++++++++++++++++++++
 samples/bpf/xdp_sample_user.h |   3 +
 2 files changed, 116 insertions(+)
diff mbox series

Patch

diff --git a/samples/bpf/xdp_sample_user.c b/samples/bpf/xdp_sample_user.c
index c34592566825..52a30fd1f2a3 100644
--- a/samples/bpf/xdp_sample_user.c
+++ b/samples/bpf/xdp_sample_user.c
@@ -74,6 +74,7 @@ 
 enum map_type {
 	MAP_RX,
 	MAP_REDIRECT_ERR,
+	MAP_EXCEPTION,
 	NUM_MAP,
 };
 
@@ -98,6 +99,7 @@  struct map_entry {
 struct stats_record {
 	struct record rx_cnt;
 	struct record redir_err[XDP_REDIRECT_ERR_MAX];
+	struct record exception[XDP_ACTION_MAX];
 };
 
 struct sample_output {
@@ -115,6 +117,9 @@  struct sample_output {
 		__u64 suc;
 		__u64 err;
 	} redir_cnt;
+	struct {
+		__u64 hits;
+	} except_cnt;
 };
 
 struct xdp_desc {
@@ -156,6 +161,15 @@  static const char *xdp_redirect_err_help[XDP_REDIRECT_ERR_MAX - 1] = {
 	"No space in ptr_ring of cpumap kthread",
 };
 
+static const char *xdp_action_names[XDP_ACTION_MAX] = {
+	[XDP_ABORTED]  = "XDP_ABORTED",
+	[XDP_DROP]     = "XDP_DROP",
+	[XDP_PASS]     = "XDP_PASS",
+	[XDP_TX]       = "XDP_TX",
+	[XDP_REDIRECT] = "XDP_REDIRECT",
+	[XDP_UNKNOWN]  = "XDP_UNKNOWN",
+};
+
 static __u64 gettime(void)
 {
 	struct timespec t;
@@ -169,6 +183,13 @@  static __u64 gettime(void)
 	return (__u64)t.tv_sec * NANOSEC_PER_SEC + t.tv_nsec;
 }
 
+static const char *action2str(int action)
+{
+	if (action < XDP_ACTION_MAX)
+		return xdp_action_names[action];
+	return NULL;
+}
+
 static void sample_print_help(int mask)
 {
 	printf("Output format description\n\n"
@@ -206,6 +227,15 @@  static void sample_print_help(int mask)
 
 		printf("  \n\t\t\t\terror/s   - Packets that failed redirection per second\n\n");
 	}
+
+	if (mask & SAMPLE_EXCEPTION_CNT) {
+		printf("  xdp_exception\t\tDisplays xdp_exception tracepoint events\n"
+		       "  \t\t\tThis can occur due to internal driver errors, unrecognized\n"
+		       "  \t\t\tXDP actions and due to explicit user trigger by use of XDP_ABORTED\n"
+		       "  \t\t\tEach action is expanded below this field with its count\n"
+		       "  \t\t\t\thit/s     - Number of times the tracepoint was hit per second\n\n");
+	}
+
 }
 
 void sample_usage(char *argv[], const struct option *long_options,
@@ -327,9 +357,26 @@  static struct stats_record *alloc_stats_record(void)
 			}
 		}
 	}
+	if (sample_mask & SAMPLE_EXCEPTION_CNT) {
+		for (i = 0; i < XDP_ACTION_MAX; i++) {
+			rec->exception[i].cpu = alloc_record_per_cpu();
+			if (!rec->exception[i].cpu) {
+				fprintf(stderr,
+					"Failed to allocate exception per-CPU array for "
+					"\"%s\" case\n",
+					action2str(i));
+				while (i--)
+					free(rec->exception[i].cpu);
+				goto end_redir;
+			}
+		}
+	}
 
 	return rec;
 
+end_redir:
+	for (i = 0; i < XDP_REDIRECT_ERR_MAX; i++)
+		free(rec->redir_err[i].cpu);
 end_rx_cnt:
 	free(rec->rx_cnt.cpu);
 end_rec:
@@ -343,6 +390,8 @@  static void free_stats_record(struct stats_record *r)
 	struct map_entry *e;
 	int i;
 
+	for (i = 0; i < XDP_ACTION_MAX; i++)
+		free(r->exception[i].cpu);
 	for (i = 0; i < XDP_REDIRECT_ERR_MAX; i++)
 		free(r->redir_err[i].cpu);
 	free(r->rx_cnt.cpu);
@@ -551,6 +600,50 @@  static void stats_get_redirect_err_cnt(struct stats_record *stats_rec,
 	}
 }
 
+static void stats_get_exception_cnt(struct stats_record *stats_rec,
+				    struct stats_record *stats_prev,
+				    unsigned int nr_cpus,
+				    struct sample_output *out)
+{
+	double t, drop, sum = 0;
+	struct record *rec, *prev;
+	int rec_i, i;
+
+	for (rec_i = 0; rec_i < XDP_ACTION_MAX; rec_i++) {
+		rec = &stats_rec->exception[rec_i];
+		prev = &stats_prev->exception[rec_i];
+		t = calc_period(rec, prev);
+
+		drop = calc_drop_pps(&rec->total, &prev->total, t);
+		/* Fold out errors after heading */
+		sum += drop;
+
+		if (drop > 0 && !out) {
+			print_always("    %-18s " FMT_COLUMNf "\n",
+				     action2str(rec_i), ERR(drop));
+
+			for (i = 0; i < nr_cpus; i++) {
+				struct datarec *r = &rec->cpu[i];
+				struct datarec *p = &prev->cpu[i];
+				char str[64];
+				double drop;
+
+				drop = calc_drop_pps(r, p, t);
+				if (!drop)
+					continue;
+
+				snprintf(str, sizeof(str), "cpu:%d", i);
+				print_default("       %-16s" FMT_COLUMNf "\n",
+					      str, ERR(drop));
+			}
+		}
+	}
+
+	if (out) {
+		out->except_cnt.hits = sum;
+		out->totals.err += sum;
+	}
+}
 
 static void stats_print(const char *prefix, int mask, struct stats_record *r,
 			struct stats_record *p, struct sample_output *out)
@@ -595,6 +688,16 @@  static void stats_print(const char *prefix, int mask, struct stats_record *r,
 		stats_get_redirect_err_cnt(r, p, nr_cpus, NULL);
 	}
 
+	if (mask & SAMPLE_EXCEPTION_CNT) {
+		str = out->except_cnt.hits ? "xdp_exception total" :
+						   "xdp_exception";
+
+		print_err(out->except_cnt.hits, "  %-20s " FMT_COLUMNl "\n", str,
+			  HITS(out->except_cnt.hits));
+
+		stats_get_exception_cnt(r, p, nr_cpus, NULL);
+	}
+
 	if (sample_log_level & LL_DEFAULT ||
 	    ((sample_log_level & LL_SIMPLE) && sample_err_exp)) {
 		sample_err_exp = false;
@@ -617,6 +720,9 @@  int sample_setup_maps(struct bpf_map **maps)
 			sample_map_count[i] =
 				XDP_REDIRECT_ERR_MAX * sample_n_cpus;
 			break;
+		case MAP_EXCEPTION:
+			sample_map_count[i] = XDP_ACTION_MAX * sample_n_cpus;
+			break;
 		default:
 			return -EINVAL;
 		}
@@ -788,6 +894,11 @@  static int sample_stats_collect(struct stats_record *rec)
 					   &rec->redir_err[i]);
 	}
 
+	if (sample_mask & SAMPLE_EXCEPTION_CNT)
+		for (i = 0; i < XDP_ACTION_MAX; i++)
+			map_collect_percpu(&sample_mmap[MAP_EXCEPTION][i * sample_n_cpus],
+					   &rec->exception[i]);
+
 	return 0;
 }
 
@@ -811,6 +922,8 @@  static void sample_stats_print(int mask, struct stats_record *cur,
 		stats_get_redirect_cnt(cur, prev, 0, &out);
 	if (mask & SAMPLE_REDIRECT_ERR_CNT)
 		stats_get_redirect_err_cnt(cur, prev, 0, &out);
+	if (mask & SAMPLE_EXCEPTION_CNT)
+		stats_get_exception_cnt(cur, prev, 0, &out);
 	sample_summary_update(&out, interval);
 
 	stats_print(prog_name, mask, cur, prev, &out);
diff --git a/samples/bpf/xdp_sample_user.h b/samples/bpf/xdp_sample_user.h
index 1935a0e2f85b..aa28e4bdd628 100644
--- a/samples/bpf/xdp_sample_user.h
+++ b/samples/bpf/xdp_sample_user.h
@@ -11,6 +11,7 @@  enum stats_mask {
 	_SAMPLE_REDIRECT_MAP        = 1U << 0,
 	SAMPLE_RX_CNT               = 1U << 1,
 	SAMPLE_REDIRECT_ERR_CNT     = 1U << 2,
+	SAMPLE_EXCEPTION_CNT        = 1U << 5,
 	SAMPLE_REDIRECT_CNT         = 1U << 7,
 	SAMPLE_REDIRECT_MAP_CNT     = SAMPLE_REDIRECT_CNT | _SAMPLE_REDIRECT_MAP,
 	SAMPLE_REDIRECT_ERR_MAP_CNT = SAMPLE_REDIRECT_ERR_CNT | _SAMPLE_REDIRECT_MAP,
@@ -75,6 +76,8 @@  static inline char *safe_strncpy(char *dst, const char *src, size_t size)
 			__attach_tp(tp_xdp_redirect_map_err);                  \
 		if (mask & SAMPLE_REDIRECT_ERR_CNT)                            \
 			__attach_tp(tp_xdp_redirect_err);                      \
+		if (mask & SAMPLE_EXCEPTION_CNT)                               \
+			__attach_tp(tp_xdp_exception);                         \
 		return 0;                                                      \
 	}