Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ae6b0710 authored by Maxim Mikityanskiy's avatar Maxim Mikityanskiy Committed by Greg Kroah-Hartman
Browse files

net/mlx5e: Fix the max MTU check in case of XDP



[ Upstream commit d460c2718906252a2a69bc6f89b537071f792e6e ]

MLX5E_XDP_MAX_MTU was calculated incorrectly. It didn't account for
NET_IP_ALIGN and MLX5E_HW2SW_MTU, and it also misused MLX5_SKB_FRAG_SZ.
This commit fixes the calculations and adds a brief explanation for the
formula used.

Fixes: a26a5bdf ("net/mlx5e: Restrict the combination of large MTU and XDP")
Signed-off-by: default avatarMaxim Mikityanskiy <maximmi@mellanox.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@mellanox.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent b08774d3
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -33,6 +33,26 @@
#include <linux/bpf_trace.h>
#include "en/xdp.h"

int mlx5e_xdp_max_mtu(struct mlx5e_params *params)
{
	int hr = NET_IP_ALIGN + XDP_PACKET_HEADROOM;

	/* Let S := SKB_DATA_ALIGN(sizeof(struct skb_shared_info)).
	 * The condition checked in mlx5e_rx_is_linear_skb is:
	 *   SKB_DATA_ALIGN(sw_mtu + hard_mtu + hr) + S <= PAGE_SIZE         (1)
	 *   (Note that hw_mtu == sw_mtu + hard_mtu.)
	 * What is returned from this function is:
	 *   max_mtu = PAGE_SIZE - S - hr - hard_mtu                         (2)
	 * After assigning sw_mtu := max_mtu, the left side of (1) turns to
	 * SKB_DATA_ALIGN(PAGE_SIZE - S) + S, which is equal to PAGE_SIZE,
	 * because both PAGE_SIZE and S are already aligned. Any number greater
	 * than max_mtu would make the left side of (1) greater than PAGE_SIZE,
	 * so max_mtu is the maximum MTU allowed.
	 */

	return MLX5E_HW2SW_MTU(params, SKB_MAX_HEAD(hr));
}

static inline bool
mlx5e_xmit_xdp_buff(struct mlx5e_xdpsq *sq, struct mlx5e_dma_info *di,
		    struct xdp_buff *xdp)
+1 −2
Original line number Diff line number Diff line
@@ -34,12 +34,11 @@

#include "en.h"

#define MLX5E_XDP_MAX_MTU ((int)(PAGE_SIZE - \
				 MLX5_SKB_FRAG_SZ(XDP_PACKET_HEADROOM)))
#define MLX5E_XDP_MIN_INLINE (ETH_HLEN + VLAN_HLEN)
#define MLX5E_XDP_TX_DS_COUNT \
	((sizeof(struct mlx5e_tx_wqe) / MLX5_SEND_WQE_DS) + 1 /* SG DS */)

int mlx5e_xdp_max_mtu(struct mlx5e_params *params);
bool mlx5e_xdp_handle(struct mlx5e_rq *rq, struct mlx5e_dma_info *di,
		      void *va, u16 *rx_headroom, u32 *len);
bool mlx5e_poll_xdpsq_cq(struct mlx5e_cq *cq);
+3 −2
Original line number Diff line number Diff line
@@ -3761,7 +3761,7 @@ int mlx5e_change_mtu(struct net_device *netdev, int new_mtu,
	if (params->xdp_prog &&
	    !mlx5e_rx_is_linear_skb(priv->mdev, &new_channels.params)) {
		netdev_err(netdev, "MTU(%d) > %d is not allowed while XDP enabled\n",
			   new_mtu, MLX5E_XDP_MAX_MTU);
			   new_mtu, mlx5e_xdp_max_mtu(params));
		err = -EINVAL;
		goto out;
	}
@@ -4227,7 +4227,8 @@ static int mlx5e_xdp_allowed(struct mlx5e_priv *priv, struct bpf_prog *prog)

	if (!mlx5e_rx_is_linear_skb(priv->mdev, &new_channels.params)) {
		netdev_warn(netdev, "XDP is not allowed with MTU(%d) > %d\n",
			    new_channels.params.sw_mtu, MLX5E_XDP_MAX_MTU);
			    new_channels.params.sw_mtu,
			    mlx5e_xdp_max_mtu(&new_channels.params));
		return -EINVAL;
	}