diff options
author | Camelia Groza <camelia.groza@nxp.com> | 2020-11-25 18:53:32 +0200 |
---|---|---|
committer | Jakub Kicinski <kuba@kernel.org> | 2020-11-30 17:33:18 -0800 |
commit | 828eadbaccc1b8090514d4b7ccc92b4876a0bd12 (patch) | |
tree | 471d3ed89eac6f80c118d769d669bad96773ea6e | |
parent | 86c0c196cbe48f844721783d9162e46bc35c0c5a (diff) | |
download | linux-828eadbaccc1b8090514d4b7ccc92b4876a0bd12.tar.bz2 |
dpaa_eth: limit the possible MTU range when XDP is enabled
Implement the ndo_change_mtu callback to prevent users from setting an
MTU that would permit processing of S/G frames. The maximum MTU size
is dependent on the buffer size.
Acked-by: Madalin Bucur <madalin.bucur@oss.nxp.com>
Signed-off-by: Camelia Groza <camelia.groza@nxp.com>
Reviewed-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rw-r--r-- | drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 39 |
1 files changed, 31 insertions, 8 deletions
diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c index 0e9bd805ec45..ac3f04c3698a 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c @@ -2756,22 +2756,44 @@ static int dpaa_eth_stop(struct net_device *net_dev) return err; } +static bool xdp_validate_mtu(struct dpaa_priv *priv, int mtu) +{ + int max_contig_data = priv->dpaa_bp->size - priv->rx_headroom; + + /* We do not support S/G fragments when XDP is enabled. + * Limit the MTU in relation to the buffer size. + */ + if (mtu + VLAN_ETH_HLEN + ETH_FCS_LEN > max_contig_data) { + dev_warn(priv->net_dev->dev.parent, + "The maximum MTU for XDP is %d\n", + max_contig_data - VLAN_ETH_HLEN - ETH_FCS_LEN); + return false; + } + + return true; +} + +static int dpaa_change_mtu(struct net_device *net_dev, int new_mtu) +{ + struct dpaa_priv *priv = netdev_priv(net_dev); + + if (priv->xdp_prog && !xdp_validate_mtu(priv, new_mtu)) + return -EINVAL; + + net_dev->mtu = new_mtu; + return 0; +} + static int dpaa_setup_xdp(struct net_device *net_dev, struct netdev_bpf *bpf) { struct dpaa_priv *priv = netdev_priv(net_dev); struct bpf_prog *old_prog; - int err, max_contig_data; + int err; bool up; - max_contig_data = priv->dpaa_bp->size - priv->rx_headroom; - /* S/G fragments are not supported in XDP-mode */ - if (bpf->prog && - (net_dev->mtu + VLAN_ETH_HLEN + ETH_FCS_LEN > max_contig_data)) { + if (bpf->prog && !xdp_validate_mtu(priv, net_dev->mtu)) { NL_SET_ERR_MSG_MOD(bpf->extack, "MTU too large for XDP"); - dev_warn(net_dev->dev.parent, - "The maximum MTU for XDP is %d\n", - max_contig_data - VLAN_ETH_HLEN - ETH_FCS_LEN); return -EINVAL; } @@ -2871,6 +2893,7 @@ static const struct net_device_ops dpaa_ops = { .ndo_set_rx_mode = dpaa_set_rx_mode, .ndo_do_ioctl = dpaa_ioctl, .ndo_setup_tc = dpaa_setup_tc, + .ndo_change_mtu = dpaa_change_mtu, .ndo_bpf = dpaa_xdp, }; |