Re: [3/5] [NET]: Add software TSOv4

2006-06-26 Thread David Miller
From: Michael Chan [EMAIL PROTECTED]
Date: Fri, 23 Jun 2006 20:08:41 -0700

 On Sat, 2006-06-24 at 09:53 +1000, Herbert Xu wrote:
 
  Nevermind, I obviously complete ignored your other fix to the length of
  the last segment :) Here is a fixed version.
  
  [NET]: Fix CHECKSUM_HW GSO problems.
  
  Fix checksum problems in the GSO code path for CHECKSUM_HW packets.
  
  The ipv4 TCP pseudo header checksum has to be adjusted for GSO
  segmented packets.
  
  The adjustment is needed because the length field in the pseudo-header
  changes.  However, because we have the inequality oldlen  newlen, we
  know that delta = (u16)~oldlen + newlen is still a 16-bit quantity.
  This also means that htonl(delta) + th-check still fits in 32 bits.
  Therefore we don't have to use csum_add on this operations.
  
  This is based on a patch by Michael Chan [EMAIL PROTECTED].
  
  Signed-off-by: Herbert Xu [EMAIL PROTECTED]
  
 Yes, this should work. ACK.

Applied, thanks a lot guys.
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


RE: [3/5] [NET]: Add software TSOv4

2006-06-26 Thread Ravinandan Arakali
We are working on it.

Ravi

-Original Message-
From: YOSHIFUJI Hideaki / g!?p-? [mailto:[EMAIL PROTECTED]
Sent: Friday, June 23, 2006 6:33 PM
To: [EMAIL PROTECTED]
Cc: [EMAIL PROTECTED]; [EMAIL PROTECTED];
netdev@vger.kernel.org; [EMAIL PROTECTED]
Subject: Re: [3/5] [NET]: Add software TSOv4


In article [EMAIL PROTECTED] (at Fri, 23 Jun 2006
17:28:12 -0700), Ravinandan Arakali [EMAIL PROTECTED]
says:

 Neterion's Xframe adapter supports TSO over IPv6.

I remember you posted some patches.
Would you post revised version reflecting Stephen's comment, please?

--yoshfuji

-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [3/5] [NET]: Add software TSOv4

2006-06-23 Thread Michael Chan
On Thu, 2006-06-22 at 18:14 +1000, Herbert Xu wrote:
 [NET]: Add software TSOv4
 
 This patch adds the GSO implementation for IPv4 TCP.

Herbert, Looks like there were some problems in the CHECKSUM_HW case.
This patch should fix it.  Please double-check my checksum math.

[NET]: Fix CHECKSUM_HW GSO problems.

Fix the following 2 problems in the GSO code path for CHECKSUM_HW
packets:

1. Adjust ipv4 TCP pseudo header checksum.

2. Initialize skb-tail.

Signed-off-by: Michael Chan [EMAIL PROTECTED]


diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 8e5044b..3f19b3d 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -1954,6 +1954,7 @@ struct sk_buff *skb_segment(struct sk_bu
nskb-data_len = len - hsize;
nskb-len += nskb-data_len;
nskb-truesize += nskb-data_len;
+   nskb-tail += nskb-data_len;
} while ((offset += len)  skb-len);
 
return segs;
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 0e029c4..3399110 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2186,7 +2186,8 @@ struct sk_buff *tcp_tso_segment(struct s
if (skb-ip_summed == CHECKSUM_NONE) {
th-check = csum_fold(csum_partial(
skb-h.raw, thlen, csum_add(skb-csum, delta)));
-   }
+   } else if (skb-ip_summed == CHECKSUM_HW)
+   th-check = ~csum_fold(csum_add(th-check, delta));
 
seq += len;
skb = skb-next;
@@ -2196,11 +2197,12 @@ struct sk_buff *tcp_tso_segment(struct s
th-cwr = 0;
} while (skb-next);
 
+   delta = csum_add(oldlen, htonl(skb-tail - skb-h.raw));
if (skb-ip_summed == CHECKSUM_NONE) {
-   delta = csum_add(oldlen, htonl(skb-tail - skb-h.raw));
th-check = csum_fold(csum_partial(
skb-h.raw, thlen, csum_add(skb-csum, delta)));
-   }
+   } else if (skb-ip_summed == CHECKSUM_HW)
+   th-check = ~csum_fold(csum_add(th-check, delta));
 
 out:
return segs;


-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [3/5] [NET]: Add software TSOv4

2006-06-23 Thread Herbert Xu
On Fri, Jun 23, 2006 at 02:26:16PM -0700, Michael Chan wrote:

 This patch is more correct.  Please ignore the previous one.
 
 [NET]: Fix CHECKSUM_HW GSO problems.
 
 Fix checksum problems in the GSO code path for CHECKSUM_HW packets.
 
 The ipv4 TCP pseudo header checksum has to be adjusted for GSO
 segmented packets.
 
 Signed-off-by: Michael Chan [EMAIL PROTECTED]

Good catch.  Obviously the only CHECKSUM_HW I tested was loop :)
Looking at this again it seems that we can optimise it further so
how about this?

[NET]: Fix CHECKSUM_HW GSO problems.

Fix checksum problems in the GSO code path for CHECKSUM_HW packets.

The ipv4 TCP pseudo header checksum has to be adjusted for GSO
segmented packets.

The adjustment is needed because the length field in the pseudo-header
changes.  However, because we have the inequality oldlen  newlen, we
know that delta = (u16)~oldlen + newlen is still a 16-bit quantity.
This also means that htonl(delta) + th-check still fits in 32 bits.
Therefore we don't have to use csum_add on this operations.

This is based on a patch by Michael Chan [EMAIL PROTECTED].

Signed-off-by: Herbert Xu [EMAIL PROTECTED]

