Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[pandora-kernel.git] / include / linux / ptp_classify.h
1 /*
2  * PTP 1588 support
3  *
4  * This file implements a BPF that recognizes PTP event messages.
5  *
6  * Copyright (C) 2010 OMICRON electronics GmbH
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22
23 #ifndef _PTP_CLASSIFY_H_
24 #define _PTP_CLASSIFY_H_
25
26 #include <linux/if_ether.h>
27 #include <linux/if_vlan.h>
28 #include <linux/filter.h>
29 #ifdef __KERNEL__
30 #include <linux/in.h>
31 #else
32 #include <netinet/in.h>
33 #endif
34
35 #define PTP_CLASS_NONE  0x00 /* not a PTP event message */
36 #define PTP_CLASS_V1    0x01 /* protocol version 1 */
37 #define PTP_CLASS_V2    0x02 /* protocol version 2 */
38 #define PTP_CLASS_VMASK 0x0f /* max protocol version is 15 */
39 #define PTP_CLASS_IPV4  0x10 /* event in an IPV4 UDP packet */
40 #define PTP_CLASS_IPV6  0x20 /* event in an IPV6 UDP packet */
41 #define PTP_CLASS_L2    0x30 /* event in a L2 packet */
42 #define PTP_CLASS_VLAN  0x40 /* event in a VLAN tagged L2 packet */
43 #define PTP_CLASS_PMASK 0xf0 /* mask for the packet type field */
44
45 #define PTP_CLASS_V1_IPV4 (PTP_CLASS_V1 | PTP_CLASS_IPV4)
46 #define PTP_CLASS_V1_IPV6 (PTP_CLASS_V1 | PTP_CLASS_IPV6) /*probably DNE*/
47 #define PTP_CLASS_V2_IPV4 (PTP_CLASS_V2 | PTP_CLASS_IPV4)
48 #define PTP_CLASS_V2_IPV6 (PTP_CLASS_V2 | PTP_CLASS_IPV6)
49 #define PTP_CLASS_V2_L2   (PTP_CLASS_V2 | PTP_CLASS_L2)
50 #define PTP_CLASS_V2_VLAN (PTP_CLASS_V2 | PTP_CLASS_VLAN)
51
52 #define PTP_EV_PORT 319
53
54 #define OFF_ETYPE       12
55 #define OFF_IHL         14
56 #define OFF_FRAG        20
57 #define OFF_PROTO4      23
58 #define OFF_NEXT        6
59 #define OFF_UDP_DST     2
60
61 #define IP6_HLEN        40
62 #define UDP_HLEN        8
63
64 #define RELOFF_DST4     (ETH_HLEN + OFF_UDP_DST)
65 #define OFF_DST6        (ETH_HLEN + IP6_HLEN + OFF_UDP_DST)
66 #define OFF_PTP6        (ETH_HLEN + IP6_HLEN + UDP_HLEN)
67
68 #define OP_AND  (BPF_ALU | BPF_AND  | BPF_K)
69 #define OP_JEQ  (BPF_JMP | BPF_JEQ  | BPF_K)
70 #define OP_JSET (BPF_JMP | BPF_JSET | BPF_K)
71 #define OP_LDB  (BPF_LD  | BPF_B    | BPF_ABS)
72 #define OP_LDH  (BPF_LD  | BPF_H    | BPF_ABS)
73 #define OP_LDHI (BPF_LD  | BPF_H    | BPF_IND)
74 #define OP_LDX  (BPF_LDX | BPF_B    | BPF_MSH)
75 #define OP_OR   (BPF_ALU | BPF_OR   | BPF_K)
76 #define OP_RETA (BPF_RET | BPF_A)
77 #define OP_RETK (BPF_RET | BPF_K)
78
79 static inline int ptp_filter_init(struct sock_filter *f, int len)
80 {
81         if (OP_LDH == f[0].code)
82                 return sk_chk_filter(f, len);
83         else
84                 return 0;
85 }
86
87 #define PTP_FILTER \
88         {OP_LDH,        0,   0, OFF_ETYPE               }, /*              */ \
89         {OP_JEQ,        0,  12, ETH_P_IP                }, /* f goto L20   */ \
90         {OP_LDB,        0,   0, OFF_PROTO4              }, /*              */ \
91         {OP_JEQ,        0,   9, IPPROTO_UDP             }, /* f goto L10   */ \
92         {OP_LDH,        0,   0, OFF_FRAG                }, /*              */ \
93         {OP_JSET,       7,   0, 0x1fff                  }, /* t goto L11   */ \
94         {OP_LDX,        0,   0, OFF_IHL                 }, /*              */ \
95         {OP_LDHI,       0,   0, RELOFF_DST4             }, /*              */ \
96         {OP_JEQ,        0,   4, PTP_EV_PORT             }, /* f goto L12   */ \
97         {OP_LDHI,       0,   0, ETH_HLEN + UDP_HLEN     }, /*              */ \
98         {OP_AND,        0,   0, PTP_CLASS_VMASK         }, /*              */ \
99         {OP_OR,         0,   0, PTP_CLASS_IPV4          }, /*              */ \
100         {OP_RETA,       0,   0, 0                       }, /*              */ \
101 /*L1x*/ {OP_RETK,       0,   0, PTP_CLASS_NONE          }, /*              */ \
102 /*L20*/ {OP_JEQ,        0,   9, ETH_P_IPV6              }, /* f goto L40   */ \
103         {OP_LDB,        0,   0, ETH_HLEN + OFF_NEXT     }, /*              */ \
104         {OP_JEQ,        0,   6, IPPROTO_UDP             }, /* f goto L30   */ \
105         {OP_LDH,        0,   0, OFF_DST6                }, /*              */ \
106         {OP_JEQ,        0,   4, PTP_EV_PORT             }, /* f goto L31   */ \
107         {OP_LDH,        0,   0, OFF_PTP6                }, /*              */ \
108         {OP_AND,        0,   0, PTP_CLASS_VMASK         }, /*              */ \
109         {OP_OR,         0,   0, PTP_CLASS_IPV6          }, /*              */ \
110         {OP_RETA,       0,   0, 0                       }, /*              */ \
111 /*L3x*/ {OP_RETK,       0,   0, PTP_CLASS_NONE          }, /*              */ \
112 /*L40*/ {OP_JEQ,        0,   6, ETH_P_8021Q             }, /* f goto L50   */ \
113         {OP_LDH,        0,   0, OFF_ETYPE + 4           }, /*              */ \
114         {OP_JEQ,        0,   9, ETH_P_1588              }, /* f goto L60   */ \
115         {OP_LDH,        0,   0, ETH_HLEN + VLAN_HLEN    }, /*              */ \
116         {OP_AND,        0,   0, PTP_CLASS_VMASK         }, /*              */ \
117         {OP_OR,         0,   0, PTP_CLASS_VLAN          }, /*              */ \
118         {OP_RETA,       0,   0, 0                       }, /*              */ \
119 /*L50*/ {OP_JEQ,        0,   4, ETH_P_1588              }, /* f goto L61   */ \
120         {OP_LDH,        0,   0, ETH_HLEN                }, /*              */ \
121         {OP_AND,        0,   0, PTP_CLASS_VMASK         }, /*              */ \
122         {OP_OR,         0,   0, PTP_CLASS_L2            }, /*              */ \
123         {OP_RETA,       0,   0, 0                       }, /*              */ \
124 /*L6x*/ {OP_RETK,       0,   0, PTP_CLASS_NONE          },
125
126 #endif