From: Stephen Hemminger <shemminger@linux-foundation.org>
To: Herbert Xu <herbert.xu@redhat.com>,
"David S. Miller" <davem@davemloft.net>
Cc: netdev@vger.kernel.org, Michael Chan <mchan@broadcom.com>
Subject: [RFC] IPV6 checksum offloading in network devices
Date: Wed, 30 May 2007 08:53:20 -0700 [thread overview]
Message-ID: <20070530085320.0c35bd71@freepuppy> (raw)
In-Reply-To: <20070529213618.GA9360@gondor.apana.org.au>
Here is a proposed change to address hardware that can do IPV6 checksum
offload, but doesn't truly do generic hw checksumming. The bnx2 and tg3
are like this for some revisions, and upcoming Marvell 88e8071 is similar.
--- a/drivers/net/bnx2.c 2007-05-30 08:26:18.000000000 -0700
+++ b/drivers/net/bnx2.c 2007-05-30 08:26:32.000000000 -0700
@@ -6471,10 +6471,10 @@ bnx2_init_one(struct pci_dev *pdev, cons
memcpy(dev->perm_addr, bp->mac_addr, 6);
bp->name = board_info[ent->driver_data].name;
+ dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
if (CHIP_NUM(bp) == CHIP_NUM_5709)
- dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG;
- else
- dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
+ dev->features |= NETIF_F_IPV6_CSUM;
+
#ifdef BCM_VLAN
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
#endif
--- a/drivers/net/tg3.c 2007-05-30 08:26:18.000000000 -0700
+++ b/drivers/net/tg3.c 2007-05-30 08:26:32.000000000 -0700
@@ -11959,12 +11959,11 @@ static int __devinit tg3_init_one(struct
* checksumming.
*/
if ((tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) == 0) {
+ dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
- dev->features |= NETIF_F_HW_CSUM;
- else
- dev->features |= NETIF_F_IP_CSUM;
- dev->features |= NETIF_F_SG;
+ dev->features |= NETIF_F_IPV6_CSUM;
+
tp->tg3_flags |= TG3_FLAG_RX_CHECKSUMS;
} else
tp->tg3_flags &= ~TG3_FLAG_RX_CHECKSUMS;
--- a/include/linux/netdevice.h 2007-05-30 08:26:18.000000000 -0700
+++ b/include/linux/netdevice.h 2007-05-30 08:30:20.000000000 -0700
@@ -314,9 +314,10 @@ struct net_device
/* Net device features */
unsigned long features;
#define NETIF_F_SG 1 /* Scatter/gather IO. */
-#define NETIF_F_IP_CSUM 2 /* Can checksum only TCP/UDP over IPv4. */
+#define NETIF_F_IP_CSUM 2 /* Can checksum TCP/UDP over IPv4. */
#define NETIF_F_NO_CSUM 4 /* Does not require checksum. F.e. loopack. */
#define NETIF_F_HW_CSUM 8 /* Can checksum all the packets. */
+#define NETIF_F_IPV6_CSUM 16 /* Can checksum TCP/UDP over IPV6 */
#define NETIF_F_HIGHDMA 32 /* Can DMA to high memory. */
#define NETIF_F_FRAGLIST 64 /* Scatter/gather IO. */
#define NETIF_F_HW_VLAN_TX 128 /* Transmit VLAN hw acceleration */
@@ -339,7 +340,8 @@ struct net_device
#define NETIF_F_GSO_SOFTWARE (NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6)
#define NETIF_F_GEN_CSUM (NETIF_F_NO_CSUM | NETIF_F_HW_CSUM)
-#define NETIF_F_ALL_CSUM (NETIF_F_IP_CSUM | NETIF_F_GEN_CSUM)
+#define NETIF_F_ALL_CSUM (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM \
+ | NETIF_F_GEN_CSUM)
struct net_device *next_sched;
--- a/net/bridge/br_if.c 2007-05-30 08:26:18.000000000 -0700
+++ b/net/bridge/br_if.c 2007-05-30 08:26:32.000000000 -0700
@@ -368,10 +368,18 @@ void br_features_recompute(struct net_br
list_for_each_entry(p, &br->port_list, list) {
unsigned long feature = p->dev->features;
+ /* if device needs checksumming, downgrade to hw checksumming */
if (checksum & NETIF_F_NO_CSUM && !(feature & NETIF_F_NO_CSUM))
checksum ^= NETIF_F_NO_CSUM | NETIF_F_HW_CSUM;
+
+ /* if device can't do all checksum, downgrade to ipv4/ipv6 */
if (checksum & NETIF_F_HW_CSUM && !(feature & NETIF_F_HW_CSUM))
- checksum ^= NETIF_F_HW_CSUM | NETIF_F_IP_CSUM;
+ checksum ^= NETIF_F_HW_CSUM
+ | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+
+ if (checksum & NETIF_F_IPV6_CSUM && !(feature & NETIF_F_IPV6_CSUM))
+ checksum &= ~NETIF_F_IPV6_CSUM;
+
if (!(feature & NETIF_F_IP_CSUM))
checksum = 0;
--- a/net/core/dev.c 2007-05-30 08:26:18.000000000 -0700
+++ b/net/core/dev.c 2007-05-30 08:49:54.000000000 -0700
@@ -1509,9 +1509,11 @@ int dev_queue_xmit(struct sk_buff *skb)
skb_set_transport_header(skb, skb->csum_start -
skb_headroom(skb));
- if (!(dev->features & NETIF_F_GEN_CSUM) &&
- (!(dev->features & NETIF_F_IP_CSUM) ||
- skb->protocol != htons(ETH_P_IP)))
+ if (!(dev->features & NETIF_F_GEN_CSUM)
+ || ((dev->features & NETIF_F_IP_CSUM)
+ && skb->protocol == htons(ETH_P_IP))
+ || ((dev->features & NETIF_F_IPV6_CSUM)
+ && skb->protocol == htons(ETH_P_IPV6)))
if (skb_checksum_help(skb))
goto out_kfree_skb;
}
@@ -3105,6 +3107,22 @@ int register_netdevice(struct net_device
}
}
+ /* Fix illegal checksum combinations */
+ if ((dev->features & NETIF_F_HW_CSUM) &&
+ (dev->features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) {
+ printk(KERN_NOTICE "%s: mixed HW and IP checksum settings.\n",
+ dev->name);
+ dev->features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM);
+ }
+
+ if ((dev->features & NETIF_F_NO_CSUM) &&
+ (dev->features & (NETIF_F_HW_CSUM|NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) {
+ printk(KERN_NOTICE "%s: mixed no checksumming and other settings.\n",
+ dev->name);
+ dev->features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM|NETIF_F_HW_CSUM);
+ }
+
+
/* Fix illegal SG+CSUM combinations. */
if ((dev->features & NETIF_F_SG) &&
!(dev->features & NETIF_F_ALL_CSUM)) {
--- a/net/ipv6/ipv6_sockglue.c 2007-05-29 16:44:45.000000000 -0700
+++ b/net/ipv6/ipv6_sockglue.c 2007-05-30 08:48:35.000000000 -0700
@@ -123,7 +123,7 @@ static struct sk_buff *ipv6_gso_segment(
struct ipv6hdr *ipv6h;
struct inet6_protocol *ops;
- if (!(features & NETIF_F_HW_CSUM))
+ if (!(features & (NETIF_F_HW_CSUM|NETIF_F_IPV6_CSUM))
features &= ~NETIF_F_SG;
if (unlikely(skb_shinfo(skb)->gso_type &
next prev parent reply other threads:[~2007-05-30 16:04 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-05-29 20:58 Definition and usage of NETIF_F_HW_SUM? Stephen Hemminger
2007-05-29 21:36 ` Herbert Xu
2007-05-29 21:58 ` Stephen Hemminger
2007-05-30 0:10 ` Michael Chan
2007-05-29 23:45 ` Stephen Hemminger
2007-06-04 15:35 ` Ron Mercer
2007-05-30 15:53 ` Stephen Hemminger [this message]
2007-05-30 16:13 ` [RFC] IPV6 checksum offloading in network devices Patrick McHardy
2007-05-30 21:00 ` Stephen Hemminger
2007-06-27 7:44 ` David Miller
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20070530085320.0c35bd71@freepuppy \
--to=shemminger@linux-foundation.org \
--cc=davem@davemloft.net \
--cc=herbert.xu@redhat.com \
--cc=mchan@broadcom.com \
--cc=netdev@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).