Cheers,
-- 
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmVHI~} [EMAIL PROTECTED]
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 0e029c4..10f1a8c 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2166,7 +2166,7 @@ struct sk_buff *tcp_tso_segment(struct s
if (!pskb_may_pull(skb, thlen))
goto out;
 
-   oldlen = ~htonl(skb-len);
+   oldlen = (u16)~skb-len;
__skb_pull(skb, thlen);
 
segs = skb_segment(skb, sg);
@@ -2174,7 +2174,7 @@ struct sk_buff *tcp_tso_segment(struct s
goto out;
 
len = skb_shinfo(skb)-gso_size;
-   delta = csum_add(oldlen, htonl(thlen + len));
+   delta = htonl(oldlen + (thlen + len));
 
skb = segs;
th = skb-h.th;
@@ -2183,10 +2183,10 @@ struct sk_buff *tcp_tso_segment(struct s
do {
th-fin = th-psh = 0;
 
-   if (skb-ip_summed == CHECKSUM_NONE) {
-   th-check = csum_fold(csum_partial(
-   skb-h.raw, thlen, csum_add(skb-csum, delta)));
-   }
+   th-check = ~csum_fold(th-check + delta);
+   if (skb-ip_summed != CHECKSUM_HW)
+   th-check = csum_fold(csum_partial(skb-h.raw, thlen,
+  skb-csum));
 
seq += len;
skb = skb-next;
@@ -2196,11 +2196,11 @@ struct sk_buff *tcp_tso_segment(struct s
th-cwr = 0;
} while (skb-next);
 
-   if (skb-ip_summed == CHECKSUM_NONE) {
-   delta = csum_add(oldlen, htonl(skb-tail - skb-h.raw));
-   th-check = csum_fold(csum_partial(
-   skb-h.raw, thlen, csum_add(skb-csum, delta)));
-   }
+   delta = htonl(oldlen + (skb-tail - skb-h.raw));
+   th-check = ~csum_fold(th-check + delta);
+   if (skb-ip_summed != CHECKSUM_HW)
+   th-check = csum_fold(csum_partial(skb-h.raw, thlen,
+  skb-csum));
 
 out:
return segs;
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [3/5] [NET]: Add software TSOv4

2006-06-23 Thread Herbert Xu
On Sat, Jun 24, 2006 at 09:38:40AM +1000, herbert wrote:
 
 Good catch.  Obviously the only CHECKSUM_HW I tested was loop :)
 Looking at this again it seems that we can optimise it further so
 how about this?

Nevermind, I obviously complete ignored your other fix to the length of
the last segment :) Here is a fixed version.

[NET]: Fix CHECKSUM_HW GSO problems.

Fix checksum problems in the GSO code path for CHECKSUM_HW packets.

The ipv4 TCP pseudo header checksum has to be adjusted for GSO
segmented packets.

The adjustment is needed because the length field in the pseudo-header
changes.  However, because we have the inequality oldlen  newlen, we
know that delta = (u16)~oldlen + newlen is still a 16-bit quantity.
This also means that htonl(delta) + th-check still fits in 32 bits.
Therefore we don't have to use csum_add on this operations.

This is based on a patch by Michael Chan [EMAIL PROTECTED].

Signed-off-by: Herbert Xu [EMAIL PROTECTED]

Cheers,
-- 
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmVHI~} [EMAIL PROTECTED]
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
cfecbf18c32a6dca8954538b5d5fb7186ed336d1
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 0e029c4..c04176b 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2166,7 +2166,7 @@ struct sk_buff *tcp_tso_segment(struct s
if (!pskb_may_pull(skb, thlen))
goto out;
 
-   oldlen = ~htonl(skb-len);
+   oldlen = (u16)~skb-len;
__skb_pull(skb, thlen);
 
segs = skb_segment(skb, sg);
@@ -2174,7 +2174,7 @@ struct sk_buff *tcp_tso_segment(struct s
goto out;
 
len = skb_shinfo(skb)-gso_size;
-   delta = csum_add(oldlen, htonl(thlen + len));
+   delta = htonl(oldlen + (thlen + len));
 
skb = segs;
th = skb-h.th;
@@ -2183,10 +2183,10 @@ struct sk_buff *tcp_tso_segment(struct s
do {
th-fin = th-psh = 0;
 
-   if (skb-ip_summed == CHECKSUM_NONE) {
-   th-check = csum_fold(csum_partial(
-   skb-h.raw, thlen, csum_add(skb-csum, delta)));
-   }
+   th-check = ~csum_fold(th-check + delta);
+   if (skb-ip_summed != CHECKSUM_HW)
+   th-check = csum_fold(csum_partial(skb-h.raw, thlen,
+  skb-csum));
 
seq += len;
skb = skb-next;
@@ -2196,11 +2196,11 @@ struct sk_buff *tcp_tso_segment(struct s
th-cwr = 0;
} while (skb-next);
 
-   if (skb-ip_summed == CHECKSUM_NONE) {
-   delta = csum_add(oldlen, htonl(skb-tail - skb-h.raw));
-   th-check = csum_fold(csum_partial(
-   skb-h.raw, thlen, csum_add(skb-csum, delta)));
-   }
+   delta = htonl(oldlen + (skb-tail - skb-h.raw) + skb-data_len);
+   th-check = ~csum_fold(th-check + delta);
+   if (skb-ip_summed != CHECKSUM_HW)
+   th-check = csum_fold(csum_partial(skb-h.raw, thlen,
+  skb-csum));
 
 out:
return segs;
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [3/5] [NET]: Add software TSOv4

2006-06-23 Thread Michael Chan
On Sat, 2006-06-24 at 09:53 +1000, Herbert Xu wrote:

 Nevermind, I obviously complete ignored your other fix to the length of
 the last segment :) Here is a fixed version.
 
 [NET]: Fix CHECKSUM_HW GSO problems.
 
 Fix checksum problems in the GSO code path for CHECKSUM_HW packets.
 
 The ipv4 TCP pseudo header checksum has to be adjusted for GSO
 segmented packets.
 
 The adjustment is needed because the length field in the pseudo-header
 changes.  However, because we have the inequality oldlen  newlen, we
 know that delta = (u16)~oldlen + newlen is still a 16-bit quantity.
 This also means that htonl(delta) + th-check still fits in 32 bits.
 Therefore we don't have to use csum_add on this operations.
 
 This is based on a patch by Michael Chan [EMAIL PROTECTED].
 
 Signed-off-by: Herbert Xu [EMAIL PROTECTED]
 
Yes, this should work. ACK.


-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[3/5] [NET]: Add software TSOv4

2006-06-22 Thread Herbert Xu
Hi:

[NET]: Add software TSOv4

This patch adds the GSO implementation for IPv4 TCP.

Signed-off-by: Herbert Xu [EMAIL PROTECTED]

Cheers,
-- 
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmVHI~} [EMAIL PROTECTED]
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1299,6 +1299,7 @@ extern void  skb_split(struct sk_b
 struct sk_buff *skb1, const u32 len);
 
 extern void   skb_release_data(struct sk_buff *skb);
+extern struct sk_buff *skb_segment(struct sk_buff *skb, int sg);
 
 static inline void *skb_header_pointer(const struct sk_buff *skb, int offset,
   int len, void *buffer)
diff --git a/include/net/protocol.h b/include/net/protocol.h
--- a/include/net/protocol.h
+++ b/include/net/protocol.h
@@ -37,6 +37,7 @@
 struct net_protocol {
int (*handler)(struct sk_buff *skb);
void(*err_handler)(struct sk_buff *skb, u32 info);
+   struct sk_buff *(*gso_segment)(struct sk_buff *skb, int sg);
int no_policy;
 };
 
diff --git a/include/net/tcp.h b/include/net/tcp.h
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -1087,6 +1087,8 @@ extern struct request_sock_ops tcp_reque
 
 extern int tcp_v4_destroy_sock(struct sock *sk);
 
+extern struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int sg);
+
 #ifdef CONFIG_PROC_FS
 extern int  tcp4_proc_init(void);
 extern void tcp4_proc_exit(void);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -1826,6 +1826,132 @@ unsigned char *skb_pull_rcsum(struct sk_
 
 EXPORT_SYMBOL_GPL(skb_pull_rcsum);
 
+/**
+ * skb_segment - Perform protocol segmentation on skb.
+ * @skb: buffer to segment
+ * @sg: whether scatter-gather can be used for generated segments
+ *
+ * This function performs segmentation on the given skb.  It returns
+ * the segment at the given position.  It returns NULL if there are
+ * no more segments to generate, or when an error is encountered.
+ */
+struct sk_buff *skb_segment(struct sk_buff *skb, int sg)
+{
+   struct sk_buff *segs = NULL;
+   struct sk_buff *tail = NULL;
+   unsigned int mss = skb_shinfo(skb)-gso_size;
+   unsigned int doffset = skb-data - skb-mac.raw;
+   unsigned int offset = doffset;
+   unsigned int headroom;
+   unsigned int len;
+   int nfrags = skb_shinfo(skb)-nr_frags;
+   int err = -ENOMEM;
+   int i = 0;
+   int pos;
+
+   __skb_push(skb, doffset);
+   headroom = skb_headroom(skb);
+   pos = skb_headlen(skb);
+
+   do {
+   struct sk_buff *nskb;
+   skb_frag_t *frag;
+   int hsize, nsize;
+   int k;
+   int size;
+
+   len = skb-len - offset;
+   if (len  mss)
+   len = mss;
+
+   hsize = skb_headlen(skb) - offset;
+   if (hsize  0)
+   hsize = 0;
+   nsize = hsize + doffset;
+   if (nsize  len + doffset || !sg)
+   nsize = len + doffset;
+
+   nskb = alloc_skb(nsize + headroom, GFP_ATOMIC);
+   if (unlikely(!nskb))
+   goto err;
+
+   if (segs)
+   tail-next = nskb;
+   else
+   segs = nskb;
+   tail = nskb;
+
+   nskb-dev = skb-dev;
+   nskb-priority = skb-priority;
+   nskb-protocol = skb-protocol;
+   nskb-dst = dst_clone(skb-dst);
+   memcpy(nskb-cb, skb-cb, sizeof(skb-cb));
+   nskb-pkt_type = skb-pkt_type;
+   nskb-mac_len = skb-mac_len;
+
+   skb_reserve(nskb, headroom);
+   nskb-mac.raw = nskb-data;
+   nskb-nh.raw = nskb-data + skb-mac_len;
+   nskb-h.raw = nskb-nh.raw + (skb-h.raw - skb-nh.raw);
+   memcpy(skb_put(nskb, doffset), skb-data, doffset);
+
+   if (!sg) {
+   nskb-csum = skb_copy_and_csum_bits(skb, offset,
+   skb_put(nskb, len),
+   len, 0);
+   continue;
+   }
+
+   frag = skb_shinfo(nskb)-frags;
+   k = 0;
+
+   nskb-ip_summed = CHECKSUM_HW;
+   nskb-csum = skb-csum;
+   memcpy(skb_put(nskb, hsize), skb-data + offset, hsize);
+
+   while (pos  offset + len) {
+   BUG_ON(i = nfrags);
+
+   *frag = skb_shinfo(skb)-frags[i];
+   get_page(frag-page);
+

Re: [3/5] [NET]: Add software TSOv4

2006-06-22 Thread Herbert Xu
On Thu, Jun 22, 2006 at 06:14:00PM +1000, herbert wrote:
 
 [NET]: Add software TSOv4

Doh, forgot to remove an unused declaration.  Here is an updated version.

[NET]: Add software TSOv4

This patch adds the GSO implementation for IPv4 TCP.

Signed-off-by: Herbert Xu [EMAIL PROTECTED]

Cheers,
-- 
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmVHI~} [EMAIL PROTECTED]
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -406,6 +406,9 @@ struct net_device
struct list_headqdisc_list;
unsigned long   tx_queue_len;   /* Max frames per queue allowed 
*/
 
+   /* Partially transmitted GSO packet. */
+   struct sk_buff  *gso_skb;
+
/* ingress path synchronizer */
spinlock_t  ingress_lock;
struct Qdisc*qdisc_ingress;
@@ -540,6 +543,7 @@ struct packet_type {
 struct net_device *,
 struct packet_type *,
 struct net_device *);
+   struct sk_buff  *(*gso_segment)(struct sk_buff *skb, int sg);
void*af_packet_priv;
struct list_headlist;
 };
@@ -690,7 +694,8 @@ extern int  dev_change_name(struct net_d
 extern int dev_set_mtu(struct net_device *, int);
 extern int dev_set_mac_address(struct net_device *,
struct sockaddr *);
-extern voiddev_queue_xmit_nit(struct sk_buff *skb, struct 
net_device *dev);
+extern int dev_hard_start_xmit(struct sk_buff *skb,
+   struct net_device *dev);
 
 extern voiddev_init(void);
 
@@ -964,6 +969,7 @@ extern int  netdev_max_backlog;
 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, int inward);
+extern struct sk_buff *skb_gso_segment(struct sk_buff *skb, int sg);
 #ifdef CONFIG_BUG
 extern void netdev_rx_csum_fault(struct net_device *dev);
 #else
diff --git a/net/core/dev.c b/net/core/dev.c
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -116,6 +116,7 @@
 #include asm/current.h
 #include linux/audit.h
 #include linux/dmaengine.h
+#include linux/err.h
 
 /*
  * The list of packet types we will receive (as opposed to discard)
@@ -1048,7 +1049,7 @@ static inline void net_timestamp(struct 
  * taps currently in use.
  */
 
-void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
+static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
 {
struct packet_type *ptype;
 
@@ -1186,6 +1187,40 @@ out: 
return ret;
 }
 
+/**
+ * skb_gso_segment - Perform segmentation on skb.
+ * @skb: buffer to segment
+ * @sg: whether scatter-gather is supported on the target.
+ *
+ * This function segments the given skb and returns a list of segments.
+ */
+struct sk_buff *skb_gso_segment(struct sk_buff *skb, int sg)
+{
+   struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT);
+   struct packet_type *ptype;
+   int type = skb-protocol;
+
+   BUG_ON(skb_shinfo(skb)-frag_list);
+   BUG_ON(skb-ip_summed != CHECKSUM_HW);
+
+   skb-mac.raw = skb-data;
+   skb-mac_len = skb-nh.raw - skb-data;
+   __skb_pull(skb, skb-mac_len);
+
+   rcu_read_lock();
+   list_for_each_entry_rcu(ptype, ptype_base[ntohs(type)  15], list) {
+   if (ptype-type == type  !ptype-dev  ptype-gso_segment) {
+   segs = ptype-gso_segment(skb, sg);
+   break;
+   }
+   }
+   rcu_read_unlock();
+
+   return segs;
+}
+
+EXPORT_SYMBOL(skb_gso_segment);
+
 /* Take action when hardware reception checksum errors are detected. */
 #ifdef CONFIG_BUG
 void netdev_rx_csum_fault(struct net_device *dev)
@@ -1222,6 +1257,86 @@ static inline int illegal_highdma(struct
 #define illegal_highdma(dev, skb)  (0)
 #endif
 
+struct dev_gso_cb {
+   void (*destructor)(struct sk_buff *skb);
+};
+
+#define DEV_GSO_CB(skb) ((struct dev_gso_cb *)(skb)-cb)
+
+static void dev_gso_skb_destructor(struct sk_buff *skb)
+{
+   struct dev_gso_cb *cb;
+
+   do {
+   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)
+   cb-destructor(skb);
+}
+
+/**
+ * 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 

Re: [3/5] [NET]: Add software TSOv4

2006-06-22 Thread YOSHIFUJI Hideaki / 吉藤英明
In article [EMAIL PROTECTED] (at Thu, 22 Jun 2006 18:14:00 +1000), Herbert Xu 
[EMAIL PROTECTED] says:

 [NET]: Add software TSOv4
 
 This patch adds the GSO implementation for IPv4 TCP.
 
 Signed-off-by: Herbert Xu [EMAIL PROTECTED]

I'd appreciate if you code up IPv6 TCP as well. :-)

Regards,

--yoshfuji
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [3/5] [NET]: Add software TSOv4

2006-06-22 Thread David Miller
From: YOSHIFUJI Hideaki [EMAIL PROTECTED]
Date: Fri, 23 Jun 2006 00:04:03 +0900 (JST)

 In article [EMAIL PROTECTED] (at Thu, 22 Jun 2006 18:14:00 +1000), Herbert 
 Xu [EMAIL PROTECTED] says:
 
  [NET]: Add software TSOv4
  
  This patch adds the GSO implementation for IPv4 TCP.
  
  Signed-off-by: Herbert Xu [EMAIL PROTECTED]
 
 I'd appreciate if you code up IPv6 TCP as well. :-)

To my understanding doing IPV6 TCP TSO is a non-trivial task, even in
software.

The header editing is a lot more complicated because things like
routing and other extension headers can sit between IPV6 and TCP
header.

It is probably why IPV6 TSO hardware does not exist yet :)

Do not take this to mean I think it should not be implemented, I think
it should.
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[3/5] [NET]: Add software TSOv4

2006-06-20 Thread Herbert Xu
Hi:

[NET]: Add software TSOv4

This patch adds the GSO implementation for IPv4 TCP.

Signed-off-by: Herbert Xu [EMAIL PROTECTED]

Cheers,
-- 
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmVHI~} [EMAIL PROTECTED]
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1299,6 +1299,7 @@ extern void  skb_split(struct sk_b
 struct sk_buff *skb1, const u32 len);
 
 extern void   skb_release_data(struct sk_buff *skb);
+extern struct sk_buff *skb_segment(struct sk_buff *skb, int sg);
 
 static inline void *skb_header_pointer(const struct sk_buff *skb, int offset,
   int len, void *buffer)
diff --git a/include/net/protocol.h b/include/net/protocol.h
--- a/include/net/protocol.h
+++ b/include/net/protocol.h
@@ -37,6 +37,7 @@
 struct net_protocol {
int (*handler)(struct sk_buff *skb);
void(*err_handler)(struct sk_buff *skb, u32 info);
+   struct sk_buff *(*gso_segment)(struct sk_buff *skb, int sg);
int no_policy;
 };
 
diff --git a/include/net/tcp.h b/include/net/tcp.h
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -1087,6 +1087,8 @@ extern struct request_sock_ops tcp_reque
 
 extern int tcp_v4_destroy_sock(struct sock *sk);
 
+extern struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int sg);
+
 #ifdef CONFIG_PROC_FS
 extern int  tcp4_proc_init(void);
 extern void tcp4_proc_exit(void);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -1826,6 +1826,132 @@ unsigned char *skb_pull_rcsum(struct sk_
 
 EXPORT_SYMBOL_GPL(skb_pull_rcsum);
 
+/**
+ * skb_segment - Perform protocol segmentation on skb.
+ * @skb: buffer to segment
+ * @sg: whether scatter-gather can be used for generated segments
+ *
+ * This function performs segmentation on the given skb.  It returns
+ * the segment at the given position.  It returns NULL if there are
+ * no more segments to generate, or when an error is encountered.
+ */
+struct sk_buff *skb_segment(struct sk_buff *skb, int sg)
+{
+   struct sk_buff *segs = NULL;
+   struct sk_buff *tail = NULL;
+   unsigned int mss = skb_shinfo(skb)-gso_size;
+   unsigned int doffset = skb-data - skb-mac.raw;
+   unsigned int offset = doffset;
+   unsigned int headroom;
+   unsigned int len;
+   int nfrags = skb_shinfo(skb)-nr_frags;
+   int err = -ENOMEM;
+   int i = 0;
+   int pos;
+
+   __skb_push(skb, doffset);
+   headroom = skb_headroom(skb);
+   pos = skb_headlen(skb);
+
+   do {
+   struct sk_buff *nskb;
+   skb_frag_t *frag;
+   int hsize, nsize;
+   int k;
+   int size;
+
+   len = skb-len - offset;
+   if (len  mss)
+   len = mss;
+
+   hsize = skb_headlen(skb) - offset;
+   if (hsize  0)
+   hsize = 0;
+   nsize = hsize + doffset;
+   if (nsize  len + doffset || !sg)
+   nsize = len + doffset;
+
+   nskb = alloc_skb(nsize + headroom, GFP_ATOMIC);
+   if (unlikely(!nskb))
+   goto err;
+
+   if (segs)
+   tail-next = nskb;
+   else
+   segs = nskb;
+   tail = nskb;
+
+   nskb-dev = skb-dev;
+   nskb-priority = skb-priority;
+   nskb-protocol = skb-protocol;
+   nskb-dst = dst_clone(skb-dst);
+   memcpy(nskb-cb, skb-cb, sizeof(skb-cb));
+   nskb-pkt_type = skb-pkt_type;
+   nskb-mac_len = skb-mac_len;
+
+   skb_reserve(nskb, headroom);
+   nskb-mac.raw = nskb-data;
+   nskb-nh.raw = nskb-data + skb-mac_len;
+   nskb-h.raw = nskb-nh.raw + (skb-h.raw - skb-nh.raw);
+   memcpy(skb_put(nskb, doffset), skb-data, doffset);
+
+   if (!sg) {
+   nskb-csum = skb_copy_and_csum_bits(skb, offset,
+   skb_put(nskb, len),
+   len, 0);
+   continue;
+   }
+
+   frag = skb_shinfo(nskb)-frags;
+   k = 0;
+
+   nskb-ip_summed = CHECKSUM_HW;
+   nskb-csum = skb-csum;
+   memcpy(skb_put(nskb, hsize), skb-data + offset, hsize);
+
+   while (pos  offset + len) {
+   BUG_ON(i = nfrags);
+
+   *frag = skb_shinfo(skb)-frags[i];
+   get_page(frag-page);
+