linux-yocto: fix kernel build (TMP)
authorKévin THIERRY <kevin.thierry@open.eurogiciel.org>
Wed, 8 Oct 2014 07:40:14 +0000 (09:40 +0200)
committerKévin THIERRY <kevin.thierry@open.eurogiciel.org>
Thu, 16 Oct 2014 08:47:44 +0000 (10:47 +0200)
Fix error: "implicit declaration of function 'sk_run_filter'".

Change-Id: I5e69461a51b9fe5aaecd053ad0ed1c2f2a831ff0
Signed-off-by: Kévin THIERRY <kevin.thierry@open.eurogiciel.org>
recipes-kernel/linux/linux-yocto/0001-net-ptp-do-not-reimplement-PTP-BPF-classifier.patch [new file with mode: 0644]
recipes-kernel/linux/linux-yocto/0001-net-ptp-move-PTP-classifier-in-its-own-file.patch [new file with mode: 0644]
recipes-kernel/linux/linux-yocto/0001-net-ptp-use-sk_unattached_filter_create-for-BPF.patch [new file with mode: 0644]
recipes-kernel/linux/linux-yocto_3.14.bbappend

diff --git a/recipes-kernel/linux/linux-yocto/0001-net-ptp-do-not-reimplement-PTP-BPF-classifier.patch b/recipes-kernel/linux/linux-yocto/0001-net-ptp-do-not-reimplement-PTP-BPF-classifier.patch
new file mode 100644 (file)
index 0000000..00e26a2
--- /dev/null
@@ -0,0 +1,190 @@
+From 164d8c6665213c931645578310256da7b1259331 Mon Sep 17 00:00:00 2001
+From: Daniel Borkmann <dborkman@redhat.com>
+Date: Fri, 28 Mar 2014 18:58:22 +0100
+Subject: [PATCH] net: ptp: do not reimplement PTP/BPF classifier
+
+There are currently pch_gbe, cpts, and ixp4xx_eth drivers that open-code
+and reimplement a BPF classifier for the PTP protocol. Since all of them
+effectively do the very same thing and load the very same PTP/BPF filter,
+we can just consolidate that code by introducing ptp_classify_raw() in
+the time-stamping core framework which can be used in drivers.
+
+As drivers get initialized after bootstrapping the core networking
+subsystem, they can make use of ptp_insns wrapped through
+ptp_classify_raw(), which allows to simplify and remove PTP classifier
+setup code in drivers.
+
+Joint work with Alexei Starovoitov.
+
+Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
+Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
+Cc: Richard Cochran <richard.cochran@omicron.at>
+Cc: Jiri Benc <jbenc@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c | 11 +----------
+ drivers/net/ethernet/ti/cpts.c                       | 10 +---------
+ drivers/net/ethernet/xscale/ixp4xx_eth.c             | 11 +----------
+ include/linux/ptp_classify.h                         | 10 ++--------
+ net/core/timestamping.c                              |  8 +++++++-
+ 5 files changed, 12 insertions(+), 38 deletions(-)
+
+diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
+index 464e910..73e6683 100644
+--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
++++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
+@@ -120,10 +120,6 @@ static void pch_gbe_mdio_write(struct net_device *netdev, int addr, int reg,
+                              int data);
+ static void pch_gbe_set_multi(struct net_device *netdev);
+-static struct sock_filter ptp_filter[] = {
+-      PTP_FILTER
+-};
+-
+ static int pch_ptp_match(struct sk_buff *skb, u16 uid_hi, u32 uid_lo, u16 seqid)
+ {
+       u8 *data = skb->data;
+@@ -131,7 +127,7 @@ static int pch_ptp_match(struct sk_buff *skb, u16 uid_hi, u32 uid_lo, u16 seqid)
+       u16 *hi, *id;
+       u32 lo;
+-      if (sk_run_filter(skb, ptp_filter) == PTP_CLASS_NONE)
++      if (ptp_classify_raw(skb) == PTP_CLASS_NONE)
+               return 0;
+       offset = ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN;
+@@ -2635,11 +2631,6 @@ static int pch_gbe_probe(struct pci_dev *pdev,
+       adapter->ptp_pdev = pci_get_bus_and_slot(adapter->pdev->bus->number,
+                                              PCI_DEVFN(12, 4));
+-      if (ptp_filter_init(ptp_filter, ARRAY_SIZE(ptp_filter))) {
+-              dev_err(&pdev->dev, "Bad ptp filter\n");
+-              ret = -EINVAL;
+-              goto err_free_netdev;
+-      }
+       netdev->netdev_ops = &pch_gbe_netdev_ops;
+       netdev->watchdog_timeo = PCH_GBE_WATCHDOG_PERIOD;
+diff --git a/drivers/net/ethernet/ti/cpts.c b/drivers/net/ethernet/ti/cpts.c
+index 372cb19..a3bbf59 100644
+--- a/drivers/net/ethernet/ti/cpts.c
++++ b/drivers/net/ethernet/ti/cpts.c
+@@ -31,10 +31,6 @@
+ #ifdef CONFIG_TI_CPTS
+-static struct sock_filter ptp_filter[] = {
+-      PTP_FILTER
+-};
+-
+ #define cpts_read32(c, r)     __raw_readl(&c->reg->r)
+ #define cpts_write32(c, v, r) __raw_writel(v, &c->reg->r)
+@@ -301,7 +297,7 @@ static u64 cpts_find_ts(struct cpts *cpts, struct sk_buff *skb, int ev_type)
+       u64 ns = 0;
+       struct cpts_event *event;
+       struct list_head *this, *next;
+-      unsigned int class = sk_run_filter(skb, ptp_filter);
++      unsigned int class = ptp_classify_raw(skb);
+       unsigned long flags;
+       u16 seqid;
+       u8 mtype;
+@@ -372,10 +368,6 @@ int cpts_register(struct device *dev, struct cpts *cpts,
+       int err, i;
+       unsigned long flags;
+-      if (ptp_filter_init(ptp_filter, ARRAY_SIZE(ptp_filter))) {
+-              pr_err("cpts: bad ptp filter\n");
+-              return -EINVAL;
+-      }
+       cpts->info = cpts_info;
+       cpts->clock = ptp_clock_register(&cpts->info, dev);
+       if (IS_ERR(cpts->clock)) {
+diff --git a/drivers/net/ethernet/xscale/ixp4xx_eth.c b/drivers/net/ethernet/xscale/ixp4xx_eth.c
+index 25283f1..f7e0f0f 100644
+--- a/drivers/net/ethernet/xscale/ixp4xx_eth.c
++++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c
+@@ -256,10 +256,6 @@ static int ports_open;
+ static struct port *npe_port_tab[MAX_NPES];
+ static struct dma_pool *dma_pool;
+-static struct sock_filter ptp_filter[] = {
+-      PTP_FILTER
+-};
+-
+ static int ixp_ptp_match(struct sk_buff *skb, u16 uid_hi, u32 uid_lo, u16 seqid)
+ {
+       u8 *data = skb->data;
+@@ -267,7 +263,7 @@ static int ixp_ptp_match(struct sk_buff *skb, u16 uid_hi, u32 uid_lo, u16 seqid)
+       u16 *hi, *id;
+       u32 lo;
+-      if (sk_run_filter(skb, ptp_filter) != PTP_CLASS_V1_IPV4)
++      if (ptp_classify_raw(skb) != PTP_CLASS_V1_IPV4)
+               return 0;
+       offset = ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN;
+@@ -1413,11 +1409,6 @@ static int eth_init_one(struct platform_device *pdev)
+       char phy_id[MII_BUS_ID_SIZE + 3];
+       int err;
+-      if (ptp_filter_init(ptp_filter, ARRAY_SIZE(ptp_filter))) {
+-              pr_err("ixp4xx_eth: bad ptp filter\n");
+-              return -EINVAL;
+-      }
+-
+       if (!(dev = alloc_etherdev(sizeof(struct port))))
+               return -ENOMEM;
+diff --git a/include/linux/ptp_classify.h b/include/linux/ptp_classify.h
+index 3decfa4..6d3b0a2 100644
+--- a/include/linux/ptp_classify.h
++++ b/include/linux/ptp_classify.h
+@@ -80,14 +80,6 @@
+ #define OP_RETA       (BPF_RET | BPF_A)
+ #define OP_RETK       (BPF_RET | BPF_K)
+-static inline int ptp_filter_init(struct sock_filter *f, int len)
+-{
+-      if (OP_LDH == f[0].code)
+-              return sk_chk_filter(f, len);
+-      else
+-              return 0;
+-}
+-
+ #define PTP_FILTER \
+       {OP_LDH,        0,   0, OFF_ETYPE               }, /*              */ \
+       {OP_JEQ,        0,  12, ETH_P_IP                }, /* f goto L20   */ \
+@@ -133,4 +125,6 @@ static inline int ptp_filter_init(struct sock_filter *f, int len)
+       {OP_RETA,       0,   0, 0                       }, /*              */ \
+ /*L6x*/       {OP_RETK,       0,   0, PTP_CLASS_NONE          },
++unsigned int ptp_classify_raw(const struct sk_buff *skb);
++
+ #endif
+diff --git a/net/core/timestamping.c b/net/core/timestamping.c
+index e43d56a..9ff26b3 100644
+--- a/net/core/timestamping.c
++++ b/net/core/timestamping.c
+@@ -25,11 +25,17 @@
+ static struct sk_filter *ptp_insns __read_mostly;
++unsigned int ptp_classify_raw(const struct sk_buff *skb)
++{
++      return SK_RUN_FILTER(ptp_insns, skb);
++}
++EXPORT_SYMBOL_GPL(ptp_classify_raw);
++
+ static unsigned int classify(const struct sk_buff *skb)
+ {
+       if (likely(skb->dev && skb->dev->phydev &&
+                  skb->dev->phydev->drv))
+-              return SK_RUN_FILTER(ptp_insns, skb);
++              return ptp_classify_raw(skb);
+       else
+               return PTP_CLASS_NONE;
+ }
+-- 
+1.8.1.4
+
diff --git a/recipes-kernel/linux/linux-yocto/0001-net-ptp-move-PTP-classifier-in-its-own-file.patch b/recipes-kernel/linux/linux-yocto/0001-net-ptp-move-PTP-classifier-in-its-own-file.patch
new file mode 100644 (file)
index 0000000..0148b68
--- /dev/null
@@ -0,0 +1,471 @@
+From 408eccce32044ee3285a7f6a812723ba3540c3e7 Mon Sep 17 00:00:00 2001
+From: Daniel Borkmann <dborkman@redhat.com>
+Date: Tue, 1 Apr 2014 16:20:23 +0200
+Subject: [PATCH] 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>
+---
+ drivers/net/ethernet/xscale/Kconfig |   1 +
+ drivers/net/phy/dp83640.c           |   1 +
+ drivers/ptp/Kconfig                 |   1 +
+ include/linux/ptp_classify.h        |  95 ++++++------------------
+ include/linux/skbuff.h              |   2 -
+ net/Kconfig                         |   4 +
+ net/core/Makefile                   |   1 +
+ net/core/ptp_classifier.c           | 141 ++++++++++++++++++++++++++++++++++++
+ net/core/timestamping.c             |  18 -----
+ net/socket.c                        |   5 +-
+ 10 files changed, 173 insertions(+), 96 deletions(-)
+ create mode 100644 net/core/ptp_classifier.c
+
+diff --git a/drivers/net/ethernet/xscale/Kconfig b/drivers/net/ethernet/xscale/Kconfig
+index 3f43101..b81bc9f 100644
+--- a/drivers/net/ethernet/xscale/Kconfig
++++ b/drivers/net/ethernet/xscale/Kconfig
+@@ -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.
+diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c
+index 352c5e4..6a999e6 100644
+--- a/drivers/net/phy/dp83640.c
++++ b/drivers/net/phy/dp83640.c
+@@ -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>
+diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig
+index 5a7910e..6963bdf 100644
+--- a/drivers/ptp/Kconfig
++++ b/drivers/ptp/Kconfig
+@@ -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
+diff --git a/include/linux/ptp_classify.h b/include/linux/ptp_classify.h
+index 6d3b0a2..7dfed71 100644
+--- a/include/linux/ptp_classify.h
++++ b/include/linux/ptp_classify.h
+@@ -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 */
+@@ -40,7 +37,7 @@
+ #define PTP_CLASS_PMASK 0xf0 /* mask for the packet type field */
+ #define PTP_CLASS_V1_IPV4 (PTP_CLASS_V1 | PTP_CLASS_IPV4)
+-#define PTP_CLASS_V1_IPV6 (PTP_CLASS_V1 | PTP_CLASS_IPV6) /*probably DNE*/
++#define PTP_CLASS_V1_IPV6 (PTP_CLASS_V1 | PTP_CLASS_IPV6) /* probably DNE */
+ #define PTP_CLASS_V2_IPV4 (PTP_CLASS_V2 | PTP_CLASS_IPV4)
+ #define PTP_CLASS_V2_IPV6 (PTP_CLASS_V2 | PTP_CLASS_IPV6)
+ #define PTP_CLASS_V2_L2   (PTP_CLASS_V2 | PTP_CLASS_L2)
+@@ -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_ */
+diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
+index 18ef022..31edf63 100644
+--- a/include/linux/skbuff.h
++++ b/include/linux/skbuff.h
+@@ -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);
+diff --git a/net/Kconfig b/net/Kconfig
+index e411046..d1f6f96 100644
+--- a/net/Kconfig
++++ b/net/Kconfig
+@@ -89,8 +89,12 @@ config NETWORK_SECMARK
+         to nfmark, but designated for security purposes.
+         If you are unsure how to answer this question, answer N.
++config NET_PTP_CLASSIFY
++      def_bool n
++
+ config NETWORK_PHY_TIMESTAMPING
+       bool "Timestamping in PHY devices"
++      select NET_PTP_CLASSIFY
+       help
+         This allows timestamping of network packets by PHYs with
+         hardware timestamping capabilities. This option adds some
+diff --git a/net/core/Makefile b/net/core/Makefile
+index 9628c20..826b925 100644
+--- a/net/core/Makefile
++++ b/net/core/Makefile
+@@ -21,5 +21,6 @@ obj-$(CONFIG_FIB_RULES) += fib_rules.o
+ obj-$(CONFIG_TRACEPOINTS) += net-traces.o
+ obj-$(CONFIG_NET_DROP_MONITOR) += drop_monitor.o
+ obj-$(CONFIG_NETWORK_PHY_TIMESTAMPING) += timestamping.o
++obj-$(CONFIG_NET_PTP_CLASSIFY) += ptp_classifier.o
+ obj-$(CONFIG_CGROUP_NET_PRIO) += netprio_cgroup.o
+ obj-$(CONFIG_CGROUP_NET_CLASSID) += netclassid_cgroup.o
+diff --git a/net/core/ptp_classifier.c b/net/core/ptp_classifier.c
+new file mode 100644
+index 0000000..eaba0f6
+--- /dev/null
++++ b/net/core/ptp_classifier.c
+@@ -0,0 +1,141 @@
++/* PTP classifier
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of version 2 of the GNU General Public
++ * License as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ */
++
++/* The below program is the bpf_asm (tools/net/) representation of
++ * the opcode array in the ptp_filter structure.
++ *
++ * For convenience, this can easily be altered and reviewed with
++ * bpf_asm and bpf_dbg, e.g. `./bpf_asm -c prog` where prog is a
++ * simple file containing the below program:
++ *
++ * ldh [12]                        ; load ethertype
++ *
++ * ; PTP over UDP over IPv4 over Ethernet
++ * test_ipv4:
++ *   jneq #0x800, test_ipv6        ; ETH_P_IP ?
++ *   ldb [23]                      ; load proto
++ *   jneq #17, drop_ipv4           ; IPPROTO_UDP ?
++ *   ldh [20]                      ; load frag offset field
++ *   jset #0x1fff, drop_ipv4       ; don't allow fragments
++ *   ldxb 4*([14]&0xf)             ; load IP header len
++ *   ldh [x + 16]                  ; load UDP dst port
++ *   jneq #319, drop_ipv4          ; is port PTP_EV_PORT ?
++ *   ldh [x + 22]                  ; load payload
++ *   and #0xf                      ; mask PTP_CLASS_VMASK
++ *   or #0x10                      ; PTP_CLASS_IPV4
++ *   ret a                         ; return PTP class
++ *   drop_ipv4: ret #0x0           ; PTP_CLASS_NONE
++ *
++ * ; PTP over UDP over IPv6 over Ethernet
++ * test_ipv6:
++ *   jneq #0x86dd, test_8021q      ; ETH_P_IPV6 ?
++ *   ldb [20]                      ; load proto
++ *   jneq #17, drop_ipv6           ; IPPROTO_UDP ?
++ *   ldh [56]                      ; load UDP dst port
++ *   jneq #319, drop_ipv6          ; is port PTP_EV_PORT ?
++ *   ldh [62]                      ; load payload
++ *   and #0xf                      ; mask PTP_CLASS_VMASK
++ *   or #0x20                      ; PTP_CLASS_IPV6
++ *   ret a                         ; return PTP class
++ *   drop_ipv6: ret #0x0           ; PTP_CLASS_NONE
++ *
++ * ; PTP over 802.1Q over Ethernet
++ * test_8021q:
++ *   jneq #0x8100, test_ieee1588   ; ETH_P_8021Q ?
++ *   ldh [16]                      ; load inner type
++ *   jneq #0x88f7, drop_ieee1588   ; ETH_P_1588 ?
++ *   ldb [18]                      ; load payload
++ *   and #0x8                      ; as we don't have ports here, test
++ *   jneq #0x0, drop_ieee1588      ; for PTP_GEN_BIT and drop these
++ *   ldh [18]                      ; reload payload
++ *   and #0xf                      ; mask PTP_CLASS_VMASK
++ *   or #0x40                      ; PTP_CLASS_V2_VLAN
++ *   ret a                         ; return PTP class
++ *
++ * ; PTP over Ethernet
++ * test_ieee1588:
++ *   jneq #0x88f7, drop_ieee1588   ; ETH_P_1588 ?
++ *   ldb [14]                      ; load payload
++ *   and #0x8                      ; as we don't have ports here, test
++ *   jneq #0x0, drop_ieee1588      ; for PTP_GEN_BIT and drop these
++ *   ldh [14]                      ; reload payload
++ *   and #0xf                      ; mask PTP_CLASS_VMASK
++ *   or #0x30                      ; PTP_CLASS_L2
++ *   ret a                         ; return PTP class
++ *   drop_ieee1588: ret #0x0       ; PTP_CLASS_NONE
++ */
++
++#include <linux/skbuff.h>
++#include <linux/filter.h>
++#include <linux/ptp_classify.h>
++
++static struct sk_filter *ptp_insns __read_mostly;
++
++unsigned int ptp_classify_raw(const struct sk_buff *skb)
++{
++      return SK_RUN_FILTER(ptp_insns, skb);
++}
++EXPORT_SYMBOL_GPL(ptp_classify_raw);
++
++void __init ptp_classifier_init(void)
++{
++      static struct sock_filter ptp_filter[] = {
++              { 0x28,  0,  0, 0x0000000c },
++              { 0x15,  0, 12, 0x00000800 },
++              { 0x30,  0,  0, 0x00000017 },
++              { 0x15,  0,  9, 0x00000011 },
++              { 0x28,  0,  0, 0x00000014 },
++              { 0x45,  7,  0, 0x00001fff },
++              { 0xb1,  0,  0, 0x0000000e },
++              { 0x48,  0,  0, 0x00000010 },
++              { 0x15,  0,  4, 0x0000013f },
++              { 0x48,  0,  0, 0x00000016 },
++              { 0x54,  0,  0, 0x0000000f },
++              { 0x44,  0,  0, 0x00000010 },
++              { 0x16,  0,  0, 0x00000000 },
++              { 0x06,  0,  0, 0x00000000 },
++              { 0x15,  0,  9, 0x000086dd },
++              { 0x30,  0,  0, 0x00000014 },
++              { 0x15,  0,  6, 0x00000011 },
++              { 0x28,  0,  0, 0x00000038 },
++              { 0x15,  0,  4, 0x0000013f },
++              { 0x28,  0,  0, 0x0000003e },
++              { 0x54,  0,  0, 0x0000000f },
++              { 0x44,  0,  0, 0x00000020 },
++              { 0x16,  0,  0, 0x00000000 },
++              { 0x06,  0,  0, 0x00000000 },
++              { 0x15,  0,  9, 0x00008100 },
++              { 0x28,  0,  0, 0x00000010 },
++              { 0x15,  0, 15, 0x000088f7 },
++              { 0x30,  0,  0, 0x00000012 },
++              { 0x54,  0,  0, 0x00000008 },
++              { 0x15,  0, 12, 0x00000000 },
++              { 0x28,  0,  0, 0x00000012 },
++              { 0x54,  0,  0, 0x0000000f },
++              { 0x44,  0,  0, 0x00000040 },
++              { 0x16,  0,  0, 0x00000000 },
++              { 0x15,  0,  7, 0x000088f7 },
++              { 0x30,  0,  0, 0x0000000e },
++              { 0x54,  0,  0, 0x00000008 },
++              { 0x15,  0,  4, 0x00000000 },
++              { 0x28,  0,  0, 0x0000000e },
++              { 0x54,  0,  0, 0x0000000f },
++              { 0x44,  0,  0, 0x00000030 },
++              { 0x16,  0,  0, 0x00000000 },
++              { 0x06,  0,  0, 0x00000000 },
++      };
++      struct sock_fprog ptp_prog = {
++              .len = ARRAY_SIZE(ptp_filter), .filter = ptp_filter,
++      };
++
++      BUG_ON(sk_unattached_filter_create(&ptp_insns, &ptp_prog));
++}
+diff --git a/net/core/timestamping.c b/net/core/timestamping.c
+index 9ff26b3..6521dfd 100644
+--- a/net/core/timestamping.c
++++ b/net/core/timestamping.c
+@@ -23,14 +23,6 @@
+ #include <linux/skbuff.h>
+ #include <linux/export.h>
+-static struct sk_filter *ptp_insns __read_mostly;
+-
+-unsigned int ptp_classify_raw(const struct sk_buff *skb)
+-{
+-      return SK_RUN_FILTER(ptp_insns, skb);
+-}
+-EXPORT_SYMBOL_GPL(ptp_classify_raw);
+-
+ static unsigned int classify(const struct sk_buff *skb)
+ {
+       if (likely(skb->dev && skb->dev->phydev &&
+@@ -140,13 +132,3 @@ bool skb_defer_rx_timestamp(struct sk_buff *skb)
+       return false;
+ }
+ EXPORT_SYMBOL_GPL(skb_defer_rx_timestamp);
+-
+-void __init skb_timestamping_init(void)
+-{
+-      static struct sock_filter ptp_filter[] = { PTP_FILTER };
+-      struct sock_fprog ptp_prog = {
+-              .len = ARRAY_SIZE(ptp_filter), .filter = ptp_filter,
+-      };
+-
+-      BUG_ON(sk_unattached_filter_create(&ptp_insns, &ptp_prog));
+-}
+diff --git a/net/socket.c b/net/socket.c
+index f25eaa3..1b1e7e6 100644
+--- a/net/socket.c
++++ b/net/socket.c
+@@ -72,6 +72,7 @@
+ #include <linux/if_bridge.h>
+ #include <linux/if_frad.h>
+ #include <linux/if_vlan.h>
++#include <linux/ptp_classify.h>
+ #include <linux/init.h>
+ #include <linux/poll.h>
+ #include <linux/cache.h>
+@@ -2685,9 +2686,7 @@ static int __init sock_init(void)
+               goto out;
+ #endif
+-#ifdef CONFIG_NETWORK_PHY_TIMESTAMPING
+-      skb_timestamping_init();
+-#endif
++      ptp_classifier_init();
+ out:
+       return err;
+-- 
+1.8.1.4
+
diff --git a/recipes-kernel/linux/linux-yocto/0001-net-ptp-use-sk_unattached_filter_create-for-BPF.patch b/recipes-kernel/linux/linux-yocto/0001-net-ptp-use-sk_unattached_filter_create-for-BPF.patch
new file mode 100644 (file)
index 0000000..291d8d3
--- /dev/null
@@ -0,0 +1,115 @@
+From e62d2df084e2849edffb206559725fa81bb569a8 Mon Sep 17 00:00:00 2001
+From: Daniel Borkmann <dborkman@redhat.com>
+Date: Fri, 28 Mar 2014 18:58:21 +0100
+Subject: [PATCH] net: ptp: use sk_unattached_filter_create() for BPF
+
+This patch migrates an open-coded sk_run_filter() implementation with
+proper use of the BPF API, that is, sk_unattached_filter_create(). This
+migration is needed, as we will be internally transforming the filter
+to a different representation, and therefore needs to be decoupled.
+
+It is okay to do so as skb_timestamping_init() is called during
+initialization of the network stack in core initcall via sock_init().
+This would effectively also allow for PTP filters to be jit compiled if
+bpf_jit_enable is set.
+
+For better readability, there are also some newlines introduced, also
+ptp_classify.h is only in kernel space.
+
+Joint work with Alexei Starovoitov.
+
+Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
+Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
+Cc: Richard Cochran <richard.cochran@omicron.at>
+Cc: Jiri Benc <jbenc@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ include/linux/ptp_classify.h |  4 ----
+ net/core/timestamping.c      | 21 ++++++++++++++-------
+ 2 files changed, 14 insertions(+), 11 deletions(-)
+
+diff --git a/include/linux/ptp_classify.h b/include/linux/ptp_classify.h
+index 1dc420b..3decfa4 100644
+--- a/include/linux/ptp_classify.h
++++ b/include/linux/ptp_classify.h
+@@ -27,11 +27,7 @@
+ #include <linux/if_vlan.h>
+ #include <linux/ip.h>
+ #include <linux/filter.h>
+-#ifdef __KERNEL__
+ #include <linux/in.h>
+-#else
+-#include <netinet/in.h>
+-#endif
+ #define PTP_CLASS_NONE  0x00 /* not a PTP event message */
+ #define PTP_CLASS_V1    0x01 /* protocol version 1 */
+diff --git a/net/core/timestamping.c b/net/core/timestamping.c
+index 661b5a4..e43d56a 100644
+--- a/net/core/timestamping.c
++++ b/net/core/timestamping.c
+@@ -23,16 +23,13 @@
+ #include <linux/skbuff.h>
+ #include <linux/export.h>
+-static struct sock_filter ptp_filter[] = {
+-      PTP_FILTER
+-};
++static struct sk_filter *ptp_insns __read_mostly;
+ static unsigned int classify(const struct sk_buff *skb)
+ {
+-      if (likely(skb->dev &&
+-                 skb->dev->phydev &&
++      if (likely(skb->dev && skb->dev->phydev &&
+                  skb->dev->phydev->drv))
+-              return sk_run_filter(skb, ptp_filter);
++              return SK_RUN_FILTER(ptp_insns, skb);
+       else
+               return PTP_CLASS_NONE;
+ }
+@@ -60,11 +57,13 @@ void skb_clone_tx_timestamp(struct sk_buff *skb)
+               if (likely(phydev->drv->txtstamp)) {
+                       if (!atomic_inc_not_zero(&sk->sk_refcnt))
+                               return;
++
+                       clone = skb_clone(skb, GFP_ATOMIC);
+                       if (!clone) {
+                               sock_put(sk);
+                               return;
+                       }
++
+                       clone->sk = sk;
+                       phydev->drv->txtstamp(phydev, clone, type);
+               }
+@@ -89,12 +88,15 @@ void skb_complete_tx_timestamp(struct sk_buff *skb,
+       }
+       *skb_hwtstamps(skb) = *hwtstamps;
++
+       serr = SKB_EXT_ERR(skb);
+       memset(serr, 0, sizeof(*serr));
+       serr->ee.ee_errno = ENOMSG;
+       serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING;
+       skb->sk = NULL;
++
+       err = sock_queue_err_skb(sk, skb);
++
+       sock_put(sk);
+       if (err)
+               kfree_skb(skb);
+@@ -135,5 +137,10 @@ EXPORT_SYMBOL_GPL(skb_defer_rx_timestamp);
+ void __init skb_timestamping_init(void)
+ {
+-      BUG_ON(sk_chk_filter(ptp_filter, ARRAY_SIZE(ptp_filter)));
++      static struct sock_filter ptp_filter[] = { PTP_FILTER };
++      struct sock_fprog ptp_prog = {
++              .len = ARRAY_SIZE(ptp_filter), .filter = ptp_filter,
++      };
++
++      BUG_ON(sk_unattached_filter_create(&ptp_insns, &ptp_prog));
+ }
+-- 
+1.8.1.4
+
index 051118e..065c2c3 100644 (file)
@@ -3,6 +3,10 @@ FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
 SRC_URI += "file://defconfig"
 SRC_URI += "file://0001-Smack-Cgroup-filesystem-access.patch"
 SRC_URI += "file://0002-SMACK-Fix-handling-value-NULL-in-post-setxattr.patch"
+# TMP fix for error: "implicit declaration of function 'sk_run_filter'"
+SRC_URI += "file://0001-net-ptp-use-sk_unattached_filter_create-for-BPF.patch"
+SRC_URI += "file://0001-net-ptp-do-not-reimplement-PTP-BPF-classifier.patch"
+SRC_URI += "file://0001-net-ptp-move-PTP-classifier-in-its-own-file.patch"
 
 # Setting the KCONFIG_MODE variable prevents it to being set to
 # "--allnoconfig" which disable all kernel options.