aboutsummaryrefslogtreecommitdiff
path: root/net/core/timestamping.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/timestamping.c')
-rw-r--r--net/core/timestamping.c40
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);