| Richard Cochran | 15f0127 | 2010-07-17 08:49:17 +0000 | [diff] [blame] | 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> | 
| Richard Cochran | d94ba80 | 2011-04-22 12:03:08 +0200 | [diff] [blame] | 28 | #include <linux/ip.h> | 
| Richard Cochran | 15f0127 | 2010-07-17 08:49:17 +0000 | [diff] [blame] | 29 | #include <linux/filter.h> | 
 | 30 | #ifdef __KERNEL__ | 
 | 31 | #include <linux/in.h> | 
 | 32 | #else | 
 | 33 | #include <netinet/in.h> | 
 | 34 | #endif | 
 | 35 |  | 
 | 36 | #define PTP_CLASS_NONE  0x00 /* not a PTP event message */ | 
 | 37 | #define PTP_CLASS_V1    0x01 /* protocol version 1 */ | 
 | 38 | #define PTP_CLASS_V2    0x02 /* protocol version 2 */ | 
 | 39 | #define PTP_CLASS_VMASK 0x0f /* max protocol version is 15 */ | 
 | 40 | #define PTP_CLASS_IPV4  0x10 /* event in an IPV4 UDP packet */ | 
 | 41 | #define PTP_CLASS_IPV6  0x20 /* event in an IPV6 UDP packet */ | 
 | 42 | #define PTP_CLASS_L2    0x30 /* event in a L2 packet */ | 
 | 43 | #define PTP_CLASS_VLAN  0x40 /* event in a VLAN tagged L2 packet */ | 
 | 44 | #define PTP_CLASS_PMASK 0xf0 /* mask for the packet type field */ | 
 | 45 |  | 
 | 46 | #define PTP_CLASS_V1_IPV4 (PTP_CLASS_V1 | PTP_CLASS_IPV4) | 
 | 47 | #define PTP_CLASS_V1_IPV6 (PTP_CLASS_V1 | PTP_CLASS_IPV6) /*probably DNE*/ | 
 | 48 | #define PTP_CLASS_V2_IPV4 (PTP_CLASS_V2 | PTP_CLASS_IPV4) | 
 | 49 | #define PTP_CLASS_V2_IPV6 (PTP_CLASS_V2 | PTP_CLASS_IPV6) | 
 | 50 | #define PTP_CLASS_V2_L2   (PTP_CLASS_V2 | PTP_CLASS_L2) | 
 | 51 | #define PTP_CLASS_V2_VLAN (PTP_CLASS_V2 | PTP_CLASS_VLAN) | 
 | 52 |  | 
 | 53 | #define PTP_EV_PORT 319 | 
| Richard Cochran | f75159e | 2011-09-20 01:25:41 +0000 | [diff] [blame] | 54 | #define PTP_GEN_BIT 0x08 /* indicates general message, if set in message type */ | 
| Richard Cochran | 15f0127 | 2010-07-17 08:49:17 +0000 | [diff] [blame] | 55 |  | 
 | 56 | #define OFF_ETYPE	12 | 
 | 57 | #define OFF_IHL		14 | 
 | 58 | #define OFF_FRAG	20 | 
 | 59 | #define OFF_PROTO4	23 | 
 | 60 | #define OFF_NEXT	6 | 
 | 61 | #define OFF_UDP_DST	2 | 
 | 62 |  | 
| Richard Cochran | d94ba80 | 2011-04-22 12:03:08 +0200 | [diff] [blame] | 63 | #define OFF_PTP_SOURCE_UUID	22 /* PTPv1 only */ | 
 | 64 | #define OFF_PTP_SEQUENCE_ID	30 | 
 | 65 | #define OFF_PTP_CONTROL		32 /* PTPv1 only */ | 
 | 66 |  | 
 | 67 | #define IPV4_HLEN(data) (((struct iphdr *)(data + OFF_IHL))->ihl << 2) | 
 | 68 |  | 
