Author SHA1 Message Date
Nils Andreas Svee 1013f95d09 fix(irtt): retry terminal targets without restarting healthy sessions
Build binaries / Build (arm-musleabi) (push) Failing after 24m1s
Build binaries / Build (aarch64-musl) (push) Failing after 24m1s
Build binaries / Build (armv7-musleabi) (push) Failing after 11m33s
Build binaries / Build (arm-musleabihf) (push) Failing after 30m39s
Build binaries / Build (i686-musl) (push) Successful in 2m7s
Build binaries / Build (armv7-musleabihf) (push) Successful in 2m9s
Build binaries / Build (mips-musl) (push) Successful in 2m7s
Build binaries / Build (mips64-muslabi64) (push) Successful in 2m11s
Build binaries / Build (mips64el-muslabi64) (push) Successful in 2m11s
Build binaries / Build (mipsel-musl) (push) Successful in 2m15s
Build binaries / Build (riscv64gc-musl) (push) Successful in 1m42s
Build binaries / Build (x86_64-musl) (push) Successful in 2m0s
2026-10-14 11:12:50 +07:00
Nils Andreas Svee 441720811e fix(irtt): use effective RTT for latency fallback 2026-10-14 11:12:50 +07:00
Nils Andreas Svee 3eab999aa5 fix(irtt): treat blank HMAC keys as unauthenticated 2026-10-14 11:12:50 +07:00
Nils Andreas Svee 6bcd9fad0e fix(settings): allow UCI reflector file loading to be disabled 2026-10-14 11:12:50 +07:00
Nils Andreas Svee 030ceff88f fix(settings): accept numeric environment booleans 2026-10-14 11:12:33 +07:00
Nils Andreas Svee 4029ce763d fix(config): reject empty reflector host entries
Build binaries / Build (arm-musleabi) (push) Successful in 2m30s
Build binaries / Build (aarch64-musl) (push) Successful in 2m31s
Build binaries / Build (armv7-musleabi) (push) Successful in 1m44s
Build binaries / Build (arm-musleabihf) (push) Successful in 1m44s
Build binaries / Build (armv7-musleabihf) (push) Successful in 1m40s
Build binaries / Build (i686-musl) (push) Successful in 1m40s
Build binaries / Build (mips-musl) (push) Successful in 2m6s
Build binaries / Build (mips64-muslabi64) (push) Successful in 2m7s
Build binaries / Build (mips64el-muslabi64) (push) Successful in 2m20s
Build binaries / Build (mipsel-musl) (push) Successful in 2m21s
Build binaries / Build (x86_64-musl) (push) Successful in 1m47s
Build binaries / Build (riscv64gc-musl) (push) Successful in 1m54s
2026-10-14 01:34:51 +07:00
Nils Andreas Svee 69647e1ffe fix(reflectors): account for partial peer sets when requesting reselection 2026-10-14 01:34:40 +07:00
Nils Andreas Svee c6fc3a7fc9 fix(reflectors): retain responsive peers on partial reselection
Build binaries / Build (arm-musleabi) (push) Successful in 1m50s
Build binaries / Build (aarch64-musl) (push) Successful in 1m51s
Build binaries / Build (arm-musleabihf) (push) Successful in 1m53s
Build binaries / Build (armv7-musleabi) (push) Successful in 1m54s
Build binaries / Build (armv7-musleabihf) (push) Successful in 1m55s
Build binaries / Build (i686-musl) (push) Successful in 1m54s
Build binaries / Build (mips-musl) (push) Successful in 2m9s
Build binaries / Build (mips64-muslabi64) (push) Successful in 2m8s
Build binaries / Build (mips64el-muslabi64) (push) Successful in 2m6s
Build binaries / Build (mipsel-musl) (push) Successful in 2m5s
Build binaries / Build (x86_64-musl) (push) Successful in 1m52s
Build binaries / Build (riscv64gc-musl) (push) Successful in 1m52s
2026-10-14 01:23:51 +07:00
Nils Andreas Svee 51f0ae2e23 fix(config): reject reflector entries without protocols 2026-10-14 01:23:28 +07:00
Nils Andreas Svee 54d162f494 fix(config): parse reflector list environment overrides 2026-10-14 01:23:15 +07:00
Nils Andreas Svee faf10aa2fe fix(reflectors): allow unspecified countries through country filter
Build binaries / Build (arm-musleabi) (push) Successful in 1m50s
Build binaries / Build (aarch64-musl) (push) Successful in 1m52s
Build binaries / Build (armv7-musleabi) (push) Successful in 1m51s
Build binaries / Build (arm-musleabihf) (push) Successful in 1m51s
Build binaries / Build (i686-musl) (push) Successful in 1m48s
Build binaries / Build (armv7-musleabihf) (push) Successful in 1m49s
Build binaries / Build (mips-musl) (push) Successful in 2m4s
Build binaries / Build (mips64-muslabi64) (push) Successful in 2m5s
Build binaries / Build (mipsel-musl) (push) Successful in 2m6s
Build binaries / Build (mips64el-muslabi64) (push) Successful in 2m6s
Build binaries / Build (x86_64-musl) (push) Successful in 1m44s
Build binaries / Build (riscv64gc-musl) (push) Successful in 1m45s
2026-10-13 23:52:24 +07:00
Nils Andreas Svee 1f1e5d1d27 chore: remove mullvad dns reflectors + remove country for anycast ips
Build binaries / Build (arm-musleabi) (push) Successful in 1m45s
Build binaries / Build (aarch64-musl) (push) Successful in 1m48s
Build binaries / Build (armv7-musleabi) (push) Successful in 1m37s
Build binaries / Build (arm-musleabihf) (push) Successful in 1m37s
Build binaries / Build (i686-musl) (push) Successful in 1m42s
Build binaries / Build (armv7-musleabihf) (push) Successful in 1m43s
Build binaries / Build (mips-musl) (push) Successful in 2m26s
Build binaries / Build (mips64-muslabi64) (push) Successful in 2m27s
Build binaries / Build (mips64el-muslabi64) (push) Successful in 2m18s
Build binaries / Build (mipsel-musl) (push) Successful in 2m19s
Build binaries / Build (x86_64-musl) (push) Successful in 1m55s
Build binaries / Build (riscv64gc-musl) (push) Successful in 1m56s
2026-10-13 23:39:20 +07:00
Nils Andreas Svee 7fb744790d fix(reflectors): merge missing country metadata without startup conflicts
Build binaries / Build (aarch64-musl) (push) Successful in 1m54s
Build binaries / Build (arm-musleabi) (push) Successful in 1m54s
Build binaries / Build (arm-musleabihf) (push) Successful in 1m56s
Build binaries / Build (armv7-musleabi) (push) Successful in 1m56s
Build binaries / Build (armv7-musleabihf) (push) Successful in 1m56s
Build binaries / Build (i686-musl) (push) Successful in 1m55s
Build binaries / Build (mips64-muslabi64) (push) Successful in 2m0s
Build binaries / Build (mips-musl) (push) Successful in 2m3s
Build binaries / Build (mipsel-musl) (push) Successful in 2m9s
Build binaries / Build (mips64el-muslabi64) (push) Successful in 2m13s
Build binaries / Build (riscv64gc-musl) (push) Successful in 1m53s
Build binaries / Build (x86_64-musl) (push) Successful in 1m53s
2026-10-13 22:58:15 +07:00
Nils Andreas Svee cb4ae4d251 chore: update reflectors list to use new format 2026-10-13 22:56:25 +07:00
Nils Andreas Svee 93bfee0624 fix(irtt): honor measurement socket routing settings
Build binaries / Build (arm-musleabi) (push) Successful in 1m37s
Build binaries / Build (aarch64-musl) (push) Successful in 1m39s
Build binaries / Build (armv7-musleabi) (push) Successful in 1m44s
Build binaries / Build (arm-musleabihf) (push) Successful in 1m45s
Build binaries / Build (armv7-musleabihf) (push) Successful in 1m52s
Build binaries / Build (i686-musl) (push) Successful in 1m53s
Build binaries / Build (mips64-muslabi64) (push) Successful in 2m19s
Build binaries / Build (mips-musl) (push) Successful in 2m20s
Build binaries / Build (mips64el-muslabi64) (push) Successful in 2m12s
Build binaries / Build (mipsel-musl) (push) Successful in 2m13s
Build binaries / Build (x86_64-musl) (push) Successful in 1m48s
Build binaries / Build (riscv64gc-musl) (push) Successful in 1m50s
2026-10-13 22:03:09 +07:00
Nils Andreas Svee 80b39da9de fix(ratecontroller): use the configured reflector count for reselection 2026-10-13 22:02:58 +07:00
Nils Andreas Svee f8691c5189 fix(reflectors): reject conflicting resolved endpoints
Build binaries / Build (aarch64-musl) (push) Successful in 2m16s
Build binaries / Build (arm-musleabi) (push) Successful in 2m48s
Build binaries / Build (arm-musleabihf) (push) Successful in 2m6s
Build binaries / Build (armv7-musleabi) (push) Successful in 2m8s
Build binaries / Build (armv7-musleabihf) (push) Successful in 2m29s
Build binaries / Build (i686-musl) (push) Successful in 2m34s
Build binaries / Build (mips-musl) (push) Successful in 1m57s
Build binaries / Build (mips64-muslabi64) (push) Successful in 1m58s
Build binaries / Build (mips64el-muslabi64) (push) Successful in 2m0s
Build binaries / Build (mipsel-musl) (push) Successful in 1m53s
Build binaries / Build (riscv64gc-musl) (push) Successful in 2m10s
Build binaries / Build (x86_64-musl) (push) Successful in 2m41s
Deduplicate compatible definitions and reject conflicting metadata or authentication within each list and across bootstrap and pool entries. Treat hostname aliases, protocol ordering, country-code case, and omitted default ports consistently.
2026-10-13 21:24:05 +07:00
Nils Andreas Svee a073a9d049 fix(reflectors): tolerate individual DNS resolution failures
Log and skip unresolved reflectors so startup can proceed with usable endpoints. Report an error when none remain for the selected protocol.
2026-10-13 21:24:05 +07:00
Nils Andreas Svee 78bcb7886a fix(controller): honor the configured ICMP probe interval
Use advanced_settings.tick_interval for Controller schedules so ICMP probe pacing follows the configured measurement cadence.
2026-10-13 21:24:05 +07:00
Nils Andreas Svee de77e5a281 feat(measurement): add configurable IRTT reflector measurements
Support optional IRTT measurements alongside ICMP with CSV and inline reflector definitions, repeated UCI registration, authentication, and endpoint-specific stream tracking.

Keep the managed driver running during target acknowledgements and stop and join it on event-loop exits. Carry stream identity through baselines, selection, and rate control so endpoints sharing an IP remain distinct.
2026-10-13 21:24:05 +07:00
Nils Andreas Svee 76a7e14835 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-13 21:24:04 +07:00
10 changed files with 53 additions and 16 deletions

No files matched your search

+1 -1
View File
@@ -50,7 +50,7 @@ jobs:
echo "exit_code=${clippy_status}" >> "$GITHUB_OUTPUT"
exit 0
- name: Upload Clippy SARIF
uses: github/codeql-action/upload-sarif@6f2ac81f5cd81fe351a197ba0b00d91d03cd2aee # v4
uses: github/codeql-action/upload-sarif@24c54180a607b1449ed407dd24f251e4e9147c8d # v4
if: always()
with:
sarif_file: rust-clippy-results.sarif
Generated
+2 -2
View File
@@ -867,9 +867,9 @@ dependencies = [
[[package]]
name = "tokio"
version = "1.53.3"
version = "1.53.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce3335fa71841cda333a58d7615b03901380ecf09d59b3296d21f8bbac0dde4e"
checksum = "e95f91fcc7a621e8b030f6aa23c71fe9838ae2fb4d8118b75602a328f5144044"
dependencies = [
"bytes",
"libc",
-2
View File
@@ -82,7 +82,6 @@ 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
@@ -156,7 +155,6 @@ 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
+3 -1
View File
@@ -120,7 +120,9 @@ impl Controller {
icmp.push(IcmpBinding::new(stream, schedule))
}
#[cfg(feature = "irtt")]
MeasurementSource::Irtt => irtt.push(IrttBinding::new(stream, port, hmac)),
MeasurementSource::Irtt => {
irtt.push(IrttBinding::new(stream, schedule, port, hmac))
}
#[cfg(not(feature = "irtt"))]
MeasurementSource::Irtt => unreachable!("IRTT feature is checked before startup"),
_ => unreachable!("unsupported reflector measurement source"),
+1
View File
@@ -389,6 +389,7 @@ 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,
+22 -4
View File
@@ -1,4 +1,4 @@
use std::{collections::HashMap, net::SocketAddr};
use std::{collections::HashMap, net::SocketAddr, time::Instant};
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, SignedDuration,
MeasurementStreamId, OneWayClock, OneWayLatency, ProbeSchedule, SignedDuration,
};
use crate::settings::NetworkSettings;
@@ -53,13 +53,27 @@ 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, port: u16, hmac: Option<String>) -> Self {
Self { stream, port, hmac }
pub fn new(
stream: MeasurementStream,
schedule: ProbeSchedule,
port: u16,
hmac: Option<String>,
) -> Self {
Self {
stream,
schedule,
port,
hmac,
}
}
}
@@ -69,12 +83,15 @@ 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>,
@@ -89,6 +106,7 @@ impl IrttEngine {
client: handle,
bindings: HashMap::new(),
targets: Vec::new(),
origin,
binding_rx,
observation_tx,
},
+1 -4
View File
@@ -492,10 +492,7 @@ 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 reflectors.is_empty()
|| self.state_dl.deltas.len() < minimum
|| self.state_ul.deltas.len() < minimum
{
if self.state_dl.deltas.len() < minimum || self.state_ul.deltas.len() < minimum {
// trigger reselection
warn!(
"Not enough delta values (D: {}, U: {}, need {}), triggering reselection",
+3 -1
View File
@@ -2,10 +2,12 @@
//
// 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};
@@ -15,7 +17,6 @@ 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;
@@ -493,3 +494,4 @@ where
)),
}
}
+9
View File
@@ -14,11 +14,16 @@ 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,
@@ -51,6 +56,10 @@ 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> {
+11 -1
View File
@@ -3,10 +3,20 @@
// SPDX-License-Identifier: MPL-2.0
use anyhow::anyhow;
use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard};
use std::sync::{Arc, Mutex, MutexGuard, 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>>;