Skip to content

Commit 180e35c

Browse files
emuslndavem330
authored andcommitted
ionic: add initial framework for XDP support
Set up the basics for running Rx packets through XDP programs. Add new queue setup and teardown steps for adding/removing an XDP program, and add the call to run the XDP on a packet. The XDP frame size needs to be the MTU plus standard ethernet header, plus head room for XDP scribblings and tail room for a struct skb_shared_info. Also, at this point, we don't support XDP frags, only a single contiguous Rx buffer. This means that our page splitting is not very useful, so when XDP is in use we need to use the full Rx buffer size and not do sharing. Co-developed-by: Brett Creeley <[email protected]> Signed-off-by: Brett Creeley <[email protected]> Signed-off-by: Shannon Nelson <[email protected]> Reviewed-by: Jacob Keller <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent d67ee21 commit 180e35c

File tree

6 files changed

+269
-14
lines changed

6 files changed

+269
-14
lines changed

drivers/net/ethernet/pensando/ionic/ionic_dev.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <linux/mutex.h>
99
#include <linux/workqueue.h>
1010
#include <linux/skbuff.h>
11+
#include <linux/bpf_trace.h>
1112

1213
#include "ionic_if.h"
1314
#include "ionic_regs.h"
@@ -195,6 +196,11 @@ typedef void (*ionic_desc_cb)(struct ionic_queue *q,
195196
#define IONIC_PAGE_GFP_MASK (GFP_ATOMIC | __GFP_NOWARN |\
196197
__GFP_COMP | __GFP_MEMALLOC)
197198

199+
#define IONIC_XDP_MAX_LINEAR_MTU (IONIC_PAGE_SIZE - \
200+
(VLAN_ETH_HLEN + \
201+
XDP_PACKET_HEADROOM + \
202+
SKB_DATA_ALIGN(sizeof(struct skb_shared_info))))
203+
198204
struct ionic_buf_info {
199205
struct page *page;
200206
dma_addr_t dma_addr;
@@ -256,6 +262,7 @@ struct ionic_queue {
256262
struct ionic_txq_sg_desc *txq_sgl;
257263
struct ionic_rxq_sg_desc *rxq_sgl;
258264
};
265+
struct xdp_rxq_info *xdp_rxq_info;
259266
dma_addr_t base_pa;
260267
dma_addr_t cmb_base_pa;
261268
dma_addr_t sg_base_pa;

drivers/net/ethernet/pensando/ionic/ionic_ethtool.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,11 @@ static int ionic_set_channels(struct net_device *netdev,
721721

722722
ionic_init_queue_params(lif, &qparam);
723723

724+
if ((ch->rx_count || ch->tx_count) && lif->xdp_prog) {
725+
netdev_info(lif->netdev, "Split Tx/Rx interrupts not available when using XDP\n");
726+
return -EOPNOTSUPP;
727+
}
728+
724729
if (ch->rx_count != ch->tx_count) {
725730
netdev_info(netdev, "The rx and tx count must be equal\n");
726731
return -EINVAL;

drivers/net/ethernet/pensando/ionic/ionic_lif.c

Lines changed: 173 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ static int ionic_start_queues(struct ionic_lif *lif);
4646
static void ionic_stop_queues(struct ionic_lif *lif);
4747
static void ionic_lif_queue_identify(struct ionic_lif *lif);
4848

49+
static int ionic_xdp_queues_config(struct ionic_lif *lif);
50+
static void ionic_xdp_unregister_rxq_info(struct ionic_queue *q);
51+
4952
static void ionic_dim_work(struct work_struct *work)
5053
{
5154
struct dim *dim = container_of(work, struct dim, work);
@@ -422,6 +425,7 @@ static void ionic_qcq_free(struct ionic_lif *lif, struct ionic_qcq *qcq)
422425
qcq->sg_base_pa = 0;
423426
}
424427

428+
ionic_xdp_unregister_rxq_info(&qcq->q);
425429
ionic_qcq_intr_free(lif, qcq);
426430

427431
vfree(qcq->cq.info);
@@ -862,8 +866,7 @@ static int ionic_lif_rxq_init(struct ionic_lif *lif, struct ionic_qcq *qcq)
862866
.type = q->type,
863867
.ver = lif->qtype_info[q->type].version,
864868
.index = cpu_to_le32(q->index),
865-
.flags = cpu_to_le16(IONIC_QINIT_F_IRQ |
866-
IONIC_QINIT_F_SG),
869+
.flags = cpu_to_le16(IONIC_QINIT_F_IRQ),
867870
.intr_index = cpu_to_le16(cq->bound_intr->index),
868871
.pid = cpu_to_le16(q->pid),
869872
.ring_size = ilog2(q->num_descs),
@@ -875,6 +878,9 @@ static int ionic_lif_rxq_init(struct ionic_lif *lif, struct ionic_qcq *qcq)
875878
};
876879
int err;
877880

881+
if (!lif->xdp_prog)
882+
ctx.cmd.q_init.flags |= cpu_to_le16(IONIC_QINIT_F_SG);
883+
878884
if (qcq->flags & IONIC_QCQ_F_CMB_RINGS) {
879885
ctx.cmd.q_init.flags |= cpu_to_le16(IONIC_QINIT_F_CMB);
880886
ctx.cmd.q_init.ring_base = cpu_to_le64(qcq->cmb_q_base_pa);
@@ -1640,6 +1646,8 @@ static int ionic_init_nic_features(struct ionic_lif *lif)
16401646
netdev->priv_flags |= IFF_UNICAST_FLT |
16411647
IFF_LIVE_ADDR_CHANGE;
16421648

1649+
netdev->xdp_features = NETDEV_XDP_ACT_BASIC;
1650+
16431651
return 0;
16441652
}
16451653

@@ -1777,6 +1785,18 @@ static int ionic_start_queues_reconfig(struct ionic_lif *lif)
17771785
return err;
17781786
}
17791787

1788+
static bool ionic_xdp_is_valid_mtu(struct ionic_lif *lif, u32 mtu,
1789+
struct bpf_prog *xdp_prog)
1790+
{
1791+
if (!xdp_prog)
1792+
return true;
1793+
1794+
if (mtu <= IONIC_XDP_MAX_LINEAR_MTU)
1795+
return true;
1796+
1797+
return false;
1798+
}
1799+
17801800
static int ionic_change_mtu(struct net_device *netdev, int new_mtu)
17811801
{
17821802
struct ionic_lif *lif = netdev_priv(netdev);
@@ -1789,8 +1809,13 @@ static int ionic_change_mtu(struct net_device *netdev, int new_mtu)
17891809
.mtu = cpu_to_le32(new_mtu),
17901810
},
17911811
};
1812+
struct bpf_prog *xdp_prog;
17921813
int err;
17931814

1815+
xdp_prog = READ_ONCE(lif->xdp_prog);
1816+
if (!ionic_xdp_is_valid_mtu(lif, new_mtu, xdp_prog))
1817+
return -EINVAL;
1818+
17941819
err = ionic_adminq_post_wait(lif, &ctx);
17951820
if (err)
17961821
return err;
@@ -2166,6 +2191,10 @@ static int ionic_txrx_enable(struct ionic_lif *lif)
21662191
int derr = 0;
21672192
int i, err;
21682193

2194+
err = ionic_xdp_queues_config(lif);
2195+
if (err)
2196+
return err;
2197+
21692198
for (i = 0; i < lif->nxqs; i++) {
21702199
if (!(lif->rxqcqs[i] && lif->txqcqs[i])) {
21712200
dev_err(lif->ionic->dev, "%s: bad qcq %d\n", __func__, i);
@@ -2211,6 +2240,8 @@ static int ionic_txrx_enable(struct ionic_lif *lif)
22112240
derr = ionic_qcq_disable(lif, lif->rxqcqs[i], derr);
22122241
}
22132242

2243+
ionic_xdp_queues_config(lif);
2244+
22142245
return err;
22152246
}
22162247

@@ -2668,11 +2699,150 @@ static void ionic_vf_attr_replay(struct ionic_lif *lif)
26682699
ionic_vf_start(ionic);
26692700
}
26702701

2702+
static void ionic_xdp_unregister_rxq_info(struct ionic_queue *q)
2703+
{
2704+
struct xdp_rxq_info *xi;
2705+
2706+
if (!q->xdp_rxq_info)
2707+
return;
2708+
2709+
xi = q->xdp_rxq_info;
2710+
q->xdp_rxq_info = NULL;
2711+
2712+
xdp_rxq_info_unreg(xi);
2713+
kfree(xi);
2714+
}
2715+
2716+
static int ionic_xdp_register_rxq_info(struct ionic_queue *q, unsigned int napi_id)
2717+
{
2718+
struct xdp_rxq_info *rxq_info;
2719+
int err;
2720+
2721+
rxq_info = kzalloc(sizeof(*rxq_info), GFP_KERNEL);
2722+
if (!rxq_info)
2723+
return -ENOMEM;
2724+
2725+
err = xdp_rxq_info_reg(rxq_info, q->lif->netdev, q->index, napi_id);
2726+
if (err) {
2727+
dev_err(q->dev, "Queue %d xdp_rxq_info_reg failed, err %d\n",
2728+
q->index, err);
2729+
goto err_out;
2730+
}
2731+
2732+
err = xdp_rxq_info_reg_mem_model(rxq_info, MEM_TYPE_PAGE_ORDER0, NULL);
2733+
if (err) {
2734+
dev_err(q->dev, "Queue %d xdp_rxq_info_reg_mem_model failed, err %d\n",
2735+
q->index, err);
2736+
xdp_rxq_info_unreg(rxq_info);
2737+
goto err_out;
2738+
}
2739+
2740+
q->xdp_rxq_info = rxq_info;
2741+
2742+
return 0;
2743+
2744+
err_out:
2745+
kfree(rxq_info);
2746+
return err;
2747+
}
2748+
2749+
static int ionic_xdp_queues_config(struct ionic_lif *lif)
2750+
{
2751+
unsigned int i;
2752+
int err;
2753+
2754+
if (!lif->rxqcqs)
2755+
return 0;
2756+
2757+
/* There's no need to rework memory if not going to/from NULL program.
2758+
* If there is no lif->xdp_prog, there should also be no q.xdp_rxq_info
2759+
* This way we don't need to keep an *xdp_prog in every queue struct.
2760+
*/
2761+
if (!lif->xdp_prog == !lif->rxqcqs[0]->q.xdp_rxq_info)
2762+
return 0;
2763+
2764+
for (i = 0; i < lif->ionic->nrxqs_per_lif && lif->rxqcqs[i]; i++) {
2765+
struct ionic_queue *q = &lif->rxqcqs[i]->q;
2766+
2767+
if (q->xdp_rxq_info) {
2768+
ionic_xdp_unregister_rxq_info(q);
2769+
continue;
2770+
}
2771+
2772+
err = ionic_xdp_register_rxq_info(q, lif->rxqcqs[i]->napi.napi_id);
2773+
if (err) {
2774+
dev_err(lif->ionic->dev, "failed to register RX queue %d info for XDP, err %d\n",
2775+
i, err);
2776+
goto err_out;
2777+
}
2778+
}
2779+
2780+
return 0;
2781+
2782+
err_out:
2783+
for (i = 0; i < lif->ionic->nrxqs_per_lif && lif->rxqcqs[i]; i++)
2784+
ionic_xdp_unregister_rxq_info(&lif->rxqcqs[i]->q);
2785+
2786+
return err;
2787+
}
2788+
2789+
static int ionic_xdp_config(struct net_device *netdev, struct netdev_bpf *bpf)
2790+
{
2791+
struct ionic_lif *lif = netdev_priv(netdev);
2792+
struct bpf_prog *old_prog;
2793+
u32 maxfs;
2794+
2795+
if (test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state)) {
2796+
#define XDP_ERR_SPLIT "XDP not available with split Tx/Rx interrupts"
2797+
NL_SET_ERR_MSG_MOD(bpf->extack, XDP_ERR_SPLIT);
2798+
netdev_info(lif->netdev, XDP_ERR_SPLIT);
2799+
return -EOPNOTSUPP;
2800+
}
2801+
2802+
if (!ionic_xdp_is_valid_mtu(lif, netdev->mtu, bpf->prog)) {
2803+
#define XDP_ERR_MTU "MTU is too large for XDP without frags support"
2804+
NL_SET_ERR_MSG_MOD(bpf->extack, XDP_ERR_MTU);
2805+
netdev_info(lif->netdev, XDP_ERR_MTU);
2806+
return -EINVAL;
2807+
}
2808+
2809+
maxfs = __le32_to_cpu(lif->identity->eth.max_frame_size) - VLAN_ETH_HLEN;
2810+
if (bpf->prog)
2811+
maxfs = min_t(u32, maxfs, IONIC_XDP_MAX_LINEAR_MTU);
2812+
netdev->max_mtu = maxfs;
2813+
2814+
if (!netif_running(netdev)) {
2815+
old_prog = xchg(&lif->xdp_prog, bpf->prog);
2816+
} else {
2817+
mutex_lock(&lif->queue_lock);
2818+
ionic_stop_queues_reconfig(lif);
2819+
old_prog = xchg(&lif->xdp_prog, bpf->prog);
2820+
ionic_start_queues_reconfig(lif);
2821+
mutex_unlock(&lif->queue_lock);
2822+
}
2823+
2824+
if (old_prog)
2825+
bpf_prog_put(old_prog);
2826+
2827+
return 0;
2828+
}
2829+
2830+
static int ionic_xdp(struct net_device *netdev, struct netdev_bpf *bpf)
2831+
{
2832+
switch (bpf->command) {
2833+
case XDP_SETUP_PROG:
2834+
return ionic_xdp_config(netdev, bpf);
2835+
default:
2836+
return -EINVAL;
2837+
}
2838+
}
2839+
26712840
static const struct net_device_ops ionic_netdev_ops = {
26722841
.ndo_open = ionic_open,
26732842
.ndo_stop = ionic_stop,
26742843
.ndo_eth_ioctl = ionic_eth_ioctl,
26752844
.ndo_start_xmit = ionic_start_xmit,
2845+
.ndo_bpf = ionic_xdp,
26762846
.ndo_get_stats64 = ionic_get_stats64,
26772847
.ndo_set_rx_mode = ionic_ndo_set_rx_mode,
26782848
.ndo_set_features = ionic_set_features,
@@ -2755,6 +2925,7 @@ static void ionic_swap_queues(struct ionic_qcq *a, struct ionic_qcq *b)
27552925
swap(a->q.base, b->q.base);
27562926
swap(a->q.base_pa, b->q.base_pa);
27572927
swap(a->q.info, b->q.info);
2928+
swap(a->q.xdp_rxq_info, b->q.xdp_rxq_info);
27582929
swap(a->q_base, b->q_base);
27592930
swap(a->q_base_pa, b->q_base_pa);
27602931
swap(a->q_size, b->q_size);

drivers/net/ethernet/pensando/ionic/ionic_lif.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ struct ionic_rx_stats {
5151
u64 alloc_err;
5252
u64 hwstamp_valid;
5353
u64 hwstamp_invalid;
54+
u64 xdp_drop;
55+
u64 xdp_aborted;
56+
u64 xdp_pass;
5457
};
5558

5659
#define IONIC_QCQ_F_INITED BIT(0)
@@ -135,6 +138,9 @@ struct ionic_lif_sw_stats {
135138
u64 hw_rx_over_errors;
136139
u64 hw_rx_missed_errors;
137140
u64 hw_tx_aborted_errors;
141+
u64 xdp_drop;
142+
u64 xdp_aborted;
143+
u64 xdp_pass;
138144
};
139145

140146
enum ionic_lif_state_flags {
@@ -230,6 +236,7 @@ struct ionic_lif {
230236
struct ionic_phc *phc;
231237

232238
struct dentry *dentry;
239+
struct bpf_prog *xdp_prog;
233240
};
234241

235242
struct ionic_phc {

drivers/net/ethernet/pensando/ionic/ionic_stats.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ static const struct ionic_stat_desc ionic_lif_stats_desc[] = {
2727
IONIC_LIF_STAT_DESC(hw_rx_over_errors),
2828
IONIC_LIF_STAT_DESC(hw_rx_missed_errors),
2929
IONIC_LIF_STAT_DESC(hw_tx_aborted_errors),
30+
IONIC_LIF_STAT_DESC(xdp_drop),
31+
IONIC_LIF_STAT_DESC(xdp_aborted),
32+
IONIC_LIF_STAT_DESC(xdp_pass),
3033
};
3134

3235
static const struct ionic_stat_desc ionic_port_stats_desc[] = {
@@ -149,6 +152,9 @@ static const struct ionic_stat_desc ionic_rx_stats_desc[] = {
149152
IONIC_RX_STAT_DESC(hwstamp_invalid),
150153
IONIC_RX_STAT_DESC(dropped),
151154
IONIC_RX_STAT_DESC(vlan_stripped),
155+
IONIC_RX_STAT_DESC(xdp_drop),
156+
IONIC_RX_STAT_DESC(xdp_aborted),
157+
IONIC_RX_STAT_DESC(xdp_pass),
152158
};
153159

154160
#define IONIC_NUM_LIF_STATS ARRAY_SIZE(ionic_lif_stats_desc)
@@ -185,6 +191,9 @@ static void ionic_add_lif_rxq_stats(struct ionic_lif *lif, int q_num,
185191
stats->rx_csum_error += rxstats->csum_error;
186192
stats->rx_hwstamp_valid += rxstats->hwstamp_valid;
187193
stats->rx_hwstamp_invalid += rxstats->hwstamp_invalid;
194+
stats->xdp_drop += rxstats->xdp_drop;
195+
stats->xdp_aborted += rxstats->xdp_aborted;
196+
stats->xdp_pass += rxstats->xdp_pass;
188197
}
189198

190199
static void ionic_get_lif_stats(struct ionic_lif *lif,

0 commit comments

Comments
 (0)