Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 408eccce authored by Daniel Borkmann's avatar Daniel Borkmann Committed by David S. Miller
Browse files

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: 164d8c66 ("net: ptp: do not reimplement PTP/BPF classifier")
Reported-by: default avatarFengguang Wu <fengguang.wu@intel.com>
Signed-off-by: default avatarDaniel Borkmann <dborkman@redhat.com>
Signed-off-by: default avatarAlexei Starovoitov <ast@plumgrid.com>
Cc: Richard Cochran <richardcochran@gmail.com>
Cc: Jiri Benc <jbenc@redhat.com>
Acked-by: default avatarRichard Cochran <richardcochran@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7baea6ef
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ config IXP4XX_ETH
	tristate "Intel IXP4xx Ethernet support"
	depends on ARM && ARCH_IXP4XX && IXP4XX_NPE && IXP4XX_QMGR
	select PHYLIB
	select NET_PTP_CLASSIFY
	---help---
	  Say Y here if you want to use built-in Ethernet ports
	  on IXP4xx processor.
+1 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include <linux/module.h>
#include <linux/net_tstamp.h>
#include <linux/netdevice.h>
#include <linux/if_vlan.h>
#include <linux/phy.h>
#include <linux/ptp_classify.h>
#include <linux/ptp_clock_kernel.h>
+1 −0
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@ menu "PTP clock support"
config PTP_1588_CLOCK
	tristate "PTP clock support"
	select PPS
	select NET_PTP_CLASSIFY
	help
	  The IEEE 1588 standard defines a method to precisely
	  synchronize distributed clocks over Ethernet networks. The
+22 −73
Original line number Diff line number Diff line
@@ -23,11 +23,8 @@
#ifndef _PTP_CLASSIFY_H_
#define _PTP_CLASSIFY_H_

#include <linux/if_ether.h>
#include <linux/if_vlan.h>
#include <linux/ip.h>
#include <linux/filter.h>
#include <linux/in.h>
#include <linux/skbuff.h>

#define PTP_CLASS_NONE  0x00 /* not a PTP event message */
#define PTP_CLASS_V1    0x01 /* protocol version 1 */
@@ -49,82 +46,34 @@
#define PTP_EV_PORT 319
#define PTP_GEN_BIT 0x08 /* indicates general message, if set in message type */

#define OFF_ETYPE	12
#define OFF_IHL		14
#define OFF_FRAG	20
#define OFF_PROTO4	23
#define OFF_NEXT	6
#define OFF_UDP_DST	2

#define OFF_PTP_SOURCE_UUID	22 /* PTPv1 only */
#define OFF_PTP_SEQUENCE_ID	30
#define OFF_PTP_CONTROL		32 /* PTPv1 only */

#define IPV4_HLEN(data) (((struct iphdr *)(data + OFF_IHL))->ihl << 2)

/* Below defines should actually be removed at some point in time. */
#define IP6_HLEN	40
#define UDP_HLEN	8

#define RELOFF_DST4	(ETH_HLEN + OFF_UDP_DST)
#define OFF_DST6	(ETH_HLEN + IP6_HLEN + OFF_UDP_DST)
#define OFF_IHL		14
#define OFF_PTP6	(ETH_HLEN + IP6_HLEN + UDP_HLEN)
#define IPV4_HLEN(data) (((struct iphdr *)(data + OFF_IHL))->ihl << 2)

#define OP_AND	(BPF_ALU | BPF_AND  | BPF_K)
#define OP_JEQ	(BPF_JMP | BPF_JEQ  | BPF_K)
#define OP_JSET	(BPF_JMP | BPF_JSET | BPF_K)
#define OP_LDB	(BPF_LD  | BPF_B    | BPF_ABS)
#define OP_LDH	(BPF_LD  | BPF_H    | BPF_ABS)
#define OP_LDHI	(BPF_LD  | BPF_H    | BPF_IND)
#define OP_LDX	(BPF_LDX | BPF_B    | BPF_MSH)
#define OP_OR	(BPF_ALU | BPF_OR   | BPF_K)
#define OP_RETA	(BPF_RET | BPF_A)
#define OP_RETK	(BPF_RET | BPF_K)

#define PTP_FILTER \
	{OP_LDH,	0,   0, OFF_ETYPE		}, /*              */ \
	{OP_JEQ,	0,  12, ETH_P_IP		}, /* f goto L20   */ \
	{OP_LDB,	0,   0, OFF_PROTO4		}, /*              */ \
	{OP_JEQ,	0,   9, IPPROTO_UDP		}, /* f goto L10   */ \
	{OP_LDH,	0,   0, OFF_FRAG		}, /*              */ \
	{OP_JSET,	7,   0, 0x1fff			}, /* t goto L11   */ \
	{OP_LDX,	0,   0, OFF_IHL			}, /*              */ \
	{OP_LDHI,	0,   0, RELOFF_DST4		}, /*              */ \
	{OP_JEQ,	0,   4, PTP_EV_PORT		}, /* f goto L12   */ \
	{OP_LDHI,	0,   0, ETH_HLEN + UDP_HLEN	}, /*              */ \
	{OP_AND,	0,   0, PTP_CLASS_VMASK		}, /*              */ \
	{OP_OR,		0,   0, PTP_CLASS_IPV4		}, /*              */ \
	{OP_RETA,	0,   0, 0			}, /*              */ \
/*L1x*/	{OP_RETK,	0,   0, PTP_CLASS_NONE		}, /*              */ \
/*L20*/	{OP_JEQ,	0,   9, ETH_P_IPV6		}, /* f goto L40   */ \
	{OP_LDB,	0,   0, ETH_HLEN + OFF_NEXT	}, /*              */ \
	{OP_JEQ,	0,   6, IPPROTO_UDP		}, /* f goto L30   */ \
	{OP_LDH,	0,   0, OFF_DST6		}, /*              */ \
	{OP_JEQ,	0,   4, PTP_EV_PORT		}, /* f goto L31   */ \
	{OP_LDH,	0,   0, OFF_PTP6		}, /*              */ \
	{OP_AND,	0,   0, PTP_CLASS_VMASK		}, /*              */ \
	{OP_OR,		0,   0, PTP_CLASS_IPV6		}, /*              */ \
	{OP_RETA,	0,   0, 0			}, /*              */ \
/*L3x*/	{OP_RETK,	0,   0, PTP_CLASS_NONE		}, /*              */ \
/*L40*/	{OP_JEQ,	0,   9, ETH_P_8021Q		}, /* f goto L50   */ \
	{OP_LDH,	0,   0, OFF_ETYPE + 4		}, /*              */ \
	{OP_JEQ,	0,  15, ETH_P_1588		}, /* f goto L60   */ \
	{OP_LDB,	0,   0, ETH_HLEN + VLAN_HLEN	}, /*              */ \
	{OP_AND,	0,   0, PTP_GEN_BIT		}, /*              */ \
	{OP_JEQ,	0,  12, 0			}, /* f goto L6x   */ \
	{OP_LDH,	0,   0, ETH_HLEN + VLAN_HLEN	}, /*              */ \
	{OP_AND,	0,   0, PTP_CLASS_VMASK		}, /*              */ \
	{OP_OR,		0,   0, PTP_CLASS_VLAN		}, /*              */ \
	{OP_RETA,	0,   0, 0			}, /*              */ \
/*L50*/	{OP_JEQ,	0,   7, ETH_P_1588		}, /* f goto L61   */ \
	{OP_LDB,	0,   0, ETH_HLEN		}, /*              */ \
	{OP_AND,	0,   0, PTP_GEN_BIT		}, /*              */ \
	{OP_JEQ,	0,   4, 0			}, /* f goto L6x   */ \
	{OP_LDH,	0,   0, ETH_HLEN		}, /*              */ \
	{OP_AND,	0,   0, PTP_CLASS_VMASK		}, /*              */ \
	{OP_OR,		0,   0, PTP_CLASS_L2		}, /*              */ \
	{OP_RETA,	0,   0, 0			}, /*              */ \
/*L6x*/	{OP_RETK,	0,   0, PTP_CLASS_NONE		},

#if defined(CONFIG_NET_PTP_CLASSIFY)
/**
 * ptp_classify_raw - classify a PTP packet
 * @skb: buffer
 *
 * Runs a minimal BPF dissector to classify a network packet to
 * determine the PTP class. In case the skb does not contain any
 * PTP protocol data, PTP_CLASS_NONE will be returned, otherwise
 * PTP_CLASS_V1_IPV{4,6}, PTP_CLASS_V2_IPV{4,6} or
 * PTP_CLASS_V2_{L2,VLAN}, depending on the packet content.
 */
unsigned int ptp_classify_raw(const struct sk_buff *skb);

void __init ptp_classifier_init(void);
#else
static inline void ptp_classifier_init(void)
{
}
#endif
#endif /* _PTP_CLASSIFY_H_ */
+0 −2
Original line number Diff line number Diff line
@@ -2630,8 +2630,6 @@ static inline ktime_t net_invalid_timestamp(void)
	return ktime_set(0, 0);
}

void skb_timestamping_init(void);

#ifdef CONFIG_NETWORK_PHY_TIMESTAMPING

void skb_clone_tx_timestamp(struct sk_buff *skb);
Loading