| Richard Cochran | 15f0127 | 2010-07-17 08:49:17 +0000 | [diff] [blame] | 69 | #define IP6_HLEN	40 | 
 | 70 | #define UDP_HLEN	8 | 
 | 71 |  | 
 | 72 | #define RELOFF_DST4	(ETH_HLEN + OFF_UDP_DST) | 
 | 73 | #define OFF_DST6	(ETH_HLEN + IP6_HLEN + OFF_UDP_DST) | 
 | 74 | #define OFF_PTP6	(ETH_HLEN + IP6_HLEN + UDP_HLEN) | 
 | 75 |  | 
 | 76 | #define OP_AND	(BPF_ALU | BPF_AND  | BPF_K) | 
 | 77 | #define OP_JEQ	(BPF_JMP | BPF_JEQ  | BPF_K) | 
 | 78 | #define OP_JSET	(BPF_JMP | BPF_JSET | BPF_K) | 
 | 79 | #define OP_LDB	(BPF_LD  | BPF_B    | BPF_ABS) | 
 | 80 | #define OP_LDH	(BPF_LD  | BPF_H    | BPF_ABS) | 
 | 81 | #define OP_LDHI	(BPF_LD  | BPF_H    | BPF_IND) | 
 | 82 | #define OP_LDX	(BPF_LDX | BPF_B    | BPF_MSH) | 
 | 83 | #define OP_OR	(BPF_ALU | BPF_OR   | BPF_K) | 
 | 84 | #define OP_RETA	(BPF_RET | BPF_A) | 
 | 85 | #define OP_RETK	(BPF_RET | BPF_K) | 
 | 86 |  | 
 | 87 | static inline int ptp_filter_init(struct sock_filter *f, int len) | 
 | 88 | { | 
 | 89 | 	if (OP_LDH == f[0].code) | 
 | 90 | 		return sk_chk_filter(f, len); | 
 | 91 | 	else | 
 | 92 | 		return 0; | 
 | 93 | } | 
 | 94 |  | 
 | 95 | #define PTP_FILTER \ | 
 | 96 | 	{OP_LDH,	0,   0, OFF_ETYPE		}, /*              */ \ | 
 | 97 | 	{OP_JEQ,	0,  12, ETH_P_IP		}, /* f goto L20   */ \ | 
 | 98 | 	{OP_LDB,	0,   0, OFF_PROTO4		}, /*              */ \ | 
 | 99 | 	{OP_JEQ,	0,   9, IPPROTO_UDP		}, /* f goto L10   */ \ | 
 | 100 | 	{OP_LDH,	0,   0, OFF_FRAG		}, /*              */ \ | 
 | 101 | 	{OP_JSET,	7,   0, 0x1fff			}, /* t goto L11   */ \ | 
 | 102 | 	{OP_LDX,	0,   0, OFF_IHL			}, /*              */ \ | 
 | 103 | 	{OP_LDHI,	0,   0, RELOFF_DST4		}, /*              */ \ | 
 | 104 | 	{OP_JEQ,	0,   4, PTP_EV_PORT		}, /* f goto L12   */ \ | 
 | 105 | 	{OP_LDHI,	0,   0, ETH_HLEN + UDP_HLEN	}, /*              */ \ | 
 | 106 | 	{OP_AND,	0,   0, PTP_CLASS_VMASK		}, /*              */ \ | 
 | 107 | 	{OP_OR,		0,   0, PTP_CLASS_IPV4		}, /*              */ \ | 
 | 108 | 	{OP_RETA,	0,   0, 0			}, /*              */ \ | 
 | 109 | /*L1x*/	{OP_RETK,	0,   0, PTP_CLASS_NONE		}, /*              */ \ | 
 | 110 | /*L20*/	{OP_JEQ,	0,   9, ETH_P_IPV6		}, /* f goto L40   */ \ | 
 | 111 | 	{OP_LDB,	0,   0, ETH_HLEN + OFF_NEXT	}, /*              */ \ | 
 | 112 | 	{OP_JEQ,	0,   6, IPPROTO_UDP		}, /* f goto L30   */ \ | 
 | 113 | 	{OP_LDH,	0,   0, OFF_DST6		}, /*              */ \ | 
 | 114 | 	{OP_JEQ,	0,   4, PTP_EV_PORT		}, /* f goto L31   */ \ | 
 | 115 | 	{OP_LDH,	0,   0, OFF_PTP6		}, /*              */ \ | 
 | 116 | 	{OP_AND,	0,   0, PTP_CLASS_VMASK		}, /*              */ \ | 
 | 117 | 	{OP_OR,		0,   0, PTP_CLASS_IPV6		}, /*              */ \ | 
 | 118 | 	{OP_RETA,	0,   0, 0			}, /*              */ \ | 
 | 119 | /*L3x*/	{OP_RETK,	0,   0, PTP_CLASS_NONE		}, /*              */ \ | 
