9 Commits
Author SHA1 Message Date
Nils Andreas Svee a58e6d1ce5 Merge branch 'feature/irtt'
Rust CI / cargo fmt (push) Successful in 13s
Rust CI / cargo clippy (push) Failing after 21s
Rust CI / cargo check (x86_64-unknown-linux-gnu) (push) Failing after 25s
Rust CI / cargo check (x86_64-unknown-linux-musl) (push) Failing after 8s
Rust CI / cargo test (x86_64-unknown-linux-musl) (push) Failing after 6s
Rust CI / cargo test (x86_64-unknown-linux-gnu) (push) Failing after 26s
Supply chain / cargo-deny advisories (push) Failing after 2s
Supply chain / cargo-deny bans licenses sources (push) Failing after 2s
Supply chain / actionlint (push) Failing after 2s
Rust CI / cargo doc (push) Failing after 51m16s
Build binaries / Build (arm-musleabi) (push) Failing after 52m19s
Build binaries / Build (aarch64-musl) (push) Failing after 52m19s
Build binaries / Build (arm-musleabihf) (push) Failing after 11m33s
Build binaries / Build (armv7-musleabi) (push) Successful in 2m37s
Build binaries / Build (armv7-musleabihf) (push) Successful in 1m51s
Build binaries / Build (i686-musl) (push) Successful in 1m38s
Build binaries / Build (mips-musl) (push) Successful in 2m2s
Build binaries / Build (mips64-muslabi64) (push) Successful in 2m15s
Build binaries / Build (mips64el-muslabi64) (push) Successful in 2m28s
Build binaries / Build (mipsel-musl) (push) Successful in 2m23s
Build binaries / Build (riscv64gc-musl) (push) Successful in 1m59s
Build binaries / Build (x86_64-musl) (push) Successful in 1m50s
2026-10-14 12:50:36 +07:00
Nils Andreas Svee 4770b4fb5d docs(reflectors): bundle protocol-aware inventory and configuration examples
Replace the ICMP-only inventory with protocol-aware records, remove Mullvad DNS entries and omit misleading anycast countries. Document IRTT authentication and explicit TOML/UCI reflector configuration, including disabling file loading.
2026-10-14 12:50:29 +07:00
Nils Andreas Svee eaa20e79d2 feat(measurement): integrate IRTT and configurable reflector selection
Add protocol-aware reflector definitions, TOML/UCI lists, validation and environment overrides. Resolve and select endpoint-aware measurement streams, honor configured ICMP timing and socket routing, and retain partial-set reselection behavior from the standalone fixes.

Drive the managed IRTT task throughout its lifecycle, retry terminal targets without restarting healthy sessions, normalize blank HMAC keys and use effective RTT for latency fallback. Fold the reviewed configuration, resolution and measurement corrections into their implementation.
2026-10-14 12:50:29 +07:00
Nils Andreas Svee 41929875f7 feat(uci): support repeated sections and skipped fields
Allow structured lists to share the existing UCI configuration adapter while keeping collection fields out of scalar section mappings.
2026-10-14 12:50:28 +07:00
renovate Bot 8aa971920c chore(deps): update rust crate tokio to v1.53.3
Rust CI / cargo fmt (push) Successful in 15s
Build binaries / Build (arm-musleabi) (push) Successful in 1m41s
Build binaries / Build (aarch64-musl) (push) Successful in 1m42s
Rust CI / cargo clippy (push) Failing after 21s
Rust CI / cargo check (x86_64-unknown-linux-musl) (push) Failing after 8s
Rust CI / cargo check (x86_64-unknown-linux-gnu) (push) Failing after 20s
Supply chain / cargo-deny advisories (push) Failing after 2s
Rust CI / cargo test (x86_64-unknown-linux-musl) (push) Failing after 5s
Supply chain / cargo-deny bans licenses sources (push) Failing after 3s
Supply chain / actionlint (push) Failing after 2s
Rust CI / cargo test (x86_64-unknown-linux-gnu) (push) Failing after 27s
Rust CI / cargo doc (push) Failing after 22s
Build binaries / Build (armv7-musleabi) (push) Failing after 30m43s
Build binaries / Build (arm-musleabihf) (push) Failing after 30m44s
Build binaries / Build (armv7-musleabihf) (push) Successful in 1m47s
Build binaries / Build (i686-musl) (push) Successful in 1m48s
Build binaries / Build (mips64-muslabi64) (push) Successful in 2m2s
Build binaries / Build (mips-musl) (push) Successful in 2m5s
Build binaries / Build (mips64el-muslabi64) (push) Successful in 2m13s
Build binaries / Build (mipsel-musl) (push) Successful in 2m13s
Build binaries / Build (riscv64gc-musl) (push) Successful in 1m48s
Build binaries / Build (x86_64-musl) (push) Successful in 1m44s
2026-10-14 12:49:23 +07:00
Nils Andreas Svee 2efa0d30c2 fix(uci): gate schema generation behind UCI feature
Rust CI / cargo fmt (push) Successful in 10s
Rust CI / cargo clippy (push) Failing after 28s
Rust CI / cargo check (x86_64-unknown-linux-gnu) (push) Failing after 26s
Rust CI / cargo check (x86_64-unknown-linux-musl) (push) Failing after 6s
Rust CI / cargo test (x86_64-unknown-linux-musl) (push) Failing after 6s
Rust CI / cargo test (x86_64-unknown-linux-gnu) (push) Failing after 22s
Supply chain / cargo-deny advisories (push) Failing after 2s
Supply chain / cargo-deny bans licenses sources (push) Failing after 3s
Supply chain / actionlint (push) Failing after 5s
Rust CI / cargo doc (push) Failing after 27s
Build binaries / Build (arm-musleabi) (push) Successful in 1m45s
Build binaries / Build (aarch64-musl) (push) Successful in 1m49s
Build binaries / Build (armv7-musleabi) (push) Successful in 1m54s
Build binaries / Build (arm-musleabihf) (push) Successful in 1m55s
Build binaries / Build (armv7-musleabihf) (push) Successful in 2m34s
Build binaries / Build (i686-musl) (push) Successful in 2m34s
Build binaries / Build (mips-musl) (push) Successful in 2m5s
Build binaries / Build (mips64-muslabi64) (push) Successful in 2m5s
Build binaries / Build (mipsel-musl) (push) Successful in 2m10s
Build binaries / Build (mips64el-muslabi64) (push) Successful in 2m12s
Build binaries / Build (riscv64gc-musl) (push) Successful in 2m8s
Build binaries / Build (x86_64-musl) (push) Successful in 2m1s
2026-10-14 12:13:13 +07:00
Nils Andreas Svee f1a50af7d3 fix(reflectors): retain current peers when no candidates respond
Rust CI / cargo fmt (push) Successful in 22s
Rust CI / cargo check (x86_64-unknown-linux-gnu) (push) Failing after 37s
Rust CI / cargo clippy (push) Failing after 37s
Rust CI / cargo test (x86_64-unknown-linux-musl) (push) Failing after 12s
Rust CI / cargo check (x86_64-unknown-linux-musl) (push) Failing after 13s
Rust CI / cargo test (x86_64-unknown-linux-gnu) (push) Failing after 31s
Supply chain / cargo-deny advisories (push) Failing after 3s
Supply chain / cargo-deny bans licenses sources (push) Failing after 2s
Supply chain / actionlint (push) Failing after 3s
Rust CI / cargo doc (push) Failing after 32s
Build binaries / Build (arm-musleabi) (push) Successful in 2m16s
Build binaries / Build (aarch64-musl) (push) Failing after 24m1s
Build binaries / Build (arm-musleabihf) (push) Failing after 51m7s
Build binaries / Build (armv7-musleabihf) (push) Failing after 11m33s
Build binaries / Build (armv7-musleabi) (push) Failing after 11m33s
Build binaries / Build (i686-musl) (push) Successful in 2m6s
Build binaries / Build (mips-musl) (push) Successful in 2m10s
Build binaries / Build (mips64-muslabi64) (push) Successful in 2m5s
Build binaries / Build (mips64el-muslabi64) (push) Successful in 2m12s
Build binaries / Build (mipsel-musl) (push) Successful in 2m10s
Build binaries / Build (riscv64gc-musl) (push) Successful in 2m9s
Build binaries / Build (x86_64-musl) (push) Successful in 1m42s
Restore the pre-probe selection when evaluation finds no usable candidates. Preserve master’s existing selection of smaller candidate sets.
2026-10-14 11:58:07 +07:00
Nils Andreas Svee 5624746914 fix(ratecontroller): account for configured and partial reflector sets
Cap the required delta count at the active peer count using advanced_settings.num_reflectors. Keep requesting reselection when the active set is empty so recovery remains possible.
2026-10-14 11:58:07 +07:00
Nils Andreas Svee 2e24da4bf8 chore: remove unused clock and mutex helpers 2026-10-14 11:58:07 +07:00
9 changed files with 15 additions and 52 deletions

