@ -65,6 +65,9 @@ static struct cdev macvtap_cdev;
static const struct proto_ops macvtap_socket_ops ;
# define TUN_OFFLOADS (NETIF_F_HW_CSUM | NETIF_F_TSO_ECN | NETIF_F_TSO | \
NETIF_F_TSO6 | NETIF_F_UFO )
# define RX_OFFLOADS (NETIF_F_GRO | NETIF_F_LRO)
/*
* RCU usage :
* The macvtap_queue and the macvlan_dev are loosely coupled , the
@ -349,6 +352,11 @@ static int macvtap_newlink(struct net *src_net,
struct macvlan_dev * vlan = netdev_priv ( dev ) ;
INIT_LIST_HEAD ( & vlan - > queue_list ) ;
/* Since macvlan supports all offloads by default, make
* tap support all offloads also .
*/
vlan - > tap_features = TUN_OFFLOADS ;
/* Don't put anything that may fail after macvlan_common_newlink
* because we can ' t undo what it does .
*/
@ -958,6 +966,58 @@ static int macvtap_ioctl_set_queue(struct file *file, unsigned int flags)
return ret ;
}
static int set_offload ( struct macvtap_queue * q , unsigned long arg )
{
struct macvlan_dev * vlan ;
netdev_features_t features ;
netdev_features_t feature_mask = 0 ;
vlan = rtnl_dereference ( q - > vlan ) ;
if ( ! vlan )
return - ENOLINK ;
features = vlan - > dev - > features ;
if ( arg & TUN_F_CSUM ) {
feature_mask = NETIF_F_HW_CSUM ;
if ( arg & ( TUN_F_TSO4 | TUN_F_TSO6 ) ) {
if ( arg & TUN_F_TSO_ECN )
feature_mask | = NETIF_F_TSO_ECN ;
if ( arg & TUN_F_TSO4 )
feature_mask | = NETIF_F_TSO ;
if ( arg & TUN_F_TSO6 )
feature_mask | = NETIF_F_TSO6 ;
}
if ( arg & TUN_F_UFO )
feature_mask | = NETIF_F_UFO ;
}
/* tun/tap driver inverts the usage for TSO offloads, where
* setting the TSO bit means that the userspace wants to
* accept TSO frames and turning it off means that user space
* does not support TSO .
* For macvtap , we have to invert it to mean the same thing .
* When user space turns off TSO , we turn off GSO / LRO so that
* user - space will not receive TSO frames .
*/
if ( feature_mask & ( NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_UFO ) )
features | = RX_OFFLOADS ;
else
features & = ~ RX_OFFLOADS ;
/* tap_features are the same as features on tun/tap and
* reflect user expectations .
*/
vlan - > tap_features = vlan - > dev - > features &
( feature_mask | ~ TUN_OFFLOADS ) ;
vlan - > set_features = features ;
netdev_update_features ( vlan - > dev ) ;
return 0 ;
}
/*
* provide compatibility with generic tun / tap interface
*/
@ -1050,7 +1110,10 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd,
got enabled for forwarded frames */
if ( ! ( q - > flags & IFF_VNET_HDR ) )
return - EINVAL ;
return 0 ;
rtnl_lock ( ) ;
ret = set_offload ( q , arg ) ;
rtnl_unlock ( ) ;
return ret ;
default :
return - EINVAL ;