Skip to content

Commit e45a4fe

Browse files
cmclachl-xilinxdavem330
authored andcommitted
sfc: Enable setting of xdp_prog
Provide an ndo_bpf function to efx_netdev_ops that allows setting and querying of xdp programs on an interface. Also check that the MTU size isn't too big when setting a program or when the MTU is explicitly set. Signed-off-by: Charles McLachlan <[email protected]> Acked-by: Jesper Dangaard Brouer <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent eb9a36b commit e45a4fe

File tree

1 file changed

+70
-0
lines changed
  • drivers/net/ethernet/sfc

1 file changed

+70
-0
lines changed

drivers/net/ethernet/sfc/efx.c

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,8 @@ static void efx_fini_napi_channel(struct efx_channel *channel);
226226
static void efx_fini_struct(struct efx_nic *efx);
227227
static void efx_start_all(struct efx_nic *efx);
228228
static void efx_stop_all(struct efx_nic *efx);
229+
static int efx_xdp_setup_prog(struct efx_nic *efx, struct bpf_prog *prog);
230+
static int efx_xdp(struct net_device *dev, struct netdev_bpf *xdp);
229231

230232
#define EFX_ASSERT_RESET_SERIALISED(efx) \
231233
do { \
@@ -2025,6 +2027,10 @@ static void efx_stop_all(struct efx_nic *efx)
20252027

20262028
static void efx_remove_all(struct efx_nic *efx)
20272029
{
2030+
rtnl_lock();
2031+
efx_xdp_setup_prog(efx, NULL);
2032+
rtnl_unlock();
2033+
20282034
efx_remove_channels(efx);
20292035
efx_remove_filters(efx);
20302036
#ifdef CONFIG_SFC_SRIOV
@@ -2280,6 +2286,17 @@ static void efx_watchdog(struct net_device *net_dev)
22802286
efx_schedule_reset(efx, RESET_TYPE_TX_WATCHDOG);
22812287
}
22822288

2289+
static unsigned int efx_xdp_max_mtu(struct efx_nic *efx)
2290+
{
2291+
/* The maximum MTU that we can fit in a single page, allowing for
2292+
* framing, overhead and XDP headroom.
2293+
*/
2294+
int overhead = EFX_MAX_FRAME_LEN(0) + sizeof(struct efx_rx_page_state) +
2295+
efx->rx_prefix_size + efx->type->rx_buffer_padding +
2296+
efx->rx_ip_align + XDP_PACKET_HEADROOM;
2297+
2298+
return PAGE_SIZE - overhead;
2299+
}
22832300

22842301
/* Context: process, rtnl_lock() held. */
22852302
static int efx_change_mtu(struct net_device *net_dev, int new_mtu)
@@ -2291,6 +2308,14 @@ static int efx_change_mtu(struct net_device *net_dev, int new_mtu)
22912308
if (rc)
22922309
return rc;
22932310

2311+
if (rtnl_dereference(efx->xdp_prog) &&
2312+
new_mtu > efx_xdp_max_mtu(efx)) {
2313+
netif_err(efx, drv, efx->net_dev,
2314+
"Requested MTU of %d too big for XDP (max: %d)\n",
2315+
new_mtu, efx_xdp_max_mtu(efx));
2316+
return -EINVAL;
2317+
}
2318+
22942319
netif_dbg(efx, drv, efx->net_dev, "changing MTU to %d\n", new_mtu);
22952320

22962321
efx_device_detach_sync(efx);
@@ -2492,8 +2517,53 @@ static const struct net_device_ops efx_netdev_ops = {
24922517
#endif
24932518
.ndo_udp_tunnel_add = efx_udp_tunnel_add,
24942519
.ndo_udp_tunnel_del = efx_udp_tunnel_del,
2520+
.ndo_bpf = efx_xdp
24952521
};
24962522

2523+
static int efx_xdp_setup_prog(struct efx_nic *efx, struct bpf_prog *prog)
2524+
{
2525+
struct bpf_prog *old_prog;
2526+
2527+
if (efx->xdp_rxq_info_failed) {
2528+
netif_err(efx, drv, efx->net_dev,
2529+
"Unable to bind XDP program due to previous failure of rxq_info\n");
2530+
return -EINVAL;
2531+
}
2532+
2533+
if (prog && efx->net_dev->mtu > efx_xdp_max_mtu(efx)) {
2534+
netif_err(efx, drv, efx->net_dev,
2535+
"Unable to configure XDP with MTU of %d (max: %d)\n",
2536+
efx->net_dev->mtu, efx_xdp_max_mtu(efx));
2537+
return -EINVAL;
2538+
}
2539+
2540+
old_prog = rtnl_dereference(efx->xdp_prog);
2541+
rcu_assign_pointer(efx->xdp_prog, prog);
2542+
/* Release the reference that was originally passed by the caller. */
2543+
if (old_prog)
2544+
bpf_prog_put(old_prog);
2545+
2546+
return 0;
2547+
}
2548+
2549+
/* Context: process, rtnl_lock() held. */
2550+
static int efx_xdp(struct net_device *dev, struct netdev_bpf *xdp)
2551+
{
2552+
struct efx_nic *efx = netdev_priv(dev);
2553+
struct bpf_prog *xdp_prog;
2554+
2555+
switch (xdp->command) {
2556+
case XDP_SETUP_PROG:
2557+
return efx_xdp_setup_prog(efx, xdp->prog);
2558+
case XDP_QUERY_PROG:
2559+
xdp_prog = rtnl_dereference(efx->xdp_prog);
2560+
xdp->prog_id = xdp_prog ? xdp_prog->aux->id : 0;
2561+
return 0;
2562+
default:
2563+
return -EINVAL;
2564+
}
2565+
}
2566+
24972567
static void efx_update_name(struct efx_nic *efx)
24982568
{
24992569
strcpy(efx->name, efx->net_dev->name);

0 commit comments

Comments
 (0)