This patch adds a new function dev_skb_segment() that generalises
the existing dev_gso_segment() by allowing to give a segmentation
function. mac80211 will use that function using the segmentation
function skb_segment().
This patch also changes dev_gso_skb_destructor() to be safe when
the skb no longer has any segments, this will happen when mac80211
has internally passed off all the fragments to the driver instead
of asking dev_hard_start_xmit() to do it (which protects against
this by resetting the destructor if it has sent all fragments.)
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
---
include/linux/netdevice.h | 1 +
net/core/dev.c | 38 ++++++++++++++++++++++++++++++--------
2 files changed, 31 insertions(+), 8 deletions(-)
--- everything.orig/net/core/dev.c 2008-04-30 01:52:23.000000000 +0200
+++ everything/net/core/dev.c 2008-04-30 03:46:33.000000000 +0200
@@ -1491,13 +1491,13 @@ static void dev_gso_skb_destructor(struc
{
struct dev_gso_cb *cb;
- do {
+ while (skb->next) {
struct sk_buff *nskb = skb->next;
skb->next = nskb->next;
nskb->next = NULL;
kfree_skb(nskb);
- } while (skb->next);
+ }
cb = DEV_GSO_CB(skb);
if (cb->destructor)
@@ -1505,22 +1505,31 @@ static void dev_gso_skb_destructor(struc
}
/**
- * dev_gso_segment - Perform emulated hardware segmentation on skb.
+ * dev_skb_segment - Perform segmentation on skb.
* @skb: buffer to segment
+ * @segmfn: function that does the actual segmentation
*
- * This function segments the given skb and stores the list of segments
- * in skb->next.
+ * This function segments the given skb and stores the list
+ * of segments in skb->next. The segmentation function is
+ * used to do the actual segmentation, it must return the
+ * list of segments as chained via the returned skb's @next
+ * pointer. The segmentation function is given the skb to
+ * segment and the features of the device the skb is going
+ * to. The segmentation function needs to return an ERR_PTR
+ * or a valid sk_buff pointer (or NULL for no segments.)
+ *
+ * Note that segmentation needs the skbs @cb data.
*/
-static int dev_gso_segment(struct sk_buff *skb)
+int dev_skb_segment(struct sk_buff *skb, struct sk_buff *(segmfn)(struct sk_buff *skb, int feat))
{
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);
+ segs = segmfn(skb, features);
- /* Verifying header integrity only. */
+ /* Verifying header integrity only/no segments required. */
if (!segs)
return 0;
@@ -1533,6 +1542,19 @@ static int dev_gso_segment(struct sk_buf
return 0;
}
+EXPORT_SYMBOL_GPL(dev_skb_segment);
+
+/**
+ * dev_gso_segment - Perform emulated hardware segmentation on skb.
+ * @skb: buffer to segment
+ *
+ * This function segments the given skb and stores the list of segments
+ * in skb->next.
+ */
+static int dev_gso_segment(struct sk_buff *skb)
+{
+ return dev_skb_segment(skb, skb_gso_segment);
+}
int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
--- everything.orig/include/linux/netdevice.h 2008-04-30 01:52:23.000000000 +0200
+++ everything/include/linux/netdevice.h 2008-04-30 01:52:26.000000000 +0200
@@ -1454,6 +1454,7 @@ extern int weight_p;
extern int netdev_set_master(struct net_device *dev, struct net_device *master);
extern int skb_checksum_help(struct sk_buff *skb);
extern struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features);
+extern int dev_skb_segment(struct sk_buff *skb, struct sk_buff *(segmfn)(struct sk_buff *skb, int feat));
#ifdef CONFIG_BUG
extern void netdev_rx_csum_fault(struct net_device *dev);
#else
--
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
| Karl Meyer | PROBLEM: 2.6.23-rc "NETDEV WATCHDOG: eth0: transmit timed out" |
| Greg Kroah-Hartman | [PATCH 040/196] kobject: add kobject_add_ng function |
| Steven Rostedt | [RFC PATCH v4] Unified trace buffer |
| Dave Airlie | [git pull] drm patches for 2.6.27 final |
| Krzysztof Halasa | Re: [PATCH v2] Re: WAN: new PPP code for generic HDLC |
| David Miller | Re: [PATCH] Expose netdevice dev_id through sysfs |
| Jay Cliburn | Re: atl1 64-bit => 32-bit DMA borkage (reproducible, bisected) |
| Evgeniy Polyakov | [resend take 2 0/4] Distributed storage. |
git: | |
| Andrew Morton | Untracked working tree files |
| Miklos Vajna | [rfc] git submodules howto |
| Ben Collins | Re: [kernel.org users] [RFD] On deprecating "git-foo" for builtins |
| Jon Smirl | ! [rejected] master -> master (non-fast forward) |
| rancor | How to copy/pipe console buffert to file? |
| Pieter Verberne | File collision while using pkg_add |
| Greg Thomas | Re: Is it possible to fix a stale NFS hadle without rebooting? |
| Didier Wiroth | win32-codecs, avi and amd64 question |
| Netfilter kernel module | 9 hours ago | Linux kernel |
| serial driver xmit problem | 12 hours ago | Linux kernel |
| Why Windows is better than Linux | 12 hours ago | Linux general |
| How can I see my kernel messages in vt12? | 19 hours ago | Linux kernel |
| Grub | 1 day ago | Linux general |
| vmalloc_fault handling in x86_64 | 1 day ago | Linux kernel |
| epoll_wait()ing on epoll FD | 1 day ago | Linux kernel |
| Framebuffer in x86_64 causes problems to multiseat | 1 day ago | Linux kernel |
| Difference between 2.4 and 2.6 regarding thread creation | 1 day ago | Linux general |
| Compiling gfs2 on kernel 2.6.27 | 2 days ago | Linux kernel |
