* [PATCH 1/6] offloading: Accept NETIF_F_HW_CSUM for all protocols.
@ 2011-01-09 16:23 Jesse Gross
2011-01-09 16:23 ` [PATCH 2/6] offloading: Generalize netif_get_vlan_features() Jesse Gross
` (5 more replies)
0 siblings, 6 replies; 7+ messages in thread
From: Jesse Gross @ 2011-01-09 16:23 UTC (permalink / raw)
To: David Miller; +Cc: netdev
We currently only have software fallback for one type of checksum: the
TCP/UDP one's complement. This means that a protocol that uses hardware
offloading for a different type of checksum (FCoE, SCTP) must directly
check the device's features and do the right thing ahead of time. By
the time we get to dev_can_checksum(), we're only deciding whether to
apply the one algorithm in software or hardware. NETIF_F_HW_CSUM has the
same capabilities as the software version, so we should always use it if
present. The primary advantage of this is multiply tagged vlans can use
hardware checksumming.
Signed-off-by: Jesse Gross <jesse@nicira.com>
---
net/core/dev.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/net/core/dev.c b/net/core/dev.c
index a215269..d8befd0 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1734,7 +1734,7 @@ EXPORT_SYMBOL(netif_device_attach);
static bool can_checksum_protocol(unsigned long features, __be16 protocol)
{
- return ((features & NETIF_F_NO_CSUM) ||
+ return ((features & NETIF_F_GEN_CSUM) ||
((features & NETIF_F_V4_CSUM) &&
protocol == htons(ETH_P_IP)) ||
((features & NETIF_F_V6_CSUM) &&
--
1.7.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/6] offloading: Generalize netif_get_vlan_features().
2011-01-09 16:23 [PATCH 1/6] offloading: Accept NETIF_F_HW_CSUM for all protocols Jesse Gross
@ 2011-01-09 16:23 ` Jesse Gross
2011-01-09 16:23 ` [PATCH 3/6] offloading: Pass features into netif_needs_gso() Jesse Gross
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Jesse Gross @ 2011-01-09 16:23 UTC (permalink / raw)
To: David Miller; +Cc: netdev
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>
---
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:
--
1.7.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 3/6] offloading: Pass features into netif_needs_gso().
2011-01-09 16:23 [PATCH 1/6] offloading: Accept NETIF_F_HW_CSUM for all protocols Jesse Gross
2011-01-09 16:23 ` [PATCH 2/6] offloading: Generalize netif_get_vlan_features() Jesse Gross
@ 2011-01-09 16:23 ` Jesse Gross
2011-01-09 16:23 ` [PATCH 4/6] offloading: Convert dev_gso_segment() to use precomputed features Jesse Gross
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Jesse Gross @ 2011-01-09 16:23 UTC (permalink / raw)
To: David Miller; +Cc: netdev
Now that there is a single function that can compute the device
features relevant to a packet, we don't want to run it for each
offload. This converts netif_needs_gso() to take the features
of the device, rather than computing them itself.
Signed-off-by: Jesse Gross <jesse@nicira.com>
---
drivers/net/xen-netfront.c | 2 +-
include/linux/netdevice.h | 12 +++---------
net/core/dev.c | 8 ++++++--
3 files changed, 10 insertions(+), 12 deletions(-)
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index cdbeec9..546de57 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -488,7 +488,7 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (unlikely(!netif_carrier_ok(dev) ||
(frags > 1 && !xennet_can_sg(dev)) ||
- netif_needs_gso(dev, skb))) {
+ netif_needs_gso(skb, netif_skb_features(skb)))) {
spin_unlock_irq(&np->tx_lock);
goto drop;
}
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index d4dac09..de2bfe6 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2317,16 +2317,10 @@ static inline int skb_gso_ok(struct sk_buff *skb, int features)
(!skb_has_frag_list(skb) || (features & NETIF_F_FRAGLIST));
}
-static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb)
+static inline int netif_needs_gso(struct sk_buff *skb, int features)
{
- if (skb_is_gso(skb)) {
- int features = netif_skb_features(skb);
-
- return (!skb_gso_ok(skb, features) ||
- unlikely(skb->ip_summed != CHECKSUM_PARTIAL));
- }
-
- return 0;
+ return skb_is_gso(skb) && (!skb_gso_ok(skb, features) ||
+ unlikely(skb->ip_summed != CHECKSUM_PARTIAL));
}
static inline void netif_set_gso_max_size(struct net_device *dev,
diff --git a/net/core/dev.c b/net/core/dev.c
index a51dfd7..1444ed3 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2086,6 +2086,8 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
int rc = NETDEV_TX_OK;
if (likely(!skb->next)) {
+ int features;
+
/*
* If device doesnt need skb->dst, release it right now while
* its hot in this cpu cache
@@ -2098,8 +2100,10 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
skb_orphan_try(skb);
+ features = netif_skb_features(skb);
+
if (vlan_tx_tag_present(skb) &&
- !(dev->features & NETIF_F_HW_VLAN_TX)) {
+ !(features & NETIF_F_HW_VLAN_TX)) {
skb = __vlan_put_tag(skb, vlan_tx_tag_get(skb));
if (unlikely(!skb))
goto out;
@@ -2107,7 +2111,7 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
skb->vlan_tci = 0;
}
- if (netif_needs_gso(dev, skb)) {
+ if (netif_needs_gso(skb, features)) {
if (unlikely(dev_gso_segment(skb)))
goto out_kfree_skb;
if (skb->next)
--
1.7.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 4/6] offloading: Convert dev_gso_segment() to use precomputed features.
2011-01-09 16:23 [PATCH 1/6] offloading: Accept NETIF_F_HW_CSUM for all protocols Jesse Gross
2011-01-09 16:23 ` [PATCH 2/6] offloading: Generalize netif_get_vlan_features() Jesse Gross
2011-01-09 16:23 ` [PATCH 3/6] offloading: Pass features into netif_needs_gso() Jesse Gross
@ 2011-01-09 16:23 ` Jesse Gross
2011-01-09 16:23 ` [PATCH 5/6] offloading: Convert skb_need_linearize() " Jesse Gross
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Jesse Gross @ 2011-01-09 16:23 UTC (permalink / raw)
To: David Miller; +Cc: netdev
This switches dev_gso_segment() to use the device features computed
by the centralized routine. In doing so, it fixes a problem where
it would always use dev->features, instead of those appropriate
to the number of vlan tags if any are present.
Signed-off-by: Jesse Gross <jesse@nicira.com>
---
net/core/dev.c | 8 +++-----
1 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/net/core/dev.c b/net/core/dev.c
index 1444ed3..4cd3e84 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1971,16 +1971,14 @@ static void dev_gso_skb_destructor(struct sk_buff *skb)
/**
* dev_gso_segment - Perform emulated hardware segmentation on skb.
* @skb: buffer to segment
+ * @features: device features as applicable to this skb
*
* This function segments the given skb and stores the list of segments
* in skb->next.
*/
-static int dev_gso_segment(struct sk_buff *skb)
+static int dev_gso_segment(struct sk_buff *skb, int features)
{
- struct net_device *dev = skb->dev;
struct sk_buff *segs;
- int features = dev->features & ~(illegal_highdma(dev, skb) ?
- NETIF_F_SG : 0);
segs = skb_gso_segment(skb, features);
@@ -2112,7 +2110,7 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
}
if (netif_needs_gso(skb, features)) {
- if (unlikely(dev_gso_segment(skb)))
+ if (unlikely(dev_gso_segment(skb, features)))
goto out_kfree_skb;
if (skb->next)
goto gso;
--
1.7.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 5/6] offloading: Convert skb_need_linearize() to use precomputed features.
2011-01-09 16:23 [PATCH 1/6] offloading: Accept NETIF_F_HW_CSUM for all protocols Jesse Gross
` (2 preceding siblings ...)
2011-01-09 16:23 ` [PATCH 4/6] offloading: Convert dev_gso_segment() to use precomputed features Jesse Gross
@ 2011-01-09 16:23 ` Jesse Gross
2011-01-09 16:23 ` [PATCH 6/6] offloading: Convert checksums to use centrally computed features Jesse Gross
2011-01-10 7:36 ` [PATCH 1/6] offloading: Accept NETIF_F_HW_CSUM for all protocols David Miller
5 siblings, 0 replies; 7+ messages in thread
From: Jesse Gross @ 2011-01-09 16:23 UTC (permalink / raw)
To: David Miller; +Cc: netdev
This switches skb_need_linearize() to use the features that have
been centrally computed. In doing so, this fixes a problem where
scatter/gather should not be used because the card does not support
checksum offloading on that type of packet. On device registration
we only check that some form of checksum offloading is available if
scatter/gatther is enabled but we must also check at transmission
time. Examples of this include IPv6 or vlan packets on a NIC that
only supports IPv4 offloading.
Signed-off-by: Jesse Gross <jesse@nicira.com>
---
net/core/dev.c | 21 ++++++---------------
1 files changed, 6 insertions(+), 15 deletions(-)
diff --git a/net/core/dev.c b/net/core/dev.c
index 4cd3e84..2f838f1 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2059,22 +2059,13 @@ EXPORT_SYMBOL(netif_skb_features);
* support DMA from it.
*/
static inline int skb_needs_linearize(struct sk_buff *skb,
- struct net_device *dev)
+ int features)
{
- if (skb_is_nonlinear(skb)) {
- int features = dev->features;
-
- if (vlan_tx_tag_present(skb))
- features &= dev->vlan_features;
-
- return (skb_has_frag_list(skb) &&
- !(features & NETIF_F_FRAGLIST)) ||
+ return skb_is_nonlinear(skb) &&
+ ((skb_has_frag_list(skb) &&
+ !(features & NETIF_F_FRAGLIST)) ||
(skb_shinfo(skb)->nr_frags &&
- (!(features & NETIF_F_SG) ||
- illegal_highdma(dev, skb)));
- }
-
- return 0;
+ !(features & NETIF_F_SG)));
}
int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
@@ -2115,7 +2106,7 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
if (skb->next)
goto gso;
} else {
- if (skb_needs_linearize(skb, dev) &&
+ if (skb_needs_linearize(skb, features) &&
__skb_linearize(skb))
goto out_kfree_skb;
--
1.7.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 6/6] offloading: Convert checksums to use centrally computed features.
2011-01-09 16:23 [PATCH 1/6] offloading: Accept NETIF_F_HW_CSUM for all protocols Jesse Gross
` (3 preceding siblings ...)
2011-01-09 16:23 ` [PATCH 5/6] offloading: Convert skb_need_linearize() " Jesse Gross
@ 2011-01-09 16:23 ` Jesse Gross
2011-01-10 7:36 ` [PATCH 1/6] offloading: Accept NETIF_F_HW_CSUM for all protocols David Miller
5 siblings, 0 replies; 7+ messages in thread
From: Jesse Gross @ 2011-01-09 16:23 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In order to compute the features for other offloads (primarily
scatter/gather), we need to first check the ability of the NIC to
offload the checksum for the packet. Since we have already computed
this, we can directly use the result instead of figuring it out
again.
Signed-off-by: Jesse Gross <jesse@nicira.com>
---
net/core/dev.c | 40 ++++++++++++----------------------------
1 files changed, 12 insertions(+), 28 deletions(-)
diff --git a/net/core/dev.c b/net/core/dev.c
index 2f838f1..3fe443b 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1732,33 +1732,6 @@ void netif_device_attach(struct net_device *dev)
}
EXPORT_SYMBOL(netif_device_attach);
-static bool can_checksum_protocol(unsigned long features, __be16 protocol)
-{
- return ((features & NETIF_F_GEN_CSUM) ||
- ((features & NETIF_F_V4_CSUM) &&
- protocol == htons(ETH_P_IP)) ||
- ((features & NETIF_F_V6_CSUM) &&
- protocol == htons(ETH_P_IPV6)) ||
- ((features & NETIF_F_FCOE_CRC) &&
- protocol == htons(ETH_P_FCOE)));
-}
-
-static bool dev_can_checksum(struct net_device *dev, struct sk_buff *skb)
-{
- __be16 protocol = skb->protocol;
- int features = dev->features;
-
- if (vlan_tx_tag_present(skb)) {
- features &= dev->vlan_features;
- } else if (protocol == htons(ETH_P_8021Q)) {
- struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data;
- protocol = veh->h_vlan_encapsulated_proto;
- features &= dev->vlan_features;
- }
-
- return can_checksum_protocol(features, protocol);
-}
-
/**
* skb_dev_set -- assign a new device to a buffer
* @skb: buffer for the new device
@@ -2015,6 +1988,17 @@ static inline void skb_orphan_try(struct sk_buff *skb)
}
}
+static bool can_checksum_protocol(unsigned long features, __be16 protocol)
+{
+ return ((features & NETIF_F_GEN_CSUM) ||
+ ((features & NETIF_F_V4_CSUM) &&
+ protocol == htons(ETH_P_IP)) ||
+ ((features & NETIF_F_V6_CSUM) &&
+ protocol == htons(ETH_P_IPV6)) ||
+ ((features & NETIF_F_FCOE_CRC) &&
+ protocol == htons(ETH_P_FCOE)));
+}
+
static int harmonize_features(struct sk_buff *skb, __be16 protocol, int features)
{
if (!can_checksum_protocol(protocol, features)) {
@@ -2117,7 +2101,7 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
if (skb->ip_summed == CHECKSUM_PARTIAL) {
skb_set_transport_header(skb,
skb_checksum_start_offset(skb));
- if (!dev_can_checksum(dev, skb) &&
+ if (!(features & NETIF_F_ALL_CSUM) &&
skb_checksum_help(skb))
goto out_kfree_skb;
}
--
1.7.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 1/6] offloading: Accept NETIF_F_HW_CSUM for all protocols.
2011-01-09 16:23 [PATCH 1/6] offloading: Accept NETIF_F_HW_CSUM for all protocols Jesse Gross
` (4 preceding siblings ...)
2011-01-09 16:23 ` [PATCH 6/6] offloading: Convert checksums to use centrally computed features Jesse Gross
@ 2011-01-10 7:36 ` David Miller
5 siblings, 0 replies; 7+ messages in thread
From: David Miller @ 2011-01-10 7:36 UTC (permalink / raw)
To: jesse; +Cc: netdev
Thanks for doing this work Jesse, I've applied all of these patches.
I added a "net " prefix to the commit header lines so that people know
what kind of "offloading" these changes are about :-)
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2011-01-10 7:36 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-01-09 16:23 [PATCH 1/6] offloading: Accept NETIF_F_HW_CSUM for all protocols Jesse Gross
2011-01-09 16:23 ` [PATCH 2/6] offloading: Generalize netif_get_vlan_features() Jesse Gross
2011-01-09 16:23 ` [PATCH 3/6] offloading: Pass features into netif_needs_gso() Jesse Gross
2011-01-09 16:23 ` [PATCH 4/6] offloading: Convert dev_gso_segment() to use precomputed features Jesse Gross
2011-01-09 16:23 ` [PATCH 5/6] offloading: Convert skb_need_linearize() " Jesse Gross
2011-01-09 16:23 ` [PATCH 6/6] offloading: Convert checksums to use centrally computed features Jesse Gross
2011-01-10 7:36 ` [PATCH 1/6] offloading: Accept NETIF_F_HW_CSUM for all protocols David Miller
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).