Subject: Re: [PATCH net-next] net: introduce netdevice gso_min_segs attribute

From: Amir Vadai <[email-masked]>
Date: Mon, 6 Oct 2014 09:41:31 +0300

On 10/5/2014 8:11 PM, Eric Dumazet wrote:
> From: Eric Dumazet <[email-masked]>
> 
> Some TSO engines might have a too heavy setup cost, that impacts
> performance on hosts sending small bursts (2 MSS per packet).
> 
> This patch adds a device gso_min_segs, allowing drivers to set
> a minimum segment size for TSO packets, according to the NIC
> performance.
> 
> Tested on a mlx4 NIC, this allows to get a ~110% increase of
> throughput when sending 2 MSS per packet.
> 

Amazing!

Shouldn't there be a netif_set_gso_min_size() too?

> Signed-off-by: Eric Dumazet <[email-masked]>
> ---
> mlx4 patch will be sent later, its a one liner.
> 
>  include/linux/netdevice.h |    4 +++-
>  net/core/dev.c            |    9 ++++++---
>  2 files changed, 9 insertions(+), 4 deletions(-)
> 
> diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
> index 22d54b9b700d..2df86f50261c 100644
> --- a/include/linux/netdevice.h
> +++ b/include/linux/netdevice.h
> @@ -1416,6 +1416,8 @@ enum netdev_priv_flags {
>   *	@gso_max_size:	Maximum size of generic segmentation offload
>   *	@gso_max_segs:	Maximum number of segments that can be passed to the
>   *			NIC for GSO
> + *	@gso_min_segs:	Minimum number of segments that can be passed to the
> + *			NIC for GSO
>   *
>   *	@dcbnl_ops:	Data Center Bridging netlink ops
>   *	@num_tc:	Number of traffic classes in the net device
> @@ -1666,7 +1668,7 @@ struct net_device {
>  	unsigned int		gso_max_size;
>  #define GSO_MAX_SEGS		65535
>  	u16			gso_max_segs;
> -
> +	u16			gso_min_segs;
>  #ifdef CONFIG_DCB
>  	const struct dcbnl_rtnl_ops *dcbnl_ops;
>  #endif
> diff --git a/net/core/dev.c b/net/core/dev.c
> index 1a90530f83ff..16e8ebbd3316 100644
> --- a/net/core/dev.c
> +++ b/net/core/dev.c
> @@ -2567,10 +2567,12 @@ static netdev_features_t harmonize_features(struct sk_buff *skb,
>  
>  netdev_features_t netif_skb_features(struct sk_buff *skb)
>  {
> +	const struct net_device *dev = skb->dev;
> +	netdev_features_t features = dev->features;
> +	u16 gso_segs = skb_shinfo(skb)->gso_segs;
>  	__be16 protocol = skb->protocol;
> -	netdev_features_t features = skb->dev->features;
>  
> -	if (skb_shinfo(skb)->gso_segs > skb->dev->gso_max_segs)
> +	if (gso_segs > dev->gso_max_segs || gso_segs < dev->gso_min_segs)
>  		features &= ~NETIF_F_GSO_MASK;
>  
>  	if (protocol == htons(ETH_P_8021Q) || protocol == htons(ETH_P_8021AD)) {
> @@ -2581,7 +2583,7 @@ netdev_features_t netif_skb_features(struct sk_buff *skb)
>  	}
>  
>  	features = netdev_intersect_features(features,
> -					     skb->dev->vlan_features |
> +					     dev->vlan_features |
>  					     NETIF_F_HW_VLAN_CTAG_TX |
>  					     NETIF_F_HW_VLAN_STAG_TX);
>  
> @@ -6658,6 +6660,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
>  
>  	dev->gso_max_size = GSO_MAX_SIZE;
>  	dev->gso_max_segs = GSO_MAX_SEGS;
> +	dev->gso_min_segs = 0;
>  
>  	INIT_LIST_HEAD(&dev->napi_list);
>  	INIT_LIST_HEAD(&dev->unreg_list);
> 
>