Skip to content

Commit

Permalink
offloading: Force software GSO for multiple vlan tags.
Browse files Browse the repository at this point in the history
We currently use vlan_features to check for TSO support if there is
a vlan tag.  However, it's quite likely that the NIC is not able to
do TSO when there is an arbitrary number of tags.  Therefore if there
is more than one tag (in-band or out-of-band), fall back to software
emulation.

Signed-off-by: Jesse Gross <[email protected]>
CC: Ben Hutchings <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
jessegross authored and davem330 committed Nov 15, 2010
1 parent c8d5bcd commit 58e998c
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 4 deletions.
7 changes: 3 additions & 4 deletions include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -2239,6 +2239,8 @@ unsigned long netdev_fix_features(unsigned long features, const char *name);
void netif_stacked_transfer_operstate(const struct net_device *rootdev,
struct net_device *dev);

int netif_get_vlan_features(struct sk_buff *skb, struct net_device *dev);

static inline int net_gso_ok(int features, int gso_type)
{
int feature = gso_type << NETIF_F_GSO_SHIFT;
Expand All @@ -2254,10 +2256,7 @@ static inline int skb_gso_ok(struct sk_buff *skb, int features)
static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb)
{
if (skb_is_gso(skb)) {
int features = dev->features;

if (skb->protocol == htons(ETH_P_8021Q) || skb->vlan_tci)
features &= dev->vlan_features;
int features = netif_get_vlan_features(skb, dev);

return (!skb_gso_ok(skb, features) ||
unlikely(skb->ip_summed != CHECKSUM_PARTIAL));
Expand Down
16 changes: 16 additions & 0 deletions net/core/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -1968,6 +1968,22 @@ static inline void skb_orphan_try(struct sk_buff *skb)
}
}

int netif_get_vlan_features(struct sk_buff *skb, struct net_device *dev)
{
__be16 protocol = skb->protocol;

if (protocol == htons(ETH_P_8021Q)) {
struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data;
protocol = veh->h_vlan_encapsulated_proto;
} else if (!skb->vlan_tci)
return dev->features;

if (protocol != htons(ETH_P_8021Q))
return dev->features & dev->vlan_features;
else
return 0;
}

/*
* Returns true if either:
* 1. skb has frag_list and the device doesn't support FRAGLIST, or
Expand Down

0 comments on commit 58e998c

Please sign in to comment.