53
53
54
54
#define DEBUG_HEXDUMP 0
55
55
56
+ #define XDP_MODES (XDP_FLAGS_SKB_MODE | XDP_FLAGS_DRV_MODE)
57
+ #define XSK_MODES (XDP_COPY | XDP_ZEROCOPY)
58
+
56
59
typedef __u64 u64 ;
57
60
typedef __u32 u32 ;
58
61
typedef __u16 u16 ;
@@ -86,7 +89,7 @@ static u32 irq_no;
86
89
static int irqs_at_init = -1 ;
87
90
static int opt_poll ;
88
91
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 ;
90
93
static u32 opt_umem_flags ;
91
94
static int opt_unaligned_chunks ;
92
95
static int opt_mmap_flags ;
@@ -95,6 +98,8 @@ static int opt_timeout = 1000;
95
98
static bool opt_need_wakeup = true;
96
99
static u32 opt_num_xsks = 1 ;
97
100
static u32 prog_id ;
101
+ static u32 xdp_caps ;
102
+ static u16 bind_caps ;
98
103
99
104
struct xsk_ring_stats {
100
105
unsigned long rx_npkts ;
@@ -957,6 +962,26 @@ static void usage(const char *prog)
957
962
exit (EXIT_FAILURE );
958
963
}
959
964
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
+
960
985
static void parse_command_line (int argc , char * * argv )
961
986
{
962
987
int option_index , c ;
@@ -989,20 +1014,19 @@ static void parse_command_line(int argc, char **argv)
989
1014
opt_poll = 1 ;
990
1015
break ;
991
1016
case 'S' :
992
- opt_xdp_flags |= XDP_FLAGS_SKB_MODE ;
993
- opt_xdp_bind_flags |= XDP_COPY ;
1017
+ set_skb_mode ();
994
1018
break ;
995
1019
case 'N' :
996
- /* default, set below */
1020
+ set_drv_mode ();
997
1021
break ;
998
1022
case 'n' :
999
1023
opt_interval = atoi (optarg );
1000
1024
break ;
1001
1025
case 'z' :
1002
- opt_xdp_bind_flags |= XDP_ZEROCOPY ;
1026
+ set_zc_mode () ;
1003
1027
break ;
1004
1028
case 'c' :
1005
- opt_xdp_bind_flags |= XDP_COPY ;
1029
+ set_copy_mode () ;
1006
1030
break ;
1007
1031
case 'u' :
1008
1032
opt_umem_flags |= XDP_UMEM_UNALIGNED_CHUNK_FLAG ;
@@ -1069,9 +1093,6 @@ static void parse_command_line(int argc, char **argv)
1069
1093
}
1070
1094
}
1071
1095
1072
- if (!(opt_xdp_flags & XDP_FLAGS_SKB_MODE ))
1073
- opt_xdp_flags |= XDP_FLAGS_DRV_MODE ;
1074
-
1075
1096
opt_ifindex = if_nametoindex (opt_if );
1076
1097
if (!opt_ifindex ) {
1077
1098
fprintf (stderr , "ERROR: interface \"%s\" does not exist\n" ,
@@ -1461,6 +1482,76 @@ static void enter_xsks_into_map(struct bpf_object *obj)
1461
1482
}
1462
1483
}
1463
1484
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
+
1464
1555
int main (int argc , char * * argv )
1465
1556
{
1466
1557
struct rlimit r = {RLIM_INFINITY , RLIM_INFINITY };
@@ -1473,6 +1564,14 @@ int main(int argc, char **argv)
1473
1564
1474
1565
parse_command_line (argc , argv );
1475
1566
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
+
1476
1575
if (setrlimit (RLIMIT_MEMLOCK , & r )) {
1477
1576
fprintf (stderr , "ERROR: setrlimit(RLIMIT_MEMLOCK) \"%s\"\n" ,
1478
1577
strerror (errno ));
0 commit comments