Skip to content

CVPN-2346 Implement GSO offload on lightway-server#413

Open
kp-samuel-tam wants to merge 7 commits into
mainfrom
gso-on-server
Open

CVPN-2346 Implement GSO offload on lightway-server#413
kp-samuel-tam wants to merge 7 commits into
mainfrom
gso-on-server

Conversation

@kp-samuel-tam
Copy link
Copy Markdown
Member

@kp-samuel-tam kp-samuel-tam commented May 4, 2026

Description

Implement GSO on server side on DTLS and Expresslane, specifically on bulk server->client traffic. This consistently halves the total syscalls used during bulk transfers, and also improves aggregated server throughput by 2x for multiple clients doing transfers.

When --enable-tun-offload is set, the server reads TSO superpackets from the TUN with IFF_VNET_HDR, segments them in userspace, and emits each superpacket as a single sendmsg(UDP_SEGMENT) instead of N per-segment syscalls. On a single-flow iperf3 reverse test the kernel UDP send path collapses near-completely: udp_sendmsg 0.71% → ~0.05%, sock_alloc_send_pskb 2.61% → ~0.13%, mlx5e_xmit 1.88% → ~0%.

Trade-off: kernel work is replaced with userspace work (per-segment IP/TCP/UDP checksum recomputation, segment assembly). Kernel-side wins are clear and measurable; userspace cost is now the dominant factor.

Pacing: each sendmsg(UDP_SEGMENT) produces a NIC burst of up to N segments. This can exceed receiver socket buffer depth and increase tail drops at peak rates. We will need to revisit better TX pacing under congested links.

Future work will focus on compatibility with TUN backends like io_uring, GRO on the server side, and full GSO/GRO on client side, where single-flow workloads should see the biggest visible speedup not in this PR.

Motivation and Context

See ticket CVPN-2346.

How Has This Been Tested?

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • The correct base branch is being used, if not main

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 4, 2026

Code coverage summary for 431f4c3:

