Skip to content

Client TUN offload (3/3): client GSO/GRO offload implementation - #504

Draft
xv-thomas-leong wants to merge 11 commits into
mainfrom
main-tun-offload-features
Draft

Client TUN offload (3/3): client GSO/GRO offload implementation#504
xv-thomas-leong wants to merge 11 commits into
mainfrom
main-tun-offload-features

Conversation

@xv-thomas-leong

@xv-thomas-leong xv-thomas-leong commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Part 3 of 3 — client GSO/GRO offload implementation

Final part of a three-PR stack that adds client-side TUN GSO/GRO offload.
Base this on part 2 (refactorings). This part adds the actual feature,
one logical change per commit: deriving the vnet header from the
negotiated IFF_VNET_HDR, chunking GSO flushes to the kernel's per-send
limits, TCP GRO coalescing, the client GSO send path, UDP_GRO receive,
TSO superpacket coalescing on download, and batched recvmmsg GRO
receive.

How Has This Been Tested?

CI and Manually 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

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown

Code coverage summary for 8a01710:

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                         11                 5    54.55%           3                 1    66.67%          11                 5    54.55%           0                 0         -
lightway-app-utils/src/args/duration.rs                               121                18    85.12%          11                 4    63.64%          64                12    81.25%           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                20    84.38%          10                 3    70.00%          68                13    80.88%           0                 0         -
lightway-app-utils/src/cmsg.rs                                        279                23    91.76%          23                 2    91.30%         220                19    91.36%           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/metrics.rs                                       4                 4     0.00%           2                 2     0.00%           4                 4     0.00%           0                 0         -
lightway-app-utils/src/network_change_monitor.rs                      348                87    75.00%          29                 8    72.41%         200                75    62.50%           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                40    50.62%           6                 2    66.67%          72                40    44.44%           0                 0         -
lightway-app-utils/src/sockopt/ip_pktinfo.rs                           14                 1    92.86%           1                 0   100.00%          16                 1    93.75%           0                 0         -
lightway-app-utils/src/sockopt/udp_gro.rs                              11                11     0.00%           1                 1     0.00%          10                10     0.00%           0                 0         -
lightway-app-utils/src/tun.rs                                         504               483     4.17%          50                45    10.00%         326               306     6.13%           0                 0         -
lightway-app-utils/src/utils.rs                                        21                21     0.00%           1                 1     0.00%          11                11     0.00%           0                 0         -
lightway-boring/src/aes256.rs                                         224                 5    97.77%          13                 0   100.00%          97                 0   100.00%           0                 0         -
lightway-boring/src/cert.rs                                            15                 1    93.33%           1                 0   100.00%           7                 0   100.00%           0                 0         -
lightway-boring/src/chacha20_poly1305.rs                              232                 6    97.41%          16                 3    81.25%         107                 3    97.20%           0                 0         -
lightway-boring/src/config.rs                                         111                17    84.68%          16                 4    75.00%          82                14    82.93%           0                 0         -
lightway-boring/src/context.rs                                        391                89    77.24%          31                 6    80.65%         247                35    85.83%           0                 0         -
lightway-boring/src/error.rs                                           37                 8    78.38%           4                 2    50.00%          28                 6    78.57%           0                 0         -
lightway-boring/src/session.rs                                        821               167    79.66%          53                 8    84.91%         448               101    77.46%           0                 0         -
lightway-boring/src/test_utils.rs                                     329                35    89.36%          25                 5    80.00%         210                24    88.57%           0                 0         -
lightway-boring/src/types.rs                                          137                10    92.70%          16                 1    93.75%          92                 9    90.22%           0                 0         -
lightway-client/src/config.rs                                         447               105    76.51%          22                 8    63.64%         295                67    77.29%           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.rs                                       10                10     0.00%           4                 4     0.00%           8                 8     0.00%           0                 0         -
lightway-client/src/io/inside/tun.rs                                  636               133    79.09%          49                22    55.10%         348                97    72.13%           0                 0         -
lightway-client/src/io/outside.rs                                      17                17     0.00%           3                 3     0.00%          15                15     0.00%           0                 0         -
lightway-client/src/io/outside/tcp.rs                                 131               131     0.00%          15                15     0.00%          86                86     0.00%           0                 0         -
lightway-client/src/io/outside/udp.rs                                 399               295    26.07%          40                27    32.50%         263               172    34.60%           0                 0         -
lightway-client/src/io/outside/udp/batch_receive.rs                   167                81    51.50%          13                 3    76.92%         137                66    51.82%           0                 0         -
lightway-client/src/keepalive.rs                                      687                45    93.45%          59                 6    89.83%         357                24    93.28%           0                 0         -
lightway-client/src/lib.rs                                           1743               971    44.29%         138                74    46.38%        1224               716    41.50%           0                 0         -
lightway-client/src/main.rs                                           277               277     0.00%          17                17     0.00%         157               157     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                                 1162               143    87.69%          79                 4    94.94%         640                69    89.22%           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                                           203                21    89.66%          10                 0   100.00%         101                 4    96.04%           0                 0         -
lightway-core/src/connection.rs                                      2123               832    60.81%          95                22    76.84%        1521               568    62.66%           0                 0         -
lightway-core/src/connection/builders.rs                              252                46    81.75%          22                 8    63.64%         260                53    79.62%           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                            88                 0   100.00%          10                 0   100.00%          74                 0   100.00%           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                           1186               167    85.92%          77                11    85.71%         619               103    83.36%           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                                          219                42    80.82%          29                 8    72.41%         243                46    81.07%           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                               37                37     0.00%           4                 4     0.00%          26                26     0.00%           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/gro.rs                                             1542                22    98.57%          64                 2    96.88%         733                19    97.41%           0                 0         -
lightway-core/src/gso.rs                                             1123                88    92.16%          42                 3    92.86%         529                55    89.60%           0                 0         -
lightway-core/src/io.rs                                                13                13     0.00%           4                 4     0.00%          12                12     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                                           81                66    18.52%          33                27    18.18%          73                58    20.55%           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                                            341                28    91.79%          24                 3    87.50%         170                18    89.41%           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                39    91.10%          29                 0   100.00%         235                 9    96.17%           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                                684                57    91.67%          34                 1    97.06%         351                24    93.16%           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                          188                 1    99.47%          10                 0   100.00%         113                 0   100.00%           0                 0         -
lightway-core/src/wire/expresslane_data.rs                             48                21    56.25%           5                 2    60.00%          52                23    55.77%           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-expresslane/src/aead.rs                                       29                29     0.00%           2                 2     0.00%          23                23     0.00%           0                 0         -
lightway-expresslane/src/aead/pool.rs                                 127                71    44.09%           9                 4    55.56%          90                50    44.44%           0                 0         -
lightway-expresslane/src/key.rs                                        24                 0   100.00%           5                 0   100.00%          17                 0   100.00%           0                 0         -
lightway-expresslane/src/replay_window.rs                             269                 4    98.51%          20                 0   100.00%         174                 4    97.70%           0                 0         -
lightway-expresslane/src/session.rs                                   469               195    58.42%          19                 2    89.47%         283               114    59.72%           0                 0         -
lightway-expresslane/src/version.rs                                    32                 0   100.00%           4                 0   100.00%          25                 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                                         135                 0   100.00%           9                 0   100.00%         112                 0   100.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                             346               346     0.00%          42                42     0.00%         303               303     0.00%           0                 0         -
lightway-server/src/connection_manager/connection_map.rs              407                20    95.09%          21                 1    95.24%         228                 8    96.49%           0                 0         -
lightway-server/src/io/inside.rs                                      100                21    79.00%          23                 9    60.87%          69                19    72.46%           0                 0         -
lightway-server/src/io/inside/tun.rs                                   61                61     0.00%          14                14     0.00%          45                45     0.00%           0                 0         -
lightway-server/src/io/outside/tcp.rs                                  93                93     0.00%          10                10     0.00%          68                68     0.00%           0                 0         -
lightway-server/src/io/outside/udp.rs                                 483               428    11.39%          27                24    11.11%         331               297    10.27%           0                 0         -
lightway-server/src/io/outside/udp/batch_receive.rs                   467                19    95.93%          20                 1    95.00%         266                15    94.36%           0                 0         -
lightway-server/src/io/outside/udp/send_queue.rs                      381                26    93.18%          24                 1    95.83%         209                16    92.34%           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                                            605               501    17.19%          34                26    23.53%         413               340    17.68%           0                 0         -
lightway-server/src/main.rs                                           201               201     0.00%          10                10     0.00%          96                96     0.00%           0                 0         -
lightway-server/src/metrics.rs                                        287               265     7.67%          99                89    10.10%         243               223     8.23%           0                 0         -
lightway-server/src/offload_stats.rs                                  125                74    40.80%           8                 3    62.50%          82                42    48.78%           0                 0         -
lightway-server/src/statistics.rs                                     133                59    55.64%           8                 4    50.00%          91                39    57.14%           0                 0         -
uniffi-bindgen/src/uniffi-bindgen.rs                                    3                 3     0.00%           1                 1     0.00%           3                 3     0.00%           0                 0         -
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TOTAL                                                               29081              7912    72.79%        2077               699    66.35%       17604              5391    69.38%           0                 0         -

