@@ -151,9 +151,6 @@ pub struct NetEpollHandler {
151
151
acked_features : u64 ,
152
152
mmds_ns : Option < MmdsNetworkStack > ,
153
153
guest_mac : Option < MacAddr > ,
154
- epoll_fd : RawFd ,
155
- rx_tap_listening : bool ,
156
- rx_tap_epoll_token : u64 ,
157
154
158
155
#[ cfg( test) ]
159
156
test_mutators : tests:: TestMutators ,
@@ -477,7 +474,7 @@ impl NetEpollHandler {
477
474
self . tx . queue . add_used ( & self . mem , head_index, 0 ) ;
478
475
raise_irq = true ;
479
476
}
480
-
477
+
481
478
if raise_irq {
482
479
self . signal_used_queue ( ) ?;
483
480
}
@@ -506,28 +503,6 @@ impl NetEpollHandler {
506
503
fn read_tap ( & mut self ) -> io:: Result < usize > {
507
504
self . tap . read ( & mut self . rx . frame_buf )
508
505
}
509
-
510
- fn register_tap_rx_listener ( & mut self ) -> std:: result:: Result < ( ) , std:: io:: Error > {
511
- epoll:: ctl (
512
- self . epoll_fd ,
513
- epoll:: ControlOptions :: EPOLL_CTL_ADD ,
514
- self . tap . as_raw_fd ( ) ,
515
- epoll:: Event :: new ( epoll:: Events :: EPOLLIN , self . rx_tap_epoll_token ) ,
516
- ) ?;
517
- self . rx_tap_listening = true ;
518
- Ok ( ( ) )
519
- }
520
-
521
- fn unregister_tap_rx_listener ( & mut self ) -> std:: result:: Result < ( ) , std:: io:: Error > {
522
- epoll:: ctl (
523
- self . epoll_fd ,
524
- epoll:: ControlOptions :: EPOLL_CTL_DEL ,
525
- self . tap . as_raw_fd ( ) ,
526
- epoll:: Event :: new ( epoll:: Events :: EPOLLIN , self . rx_tap_epoll_token ) ,
527
- ) ?;
528
- self . rx_tap_listening = false ;
529
- Ok ( ( ) )
530
- }
531
506
}
532
507
533
508
impl EpollHandler for NetEpollHandler {
@@ -547,10 +522,6 @@ impl EpollHandler for NetEpollHandler {
547
522
underlying : e,
548
523
} )
549
524
} else {
550
- if !self . rx_tap_listening {
551
- self . register_tap_rx_listener ( )
552
- . map_err ( DeviceError :: IoError ) ?;
553
- }
554
525
// If the limiter is not blocked, resume the receiving of bytes.
555
526
if !self . rx . rate_limiter . is_blocked ( ) {
556
527
// There should be a buffer available now to receive the frame into.
@@ -564,8 +535,6 @@ impl EpollHandler for NetEpollHandler {
564
535
METRICS . net . rx_tap_event_count . inc ( ) ;
565
536
566
537
if self . rx . queue . is_empty ( & self . mem ) {
567
- self . unregister_tap_rx_listener ( )
568
- . map_err ( DeviceError :: IoError ) ?;
569
538
return Err ( DeviceError :: NoAvailBuffers ) ;
570
539
}
571
540
@@ -827,6 +796,8 @@ impl VirtioDevice for Net {
827
796
} else {
828
797
None
829
798
} ;
799
+ let tap_fd = tap. as_raw_fd ( ) ;
800
+
830
801
let handler = NetEpollHandler {
831
802
rx : RxVirtio :: new (
832
803
rx_queue,
@@ -845,9 +816,6 @@ impl VirtioDevice for Net {
845
816
acked_features : self . acked_features ,
846
817
mmds_ns,
847
818
guest_mac : self . guest_mac ( ) ,
848
- epoll_fd : self . epoll_config . epoll_raw_fd ,
849
- rx_tap_listening : false ,
850
- rx_tap_epoll_token : self . epoll_config . rx_tap_token ,
851
819
852
820
#[ cfg( test) ]
853
821
test_mutators : tests:: TestMutators :: default ( ) ,
@@ -867,6 +835,20 @@ impl VirtioDevice for Net {
867
835
868
836
//TODO: barrier needed here maybe?
869
837
838
+ epoll:: ctl (
839
+ self . epoll_config . epoll_raw_fd ,
840
+ epoll:: ControlOptions :: EPOLL_CTL_ADD ,
841
+ tap_fd,
842
+ epoll:: Event :: new (
843
+ epoll:: Events :: EPOLLIN | epoll:: Events :: EPOLLET ,
844
+ self . epoll_config . rx_tap_token ,
845
+ ) ,
846
+ )
847
+ . map_err ( |e| {
848
+ METRICS . net . activate_fails . inc ( ) ;
849
+ ActivateError :: EpollCtl ( e)
850
+ } ) ?;
851
+
870
852
epoll:: ctl (
871
853
self . epoll_config . epoll_raw_fd ,
872
854
epoll:: ControlOptions :: EPOLL_CTL_ADD ,
@@ -1130,7 +1112,6 @@ mod tests {
1130
1112
let interrupt_evt = EventFd :: new ( libc:: EFD_NONBLOCK ) . unwrap ( ) ;
1131
1113
let rx_queue_evt = EventFd :: new ( libc:: EFD_NONBLOCK ) . unwrap ( ) ;
1132
1114
let tx_queue_evt = EventFd :: new ( libc:: EFD_NONBLOCK ) . unwrap ( ) ;
1133
- let epoll_fd = epoll:: create ( true ) . unwrap ( ) ;
1134
1115
1135
1116
(
1136
1117
NetEpollHandler {
@@ -1144,9 +1125,6 @@ mod tests {
1144
1125
mmds_ns : Some ( MmdsNetworkStack :: new_with_defaults ( ) ) ,
1145
1126
test_mutators,
1146
1127
guest_mac : None ,
1147
- epoll_fd,
1148
- rx_tap_epoll_token : 0 ,
1149
- rx_tap_listening : false ,
1150
1128
} ,
1151
1129
txq,
1152
1130
rxq,
@@ -1482,15 +1460,12 @@ mod tests {
1482
1460
} ;
1483
1461
let mem = GuestMemory :: new ( & [ ( GuestAddress ( 0 ) , 0x10000 ) ] ) . unwrap ( ) ;
1484
1462
let ( mut h, _txq, rxq) = default_test_netepollhandler ( & mem, test_mutators) ;
1485
- h. register_tap_rx_listener ( ) . unwrap ( ) ;
1486
1463
1487
1464
// The RX queue is empty.
1488
1465
match h. handle_event ( RX_TAP_EVENT , epoll:: Events :: EPOLLIN ) {
1489
1466
Err ( DeviceError :: NoAvailBuffers ) => ( ) ,
1490
1467
_ => panic ! ( "invalid" ) ,
1491
1468
}
1492
- // Since the RX was empty, we shouldn't be listening for tap RX events.
1493
- assert ! ( !h. rx_tap_listening) ;
1494
1469
1495
1470
// Fake an avail buffer; this time, tap reading should error out.
1496
1471
rxq. avail . idx . set ( 1 ) ;
@@ -1711,8 +1686,8 @@ mod tests {
1711
1686
}
1712
1687
1713
1688
// wait for 100ms to give the rate-limiter timer a chance to replenish
1714
- // wait for an extra 50ms to make sure the timerfd event makes its way from the kernel
1715
- thread:: sleep ( Duration :: from_millis ( 150 ) ) ;
1689
+ // wait for an extra 100ms to make sure the timerfd event makes its way from the kernel
1690
+ thread:: sleep ( Duration :: from_millis ( 200 ) ) ;
1716
1691
1717
1692
// following TX procedure should succeed because bandwidth should now be available
1718
1693
{
@@ -1762,8 +1737,8 @@ mod tests {
1762
1737
}
1763
1738
1764
1739
// wait for 100ms to give the rate-limiter timer a chance to replenish
1765
- // wait for an extra 50ms to make sure the timerfd event makes its way from the kernel
1766
- thread:: sleep ( Duration :: from_millis ( 150 ) ) ;
1740
+ // wait for an extra 100ms to make sure the timerfd event makes its way from the kernel
1741
+ thread:: sleep ( Duration :: from_millis ( 200 ) ) ;
1767
1742
1768
1743
// following RX procedure should succeed because bandwidth should now be available
1769
1744
{
@@ -1819,8 +1794,8 @@ mod tests {
1819
1794
}
1820
1795
1821
1796
// wait for 100ms to give the rate-limiter timer a chance to replenish
1822
- // wait for an extra 50ms to make sure the timerfd event makes its way from the kernel
1823
- thread:: sleep ( Duration :: from_millis ( 150 ) ) ;
1797
+ // wait for an extra 100ms to make sure the timerfd event makes its way from the kernel
1798
+ thread:: sleep ( Duration :: from_millis ( 200 ) ) ;
1824
1799
1825
1800
// following TX procedure should succeed because ops should now be available
1826
1801
{
@@ -1874,8 +1849,8 @@ mod tests {
1874
1849
}
1875
1850
1876
1851
// wait for 100ms to give the rate-limiter timer a chance to replenish
1877
- // wait for an extra 50ms to make sure the timerfd event makes its way from the kernel
1878
- thread:: sleep ( Duration :: from_millis ( 150 ) ) ;
1852
+ // wait for an extra 100ms to make sure the timerfd event makes its way from the kernel
1853
+ thread:: sleep ( Duration :: from_millis ( 200 ) ) ;
1879
1854
1880
1855
// following RX procedure should succeed because ops should now be available
1881
1856
{
@@ -1924,4 +1899,28 @@ mod tests {
1924
1899
compare_buckets ( h. get_tx_rate_limiter ( ) . bandwidth ( ) . unwrap ( ) , & tx_bytes) ;
1925
1900
compare_buckets ( h. get_tx_rate_limiter ( ) . ops ( ) . unwrap ( ) , & tx_ops) ;
1926
1901
}
1902
+
1903
+ #[ test]
1904
+ fn test_tx_queue_interrupt ( ) {
1905
+ // Regression test for https://github.com/firecracker-microvm/firecracker/issues/1436 .
1906
+ let mem = GuestMemory :: new ( & [ ( GuestAddress ( 0 ) , 0x10000 ) ] ) . unwrap ( ) ;
1907
+ let ( mut h, txq, _) = default_test_netepollhandler ( & mem, TestMutators :: default ( ) ) ;
1908
+
1909
+ let daddr = 0x2000 ;
1910
+ assert ! ( daddr > txq. end( ) . 0 ) ;
1911
+
1912
+ // Do some TX.
1913
+ txq. avail . idx . set ( 1 ) ;
1914
+ txq. avail . ring [ 0 ] . set ( 0 ) ;
1915
+ txq. dtable [ 0 ] . set ( daddr, 0x1000 , 0 , 0 ) ;
1916
+
1917
+ // trigger the TX handler
1918
+ h. tx . queue_evt . write ( 1 ) . unwrap ( ) ;
1919
+ h. handle_event ( TX_QUEUE_EVENT , EPOLLIN ) . unwrap ( ) ;
1920
+
1921
+ // Verify if TX queue was processed.
1922
+ assert_eq ! ( txq. used. idx. get( ) , 1 ) ;
1923
+ // Check if interrupt was triggered.
1924
+ assert_eq ! ( h. interrupt_evt. read( ) . unwrap( ) , 1 ) ;
1925
+ }
1927
1926
}
0 commit comments