diff options
Diffstat (limited to 'net/core/timestamping.c')
| -rw-r--r-- | net/core/timestamping.c | 40 | 
1 files changed, 24 insertions, 16 deletions
diff --git a/net/core/timestamping.c b/net/core/timestamping.c index b124d28ff1c..6521dfd8b7c 100644 --- a/net/core/timestamping.c +++ b/net/core/timestamping.c @@ -21,17 +21,13 @@  #include <linux/phy.h>  #include <linux/ptp_classify.h>  #include <linux/skbuff.h> - -static struct sock_filter ptp_filter[] = { -	PTP_FILTER -}; +#include <linux/export.h>  static unsigned int classify(const struct sk_buff *skb)  { -	if (likely(skb->dev && -		   skb->dev->phydev && +	if (likely(skb->dev && skb->dev->phydev &&  		   skb->dev->phydev->drv)) -		return sk_run_filter(skb, ptp_filter); +		return ptp_classify_raw(skb);  	else  		return PTP_CLASS_NONE;  } @@ -57,9 +53,15 @@ void skb_clone_tx_timestamp(struct sk_buff *skb)  	case PTP_CLASS_V2_VLAN:  		phydev = skb->dev->phydev;  		if (likely(phydev->drv->txtstamp)) { +			if (!atomic_inc_not_zero(&sk->sk_refcnt)) +				return; +  			clone = skb_clone(skb, GFP_ATOMIC); -			if (!clone) +			if (!clone) { +				sock_put(sk);  				return; +			} +  			clone->sk = sk;  			phydev->drv->txtstamp(phydev, clone, type);  		} @@ -68,6 +70,7 @@ void skb_clone_tx_timestamp(struct sk_buff *skb)  		break;  	}  } +EXPORT_SYMBOL_GPL(skb_clone_tx_timestamp);  void skb_complete_tx_timestamp(struct sk_buff *skb,  			       struct skb_shared_hwtstamps *hwtstamps) @@ -76,16 +79,23 @@ void skb_complete_tx_timestamp(struct sk_buff *skb,  	struct sock_exterr_skb *serr;  	int err; -	if (!hwtstamps) +	if (!hwtstamps) { +		sock_put(sk); +		kfree_skb(skb);  		return; +	}  	*skb_hwtstamps(skb) = *hwtstamps; +  	serr = SKB_EXT_ERR(skb);  	memset(serr, 0, sizeof(*serr));  	serr->ee.ee_errno = ENOMSG;  	serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING;  	skb->sk = NULL; +  	err = sock_queue_err_skb(sk, skb); + +	sock_put(sk);  	if (err)  		kfree_skb(skb);  } @@ -96,11 +106,13 @@ bool skb_defer_rx_timestamp(struct sk_buff *skb)  	struct phy_device *phydev;  	unsigned int type; -	skb_push(skb, ETH_HLEN); +	if (skb_headroom(skb) < ETH_HLEN) +		return false; +	__skb_push(skb, ETH_HLEN);  	type = classify(skb); -	skb_pull(skb, ETH_HLEN); +	__skb_pull(skb, ETH_HLEN);  	switch (type) {  	case PTP_CLASS_V1_IPV4: @@ -119,8 +131,4 @@ bool skb_defer_rx_timestamp(struct sk_buff *skb)  	return false;  } - -void __init skb_timestamping_init(void) -{ -	BUG_ON(sk_chk_filter(ptp_filter, ARRAY_SIZE(ptp_filter))); -} +EXPORT_SYMBOL_GPL(skb_defer_rx_timestamp);  | 
