@@ -424,7 +424,8 @@ static void __test_spec_init(struct test_spec *test, struct ifobject *ifobj_tx,
424424
425425 ifobj -> xsk = & ifobj -> xsk_arr [0 ];
426426 ifobj -> use_poll = false;
427- ifobj -> pacing_on = true;
427+ ifobj -> use_fill_ring = true;
428+ ifobj -> release_rx = true;
428429 ifobj -> pkt_stream = test -> pkt_stream_default ;
429430 ifobj -> validation_func = NULL ;
430431
@@ -503,9 +504,10 @@ static struct pkt *pkt_stream_get_pkt(struct pkt_stream *pkt_stream, u32 pkt_nb)
503504 return & pkt_stream -> pkts [pkt_nb ];
504505}
505506
506- static struct pkt * pkt_stream_get_next_rx_pkt (struct pkt_stream * pkt_stream )
507+ static struct pkt * pkt_stream_get_next_rx_pkt (struct pkt_stream * pkt_stream , u32 * pkts_sent )
507508{
508509 while (pkt_stream -> rx_pkt_nb < pkt_stream -> nb_pkts ) {
510+ (* pkts_sent )++ ;
509511 if (pkt_stream -> pkts [pkt_stream -> rx_pkt_nb ].valid )
510512 return & pkt_stream -> pkts [pkt_stream -> rx_pkt_nb ++ ];
511513 pkt_stream -> rx_pkt_nb ++ ;
@@ -521,10 +523,16 @@ static void pkt_stream_delete(struct pkt_stream *pkt_stream)
521523
522524static void pkt_stream_restore_default (struct test_spec * test )
523525{
524- if (test -> ifobj_tx -> pkt_stream != test -> pkt_stream_default ) {
526+ struct pkt_stream * tx_pkt_stream = test -> ifobj_tx -> pkt_stream ;
527+
528+ if (tx_pkt_stream != test -> pkt_stream_default ) {
525529 pkt_stream_delete (test -> ifobj_tx -> pkt_stream );
526530 test -> ifobj_tx -> pkt_stream = test -> pkt_stream_default ;
527531 }
532+
533+ if (test -> ifobj_rx -> pkt_stream != test -> pkt_stream_default &&
534+ test -> ifobj_rx -> pkt_stream != tx_pkt_stream )
535+ pkt_stream_delete (test -> ifobj_rx -> pkt_stream );
528536 test -> ifobj_rx -> pkt_stream = test -> pkt_stream_default ;
529537}
530538
@@ -546,6 +554,16 @@ static struct pkt_stream *__pkt_stream_alloc(u32 nb_pkts)
546554 return pkt_stream ;
547555}
548556
557+ static void pkt_set (struct xsk_umem_info * umem , struct pkt * pkt , u64 addr , u32 len )
558+ {
559+ pkt -> addr = addr ;
560+ pkt -> len = len ;
561+ if (len > umem -> frame_size - XDP_PACKET_HEADROOM - MIN_PKT_SIZE * 2 - umem -> frame_headroom )
562+ pkt -> valid = false;
563+ else
564+ pkt -> valid = true;
565+ }
566+
549567static struct pkt_stream * pkt_stream_generate (struct xsk_umem_info * umem , u32 nb_pkts , u32 pkt_len )
550568{
551569 struct pkt_stream * pkt_stream ;
@@ -557,14 +575,9 @@ static struct pkt_stream *pkt_stream_generate(struct xsk_umem_info *umem, u32 nb
557575
558576 pkt_stream -> nb_pkts = nb_pkts ;
559577 for (i = 0 ; i < nb_pkts ; i ++ ) {
560- pkt_stream -> pkts [i ]. addr = (i % umem -> num_frames ) * umem -> frame_size ;
561- pkt_stream -> pkts [ i ]. len = pkt_len ;
578+ pkt_set ( umem , & pkt_stream -> pkts [i ], (i % umem -> num_frames ) * umem -> frame_size ,
579+ pkt_len ) ;
562580 pkt_stream -> pkts [i ].payload = i ;
563-
564- if (pkt_len > umem -> frame_size )
565- pkt_stream -> pkts [i ].valid = false;
566- else
567- pkt_stream -> pkts [i ].valid = true;
568581 }
569582
570583 return pkt_stream ;
@@ -592,15 +605,27 @@ static void pkt_stream_replace_half(struct test_spec *test, u32 pkt_len, int off
592605 u32 i ;
593606
594607 pkt_stream = pkt_stream_clone (umem , test -> pkt_stream_default );
595- for (i = 1 ; i < test -> pkt_stream_default -> nb_pkts ; i += 2 ) {
596- pkt_stream -> pkts [i ].addr = (i % umem -> num_frames ) * umem -> frame_size + offset ;
597- pkt_stream -> pkts [i ].len = pkt_len ;
598- }
608+ for (i = 1 ; i < test -> pkt_stream_default -> nb_pkts ; i += 2 )
609+ pkt_set (umem , & pkt_stream -> pkts [i ],
610+ (i % umem -> num_frames ) * umem -> frame_size + offset , pkt_len );
599611
600612 test -> ifobj_tx -> pkt_stream = pkt_stream ;
601613 test -> ifobj_rx -> pkt_stream = pkt_stream ;
602614}
603615
616+ static void pkt_stream_receive_half (struct test_spec * test )
617+ {
618+ struct xsk_umem_info * umem = test -> ifobj_rx -> umem ;
619+ struct pkt_stream * pkt_stream = test -> ifobj_tx -> pkt_stream ;
620+ u32 i ;
621+
622+ test -> ifobj_rx -> pkt_stream = pkt_stream_generate (umem , pkt_stream -> nb_pkts ,
623+ pkt_stream -> pkts [0 ].len );
624+ pkt_stream = test -> ifobj_rx -> pkt_stream ;
625+ for (i = 1 ; i < pkt_stream -> nb_pkts ; i += 2 )
626+ pkt_stream -> pkts [i ].valid = false;
627+ }
628+
604629static struct pkt * pkt_generate (struct ifobject * ifobject , u32 pkt_nb )
605630{
606631 struct pkt * pkt = pkt_stream_get_pkt (ifobject -> pkt_stream , pkt_nb );
@@ -795,18 +820,19 @@ static int complete_pkts(struct xsk_socket_info *xsk, int batch_size)
795820static int receive_pkts (struct ifobject * ifobj , struct pollfd * fds )
796821{
797822 struct timeval tv_end , tv_now , tv_timeout = {RECV_TMOUT , 0 };
823+ u32 idx_rx = 0 , idx_fq = 0 , rcvd , i , pkts_sent = 0 ;
798824 struct pkt_stream * pkt_stream = ifobj -> pkt_stream ;
799- struct pkt * pkt = pkt_stream_get_next_rx_pkt (pkt_stream );
800825 struct xsk_socket_info * xsk = ifobj -> xsk ;
801826 struct xsk_umem_info * umem = xsk -> umem ;
802- u32 idx_rx = 0 , idx_fq = 0 , rcvd , i ;
827+ struct pkt * pkt ;
803828 int ret ;
804829
805830 ret = gettimeofday (& tv_now , NULL );
806831 if (ret )
807832 exit_with_error (errno );
808833 timeradd (& tv_now , & tv_timeout , & tv_end );
809834
835+ pkt = pkt_stream_get_next_rx_pkt (pkt_stream , & pkts_sent );
810836 while (pkt ) {
811837 ret = gettimeofday (& tv_now , NULL );
812838 if (ret )
@@ -828,49 +854,47 @@ static int receive_pkts(struct ifobject *ifobj, struct pollfd *fds)
828854 continue ;
829855 }
830856
831- ret = xsk_ring_prod__reserve (& umem -> fq , rcvd , & idx_fq );
832- while (ret != rcvd ) {
833- if (ret < 0 )
834- exit_with_error (- ret );
835- if (xsk_ring_prod__needs_wakeup (& umem -> fq )) {
836- ret = poll (fds , 1 , POLL_TMOUT );
857+ if (ifobj -> use_fill_ring ) {
858+ ret = xsk_ring_prod__reserve (& umem -> fq , rcvd , & idx_fq );
859+ while (ret != rcvd ) {
837860 if (ret < 0 )
838861 exit_with_error (- ret );
862+ if (xsk_ring_prod__needs_wakeup (& umem -> fq )) {
863+ ret = poll (fds , 1 , POLL_TMOUT );
864+ if (ret < 0 )
865+ exit_with_error (- ret );
866+ }
867+ ret = xsk_ring_prod__reserve (& umem -> fq , rcvd , & idx_fq );
839868 }
840- ret = xsk_ring_prod__reserve (& umem -> fq , rcvd , & idx_fq );
841869 }
842870
843871 for (i = 0 ; i < rcvd ; i ++ ) {
844872 const struct xdp_desc * desc = xsk_ring_cons__rx_desc (& xsk -> rx , idx_rx ++ );
845873 u64 addr = desc -> addr , orig ;
846874
847- if (!pkt ) {
848- ksft_print_msg ("[%s] Received too many packets.\n" ,
849- __func__ );
850- ksft_print_msg ("Last packet has addr: %llx len: %u\n" ,
851- addr , desc -> len );
852- return TEST_FAILURE ;
853- }
854-
855875 orig = xsk_umem__extract_addr (addr );
856876 addr = xsk_umem__add_offset_to_addr (addr );
857877
858878 if (!is_pkt_valid (pkt , umem -> buffer , addr , desc -> len ) ||
859879 !is_offset_correct (umem , pkt_stream , addr , pkt -> addr ))
860880 return TEST_FAILURE ;
861881
862- * xsk_ring_prod__fill_addr (& umem -> fq , idx_fq ++ ) = orig ;
863- pkt = pkt_stream_get_next_rx_pkt (pkt_stream );
882+ if (ifobj -> use_fill_ring )
883+ * xsk_ring_prod__fill_addr (& umem -> fq , idx_fq ++ ) = orig ;
884+ pkt = pkt_stream_get_next_rx_pkt (pkt_stream , & pkts_sent );
864885 }
865886
866- xsk_ring_prod__submit (& umem -> fq , rcvd );
867- xsk_ring_cons__release (& xsk -> rx , rcvd );
887+ if (ifobj -> use_fill_ring )
888+ xsk_ring_prod__submit (& umem -> fq , rcvd );
889+ if (ifobj -> release_rx )
890+ xsk_ring_cons__release (& xsk -> rx , rcvd );
868891
869892 pthread_mutex_lock (& pacing_mutex );
870- pkts_in_flight -= rcvd ;
893+ pkts_in_flight -= pkts_sent ;
871894 if (pkts_in_flight < umem -> num_frames )
872895 pthread_cond_signal (& pacing_cond );
873896 pthread_mutex_unlock (& pacing_mutex );
897+ pkts_sent = 0 ;
874898 }
875899
876900 return TEST_PASS ;
@@ -900,7 +924,8 @@ static int __send_pkts(struct ifobject *ifobject, u32 *pkt_nb)
900924
901925 pthread_mutex_lock (& pacing_mutex );
902926 pkts_in_flight += valid_pkts ;
903- if (ifobject -> pacing_on && pkts_in_flight >= ifobject -> umem -> num_frames - BATCH_SIZE ) {
927+ /* pkts_in_flight might be negative if many invalid packets are sent */
928+ if (pkts_in_flight >= (int )(ifobject -> umem -> num_frames - BATCH_SIZE )) {
904929 kick_tx (xsk );
905930 pthread_cond_wait (& pacing_cond , & pacing_mutex );
906931 }
@@ -987,34 +1012,29 @@ static int validate_rx_dropped(struct ifobject *ifobject)
9871012 if (err )
9881013 return TEST_FAILURE ;
9891014
990- if (stats .rx_dropped == ifobject -> pkt_stream -> nb_pkts )
1015+ if (stats .rx_dropped == ifobject -> pkt_stream -> nb_pkts / 2 )
9911016 return TEST_PASS ;
9921017
993- return TEST_CONTINUE ;
1018+ return TEST_FAILURE ;
9941019}
9951020
9961021static int validate_rx_full (struct ifobject * ifobject )
9971022{
9981023 struct xsk_socket * xsk = ifobject -> xsk -> xsk ;
9991024 struct xdp_statistics stats ;
1000- u32 expected_stat ;
10011025 int err ;
10021026
1027+ usleep (1000 );
10031028 kick_rx (ifobject -> xsk );
10041029
10051030 err = get_xsk_stats (xsk , & stats );
10061031 if (err )
10071032 return TEST_FAILURE ;
10081033
1009- if (ifobject -> umem -> num_frames < XSK_RING_PROD__DEFAULT_NUM_DESCS )
1010- expected_stat = ifobject -> umem -> num_frames - RX_FULL_RXQSIZE ;
1011- else
1012- expected_stat = XSK_RING_PROD__DEFAULT_NUM_DESCS - RX_FULL_RXQSIZE ;
1013-
1014- if (stats .rx_ring_full == expected_stat )
1034+ if (stats .rx_ring_full )
10151035 return TEST_PASS ;
10161036
1017- return TEST_CONTINUE ;
1037+ return TEST_FAILURE ;
10181038}
10191039
10201040static int validate_fill_empty (struct ifobject * ifobject )
@@ -1023,16 +1043,17 @@ static int validate_fill_empty(struct ifobject *ifobject)
10231043 struct xdp_statistics stats ;
10241044 int err ;
10251045
1046+ usleep (1000 );
10261047 kick_rx (ifobject -> xsk );
10271048
10281049 err = get_xsk_stats (xsk , & stats );
10291050 if (err )
10301051 return TEST_FAILURE ;
10311052
1032- if (stats .rx_fill_ring_empty_descs == ifobject -> pkt_stream -> nb_pkts )
1053+ if (stats .rx_fill_ring_empty_descs )
10331054 return TEST_PASS ;
10341055
1035- return TEST_CONTINUE ;
1056+ return TEST_FAILURE ;
10361057}
10371058
10381059static int validate_tx_invalid_descs (struct ifobject * ifobject )
@@ -1051,7 +1072,7 @@ static int validate_tx_invalid_descs(struct ifobject *ifobject)
10511072 return TEST_FAILURE ;
10521073 }
10531074
1054- if (stats .tx_invalid_descs != ifobject -> pkt_stream -> nb_pkts ) {
1075+ if (stats .tx_invalid_descs != ifobject -> pkt_stream -> nb_pkts / 2 ) {
10551076 ksft_print_msg ("[%s] tx_invalid_descs incorrect. Got [%u] expected [%u]\n" ,
10561077 __func__ , stats .tx_invalid_descs , ifobject -> pkt_stream -> nb_pkts );
10571078 return TEST_FAILURE ;
@@ -1138,17 +1159,12 @@ static void *worker_testapp_validate_tx(void *arg)
11381159 print_verbose ("Sending %d packets on interface %s\n" , ifobject -> pkt_stream -> nb_pkts ,
11391160 ifobject -> ifname );
11401161 err = send_pkts (test , ifobject );
1141- if (err ) {
1142- report_failure (test );
1143- goto out ;
1144- }
11451162
1146- if (ifobject -> validation_func ) {
1163+ if (! err && ifobject -> validation_func )
11471164 err = ifobject -> validation_func (ifobject );
1165+ if (err )
11481166 report_failure (test );
1149- }
11501167
1151- out :
11521168 if (test -> total_steps == test -> current_step || err )
11531169 testapp_cleanup_xsk_res (ifobject );
11541170 pthread_exit (NULL );
@@ -1202,14 +1218,10 @@ static void *worker_testapp_validate_rx(void *arg)
12021218
12031219 pthread_barrier_wait (& barr );
12041220
1205- if (ifobject -> validation_func ) {
1206- do {
1207- err = ifobject -> validation_func (ifobject );
1208- } while (err == TEST_CONTINUE );
1209- } else {
1210- err = receive_pkts (ifobject , & fds );
1211- }
1221+ err = receive_pkts (ifobject , & fds );
12121222
1223+ if (!err && ifobject -> validation_func )
1224+ err = ifobject -> validation_func (ifobject );
12131225 if (err ) {
12141226 report_failure (test );
12151227 pthread_mutex_lock (& pacing_mutex );
@@ -1327,18 +1339,18 @@ static void testapp_headroom(struct test_spec *test)
13271339static void testapp_stats_rx_dropped (struct test_spec * test )
13281340{
13291341 test_spec_set_name (test , "STAT_RX_DROPPED" );
1330- test -> ifobj_tx -> pacing_on = false;
13311342 test -> ifobj_rx -> umem -> frame_headroom = test -> ifobj_rx -> umem -> frame_size -
1332- XDP_PACKET_HEADROOM - 1 ;
1343+ XDP_PACKET_HEADROOM - MIN_PKT_SIZE * 3 ;
1344+ pkt_stream_replace_half (test , MIN_PKT_SIZE * 4 , 0 );
1345+ pkt_stream_receive_half (test );
13331346 test -> ifobj_rx -> validation_func = validate_rx_dropped ;
13341347 testapp_validate_traffic (test );
13351348}
13361349
13371350static void testapp_stats_tx_invalid_descs (struct test_spec * test )
13381351{
13391352 test_spec_set_name (test , "STAT_TX_INVALID" );
1340- test -> ifobj_tx -> pacing_on = false;
1341- pkt_stream_replace (test , DEFAULT_PKT_CNT , XSK_UMEM__INVALID_FRAME_SIZE );
1353+ pkt_stream_replace_half (test , XSK_UMEM__INVALID_FRAME_SIZE , 0 );
13421354 test -> ifobj_tx -> validation_func = validate_tx_invalid_descs ;
13431355 testapp_validate_traffic (test );
13441356
@@ -1348,20 +1360,30 @@ static void testapp_stats_tx_invalid_descs(struct test_spec *test)
13481360static void testapp_stats_rx_full (struct test_spec * test )
13491361{
13501362 test_spec_set_name (test , "STAT_RX_FULL" );
1351- test -> ifobj_tx -> pacing_on = false;
1352- test -> ifobj_rx -> xsk -> rxqsize = RX_FULL_RXQSIZE ;
1363+ pkt_stream_replace (test , DEFAULT_UMEM_BUFFERS + DEFAULT_UMEM_BUFFERS / 2 , PKT_SIZE );
1364+ test -> ifobj_rx -> pkt_stream = pkt_stream_generate (test -> ifobj_rx -> umem ,
1365+ DEFAULT_UMEM_BUFFERS , PKT_SIZE );
1366+ if (!test -> ifobj_rx -> pkt_stream )
1367+ exit_with_error (ENOMEM );
1368+
1369+ test -> ifobj_rx -> xsk -> rxqsize = DEFAULT_UMEM_BUFFERS ;
1370+ test -> ifobj_rx -> release_rx = false;
13531371 test -> ifobj_rx -> validation_func = validate_rx_full ;
13541372 testapp_validate_traffic (test );
1373+
1374+ pkt_stream_restore_default (test );
13551375}
13561376
13571377static void testapp_stats_fill_empty (struct test_spec * test )
13581378{
13591379 test_spec_set_name (test , "STAT_RX_FILL_EMPTY" );
1360- test -> ifobj_tx -> pacing_on = false;
1361- test -> ifobj_rx -> pkt_stream = pkt_stream_generate (test -> ifobj_rx -> umem , 0 , MIN_PKT_SIZE );
1380+ pkt_stream_replace (test , DEFAULT_UMEM_BUFFERS + DEFAULT_UMEM_BUFFERS / 2 , PKT_SIZE );
1381+ test -> ifobj_rx -> pkt_stream = pkt_stream_generate (test -> ifobj_rx -> umem ,
1382+ DEFAULT_UMEM_BUFFERS , PKT_SIZE );
13621383 if (!test -> ifobj_rx -> pkt_stream )
13631384 exit_with_error (ENOMEM );
1364- test -> ifobj_rx -> pkt_stream -> use_addr_for_fill = true;
1385+
1386+ test -> ifobj_rx -> use_fill_ring = false;
13651387 test -> ifobj_rx -> validation_func = validate_fill_empty ;
13661388 testapp_validate_traffic (test );
13671389
@@ -1504,7 +1526,7 @@ static void run_pkt_test(struct test_spec *test, enum test_mode mode, enum test_
15041526 test_spec_set_name (test , "RUN_TO_COMPLETION_2K_FRAME_SIZE" );
15051527 test -> ifobj_tx -> umem -> frame_size = 2048 ;
15061528 test -> ifobj_rx -> umem -> frame_size = 2048 ;
1507- pkt_stream_replace (test , DEFAULT_PKT_CNT , MIN_PKT_SIZE );
1529+ pkt_stream_replace (test , DEFAULT_PKT_CNT , PKT_SIZE );
15081530 testapp_validate_traffic (test );
15091531
15101532 pkt_stream_restore_default (test );
0 commit comments