@@ -397,27 +397,19 @@ net_check_gre_interface_exists( fd_net_ctx_t * ctx ) {
397397}
398398
399399
400- /* net_tx_ready returns 1 if the current XSK is ready to submit a TX send
401- job. If the XSK is blocked for sends, returns 0. Reasons for block
402- include:
403- - No XSK TX buffer is available
404- - XSK TX ring is full */
400+ /* net_tx_ready returns 1 if we can submit a job to this TX ring, and 0 otherwise.
401+ Reasons for block include:
402+ - No TX buffer is available (free ring empty)
403+ - TX ring is full
404+
405+ tx_ring: pointer to the XDP TX ring
406+ free_ring: pointer to the free TX ring */
405407
406408static int
407- net_tx_ready ( fd_net_ctx_t * ctx ,
408- uint xsk_idx ) {
409- fd_xsk_t * xsk = & ctx -> xsk [ xsk_idx ];
410- fd_xdp_ring_t * tx_ring = & xsk -> ring_tx ;
411- fd_net_free_ring_t * free = & ctx -> free_tx ;
412- if ( free -> prod == free -> cons ) return 0 ; /* drop */
413-
414- /* If potentially stale cached_cons says there is space,
415- there is definitely space */
416- if ( tx_ring -> cached_prod - tx_ring -> cached_cons >= tx_ring -> depth ) return 1 ;
417-
418- /* read the fseq, and update our cache */
419- tx_ring -> cached_cons = FD_VOLATILE_CONST ( * tx_ring -> cons );
420- if ( tx_ring -> cached_prod - tx_ring -> cached_cons >= tx_ring -> depth ) return 0 ; /* drop */
409+ net_tx_ready ( fd_xdp_ring_t * tx_ring ,
410+ fd_net_free_ring_t * free_ring ) {
411+ if ( FD_UNLIKELY ( free_ring -> prod == free_ring -> cons ) ) return 0 ; /* drop - no free buffers */
412+ if ( FD_UNLIKELY ( fd_xdp_ring_full ( tx_ring ) ) ) return 0 ; /* drop - tx ring full */
421413 return 1 ;
422414}
423415
@@ -483,17 +475,7 @@ net_tx_periodic_wakeup( fd_net_ctx_t * ctx,
483475 long now ,
484476 int * charge_busy ) {
485477 fd_xdp_ring_t * tx_ring = & ctx -> xsk [ xsk_idx ].ring_tx ;
486- uint tx_prod = tx_ring -> cached_prod ;
487- uint tx_cons = tx_ring -> cached_cons ;
488-
489- int tx_ring_empty = tx_prod == tx_cons ;
490- /* If we already think tx_ring_empty, it's definitely empty.
491- But if not, we should update our view of what kernel has consumed. */
492- if ( FD_LIKELY ( !tx_ring_empty ) ) {
493- tx_cons = tx_ring -> cached_cons = FD_VOLATILE_CONST ( * tx_ring -> cons );
494- tx_ring_empty = tx_prod == tx_cons ;
495- }
496-
478+ int tx_ring_empty = fd_xdp_ring_empty ( tx_ring , FD_XDP_RING_ROLE_PROD );
497479 if ( fd_net_flusher_check ( ctx -> tx_flusher + xsk_idx , now , tx_ring_empty ) ) {
498480 net_tx_wakeup ( ctx , & ctx -> xsk [ xsk_idx ], charge_busy );
499481 fd_net_flusher_wakeup ( ctx -> tx_flusher + xsk_idx , now );
@@ -712,14 +694,14 @@ before_frag( fd_net_ctx_t * ctx,
712694
713695 /* Skip if TX is blocked */
714696
715- if ( FD_UNLIKELY ( !net_tx_ready ( ctx , xsk_idx ) ) ) {
697+ fd_xsk_t * xsk = & ctx -> xsk [ xsk_idx ];
698+ fd_net_free_ring_t * free = & ctx -> free_tx ;
699+ if ( FD_UNLIKELY ( !net_tx_ready ( & xsk -> ring_tx , free ) ) ) {
716700 ctx -> metrics .tx_full_fail_cnt ++ ;
717701 return 1 ;
718702 }
719703
720704 /* Allocate buffer for receive */
721-
722- fd_net_free_ring_t * free = & ctx -> free_tx ;
723705 ulong alloc_seq = free -> cons ;
724706 void * frame = (void * )free -> queue [ alloc_seq % free -> depth ];
725707 free -> cons = fd_seq_inc ( alloc_seq , 1UL );
@@ -1057,6 +1039,7 @@ net_comp_event( fd_net_ctx_t * ctx,
10571039 uint comp_mask = comp_ring -> depth - 1U ;
10581040 ulong frame = FD_VOLATILE_CONST ( comp_ring -> frame_ring [ comp_seq & comp_mask ] );
10591041 ulong const frame_mask = FD_NET_MTU - 1UL ;
1042+ FD_STATIC_ASSERT ( FD_ULONG_IS_POW2 ( FD_NET_MTU ), "FD_NET_MTU must be a power of two" );
10601043 if ( FD_UNLIKELY ( frame + FD_NET_MTU > ctx -> umem_sz ) ) {
10611044 FD_LOG_ERR (( "Bounds check failed: frame=0x%lx umem_sz=0x%lx" ,
10621045 frame , (ulong )ctx -> umem_sz ));
@@ -1101,28 +1084,15 @@ net_rx_event( fd_net_ctx_t * ctx,
11011084 /* Check if we have space in the fill ring to free the frame */
11021085
11031086 fd_xdp_ring_t * fill_ring = & xsk -> ring_fr ;
1104- uint fill_depth = fill_ring -> depth ;
1105- uint fill_mask = fill_depth - 1U ;
1106- ulong frame_mask = FD_NET_MTU - 1UL ;
1107- uint fill_prod = fill_ring -> cached_prod ;
1108- uint fill_cons = fill_ring -> cached_cons ;
1109-
1110- /* If cached_cons suggests there may not be space in the fill ring,
1111- refresh from fseq and check again. Else, skip the fseq access */
1112-
1113- if ( FD_UNLIKELY ( fill_prod - fill_cons >= fill_depth ) ) {
1114- fill_cons = fill_ring -> cached_cons = FD_VOLATILE_CONST ( * fill_ring -> cons );
1115- if ( FD_UNLIKELY ( fill_prod - fill_cons >= fill_depth ) ) {
1116- ctx -> metrics .rx_fill_blocked_cnt ++ ;
1117- return ; /* blocked */
1118- }
1087+ if ( FD_UNLIKELY ( fd_xdp_ring_full ( fill_ring ) ) ) {
1088+ ctx -> metrics .rx_fill_blocked_cnt ++ ;
1089+ return ; /* blocked */
11191090 }
11201091
11211092 /* Pass it to the receive handler */
11221093
11231094 uint freed_chunk = (uint )( ctx -> umem_chunk0 + (frame .addr >>FD_CHUNK_LG_SZ ) );
11241095 net_rx_packet ( ctx , frame .addr , frame .len , & freed_chunk );
1125-
11261096 FD_COMPILER_MFENCE ();
11271097 rx_ring -> cached_cons = rx_seq + 1U ;
11281098
@@ -1135,7 +1105,12 @@ net_rx_event( fd_net_ctx_t * ctx,
11351105 FD_LOG_CRIT (( "mcache corruption detected: chunk=%u chunk0=%u wmark=%u" ,
11361106 freed_chunk , ctx -> umem_chunk0 , ctx -> umem_wmark ));
11371107 }
1138- ulong freed_off = (freed_chunk - ctx -> umem_chunk0 )<<FD_CHUNK_LG_SZ ;
1108+
1109+ FD_STATIC_ASSERT ( FD_ULONG_IS_POW2 ( FD_NET_MTU ), "FD_NET_MTU must be a power of two" );
1110+ uint fill_prod = fill_ring -> cached_prod ;
1111+ uint fill_mask = (fill_ring -> depth )- 1U ;
1112+ ulong frame_mask = FD_NET_MTU - 1UL ;
1113+ ulong freed_off = (freed_chunk - ctx -> umem_chunk0 )<<FD_CHUNK_LG_SZ ;
11391114 fill_ring -> frame_ring [ fill_prod & fill_mask ] = freed_off & (~frame_mask );
11401115 fill_ring -> cached_prod = fill_prod + 1U ;
11411116}
@@ -1168,31 +1143,20 @@ before_credit( fd_net_ctx_t * ctx,
11681143
11691144 net_tx_periodic_wakeup ( ctx , rr_idx , fd_tickcount (), charge_busy );
11701145
1171- uint rx_cons = rr_xsk -> ring_rx .cached_cons ;
1172- uint rx_prod = rr_xsk -> ring_rx .cached_prod ; /* might be stale */
1173- if ( FD_UNLIKELY ( rx_cons == rx_prod ) ) {
1174- rx_prod = rr_xsk -> ring_rx .cached_prod = FD_VOLATILE_CONST ( * rr_xsk -> ring_rx .prod );
1175- }
1176-
1177- if ( rx_cons != rx_prod ) {
1146+ /* Fire RX event if we have RX desc avail */
1147+ if ( !fd_xdp_ring_empty ( & rr_xsk -> ring_rx , FD_XDP_RING_ROLE_CONS ) ) {
11781148 * charge_busy = 1 ;
1179- net_rx_event ( ctx , rr_xsk , rx_cons );
1149+ net_rx_event ( ctx , rr_xsk , rr_xsk -> ring_rx . cached_cons );
11801150 } else {
11811151 net_rx_wakeup ( ctx , rr_xsk , charge_busy );
11821152 ctx -> rr_idx ++ ;
11831153 ctx -> rr_idx = fd_uint_if ( ctx -> rr_idx >=ctx -> xsk_cnt , 0 , ctx -> rr_idx );
11841154 }
11851155
1186- uint comp_cons = rr_xsk -> ring_cr .cached_cons ;
1187- uint comp_prod = rr_xsk -> ring_cr .cached_prod ; /* might be stale */
1188- if ( FD_UNLIKELY ( comp_cons == comp_prod ) ) {
1189- comp_prod = rr_xsk -> ring_cr .cached_prod = FD_VOLATILE_CONST ( * rr_xsk -> ring_cr .prod );
1190- }
1191-
1192- if ( comp_cons != comp_prod ) {
1156+ /* Fire comp event if we have comp desc avail */
1157+ if ( !fd_xdp_ring_empty ( & rr_xsk -> ring_cr , FD_XDP_RING_ROLE_CONS ) ) {
11931158 * charge_busy = 1 ;
1194- rr_xsk -> ring_cr .cached_prod = comp_prod ;
1195- net_comp_event ( ctx , rr_xsk , comp_cons );
1159+ net_comp_event ( ctx , rr_xsk , rr_xsk -> ring_cr .cached_cons );
11961160 }
11971161}
11981162
0 commit comments