✅ Region coverage 72% passes
✅ Line coverage 69% passes

@xv-thomas-leong
xv-thomas-leong force-pushed the main-tun-offload-features branch from bd6137a to cd53e1b Compare August 7, 2026 03:05
@xv-thomas-leong
xv-thomas-leong force-pushed the main-tun-offload-features branch from cd53e1b to 96d1252 Compare August 7, 2026 03:16
@xv-thomas-leong
xv-thomas-leong force-pushed the main-tun-offload-features branch from 96d1252 to 7632068 Compare August 7, 2026 03:39
@xv-thomas-leong xv-thomas-leong changed the title TUN offload (3/3): client GSO/GRO offload implementation Client TUN offload (3/3): client GSO/GRO offload implementation Aug 7, 2026
@xv-thomas-leong
xv-thomas-leong force-pushed the main-tun-offload-features branch from 7632068 to 286849c Compare August 7, 2026 04:24
@xv-thomas-leong
xv-thomas-leong force-pushed the main-tun-offload-features branch from 286849c to 6c2d4e3 Compare August 13, 2026 05:18
@xv-thomas-leong
xv-thomas-leong force-pushed the main-tun-offload-features branch from 6c2d4e3 to 8f30da5 Compare August 17, 2026 02:51
@xv-thomas-leong
xv-thomas-leong force-pushed the main-tun-offload-features branch from 8f30da5 to 5867772 Compare August 17, 2026 04:13
@xv-thomas-leong
xv-thomas-leong force-pushed the main-tun-offload-features branch from 5867772 to e66d9a7 Compare August 17, 2026 07:58
@xv-thomas-leong
xv-thomas-leong force-pushed the main-tun-offload-features branch from e66d9a7 to 537d1a3 Compare August 19, 2026 04:03
@xv-thomas-leong
xv-thomas-leong force-pushed the main-tun-offload-features branch from 537d1a3 to 6c4dde1 Compare August 19, 2026 05:43
@xv-thomas-leong
xv-thomas-leong force-pushed the main-tun-offload-features branch 2 times, most recently from 765a97f to b58ce7e Compare August 21, 2026 03:56
@xv-thomas-leong
xv-thomas-leong force-pushed the main-tun-offload-features branch from b58ce7e to 15451ef Compare August 21, 2026 04:00
Base automatically changed from main-tun-offload-refactor to main August 21, 2026 04:43
@xv-thomas-leong
xv-thomas-leong force-pushed the main-tun-offload-features branch 3 times, most recently from e8ae254 to 27b3574 Compare August 24, 2026 07:59
Trust `tun_device.tcp_gso()` over `config.offload`: `build_async` succeeds
even when `TUNSETOFFLOAD` is rejected (tun-rs only warns), so config alone
could leave recv_gso/try_send_gso handling a header the device never
negotiated. Warn when offload was requested but not granted.

