Instead of dropping we can switch to software segmentation before
encapsulating packets already encapsulated in a tunnel.

Signed-off-by: David Marchand <[email protected]>
---
 lib/netdev.c         | 56 +++++++++++++++++-----------------
 tests/dpif-netdev.at | 71 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 100 insertions(+), 27 deletions(-)

diff --git a/lib/netdev.c b/lib/netdev.c
index 1288ae7871..7cdab1e47d 100644
--- a/lib/netdev.c
+++ b/lib/netdev.c
@@ -964,43 +964,45 @@ netdev_push_header(const struct netdev *netdev,
                    struct dp_packet_batch *batch,
                    const struct ovs_action_push_tnl *data)
 {
+    bool supported_offloads = (data->tnl_type == OVS_VPORT_TYPE_GENEVE)
+                              || (data->tnl_type == OVS_VPORT_TYPE_VXLAN)
+                              || (data->tnl_type == OVS_VPORT_TYPE_GRE)
+                              || (data->tnl_type == OVS_VPORT_TYPE_IP6GRE);
     struct dp_packet *packet;
-    size_t i, size = dp_packet_batch_size(batch);
 
-    DP_PACKET_BATCH_REFILL_FOR_EACH (i, size, packet, batch) {
-        if (OVS_UNLIKELY(data->tnl_type != OVS_VPORT_TYPE_GENEVE &&
-                         data->tnl_type != OVS_VPORT_TYPE_VXLAN &&
-                         data->tnl_type != OVS_VPORT_TYPE_GRE &&
-                         data->tnl_type != OVS_VPORT_TYPE_IP6GRE &&
-                         dp_packet_get_tso_segsz(packet))) {
-            COVERAGE_INC(netdev_push_header_drops);
-            dp_packet_delete(packet);
-            VLOG_WARN_RL(&rl, "%s: Tunneling packets with TSO is not "
-                              "supported for %s tunnels: packet dropped",
-                         netdev_get_name(netdev), netdev_get_type(netdev));
-        } else {
-            if (data->tnl_type != OVS_VPORT_TYPE_GENEVE &&
-                data->tnl_type != OVS_VPORT_TYPE_VXLAN &&
-                data->tnl_type != OVS_VPORT_TYPE_GRE &&
-                data->tnl_type != OVS_VPORT_TYPE_IP6GRE) {
-                dp_packet_ol_send_prepare(packet, 0);
-            } else if (dp_packet_tunnel(packet)) {
-                if (dp_packet_get_tso_segsz(packet)) {
+    if (userspace_tso_enabled()) {
+        if (OVS_UNLIKELY(!supported_offloads)) {
+            size_t i, size = dp_packet_batch_size(batch);
+
+            DP_PACKET_BATCH_REFILL_FOR_EACH (i, size, packet, batch) {
+                if (OVS_UNLIKELY(dp_packet_get_tso_segsz(packet))) {
                     COVERAGE_INC(netdev_push_header_drops);
                     dp_packet_delete(packet);
                     VLOG_WARN_RL(&rl, "%s: Tunneling packets with TSO is not "
-                                      "supported with multiple levels of "
-                                      "VXLAN, GENEVE, or GRE encapsulation.",
-                                 netdev_get_name(netdev));
+                                 "supported for %s tunnels: packet dropped",
+                                 netdev_get_name(netdev),
+                                 netdev_get_type(netdev));
                     continue;
                 }
-                dp_packet_ol_send_prepare(packet, 0);
+                dp_packet_batch_add(batch, packet);
             }
-            netdev->netdev_class->push_header(netdev, packet, data);
+        } else {
+            DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
+                if (dp_packet_tunnel(packet)
+                    && dp_packet_get_tso_segsz(packet)) {
+                    dp_packet_gso_batch(batch);
+                    break;
+                }
+            }
+        }
+    }
 
-            pkt_metadata_init(&packet->md, data->out_port);
-            dp_packet_batch_add(batch, packet);
+    DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
+        if (!supported_offloads || dp_packet_tunnel(packet)) {
+            dp_packet_ol_send_prepare(packet, 0);
         }
+        netdev->netdev_class->push_header(netdev, packet, data);
+        pkt_metadata_init(&packet->md, data->out_port);
     }
 
     return 0;
diff --git a/tests/dpif-netdev.at b/tests/dpif-netdev.at
index b4eb64ffd0..4adef9428f 100644
--- a/tests/dpif-netdev.at
+++ b/tests/dpif-netdev.at
@@ -3436,6 +3436,77 @@ AT_CHECK([ovs-vsctl get interface p2 
statistics:tx_packets], [0], [35
 OVS_VSWITCHD_STOP
 AT_CLEANUP
 
+AT_SETUP([dpif-netdev - tso + dual tunnel encap])
+AT_KEYWORDS([userspace offload])
+OVS_VSWITCHD_START(
+  [set Open_vSwitch . other_config:userspace-tso-enable=true -- \
+   add-br br1 -- set bridge br1 datapath-type=dummy -- \
+   add-port br1 p1 -- \
+       set Interface p1 type=dummy -- \
+   add-br br2 -- set bridge br2 datapath-type=dummy -- \
+       set bridge br2 other-config:hwaddr=aa:66:aa:66:00:00 -- \
+   add-port br2 p2 -- \
+       set Interface p2 type=dummy -- \
+   add-br br3 -- set bridge br3 datapath-type=dummy -- \
+       set bridge br3 other-config:hwaddr=aa:66:bb:66:00:00 -- \
+   add-port br3 p3 -- \
+       set Interface p3 type=dummy])
+
+AT_CHECK([ovs-vsctl add-port br1 t1 \
+                    -- set Interface t1 type=vxlan \
+                       options:remote_ip=1.1.2.92 options:key=123 \
+                       ofport_request=11], [0])
+AT_CHECK([ovs-vsctl add-port br2 t2 \
+                    -- set Interface t2 type=vxlan \
+                       options:remote_ip=1.1.3.92 options:key=456 \
+                       ofport_request=21], [0])
+
+AT_CHECK([ovs-ofctl del-flows br1])
+AT_CHECK([ovs-ofctl add-flow br1 in_port=p1,actions=output:11])
+AT_CHECK([ovs-ofctl del-flows br2])
+AT_CHECK([ovs-ofctl add-flow br2 in_port=br2,actions=output:21])
+
+AT_CHECK([ovs-appctl netdev-dummy/ip4addr br2 1.1.2.88/24], [0], [OK
+])
+AT_CHECK([ovs-appctl tnl/neigh/set br2 1.1.2.92 aa:66:aa:66:00:01], [0], [OK
+])
+AT_CHECK([ovs-appctl netdev-dummy/ip4addr br3 1.1.3.88/24], [0], [OK
+])
+AT_CHECK([ovs-appctl tnl/neigh/set br3 1.1.3.92 aa:66:bb:66:00:01], [0], [OK
+])
+
+AT_CHECK([ovs-vsctl set Interface p1 options:ol_tso_segsz=1000])
+
+flow_s="in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:01:00),eth_type(0x0800),
 \
+        ipv4(src=10.0.1.1,dst=10.0.0.1,proto=6,tos=0,ttl=64,frag=no), \
+        tcp(src=1234,dst=80),tcp_flags(ack)"
+AT_CHECK([ovs-appctl netdev-dummy/receive p1 "${flow_s}" --len 2000])
+
+dnl Interface statistics and coverage counters take some time to refresh.
+OVS_WAIT_UNTIL([test `ovs-vsctl get interface p1 statistics:rx_packets` -eq 1])
+CHECK_COVERAGE([netdev_received], [1])
+CHECK_COVERAGE([dp_packet_gso], [1])
+CHECK_COVERAGE([netdev_send_multi], [0])
+CHECK_COVERAGE([netdev_sent], [1])
+AT_CHECK([ovs-vsctl get interface p3 statistics:tx_packets], [0], [2
+])
+
+OVS_CHECK_BATCH_GROW([0])
+AT_CHECK([ovs-appctl netdev-dummy/receive p1 "${flow_s}" --len 35000])
+
+OVS_WAIT_UNTIL([test `ovs-vsctl get interface p1 statistics:rx_packets` -eq 2])
+CHECK_COVERAGE([netdev_received], [2])
+OVS_CHECK_BATCH_GROW([1])
+CHECK_COVERAGE([dp_packet_gso], [2])
+CHECK_COVERAGE([dpif_netdev_output_big_batch], [1])
+CHECK_COVERAGE([netdev_send_multi], [0])
+CHECK_COVERAGE([netdev_sent], [3])
+AT_CHECK([ovs-vsctl get interface p3 statistics:tx_packets], [0], [37
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
 AT_SETUP([dpif-netdev - revalidators handle dp modification fail correctly])
 OVS_VSWITCHD_START(
   [add-port br0 p1 \
-- 
2.53.0

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to