Skip to content

Commit

Permalink
Truncate GSO when necessary to avoid excessive padding
Browse files Browse the repository at this point in the history
  • Loading branch information
Ralith committed Apr 29, 2024
1 parent a23970b commit 98b9664
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 0 deletions.
18 changes: 18 additions & 0 deletions quinn-proto/src/connection/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,24 @@ impl Connection {
}

if num_datagrams > 1 {
// If too many padding bytes would be required to continue the GSO batch
// after this packet, end the GSO batch here. Ensures that fixed-size frames
// with heterogeneous sizes (e.g. application datagrams) won't inadvertently
// waste large amounts of bandwidth. The exact threshold is a bit arbitrary
// and might benefit from further tuning, though there's no universally
// optimal value.
const MAX_PADDING: usize = 16;
let packet_len_unpadded = cmp::max(builder.min_size, buf.len())
- datagram_start
+ builder.tag_len;
if packet_len_unpadded + MAX_PADDING < segment_size as usize {
trace!(
"GSO truncated by demand for {} padding bytes",
segment_size as usize - packet_len_unpadded
);
break;
}

// Pad the current packet to GSO segment size so it can be included in the
// GSO batch.
builder.pad_to(segment_size as u16);
Expand Down
22 changes: 22 additions & 0 deletions quinn-proto/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2935,3 +2935,25 @@ fn datagram_gso() {
((29 + DATAGRAM_LEN) * DATAGRAMS) as u64
);
}

#[test]
fn gso_truncation() {
let _guard = subscribe();
let mut pair = Pair::default();
let (client_ch, _) = pair.connect();

let initial_ios = pair.client_conn_mut(client_ch).stats().udp_tx.ios;

// Send three application datagrams such that each is large to be combined with another in a
// single MTU, and the second datagram would require an unreasonably large amount of padding to
// produce a QUIC packet of the same length as the first.
info!("sending");
for len in [1024, 768, 768] {
pair.client_datagrams(client_ch)
.send(vec![0; len].into(), false)
.unwrap();
}
pair.drive();
let final_ios = pair.client_conn_mut(client_ch).stats().udp_tx.ios;
assert_eq!(final_ios - initial_ios, 2);
}

0 comments on commit 98b9664

Please sign in to comment.