aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Gross <jesse@nicira.com>2011-01-09 01:23:31 -0500
committerDavid S. Miller <davem@davemloft.net>2011-01-10 02:35:33 -0500
commitf01a5236bd4b140198fbcc550f085e8361fd73fa (patch)
tree01d122dcd3aa7e8e1f84f11f74f5c30593a5f850
parent9497a0518e8183959e45da05f317f1cb36f2cd7c (diff)
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: Michał Mirosław <mirqus@gmail.com> Signed-off-by: Jesse Gross <jesse@nicira.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/netdevice.h4
-rw-r--r--net/core/dev.c35
2 files changed, 29 insertions, 10 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 0f6b1c965815..d4dac09a5ad2 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2303,7 +2303,7 @@ unsigned long netdev_fix_features(unsigned long features, const char *name);
2303void netif_stacked_transfer_operstate(const struct net_device *rootdev, 2303void netif_stacked_transfer_operstate(const struct net_device *rootdev,
2304 struct net_device *dev); 2304 struct net_device *dev);
2305 2305
2306int netif_get_vlan_features(struct sk_buff *skb, struct net_device *dev); 2306int netif_skb_features(struct sk_buff *skb);
2307 2307
2308static inline int net_gso_ok(int features, int gso_type) 2308static inline int net_gso_ok(int features, int gso_type)
2309{ 2309{
@@ -2320,7 +2320,7 @@ static inline int skb_gso_ok(struct sk_buff *skb, int features)
2320static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb) 2320static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb)
2321{ 2321{
2322 if (skb_is_gso(skb)) { 2322 if (skb_is_gso(skb)) {
2323 int features = netif_get_vlan_features(skb, dev); 2323 int features = netif_skb_features(skb);
2324 2324
2325 return (!skb_gso_ok(skb, features) || 2325 return (!skb_gso_ok(skb, features) ||
2326 unlikely(skb->ip_summed != CHECKSUM_PARTIAL)); 2326 unlikely(skb->ip_summed != CHECKSUM_PARTIAL));
diff --git a/net/core/dev.c b/net/core/dev.c
index d8befd06da04..a51dfd7b56fb 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2017,22 +2017,41 @@ static inline void skb_orphan_try(struct sk_buff *skb)
2017 } 2017 }
2018} 2018}
2019 2019
2020int netif_get_vlan_features(struct sk_buff *skb, struct net_device *dev) 2020static int harmonize_features(struct sk_buff *skb, __be16 protocol, int features)
2021{
2022 if (!can_checksum_protocol(protocol, features)) {
2023 features &= ~NETIF_F_ALL_CSUM;
2024 features &= ~NETIF_F_SG;
2025 } else if (illegal_highdma(skb->dev, skb)) {
2026 features &= ~NETIF_F_SG;
2027 }
2028
2029 return features;
2030}
2031
2032int netif_skb_features(struct sk_buff *skb)
2021{ 2033{
2022 __be16 protocol = skb->protocol; 2034 __be16 protocol = skb->protocol;
2035 int features = skb->dev->features;
2023 2036
2024 if (protocol == htons(ETH_P_8021Q)) { 2037 if (protocol == htons(ETH_P_8021Q)) {
2025 struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; 2038 struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data;
2026 protocol = veh->h_vlan_encapsulated_proto; 2039 protocol = veh->h_vlan_encapsulated_proto;
2027 } else if (!skb->vlan_tci) 2040 } else if (!vlan_tx_tag_present(skb)) {
2028 return dev->features; 2041 return harmonize_features(skb, protocol, features);
2042 }
2029 2043
2030 if (protocol != htons(ETH_P_8021Q)) 2044 features &= skb->dev->vlan_features;
2031 return dev->features & dev->vlan_features; 2045
2032 else 2046 if (protocol != htons(ETH_P_8021Q)) {
2033 return 0; 2047 return harmonize_features(skb, protocol, features);
2048 } else {
2049 features &= NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST |
2050 NETIF_F_GEN_CSUM;
2051 return harmonize_features(skb, protocol, features);
2052 }
2034} 2053}
2035EXPORT_SYMBOL(netif_get_vlan_features); 2054EXPORT_SYMBOL(netif_skb_features);
2036 2055
2037/* 2056/*
2038 * Returns true if either: 2057 * Returns true if either: