Bug 1902065 - send and recv IP ECN on HTTP3/QUIC r=necko-reviewers,kershaw

This commit adds the `network.http.http3.ecn` pref. When `true`, IP ECN markings
are send and received for HTTP3 QUIC UDP datagrams.

In addition, this commit adds two new telemetry metrics, each keyed by send and
receive path:

1. `HTTP3_ECN_CE_ECT0_RATIO` histogram
2. `ecn_paths_capability` scalar

Differential Revision: https://phabricator.services.mozilla.com/D220062
This commit is contained in:
Max Inden 2024-09-11 08:22:13 +00:00
Родитель d00f1e579e
Коммит 36dc3888a1
5 изменённых файлов: 111 добавлений и 7 удалений

1
Cargo.lock сгенерированный
Просмотреть файл

@ -4149,6 +4149,7 @@ dependencies = [
name = "neqo_glue"
version = "0.1.0"
dependencies = [
"firefox-on-glean",
"libc",
"log",
"neqo-common",

Просмотреть файл

@ -13699,6 +13699,14 @@
#endif
mirror: always
# Send and receive IP ECN marks. Noop if network.http.http3.use_nspr_for_io is
# true.
- name: network.http.http3.ecn
type: RelaxedAtomicBool
value: false
mirror: always
rust: true
- name: network.http.http3.enable_qlog
type: RelaxedAtomicBool
value: false

Просмотреть файл

@ -980,6 +980,47 @@ networking:
expires: never
telemetry_mirror: HTTP_UPLOAD_THROUGHPUT_MBPS_HTTP_3_100
http_3_ecn_ce_ect0_ratio:
type: labeled_custom_distribution
unit: integer
range_min: 0
range_max: 2000
bucket_count: 100
histogram_type: exponential
description: >
HTTP3: ECN CE to ECT0 ratio (multiply by 10000).
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1902065
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1902065
data_sensitivity:
- technical
notification_emails:
- necko@mozilla.com
- minden@mozilla.com
expires: never
labels:
- tx
- rx
http_3_ecn_path_capability:
type: labeled_counter
description: >
Number of paths known to be ECN capable or not-capable.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1902065
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1902065
data_sensitivity:
- technical
notification_emails:
- necko@mozilla.com
- minden@mozilla.com
expires: never
labels:
- capable
- not-capable
cache_metadata_first_read_time: &cache_metadata_first_read_time
type: timing_distribution
time_unit: millisecond

Просмотреть файл

@ -9,6 +9,7 @@ license = "MPL-2.0"
name = "neqo_glue"
[dependencies]
firefox-on-glean = { path = "../../../toolkit/components/glean/api" }
neqo-udp = { tag = "v0.9.0", git = "https://github.com/mozilla/neqo" }
neqo-http3 = { tag = "v0.9.0", git = "https://github.com/mozilla/neqo" }
neqo-transport = { tag = "v0.9.0", git = "https://github.com/mozilla/neqo" }

Просмотреть файл

@ -56,6 +56,12 @@ pub struct NeqoHttp3Conn {
socket: Option<neqo_udp::Socket<BorrowedSocket>>,
}
impl Drop for NeqoHttp3Conn {
fn drop(&mut self) {
self.record_stats_in_glean();
}
}
// Opaque interface to mozilla::net::NetAddr defined in DNS.h
#[repr(C)]
pub union NetAddr {
@ -310,6 +316,53 @@ impl NeqoHttp3Conn {
}));
unsafe { Ok(RefPtr::from_raw(conn).unwrap()) }
}
#[cfg(not(target_os = "android"))]
fn record_stats_in_glean(&self) {
use firefox_on_glean::metrics::networking as glean;
use neqo_common::IpTosEcn;
// Metric values must be recorded as integers. Glean does not support
// floating point distributions. In order to represent values <1, they
// are multiplied by `PRECISION_FACTOR`. A `PRECISION_FACTOR` of
// `10_000` allows one to represent fractions down to 0.0001.
const PRECISION_FACTOR: u64 = 10_000;
let stats = self.conn.transport_stats();
if stats.packets_tx == 0 {
return;
}
if static_prefs::pref!("network.http.http3.ecn") {
if stats.ecn_tx[IpTosEcn::Ect0] > 0 {
let ratio =
(stats.ecn_tx[IpTosEcn::Ce] * PRECISION_FACTOR) / stats.ecn_tx[IpTosEcn::Ect0];
glean::http_3_ecn_ce_ect0_ratio
.get(&"tx")
.accumulate_single_sample_signed(ratio as i64);
}
if stats.ecn_rx[IpTosEcn::Ect0] > 0 {
let ratio =
(stats.ecn_rx[IpTosEcn::Ce] * PRECISION_FACTOR) / stats.ecn_rx[IpTosEcn::Ect0];
glean::http_3_ecn_ce_ect0_ratio
.get(&"rx")
.accumulate_single_sample_signed(ratio as i64);
}
glean::http_3_ecn_path_capability
.get(&"capable")
.add(stats.ecn_paths_capable as i32);
glean::http_3_ecn_path_capability
.get(&"not-capable")
.add(stats.ecn_paths_not_capable as i32);
}
}
// Noop on Android for now, due to performance regressions.
// - <https://bugzilla.mozilla.org/show_bug.cgi?id=1898810>
// - <https://bugzilla.mozilla.org/show_bug.cgi?id=1906664>
#[cfg(target_os = "android")]
fn record_stats_in_glean(&self) {}
}
#[no_mangle]
@ -491,10 +544,10 @@ pub unsafe extern "C" fn neqo_http3conn_process_input(
break;
}
bytes_read += dgrams.iter().map(|d| d.len()).sum::<usize>();
// ECN support will be introduced with
// https://bugzilla.mozilla.org/show_bug.cgi?id=1902065.
for dgram in &mut dgrams {
dgram.set_tos(Default::default());
if !static_prefs::pref!("network.http.http3.ecn") {
for dgram in &mut dgrams {
dgram.set_tos(Default::default());
}
}
conn.conn
.process_multiple_input(dgrams.iter(), Instant::now());
@ -623,9 +676,9 @@ pub extern "C" fn neqo_http3conn_process_output_and_send(
};
match conn.conn.process_output(conn.last_output_time) {
Output::Datagram(mut dg) => {
// ECN support will be introduced with
// https://bugzilla.mozilla.org/show_bug.cgi?id=1902065.
dg.set_tos(Default::default());
if !static_prefs::pref!("network.http.http3.ecn") {
dg.set_tos(Default::default());
}
if static_prefs::pref!("network.http.http3.block_loopback_ipv6_addr")
&& matches!(dg.destination(), SocketAddr::V6(addr) if addr.ip().is_loopback())