diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/Kconfig | 10 | ||||
-rw-r--r-- | net/core/Makefile | 2 | ||||
-rw-r--r-- | net/core/dev.c | 3 | ||||
-rw-r--r-- | net/core/timestamping.c | 126 | ||||
-rw-r--r-- | net/socket.c | 4 |
5 files changed, 144 insertions, 1 deletions
diff --git a/net/Kconfig b/net/Kconfig index 0d68b40fc0e..b3250944cde 100644 --- a/net/Kconfig +++ b/net/Kconfig | |||
@@ -86,6 +86,16 @@ config NETWORK_SECMARK | |||
86 | to nfmark, but designated for security purposes. | 86 | to nfmark, but designated for security purposes. |
87 | If you are unsure how to answer this question, answer N. | 87 | If you are unsure how to answer this question, answer N. |
88 | 88 | ||
89 | config NETWORK_PHY_TIMESTAMPING | ||
90 | bool "Timestamping in PHY devices" | ||
91 | depends on EXPERIMENTAL | ||
92 | help | ||
93 | This allows timestamping of network packets by PHYs with | ||
94 | hardware timestamping capabilities. This option adds some | ||
95 | overhead in the transmit and receive paths. | ||
96 | |||
97 | If you are unsure how to answer this question, answer N. | ||
98 | |||
89 | menuconfig NETFILTER | 99 | menuconfig NETFILTER |
90 | bool "Network packet filtering framework (Netfilter)" | 100 | bool "Network packet filtering framework (Netfilter)" |
91 | ---help--- | 101 | ---help--- |
diff --git a/net/core/Makefile b/net/core/Makefile index 51c3eec850e..8a04dd22cf7 100644 --- a/net/core/Makefile +++ b/net/core/Makefile | |||
@@ -18,4 +18,4 @@ obj-$(CONFIG_NET_DMA) += user_dma.o | |||
18 | obj-$(CONFIG_FIB_RULES) += fib_rules.o | 18 | obj-$(CONFIG_FIB_RULES) += fib_rules.o |
19 | obj-$(CONFIG_TRACEPOINTS) += net-traces.o | 19 | obj-$(CONFIG_TRACEPOINTS) += net-traces.o |
20 | obj-$(CONFIG_NET_DROP_MONITOR) += drop_monitor.o | 20 | obj-$(CONFIG_NET_DROP_MONITOR) += drop_monitor.o |
21 | 21 | obj-$(CONFIG_NETWORK_PHY_TIMESTAMPING) += timestamping.o | |
diff --git a/net/core/dev.c b/net/core/dev.c index e2b9fa2c917..1c002c7ef5d 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -2957,6 +2957,9 @@ int netif_receive_skb(struct sk_buff *skb) | |||
2957 | if (netdev_tstamp_prequeue) | 2957 | if (netdev_tstamp_prequeue) |
2958 | net_timestamp_check(skb); | 2958 | net_timestamp_check(skb); |
2959 | 2959 | ||
2960 | if (skb_defer_rx_timestamp(skb)) | ||
2961 | return NET_RX_SUCCESS; | ||
2962 | |||
2960 | #ifdef CONFIG_RPS | 2963 | #ifdef CONFIG_RPS |
2961 | { | 2964 | { |
2962 | struct rps_dev_flow voidflow, *rflow = &voidflow; | 2965 | struct rps_dev_flow voidflow, *rflow = &voidflow; |
diff --git a/net/core/timestamping.c b/net/core/timestamping.c new file mode 100644 index 00000000000..0ae6c22da85 --- /dev/null +++ b/net/core/timestamping.c | |||
@@ -0,0 +1,126 @@ | |||
1 | /* | ||
2 | * PTP 1588 clock support - support for timestamping in PHY devices | ||
3 | * | ||
4 | * Copyright (C) 2010 OMICRON electronics GmbH | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | #include <linux/errqueue.h> | ||
21 | #include <linux/phy.h> | ||
22 | #include <linux/ptp_classify.h> | ||
23 | #include <linux/skbuff.h> | ||
24 | |||
25 | static struct sock_filter ptp_filter[] = { | ||
26 | PTP_FILTER | ||
27 | }; | ||
28 | |||
29 | static unsigned int classify(struct sk_buff *skb) | ||
30 | { | ||
31 | if (likely(skb->dev && | ||
32 | skb->dev->phydev && | ||
33 | skb->dev->phydev->drv)) | ||
34 | return sk_run_filter(skb, ptp_filter, ARRAY_SIZE(ptp_filter)); | ||
35 | else | ||
36 | return PTP_CLASS_NONE; | ||
37 | } | ||
38 | |||
39 | void skb_clone_tx_timestamp(struct sk_buff *skb) | ||
40 | { | ||
41 | struct phy_device *phydev; | ||
42 | struct sk_buff *clone; | ||
43 | struct sock *sk = skb->sk; | ||
44 | unsigned int type; | ||
45 | |||
46 | if (!sk) | ||
47 | return; | ||
48 | |||
49 | type = classify(skb); | ||
50 | |||
51 | switch (type) { | ||
52 | case PTP_CLASS_V1_IPV4: | ||
53 | case PTP_CLASS_V1_IPV6: | ||
54 | case PTP_CLASS_V2_IPV4: | ||
55 | case PTP_CLASS_V2_IPV6: | ||
56 | case PTP_CLASS_V2_L2: | ||
57 | case PTP_CLASS_V2_VLAN: | ||
58 | phydev = skb->dev->phydev; | ||
59 | if (likely(phydev->drv->txtstamp)) { | ||
60 | clone = skb_clone(skb, GFP_ATOMIC); | ||
61 | if (!clone) | ||
62 | return; | ||
63 | clone->sk = sk; | ||
64 | phydev->drv->txtstamp(phydev, clone, type); | ||
65 | } | ||
66 | break; | ||
67 | default: | ||
68 | break; | ||
69 | } | ||
70 | } | ||
71 | |||
72 | void skb_complete_tx_timestamp(struct sk_buff *skb, | ||
73 | struct skb_shared_hwtstamps *hwtstamps) | ||
74 | { | ||
75 | struct sock *sk = skb->sk; | ||
76 | struct sock_exterr_skb *serr; | ||
77 | int err; | ||
78 | |||
79 | if (!hwtstamps) | ||
80 | return; | ||
81 | |||
82 | *skb_hwtstamps(skb) = *hwtstamps; | ||
83 | serr = SKB_EXT_ERR(skb); | ||
84 | memset(serr, 0, sizeof(*serr)); | ||
85 | serr->ee.ee_errno = ENOMSG; | ||
86 | serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING; | ||
87 | skb->sk = NULL; | ||
88 | err = sock_queue_err_skb(sk, skb); | ||
89 | if (err) | ||
90 | kfree_skb(skb); | ||
91 | } | ||
92 | EXPORT_SYMBOL_GPL(skb_complete_tx_timestamp); | ||
93 | |||
94 | bool skb_defer_rx_timestamp(struct sk_buff *skb) | ||
95 | { | ||
96 | struct phy_device *phydev; | ||
97 | unsigned int type; | ||
98 | |||
99 | skb_push(skb, ETH_HLEN); | ||
100 | |||
101 | type = classify(skb); | ||
102 | |||
103 | skb_pull(skb, ETH_HLEN); | ||
104 | |||
105 | switch (type) { | ||
106 | case PTP_CLASS_V1_IPV4: | ||
107 | case PTP_CLASS_V1_IPV6: | ||
108 | case PTP_CLASS_V2_IPV4: | ||
109 | case PTP_CLASS_V2_IPV6: | ||
110 | case PTP_CLASS_V2_L2: | ||
111 | case PTP_CLASS_V2_VLAN: | ||
112 | phydev = skb->dev->phydev; | ||
113 | if (likely(phydev->drv->rxtstamp)) | ||
114 | return phydev->drv->rxtstamp(phydev, skb, type); | ||
115 | break; | ||
116 | default: | ||
117 | break; | ||
118 | } | ||
119 | |||
120 | return false; | ||
121 | } | ||
122 | |||
123 | void __init skb_timestamping_init(void) | ||
124 | { | ||
125 | BUG_ON(sk_chk_filter(ptp_filter, ARRAY_SIZE(ptp_filter))); | ||
126 | } | ||
diff --git a/net/socket.c b/net/socket.c index 6fe484122a4..2270b941bcc 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -2394,6 +2394,10 @@ static int __init sock_init(void) | |||
2394 | netfilter_init(); | 2394 | netfilter_init(); |
2395 | #endif | 2395 | #endif |
2396 | 2396 | ||
2397 | #ifdef CONFIG_NETWORK_PHY_TIMESTAMPING | ||
2398 | skb_timestamping_init(); | ||
2399 | #endif | ||
2400 | |||
2397 | return 0; | 2401 | return 0; |
2398 | } | 2402 | } |
2399 | 2403 | ||