On 7/10/26 9:08 AM, David Marchand wrote:
> 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 | 58 +++++++++++++++++++------------------
> tests/dpif-netdev.at | 69 ++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 99 insertions(+), 28 deletions(-)
>
> diff --git a/lib/netdev.c b/lib/netdev.c
> index 330c462e98..533c1eadfd 100644
> --- a/lib/netdev.c
> +++ b/lib/netdev.c
> @@ -912,44 +912,46 @@ 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);
> + }
> + } 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;
> + }
> }
> - netdev->netdev_class->push_header(netdev, ingress_netdev, packet,
> - data);
> + }
> + }
>
> - 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, ingress_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 71cce9f895..bc1a4ff5db 100644
> --- a/tests/dpif-netdev.at
> +++ b/tests/dpif-netdev.at
> @@ -3663,6 +3663,75 @@ 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])
nit:
AT_CHECK([ovs-vsctl wait-until interface p1 statistics:rx_packets=1])
> +CHECK_COVERAGE([netdev_received], [1])
> +CHECK_COVERAGE([dp_packet_gso], [1])
> +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])
nit:
AT_CHECK([ovs-vsctl wait-until interface p1 statistics:rx_packets=2])
> +CHECK_COVERAGE([netdev_received], [2])
> +OVS_CHECK_BATCH_GROW([2])
> +CHECK_COVERAGE([dp_packet_gso], [2])
> +CHECK_COVERAGE([dpif_netdev_output_grow_queues], [1])
> +CHECK_COVERAGE([netdev_sent], [2])
> +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 \
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev