Skip to content

Commit

Permalink
fix(udp): retry send on first EINVAL
Browse files Browse the repository at this point in the history
Android API level < 26 does not support the `libc::IP_TOS` control message.
`sendmsg` calls with `libc::IP_TOS` return `libc::EINVAL`.

#1516 added a fallback, not setting
`libc::IP_TOS` on consecutive calls to `sendmsg` after a failure with
`libc::EINVAL`. The current datagram would be dropped. Consecutive datagrams
passed to `sendmsg` would succeed as they would be sent without `libc::IP_TOS`
through the fallback.

Instead of dropping the first datagram on `libc::EINVAL`, this commit adds a
retry for it without `libc::IP_TOS`.

This is e.g. relevant for Neqo. When establishing a QUIC connection, dropping
the first datagram [delays connection establishment by
100ms](https://github.com/mozilla/neqo/blob/3001a3a56f2274eaafaa956fb394f0817f526ae7/neqo-transport/src/rtt.rs#L28).
With the retry introduced in this commit, delay due to unsupported
`libc::IP_TOS` should be negligeable.

Closes #1975.
  • Loading branch information
mxinden authored and djc committed Dec 17, 2024
1 parent a83c6e4 commit e953059
Showing 1 changed file with 13 additions and 3 deletions.
16 changes: 13 additions & 3 deletions quinn-udp/src/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,10 +330,20 @@ fn send(
}
}

if e.raw_os_error() == Some(libc::EINVAL) {
// Some arguments to `sendmsg` are not supported.
// Switch to fallback mode.
// Some arguments to `sendmsg` are not supported. Switch to
// fallback mode and retry if we haven't already.
if e.raw_os_error() == Some(libc::EINVAL) && !state.sendmsg_einval() {
state.set_sendmsg_einval();
prepare_msg(
transmit,
&dst_addr,
&mut msg_hdr,
&mut iovec,
&mut cmsgs,
encode_src_ip,
state.sendmsg_einval(),
);
continue;
}

// - EMSGSIZE is expected for MTU probes. Future work might be able to avoid
Expand Down

0 comments on commit e953059

Please sign in to comment.