Skip to content

Commit 07f0b3b

Browse files
committed
intf prio
1 parent 7085738 commit 07f0b3b

File tree

7 files changed

+489
-33
lines changed

7 files changed

+489
-33
lines changed

iroh/src/endpoint.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ impl Builder {
183183
insecure_skip_relay_cert_verify: self.insecure_skip_relay_cert_verify,
184184
#[cfg(any(test, feature = "test-utils"))]
185185
path_selection: self.path_selection,
186+
interface_priority: Default::default(),
186187
metrics,
187188
};
188189

iroh/src/magicsock.rs

Lines changed: 62 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ use crate::{
7979
net_report::{self, IfStateDetails, IpMappedAddresses, Report},
8080
};
8181

82+
mod interface_priority;
8283
mod metrics;
8384
mod node_map;
8485

@@ -87,6 +88,7 @@ pub(crate) mod transports;
8788
pub use node_map::Source;
8889

8990
pub use self::{
91+
interface_priority::InterfacePriority,
9092
metrics::Metrics,
9193
node_map::{ConnectionType, ControlMsg, DirectAddrInfo},
9294
};
@@ -157,6 +159,12 @@ pub(crate) struct Options {
157159
#[cfg(any(test, feature = "test-utils"))]
158160
pub(crate) path_selection: PathSelection,
159161

162+
/// Interface-based path prioritization configuration.
163+
///
164+
/// Allows preferring certain network interfaces over others when multiple paths exist.
165+
/// Useful for scenarios like preferring Ethernet over Wi-Fi.
166+
pub(crate) interface_priority: InterfacePriority,
167+
160168
pub(crate) metrics: EndpointMetrics,
161169
}
162170

@@ -685,7 +693,7 @@ impl MagicSock {
685693
// UDP
686694

687695
// Update the NodeMap and remap RecvMeta to the NodeIdMappedAddr.
688-
match self.node_map.receive_udp(*addr) {
696+
match self.node_map.receive_udp(*addr, quinn_meta.dst_ip) {
689697
None => {
690698
// Check if this address is mapped to an IpMappedAddr
691699
if let Some(ip_mapped_addr) =
@@ -1365,6 +1373,7 @@ impl Handle {
13651373
insecure_skip_relay_cert_verify,
13661374
#[cfg(any(test, feature = "test-utils"))]
13671375
path_selection,
1376+
interface_priority,
13681377
metrics,
13691378
} = opts;
13701379

@@ -1384,6 +1393,23 @@ impl Handle {
13841393
}
13851394
};
13861395

1396+
// Load interface priority from environment if not explicitly set
1397+
let interface_priority = if interface_priority.is_empty() {
1398+
match InterfacePriority::from_env() {
1399+
Ok(Some(priority)) => {
1400+
info!("Loaded interface priority from IROH_INTERFACE_PRIORITY");
1401+
priority
1402+
}
1403+
Ok(None) => InterfacePriority::default(),
1404+
Err(e) => {
1405+
warn!("Failed to parse IROH_INTERFACE_PRIORITY: {}", e);
1406+
InterfacePriority::default()
1407+
}
1408+
}
1409+
} else {
1410+
interface_priority
1411+
};
1412+
13871413
let addr_v4 = addr_v4.unwrap_or_else(|| SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 0));
13881414

13891415
#[cfg(not(wasm_browser))]
@@ -1397,13 +1423,7 @@ impl Handle {
13971423
let ipv6_reported = false;
13981424

13991425
// load the node data
1400-
let node_map = NodeMap::load_from_vec(
1401-
Vec::new(),
1402-
#[cfg(any(test, feature = "test-utils"))]
1403-
path_selection,
1404-
ipv6_reported,
1405-
&metrics.magicsock,
1406-
);
1426+
let node_addrs = node_map.unwrap_or_default();
14071427

14081428
let my_relay = Watchable::new(None);
14091429
let ipv6_reported = Arc::new(AtomicBool::new(ipv6_reported));
@@ -1430,6 +1450,35 @@ impl Handle {
14301450
#[cfg(wasm_browser)]
14311451
let transports = Transports::new(relay_transports);
14321452

1453+
// Create network monitor early, so we can build the interface map
1454+
let network_monitor = netmon::Monitor::new()
1455+
.await
1456+
.context(CreateNetmonMonitorSnafu)?;
1457+
1458+
// Build interface map from bind addresses and network state
1459+
#[cfg(not(wasm_browser))]
1460+
let ip_to_interface = {
1461+
let netmon_state = network_monitor.interface_state().get();
1462+
let bind_addrs = transports.ip_bind_addrs();
1463+
interface_priority::build_interface_map(&bind_addrs, &netmon_state)
1464+
};
1465+
#[cfg(wasm_browser)]
1466+
let ip_to_interface = Default::default();
1467+
1468+
// Create NodeMap with the interface map
1469+
let node_map = NodeMap::load_from_vec(
1470+
node_addrs,
1471+
#[cfg(any(test, feature = "test-utils"))]
1472+
path_selection,
1473+
interface_priority.clone(),
1474+
ip_to_interface,
1475+
#[cfg(not(wasm_browser))]
1476+
ipv6,
1477+
#[cfg(wasm_browser)]
1478+
false,
1479+
&metrics.magicsock,
1480+
);
1481+
14331482
let (disco, disco_receiver) = DiscoState::new(secret_encryption_key);
14341483

14351484
let msock = Arc::new(MagicSock {
@@ -1438,7 +1487,7 @@ impl Handle {
14381487
closed: AtomicBool::new(false),
14391488
disco,
14401489
actor_sender: actor_sender.clone(),
1441-
ipv6_reported,
1490+
ipv6_reported: ipv6_reported.clone(),
14421491
node_map,
14431492
ip_mapped_addrs: ip_mapped_addrs.clone(),
14441493
discovery,
@@ -1479,10 +1528,6 @@ impl Handle {
14791528
)
14801529
.context(CreateQuinnEndpointSnafu)?;
14811530

1482-
let network_monitor = netmon::Monitor::new()
1483-
.await
1484-
.context(CreateNetmonMonitorSnafu)?;
1485-
14861531
let qad_endpoint = endpoint.clone();
14871532

14881533
#[cfg(any(test, feature = "test-utils"))]
@@ -1528,6 +1573,7 @@ impl Handle {
15281573
);
15291574

15301575
let netmon_watcher = network_monitor.interface_state();
1576+
15311577
let actor = Actor {
15321578
msg_receiver: actor_receiver,
15331579
msock: msock.clone(),
@@ -2563,6 +2609,7 @@ mod tests {
25632609
addr_v6: None,
25642610
secret_key,
25652611
relay_map: RelayMap::empty(),
2612+
node_map: None,
25662613
discovery: Default::default(),
25672614
proxy_url: None,
25682615
dns_resolver: DnsResolver::new(),
@@ -2571,6 +2618,7 @@ mod tests {
25712618
insecure_skip_relay_cert_verify: false,
25722619
#[cfg(any(test, feature = "test-utils"))]
25732620
path_selection: PathSelection::default(),
2621+
interface_priority: Default::default(),
25742622
discovery_user_data: None,
25752623
metrics: Default::default(),
25762624
}
@@ -3109,6 +3157,7 @@ mod tests {
31093157
server_config,
31103158
insecure_skip_relay_cert_verify: false,
31113159
path_selection: PathSelection::default(),
3160+
interface_priority: Default::default(),
31123161
metrics: Default::default(),
31133162
};
31143163
let msock = MagicSock::spawn(opts).await?;

0 commit comments

Comments
 (0)