Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ptp: Add generic ptp v2 header parsing function

Reason: A lot of the ptp drivers - which implement hardware time stamping - need
specific fields such as the sequence id from the ptp v2 header. Currently all
drivers implement that themselves.

Introduce a generic function to retrieve a pointer to the start of the ptp v2
header.

Suggested-by: Russell King <rmk+kernel@armlinux.org.uk>
Signed-off-by: Kurt Kanzenbach <kurt@linutronix.de>
Reviewed-by: Richard Cochran <richardcochran@gmail.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Reviewed-by: Russell King <rmk+kernel@armlinux.org.uk>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Kurt Kanzenbach and committed by
David S. Miller
bdfbb63c f3ae59c0

+74
+44
include/linux/ptp_classify.h
··· 44 44 #define OFF_IHL 14 45 45 #define IPV4_HLEN(data) (((struct iphdr *)(data + OFF_IHL))->ihl << 2) 46 46 47 + struct clock_identity { 48 + u8 id[8]; 49 + } __packed; 50 + 51 + struct port_identity { 52 + struct clock_identity clock_identity; 53 + __be16 port_number; 54 + } __packed; 55 + 56 + struct ptp_header { 57 + u8 tsmt; /* transportSpecific | messageType */ 58 + u8 ver; /* reserved | versionPTP */ 59 + __be16 message_length; 60 + u8 domain_number; 61 + u8 reserved1; 62 + u8 flag_field[2]; 63 + __be64 correction; 64 + __be32 reserved2; 65 + struct port_identity source_port_identity; 66 + __be16 sequence_id; 67 + u8 control; 68 + u8 log_message_interval; 69 + } __packed; 70 + 47 71 #if defined(CONFIG_NET_PTP_CLASSIFY) 48 72 /** 49 73 * ptp_classify_raw - classify a PTP packet ··· 81 57 */ 82 58 unsigned int ptp_classify_raw(const struct sk_buff *skb); 83 59 60 + /** 61 + * ptp_parse_header - Get pointer to the PTP v2 header 62 + * @skb: packet buffer 63 + * @type: type of the packet (see ptp_classify_raw()) 64 + * 65 + * This function takes care of the VLAN, UDP, IPv4 and IPv6 headers. The length 66 + * is checked. 67 + * 68 + * Note, internally skb_mac_header() is used. Make sure that the @skb is 69 + * initialized accordingly. 70 + * 71 + * Return: Pointer to the ptp v2 header or NULL if not found 72 + */ 73 + struct ptp_header *ptp_parse_header(struct sk_buff *skb, unsigned int type); 74 + 84 75 void __init ptp_classifier_init(void); 85 76 #else 86 77 static inline void ptp_classifier_init(void) ··· 104 65 static inline unsigned int ptp_classify_raw(struct sk_buff *skb) 105 66 { 106 67 return PTP_CLASS_NONE; 68 + } 69 + static inline struct ptp_header *ptp_parse_header(struct sk_buff *skb, 70 + unsigned int type) 71 + { 72 + return NULL; 107 73 } 108 74 #endif 109 75 #endif /* _PTP_CLASSIFY_H_ */
+30
net/core/ptp_classifier.c
··· 107 107 } 108 108 EXPORT_SYMBOL_GPL(ptp_classify_raw); 109 109 110 + struct ptp_header *ptp_parse_header(struct sk_buff *skb, unsigned int type) 111 + { 112 + u8 *ptr = skb_mac_header(skb); 113 + 114 + if (type & PTP_CLASS_VLAN) 115 + ptr += VLAN_HLEN; 116 + 117 + switch (type & PTP_CLASS_PMASK) { 118 + case PTP_CLASS_IPV4: 119 + ptr += IPV4_HLEN(ptr) + UDP_HLEN; 120 + break; 121 + case PTP_CLASS_IPV6: 122 + ptr += IP6_HLEN + UDP_HLEN; 123 + break; 124 + case PTP_CLASS_L2: 125 + break; 126 + default: 127 + return NULL; 128 + } 129 + 130 + ptr += ETH_HLEN; 131 + 132 + /* Ensure that the entire header is present in this packet. */ 133 + if (ptr + sizeof(struct ptp_header) > skb->data + skb->len) 134 + return NULL; 135 + 136 + return (struct ptp_header *)ptr; 137 + } 138 + EXPORT_SYMBOL_GPL(ptp_parse_header); 139 + 110 140 void __init ptp_classifier_init(void) 111 141 { 112 142 static struct sock_filter ptp_filter[] __initdata = {