Skip to content

Commit

Permalink
[NET]: Added GSO toggle
Browse files Browse the repository at this point in the history
This patch adds a generic segmentation offload toggle that can be turned
on/off for each net device.  For now it only supports in TCPv4.

Signed-off-by: Herbert Xu <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
herbertx authored and David S. Miller committed Jun 23, 2006
1 parent f4c50d9 commit 37c3185
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 6 deletions.
2 changes: 2 additions & 0 deletions include/linux/ethtool.h
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,8 @@ struct ethtool_ops {
#define ETHTOOL_GPERMADDR 0x00000020 /* Get permanent hardware address */
#define ETHTOOL_GUFO 0x00000021 /* Get UFO enable (ethtool_value) */
#define ETHTOOL_SUFO 0x00000022 /* Set UFO enable (ethtool_value) */
#define ETHTOOL_GGSO 0x00000023 /* Get GSO enable (ethtool_value) */
#define ETHTOOL_SGSO 0x00000024 /* Set GSO enable (ethtool_value) */

/* compatibility with older code */
#define SPARC_ETH_GSET ETHTOOL_GSET
Expand Down
1 change: 1 addition & 0 deletions include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@ struct net_device
#define NETIF_F_HW_VLAN_RX 256 /* Receive VLAN hw acceleration */
#define NETIF_F_HW_VLAN_FILTER 512 /* Receive filtering on VLAN */
#define NETIF_F_VLAN_CHALLENGED 1024 /* Device cannot handle VLAN packets */
#define NETIF_F_GSO 2048 /* Enable software GSO. */
#define NETIF_F_LLTX 4096 /* LockLess TX */

/* Segmentation offload features */
Expand Down
4 changes: 4 additions & 0 deletions include/net/sock.h
Original file line number Diff line number Diff line change
Expand Up @@ -1030,9 +1030,13 @@ static inline void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
{
__sk_dst_set(sk, dst);
sk->sk_route_caps = dst->dev->features;
if (sk->sk_route_caps & NETIF_F_GSO)
sk->sk_route_caps |= NETIF_F_TSO;
if (sk->sk_route_caps & NETIF_F_TSO) {
if (sock_flag(sk, SOCK_NO_LARGESEND) || dst->header_len)
sk->sk_route_caps &= ~NETIF_F_TSO;
else
sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM;
}
}

Expand Down
17 changes: 11 additions & 6 deletions net/bridge/br_if.c
Original file line number Diff line number Diff line change
Expand Up @@ -376,15 +376,20 @@ void br_features_recompute(struct net_bridge *br)
features = br->feature_mask & ~NETIF_F_ALL_CSUM;

list_for_each_entry(p, &br->port_list, list) {
if (checksum & NETIF_F_NO_CSUM &&
!(p->dev->features & NETIF_F_NO_CSUM))
unsigned long feature = p->dev->features;

if (checksum & NETIF_F_NO_CSUM && !(feature & NETIF_F_NO_CSUM))
checksum ^= NETIF_F_NO_CSUM | NETIF_F_HW_CSUM;
if (checksum & NETIF_F_HW_CSUM &&
!(p->dev->features & NETIF_F_HW_CSUM))
if (checksum & NETIF_F_HW_CSUM && !(feature & NETIF_F_HW_CSUM))
checksum ^= NETIF_F_HW_CSUM | NETIF_F_IP_CSUM;
if (!(p->dev->features & NETIF_F_IP_CSUM))
if (!(feature & NETIF_F_IP_CSUM))
checksum = 0;
features &= p->dev->features;

if (feature & NETIF_F_GSO)
feature |= NETIF_F_TSO;
feature |= NETIF_F_GSO;

features &= feature;
}

br->dev->features = features | checksum | NETIF_F_LLTX;
Expand Down
29 changes: 29 additions & 0 deletions net/core/ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,29 @@ static int ethtool_set_ufo(struct net_device *dev, char __user *useraddr)
return dev->ethtool_ops->set_ufo(dev, edata.data);
}

static int ethtool_get_gso(struct net_device *dev, char __user *useraddr)
{
struct ethtool_value edata = { ETHTOOL_GGSO };

edata.data = dev->features & NETIF_F_GSO;
if (copy_to_user(useraddr, &edata, sizeof(edata)))
return -EFAULT;
return 0;
}

static int ethtool_set_gso(struct net_device *dev, char __user *useraddr)
{
struct ethtool_value edata;

if (copy_from_user(&edata, useraddr, sizeof(edata)))
return -EFAULT;
if (edata.data)
dev->features |= NETIF_F_GSO;
else
dev->features &= ~NETIF_F_GSO;
return 0;
}

static int ethtool_self_test(struct net_device *dev, char __user *useraddr)
{
struct ethtool_test test;
Expand Down Expand Up @@ -905,6 +928,12 @@ int dev_ethtool(struct ifreq *ifr)
case ETHTOOL_SUFO:
rc = ethtool_set_ufo(dev, useraddr);
break;
case ETHTOOL_GGSO:
rc = ethtool_get_gso(dev, useraddr);
break;
case ETHTOOL_SGSO:
rc = ethtool_set_gso(dev, useraddr);
break;
default:
rc = -EOPNOTSUPP;
}
Expand Down

0 comments on commit 37c3185

Please sign in to comment.