Commit e817f856 authored by Jesper Dangaard Brouer's avatar Jesper Dangaard Brouer Committed by Alexei Starovoitov

xdp: generic XDP handling of xdp_rxq_info

Hook points for xdp_rxq_info:
 * reg  : netif_alloc_rx_queues
 * unreg: netif_free_rx_queues

The net_device have some members (num_rx_queues + real_num_rx_queues)
and data-area (dev->_rx with struct netdev_rx_queue's) that were
primarily used for exporting information about RPS (CONFIG_RPS) queues
to sysfs (CONFIG_SYSFS).

For generic XDP extend struct netdev_rx_queue with the xdp_rxq_info,
and remove some of the CONFIG_SYSFS ifdefs.
Signed-off-by: default avatarJesper Dangaard Brouer <brouer@redhat.com>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 754b8a21
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#include <net/dcbnl.h> #include <net/dcbnl.h>
#endif #endif
#include <net/netprio_cgroup.h> #include <net/netprio_cgroup.h>
#include <net/xdp.h>
#include <linux/netdev_features.h> #include <linux/netdev_features.h>
#include <linux/neighbour.h> #include <linux/neighbour.h>
...@@ -686,6 +687,7 @@ struct netdev_rx_queue { ...@@ -686,6 +687,7 @@ struct netdev_rx_queue {
#endif #endif
struct kobject kobj; struct kobject kobj;
struct net_device *dev; struct net_device *dev;
struct xdp_rxq_info xdp_rxq;
} ____cacheline_aligned_in_smp; } ____cacheline_aligned_in_smp;
/* /*
......
...@@ -3906,9 +3906,33 @@ static int enqueue_to_backlog(struct sk_buff *skb, int cpu, ...@@ -3906,9 +3906,33 @@ static int enqueue_to_backlog(struct sk_buff *skb, int cpu,
return NET_RX_DROP; return NET_RX_DROP;
} }
static struct netdev_rx_queue *netif_get_rxqueue(struct sk_buff *skb)
{
struct net_device *dev = skb->dev;
struct netdev_rx_queue *rxqueue;
rxqueue = dev->_rx;
if (skb_rx_queue_recorded(skb)) {
u16 index = skb_get_rx_queue(skb);
if (unlikely(index >= dev->real_num_rx_queues)) {
WARN_ONCE(dev->real_num_rx_queues > 1,
"%s received packet on queue %u, but number "
"of RX queues is %u\n",
dev->name, index, dev->real_num_rx_queues);
return rxqueue; /* Return first rxqueue */
}
rxqueue += index;
}
return rxqueue;
}
static u32 netif_receive_generic_xdp(struct sk_buff *skb, static u32 netif_receive_generic_xdp(struct sk_buff *skb,
struct bpf_prog *xdp_prog) struct bpf_prog *xdp_prog)
{ {
struct netdev_rx_queue *rxqueue;
u32 metalen, act = XDP_DROP; u32 metalen, act = XDP_DROP;
struct xdp_buff xdp; struct xdp_buff xdp;
void *orig_data; void *orig_data;
...@@ -3952,6 +3976,9 @@ static u32 netif_receive_generic_xdp(struct sk_buff *skb, ...@@ -3952,6 +3976,9 @@ static u32 netif_receive_generic_xdp(struct sk_buff *skb,
xdp.data_hard_start = skb->data - skb_headroom(skb); xdp.data_hard_start = skb->data - skb_headroom(skb);
orig_data = xdp.data; orig_data = xdp.data;
rxqueue = netif_get_rxqueue(skb);
xdp.rxq = &rxqueue->xdp_rxq;
act = bpf_prog_run_xdp(xdp_prog, &xdp); act = bpf_prog_run_xdp(xdp_prog, &xdp);
off = xdp.data - orig_data; off = xdp.data - orig_data;
...@@ -7589,12 +7616,12 @@ void netif_stacked_transfer_operstate(const struct net_device *rootdev, ...@@ -7589,12 +7616,12 @@ void netif_stacked_transfer_operstate(const struct net_device *rootdev,
} }
EXPORT_SYMBOL(netif_stacked_transfer_operstate); EXPORT_SYMBOL(netif_stacked_transfer_operstate);
#ifdef CONFIG_SYSFS
static int netif_alloc_rx_queues(struct net_device *dev) static int netif_alloc_rx_queues(struct net_device *dev)
{ {
unsigned int i, count = dev->num_rx_queues; unsigned int i, count = dev->num_rx_queues;
struct netdev_rx_queue *rx; struct netdev_rx_queue *rx;
size_t sz = count * sizeof(*rx); size_t sz = count * sizeof(*rx);
int err = 0;
BUG_ON(count < 1); BUG_ON(count < 1);
...@@ -7604,11 +7631,39 @@ static int netif_alloc_rx_queues(struct net_device *dev) ...@@ -7604,11 +7631,39 @@ static int netif_alloc_rx_queues(struct net_device *dev)
dev->_rx = rx; dev->_rx = rx;
for (i = 0; i < count; i++) for (i = 0; i < count; i++) {
rx[i].dev = dev; rx[i].dev = dev;
/* XDP RX-queue setup */
err = xdp_rxq_info_reg(&rx[i].xdp_rxq, dev, i);
if (err < 0)
goto err_rxq_info;
}
return 0; return 0;
err_rxq_info:
/* Rollback successful reg's and free other resources */
while (i--)
xdp_rxq_info_unreg(&rx[i].xdp_rxq);
kfree(dev->_rx);
dev->_rx = NULL;
return err;
}
static void netif_free_rx_queues(struct net_device *dev)
{
unsigned int i, count = dev->num_rx_queues;
struct netdev_rx_queue *rx;
/* netif_alloc_rx_queues alloc failed, resources have been unreg'ed */
if (!dev->_rx)
return;
rx = dev->_rx;
for (i = 0; i < count; i++)
xdp_rxq_info_unreg(&rx[i].xdp_rxq);
} }
#endif
static void netdev_init_one_queue(struct net_device *dev, static void netdev_init_one_queue(struct net_device *dev,
struct netdev_queue *queue, void *_unused) struct netdev_queue *queue, void *_unused)
...@@ -8169,12 +8224,10 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, ...@@ -8169,12 +8224,10 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
return NULL; return NULL;
} }
#ifdef CONFIG_SYSFS
if (rxqs < 1) { if (rxqs < 1) {
pr_err("alloc_netdev: Unable to allocate device with zero RX queues\n"); pr_err("alloc_netdev: Unable to allocate device with zero RX queues\n");
return NULL; return NULL;
} }
#endif
alloc_size = sizeof(struct net_device); alloc_size = sizeof(struct net_device);
if (sizeof_priv) { if (sizeof_priv) {
...@@ -8231,12 +8284,10 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, ...@@ -8231,12 +8284,10 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
if (netif_alloc_netdev_queues(dev)) if (netif_alloc_netdev_queues(dev))
goto free_all; goto free_all;
#ifdef CONFIG_SYSFS
dev->num_rx_queues = rxqs; dev->num_rx_queues = rxqs;
dev->real_num_rx_queues = rxqs; dev->real_num_rx_queues = rxqs;
if (netif_alloc_rx_queues(dev)) if (netif_alloc_rx_queues(dev))
goto free_all; goto free_all;
#endif
strcpy(dev->name, name); strcpy(dev->name, name);
dev->name_assign_type = name_assign_type; dev->name_assign_type = name_assign_type;
...@@ -8275,9 +8326,7 @@ void free_netdev(struct net_device *dev) ...@@ -8275,9 +8326,7 @@ void free_netdev(struct net_device *dev)
might_sleep(); might_sleep();
netif_free_tx_queues(dev); netif_free_tx_queues(dev);
#ifdef CONFIG_SYSFS netif_free_rx_queues(dev);
kvfree(dev->_rx);
#endif
kfree(rcu_dereference_protected(dev->ingress_queue, 1)); kfree(rcu_dereference_protected(dev->ingress_queue, 1));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment