]> git.proxmox.com Git - mirror_ovs.git/commitdiff
userspace TSO: Include UDP checksum offload.
authorFlavio Leitner <fbl@sysclose.org>
Fri, 14 Feb 2020 13:03:35 +0000 (10:03 -0300)
committerIlya Maximets <i.maximets@ovn.org>
Wed, 26 Feb 2020 14:24:15 +0000 (15:24 +0100)
Virtio doesn't expose flags to control which protocols checksum
offload needs to be enabled or disabled. This patch checks if the
NIC supports UDP checksum offload and active it when TSO is enabled.

Reported-by: Ilya Maximets <i.maximets@ovn.org>
Fixes: 29cf9c1b3b9c ("userspace: Add TCP Segmentation Offload support")
Signed-off-by: Flavio Leitner <fbl@sysclose.org>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
lib/netdev-dpdk.c
lib/netdev-linux.c
lib/netdev-provider.h
lib/netdev.c

index 192c174f3f5f7acb75980c1fef24ced868f49961..ec8be64aa985e466b7983614a4cff27b1b55cad2 100644 (file)
@@ -152,6 +152,14 @@ 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. */
+#define DPDK_TX_TSO_OFFLOAD_FLAGS (DEV_TX_OFFLOAD_TCP_TSO        \
+                                   | DEV_TX_OFFLOAD_TCP_CKSUM    \
+                                   | DEV_TX_OFFLOAD_UDP_CKSUM    \
+                                   | DEV_TX_OFFLOAD_IPV4_CKSUM)
+
+
 static const struct rte_eth_conf port_conf = {
     .rxmode = {
         .mq_mode = ETH_MQ_RX_RSS,
@@ -997,9 +1005,7 @@ 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 |= DEV_TX_OFFLOAD_TCP_TSO;
-        conf.txmode.offloads |= DEV_TX_OFFLOAD_TCP_CKSUM;
-        conf.txmode.offloads |= DEV_TX_OFFLOAD_IPV4_CKSUM;
+        conf.txmode.offloads |= DPDK_TX_TSO_OFFLOAD_FLAGS;
     }
 
     /* Limit configured rss hash functions to only those supported
@@ -1100,12 +1106,10 @@ dpdk_eth_dev_init(struct netdev_dpdk *dev)
     struct rte_ether_addr eth_addr;
     int diag;
     int n_rxq, n_txq;
+    uint32_t tx_tso_offload_capa = DPDK_TX_TSO_OFFLOAD_FLAGS;
     uint32_t rx_chksm_offload_capa = DEV_RX_OFFLOAD_UDP_CKSUM |
                                      DEV_RX_OFFLOAD_TCP_CKSUM |
                                      DEV_RX_OFFLOAD_IPV4_CKSUM;
-    uint32_t tx_tso_offload_capa = DEV_TX_OFFLOAD_TCP_TSO |
-                                   DEV_TX_OFFLOAD_TCP_CKSUM |
-                                   DEV_TX_OFFLOAD_IPV4_CKSUM;
 
     rte_eth_dev_info_get(dev->port_id, &info);
 
@@ -5110,6 +5114,7 @@ netdev_dpdk_reconfigure(struct netdev *netdev)
     if (dev->hw_ol_features & NETDEV_TX_TSO_OFFLOAD) {
         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_IPV4_CKSUM;
     }
 
@@ -5252,6 +5257,7 @@ netdev_dpdk_vhost_client_reconfigure(struct netdev *netdev)
         if (userspace_tso_enabled()) {
             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_IPV4_CKSUM;
             vhost_unsup_flags = 1ULL << VIRTIO_NET_F_HOST_ECN
                                 | 1ULL << VIRTIO_NET_F_HOST_UFO;
index c6f3d27409b683b32f702ff40edec80348c04e5d..85f3a73674be4bf3d1d8b2216d4f4dd859bc2dde 100644 (file)
@@ -923,6 +923,7 @@ netdev_linux_common_construct(struct netdev *netdev_)
     if (userspace_tso_enabled()) {
         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_IPV4_CKSUM;
     }
 
index 22f4cde3337a81eb9fbc8a1bd06eed01caf26256..00677dc9dbcd62d638e3636d9381a24f6a9d9ba8 100644 (file)
@@ -40,7 +40,8 @@ struct netdev_tnl_build_header_params;
 enum netdev_ol_flags {
     NETDEV_TX_OFFLOAD_IPV4_CKSUM = 1 << 0,
     NETDEV_TX_OFFLOAD_TCP_CKSUM = 1 << 1,
-    NETDEV_TX_OFFLOAD_TCP_TSO = 1 << 2,
+    NETDEV_TX_OFFLOAD_UDP_CKSUM = 1 << 2,
+    NETDEV_TX_OFFLOAD_TCP_TSO = 1 << 3,
 };
 
 /* A network device (e.g. an Ethernet device).
index f95b19af4da0f3685cc2dec918653d633fb3c8b3..a55f77961a9485003a9e37785b0d3284f0d898ca 100644 (file)
@@ -791,6 +791,8 @@ static bool
 netdev_send_prepare_packet(const uint64_t netdev_flags,
                            struct dp_packet *packet, char **errormsg)
 {
+    uint64_t l4_mask;
+
     if (dp_packet_hwol_is_tso(packet)
         && !(netdev_flags & NETDEV_TX_OFFLOAD_TCP_TSO)) {
             /* Fall back to GSO in software. */
@@ -798,11 +800,25 @@ netdev_send_prepare_packet(const uint64_t netdev_flags,
             return false;
     }
 
-    if (dp_packet_hwol_l4_mask(packet)
-        && !(netdev_flags & NETDEV_TX_OFFLOAD_TCP_CKSUM)) {
-            /* Fall back to L4 csum in software. */
-            VLOG_ERR_BUF(errormsg, "No L4 checksum support");
+    l4_mask = dp_packet_hwol_l4_mask(packet);
+    if (l4_mask) {
+        if (dp_packet_hwol_l4_is_tcp(packet)) {
+            if (!(netdev_flags & NETDEV_TX_OFFLOAD_TCP_CKSUM)) {
+                /* Fall back to TCP csum in software. */
+                VLOG_ERR_BUF(errormsg, "No TCP checksum support");
+                return false;
+            }
+        } else if (dp_packet_hwol_l4_is_udp(packet)) {
+            if (!(netdev_flags & NETDEV_TX_OFFLOAD_UDP_CKSUM)) {
+                /* Fall back to UDP csum in software. */
+                VLOG_ERR_BUF(errormsg, "No UDP checksum support");
+                return false;
+            }
+        } else {
+            VLOG_ERR_BUF(errormsg, "No L4 checksum support: mask: %"PRIu64,
+                         l4_mask);
             return false;
+        }
     }
 
     return true;