Filename                                                          Regions    Missed Regions     Cover   Functions  Missed Functions  Executed       Lines      Missed Lines     Cover    Branches   Missed Branches     Cover
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
lightway-app-utils/src/args/cipher.rs                                   5                 5     0.00%           1                 1     0.00%           5                 5     0.00%           0                 0         -
lightway-app-utils/src/args/connection_type.rs                          8                 8     0.00%           2                 2     0.00%           8                 8     0.00%           0                 0         -
lightway-app-utils/src/args/duration.rs                               121                22    81.82%          11                 5    54.55%          64                15    76.56%           0                 0         -
lightway-app-utils/src/args/ip_map.rs                                  27                27     0.00%           5                 5     0.00%          19                19     0.00%           0                 0         -
lightway-app-utils/src/args/keyshare.rs                                 5                 5     0.00%           1                 1     0.00%           5                 5     0.00%           0                 0         -
lightway-app-utils/src/args/logging.rs                                 37                37     0.00%           3                 3     0.00%          31                31     0.00%           0                 0         -
lightway-app-utils/src/args/nonzero_duration.rs                       128                24    81.25%          10                 4    60.00%          68                16    76.47%           0                 0         -
lightway-app-utils/src/connection_ticker.rs                           229                17    92.58%          28                 4    85.71%         126                15    88.10%           0                 0         -
lightway-app-utils/src/dplpmtud_timer.rs                              209                13    93.78%          22                 4    81.82%         117                11    90.60%           0                 0         -
lightway-app-utils/src/event_stream.rs                                 19                 0   100.00%           3                 0   100.00%          11                 0   100.00%           0                 0         -
lightway-app-utils/src/packet_codec.rs                                  2                 2     0.00%           1                 1     0.00%           1                 1     0.00%           0                 0         -
lightway-app-utils/src/sockopt/ip_mtu_discover.rs                      81                81     0.00%           6                 6     0.00%          72                72     0.00%           0                 0         -
lightway-app-utils/src/sockopt/ip_pktinfo.rs                           14                14     0.00%           1                 1     0.00%          16                16     0.00%           0                 0         -
lightway-app-utils/src/tun.rs                                         331               331     0.00%          36                36     0.00%         202               202     0.00%           0                 0         -
lightway-app-utils/src/utils.rs                                        21                21     0.00%           1                 1     0.00%          11                11     0.00%           0                 0         -
lightway-client/src/config.rs                                         234                39    83.33%          12                 5    58.33%         170                34    80.00%           0                 0         -
lightway-client/src/dns_manager.rs                                     18                18     0.00%           4                 4     0.00%          16                16     0.00%           0                 0         -
lightway-client/src/io/inside/tun.rs                                   82                82     0.00%          12                12     0.00%          60                60     0.00%           0                 0         -
lightway-client/src/io/outside.rs                                      14                14     0.00%           2                 2     0.00%          12                12     0.00%           0                 0         -
lightway-client/src/io/outside/tcp.rs                                  91                91     0.00%          13                13     0.00%          58                58     0.00%           0                 0         -
lightway-client/src/io/outside/udp.rs                                 169               169     0.00%          18                18     0.00%         110               110     0.00%           0                 0         -
lightway-client/src/io/outside/udp_batch_receiver.rs                   61                11    81.97%           6                 1    83.33%          56                12    78.57%           0                 0         -
lightway-client/src/keepalive.rs                                      615                44    92.85%          55                 6    89.09%         330                25    92.42%           0                 0         -
lightway-client/src/lib.rs                                           1243               667    46.34%         102                53    48.04%         833               487    41.54%           0                 0         -
lightway-client/src/main.rs                                           359               359     0.00%          20                20     0.00%         227               227     0.00%           0                 0         -
lightway-client/src/platform/linux/dns_manager.rs                     118                91    22.88%          14                 9    35.71%          87                62    28.74%           0                 0         -
lightway-client/src/platform/linux/dns_manager/direct_file.rs         106                42    60.38%          12                 6    50.00%          65                29    55.38%           0                 0         -
lightway-client/src/platform/linux/dns_manager/resolvconf.rs           61                61     0.00%           8                 8     0.00%          52                52     0.00%           0                 0         -
lightway-client/src/platform/linux/dns_manager/resolvectl.rs           41                41     0.00%           5                 5     0.00%          34                34     0.00%           0                 0         -
lightway-client/src/route_manager.rs                                 1190               212    82.18%          77                 8    89.61%         663               117    82.35%           0                 0         -
lightway-core/src/borrowed_bytesmut.rs                                373                 0   100.00%          24                 0   100.00%         185                 0   100.00%           0                 0         -
lightway-core/src/builder_predicates.rs                                24                12    50.00%           4                 2    50.00%          24                12    50.00%           0                 0         -
lightway-core/src/cipher.rs                                            13                 0   100.00%           2                 0   100.00%          10                 0   100.00%           0                 0         -
lightway-core/src/connection.rs                                      1756               925    47.32%          74                29    60.81%        1242               625    49.68%           0                 0         -
lightway-core/src/connection/builders.rs                              244                46    81.15%          21                 8    61.90%         254                53    79.13%           0                 0         -
lightway-core/src/connection/dplpmtud.rs                             1741                81    95.35%          63                 0   100.00%         830                 7    99.16%           0                 0         -
lightway-core/src/connection/expresslane.rs                            26                11    57.69%           4                 1    75.00%          34                 7    79.41%           0                 0         -
lightway-core/src/connection/fragment_map.rs                          366                 6    98.36%          25                 0   100.00%         254                 3    98.82%           0                 0         -
lightway-core/src/connection/io_adapter.rs                            656               151    76.98%          37                 8    78.38%         354                96    72.88%           0                 0         -
lightway-core/src/connection/key_update.rs                             34                13    61.76%           5                 0   100.00%          38                19    50.00%           0                 0         -
lightway-core/src/context.rs                                          212                51    75.94%          28                11    60.71%         229                64    72.05%           0                 0         -
lightway-core/src/context/ip_pool.rs                                    8                 3    62.50%           1                 0   100.00%           5                 0   100.00%           0                 0         -
lightway-core/src/context/server_auth.rs                               32                24    25.00%           4                 3    25.00%          24                20    16.67%           0                 0         -
lightway-core/src/encoding_request_states.rs                            3                 0   100.00%           1                 0   100.00%           3                 0   100.00%           0                 0         -
lightway-core/src/gso.rs                                              252               252     0.00%          15                15     0.00%         153               153     0.00%           0                 0         -
lightway-core/src/io.rs                                                10                10     0.00%           3                 3     0.00%           9                 9     0.00%           0                 0         -
lightway-core/src/keyshare.rs                                           5                 0   100.00%           1                 0   100.00%           5                 0   100.00%           0                 0         -
lightway-core/src/lib.rs                                                9                 0   100.00%           3                 0   100.00%           9                 0   100.00%           0                 0         -
lightway-core/src/metrics.rs                                           51                41    19.61%          21                17    19.05%          47                37    21.28%           0                 0         -
lightway-core/src/packet.rs                                            38                10    73.68%           4                 1    75.00%          30                 6    80.00%           0                 0         -
lightway-core/src/plugin.rs                                           307                17    94.46%          22                 4    81.82%         148                10    93.24%           0                 0         -
lightway-core/src/tls/mod.rs                                            4                 4     0.00%           1                 1     0.00%           3                 3     0.00%           0                 0         -
lightway-core/src/utils.rs                                            334                26    92.22%          22                 2    90.91%         165                17    89.70%           0                 0         -
lightway-core/src/version.rs                                           93                 0   100.00%          17                 0   100.00%          82                 0   100.00%           0                 0         -
lightway-core/src/wire.rs                                             438                42    90.41%          29                 1    96.55%         235                12    94.89%           0                 0         -
lightway-core/src/wire/auth_failure.rs                                 27                 1    96.30%           3                 0   100.00%          17                 0   100.00%           0                 0         -
lightway-core/src/wire/auth_request.rs                                472                12    97.46%          26                 0   100.00%         241                 0   100.00%           0                 0         -
lightway-core/src/wire/auth_success_with_config_ipv4.rs               222                 3    98.65%          11                 0   100.00%         124                 0   100.00%           0                 0         -
lightway-core/src/wire/data.rs                                         51                 1    98.04%           5                 0   100.00%          33                 0   100.00%           0                 0         -
lightway-core/src/wire/data_frag.rs                                   127                 1    99.21%          14                 0   100.00%          80                 0   100.00%           0                 0         -
lightway-core/src/wire/encoding_request.rs                             82                 2    97.56%           6                 0   100.00%          42                 1    97.62%           0                 0         -
lightway-core/src/wire/encoding_response.rs                            82                 2    97.56%           6                 0   100.00%          42                 1    97.62%           0                 0         -
lightway-core/src/wire/expresslane_config.rs                          166                 1    99.40%           8                 0   100.00%          92                 0   100.00%           0                 0         -
lightway-core/src/wire/expresslane_data.rs                           1038                61    94.12%          41                 5    87.80%         528                36    93.18%           0                 0         -
lightway-core/src/wire/ping.rs                                         95                 2    97.89%           7                 0   100.00%          59                 0   100.00%           0                 0         -
lightway-core/src/wire/pong.rs                                        109                 2    98.17%           8                 0   100.00%          72                 0   100.00%           0                 0         -
lightway-core/src/wire/server_config.rs                                69                 2    97.10%           4                 0   100.00%          37                 0   100.00%           0                 0         -
lightway-server/src/auth.rs                                           273                49    82.05%          22                 6    72.73%         171                28    83.63%           0                 0         -
lightway-server/src/config.rs                                          23                23     0.00%           1                 1     0.00%          36                36     0.00%           0                 0         -
lightway-server/src/connection.rs                                     137               137     0.00%          11                11     0.00%         110               110     0.00%           0                 0         -
lightway-server/src/connection_manager.rs                             335               335     0.00%          39                39     0.00%         288               288     0.00%           0                 0         -
lightway-server/src/connection_manager/connection_map.rs              407                16    96.07%          21                 1    95.24%         228                 7    96.93%           0                 0         -
lightway-server/src/io/inside/tun.rs                                   50                50     0.00%          11                11     0.00%          35                35     0.00%           0                 0         -
lightway-server/src/io/outside/tcp.rs                                  92                92     0.00%          10                10     0.00%          67                67     0.00%           0                 0         -
lightway-server/src/io/outside/udp.rs                                 342               342     0.00%          17                17     0.00%         235               235     0.00%           0                 0         -
lightway-server/src/io/outside/udp/cmsg.rs                            197                53    73.10%          14                 5    64.29%         158                43    72.78%           0                 0         -
lightway-server/src/ip_manager.rs                                     542                50    90.77%          22                 4    81.82%         242                23    90.50%           0                 0         -
lightway-server/src/ip_manager/ip_pool.rs                             545                 0   100.00%          28                 0   100.00%         257                 0   100.00%           0                 0         -
lightway-server/src/lib.rs                                            403               403     0.00%          18                18     0.00%         270               270     0.00%           0                 0         -
lightway-server/src/main.rs                                           241               241     0.00%          10                10     0.00%         127               127     0.00%           0                 0         -
lightway-server/src/metrics.rs                                        254               250     1.57%          85                83     2.35%         215               211     1.86%           0                 0         -
lightway-server/src/statistics.rs                                     132                59    55.30%           8                 4    50.00%          86                35    59.30%           0                 0         -
uniffi-bindgen/src/uniffi-bindgen.rs                                    3                 3     0.00%           1                 1     0.00%           3                 3     0.00%           0                 0         -
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TOTAL                                                               19184              6466    66.29%        1379               576    58.23%       11796              4471    62.10%           0                 0         -