Note the flag tracks TSO/USO capability, not the IFF_VNET_HDR framing that
TUNSETIFF already granted; traffic never flows in the mismatched state
because the as_gso() startup check aborts first.
build_segment recomputes each segment's checksum from scratch, so folding
the NEEDS_CSUM aggregate first is a wasted one's-complement sum over up to
64KB per superpacket. Gate the fold on non-GSO packets. Uses is_gso_none()
so the ECN bit is masked.
@xv-thomas-leong
xv-thomas-leong force-pushed the main-tun-offload-features branch 2 times, most recently from 3ccc964 to f78bf17 Compare August 25, 2026 04:56
A UDP_SEGMENT sendmsg is bounded by two kernel limits: total bytes
(MAX_GSO_SEND_BYTES = 65535-8-40, EMSGSIZE beyond) and segment count
(gso_size * UDP_MAX_SEGMENTS, EINVAL beyond). A TUN aggregate can reach
65535 bytes before the per-segment wire::Header, so split on segment
boundaries to keep UDP_SEGMENT's uniform stride, clamping segs_per_send to
MAX_GSO_SEGS. A mid-batch failure drops the remainder; datagram semantics
let the peer recover.

Gates MAX_GSO_SEND_BYTES to Linux, its only consumer.
send_gso_chunked and udp_send_gso returned IOCallbackResult<usize>, but the
byte count was misleading: the unit was inconsistent between legs (inside
bytes when plugins dropped everything, wire bytes on success), and a
send_gso implementation may report a batch as fully sent that the kernel
actually shed, so no caller may treat a successful return as a delivery
count. Return IOCallbackResult<()> so failures are surfaced for logging
only and nothing reads a bogus count.
Receive-side mirror of gso: merge in-order same-flow IPv4 TCP segments into
one TSO superpacket behind a virtio_net_hdr so the kernel traverses its
receive path once per batch. TcpGroTable coalesces several flows per window
while preserving within-flow write order. Rules mirror the kernel's
tcp_gro_receive; PSH/FIN-first segments are written directly, uncopied.

The header compare in `append` is a byte-range whitelist-of-exclusions, not
field accessors: every byte is compared except the fields that legitimately
differ, so any unanticipated field forces a safe flush. Field accessors
would invert this into a blacklist that splices two TCP states on a
forgotten field. Rationale is recorded at the code. Other fields use
pnet_packet, matching gso.rs.

NEEDS_CSUM seeding is the inverse of gso_none_checksum. Adds
VirtioNetHdr::to_bytes.
With --enable-tun-offload on Linux the TUN opens with IFF_VNET_HDR and the
inside loop reads TSO superpackets, forwarding each via
inside_data_received_gso (segmented and encrypted per segment, shipped as
chunked sendmsg(UDP_SEGMENT) batches).

The capability is an upgrade trait (InsideIORecvGso via as_gso), checked
once at startup; kernels refusing IFF_VNET_HDR fail with a clear error
before traffic moves. The io-uring inside backend cannot supply a GSO
device, so that combination is rejected in validation.

Offload is also rejected with the inside packet codec: the codec takes the
packet before segmentation and would ship a ~64KB superpacket whose
total_length lies to the peer. Skips the checksum fold for aggregates
(mirrors the server loop); both gso_type tests use is_gso_none() to mask
ECN. Adds client-side and both-sides offload e2e targets.
socket_enable_udp_gro flips the UDP_GRO sockopt (Linux 5.0+), and the cmsg
iterator learns the UDP_GRO control message reporting coalesced segment
size. The sockopt is what makes the kernel coalesce (valid peer checksums
are necessary but not sufficient), and it changes every subsequent receive
on the socket: a plain recv(2) with no control space silently concatenates
datagrams. The doc comment says so.

The new arm's two unsafe ops are split into separate SAFETY blocks
(multiple_unsafe_ops_per_block is denied).
Mirror of the GSO upload path: in-order TCP segments are merged per flow by
a TcpGroTable and written to the TUN once as a TSO superpacket via
Tun::try_send_gso. Coalescing runs in a window the receive loop opens per
batch (gro_open/gro_flush on InsideIORecv, no-ops without offload); the
window flag is an AtomicBool with relaxed load, since all opens, sends and
flushes run on one task.

The send path takes a TunSend seam with the GRO fields in a Gro struct
generic over it (monomorphised, so the closed-window path stays a relaxed
load). Seven tests over a FakeTun cover the load-bearing ordering guarantee
(flushed superpackets reach the TUN before a non-consumed packet's direct
write), the no-op/bypass/drain cases, and drop accounting; the ordering
test is mutation-verified.

Write failures are logged and dropped, not propagated -- the absorbed sends
already reported success. The log carries the segment count.
Route UDP receives through one recvmmsg per readiness event when offload is
on: up to MAX_IO_BATCH_SIZE datagrams per syscall, each with its own
control buffer, so kernel-coalesced aggregates arrive with their UDP_GRO
segment size and split zero-copy on that boundary. Without coalescing (old
kernel, or zero-checksum peer) each slot holds one datagram and recvmmsg
still cuts syscalls.

The GRO window is flushed inside the conn lock, not after it: send() only
runs under that mutex, so closing the window while held leaves no gap for
another task to coalesce past the drain and strand a tail packet.
write_super only issues non-blocking try_sends, so holding the lock longer
is free. gso_size == 0 falls back to whole-buffer at the split.

The capability is an upgrade trait (OutsideIORecvGro via as_gro), selected
at startup; TCP mode keeps the per-packet loop. The sockopt is flipped only
when that loop consumes it.
On an egress device without TX checksum offload the kernel refuses a
UDP_SEGMENT send in udp_send_skb() with EIO (UDP GSO needs CHECKSUM_PARTIAL,
which such a device cannot provide), dropping every coalesced batch.
Observed on a Realtek USB 5GbE adapter (cdc_ncm); checksum-offload NICs are
unaffected.

Latch a per-socket flag on EIO/EINVAL/EOPNOTSUPP, exposed via the new
OutsideIOSendCallback::gso_enabled(); the connection then drops to the
existing per-segment fallback (send_to_outside). Transient errors and the
sizing error EMSGSIZE do not latch. One batch is lost at latching; the
socket never attempts GSO again.
parse_coalescable accepted any structurally-valid segment without checking
its TCP checksum, and take() reseeds VIRTIO_NET_HDR_F_NEEDS_CSUM so the
kernel *completes* the checksum rather than verifying it. A download
segment corrupted upstream of the tunnel (origin->server leg, outside the
DTLS AEAD) would then be merged and handed to the app with a freshly-valid
checksum over corrupt bytes — laundering a packet the non-offload path
drops. Kernel GRO validates for exactly this reason.

Verify the checksum as the last (most expensive) check; a failing segment
falls out to Incompatible and is written directly, where a plain
(non-NEEDS_CSUM) write lets the kernel validate and drop it and TCP
retransmits. Single-segment packets were already safe (take() returns them
untouched with a GSO_NONE header).
@xv-thomas-leong
xv-thomas-leong force-pushed the main-tun-offload-features branch from f78bf17 to 503d266 Compare August 25, 2026 05:20
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.

1 participant