@@ -133,30 +133,6 @@ pub fn tx_loop<T: AsRef<[u8]>, A: AsRef<[SocketAddr]>>(
133133 // packets.
134134 let mut batched_packets = 0 ;
135135
136- // With some drivers, or always when we work in SKB mode, we need to explicitly kick the driver
137- // once we want the NIC to do something.
138- let kick = |ring : & TxRing < SliceUmemFrame < ' _ > > | {
139- if !ring. needs_wakeup ( ) {
140- return ;
141- }
142-
143- if let Err ( e) = ring. wake ( ) {
144- match e. raw_os_error ( ) {
145- // these are non-fatal errors
146- Some ( libc:: EBUSY | libc:: ENOBUFS | libc:: EAGAIN ) => { }
147- // this can temporarily happen with some drivers when changing
148- // settings (eg with ethtool)
149- Some ( libc:: ENETDOWN ) => {
150- log:: warn!( "network interface is down" )
151- }
152- // we should never get here, hopefully the driver recovers?
153- _ => {
154- log:: error!( "network interface driver error: {e:?}" ) ;
155- }
156- }
157- }
158- } ;
159-
160136 let mut timeouts = 0 ;
161137 loop {
162138 match receiver. try_recv ( ) {
@@ -193,25 +169,27 @@ pub fn tx_loop<T: AsRef<[u8]>, A: AsRef<[SocketAddr]>>(
193169
194170 for ( addrs, payload) in batched_items. drain ( ..) {
195171 for addr in addrs. as_ref ( ) {
196- // loop until we have space for the next packet
197- loop {
198- completion. sync ( true ) ;
199- // we haven't written any frames so we only need to sync the consumer position
200- ring. sync ( false ) ;
201-
202- // check if any frames were completed
203- while let Some ( frame_offset) = completion. read ( ) {
204- umem. release ( frame_offset) ;
172+ if ring. available ( ) == 0 || umem. available ( ) == 0 {
173+ // loop until we have space for the next packet
174+ loop {
175+ completion. sync ( true ) ;
176+ // we haven't written any frames so we only need to sync the consumer position
177+ ring. sync ( false ) ;
178+
179+ // check if any frames were completed
180+ while let Some ( frame_offset) = completion. read ( ) {
181+ umem. release ( frame_offset) ;
182+ }
183+
184+ if ring. available ( ) > 0 && umem. available ( ) > 0 {
185+ // we have space for the next packet, break out of the loop
186+ break ;
187+ }
188+
189+ // queues are full, if NEEDS_WAKEUP is set kick the driver so hopefully it'll
190+ // complete some work
191+ kick ( & ring) ;
205192 }
206-
207- if ring. available ( ) > 0 && umem. available ( ) > 0 {
208- // we have a frame and a slot in the ring
209- break ;
210- }
211-
212- // queues are full, if NEEDS_WAKEUP is set kick the driver so hopefully it'll
213- // complete some work
214- kick ( & ring) ;
215193 }
216194
217195 // at this point we're guaranteed to have a frame to write the next packet into and
@@ -325,3 +303,33 @@ pub fn tx_loop<T: AsRef<[u8]>, A: AsRef<[SocketAddr]>>(
325303 kick ( & ring) ;
326304 }
327305}
306+
307+ // With some drivers, or always when we work in SKB mode, we need to explicitly kick the driver once
308+ // we want the NIC to do something.
309+ #[ inline( always) ]
310+ fn kick ( ring : & TxRing < SliceUmemFrame < ' _ > > ) {
311+ if !ring. needs_wakeup ( ) {
312+ return ;
313+ }
314+
315+ if let Err ( e) = ring. wake ( ) {
316+ kick_error ( e) ;
317+ }
318+ }
319+
320+ #[ inline( never) ]
321+ fn kick_error ( e : std:: io:: Error ) {
322+ match e. raw_os_error ( ) {
323+ // these are non-fatal errors
324+ Some ( libc:: EBUSY | libc:: ENOBUFS | libc:: EAGAIN ) => { }
325+ // this can temporarily happen with some drivers when changing
326+ // settings (eg with ethtool)
327+ Some ( libc:: ENETDOWN ) => {
328+ log:: warn!( "network interface is down" )
329+ }
330+ // we should never get here, hopefully the driver recovers?
331+ _ => {
332+ log:: error!( "network interface driver error: {e:?}" ) ;
333+ }
334+ }
335+ }
0 commit comments