aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/ptp_classifier.c
diff options
context:
space:
mode:
authorDaniel Borkmann <dborkman@redhat.com>2014-04-01 10:20:23 -0400
committerDavid S. Miller <davem@davemloft.net>2014-04-01 16:43:18 -0400
commit408eccce32044ee3285a7f6a812723ba3540c3e7 (patch)
tree958eefea88ca8eb30cb6228df8b6a6878e146c64 /net/core/ptp_classifier.c
parent7baea6efb4b716db7d49c3a6815305dfe6afb888 (diff)
net: ptp: move PTP classifier in its own file
This commit fixes a build error reported by Fengguang, that is triggered when CONFIG_NETWORK_PHY_TIMESTAMPING is not set: ERROR: "ptp_classify_raw" [drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.ko] undefined! The fix is to introduce its own file for the PTP BPF classifier, so that PTP_1588_CLOCK and/or NETWORK_PHY_TIMESTAMPING can select it independently from each other. IXP4xx driver on ARM needs to select it as well since it does not seem to select PTP_1588_CLOCK or similar that would pull it in automatically. This also allows for hiding all of the internals of the BPF PTP program inside that file, and only exporting relevant API bits to drivers. This patch also adds a kdoc documentation of ptp_classify_raw() API to make it clear that it can return PTP_CLASS_* defines. Also, the BPF program has been translated into bpf_asm code, so that it can be more easily read and altered (extensively documented in [1]). In the kernel tree under tools/net/ we have bpf_asm and bpf_dbg tools, so the commented program can simply be translated via `./bpf_asm -c prog` where prog is a file that contains the commented code. This makes it easily readable/verifiable and when there's a need to change something, jump offsets etc do not need to be replaced manually which can be very error prone. Instead, a newly translated version via bpf_asm can simply replace the old code. I have checked opcode diffs before/after and it's the very same filter. [1] Documentation/networking/filter.txt Fixes: 164d8c666521 ("net: ptp: do not reimplement PTP/BPF classifier") Reported-by: Fengguang Wu <fengguang.wu@intel.com> Signed-off-by: Daniel Borkmann <dborkman@redhat.com> Signed-off-by: Alexei Starovoitov <ast@plumgrid.com> Cc: Richard Cochran <richardcochran@gmail.com> Cc: Jiri Benc <jbenc@redhat.com> Acked-by: Richard Cochran <richardcochran@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core/ptp_classifier.c')
-rw-r--r--net/core/ptp_classifier.c141
1 files changed, 141 insertions, 0 deletions
diff --git a/net/core/ptp_classifier.c b/net/core/ptp_classifier.c
new file mode 100644
index 000000000000..eaba0f68f860
--- /dev/null
+++ b/net/core/ptp_classifier.c
@@ -0,0 +1,141 @@
1/* PTP classifier
2 *
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of version 2 of the GNU General Public
5 * License as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful, but
8 * WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * General Public License for more details.
11 */
12
13/* The below program is the bpf_asm (tools/net/) representation of
14 * the opcode array in the ptp_filter structure.
15 *
16 * For convenience, this can easily be altered and reviewed with
17 * bpf_asm and bpf_dbg, e.g. `./bpf_asm -c prog` where prog is a
18 * simple file containing the below program:
19 *
20 * ldh [12] ; load ethertype
21 *
22 * ; PTP over UDP over IPv4 over Ethernet
23 * test_ipv4:
24 * jneq #0x800, test_ipv6 ; ETH_P_IP ?
25 * ldb [23] ; load proto
26 * jneq #17, drop_ipv4 ; IPPROTO_UDP ?
27 * ldh [20] ; load frag offset field
28 * jset #0x1fff, drop_ipv4 ; don't allow fragments
29 * ldxb 4*([14]&0xf) ; load IP header len
30 * ldh [x + 16] ; load UDP dst port
31 * jneq #319, drop_ipv4 ; is port PTP_EV_PORT ?
32 * ldh [x + 22] ; load payload
33 * and #0xf ; mask PTP_CLASS_VMASK
34 * or #0x10 ; PTP_CLASS_IPV4
35 * ret a ; return PTP class
36 * drop_ipv4: ret #0x0 ; PTP_CLASS_NONE
37 *
38 * ; PTP over UDP over IPv6 over Ethernet
39 * test_ipv6:
40 * jneq #0x86dd, test_8021q ; ETH_P_IPV6 ?
41 * ldb [20] ; load proto
42 * jneq #17, drop_ipv6 ; IPPROTO_UDP ?
43 * ldh [56] ; load UDP dst port
44 * jneq #319, drop_ipv6 ; is port PTP_EV_PORT ?
45 * ldh [62] ; load payload
46 * and #0xf ; mask PTP_CLASS_VMASK
47 * or #0x20 ; PTP_CLASS_IPV6
48 * ret a ; return PTP class
49 * drop_ipv6: ret #0x0 ; PTP_CLASS_NONE
50 *
51 * ; PTP over 802.1Q over Ethernet
52 * test_8021q:
53 * jneq #0x8100, test_ieee1588 ; ETH_P_8021Q ?
54 * ldh [16] ; load inner type
55 * jneq #0x88f7, drop_ieee1588 ; ETH_P_1588 ?
56 * ldb [18] ; load payload
57 * and #0x8 ; as we don't have ports here, test
58 * jneq #0x0, drop_ieee1588 ; for PTP_GEN_BIT and drop these
59 * ldh [18] ; reload payload
60 * and #0xf ; mask PTP_CLASS_VMASK
61 * or #0x40 ; PTP_CLASS_V2_VLAN
62 * ret a ; return PTP class
63 *
64 * ; PTP over Ethernet
65 * test_ieee1588:
66 * jneq #0x88f7, drop_ieee1588 ; ETH_P_1588 ?
67 * ldb [14] ; load payload
68 * and #0x8 ; as we don't have ports here, test
69 * jneq #0x0, drop_ieee1588 ; for PTP_GEN_BIT and drop these
70 * ldh [14] ; reload payload
71 * and #0xf ; mask PTP_CLASS_VMASK
72 * or #0x30 ; PTP_CLASS_L2
73 * ret a ; return PTP class
74 * drop_ieee1588: ret #0x0 ; PTP_CLASS_NONE
75 */
76
77#include <linux/skbuff.h>
78#include <linux/filter.h>
79#include <linux/ptp_classify.h>
80
81static struct sk_filter *ptp_insns __read_mostly;
82
83unsigned int ptp_classify_raw(const struct sk_buff *skb)
84{
85 return SK_RUN_FILTER(ptp_insns, skb);
86}
87EXPORT_SYMBOL_GPL(ptp_classify_raw);
88
89void __init ptp_classifier_init(void)
90{
91 static struct sock_filter ptp_filter[] = {
92 { 0x28, 0, 0, 0x0000000c },
93 { 0x15, 0, 12, 0x00000800 },
94 { 0x30, 0, 0, 0x00000017 },
95 { 0x15, 0, 9, 0x00000011 },
96 { 0x28, 0, 0, 0x00000014 },
97 { 0x45, 7, 0, 0x00001fff },
98 { 0xb1, 0, 0, 0x0000000e },
99 { 0x48, 0, 0, 0x00000010 },
100 { 0x15, 0, 4, 0x0000013f },
101 { 0x48, 0, 0, 0x00000016 },
102 { 0x54, 0, 0, 0x0000000f },
103 { 0x44, 0, 0, 0x00000010 },
104 { 0x16, 0, 0, 0x00000000 },
105 { 0x06, 0, 0, 0x00000000 },
106 { 0x15, 0, 9, 0x000086dd },
107 { 0x30, 0, 0, 0x00000014 },
108 { 0x15, 0, 6, 0x00000011 },
109 { 0x28, 0, 0, 0x00000038 },
110 { 0x15, 0, 4, 0x0000013f },
111 { 0x28, 0, 0, 0x0000003e },
112 { 0x54, 0, 0, 0x0000000f },
113 { 0x44, 0, 0, 0x00000020 },
114 { 0x16, 0, 0, 0x00000000 },
115 { 0x06, 0, 0, 0x00000000 },
116 { 0x15, 0, 9, 0x00008100 },
117 { 0x28, 0, 0, 0x00000010 },
118 { 0x15, 0, 15, 0x000088f7 },
119 { 0x30, 0, 0, 0x00000012 },
120 { 0x54, 0, 0, 0x00000008 },
121 { 0x15, 0, 12, 0x00000000 },
122 { 0x28, 0, 0, 0x00000012 },
123 { 0x54, 0, 0, 0x0000000f },
124 { 0x44, 0, 0, 0x00000040 },
125 { 0x16, 0, 0, 0x00000000 },
126 { 0x15, 0, 7, 0x000088f7 },
127 { 0x30, 0, 0, 0x0000000e },
128 { 0x54, 0, 0, 0x00000008 },
129 { 0x15, 0, 4, 0x00000000 },
130 { 0x28, 0, 0, 0x0000000e },
131 { 0x54, 0, 0, 0x0000000f },
132 { 0x44, 0, 0, 0x00000030 },
133 { 0x16, 0, 0, 0x00000000 },
134 { 0x06, 0, 0, 0x00000000 },
135 };
136 struct sock_fprog ptp_prog = {
137 .len = ARRAY_SIZE(ptp_filter), .filter = ptp_filter,
138 };
139
140 BUG_ON(sk_unattached_filter_create(&ptp_insns, &ptp_prog));
141}