✅ Region coverage 66% passes
✅ Line coverage 62% passes

@kp-samuel-tam kp-samuel-tam changed the title Implement GSO offload on lightway-server CVPN-2346 Implement GSO offload on lightway-server May 11, 2026
@kp-samuel-tam kp-samuel-tam force-pushed the gso-on-server branch 5 times, most recently from 76f46f2 to 45a8d96 Compare May 11, 2026 09:28
Add the `gso` module to lightway-core with VirtioNetHdr definition,
checksum helpers, and segment build/count functions for splitting GSO
superpackets into individual segments with correct per-segment header
fixups (IP ID, TCP seq, checksums).

Also add tun-rs workspace dependency to lightway-core and
lightway-server Cargo.toml.
Add the `send_gso` method to the OutsideIOSendCallback trait for
sending concatenated wire packets via kernel GSO (UDP_SEGMENT).

Include todo!() stub implementations in client TCP/UDP, server TCP,
and test harnesses to satisfy the trait contract.
Add gso_buf/gso_size fields to TlsIOAdapter so the wolfssl send()
callback can buffer raw encrypted segments during GSO processing.
Add udp_send_gso to wrap buffered segments with wire headers and
send as one sendmsg via the vectored send_gso callback.

The implementation uses a zero-copy fast path when no outside
plugins are configured: scatter-gather via iovec with a shared
header buffer and borrowed slices of the encrypted segment buffer.
The plugin path builds each segment as its own BytesMut and enforces
the uniform-stride requirement of UDP_SEGMENT.
Add inside_data_received_gso and send_to_outside_gso methods to
Connection. These process a GSO superpacket as a single packet through
plugins/encoder, then split into per-segment encrypted frames and
collect into a wire buffer for batch send via UDP_SEGMENT.
Add offload config field to TunConfig to enable IFF_VNET_HDR on TUN
devices. Add recv_gso for raw reads that include the virtio_net_hdr
prefix, and prepend a zeroed virtio header on try_send when offload
is enabled.
Extend send_to_socket to accept an optional gso_size parameter and
build UDP_SEGMENT cmsg for kernel-level segmentation. Implement the
real send_gso on UdpSocket using this path.
Add enable_tun_offload config option and wire it through ServerConfig
to main. Extract the default inside IO loop into its own function and
add inside_io_loop_gso that reads virtio-framed superpackets from TUN,
dispatches GSO vs single-packet paths, and sets gso_max_size on the
TUN device.
@kp-samuel-tam kp-samuel-tam marked this pull request as ready for review May 13, 2026 12:48
@kp-samuel-tam kp-samuel-tam requested a review from a team as a code owner May 13, 2026 12:48
}

