Patchwork [v2] gianfar: Fix invalid TX frames returned on error queue when time stamping.

login
register
mail settings
Submitter Eric Dumazet
Date Jan. 9, 2012, 3:12 p.m.
Message ID <1326121920.2407.6.camel@edumazet-HP-Compaq-6005-Pro-SFF-PC>
Download mbox | patch
Permalink /patch/135037/
State RFC
Delegated to: David Miller
Headers show

Comments

Eric Dumazet - Jan. 9, 2012, 3:12 p.m.
Le lundi 09 janvier 2012 à 15:52 +0100, Manfred Rudigier a écrit :
> When TX time stamping for PTP messages is enabled on a socket, a time
> stamp is returned on the socket error queue to the user space application
> after the frame was transmitted. The transmitted frame is also returned on
> the error queue so that an application knows to which frame the time stamp
> belongs.

...

>  	/* make space for additional header when fcb is needed */
>  	if (((skb->ip_summed == CHECKSUM_PARTIAL) ||
>  			vlan_tx_tag_present(skb) ||
>  			unlikely(do_tstamp)) &&
> -			(skb_headroom(skb) < GMAC_FCB_LEN)) {
> +			(skb_headroom(skb) < fcb_length)) {
>  		struct sk_buff *skb_new;
>  
> -		skb_new = skb_realloc_headroom(skb, GMAC_FCB_LEN);
> +		skb_new = skb_realloc_headroom(skb, fcb_length);
>  		if (!skb_new) {
>  			dev->stats.tx_errors++;
>  			kfree_skb(skb);
>  			return NETDEV_TX_OK;
>  		}
> +
> +		/* Hold sock reference for processing TX time stamps */
> +		if (unlikely(do_tstamp)) {
> +			struct sock *sk = skb->sk;

Not clear to me why sk_refcnt could be 0 here

> +			if (!atomic_inc_not_zero(&sk->sk_refcnt)) {
> +				dev->stats.tx_errors++;
> +				kfree_skb(skb_new);
> +				kfree_skb(skb);
> +				return NETDEV_TX_OK;
> +			}
> +			skb_new->sk = skb->sk;
> +		}
> +
>  		kfree_skb(skb);
>  		skb = skb_new;

Not clear to me why ->destructor access is not needed here.

This change should be isolated from your patch IMHO

I would rather do something like :



--
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
Manfred Rudigier - Jan. 10, 2012, 9:05 a.m.
From: netdev-owner@vger.kernel.org [mailto:netdev-

owner@vger.kernel.org] On Behalf Of Eric Dumazet
Sent: Monday, January 09, 2012 16:12

>> +

>> +		/* Hold sock reference for processing TX time stamps */

>> +		if (unlikely(do_tstamp)) {

>> +			struct sock *sk = skb->sk;

>

>Not clear to me why sk_refcnt could be 0 here


Well, I have tried to make a similar solution as outlined in commit da92b194cc36b5dc1fbd85206aeeffd80bee0c39.

>I would rather do something like :

>

>diff --git a/drivers/net/ethernet/freescale/gianfar.c

>b/drivers/net/ethernet/freescale/gianfar.c

>index e01cdaa..8e00461 100644

>--- a/drivers/net/ethernet/freescale/gianfar.c

>+++ b/drivers/net/ethernet/freescale/gianfar.c

>@@ -2086,6 +2086,8 @@ static int gfar_start_xmit(struct sk_buff *skb, struct

>net_device *dev)

> 			kfree_skb(skb);

> 			return NETDEV_TX_OK;

> 		}

>+		swap(skb_new->sk, skb->sk);

>+		swap(skb_new->destructor, skb->destructor);

> 		kfree_skb(skb);

> 		skb = skb_new;

> 	}


I guess this should also work, so I will come up with a new version.

Patch

diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index e01cdaa..8e00461 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -2086,6 +2086,8 @@  static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
 			kfree_skb(skb);
 			return NETDEV_TX_OK;
 		}
+		swap(skb_new->sk, skb->sk);
+		swap(skb_new->destructor, skb->destructor);
 		kfree_skb(skb);
 		skb = skb_new;
 	}