Skip to content

Commit afe5756

Browse files
alardamkernel-patches-bot
authored andcommitted
samples/bpf/xdp: apply netdev XDP/XSK modes info
Update xdpsock sample so that it utilizes netlink ethtool interface to get available XDP/XSK modes. This allows to automatically choose the best available mode of operation, if these are not provided explicitly. Signed-off-by: Marek Majtyka <[email protected]>
1 parent c13a17b commit afe5756

File tree

1 file changed

+108
-9
lines changed

1 file changed

+108
-9
lines changed

samples/bpf/xdpsock_user.c

Lines changed: 108 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@
5353

5454
#define DEBUG_HEXDUMP 0
5555

56+
#define XDP_MODES (XDP_FLAGS_SKB_MODE | XDP_FLAGS_DRV_MODE)
57+
#define XSK_MODES (XDP_COPY | XDP_ZEROCOPY)
58+
5659
typedef __u64 u64;
5760
typedef __u32 u32;
5861
typedef __u16 u16;
@@ -86,7 +89,7 @@ static u32 irq_no;
8689
static int irqs_at_init = -1;
8790
static int opt_poll;
8891
static int opt_interval = 1;
89-
static u32 opt_xdp_bind_flags = XDP_USE_NEED_WAKEUP;
92+
static u16 opt_xdp_bind_flags = XDP_USE_NEED_WAKEUP;
9093
static u32 opt_umem_flags;
9194
static int opt_unaligned_chunks;
9295
static int opt_mmap_flags;
@@ -95,6 +98,8 @@ static int opt_timeout = 1000;
9598
static bool opt_need_wakeup = true;
9699
static u32 opt_num_xsks = 1;
97100
static u32 prog_id;
101+
static u32 xdp_caps;
102+
static u16 bind_caps;
98103

99104
struct xsk_ring_stats {
100105
unsigned long rx_npkts;
@@ -957,6 +962,26 @@ static void usage(const char *prog)
957962
exit(EXIT_FAILURE);
958963
}
959964

965+
static inline void set_drv_mode(void)
966+
{
967+
opt_xdp_flags |= XDP_FLAGS_DRV_MODE;
968+
}
969+
970+
static inline void set_skb_mode(void)
971+
{
972+
opt_xdp_flags |= XDP_FLAGS_SKB_MODE;
973+
}
974+
975+
static inline void set_zc_mode(void)
976+
{
977+
opt_xdp_bind_flags |= XDP_ZEROCOPY;
978+
}
979+
980+
static inline void set_copy_mode(void)
981+
{
982+
opt_xdp_bind_flags |= XDP_COPY;
983+
}
984+
960985
static void parse_command_line(int argc, char **argv)
961986
{
962987
int option_index, c;
@@ -989,20 +1014,19 @@ static void parse_command_line(int argc, char **argv)
9891014
opt_poll = 1;
9901015
break;
9911016
case 'S':
992-
opt_xdp_flags |= XDP_FLAGS_SKB_MODE;
993-
opt_xdp_bind_flags |= XDP_COPY;
1017+
set_skb_mode();
9941018
break;
9951019
case 'N':
996-
/* default, set below */
1020+
set_drv_mode();
9971021
break;
9981022
case 'n':
9991023
opt_interval = atoi(optarg);
10001024
break;
10011025
case 'z':
1002-
opt_xdp_bind_flags |= XDP_ZEROCOPY;
1026+
set_zc_mode();
10031027
break;
10041028
case 'c':
1005-
opt_xdp_bind_flags |= XDP_COPY;
1029+
set_copy_mode();
10061030
break;
10071031
case 'u':
10081032
opt_umem_flags |= XDP_UMEM_UNALIGNED_CHUNK_FLAG;
@@ -1069,9 +1093,6 @@ static void parse_command_line(int argc, char **argv)
10691093
}
10701094
}
10711095

1072-
if (!(opt_xdp_flags & XDP_FLAGS_SKB_MODE))
1073-
opt_xdp_flags |= XDP_FLAGS_DRV_MODE;
1074-
10751096
opt_ifindex = if_nametoindex(opt_if);
10761097
if (!opt_ifindex) {
10771098
fprintf(stderr, "ERROR: interface \"%s\" does not exist\n",
@@ -1461,6 +1482,76 @@ static void enter_xsks_into_map(struct bpf_object *obj)
14611482
}
14621483
}
14631484

1485+
static inline u32 xdp_mode_not_set(void)
1486+
{
1487+
return (opt_xdp_flags & XDP_MODES) == 0;
1488+
}
1489+
1490+
static inline u16 bind_mode_not_set(void)
1491+
{
1492+
return (opt_xdp_bind_flags & XSK_MODES) == 0;
1493+
}
1494+
1495+
static inline u16 zc_mode_set(void)
1496+
{
1497+
return opt_xdp_bind_flags & XDP_ZEROCOPY;
1498+
}
1499+
1500+
static inline u32 drv_mode_set(void)
1501+
{
1502+
return opt_xdp_flags & XDP_FLAGS_DRV_MODE;
1503+
}
1504+
1505+
static inline u16 zc_mode_available(void)
1506+
{
1507+
return bind_caps & XDP_ZEROCOPY;
1508+
}
1509+
1510+
static inline u32 drv_mode_available(void)
1511+
{
1512+
return xdp_caps & XDP_FLAGS_DRV_MODE;
1513+
}
1514+
1515+
static void set_xsk_default_flags(void)
1516+
{
1517+
if (drv_mode_available()) {
1518+
set_drv_mode();
1519+
1520+
if (zc_mode_available())
1521+
set_zc_mode();
1522+
else
1523+
set_copy_mode();
1524+
} else {
1525+
set_skb_mode();
1526+
set_copy_mode();
1527+
}
1528+
}
1529+
1530+
static void adjust_missing_flags(void)
1531+
{
1532+
if (xdp_mode_not_set()) {
1533+
if (bind_mode_not_set()) {
1534+
set_xsk_default_flags();
1535+
} else {
1536+
if (zc_mode_set()) {
1537+
set_drv_mode();
1538+
} else {
1539+
if (drv_mode_available())
1540+
set_drv_mode();
1541+
else
1542+
set_skb_mode();
1543+
}
1544+
}
1545+
} else {
1546+
if (bind_mode_not_set()) {
1547+
if (drv_mode_set() && zc_mode_available())
1548+
set_zc_mode();
1549+
else
1550+
set_copy_mode();
1551+
}
1552+
}
1553+
}
1554+
14641555
int main(int argc, char **argv)
14651556
{
14661557
struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
@@ -1473,6 +1564,14 @@ int main(int argc, char **argv)
14731564

14741565
parse_command_line(argc, argv);
14751566

1567+
ret = xsk_socket__get_caps(opt_if, &xdp_caps, &bind_caps);
1568+
if (ret) {
1569+
fprintf(stderr, "ERROR: xsk_socket__get_caps\n");
1570+
exit(EXIT_FAILURE);
1571+
}
1572+
1573+
adjust_missing_flags();
1574+
14761575
if (setrlimit(RLIMIT_MEMLOCK, &r)) {
14771576
fprintf(stderr, "ERROR: setrlimit(RLIMIT_MEMLOCK) \"%s\"\n",
14781577
strerror(errno));

0 commit comments

Comments
 (0)