impl PluginList {
#[cfg(target_os = "linux")]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This need not be a linux specific method. Looks generic

// Expose the full slab to `recv_gso` as `&mut [u8]`.
// SAFETY: every byte of the slab was zero-initialized at
// construction; subsequent iters only ever shrunk `len` or
// overwrote bytes. We never hand out uninitialized memory.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not sound safe, as pkt is mutable we could also create new BytesMut and replace it.
So now if you reserve, it might be unintialized.

I think what you want is https://docs.rs/bytes/latest/bytes/struct.BytesMut.html#method.spare_capacity_mut which gives pointer to spare buffer which you can sent to recv_gso

Comment on lines +471 to +503
#[cfg(target_os = "linux")]
if config.enable_tun_offload {
// TODO: derive from a proper inside-MTU server config field.
const INSIDE_MTU: u32 = 1350;
// Cap gso_max_size so a single UDP_SEGMENT sendmsg of the
// re-segmented superpacket stays within one IPv4 UDP
// datagram (65535 − 20 IP − 8 UDP = 65507 bytes payload)
// and ≤ UDP_MAX_SEGMENTS (64) segments. Each wire segment
// is: inside packet (IP+TCP hdr 40 + MSS) + worst-case
// crypto overhead (~40, Expresslane is the larger of
// DTLS-37 and Expresslane-40) + Lightway hdr (16).
const UDP_MAX_GSO_PAYLOAD: u32 = 65507;
const UDP_MAX_SEGMENTS: u32 = 64;
const CRYPTO_OVERHEAD: u32 = 40;
const WIRE_HDR: u32 = 16;
const IP_TCP_HDR: u32 = 40;
let wire_per_seg = INSIDE_MTU + CRYPTO_OVERHEAD + WIRE_HDR;
let n_max = (UDP_MAX_GSO_PAYLOAD / wire_per_seg).min(UDP_MAX_SEGMENTS);
let mss = INSIDE_MTU - IP_TCP_HDR;
let max_gso_buf_size = IP_TCP_HDR + n_max * mss;
if let Ok(name) = tun.name() {
let _ = std::process::Command::new("ip")
.args([
"link",
"set",
&name,
"gso_max_size",
&max_gso_buf_size.to_string(),
])
.output();
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better to make this a config and move the responsibility of setting gso size, outside of server to avoid needing ADMIN capability

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants