Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
net
core
timestamping.c
Go to the documentation of this file.
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
#include <linux/export.h>
25
26
static
struct
sock_filter
ptp_filter[] = {
27
PTP_FILTER
28
};
29
30
static
unsigned
int
classify(
const
struct
sk_buff
*
skb
)
31
{
32
if
(
likely
(skb->
dev
&&
33
skb->
dev
->phydev &&
34
skb->
dev
->phydev->drv))
35
return
sk_run_filter
(skb, ptp_filter);
36
else
37
return
PTP_CLASS_NONE
;
38
}
39
40
void
skb_clone_tx_timestamp
(
struct
sk_buff
*skb)
41
{
42
struct
phy_device
*phydev;
43
struct
sk_buff
*clone;
44
struct
sock
*
sk
= skb->
sk
;
45
unsigned
int
type
;
46
47
if
(!sk)
48
return
;
49
50
type = classify(skb);
51
52
switch
(type) {
53
case
PTP_CLASS_V1_IPV4
:
54
case
PTP_CLASS_V1_IPV6
:
55
case
PTP_CLASS_V2_IPV4
:
56
case
PTP_CLASS_V2_IPV6
:
57
case
PTP_CLASS_V2_L2
:
58
case
PTP_CLASS_V2_VLAN
:
59
phydev = skb->
dev
->phydev;
60
if
(
likely
(phydev->
drv
->txtstamp)) {
61
if
(!
atomic_inc_not_zero
(&sk->sk_refcnt))
62
return
;
63
clone =
skb_clone
(skb,
GFP_ATOMIC
);
64
if
(!clone) {
65
sock_put(sk);
66
return
;
67
}
68
clone->
sk
=
sk
;
69
phydev->
drv
->txtstamp(phydev, clone, type);
70
}
71
break
;
72
default
:
73
break
;
74
}
75
}
76
EXPORT_SYMBOL_GPL
(
skb_clone_tx_timestamp
);
77
78
void
skb_complete_tx_timestamp
(
struct
sk_buff
*skb,
79
struct
skb_shared_hwtstamps
*hwtstamps)
80
{
81
struct
sock
*
sk
= skb->
sk
;
82
struct
sock_exterr_skb
*
serr
;
83
int
err
;
84
85
if
(!hwtstamps) {
86
sock_put(sk);
87
kfree_skb
(skb);
88
return
;
89
}
90
91
*skb_hwtstamps(skb) = *hwtstamps;
92
serr =
SKB_EXT_ERR
(skb);
93
memset
(serr, 0,
sizeof
(*serr));
94
serr->
ee
.ee_errno =
ENOMSG
;
95
serr->
ee
.ee_origin =
SO_EE_ORIGIN_TIMESTAMPING
;
96
skb->
sk
=
NULL
;
97
err =
sock_queue_err_skb
(sk, skb);
98
sock_put(sk);
99
if
(err)
100
kfree_skb
(skb);
101
}
102
EXPORT_SYMBOL_GPL
(
skb_complete_tx_timestamp
);
103
104
bool
skb_defer_rx_timestamp
(
struct
sk_buff
*skb)
105
{
106
struct
phy_device
*phydev;
107
unsigned
int
type
;
108
109
if
(skb_headroom(skb) <
ETH_HLEN
)
110
return
false
;
111
__skb_push(skb,
ETH_HLEN
);
112
113
type = classify(skb);
114
115
__skb_pull(skb,
ETH_HLEN
);
116
117
switch
(type) {
118
case
PTP_CLASS_V1_IPV4
:
119
case
PTP_CLASS_V1_IPV6
:
120
case
PTP_CLASS_V2_IPV4
:
121
case
PTP_CLASS_V2_IPV6
:
122
case
PTP_CLASS_V2_L2
:
123
case
PTP_CLASS_V2_VLAN
:
124
phydev = skb->
dev
->phydev;
125
if
(
likely
(phydev->
drv
->rxtstamp))
126
return
phydev->
drv
->rxtstamp(phydev, skb, type);
127
break
;
128
default
:
129
break
;
130
}
131
132
return
false
;
133
}
134
EXPORT_SYMBOL_GPL
(
skb_defer_rx_timestamp
);
135
136
void
__init
skb_timestamping_init
(
void
)
137
{
138
BUG_ON
(
sk_chk_filter
(ptp_filter,
ARRAY_SIZE
(ptp_filter)));
139
}
Generated on Thu Jan 10 2013 13:23:19 for Linux Kernel by
1.8.2