Skip to content

Commit 838c93d

Browse files
Sameeh Jubrandavem330
Sameeh Jubran
authored andcommitted
net: ena: implement XDP drop support
This commit implements the basic functionality of drop/pass logic in the ena driver. Signed-off-by: Sameeh Jubran <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent aabf23d commit 838c93d

File tree

2 files changed

+233
-11
lines changed

2 files changed

+233
-11
lines changed

drivers/net/ethernet/amazon/ena/ena_netdev.c

+202-11
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
#include <linux/cpu_rmap.h>
3737
#endif /* CONFIG_RFS_ACCEL */
3838
#include <linux/ethtool.h>
39-
#include <linux/if_vlan.h>
4039
#include <linux/kernel.h>
4140
#include <linux/module.h>
4241
#include <linux/numa.h>
@@ -47,6 +46,7 @@
4746
#include <net/ip.h>
4847

4948
#include "ena_netdev.h"
49+
#include <linux/bpf_trace.h>
5050
#include "ena_pci_id_tbl.h"
5151

5252
static char version[] = DEVICE_NAME " v" DRV_MODULE_VERSION "\n";
@@ -77,6 +77,8 @@ static int ena_rss_init_default(struct ena_adapter *adapter);
7777
static void check_for_admin_com_state(struct ena_adapter *adapter);
7878
static void ena_destroy_device(struct ena_adapter *adapter, bool graceful);
7979
static int ena_restore_device(struct ena_adapter *adapter);
80+
static void ena_down(struct ena_adapter *adapter);
81+
static int ena_up(struct ena_adapter *adapter);
8082

8183
static void ena_tx_timeout(struct net_device *dev)
8284
{
@@ -123,6 +125,115 @@ static int ena_change_mtu(struct net_device *dev, int new_mtu)
123125
return ret;
124126
}
125127

128+
static int ena_xdp_execute(struct ena_ring *rx_ring, struct xdp_buff *xdp)
129+
{
130+
struct bpf_prog *xdp_prog;
131+
u32 verdict = XDP_PASS;
132+
133+
rcu_read_lock();
134+
xdp_prog = READ_ONCE(rx_ring->xdp_bpf_prog);
135+
136+
if (!xdp_prog)
137+
goto out;
138+
139+
verdict = bpf_prog_run_xdp(xdp_prog, xdp);
140+
141+
if (unlikely(verdict == XDP_ABORTED))
142+
trace_xdp_exception(rx_ring->netdev, xdp_prog, verdict);
143+
else if (unlikely(verdict >= XDP_TX))
144+
bpf_warn_invalid_xdp_action(verdict);
145+
out:
146+
rcu_read_unlock();
147+
return verdict;
148+
}
149+
150+
void ena_xdp_exchange_program_rx_in_range(struct ena_adapter *adapter,
151+
struct bpf_prog *prog,
152+
int first,
153+
int count)
154+
{
155+
struct ena_ring *rx_ring;
156+
int i = 0;
157+
158+
for (i = first; i < count; i++) {
159+
rx_ring = &adapter->rx_ring[i];
160+
xchg(&rx_ring->xdp_bpf_prog, prog);
161+
if (prog)
162+
rx_ring->rx_headroom = XDP_PACKET_HEADROOM;
163+
else
164+
rx_ring->rx_headroom = 0;
165+
}
166+
}
167+
168+
void ena_xdp_exchange_program(struct ena_adapter *adapter,
169+
struct bpf_prog *prog)
170+
{
171+
struct bpf_prog *old_bpf_prog = xchg(&adapter->xdp_bpf_prog, prog);
172+
173+
ena_xdp_exchange_program_rx_in_range(adapter,
174+
prog,
175+
0,
176+
adapter->num_io_queues);
177+
178+
if (old_bpf_prog)
179+
bpf_prog_put(old_bpf_prog);
180+
}
181+
182+
static int ena_xdp_set(struct net_device *netdev, struct netdev_bpf *bpf)
183+
{
184+
struct ena_adapter *adapter = netdev_priv(netdev);
185+
struct bpf_prog *prog = bpf->prog;
186+
int rc, prev_mtu;
187+
bool is_up;
188+
189+
is_up = test_bit(ENA_FLAG_DEV_UP, &adapter->flags);
190+
191+
if (ena_xdp_allowed(adapter)) {
192+
if (is_up)
193+
ena_down(adapter);
194+
195+
ena_xdp_exchange_program(adapter, prog);
196+
197+
prev_mtu = netdev->max_mtu;
198+
netdev->max_mtu = prog ? ENA_XDP_MAX_MTU : adapter->max_mtu;
199+
if (is_up) {
200+
rc = ena_up(adapter);
201+
if (rc)
202+
return rc;
203+
}
204+
netif_info(adapter, drv, adapter->netdev, "xdp program set, changging the max_mtu from %d to %d",
205+
prev_mtu, netdev->max_mtu);
206+
207+
} else {
208+
netif_err(adapter, drv, adapter->netdev, "Failed to set xdp program, the current MTU (%d) is larger than the maximum allowed MTU (%lu) while xdp is on",
209+
netdev->mtu, ENA_XDP_MAX_MTU);
210+
NL_SET_ERR_MSG_MOD(bpf->extack, "Failed to set xdp program, the current MTU is larger than the maximum allowed MTU. Check the dmesg for more info");
211+
return -EINVAL;
212+
}
213+
214+
return 0;
215+
}
216+
217+
/* This is the main xdp callback, it's used by the kernel to set/unset the xdp
218+
* program as well as to query the current xdp program id.
219+
*/
220+
static int ena_xdp(struct net_device *netdev, struct netdev_bpf *bpf)
221+
{
222+
struct ena_adapter *adapter = netdev_priv(netdev);
223+
224+
switch (bpf->command) {
225+
case XDP_SETUP_PROG:
226+
return ena_xdp_set(netdev, bpf);
227+
case XDP_QUERY_PROG:
228+
bpf->prog_id = adapter->xdp_bpf_prog ?
229+
adapter->xdp_bpf_prog->aux->id : 0;
230+
break;
231+
default:
232+
return -EINVAL;
233+
}
234+
return 0;
235+
}
236+
126237
static int ena_init_rx_cpu_rmap(struct ena_adapter *adapter)
127238
{
128239
#ifdef CONFIG_RFS_ACCEL
@@ -417,6 +528,9 @@ static void ena_free_rx_resources(struct ena_adapter *adapter,
417528

418529
vfree(rx_ring->free_ids);
419530
rx_ring->free_ids = NULL;
531+
532+
xdp_rxq_info_unreg_mem_model(&rx_ring->xdp_rxq);
533+
xdp_rxq_info_unreg(&rx_ring->xdp_rxq);
420534
}
421535

422536
/* ena_setup_all_rx_resources - allocate I/O Rx queues resources for all queues
@@ -495,7 +609,7 @@ static int ena_alloc_rx_page(struct ena_ring *rx_ring,
495609
rx_info->page = page;
496610
rx_info->page_offset = 0;
497611
ena_buf = &rx_info->ena_buf;
498-
ena_buf->paddr = dma;
612+
ena_buf->paddr = dma + rx_ring->rx_headroom;
499613
ena_buf->len = ENA_PAGE_SIZE;
500614

501615
return 0;
@@ -1037,6 +1151,33 @@ static void ena_set_rx_hash(struct ena_ring *rx_ring,
10371151
}
10381152
}
10391153

1154+
int ena_xdp_handle_buff(struct ena_ring *rx_ring, struct xdp_buff *xdp)
1155+
{
1156+
struct ena_rx_buffer *rx_info;
1157+
int ret;
1158+
1159+
rx_info = &rx_ring->rx_buffer_info[rx_ring->ena_bufs[0].req_id];
1160+
xdp->data = page_address(rx_info->page) +
1161+
rx_info->page_offset + rx_ring->rx_headroom;
1162+
xdp_set_data_meta_invalid(xdp);
1163+
xdp->data_hard_start = page_address(rx_info->page);
1164+
xdp->data_end = xdp->data + rx_ring->ena_bufs[0].len;
1165+
/* If for some reason we received a bigger packet than
1166+
* we expect, then we simply drop it
1167+
*/
1168+
if (unlikely(rx_ring->ena_bufs[0].len > ENA_XDP_MAX_MTU))
1169+
return XDP_DROP;
1170+
1171+
ret = ena_xdp_execute(rx_ring, xdp);
1172+
1173+
/* The xdp program might expand the headers */
1174+
if (ret == XDP_PASS) {
1175+
rx_info->page_offset = xdp->data - xdp->data_hard_start;
1176+
rx_ring->ena_bufs[0].len = xdp->data_end - xdp->data;
1177+
}
1178+
1179+
return ret;
1180+
}
10401181
/* ena_clean_rx_irq - Cleanup RX irq
10411182
* @rx_ring: RX ring to clean
10421183
* @napi: napi handler
@@ -1052,19 +1193,23 @@ static int ena_clean_rx_irq(struct ena_ring *rx_ring, struct napi_struct *napi,
10521193

10531194
struct ena_com_rx_ctx ena_rx_ctx;
10541195
struct ena_adapter *adapter;
1196+
int rx_copybreak_pkt = 0;
1197+
int refill_threshold;
10551198
struct sk_buff *skb;
10561199
int refill_required;
1057-
int refill_threshold;
1058-
int rc = 0;
1200+
struct xdp_buff xdp;
10591201
int total_len = 0;
1060-
int rx_copybreak_pkt = 0;
1202+
int xdp_verdict;
1203+
int rc = 0;
10611204
int i;
10621205

10631206
netif_dbg(rx_ring->adapter, rx_status, rx_ring->netdev,
10641207
"%s qid %d\n", __func__, rx_ring->qid);
10651208
res_budget = budget;
1066-
1209+
xdp.rxq = &rx_ring->xdp_rxq;
10671210
do {
1211+
xdp_verdict = XDP_PASS;
1212+
skb = NULL;
10681213
ena_rx_ctx.ena_bufs = rx_ring->ena_bufs;
10691214
ena_rx_ctx.max_bufs = rx_ring->sgl_size;
10701215
ena_rx_ctx.descs = 0;
@@ -1082,11 +1227,16 @@ static int ena_clean_rx_irq(struct ena_ring *rx_ring, struct napi_struct *napi,
10821227
rx_ring->qid, ena_rx_ctx.descs, ena_rx_ctx.l3_proto,
10831228
ena_rx_ctx.l4_proto, ena_rx_ctx.hash);
10841229

1230+
if (ena_xdp_present_ring(rx_ring))
1231+
xdp_verdict = ena_xdp_handle_buff(rx_ring, &xdp);
1232+
10851233
/* allocate skb and fill it */
1086-
skb = ena_rx_skb(rx_ring, rx_ring->ena_bufs, ena_rx_ctx.descs,
1087-
&next_to_clean);
1234+
if (xdp_verdict == XDP_PASS)
1235+
skb = ena_rx_skb(rx_ring,
1236+
rx_ring->ena_bufs,
1237+
ena_rx_ctx.descs,
1238+
&next_to_clean);
10881239

1089-
/* exit if we failed to retrieve a buffer */
10901240
if (unlikely(!skb)) {
10911241
for (i = 0; i < ena_rx_ctx.descs; i++) {
10921242
rx_ring->free_ids[next_to_clean] =
@@ -1095,6 +1245,8 @@ static int ena_clean_rx_irq(struct ena_ring *rx_ring, struct napi_struct *napi,
10951245
ENA_RX_RING_IDX_NEXT(next_to_clean,
10961246
rx_ring->ring_size);
10971247
}
1248+
if (xdp_verdict == XDP_DROP)
1249+
continue;
10981250
break;
10991251
}
11001252

@@ -1727,12 +1879,34 @@ static int ena_create_io_rx_queue(struct ena_adapter *adapter, int qid)
17271879
netif_err(adapter, ifup, adapter->netdev,
17281880
"Failed to get RX queue handlers. RX queue num %d rc: %d\n",
17291881
qid, rc);
1730-
ena_com_destroy_io_queue(ena_dev, ena_qid);
1731-
return rc;
1882+
goto err;
17321883
}
17331884

17341885
ena_com_update_numa_node(rx_ring->ena_com_io_cq, ctx.numa_node);
17351886

1887+
rc = xdp_rxq_info_reg(&rx_ring->xdp_rxq, adapter->netdev, qid);
1888+
1889+
if (rc) {
1890+
netif_err(adapter, ifup, adapter->netdev,
1891+
"Failed to register xdp rx queue info. RX queue num %d rc: %d\n",
1892+
qid, rc);
1893+
goto err;
1894+
}
1895+
1896+
rc = xdp_rxq_info_reg_mem_model(&rx_ring->xdp_rxq, MEM_TYPE_PAGE_SHARED,
1897+
NULL);
1898+
1899+
if (rc) {
1900+
netif_err(adapter, ifup, adapter->netdev,
1901+
"Failed to register xdp rx queue info memory model. RX queue num %d rc: %d\n",
1902+
qid, rc);
1903+
xdp_rxq_info_unreg(&rx_ring->xdp_rxq);
1904+
goto err;
1905+
}
1906+
1907+
return rc;
1908+
err:
1909+
ena_com_destroy_io_queue(ena_dev, ena_qid);
17361910
return rc;
17371911
}
17381912

@@ -2056,11 +2230,27 @@ int ena_update_queue_sizes(struct ena_adapter *adapter,
20562230
int ena_update_queue_count(struct ena_adapter *adapter, u32 new_channel_count)
20572231
{
20582232
struct ena_com_dev *ena_dev = adapter->ena_dev;
2233+
int prev_channel_count;
20592234
bool dev_was_up;
20602235

20612236
dev_was_up = test_bit(ENA_FLAG_DEV_UP, &adapter->flags);
20622237
ena_close(adapter->netdev);
2238+
prev_channel_count = adapter->num_io_queues;
20632239
adapter->num_io_queues = new_channel_count;
2240+
2241+
if (ena_xdp_present(adapter) && ena_xdp_allowed(adapter)) {
2242+
if (prev_channel_count > new_channel_count)
2243+
ena_xdp_exchange_program_rx_in_range(adapter,
2244+
NULL,
2245+
new_channel_count,
2246+
prev_channel_count);
2247+
else
2248+
ena_xdp_exchange_program_rx_in_range(adapter,
2249+
adapter->xdp_bpf_prog,
2250+
prev_channel_count,
2251+
new_channel_count);
2252+
}
2253+
20642254
/* We need to destroy the rss table so that the indirection
20652255
* table will be reinitialized by ena_up()
20662256
*/
@@ -2568,6 +2758,7 @@ static const struct net_device_ops ena_netdev_ops = {
25682758
.ndo_change_mtu = ena_change_mtu,
25692759
.ndo_set_mac_address = NULL,
25702760
.ndo_validate_addr = eth_validate_addr,
2761+
.ndo_bpf = ena_xdp,
25712762
};
25722763

25732764
static int ena_device_validate_params(struct ena_adapter *adapter,

drivers/net/ethernet/amazon/ena/ena_netdev.h

+31
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include <linux/bitops.h>
3737
#include <linux/dim.h>
3838
#include <linux/etherdevice.h>
39+
#include <linux/if_vlan.h>
3940
#include <linux/inetdevice.h>
4041
#include <linux/interrupt.h>
4142
#include <linux/netdevice.h>
@@ -142,6 +143,15 @@
142143

143144
#define ENA_MMIO_DISABLE_REG_READ BIT(0)
144145

146+
/* The max MTU size is configured to be the ethernet frame size without
147+
* the overhead of the ethernet header, which can have a VLAN header, and
148+
* a frame check sequence (FCS).
149+
* The buffer size we share with the device is defined to be ENA_PAGE_SIZE
150+
*/
151+
152+
#define ENA_XDP_MAX_MTU (ENA_PAGE_SIZE - ETH_HLEN - ETH_FCS_LEN - \
153+
VLAN_HLEN - XDP_PACKET_HEADROOM)
154+
145155
struct ena_irq {
146156
irq_handler_t handler;
147157
void *data;
@@ -258,10 +268,13 @@ struct ena_ring {
258268
struct ena_adapter *adapter;
259269
struct ena_com_io_cq *ena_com_io_cq;
260270
struct ena_com_io_sq *ena_com_io_sq;
271+
struct bpf_prog *xdp_bpf_prog;
272+
struct xdp_rxq_info xdp_rxq;
261273

262274
u16 next_to_use;
263275
u16 next_to_clean;
264276
u16 rx_copybreak;
277+
u16 rx_headroom;
265278
u16 qid;
266279
u16 mtu;
267280
u16 sgl_size;
@@ -379,6 +392,8 @@ struct ena_adapter {
379392
u32 last_monitored_tx_qid;
380393

381394
enum ena_regs_reset_reason_types reset_reason;
395+
396+
struct bpf_prog *xdp_bpf_prog;
382397
};
383398

384399
void ena_set_ethtool_ops(struct net_device *netdev);
@@ -390,8 +405,24 @@ void ena_dump_stats_to_buf(struct ena_adapter *adapter, u8 *buf);
390405
int ena_update_queue_sizes(struct ena_adapter *adapter,
391406
u32 new_tx_size,
392407
u32 new_rx_size);
408+
393409
int ena_update_queue_count(struct ena_adapter *adapter, u32 new_channel_count);
394410

395411
int ena_get_sset_count(struct net_device *netdev, int sset);
396412

413+
static inline bool ena_xdp_present(struct ena_adapter *adapter)
414+
{
415+
return !!adapter->xdp_bpf_prog;
416+
}
417+
418+
static inline bool ena_xdp_present_ring(struct ena_ring *ring)
419+
{
420+
return !!ring->xdp_bpf_prog;
421+
}
422+
423+
static inline bool ena_xdp_allowed(struct ena_adapter *adapter)
424+
{
425+
return adapter->netdev->mtu <= ENA_XDP_MAX_MTU;
426+
}
427+
397428
#endif /* !(ENA_H) */

0 commit comments

Comments
 (0)