| Richard Cochran | f75159e | 2011-09-20 01:25:41 +0000 | [diff] [blame] | 120 | /*L40*/	{OP_JEQ,	0,   9, ETH_P_8021Q		}, /* f goto L50   */ \ | 
| Richard Cochran | 15f0127 | 2010-07-17 08:49:17 +0000 | [diff] [blame] | 121 | 	{OP_LDH,	0,   0, OFF_ETYPE + 4		}, /*              */ \ | 
| Richard Cochran | f75159e | 2011-09-20 01:25:41 +0000 | [diff] [blame] | 122 | 	{OP_JEQ,	0,  15, ETH_P_1588		}, /* f goto L60   */ \ | 
 | 123 | 	{OP_LDB,	0,   0, ETH_HLEN + VLAN_HLEN	}, /*              */ \ | 
 | 124 | 	{OP_AND,	0,   0, PTP_GEN_BIT		}, /*              */ \ | 
 | 125 | 	{OP_JEQ,	0,  12, 0			}, /* f goto L6x   */ \ | 
| Richard Cochran | 15f0127 | 2010-07-17 08:49:17 +0000 | [diff] [blame] | 126 | 	{OP_LDH,	0,   0, ETH_HLEN + VLAN_HLEN	}, /*              */ \ | 
 | 127 | 	{OP_AND,	0,   0, PTP_CLASS_VMASK		}, /*              */ \ | 
 | 128 | 	{OP_OR,		0,   0, PTP_CLASS_VLAN		}, /*              */ \ | 
 | 129 | 	{OP_RETA,	0,   0, 0			}, /*              */ \ | 
| Richard Cochran | f75159e | 2011-09-20 01:25:41 +0000 | [diff] [blame] | 130 | /*L50*/	{OP_JEQ,	0,   7, ETH_P_1588		}, /* f goto L61   */ \ | 
 | 131 | 	{OP_LDB,	0,   0, ETH_HLEN		}, /*              */ \ | 
 | 132 | 	{OP_AND,	0,   0, PTP_GEN_BIT		}, /*              */ \ | 
 | 133 | 	{OP_JEQ,	0,   4, 0			}, /* f goto L6x   */ \ | 
| Richard Cochran | 15f0127 | 2010-07-17 08:49:17 +0000 | [diff] [blame] | 134 | 	{OP_LDH,	0,   0, ETH_HLEN		}, /*              */ \ | 
 | 135 | 	{OP_AND,	0,   0, PTP_CLASS_VMASK		}, /*              */ \ | 
 | 136 | 	{OP_OR,		0,   0, PTP_CLASS_L2		}, /*              */ \ | 
 | 137 | 	{OP_RETA,	0,   0, 0			}, /*              */ \ | 
 | 138 | /*L6x*/	{OP_RETK,	0,   0, PTP_CLASS_NONE		}, | 
 | 139 |  | 
 | 140 | #endif |