Commit f01a5236 authored by Jesse Gross's avatar Jesse Gross Committed by David S. Miller

net offloading: Generalize netif_get_vlan_features().

netif_get_vlan_features() is currently only used by netif_needs_gso(),
so it only concerns itself with GSO features.  However, several other
places also should take into account the contents of the packet when
deciding whether to offload to hardware.  This generalizes the function
to return features about all of the various forms of offloading.  Since
offloads tend to be linked together, this avoids duplicating the logic
in each location (i.e. the scatter/gather code also needs the checksum
logic).
Suggested-by: default avatarMichał Mirosław <mirqus@gmail.com>
Signed-off-by: default avatarJesse Gross <jesse@nicira.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9497a051
...@@ -2303,7 +2303,7 @@ unsigned long netdev_fix_features(unsigned long features, const char *name); ...@@ -2303,7 +2303,7 @@ unsigned long netdev_fix_features(unsigned long features, const char *name);
void netif_stacked_transfer_operstate(const struct net_device *rootdev, void netif_stacked_transfer_operstate(const struct net_device *rootdev,
struct net_device *dev); struct net_device *dev);
int netif_get_vlan_features(struct sk_buff *skb, struct net_device *dev); int netif_skb_features(struct sk_buff *skb);
static inline int net_gso_ok(int features, int gso_type) static inline int net_gso_ok(int features, int gso_type)
{ {
...@@ -2320,7 +2320,7 @@ static inline int skb_gso_ok(struct sk_buff *skb, int features) ...@@ -2320,7 +2320,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) static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb)
{ {
if (skb_is_gso(skb)) { if (skb_is_gso(skb)) {
int features = netif_get_vlan_features(skb, dev); int features = netif_skb_features(skb);
return (!skb_gso_ok(skb, features) || return (!skb_gso_ok(skb, features) ||
unlikely(skb->ip_summed != CHECKSUM_PARTIAL)); unlikely(skb->ip_summed != CHECKSUM_PARTIAL));
......
...@@ -2017,22 +2017,41 @@ static inline void skb_orphan_try(struct sk_buff *skb) ...@@ -2017,22 +2017,41 @@ static inline void skb_orphan_try(struct sk_buff *skb)
} }
} }
int netif_get_vlan_features(struct sk_buff *skb, struct net_device *dev) static int harmonize_features(struct sk_buff *skb, __be16 protocol, int features)
{
if (!can_checksum_protocol(protocol, features)) {
features &= ~NETIF_F_ALL_CSUM;
features &= ~NETIF_F_SG;
} else if (illegal_highdma(skb->dev, skb)) {
features &= ~NETIF_F_SG;
}
return features;
}
int netif_skb_features(struct sk_buff *skb)
{ {
__be16 protocol = skb->protocol; __be16 protocol = skb->protocol;
int features = skb->dev->features;
if (protocol == htons(ETH_P_8021Q)) { if (protocol == htons(ETH_P_8021Q)) {
struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data;
protocol = veh->h_vlan_encapsulated_proto; protocol = veh->h_vlan_encapsulated_proto;
} else if (!skb->vlan_tci) } else if (!vlan_tx_tag_present(skb)) {
return dev->features; return harmonize_features(skb, protocol, features);
}
if (protocol != htons(ETH_P_8021Q)) features &= skb->dev->vlan_features;
return dev->features & dev->vlan_features;
else if (protocol != htons(ETH_P_8021Q)) {
return 0; return harmonize_features(skb, protocol, features);
} else {
features &= NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST |
NETIF_F_GEN_CSUM;
return harmonize_features(skb, protocol, features);
}
} }
EXPORT_SYMBOL(netif_get_vlan_features); EXPORT_SYMBOL(netif_skb_features);
/* /*
* Returns true if either: * Returns true if either:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment