ChangeSet 1.1506, 2005/05/21 20:08:56+01:00, kaf24@viper.(none)
Checksum offload for local virtual networking, and to/from a physical
interface that may be connected via a virtual bridge or router. This
adds
a coupel of new fields to skbuffs that are intended to survive across IP
or MAC level forwarding. I've tested basic connectivity with this patch,
but further stress-testing and performance benchmarking is really
required.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
linux-2.6.11-xen-sparse/drivers/xen/netback/interface.c | 1
linux-2.6.11-xen-sparse/drivers/xen/netback/loopback.c | 10
linux-2.6.11-xen-sparse/drivers/xen/netback/netback.c | 22
linux-2.6.11-xen-sparse/drivers/xen/netfront/netfront.c | 7
linux-2.6.11-xen-sparse/include/linux/skbuff.h | 1184 +++++
linux-2.6.11-xen-sparse/net/core/dev.c | 3389 ++++++++++++++++
linux-2.6.11-xen-sparse/net/core/skbuff.c | 1523 +++++++
xen/include/public/io/netif.h | 6
8 files changed, 6133 insertions(+), 9 deletions(-)
diff -Nru a/linux-2.6.11-xen-sparse/drivers/xen/netback/interface.c
b/linux-2.6.11-xen-sparse/drivers/xen/netback/interface.c
--- a/linux-2.6.11-xen-sparse/drivers/xen/netback/interface.c 2005-05-22
13:04:37 -04:00
+++ b/linux-2.6.11-xen-sparse/drivers/xen/netback/interface.c 2005-05-22
13:04:37 -04:00
@@ -159,6 +159,7 @@
dev->get_stats = netif_be_get_stats;
dev->open = net_open;
dev->stop = net_close;
+ dev->features = NETIF_F_NO_CSUM;
/* Disable queuing. */
dev->tx_queue_len = 0;
diff -Nru a/linux-2.6.11-xen-sparse/drivers/xen/netback/loopback.c
b/linux-2.6.11-xen-sparse/drivers/xen/netback/loopback.c
--- a/linux-2.6.11-xen-sparse/drivers/xen/netback/loopback.c 2005-05-22
13:04:37 -04:00
+++ b/linux-2.6.11-xen-sparse/drivers/xen/netback/loopback.c 2005-05-22
13:04:37 -04:00
@@ -67,6 +67,11 @@
np->stats.rx_bytes += skb->len;
np->stats.rx_packets++;
+ if ( skb->ip_summed == CHECKSUM_HW )
+ skb->proto_csum_blank = 1;
+ skb->ip_summed = skb->proto_csum_valid ?
+ CHECKSUM_UNNECESSARY : CHECKSUM_NONE;
+
skb->pkt_type = PACKET_HOST; /* overridden by eth_type_trans() */
skb->protocol = eth_type_trans(skb, dev);
skb->dev = dev;
@@ -95,6 +100,8 @@
dev->tx_queue_len = 0;
+ dev->features = NETIF_F_HIGHDMA | NETIF_F_LLTX;
+
/*
* We do not set a jumbo MTU on the interface. Otherwise the network
* stack will try to send large packets that will get dropped by the
@@ -117,6 +124,9 @@
loopback_construct(dev1, dev2);
loopback_construct(dev2, dev1);
+
+ dev1->features |= NETIF_F_NO_CSUM;
+ dev2->features |= NETIF_F_IP_CSUM;
/*
* Initialise a dummy MAC address for the 'dummy backend' interface. We
diff -Nru a/linux-2.6.11-xen-sparse/drivers/xen/netback/netback.c
b/linux-2.6.11-xen-sparse/drivers/xen/netback/netback.c
--- a/linux-2.6.11-xen-sparse/drivers/xen/netback/netback.c 2005-05-22
13:04:37 -04:00
+++ b/linux-2.6.11-xen-sparse/drivers/xen/netback/netback.c 2005-05-22
13:04:37 -04:00
@@ -27,7 +27,8 @@
u16 id,
s8 st,
memory_t addr,
- u16 size);
+ u16 size,
+ u16 csum_valid);
static void net_tx_action(unsigned long unused);
static DECLARE_TASKLET(net_tx_tasklet, net_tx_action, 0);
@@ -154,6 +155,7 @@
__skb_put(nskb, skb->len);
(void)skb_copy_bits(skb, -hlen, nskb->data - hlen, skb->len + hlen);
nskb->dev = skb->dev;
+ nskb->proto_csum_valid = skb->proto_csum_valid;
dev_kfree_skb(skb);
skb = nskb;
}
@@ -308,7 +310,8 @@
evtchn = netif->evtchn;
id = netif->rx->ring[MASK_NETIF_RX_IDX(netif->rx_resp_prod)].req.id;
- if ( make_rx_response(netif, id, status, mdata, size) &&
+ if ( make_rx_response(netif, id, status, mdata,
+ size, skb->proto_csum_valid) &&
(rx_notify[evtchn] == 0) )
{
rx_notify[evtchn] = 1;
@@ -646,6 +649,11 @@
skb->dev = netif->dev;
skb->protocol = eth_type_trans(skb, skb->dev);
+ /* No checking needed on localhost, but remember the field is blank. */
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ skb->proto_csum_valid = 1;
+ skb->proto_csum_blank = txreq.csum_blank;
+
netif->stats.rx_bytes += txreq.size;
netif->stats.rx_packets++;
@@ -711,15 +719,17 @@
u16 id,
s8 st,
memory_t addr,
- u16 size)
+ u16 size,
+ u16 csum_valid)
{
NETIF_RING_IDX i = netif->rx_resp_prod;
netif_rx_response_t *resp;
resp = &netif->rx->ring[MASK_NETIF_RX_IDX(i)].resp;
- resp->addr = addr;
- resp->id = id;
- resp->status = (s16)size;
+ resp->addr = addr;
+ resp->csum_valid = csum_valid;
+ resp->id = id;
+ resp->status = (s16)size;
if ( st < 0 )
resp->status = (s16)st;
wmb();
diff -Nru a/linux-2.6.11-xen-sparse/drivers/xen/netfront/netfront.c
b/linux-2.6.11-xen-sparse/drivers/xen/netfront/netfront.c
--- a/linux-2.6.11-xen-sparse/drivers/xen/netfront/netfront.c 2005-05-22
13:04:37 -04:00
+++ b/linux-2.6.11-xen-sparse/drivers/xen/netfront/netfront.c 2005-05-22
13:04:37 -04:00
@@ -473,6 +473,7 @@
tx->id = id;
tx->addr = virt_to_machine(skb->data);
tx->size = skb->len;
+ tx->csum_blank = (skb->ip_summed == CHECKSUM_HW);
wmb(); /* Ensure that backend will see the request. */
np->tx->req_prod = i + 1;
@@ -573,6 +574,9 @@
skb->len = rx->status;
skb->tail = skb->data + skb->len;
+ if ( rx->csum_valid )
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+
np->stats.rx_packets++;
np->stats.rx_bytes += rx->status;
@@ -967,7 +971,8 @@
dev->get_stats = network_get_stats;
dev->poll = netif_poll;
dev->weight = 64;
-
+ dev->features = NETIF_F_IP_CSUM;
+
if ((err = register_netdev(dev)) != 0) {
printk(KERN_WARNING "%s> register_netdev err=%d\n", __FUNCTION__, err);
goto exit;
diff -Nru a/linux-2.6.11-xen-sparse/include/linux/skbuff.h
b/linux-2.6.11-xen-sparse/include/linux/skbuff.h
--- /dev/null Wed Dec 31 16:00:00 196900
+++ b/linux-2.6.11-xen-sparse/include/linux/skbuff.h 2005-05-22 13:04:37
-04:00
@@ -0,0 +1,1184 @@
+/*
+ * Definitions for the 'struct sk_buff' memory handlers.
+ *
+ * Authors:
+ * Alan Cox, <gw4pts@xxxxxxxxxxxxxxx>
+ * Florian La Roche, <rzsfl@xxxxxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _LINUX_SKBUFF_H
+#define _LINUX_SKBUFF_H
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/compiler.h>
+#include <linux/time.h>
+#include <linux/cache.h>
+
+#include <asm/atomic.h>
+#include <asm/types.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <linux/poll.h>
+#include <linux/net.h>
+#include <net/checksum.h>
+
+#define HAVE_ALLOC_SKB /* For the drivers to know */
+#define HAVE_ALIGNABLE_SKB /* Ditto 8) */
+#define SLAB_SKB /* Slabified skbuffs */
+
+#define CHECKSUM_NONE 0
+#define CHECKSUM_HW 1
+#define CHECKSUM_UNNECESSARY 2
+
+#define SKB_DATA_ALIGN(X) (((X) + (SMP_CACHE_BYTES - 1)) & \
+ ~(SMP_CACHE_BYTES - 1))
+#define SKB_MAX_ORDER(X, ORDER) (((PAGE_SIZE << (ORDER)) - (X) - \
+ sizeof(struct skb_shared_info)) & \
+ ~(SMP_CACHE_BYTES - 1))
+#define SKB_MAX_HEAD(X) (SKB_MAX_ORDER((X), 0))
+#define SKB_MAX_ALLOC (SKB_MAX_ORDER(0, 2))
+
+/* A. Checksumming of received packets by device.
+ *
+ * NONE: device failed to checksum this packet.
+ * skb->csum is undefined.
+ *
+ * UNNECESSARY: device parsed packet and wouldbe verified checksum.
+ * skb->csum is undefined.
+ * It is bad option, but, unfortunately, many of vendors do this.
+ * Apparently with secret goal to sell you new device, when you
+ * will add new protocol to your host. F.e. IPv6. 8)
+ *
+ * HW: the most generic way. Device supplied checksum of _all_
+ * the packet as seen by netif_rx in skb->csum.
+ * NOTE: Even if device supports only some protocols, but
+ * is able to produce some skb->csum, it MUST use HW,
+ * not UNNECESSARY.
+ *
+ * B. Checksumming on output.
+ *
+ * NONE: skb is checksummed by protocol or csum is not required.
+ *
+ * HW: device is required to csum packet as seen by hard_start_xmit
+ * from skb->h.raw to the end and to record the checksum
+ * at skb->h.raw+skb->csum.
+ *
+ * Device must show its capabilities in dev->features, set
+ * at device setup time.
+ * NETIF_F_HW_CSUM - it is clever device, it is able to checksum
+ * everything.
+ * NETIF_F_NO_CSUM - loopback or reliable single hop media.
+ * NETIF_F_IP_CSUM - device is dumb. It is able to csum only
+ * TCP/UDP over IPv4. Sigh. Vendors like this
+ * way by an unknown reason. Though, see comment above
+ * about CHECKSUM_UNNECESSARY. 8)
+ *
+ * Any questions? No questions, good. --ANK
+ */
+
+#ifdef __i386__
+#define NET_CALLER(arg) (*(((void **)&arg) - 1))
+#else
+#define NET_CALLER(arg) __builtin_return_address(0)
+#endif
+
+struct net_device;
+
+#ifdef CONFIG_NETFILTER
+struct nf_conntrack {
+ atomic_t use;
+ void (*destroy)(struct nf_conntrack *);
+};
+
+#ifdef CONFIG_BRIDGE_NETFILTER
+struct nf_bridge_info {
+ atomic_t use;
+ struct net_device *physindev;
+ struct net_device *physoutdev;
+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|