diff options
Diffstat (limited to 'net/core/timestamping.c')
| -rw-r--r-- | net/core/timestamping.c | 42 |
1 files changed, 25 insertions, 17 deletions
diff --git a/net/core/timestamping.c b/net/core/timestamping.c index 0ae6c22da85..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> +#include <linux/export.h> -static struct sock_filter ptp_filter[] = { - PTP_FILTER -}; - -static unsigned int classify(struct sk_buff *skb) +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, ARRAY_SIZE(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); |
