Skip to content

Commit 0fca931

Browse files
netoptimizerAlexei Starovoitov
authored andcommitted
samples/bpf: program demonstrating access to xdp_rxq_info
This sample program can be used for monitoring and reporting how many packets per sec (pps) are received per NIC RX queue index and which CPU processed the packet. In itself it is a useful tool for quickly identifying RSS imbalance issues, see below. The default XDP action is XDP_PASS in-order to provide a monitor mode. For benchmarking purposes it is possible to specify other XDP actions on the cmdline --action. Output below shows an imbalance RSS case where most RXQ's deliver to CPU-0 while CPU-2 only get packets from a single RXQ. Looking at things from a CPU level the two CPUs are processing approx the same amount, BUT looking at the rx_queue_index levels it is clear that RXQ-2 receive much better service, than other RXQs which all share CPU-0. Running XDP on dev:i40e1 (ifindex:3) action:XDP_PASS XDP stats CPU pps issue-pps XDP-RX CPU 0 900,473 0 XDP-RX CPU 2 906,921 0 XDP-RX CPU total 1,807,395 RXQ stats RXQ:CPU pps issue-pps rx_queue_index 0:0 180,098 0 rx_queue_index 0:sum 180,098 rx_queue_index 1:0 180,098 0 rx_queue_index 1:sum 180,098 rx_queue_index 2:2 906,921 0 rx_queue_index 2:sum 906,921 rx_queue_index 3:0 180,098 0 rx_queue_index 3:sum 180,098 rx_queue_index 4:0 180,082 0 rx_queue_index 4:sum 180,082 rx_queue_index 5:0 180,093 0 rx_queue_index 5:sum 180,093 Signed-off-by: Jesper Dangaard Brouer <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent 02dd329 commit 0fca931

File tree

3 files changed

+631
-0
lines changed

3 files changed

+631
-0
lines changed

samples/bpf/Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ hostprogs-y += xdp_redirect
4141
hostprogs-y += xdp_redirect_map
4242
hostprogs-y += xdp_redirect_cpu
4343
hostprogs-y += xdp_monitor
44+
hostprogs-y += xdp_rxq_info
4445
hostprogs-y += syscall_tp
4546

4647
# Libbpf dependencies
@@ -90,6 +91,7 @@ xdp_redirect-objs := bpf_load.o $(LIBBPF) xdp_redirect_user.o
9091
xdp_redirect_map-objs := bpf_load.o $(LIBBPF) xdp_redirect_map_user.o
9192
xdp_redirect_cpu-objs := bpf_load.o $(LIBBPF) xdp_redirect_cpu_user.o
9293
xdp_monitor-objs := bpf_load.o $(LIBBPF) xdp_monitor_user.o
94+
xdp_rxq_info-objs := bpf_load.o $(LIBBPF) xdp_rxq_info_user.o
9395
syscall_tp-objs := bpf_load.o $(LIBBPF) syscall_tp_user.o
9496

9597
# Tell kbuild to always build the programs
@@ -139,6 +141,7 @@ always += xdp_redirect_kern.o
139141
always += xdp_redirect_map_kern.o
140142
always += xdp_redirect_cpu_kern.o
141143
always += xdp_monitor_kern.o
144+
always += xdp_rxq_info_kern.o
142145
always += syscall_tp_kern.o
143146

144147
HOSTCFLAGS += -I$(objtree)/usr/include
@@ -182,6 +185,7 @@ HOSTLOADLIBES_xdp_redirect += -lelf
182185
HOSTLOADLIBES_xdp_redirect_map += -lelf
183186
HOSTLOADLIBES_xdp_redirect_cpu += -lelf
184187
HOSTLOADLIBES_xdp_monitor += -lelf
188+
HOSTLOADLIBES_xdp_rxq_info += -lelf
185189
HOSTLOADLIBES_syscall_tp += -lelf
186190

187191
# Allows pointing LLC/CLANG to a LLVM backend with bpf support, redefine on cmdline:

samples/bpf/xdp_rxq_info_kern.c

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/* SPDX-License-Identifier: GPL-2.0
2+
* Copyright (c) 2017 Jesper Dangaard Brouer, Red Hat Inc.
3+
*
4+
* Example howto extract XDP RX-queue info
5+
*/
6+
#include <uapi/linux/bpf.h>
7+
#include "bpf_helpers.h"
8+
9+
/* Config setup from with userspace
10+
*
11+
* User-side setup ifindex in config_map, to verify that
12+
* ctx->ingress_ifindex is correct (against configured ifindex)
13+
*/
14+
struct config {
15+
__u32 action;
16+
int ifindex;
17+
};
18+
struct bpf_map_def SEC("maps") config_map = {
19+
.type = BPF_MAP_TYPE_ARRAY,
20+
.key_size = sizeof(int),
21+
.value_size = sizeof(struct config),
22+
.max_entries = 1,
23+
};
24+
25+
/* Common stats data record (shared with userspace) */
26+
struct datarec {
27+
__u64 processed;
28+
__u64 issue;
29+
};
30+
31+
struct bpf_map_def SEC("maps") stats_global_map = {
32+
.type = BPF_MAP_TYPE_PERCPU_ARRAY,
33+
.key_size = sizeof(u32),
34+
.value_size = sizeof(struct datarec),
35+
.max_entries = 1,
36+
};
37+
38+
#define MAX_RXQs 64
39+
40+
/* Stats per rx_queue_index (per CPU) */
41+
struct bpf_map_def SEC("maps") rx_queue_index_map = {
42+
.type = BPF_MAP_TYPE_PERCPU_ARRAY,
43+
.key_size = sizeof(u32),
44+
.value_size = sizeof(struct datarec),
45+
.max_entries = MAX_RXQs + 1,
46+
};
47+
48+
SEC("xdp_prog0")
49+
int xdp_prognum0(struct xdp_md *ctx)
50+
{
51+
void *data_end = (void *)(long)ctx->data_end;
52+
void *data = (void *)(long)ctx->data;
53+
struct datarec *rec, *rxq_rec;
54+
int ingress_ifindex;
55+
struct config *config;
56+
u32 key = 0;
57+
58+
/* Global stats record */
59+
rec = bpf_map_lookup_elem(&stats_global_map, &key);
60+
if (!rec)
61+
return XDP_ABORTED;
62+
rec->processed++;
63+
64+
/* Accessing ctx->ingress_ifindex, cause BPF to rewrite BPF
65+
* instructions inside kernel to access xdp_rxq->dev->ifindex
66+
*/
67+
ingress_ifindex = ctx->ingress_ifindex;
68+
69+
config = bpf_map_lookup_elem(&config_map, &key);
70+
if (!config)
71+
return XDP_ABORTED;
72+
73+
/* Simple test: check ctx provided ifindex is as expected */
74+
if (ingress_ifindex != config->ifindex) {
75+
/* count this error case */
76+
rec->issue++;
77+
return XDP_ABORTED;
78+
}
79+
80+
/* Update stats per rx_queue_index. Handle if rx_queue_index
81+
* is larger than stats map can contain info for.
82+
*/
83+
key = ctx->rx_queue_index;
84+
if (key >= MAX_RXQs)
85+
key = MAX_RXQs;
86+
rxq_rec = bpf_map_lookup_elem(&rx_queue_index_map, &key);
87+
if (!rxq_rec)
88+
return XDP_ABORTED;
89+
rxq_rec->processed++;
90+
if (key == MAX_RXQs)
91+
rxq_rec->issue++;
92+
93+
return config->action;
94+
}
95+
96+
char _license[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)