diff options
| author | Toke Høiland-Jørgensen <toke@redhat.com> | 2021-11-08 22:18:28 +0100 |
|---|---|---|
| committer | Toke Høiland-Jørgensen <toke@redhat.com> | 2021-11-09 21:35:16 +0100 |
| commit | f88dc77e8d556abca484fb6dc9b6fc7517452af8 (patch) | |
| tree | 8ddfe4402135169866430739b36f7db003cd4173 | |
| parent | 6805907f11a49512c2e6fb534df22784eb91d2ef (diff) | |
| download | linux-f88dc77e8d556abca484fb6dc9b6fc7517452af8.tar.gz | |
net: add a page pool instance to the loopback device
This adds a page pool instance to the loopback device. This will be used in
a subsequent patch to support proper XDP_REDIRECT in bpf_prog_run(), and is
only initialised on the first use (so the memory overhead when it's not
used is only a single pointer).
Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
| -rw-r--r-- | drivers/net/loopback.c | 48 | ||||
| -rw-r--r-- | include/linux/netdevice.h | 1 |
2 files changed, 48 insertions, 1 deletions
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index a1c77cc004165..b3514568890a9 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -54,6 +54,7 @@ #include <linux/net_tstamp.h> #include <net/net_namespace.h> #include <linux/u64_stats_sync.h> +#include <net/page_pool.h> /* blackhole_netdev - a device used for dsts that are marked expired! * This is global device (instead of per-net-ns) since it's not needed @@ -62,6 +63,10 @@ struct net_device *blackhole_netdev; EXPORT_SYMBOL(blackhole_netdev); +struct loopback_priv { + struct page_pool *page_pool; +}; + /* The higher levels take care of making this non-reentrant (it's * called with bh's disabled). */ @@ -148,10 +153,51 @@ static int loopback_dev_init(struct net_device *dev) static void loopback_dev_free(struct net_device *dev) { + struct loopback_priv *priv = netdev_priv(dev); + + if (priv->page_pool) { + page_pool_destroy(priv->page_pool); + priv->page_pool = NULL; + } + dev_net(dev)->loopback_dev = NULL; free_percpu(dev->lstats); } +struct page_pool *dev_loopback_get_page_pool(struct net *net) +{ + struct net_device *dev = net->loopback_dev; + struct loopback_priv *priv = netdev_priv(dev); + + if (!priv->page_pool) { + struct page_pool_params pp_params = { + .order = 0, + .flags = 0, + .pool_size = 128, + .nid = NUMA_NO_NODE, + .max_len = PAGE_SIZE - sizeof(struct skb_shared_info), + }; + struct netdev_rx_queue *rxq; + struct page_pool *pp; + int err; + + rxq = __netif_get_rx_queue(dev, 0); + + pp = page_pool_create(&pp_params); + if (IS_ERR(pp)) + return pp; + + err = xdp_rxq_info_reg_mem_model(&rxq->xdp_rxq, MEM_TYPE_PAGE_POOL, pp); + if (err) { + page_pool_destroy(pp); + return ERR_PTR(err); + } + priv->page_pool = pp; + } + + return priv->page_pool; +} + static const struct net_device_ops loopback_ops = { .ndo_init = loopback_dev_init, .ndo_start_xmit = loopback_xmit, @@ -208,7 +254,7 @@ static __net_init int loopback_net_init(struct net *net) int err; err = -ENOMEM; - dev = alloc_netdev(0, "lo", NET_NAME_UNKNOWN, loopback_setup); + dev = alloc_netdev(sizeof(struct loopback_priv), "lo", NET_NAME_UNKNOWN, loopback_setup); if (!dev) goto out; diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 3ec42495a43a5..efce0f22b71ca 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2962,6 +2962,7 @@ void dev_close(struct net_device *dev); void dev_close_many(struct list_head *head, bool unlink); void dev_disable_lro(struct net_device *dev); int dev_loopback_xmit(struct net *net, struct sock *sk, struct sk_buff *newskb); +struct page_pool *dev_loopback_get_page_pool(struct net *net); u16 dev_pick_tx_zero(struct net_device *dev, struct sk_buff *skb, struct net_device *sb_dev); u16 dev_pick_tx_cpu_id(struct net_device *dev, struct sk_buff *skb, |
