netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] netpoll: Fix skb tail pointer in netpoll_send_udp()
@ 2012-06-12 10:26 Bogdan Hamciuc
  2012-06-12 10:26 ` [PATCH] netpoll: Add support for hardware checksumming on egress Bogdan Hamciuc
  2012-06-12 12:22 ` [PATCH] netpoll: Fix skb tail pointer in netpoll_send_udp() Eric Dumazet
  0 siblings, 2 replies; 7+ messages in thread
From: Bogdan Hamciuc @ 2012-06-12 10:26 UTC (permalink / raw)
  To: davem; +Cc: netdev, Bogdan Hamciuc

As skb->tail wasn't updated after skb_copy_to_linear_data(), subsequent
calls to skb_realloc_headroom() (as made by an ethernet driver's
ndo_start_xmit routine) would only effectively copy the packet headers,
leaving garbage in the payload.

In the process, removed some unnecessary code.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
---
 net/core/netpoll.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 3d84fb9..9a08068 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -362,22 +362,22 @@ EXPORT_SYMBOL(netpoll_send_skb_on_dev);
 
 void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
 {
-	int total_len, eth_len, ip_len, udp_len;
+	int total_len, ip_len, udp_len;
 	struct sk_buff *skb;
 	struct udphdr *udph;
 	struct iphdr *iph;
 	struct ethhdr *eth;
 
 	udp_len = len + sizeof(*udph);
-	ip_len = eth_len = udp_len + sizeof(*iph);
-	total_len = eth_len + ETH_HLEN + NET_IP_ALIGN;
+	ip_len = udp_len + sizeof(*iph);
+	total_len = ip_len + ETH_HLEN + NET_IP_ALIGN;
 
 	skb = find_skb(np, total_len, total_len - len);
 	if (!skb)
 		return;
 
 	skb_copy_to_linear_data(skb, msg, len);
-	skb->len += len;
+	skb_put(skb, len);
 
 	skb_push(skb, sizeof(*udph));
 	skb_reset_transport_header(skb);
-- 
1.5.6.3

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH] netpoll: Add support for hardware checksumming on egress
  2012-06-12 10:26 [PATCH] netpoll: Fix skb tail pointer in netpoll_send_udp() Bogdan Hamciuc
@ 2012-06-12 10:26 ` Bogdan Hamciuc
  2012-06-12 12:43   ` Eric Dumazet
  2012-06-12 12:22 ` [PATCH] netpoll: Fix skb tail pointer in netpoll_send_udp() Eric Dumazet
  1 sibling, 1 reply; 7+ messages in thread
From: Bogdan Hamciuc @ 2012-06-12 10:26 UTC (permalink / raw)
  To: davem; +Cc: netdev, Bogdan Hamciuc

Netpoll used to compute its own csum; but if the device supports, we
should let it do the checksum itself.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
---
 net/core/netpoll.c |   14 ++++++++++----
 1 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 9a08068..f5d00b4 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -385,13 +385,19 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
 	udph->source = htons(np->local_port);
 	udph->dest = htons(np->remote_port);
 	udph->len = htons(udp_len);
-	udph->check = 0;
-	udph->check = csum_tcpudp_magic(np->local_ip,
+
+	/* Only querying the IPv4 csumming capabilities */
+	if (np->dev->features & NETIF_F_IP_CSUM)
+		skb->ip_summed = CHECKSUM_PARTIAL;
+	else {
+		skb->ip_summed = CHECKSUM_NONE;
+		udph->check = csum_tcpudp_magic(np->local_ip,
 					np->remote_ip,
 					udp_len, IPPROTO_UDP,
 					csum_partial(udph, udp_len, 0));
-	if (udph->check == 0)
-		udph->check = CSUM_MANGLED_0;
+		if (udph->check == 0)
+			udph->check = CSUM_MANGLED_0;
+	}
 
 	skb_push(skb, sizeof(*iph));
 	skb_reset_network_header(skb);
-- 
1.5.6.3

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH] netpoll: Fix skb tail pointer in netpoll_send_udp()
  2012-06-12 10:26 [PATCH] netpoll: Fix skb tail pointer in netpoll_send_udp() Bogdan Hamciuc
  2012-06-12 10:26 ` [PATCH] netpoll: Add support for hardware checksumming on egress Bogdan Hamciuc
@ 2012-06-12 12:22 ` Eric Dumazet
  2012-06-12 13:15   ` Eric Dumazet
  1 sibling, 1 reply; 7+ messages in thread
From: Eric Dumazet @ 2012-06-12 12:22 UTC (permalink / raw)
  To: Bogdan Hamciuc; +Cc: davem, netdev

On Tue, 2012-06-12 at 13:26 +0300, Bogdan Hamciuc wrote:
> As skb->tail wasn't updated after skb_copy_to_linear_data(), subsequent
> calls to skb_realloc_headroom() (as made by an ethernet driver's
> ndo_start_xmit routine) would only effectively copy the packet headers,
> leaving garbage in the payload.
> 
> In the process, removed some unnecessary code.
> 
> Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
> ---
>  net/core/netpoll.c |    8 ++++----
>  1 files changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/net/core/netpoll.c b/net/core/netpoll.c
> index 3d84fb9..9a08068 100644
> --- a/net/core/netpoll.c
> +++ b/net/core/netpoll.c
> @@ -362,22 +362,22 @@ EXPORT_SYMBOL(netpoll_send_skb_on_dev);
>  
>  void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
>  {
> -	int total_len, eth_len, ip_len, udp_len;
> +	int total_len, ip_len, udp_len;
>  	struct sk_buff *skb;
>  	struct udphdr *udph;
>  	struct iphdr *iph;
>  	struct ethhdr *eth;
>  
>  	udp_len = len + sizeof(*udph);
> -	ip_len = eth_len = udp_len + sizeof(*iph);
> -	total_len = eth_len + ETH_HLEN + NET_IP_ALIGN;
> +	ip_len = udp_len + sizeof(*iph);
> +	total_len = ip_len + ETH_HLEN + NET_IP_ALIGN;
>  
>  	skb = find_skb(np, total_len, total_len - len);
>  	if (!skb)
>  		return;
>  
>  	skb_copy_to_linear_data(skb, msg, len);
> -	skb->len += len;
> +	skb_put(skb, len);
>  
>  	skb_push(skb, sizeof(*udph));
>  	skb_reset_transport_header(skb);

Hmm, real question is why skb_realloc_headroom() is even necessary...

I suspect we need to reserve more bytes.

	total_len = ip_len + ETH_HLEN + NET_IP_ALIGN + NET_SKB_PAD;

or something like that ?

Which driver triggers the bug ?

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] netpoll: Add support for hardware checksumming on egress
  2012-06-12 10:26 ` [PATCH] netpoll: Add support for hardware checksumming on egress Bogdan Hamciuc
@ 2012-06-12 12:43   ` Eric Dumazet
  0 siblings, 0 replies; 7+ messages in thread
From: Eric Dumazet @ 2012-06-12 12:43 UTC (permalink / raw)
  To: Bogdan Hamciuc; +Cc: davem, netdev

On Tue, 2012-06-12 at 13:26 +0300, Bogdan Hamciuc wrote:
> Netpoll used to compute its own csum; but if the device supports, we
> should let it do the checksum itself.
> 
> Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
> ---
>  net/core/netpoll.c |   14 ++++++++++----
>  1 files changed, 10 insertions(+), 4 deletions(-)
> 
> diff --git a/net/core/netpoll.c b/net/core/netpoll.c
> index 9a08068..f5d00b4 100644
> --- a/net/core/netpoll.c
> +++ b/net/core/netpoll.c
> @@ -385,13 +385,19 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
>  	udph->source = htons(np->local_port);
>  	udph->dest = htons(np->remote_port);
>  	udph->len = htons(udp_len);
> -	udph->check = 0;
> -	udph->check = csum_tcpudp_magic(np->local_ip,
> +
> +	/* Only querying the IPv4 csumming capabilities */
> +	if (np->dev->features & NETIF_F_IP_CSUM)
> +		skb->ip_summed = CHECKSUM_PARTIAL;
> +	else {
> +		skb->ip_summed = CHECKSUM_NONE;
> +		udph->check = csum_tcpudp_magic(np->local_ip,
>  					np->remote_ip,
>  					udp_len, IPPROTO_UDP,
>  					csum_partial(udph, udp_len, 0));
> -	if (udph->check == 0)
> -		udph->check = CSUM_MANGLED_0;
> +		if (udph->check == 0)
> +			udph->check = CSUM_MANGLED_0;
> +	}
>  
>  	skb_push(skb, sizeof(*iph));
>  	skb_reset_network_header(skb);

Hi Bogdan

I cant see how this can possibly work ?

Which NIC was able to send a good UDP frame after this patch ?

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] netpoll: Fix skb tail pointer in netpoll_send_udp()
  2012-06-12 12:22 ` [PATCH] netpoll: Fix skb tail pointer in netpoll_send_udp() Eric Dumazet
@ 2012-06-12 13:15   ` Eric Dumazet
  2012-06-12 13:34     ` Eric Dumazet
  0 siblings, 1 reply; 7+ messages in thread
From: Eric Dumazet @ 2012-06-12 13:15 UTC (permalink / raw)
  To: Bogdan Hamciuc; +Cc: davem, netdev

On Tue, 2012-06-12 at 14:22 +0200, Eric Dumazet wrote:
> On Tue, 2012-06-12 at 13:26 +0300, Bogdan Hamciuc wrote:
> > As skb->tail wasn't updated after skb_copy_to_linear_data(), subsequent
> > calls to skb_realloc_headroom() (as made by an ethernet driver's
> > ndo_start_xmit routine) would only effectively copy the packet headers,
> > leaving garbage in the payload.
> > 
> > In the process, removed some unnecessary code.
> > 
> > Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
> > ---
> >  net/core/netpoll.c |    8 ++++----
> >  1 files changed, 4 insertions(+), 4 deletions(-)
> > 
> > diff --git a/net/core/netpoll.c b/net/core/netpoll.c
> > index 3d84fb9..9a08068 100644
> > --- a/net/core/netpoll.c
> > +++ b/net/core/netpoll.c
> > @@ -362,22 +362,22 @@ EXPORT_SYMBOL(netpoll_send_skb_on_dev);
> >  
> >  void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
> >  {
> > -	int total_len, eth_len, ip_len, udp_len;
> > +	int total_len, ip_len, udp_len;
> >  	struct sk_buff *skb;
> >  	struct udphdr *udph;
> >  	struct iphdr *iph;
> >  	struct ethhdr *eth;
> >  
> >  	udp_len = len + sizeof(*udph);
> > -	ip_len = eth_len = udp_len + sizeof(*iph);
> > -	total_len = eth_len + ETH_HLEN + NET_IP_ALIGN;
> > +	ip_len = udp_len + sizeof(*iph);
> > +	total_len = ip_len + ETH_HLEN + NET_IP_ALIGN;
> >  
> >  	skb = find_skb(np, total_len, total_len - len);
> >  	if (!skb)
> >  		return;
> >  
> >  	skb_copy_to_linear_data(skb, msg, len);
> > -	skb->len += len;
> > +	skb_put(skb, len);
> >  
> >  	skb_push(skb, sizeof(*udph));
> >  	skb_reset_transport_header(skb);
> 
> Hmm, real question is why skb_realloc_headroom() is even necessary...
> 
> I suspect we need to reserve more bytes.
> 
> 	total_len = ip_len + ETH_HLEN + NET_IP_ALIGN + NET_SKB_PAD;
> 
> or something like that ?
> 
> Which driver triggers the bug ?
> 

Please try the following :

diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 3d84fb9..1c6fb72 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -362,17 +362,18 @@ EXPORT_SYMBOL(netpoll_send_skb_on_dev);
 
 void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
 {
-	int total_len, eth_len, ip_len, udp_len;
+	int total_len, ip_len, udp_len;
 	struct sk_buff *skb;
 	struct udphdr *udph;
 	struct iphdr *iph;
 	struct ethhdr *eth;
 
 	udp_len = len + sizeof(*udph);
-	ip_len = eth_len = udp_len + sizeof(*iph);
-	total_len = eth_len + ETH_HLEN + NET_IP_ALIGN;
+	ip_len = udp_len + sizeof(*iph);
+	total_len = ip_len + LL_RESERVED_SPACE(np->dev);
 
-	skb = find_skb(np, total_len, total_len - len);
+	skb = find_skb(np, total_len + np->dev->needed_tailroom,
+		       total_len - len);
 	if (!skb)
 		return;
 

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH] netpoll: Fix skb tail pointer in netpoll_send_udp()
  2012-06-12 13:15   ` Eric Dumazet
@ 2012-06-12 13:34     ` Eric Dumazet
  2012-06-12 15:08       ` Hamciuc Bogdan-BHAMCIU1
  0 siblings, 1 reply; 7+ messages in thread
From: Eric Dumazet @ 2012-06-12 13:34 UTC (permalink / raw)
  To: Bogdan Hamciuc; +Cc: davem, netdev

On Tue, 2012-06-12 at 15:15 +0200, Eric Dumazet wrote:
> On Tue, 2012-06-12 at 14:22 +0200, Eric Dumazet wrote:

> > Hmm, real question is why skb_realloc_headroom() is even necessary...
> > 
> > I suspect we need to reserve more bytes.
> > 
> > 	total_len = ip_len + ETH_HLEN + NET_IP_ALIGN + NET_SKB_PAD;
> > 
> > or something like that ?
> > 
> > Which driver triggers the bug ?
> > 

In case you wonder why I try so hard to avoid the
skb_realloc_headroom() :

netpoll has complicated^Wspecial^Wnice skb cache, to make sure it can
work even if memory is exhausted.

But if we trigger skb_realloc_headroom() the whole thing is useless. 

Thanks

^ permalink raw reply	[flat|nested] 7+ messages in thread

* RE: [PATCH] netpoll: Fix skb tail pointer in netpoll_send_udp()
  2012-06-12 13:34     ` Eric Dumazet
@ 2012-06-12 15:08       ` Hamciuc Bogdan-BHAMCIU1
  0 siblings, 0 replies; 7+ messages in thread
From: Hamciuc Bogdan-BHAMCIU1 @ 2012-06-12 15:08 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: davem, netdev

Hi Eric,

> -----Original Message-----
> From: Eric Dumazet [mailto:eric.dumazet@gmail.com]
> Sent: Tuesday, June 12, 2012 4:34 PM
> To: Hamciuc Bogdan-BHAMCIU1
> Cc: davem@davemloft.net; netdev@vger.kernel.org
> Subject: Re: [PATCH] netpoll: Fix skb tail pointer in netpoll_send_udp()
> 
> On Tue, 2012-06-12 at 15:15 +0200, Eric Dumazet wrote:
> > On Tue, 2012-06-12 at 14:22 +0200, Eric Dumazet wrote:
> 
> > > Hmm, real question is why skb_realloc_headroom() is even necessary...
Our driver (Freescale P4080, unfortunately not upstream yet) needs a minimum amount of headroom in order to communicate metadata to the NIC.
For instance, frame offsets to the protocol headers are stored there, which the NIC then uses to fill in the egress checksum.
Originating frames, on the other hand, don't always have that amount of headroom, so we occasionally need to realloc. 
> > >
> > > I suspect we need to reserve more bytes.
> > >
> > > 	total_len = ip_len + ETH_HLEN + NET_IP_ALIGN + NET_SKB_PAD;
> > >
> > > or something like that ?
Indeed, your counter-proposal patch (adding LL_RESERVED_SPACE()) worked fine.

> > >
> > > Which driver triggers the bug ?
> > >
> 
> In case you wonder why I try so hard to avoid the
> skb_realloc_headroom() :
> 
> netpoll has complicated^Wspecial^Wnice skb cache, to make sure it can
> work even if memory is exhausted.
> 
> But if we trigger skb_realloc_headroom() the whole thing is useless.
> 
Thank you,
Bogdan


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2012-06-12 15:22 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-06-12 10:26 [PATCH] netpoll: Fix skb tail pointer in netpoll_send_udp() Bogdan Hamciuc
2012-06-12 10:26 ` [PATCH] netpoll: Add support for hardware checksumming on egress Bogdan Hamciuc
2012-06-12 12:43   ` Eric Dumazet
2012-06-12 12:22 ` [PATCH] netpoll: Fix skb tail pointer in netpoll_send_udp() Eric Dumazet
2012-06-12 13:15   ` Eric Dumazet
2012-06-12 13:34     ` Eric Dumazet
2012-06-12 15:08       ` Hamciuc Bogdan-BHAMCIU1

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).