Following support of L3 and L4 checksum offloading, some bugs have been
raised in different DPDK drivers.
When faced with such bugs, a OVS user can't do anything but wait for a
DPDK fix (which can take some time to make it to the LTS releases).

Make it possible for the user to disable some Tx offloads.

Link: 
https://patchwork.dpdk.org/project/dpdk/patch/20230818090351.2402519-1-david.march...@redhat.com/
Link: 
https://patchwork.dpdk.org/project/dpdk/patch/20230822073244.3751885-1-david.march...@redhat.com/
Signed-off-by: David Marchand <david.march...@redhat.com>
---
 lib/netdev-provider.h |  5 ++-
 lib/netdev.c          | 72 +++++++++++++++++++++++++++++++++++++------
 tests/dpif-netdev.at  | 10 ++++++
 3 files changed, 76 insertions(+), 11 deletions(-)

diff --git a/lib/netdev-provider.h b/lib/netdev-provider.h
index a7393c7cec..32a760d826 100644
--- a/lib/netdev-provider.h
+++ b/lib/netdev-provider.h
@@ -59,9 +59,12 @@ struct netdev {
      * opening this device, and therefore got assigned to the "system" class */
     bool auto_classified;
 
-    /* This bitmask of the offloading features enabled by the netdev. */
+    /* Bitmask of the offloading features supported by the netdev. */
     uint64_t ol_flags;
 
+    /* Bitmask of the offloading features disabled by the user. */
+    uint64_t disabled_ol_flags;
+
     /* If this is 'true', the user explicitly specified an MTU for this
      * netdev.  Otherwise, Open vSwitch is allowed to override it. */
     bool mtu_user_config;
diff --git a/lib/netdev.c b/lib/netdev.c
index e5ac7713d2..e86dc82301 100644
--- a/lib/netdev.c
+++ b/lib/netdev.c
@@ -490,6 +490,59 @@ netdev_ref(const struct netdev *netdev_)
     return netdev;
 }
 
+#define NETDEV_OL_FLAGS \
+    NETDEV_OL_FLAG("ip_csum", NETDEV_TX_OFFLOAD_IPV4_CKSUM); \
+    NETDEV_OL_FLAG("tcp_csum", NETDEV_TX_OFFLOAD_TCP_CKSUM); \
+    NETDEV_OL_FLAG("udp_csum", NETDEV_TX_OFFLOAD_UDP_CKSUM); \
+    NETDEV_OL_FLAG("sctp_csum", NETDEV_TX_OFFLOAD_SCTP_CKSUM); \
+    NETDEV_OL_FLAG("tcp_seg", NETDEV_TX_OFFLOAD_TCP_TSO);
+
+static int
+netdev_parse_disabled_ol_flags(struct netdev *netdev, const struct smap *args)
+{
+    const char *ol_flags = NULL;
+    int err = 0;
+
+    netdev->disabled_ol_flags = 0;
+
+    if (args) {
+        ol_flags = smap_get(args, "disabled_ol_flags");
+    }
+    if (ol_flags && ol_flags[0] != '\0') {
+        char *list = xstrdup(ol_flags);
+        char *ptr = list;
+
+        while (ptr) {
+            char *end = strchr(ptr, ',');
+            bool known_ol_flag = false;
+
+            if (end) {
+                end[0] = '\0';
+            }
+#define NETDEV_OL_FLAG(name, bit) \
+            if (!strcmp(ptr, name)) { \
+                netdev->disabled_ol_flags |= bit; \
+                VLOG_DBG("Disabling %s on %s", name, \
+                         netdev_get_name(netdev)); \
+                known_ol_flag = true; \
+            }
+            NETDEV_OL_FLAGS
+#undef NETDEV_OL_FLAG
+            if (!known_ol_flag) {
+                VLOG_WARN("unknown offload type '%s'", ptr);
+            }
+            if (end) {
+                ptr = end + 1;
+            } else {
+                ptr = NULL;
+            }
+        }
+        free(list);
+    }
+
+    return err;
+}
+
 /* Reconfigures the device 'netdev' with 'args'.  'args' may be empty
  * or NULL if none are needed. */
 int
@@ -501,6 +554,7 @@ netdev_set_config(struct netdev *netdev, const struct smap 
*args, char **errp)
         char *verbose_error = NULL;
         int error;
 
+        netdev_parse_disabled_ol_flags(netdev, args);
         error = netdev->netdev_class->set_config(netdev,
                                                  args ? args : &no_args,
                                                  &verbose_error);
@@ -834,9 +888,10 @@ netdev_send_prepare_batch(const struct netdev *netdev,
     size_t i, size = dp_packet_batch_size(batch);
 
     DP_PACKET_BATCH_REFILL_FOR_EACH (i, size, packet, batch) {
+        uint64_t ol_flags = netdev->ol_flags & ~netdev->disabled_ol_flags;
         char *errormsg = NULL;
 
-        if (netdev_send_prepare_packet(netdev->ol_flags, packet, &errormsg)) {
+        if (netdev_send_prepare_packet(ol_flags, packet, &errormsg)) {
             dp_packet_batch_refill(batch, packet, i);
         } else {
             dp_packet_delete(packet);
@@ -1400,16 +1455,13 @@ netdev_get_status(const struct netdev *netdev, struct 
smap *smap)
     if (netdev_get_dpif_type(netdev) &&
         strcmp(netdev_get_dpif_type(netdev), "system")) {
 
-#define OL_ADD_STAT(name, bit) \
+#define NETDEV_OL_FLAG(name, bit) \
         smap_add(smap, "tx_" name "_offload", \
-                 netdev->ol_flags & bit ? "true" : "false");
-
-        OL_ADD_STAT("ip_csum", NETDEV_TX_OFFLOAD_IPV4_CKSUM);
-        OL_ADD_STAT("tcp_csum", NETDEV_TX_OFFLOAD_TCP_CKSUM);
-        OL_ADD_STAT("udp_csum", NETDEV_TX_OFFLOAD_UDP_CKSUM);
-        OL_ADD_STAT("sctp_csum", NETDEV_TX_OFFLOAD_SCTP_CKSUM);
-        OL_ADD_STAT("tcp_seg", NETDEV_TX_OFFLOAD_TCP_TSO);
-#undef OL_ADD_STAT
+                 netdev->ol_flags & bit \
+                 ?  (netdev->disabled_ol_flags & bit ? "disabled" : "true") \
+                 : "false");
+        NETDEV_OL_FLAGS
+#undef NETDEV_OL_FLAG
 
         err = 0;
     }
diff --git a/tests/dpif-netdev.at b/tests/dpif-netdev.at
index 85119fb819..922badd90c 100644
--- a/tests/dpif-netdev.at
+++ b/tests/dpif-netdev.at
@@ -665,6 +665,16 @@ AT_CHECK([ovs-vsctl get interface br0 status | sed -n 
's/^{\(.*\).*}$/\1/p'], [0
 tx_ip_csum_offload="false", tx_sctp_csum_offload="false", 
tx_tcp_csum_offload="false", tx_tcp_seg_offload="false", 
tx_udp_csum_offload="false"
 ], [])
 
+AT_CHECK([ovs-vsctl set Interface p1 options:ol_ip_csum=true])
+AT_CHECK([ovs-vsctl get interface p1 status | sed -n 's/^{\(.*\).*}$/\1/p'], 
[0], [dnl
+tx_ip_csum_offload="true", tx_sctp_csum_offload="false", 
tx_tcp_csum_offload="false", tx_tcp_seg_offload="false", 
tx_udp_csum_offload="false"
+], [])
+
+AT_CHECK([ovs-vsctl set Interface p1 options:disabled_ol_flags="ip_csum"])
+AT_CHECK([ovs-vsctl get interface p1 status | sed -n 's/^{\(.*\).*}$/\1/p'], 
[0], [dnl
+tx_ip_csum_offload=disabled, tx_sctp_csum_offload="false", 
tx_tcp_csum_offload="false", tx_tcp_seg_offload="false", 
tx_udp_csum_offload="false"
+], [])
+
 OVS_VSWITCHD_STOP
 AT_CLEANUP
 
-- 
2.41.0

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to