@@ -23,8 +23,10 @@ use vm_memory::GuestMemoryError;
23
23
use crate :: devices:: virtio:: device:: { DeviceState , IrqTrigger , IrqType , VirtioDevice } ;
24
24
use crate :: devices:: virtio:: gen:: virtio_blk:: VIRTIO_F_VERSION_1 ;
25
25
use crate :: devices:: virtio:: gen:: virtio_net:: {
26
- virtio_net_hdr_v1, VIRTIO_NET_F_CSUM , VIRTIO_NET_F_GUEST_CSUM , VIRTIO_NET_F_GUEST_TSO4 ,
27
- VIRTIO_NET_F_GUEST_UFO , VIRTIO_NET_F_HOST_TSO4 , VIRTIO_NET_F_HOST_UFO , VIRTIO_NET_F_MAC ,
26
+ virtio_net_hdr_v1, VIRTIO_NET_F_CSUM , VIRTIO_NET_F_GUEST_CSUM , VIRTIO_NET_F_GUEST_ECN ,
27
+ VIRTIO_NET_F_GUEST_TSO4 , VIRTIO_NET_F_GUEST_TSO6 , VIRTIO_NET_F_GUEST_UFO ,
28
+ VIRTIO_NET_F_HOST_ECN , VIRTIO_NET_F_HOST_TSO4 , VIRTIO_NET_F_HOST_TSO6 , VIRTIO_NET_F_HOST_UFO ,
29
+ VIRTIO_NET_F_MAC ,
28
30
} ;
29
31
use crate :: devices:: virtio:: gen:: virtio_ring:: VIRTIO_RING_F_EVENT_IDX ;
30
32
use crate :: devices:: virtio:: iovec:: IoVecBuffer ;
@@ -160,7 +162,11 @@ impl Net {
160
162
| 1 << VIRTIO_NET_F_HOST_TSO4
161
163
| 1 << VIRTIO_NET_F_HOST_UFO
162
164
| 1 << VIRTIO_F_VERSION_1
163
- | 1 << VIRTIO_RING_F_EVENT_IDX ;
165
+ | 1 << VIRTIO_RING_F_EVENT_IDX
166
+ | 1 << VIRTIO_NET_F_GUEST_TSO6
167
+ | 1 << VIRTIO_NET_F_HOST_TSO6
168
+ | 1 << VIRTIO_NET_F_GUEST_ECN
169
+ | 1 << VIRTIO_NET_F_HOST_ECN ;
164
170
165
171
let mut config_space = ConfigSpace :: default ( ) ;
166
172
if let Some ( mac) = guest_mac {
@@ -210,10 +216,6 @@ impl Net {
210
216
) -> Result < Self , NetError > {
211
217
let tap = Tap :: open_named ( tap_if_name) . map_err ( NetError :: TapOpen ) ?;
212
218
213
- // Set offload flags to match the virtio features below.
214
- tap. set_offload ( gen:: TUN_F_CSUM | gen:: TUN_F_UFO | gen:: TUN_F_TSO4 | gen:: TUN_F_TSO6 )
215
- . map_err ( NetError :: TapSetOffload ) ?;
216
-
217
219
let vnet_hdr_size = i32:: try_from ( vnet_hdr_len ( ) ) . unwrap ( ) ;
218
220
tap. set_vnet_hdr_size ( vnet_hdr_size)
219
221
. map_err ( NetError :: TapSetVnetHdrSize ) ?;
@@ -644,6 +646,44 @@ impl Net {
644
646
}
645
647
}
646
648
649
+ fn build_tap_supported_features ( virtio_supported_features : u64 ) -> u32 {
650
+ let add_if_supported =
651
+ |tap_features : & mut u32 , virtio_features : u64 , tap_flag : u32 , virtio_flag : u32 | {
652
+ if virtio_features & ( 1 << virtio_flag) != 0 {
653
+ * tap_features |= tap_flag;
654
+ }
655
+ } ;
656
+
657
+ let mut tap_features: u32 = 0 ;
658
+
659
+ add_if_supported (
660
+ & mut tap_features,
661
+ virtio_supported_features,
662
+ gen:: TUN_F_CSUM ,
663
+ VIRTIO_NET_F_CSUM ,
664
+ ) ;
665
+ add_if_supported (
666
+ & mut tap_features,
667
+ virtio_supported_features,
668
+ gen:: TUN_F_UFO ,
669
+ VIRTIO_NET_F_GUEST_UFO ,
670
+ ) ;
671
+ add_if_supported (
672
+ & mut tap_features,
673
+ virtio_supported_features,
674
+ gen:: TUN_F_TSO4 ,
675
+ VIRTIO_NET_F_GUEST_TSO4 ,
676
+ ) ;
677
+ add_if_supported (
678
+ & mut tap_features,
679
+ virtio_supported_features,
680
+ gen:: TUN_F_TSO6 ,
681
+ VIRTIO_NET_F_GUEST_TSO6 ,
682
+ ) ;
683
+
684
+ tap_features
685
+ }
686
+
647
687
/// Updates the parameters for the rate limiters
648
688
pub fn patch_rate_limiters (
649
689
& mut self ,
@@ -859,6 +899,11 @@ impl VirtioDevice for Net {
859
899
}
860
900
}
861
901
902
+ let supported_flags: u32 = Net :: build_tap_supported_features ( self . acked_features ) ;
903
+ self . tap
904
+ . set_offload ( supported_flags)
905
+ . map_err ( super :: super :: ActivateError :: TapSetOffload ) ?;
906
+
862
907
if self . activate_evt . write ( 1 ) . is_err ( ) {
863
908
error ! ( "Net: Cannot write to activate_evt" ) ;
864
909
return Err ( super :: super :: ActivateError :: BadActivate ) ;
@@ -978,7 +1023,11 @@ pub mod tests {
978
1023
| 1 << VIRTIO_NET_F_HOST_TSO4
979
1024
| 1 << VIRTIO_NET_F_HOST_UFO
980
1025
| 1 << VIRTIO_F_VERSION_1
981
- | 1 << VIRTIO_RING_F_EVENT_IDX ;
1026
+ | 1 << VIRTIO_RING_F_EVENT_IDX
1027
+ | 1 << VIRTIO_NET_F_GUEST_TSO6
1028
+ | 1 << VIRTIO_NET_F_HOST_TSO6
1029
+ | 1 << VIRTIO_NET_F_GUEST_ECN
1030
+ | 1 << VIRTIO_NET_F_HOST_ECN ;
982
1031
983
1032
assert_eq ! (
984
1033
net. avail_features_by_page( 0 ) ,
@@ -996,6 +1045,37 @@ pub mod tests {
996
1045
assert_eq ! ( net. acked_features, features) ;
997
1046
}
998
1047
1048
+ #[ test]
1049
+ // We can't get offload features, that were set up to a TAP device by ioctl,
1050
+ // hence that we have to validate, that we sort out unsupported features correctly
1051
+ fn test_build_tap_supported_features_all ( ) {
1052
+ let supported_features = 1 << VIRTIO_NET_F_CSUM
1053
+ | 1 << VIRTIO_NET_F_GUEST_UFO
1054
+ | 1 << VIRTIO_NET_F_GUEST_TSO4
1055
+ | 1 << VIRTIO_NET_F_GUEST_TSO6 ;
1056
+
1057
+ let expected_tap_features =
1058
+ gen:: TUN_F_CSUM | gen:: TUN_F_UFO | gen:: TUN_F_TSO4 | gen:: TUN_F_TSO6 ;
1059
+
1060
+ let supported_flags = Net :: build_tap_supported_features ( supported_features) ;
1061
+
1062
+ assert_eq ! ( supported_flags, expected_tap_features) ;
1063
+ }
1064
+
1065
+ #[ test]
1066
+ fn test_build_tap_supported_features_one_by_one ( ) {
1067
+ let features = [
1068
+ ( 1 << VIRTIO_NET_F_CSUM , gen:: TUN_F_CSUM ) ,
1069
+ ( 1 << VIRTIO_NET_F_GUEST_UFO , gen:: TUN_F_UFO ) ,
1070
+ ( 1 << VIRTIO_NET_F_GUEST_TSO4 , gen:: TUN_F_TSO4 ) ,
1071
+ ( 1 << VIRTIO_NET_F_GUEST_TSO6 , gen:: TUN_F_TSO6 ) ,
1072
+ ] ;
1073
+ for ( virtio_flag, tap_flag) in features {
1074
+ let supported_flags = Net :: build_tap_supported_features ( virtio_flag) ;
1075
+ assert_eq ! ( supported_flags, tap_flag) ;
1076
+ }
1077
+ }
1078
+
999
1079
#[ test]
1000
1080
fn test_virtio_device_read_config ( ) {
1001
1081
let mut net = default_net ( ) ;
0 commit comments