net: ptp: do not reimplement PTP/BPF classifier
authorDaniel Borkmann <dborkman@redhat.com>
Fri, 28 Mar 2014 17:58:22 +0000 (18:58 +0100)
committerDavid S. Miller <davem@davemloft.net>
Mon, 31 Mar 2014 04:45:09 +0000 (00:45 -0400)
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
drivers/net/ethernet/ti/cpts.c
drivers/net/ethernet/xscale/ixp4xx_eth.c
include/linux/ptp_classify.h
net/core/timestamping.c

index 464e91058c81157da7fa8d3c25a03b266ed0ffe6..73e66838cfef901e276803b2a6d136fdbd20aa02 100644 (file)
@@ -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;
index 372cb192c5aaadb1238a8bb50862c4b7a5155008..a3bbf59eaafdf2e31b400336129e3731e0d88364 100644 (file)
 
 #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)) {
index 25283f17d82f34e093e8b41fe195f82ebb66db26..f7e0f0f7c2e27dd19b2cbc674644cd4678074c2c 100644 (file)
@@ -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;
 
index 3decfa4d3732cd8bbef5b5efba7b0a4b64ceab8c..6d3b0a2ef9ce851f299c03b3f83fcd5a8e4d4952 100644 (file)
 #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
index e43d56acf803cdef5aeb38a17e071db9325b2de1..9ff26b3cc021b1c3e80d80f5dfff7d726a0c46e9 100644 (file)
 
 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;
 }