mirror of
https://github.com/torvalds/linux.git
synced 2024-12-03 17:41:22 +00:00
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: Jesper Dangaard Brouer <brouer@redhat.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
parent
754b8a21a9
commit
e817f85652
@ -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 {
|
|||||||
#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 @@ drop:
|
|||||||
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,
|
|||||||
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,
|
|||||||
}
|
}
|
||||||
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)
|
|||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
|
|
||||||
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));
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user