@@ -147,11 +147,19 @@ const LINK_DELAY_DURATION: Duration = Duration::from_secs(5);
147
147
#[ cfg( test) ]
148
148
const LINK_DELAY_DURATION : Duration = Duration :: from_millis ( 333 ) ;
149
149
150
- #[ derive( PartialEq ) ]
151
- enum CoordinatorMessage {
150
+ #[ derive( Default , PartialEq ) ]
151
+ struct CoordinatorMessageUpdateType {
152
152
/// Update guest VF state based on current availability and the guest VF state tracked by the primary channel.
153
153
/// This includes adding the guest VF device and switching the data path.
154
- UpdateGuestVfState ,
154
+ guest_vf_state : bool ,
155
+ /// Update the receive filter for all channels.
156
+ filter_state : bool ,
157
+ }
158
+
159
+ #[ derive( PartialEq ) ]
160
+ enum CoordinatorMessage {
161
+ /// Update network state.
162
+ Update ( CoordinatorMessageUpdateType ) ,
155
163
/// Restart endpoints and resume processing. This will also attempt to set VF and data path state to match current
156
164
/// expectations.
157
165
Restart ,
@@ -382,6 +390,7 @@ struct NetChannel<T: RingMem> {
382
390
pending_send_size : usize ,
383
391
restart : Option < CoordinatorMessage > ,
384
392
can_use_ring_size_opt : bool ,
393
+ packet_filter : u32 ,
385
394
}
386
395
387
396
/// Buffers used during packet processing.
@@ -1364,6 +1373,7 @@ impl Nic {
1364
1373
pending_send_size : 0 ,
1365
1374
restart : None ,
1366
1375
can_use_ring_size_opt,
1376
+ packet_filter : rndisprot:: NDIS_PACKET_TYPE_NONE ,
1367
1377
} ,
1368
1378
state,
1369
1379
coordinator_send : self . coordinator_send . clone ( ) . unwrap ( ) ,
@@ -1453,6 +1463,7 @@ impl Nic {
1453
1463
mut control : RestoreControl < ' _ > ,
1454
1464
state : saved_state:: SavedState ,
1455
1465
) -> Result < ( ) , NetRestoreError > {
1466
+ let mut saved_packet_filter = 0u32 ;
1456
1467
if let Some ( state) = state. open {
1457
1468
let open = match & state. primary {
1458
1469
saved_state:: Primary :: Version => vec ! [ true ] ,
@@ -1537,8 +1548,12 @@ impl Nic {
1537
1548
tx_spread_sent,
1538
1549
guest_link_down,
1539
1550
pending_link_action,
1551
+ packet_filter,
1540
1552
} = ready;
1541
1553
1554
+ // If saved state does not have a packet filter set, default to directed, multicast, and broadcast.
1555
+ saved_packet_filter = packet_filter. unwrap_or ( rndisprot:: NPROTO_PACKET_FILTER ) ;
1556
+
1542
1557
let version = check_version ( version)
1543
1558
. ok_or ( NetRestoreError :: UnsupportedVersion ( version) ) ?;
1544
1559
@@ -1621,6 +1636,11 @@ impl Nic {
1621
1636
self . insert_worker ( channel_idx as u16 , & request. unwrap ( ) , state, false ) ?;
1622
1637
}
1623
1638
}
1639
+ for worker in self . coordinator . state_mut ( ) . unwrap ( ) . workers . iter_mut ( ) {
1640
+ if let Some ( worker_state) = worker. state_mut ( ) {
1641
+ worker_state. channel . packet_filter = saved_packet_filter;
1642
+ }
1643
+ }
1624
1644
} else {
1625
1645
control
1626
1646
. restore ( & [ false ] )
@@ -1782,6 +1802,11 @@ impl Nic {
1782
1802
PrimaryChannelGuestVfState :: Restoring ( saved_state) => saved_state,
1783
1803
} ;
1784
1804
1805
+ let worker_0_packet_filter = coordinator. workers [ 0 ]
1806
+ . state ( )
1807
+ . unwrap ( )
1808
+ . channel
1809
+ . packet_filter ;
1785
1810
saved_state:: Primary :: Ready ( saved_state:: ReadyPrimary {
1786
1811
version : ready. buffers . version as u32 ,
1787
1812
receive_buffer : ready. buffers . recv_buffer . saved_state ( ) ,
@@ -1811,6 +1836,7 @@ impl Nic {
1811
1836
tx_spread_sent : primary. tx_spread_sent ,
1812
1837
guest_link_down : !primary. guest_link_up ,
1813
1838
pending_link_action,
1839
+ packet_filter : Some ( worker_0_packet_filter) ,
1814
1840
} )
1815
1841
}
1816
1842
} ;
@@ -2594,7 +2620,12 @@ impl<T: RingMem> NetChannel<T> {
2594
2620
if primary. rndis_state == RndisState :: Operational {
2595
2621
if self . guest_vf_is_available ( Some ( vfid) , buffers. version , buffers. ndis_config ) ? {
2596
2622
primary. guest_vf_state = PrimaryChannelGuestVfState :: AvailableAdvertised ;
2597
- return Ok ( Some ( CoordinatorMessage :: UpdateGuestVfState ) ) ;
2623
+ return Ok ( Some ( CoordinatorMessage :: Update (
2624
+ CoordinatorMessageUpdateType {
2625
+ guest_vf_state : true ,
2626
+ ..Default :: default ( )
2627
+ } ,
2628
+ ) ) ) ;
2598
2629
} else if let Some ( true ) = primary. is_data_path_switched {
2599
2630
tracing:: error!(
2600
2631
"Data path switched, but current guest negotiation does not support VTL0 VF"
@@ -2734,10 +2765,7 @@ impl<T: RingMem> NetChannel<T> {
2734
2765
// flag on inband packets and won't send a completion
2735
2766
// packet.
2736
2767
primary. guest_vf_state = PrimaryChannelGuestVfState :: AvailableAdvertised ;
2737
- // restart will also add the VF based on the guest_vf_state
2738
- if self . restart . is_none ( ) {
2739
- self . restart = Some ( CoordinatorMessage :: UpdateGuestVfState ) ;
2740
- }
2768
+ self . send_coordinator_update_vf ( ) ;
2741
2769
} else if let Some ( true ) = primary. is_data_path_switched {
2742
2770
tracing:: error!(
2743
2771
"Data path switched, but current guest negotiation does not support VTL0 VF"
@@ -2785,12 +2813,18 @@ impl<T: RingMem> NetChannel<T> {
2785
2813
tracing:: trace!( ?request, "handling control message MESSAGE_TYPE_SET_MSG" ) ;
2786
2814
2787
2815
let status = match self . adapter . handle_oid_set ( primary, request. oid , reader) {
2788
- Ok ( restart_endpoint) => {
2816
+ Ok ( ( restart_endpoint, packet_filter ) ) => {
2789
2817
// Restart the endpoint if the OID changed some critical
2790
2818
// endpoint property.
2791
2819
if restart_endpoint {
2792
2820
self . restart = Some ( CoordinatorMessage :: Restart ) ;
2793
2821
}
2822
+ if let Some ( filter) = packet_filter {
2823
+ if self . packet_filter != filter {
2824
+ self . packet_filter = filter;
2825
+ self . send_coordinator_update_filter ( ) ;
2826
+ }
2827
+ }
2794
2828
rndisprot:: STATUS_SUCCESS
2795
2829
}
2796
2830
Err ( err) => {
@@ -2974,6 +3008,31 @@ impl<T: RingMem> NetChannel<T> {
2974
3008
}
2975
3009
Ok ( ( ) )
2976
3010
}
3011
+
3012
+ fn send_coordinator_update_message ( & mut self , guest_vf : bool , packet_filter : bool ) {
3013
+ if self . restart . is_none ( ) {
3014
+ self . restart = Some ( CoordinatorMessage :: Update ( CoordinatorMessageUpdateType {
3015
+ guest_vf_state : guest_vf,
3016
+ filter_state : packet_filter,
3017
+ } ) ) ;
3018
+ } else if let Some ( CoordinatorMessage :: Restart ) = self . restart {
3019
+ // If a restart message is pending, do nothing.
3020
+ // A restart will try to switch the data path based on primary.guest_vf_state.
3021
+ // A restart will apply packet filter changes.
3022
+ } else if let Some ( CoordinatorMessage :: Update ( ref mut update) ) = self . restart {
3023
+ // Add the new update to the existing message.
3024
+ update. guest_vf_state |= guest_vf;
3025
+ update. filter_state |= packet_filter;
3026
+ }
3027
+ }
3028
+
3029
+ fn send_coordinator_update_vf ( & mut self ) {
3030
+ self . send_coordinator_update_message ( true , false ) ;
3031
+ }
3032
+
3033
+ fn send_coordinator_update_filter ( & mut self ) {
3034
+ self . send_coordinator_update_message ( false , true ) ;
3035
+ }
2977
3036
}
2978
3037
2979
3038
/// Writes an RNDIS message to `writer`.
@@ -3291,13 +3350,14 @@ impl Adapter {
3291
3350
primary : & mut PrimaryChannelState ,
3292
3351
oid : rndisprot:: Oid ,
3293
3352
reader : impl MemoryRead + Clone ,
3294
- ) -> Result < bool , OidError > {
3353
+ ) -> Result < ( bool , Option < u32 > ) , OidError > {
3295
3354
tracing:: debug!( ?oid, "oid set" ) ;
3296
3355
3297
3356
let mut restart_endpoint = false ;
3357
+ let mut packet_filter = None ;
3298
3358
match oid {
3299
3359
rndisprot:: Oid :: OID_GEN_CURRENT_PACKET_FILTER => {
3300
- // TODO
3360
+ packet_filter = self . oid_set_packet_filter ( reader ) ? ;
3301
3361
}
3302
3362
rndisprot:: Oid :: OID_TCP_OFFLOAD_PARAMETERS => {
3303
3363
self . oid_set_offload_parameters ( reader, primary) ?;
@@ -3324,7 +3384,7 @@ impl Adapter {
3324
3384
return Err ( OidError :: UnknownOid ) ;
3325
3385
}
3326
3386
}
3327
- Ok ( restart_endpoint)
3387
+ Ok ( ( restart_endpoint, packet_filter ) )
3328
3388
}
3329
3389
3330
3390
fn oid_set_rss_parameters (
@@ -3382,6 +3442,15 @@ impl Adapter {
3382
3442
Ok ( ( ) )
3383
3443
}
3384
3444
3445
+ fn oid_set_packet_filter (
3446
+ & self ,
3447
+ reader : impl MemoryRead + Clone ,
3448
+ ) -> Result < Option < u32 > , OidError > {
3449
+ let filter: rndisprot:: RndisPacketFilterOidValue = reader. clone ( ) . read_plain ( ) ?;
3450
+ tracing:: debug!( filter, "set packet filter" ) ;
3451
+ Ok ( Some ( filter) )
3452
+ }
3453
+
3385
3454
fn oid_set_offload_parameters (
3386
3455
& self ,
3387
3456
reader : impl MemoryRead + Clone ,
@@ -3872,8 +3941,26 @@ impl Coordinator {
3872
3941
}
3873
3942
sleep_duration = None ;
3874
3943
}
3875
- Message :: Internal ( CoordinatorMessage :: UpdateGuestVfState ) => {
3876
- self . update_guest_vf_state ( state) . await ;
3944
+ Message :: Internal ( CoordinatorMessage :: Update ( update_type) ) => {
3945
+ if update_type. filter_state {
3946
+ self . stop_workers ( ) . await ;
3947
+ let worker_0_packet_filter =
3948
+ self . workers [ 0 ] . state ( ) . unwrap ( ) . channel . packet_filter ;
3949
+ self . workers . iter_mut ( ) . skip ( 1 ) . for_each ( |worker| {
3950
+ if let Some ( state) = worker. state_mut ( ) {
3951
+ state. channel . packet_filter = worker_0_packet_filter;
3952
+ tracing:: debug!(
3953
+ packet_filter = ?worker_0_packet_filter,
3954
+ channel_idx = state. channel_idx,
3955
+ "update packet filter"
3956
+ ) ;
3957
+ }
3958
+ } ) ;
3959
+ }
3960
+
3961
+ if update_type. guest_vf_state {
3962
+ self . update_guest_vf_state ( state) . await ;
3963
+ }
3877
3964
}
3878
3965
Message :: UpdateFromEndpoint ( EndpointAction :: RestartRequired ) => self . restart = true ,
3879
3966
Message :: UpdateFromEndpoint ( EndpointAction :: LinkStatusNotify ( connect) ) => {
@@ -4306,13 +4393,18 @@ impl Coordinator {
4306
4393
self . num_queues = num_queues;
4307
4394
}
4308
4395
4396
+ let worker_0_packet_filter = self . workers [ 0 ] . state ( ) . unwrap ( ) . channel . packet_filter ;
4309
4397
// Provide the queue and receive buffer ranges for each worker.
4310
4398
for ( ( worker, queue) , rx_buffer) in self . workers . iter_mut ( ) . zip ( queues) . zip ( rx_buffers) {
4311
4399
worker. task_mut ( ) . queue_state = Some ( QueueState {
4312
4400
queue,
4313
4401
target_vp_set : false ,
4314
4402
rx_buffer_range : rx_buffer,
4315
4403
} ) ;
4404
+ // Update the receive packet filter for the subchannel worker.
4405
+ if let Some ( worker) = worker. state_mut ( ) {
4406
+ worker. channel . packet_filter = worker_0_packet_filter;
4407
+ }
4316
4408
}
4317
4409
4318
4410
Ok ( ( ) )
@@ -4920,6 +5012,13 @@ impl<T: 'static + RingMem> NetChannel<T> {
4920
5012
data : & mut ProcessingData ,
4921
5013
epqueue : & mut dyn net_backend:: Queue ,
4922
5014
) -> Result < bool , WorkerError > {
5015
+ if self . packet_filter == rndisprot:: NDIS_PACKET_TYPE_NONE {
5016
+ tracing:: trace!(
5017
+ packet_filter = self . packet_filter,
5018
+ "rx packet not processed"
5019
+ ) ;
5020
+ return Ok ( false ) ;
5021
+ }
4923
5022
let n = epqueue
4924
5023
. rx_poll ( & mut data. rx_ready )
4925
5024
. map_err ( WorkerError :: Endpoint ) ?;
@@ -5062,10 +5161,7 @@ impl<T: 'static + RingMem> NetChannel<T> {
5062
5161
_ => ( ) ,
5063
5162
} ;
5064
5163
if queue_switch_operation {
5065
- // A restart will also try to switch the data path based on primary.guest_vf_state.
5066
- if self . restart . is_none ( ) {
5067
- self . restart = Some ( CoordinatorMessage :: UpdateGuestVfState )
5068
- } ;
5164
+ self . send_coordinator_update_vf ( ) ;
5069
5165
} else {
5070
5166
self . send_completion ( transaction_id, & [ ] ) ?;
5071
5167
}
0 commit comments