@@ -454,6 +454,7 @@ struct QueueStats {
454
454
struct PendingTxCompletion {
455
455
transaction_id : u64 ,
456
456
tx_id : Option < TxId > ,
457
+ status : protocol:: Status ,
457
458
}
458
459
459
460
#[ derive( Clone , Copy ) ]
@@ -934,11 +935,14 @@ impl ActiveState {
934
935
// This shouldn't be referenced, but set it in case it is in the future.
935
936
active. pending_tx_packets [ id. 0 as usize ] . transaction_id = transaction_id;
936
937
}
938
+ // Save/Restore does not preserve the status of pending tx completions,
939
+ // completing any pending completions with 'success' to avoid making changes to saved_state.
937
940
active
938
941
. pending_tx_completions
939
942
. push_back ( PendingTxCompletion {
940
943
transaction_id,
941
944
tx_id,
945
+ status : protocol:: Status :: SUCCESS ,
942
946
} ) ;
943
947
}
944
948
Ok ( active)
@@ -4956,7 +4960,7 @@ impl<T: 'static + RingMem> NetChannel<T> {
4956
4960
assert ! ( tx_packet. pending_packet_count > 0 ) ;
4957
4961
tx_packet. pending_packet_count -= 1 ;
4958
4962
if tx_packet. pending_packet_count == 0 {
4959
- self . complete_tx_packet ( state, id) ?;
4963
+ self . complete_tx_packet ( state, id, protocol :: Status :: SUCCESS ) ?;
4960
4964
}
4961
4965
}
4962
4966
@@ -4974,6 +4978,7 @@ impl<T: 'static + RingMem> NetChannel<T> {
4974
4978
Some ( PendingTxCompletion {
4975
4979
transaction_id : inflight. transaction_id ,
4976
4980
tx_id : Some ( TxId ( id as u32 ) ) ,
4981
+ status : protocol:: Status :: SUCCESS ,
4977
4982
} )
4978
4983
} else {
4979
4984
None
@@ -5070,8 +5075,19 @@ impl<T: 'static + RingMem> NetChannel<T> {
5070
5075
PacketData :: RndisPacket ( _) => {
5071
5076
assert ! ( data. tx_segments. is_empty( ) ) ;
5072
5077
let id = state. free_tx_packets . pop ( ) . unwrap ( ) ;
5073
- let num_packets =
5074
- self . handle_rndis ( buffers, id, state, & packet, & mut data. tx_segments ) ?;
5078
+ let result: Result < usize , WorkerError > =
5079
+ self . handle_rndis ( buffers, id, state, & packet, & mut data. tx_segments ) ;
5080
+ let num_packets = match result {
5081
+ Ok ( num_packets) => num_packets,
5082
+ Err ( err) => {
5083
+ tracelimit:: error_ratelimited!(
5084
+ err = & err as & dyn std:: error:: Error ,
5085
+ "failed to handle RNDIS packet"
5086
+ ) ;
5087
+ self . complete_tx_packet ( state, id, protocol:: Status :: FAILURE ) ?;
5088
+ continue ;
5089
+ }
5090
+ } ;
5075
5091
total_packets += num_packets as u64 ;
5076
5092
state. pending_tx_packets [ id. 0 as usize ] . pending_packet_count += num_packets;
5077
5093
@@ -5082,7 +5098,7 @@ impl<T: 'static + RingMem> NetChannel<T> {
5082
5098
state. stats . tx_stalled . increment ( ) ;
5083
5099
}
5084
5100
} else {
5085
- self . complete_tx_packet ( state, id) ?;
5101
+ self . complete_tx_packet ( state, id, protocol :: Status :: SUCCESS ) ?;
5086
5102
}
5087
5103
}
5088
5104
PacketData :: RndisPacketComplete ( _completion) => {
@@ -5222,7 +5238,7 @@ impl<T: 'static + RingMem> NetChannel<T> {
5222
5238
}
5223
5239
5224
5240
if state. pending_tx_packets [ id. 0 as usize ] . pending_packet_count == 0 {
5225
- self . complete_tx_packet ( state, id) ?;
5241
+ self . complete_tx_packet ( state, id, protocol :: Status :: SUCCESS ) ?;
5226
5242
}
5227
5243
5228
5244
Ok ( packets_sent)
@@ -5276,12 +5292,14 @@ impl<T: 'static + RingMem> NetChannel<T> {
5276
5292
Ok ( num_packets)
5277
5293
}
5278
5294
5279
- fn try_send_tx_packet ( & mut self , transaction_id : u64 ) -> Result < bool , WorkerError > {
5295
+ fn try_send_tx_packet (
5296
+ & mut self ,
5297
+ transaction_id : u64 ,
5298
+ status : protocol:: Status ,
5299
+ ) -> Result < bool , WorkerError > {
5280
5300
let message = self . message (
5281
5301
protocol:: MESSAGE1_TYPE_SEND_RNDIS_PACKET_COMPLETE ,
5282
- protocol:: Message1SendRndisPacketComplete {
5283
- status : protocol:: Status :: SUCCESS ,
5284
- } ,
5302
+ protocol:: Message1SendRndisPacketComplete { status } ,
5285
5303
) ;
5286
5304
let result = self . queue . split ( ) . 1 . try_write ( & queue:: OutgoingPacket {
5287
5305
transaction_id,
@@ -5302,7 +5320,7 @@ impl<T: 'static + RingMem> NetChannel<T> {
5302
5320
fn send_pending_packets ( & mut self , state : & mut ActiveState ) -> Result < bool , WorkerError > {
5303
5321
let mut did_some_work = false ;
5304
5322
while let Some ( pending) = state. pending_tx_completions . front ( ) {
5305
- if !self . try_send_tx_packet ( pending. transaction_id ) ? {
5323
+ if !self . try_send_tx_packet ( pending. transaction_id , pending . status ) ? {
5306
5324
return Ok ( did_some_work) ;
5307
5325
}
5308
5326
did_some_work = true ;
@@ -5317,17 +5335,25 @@ impl<T: 'static + RingMem> NetChannel<T> {
5317
5335
Ok ( did_some_work)
5318
5336
}
5319
5337
5320
- fn complete_tx_packet ( & mut self , state : & mut ActiveState , id : TxId ) -> Result < ( ) , WorkerError > {
5338
+ fn complete_tx_packet (
5339
+ & mut self ,
5340
+ state : & mut ActiveState ,
5341
+ id : TxId ,
5342
+ status : protocol:: Status ,
5343
+ ) -> Result < ( ) , WorkerError > {
5321
5344
let tx_packet = & mut state. pending_tx_packets [ id. 0 as usize ] ;
5322
5345
assert_eq ! ( tx_packet. pending_packet_count, 0 ) ;
5323
- if self . pending_send_size == 0 && self . try_send_tx_packet ( tx_packet. transaction_id ) ? {
5346
+ if self . pending_send_size == 0
5347
+ && self . try_send_tx_packet ( tx_packet. transaction_id , status) ?
5348
+ {
5324
5349
tracing:: trace!( id = id. 0 , "sent tx completion" ) ;
5325
5350
state. free_tx_packets . push ( id) ;
5326
5351
} else {
5327
5352
tracing:: trace!( id = id. 0 , "pended tx completion" ) ;
5328
5353
state. pending_tx_completions . push_back ( PendingTxCompletion {
5329
5354
transaction_id : tx_packet. transaction_id ,
5330
5355
tx_id : Some ( id) ,
5356
+ status,
5331
5357
} ) ;
5332
5358
}
5333
5359
Ok ( ( ) )
0 commit comments