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

Reply via email to