Drivers natively supporting AF_XDP will check that a configured MTU size will not exceed the allowed size for AF_XDP. However, when the skb compatibility mode is used there is no check and any value is accepted. This, for example, is the case when using the TAP interface.
This fix adds a check to make sure only AF_XDP valid values are excepted. Signed-off-by: Eelco Chaudron <echau...@redhat.com> --- v1 -> v2: Included (subtracted) ethernet and vlan header from the MTU size to match kernel/driver MTU behavior. Use netdev class compare rather than based on name string lib/netdev-afxdp.c | 17 +++++++++++++++++ lib/netdev-afxdp.h | 1 + lib/netdev-linux.c | 9 +++++++++ 3 files changed, 27 insertions(+) diff --git a/lib/netdev-afxdp.c b/lib/netdev-afxdp.c index af654d498..86422955c 100644 --- a/lib/netdev-afxdp.c +++ b/lib/netdev-afxdp.c @@ -1084,6 +1084,23 @@ netdev_afxdp_destruct(struct netdev *netdev) ovs_mutex_destroy(&dev->mutex); } +int +netdev_afxdp_verify_mtu_size(const struct netdev *netdev OVS_UNUSED, int mtu) +{ + /* + * If a device is used in xdpmode skb, no driver-specific MTU size is + * checked and any value is allowed resulting in packet drops. + * This check will verify the maximum supported value based on the + * buffer size allocated and the additional headroom required. + */ + if (mtu > (FRAME_SIZE - OVS_XDP_HEADROOM - + XDP_PACKET_HEADROOM - VLAN_ETH_HEADER_LEN)) { + return EINVAL; + } + + return 0; +} + int netdev_afxdp_get_custom_stats(const struct netdev *netdev, struct netdev_custom_stats *custom_stats) diff --git a/lib/netdev-afxdp.h b/lib/netdev-afxdp.h index e2f400b72..ee6939fce 100644 --- a/lib/netdev-afxdp.h +++ b/lib/netdev-afxdp.h @@ -39,6 +39,7 @@ int netdev_afxdp_rxq_construct(struct netdev_rxq *rxq_); void netdev_afxdp_rxq_destruct(struct netdev_rxq *rxq_); int netdev_afxdp_construct(struct netdev *netdev_); void netdev_afxdp_destruct(struct netdev *netdev_); +int netdev_afxdp_verify_mtu_size(const struct netdev *netdev, int mtu); int netdev_afxdp_rxq_recv(struct netdev_rxq *rxq_, struct dp_packet_batch *batch, diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c index f48192373..0a32cf9bc 100644 --- a/lib/netdev-linux.c +++ b/lib/netdev-linux.c @@ -1593,6 +1593,15 @@ netdev_linux_set_mtu(struct netdev *netdev_, int mtu) goto exit; } +#ifdef HAVE_AF_XDP + if (netdev_get_class(netdev_) == &netdev_afxdp_class) { + error = netdev_afxdp_verify_mtu_size(netdev_, mtu); + if (error) { + goto exit; + } + } +#endif + if (netdev->cache_valid & VALID_MTU) { error = netdev->netdev_mtu_error; if (error || netdev->mtu == mtu) { _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev