[ovs-dev] [PATCH 3/3] userspace TSO: SCTP checksum offload optional.

Flavio Leitner fbl at sysclose.org
Fri Feb 14 13:03:36 UTC 2020


Ideally SCTP checksum offload needs be advertised by the
NIC when userspace TSO is enabled. However, very few drivers
do that and it's not a widely used protocol. So, this patch
enables SCTP checksum offload if available, otherwise userspace
TSO can still be enabled but SCTP packets will be dropped on
NICs without support.

Fixes: 29cf9c1b3b9c ("userspace: Add TCP Segmentation Offload support")
Signed-off-by: Flavio Leitner <fbl at sysclose.org>
---
 Documentation/topics/userspace-tso.rst |  7 +++++++
 lib/netdev-dpdk.c                      | 21 +++++++++++++++++++--
 lib/netdev-linux.c                     |  1 +
 lib/netdev-provider.h                  |  3 ++-
 lib/netdev.c                           |  6 ++++++
 5 files changed, 35 insertions(+), 3 deletions(-)

diff --git a/Documentation/topics/userspace-tso.rst b/Documentation/topics/userspace-tso.rst
index 9da5d7ef2..0fbac93a5 100644
--- a/Documentation/topics/userspace-tso.rst
+++ b/Documentation/topics/userspace-tso.rst
@@ -91,6 +91,13 @@ The current OvS userspace `TSO` implementation supports flat and VLAN networks
 only (i.e. no support for `TSO` over tunneled connection [VxLAN, GRE, IPinIP,
 etc.]).
 
+The NIC driver must support and advertise checksum offload for TCP and UDP.
+However, SCTP is not mandatory because very few drivers advertised support
+and it wasn't a widely used protocol at the moment this feature was introduced
+in Open vSwitch. Currently, if the NIC supports that, then the feature is
+enabled, otherwise TSO can still be enabled but SCTP packets sent to the NIC
+will be dropped.
+
 There is no software implementation of TSO, so all ports attached to the
 datapath must support TSO or packets using that feature will be dropped
 on ports without TSO support.  That also means guests using vhost-user
diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c
index ec8be64aa..7ab81864d 100644
--- a/lib/netdev-dpdk.c
+++ b/lib/netdev-dpdk.c
@@ -152,8 +152,10 @@ typedef uint16_t dpdk_port_t;
 
 #define IF_NAME_SZ (PATH_MAX > IFNAMSIZ ? PATH_MAX : IFNAMSIZ)
 
-/* List of required flags advertised by the hardware that will be
- * used if TSO is enabled. */
+/* List of required flags advertised by the hardware that will be used
+ * if TSO is enabled. Ideally this should include DEV_TX_OFFLOAD_SCTP_CKSUM.
+ * However, very few drivers supports that the moment and SCTP is not a
+ * widely used protocol as TCP and UDP, so it's optional. */
 #define DPDK_TX_TSO_OFFLOAD_FLAGS (DEV_TX_OFFLOAD_TCP_TSO        \
                                    | DEV_TX_OFFLOAD_TCP_CKSUM    \
                                    | DEV_TX_OFFLOAD_UDP_CKSUM    \
@@ -423,6 +425,7 @@ enum dpdk_hw_ol_features {
     NETDEV_RX_HW_CRC_STRIP = 1 << 1,
     NETDEV_RX_HW_SCATTER = 1 << 2,
     NETDEV_TX_TSO_OFFLOAD = 1 << 3,
+    NETDEV_TX_SCTP_CHECKSUM_OFFLOAD = 1 << 4,
 };
 
 /*
@@ -1006,6 +1009,9 @@ dpdk_eth_dev_port_config(struct netdev_dpdk *dev, int n_rxq, int n_txq)
 
     if (dev->hw_ol_features & NETDEV_TX_TSO_OFFLOAD) {
         conf.txmode.offloads |= DPDK_TX_TSO_OFFLOAD_FLAGS;
+        if (dev->hw_ol_features & NETDEV_TX_SCTP_CHECKSUM_OFFLOAD) {
+            conf.txmode.offloads |= DEV_TX_OFFLOAD_SCTP_CKSUM;
+        }
     }
 
     /* Limit configured rss hash functions to only those supported
@@ -1141,6 +1147,13 @@ dpdk_eth_dev_init(struct netdev_dpdk *dev)
         if ((info.tx_offload_capa & tx_tso_offload_capa)
             == tx_tso_offload_capa) {
             dev->hw_ol_features |= NETDEV_TX_TSO_OFFLOAD;
+            if (info.tx_offload_capa & DEV_TX_OFFLOAD_SCTP_CKSUM) {
+                dev->hw_ol_features |= NETDEV_TX_SCTP_CHECKSUM_OFFLOAD;
+            } else {
+                VLOG_WARN("%s: Tx SCTP checksum offload is not supported, "
+                          "SCTP packets sent to this device will be dropped",
+                          netdev_get_name(&dev->up));
+            }
         } else {
             VLOG_WARN("%s: Tx TSO offload is not supported.",
                       netdev_get_name(&dev->up));
@@ -5116,6 +5129,9 @@ netdev_dpdk_reconfigure(struct netdev *netdev)
         netdev->ol_flags |= NETDEV_TX_OFFLOAD_TCP_CKSUM;
         netdev->ol_flags |= NETDEV_TX_OFFLOAD_UDP_CKSUM;
         netdev->ol_flags |= NETDEV_TX_OFFLOAD_IPV4_CKSUM;
+        if (dev->hw_ol_features & NETDEV_TX_SCTP_CHECKSUM_OFFLOAD) {
+            netdev->ol_flags |= NETDEV_TX_OFFLOAD_SCTP_CKSUM;
+        }
     }
 
     dev->tx_q = netdev_dpdk_alloc_txq(netdev->n_txq);
@@ -5258,6 +5274,7 @@ netdev_dpdk_vhost_client_reconfigure(struct netdev *netdev)
             netdev->ol_flags |= NETDEV_TX_OFFLOAD_TCP_TSO;
             netdev->ol_flags |= NETDEV_TX_OFFLOAD_TCP_CKSUM;
             netdev->ol_flags |= NETDEV_TX_OFFLOAD_UDP_CKSUM;
+            netdev->ol_flags |= NETDEV_TX_OFFLOAD_SCTP_CKSUM;
             netdev->ol_flags |= NETDEV_TX_OFFLOAD_IPV4_CKSUM;
             vhost_unsup_flags = 1ULL << VIRTIO_NET_F_HOST_ECN
                                 | 1ULL << VIRTIO_NET_F_HOST_UFO;
diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c
index 85f3a7367..432645601 100644
--- a/lib/netdev-linux.c
+++ b/lib/netdev-linux.c
@@ -924,6 +924,7 @@ netdev_linux_common_construct(struct netdev *netdev_)
         netdev_->ol_flags |= NETDEV_TX_OFFLOAD_TCP_TSO;
         netdev_->ol_flags |= NETDEV_TX_OFFLOAD_TCP_CKSUM;
         netdev_->ol_flags |= NETDEV_TX_OFFLOAD_UDP_CKSUM;
+        netdev_->ol_flags |= NETDEV_TX_OFFLOAD_SCTP_CKSUM;
         netdev_->ol_flags |= NETDEV_TX_OFFLOAD_IPV4_CKSUM;
     }
 
diff --git a/lib/netdev-provider.h b/lib/netdev-provider.h
index 00677dc9d..6f509424b 100644
--- a/lib/netdev-provider.h
+++ b/lib/netdev-provider.h
@@ -41,7 +41,8 @@ enum netdev_ol_flags {
     NETDEV_TX_OFFLOAD_IPV4_CKSUM = 1 << 0,
     NETDEV_TX_OFFLOAD_TCP_CKSUM = 1 << 1,
     NETDEV_TX_OFFLOAD_UDP_CKSUM = 1 << 2,
-    NETDEV_TX_OFFLOAD_TCP_TSO = 1 << 3,
+    NETDEV_TX_OFFLOAD_SCTP_CKSUM = 1 << 3,
+    NETDEV_TX_OFFLOAD_TCP_TSO = 1 << 4,
 };
 
 /* A network device (e.g. an Ethernet device).
diff --git a/lib/netdev.c b/lib/netdev.c
index a55f77961..8c44eee8e 100644
--- a/lib/netdev.c
+++ b/lib/netdev.c
@@ -814,6 +814,12 @@ netdev_send_prepare_packet(const uint64_t netdev_flags,
                 VLOG_ERR_BUF(errormsg, "No UDP checksum support");
                 return false;
             }
+        } else if (dp_packet_hwol_l4_is_sctp(packet)) {
+            if (!(netdev_flags & NETDEV_TX_OFFLOAD_SCTP_CKSUM)) {
+                /* Fall back to SCTP csum in software. */
+                VLOG_ERR_BUF(errormsg, "No SCTP checksum support");
+                return false;
+            }
         } else {
             VLOG_ERR_BUF(errormsg, "No L4 checksum support: mask: %"PRIu64,
                          l4_mask);
-- 
2.24.1



More information about the dev mailing list