No files matched your search

Generated
+2 -2
View File
@@ -867,9 +867,9 @@ dependencies = [
[[package]]
name = "tokio"
version = "1.53.2"
version = "1.53.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e95f91fcc7a621e8b030f6aa23c71fe9838ae2fb4d8118b75602a328f5144044"
checksum = "ce3335fa71841cda333a58d7615b03901380ecf09d59b3296d21f8bbac0dde4e"
dependencies = [
"bytes",
"libc",
+2
View File
@@ -82,6 +82,7 @@ fn expand_uci_section(input: &DeriveInput) -> syn::Result<proc_macro2::TokenStre
let (impl_generics, type_generics, where_clause) = input.generics.split_for_impl();
Ok(quote! {
#[cfg(all(feature = "uci", unix))]
#[automatically_derived]
impl #impl_generics
crate::settings::uci_schema::UciSectionSchema
@@ -155,6 +156,7 @@ fn expand_uci_config(input: &DeriveInput) -> syn::Result<proc_macro2::TokenStrea
let (impl_generics, type_generics, where_clause) = input.generics.split_for_impl();
Ok(quote! {
#[cfg(all(feature = "uci", unix))]
#[automatically_derived]
impl #impl_generics
crate::settings::uci_schema::UciConfigSchema
+1 -3
View File
@@ -120,9 +120,7 @@ impl Controller {
icmp.push(IcmpBinding::new(stream, schedule))
}
#[cfg(feature = "irtt")]
MeasurementSource::Irtt => {
irtt.push(IrttBinding::new(stream, schedule, port, hmac))
}
MeasurementSource::Irtt => irtt.push(IrttBinding::new(stream, port, hmac)),
#[cfg(not(feature = "irtt"))]
MeasurementSource::Irtt => unreachable!("IRTT feature is checked before startup"),
_ => unreachable!("unsupported reflector measurement source"),
-1
View File
@@ -389,7 +389,6 @@ fn run(settings: &Settings) -> anyhow::Result<()> {
let (irtt_task, irtt_engine) = {
let _guard = rt.enter();
IrttEngine::new(
start_time,
Duration::from_secs_f64(settings.advanced_settings.tick_interval),
&settings.network,
measurement_tx,
+4 -22
View File
@@ -1,4 +1,4 @@
use std::{collections::HashMap, net::SocketAddr, time::Instant};
use std::{collections::HashMap, net::SocketAddr};
use flume::{Receiver, Sender};
use irtt_client::{
@@ -17,7 +17,7 @@ use tokio::sync::broadcast::error::RecvError;
use crate::SHUTDOWN;
use crate::measurement::model::{
MeasurementEvent, MeasurementLoss, MeasurementObservation, MeasurementStream,
MeasurementStreamId, OneWayClock, OneWayLatency, ProbeSchedule, SignedDuration,
MeasurementStreamId, OneWayClock, OneWayLatency, SignedDuration,
};
use crate::settings::NetworkSettings;
@@ -53,27 +53,13 @@ pub enum IrttError {
pub struct IrttBinding {
stream: MeasurementStream,
/// Retained for future hybrid-mode scheduling. IRTT currently uses the
/// global interval configured on its managed client.
#[allow(dead_code)]
schedule: ProbeSchedule,
port: u16,
hmac: Option<String>,
}
impl IrttBinding {
pub fn new(
stream: MeasurementStream,
schedule: ProbeSchedule,
port: u16,
hmac: Option<String>,
) -> Self {
Self {
stream,
schedule,
port,
hmac,
}
pub fn new(stream: MeasurementStream, port: u16, hmac: Option<String>) -> Self {
Self { stream, port, hmac }
}
}
@@ -83,15 +69,12 @@ pub struct IrttEngine {
bindings: HashMap<MeasurementStreamId, IrttBinding>,
targets: Vec<ManagedTargetConfig>,
origin: Instant,
binding_rx: Receiver<Vec<IrttBinding>>,
observation_tx: Sender<MeasurementEvent>,
}
impl IrttEngine {
pub fn new(
origin: Instant,
interval: std::time::Duration,
settings: &NetworkSettings,
observation_tx: Sender<MeasurementEvent>,
@@ -106,7 +89,6 @@ impl IrttEngine {
client: handle,
bindings: HashMap::new(),
targets: Vec::new(),
origin,
binding_rx,
observation_tx,
},
+4 -1
View File
@@ -492,7 +492,10 @@ impl<S: InterfaceStatsProvider, T: TrafficControlBackend> Ratecontroller<S, T> {
self.state_ul.deltas = up_deltas;
let minimum = usize::from(self.settings.reflectors.num_reflectors).min(reflectors.len());
if self.state_dl.deltas.len() < minimum || self.state_ul.deltas.len() < minimum {
if reflectors.is_empty()
|| self.state_dl.deltas.len() < minimum
|| self.state_ul.deltas.len() < minimum
{
// trigger reselection
warn!(
"Not enough delta values (D: {}, U: {}, need {}), triggering reselection",
+1 -3
View File
@@ -2,12 +2,10 @@
//
// SPDX-License-Identifier: MPL-2.0
use anyhow::{Context, bail};
use config::{Config, ConfigError, Environment};
use log::Level;
use serde::{Deserialize, Deserializer, de};
use std::fmt::{self, Display};
use std::net::IpAddr;
use std::str::FromStr;
use uci_derive::{UciConfig, UciSection};
@@ -17,6 +15,7 @@ use crate::settings::uci::UciSource;
#[cfg(all(feature = "uci", unix))]
pub mod uci;
#[cfg(all(feature = "uci", unix))]
pub(crate) mod uci_schema;
mod validation;
@@ -494,4 +493,3 @@ where
)),
}
}
-9
View File
@@ -14,16 +14,11 @@ pub trait Clock {
}
pub enum Realtime {}
pub enum Monotonic {}
impl Clock for Realtime {
const ID: ClockId = ClockId::Realtime;
}
impl Clock for Monotonic {
const ID: ClockId = ClockId::Monotonic;
}
pub struct ClockSample<C> {
time_s: u64,
time_ns: u64,
@@ -56,10 +51,6 @@ impl<C: Clock> ClockSample<C> {
pub fn as_secs_f64(&self) -> f64 {
self.time_s as f64 + self.time_ns as f64 / 1_000_000_000.0
}
pub fn to_milliseconds(&self) -> u64 {
(self.time_s * 1000) + (self.time_ns / 1000000)
}
}
impl ClockSample<Realtime> {
+1 -11
View File
@@ -3,20 +3,10 @@
// SPDX-License-Identifier: MPL-2.0
use anyhow::anyhow;
use std::sync::{Arc, Mutex, MutexGuard, RwLock, RwLockReadGuard, RwLockWriteGuard};
use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard};
pub type ArcRwLock<T> = Arc<RwLock<T>>;
pub trait MutexExt<T> {
fn lock_anyhow(&self) -> anyhow::Result<MutexGuard<'_, T>>;
}
impl<T> MutexExt<T> for Mutex<T> {
fn lock_anyhow(&self) -> anyhow::Result<MutexGuard<'_, T>> {
self.lock().map_err(|e| anyhow!("mutex poisoned: {e}"))
}
}
pub trait RwLockExt<T> {
fn read_anyhow(&self) -> anyhow::Result<RwLockReadGuard<'_, T>>;
fn write_anyhow(&self) -> anyhow::Result<RwLockWriteGuard<'_, T>>;