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+
5659typedef __u64 u64 ;
5760typedef __u32 u32 ;
5861typedef __u16 u16 ;
@@ -86,7 +89,7 @@ static u32 irq_no;
8689static int irqs_at_init = -1 ;
8790static int opt_poll ;
8891static 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 ;
9093static u32 opt_umem_flags ;
9194static int opt_unaligned_chunks ;
9295static int opt_mmap_flags ;
@@ -95,6 +98,8 @@ static int opt_timeout = 1000;
9598static bool opt_need_wakeup = true;
9699static u32 opt_num_xsks = 1 ;
97100static u32 prog_id ;
101+ static u32 xdp_caps ;
102+ static u16 bind_caps ;
98103
99104struct 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+
960985static 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+
14641555int 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