From patchwork Sun Jan 9 16:23:31 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jesse Gross X-Patchwork-Id: 78034 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 8380BB7139 for ; Mon, 10 Jan 2011 03:24:03 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752153Ab1AIQXr (ORCPT ); Sun, 9 Jan 2011 11:23:47 -0500 Received: from mail-yi0-f46.google.com ([209.85.218.46]:37428 "EHLO mail-yi0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751800Ab1AIQXo (ORCPT ); Sun, 9 Jan 2011 11:23:44 -0500 Received: by yib18 with SMTP id 18so5042831yib.19 for ; Sun, 09 Jan 2011 08:23:44 -0800 (PST) Received: by 10.100.96.5 with SMTP id t5mr16513628anb.258.1294590224118; Sun, 09 Jan 2011 08:23:44 -0800 (PST) Received: from umstead.nicira.com ([66.201.54.10]) by mx.google.com with ESMTPS id d15sm36347479ana.35.2011.01.09.08.23.41 (version=SSLv3 cipher=RC4-MD5); Sun, 09 Jan 2011 08:23:43 -0800 (PST) From: Jesse Gross To: David Miller Cc: netdev@vger.kernel.org Subject: [PATCH 2/6] offloading: Generalize netif_get_vlan_features(). Date: Sun, 9 Jan 2011 08:23:31 -0800 Message-Id: <1294590215-15541-2-git-send-email-jesse@nicira.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1294590215-15541-1-git-send-email-jesse@nicira.com> References: <1294590215-15541-1-git-send-email-jesse@nicira.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org 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 Signed-off-by: Jesse Gross --- include/linux/netdevice.h | 4 ++-- net/core/dev.c | 35 +++++++++++++++++++++++++++-------- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 0f6b1c9..d4dac09 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); 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); +int netif_skb_features(struct sk_buff *skb); 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) static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *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) || unlikely(skb->ip_summed != CHECKSUM_PARTIAL)); diff --git a/net/core/dev.c b/net/core/dev.c index d8befd0..a51dfd7 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) } } -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; + int features = skb->dev->features; 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; + } else if (!vlan_tx_tag_present(skb)) { + return harmonize_features(skb, protocol, features); + } - if (protocol != htons(ETH_P_8021Q)) - return dev->features & dev->vlan_features; - else - return 0; + features &= skb->dev->vlan_features; + + if (protocol != htons(ETH_P_8021Q)) { + 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: