Skip to content

Commit 738f8bf

Browse files
committed
intf prio
1 parent a6e63a8 commit 738f8bf

File tree

7 files changed

+488
-34
lines changed

7 files changed

+488
-34
lines changed

iroh/src/endpoint.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ impl Builder {
206206
insecure_skip_relay_cert_verify: self.insecure_skip_relay_cert_verify,
207207
#[cfg(any(test, feature = "test-utils"))]
208208
path_selection: self.path_selection,
209+
interface_priority: Default::default(),
209210
metrics,
210211
};
211212

iroh/src/magicsock.rs

Lines changed: 61 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ use crate::{
7777
net_report::{self, IfStateDetails, IpMappedAddresses, Report},
7878
};
7979

80+
mod interface_priority;
8081
mod metrics;
8182
mod node_map;
8283

@@ -85,6 +86,7 @@ pub(crate) mod transports;
8586
pub use node_map::Source;
8687

8788
pub use self::{
89+
interface_priority::InterfacePriority,
8890
metrics::Metrics,
8991
node_map::{ConnectionType, ControlMsg, DirectAddrInfo, RemoteInfo},
9092
};
@@ -158,6 +160,12 @@ pub(crate) struct Options {
158160
#[cfg(any(test, feature = "test-utils"))]
159161
pub(crate) path_selection: PathSelection,
160162

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

@@ -688,7 +696,7 @@ impl MagicSock {
688696
// UDP
689697

690698
// Update the NodeMap and remap RecvMeta to the NodeIdMappedAddr.
691-
match self.node_map.receive_udp(*addr) {
699+
match self.node_map.receive_udp(*addr, quinn_meta.dst_ip) {
692700
None => {
693701
// Check if this address is mapped to an IpMappedAddr
694702
if let Some(ip_mapped_addr) =
@@ -1367,9 +1375,27 @@ impl Handle {
13671375
insecure_skip_relay_cert_verify,
13681376
#[cfg(any(test, feature = "test-utils"))]
13691377
path_selection,
1378+
interface_priority,
13701379
metrics,
13711380
} = opts;
13721381

1382+
// Load interface priority from environment if not explicitly set
1383+
let interface_priority = if interface_priority.is_empty() {
1384+
match InterfacePriority::from_env() {
1385+
Ok(Some(priority)) => {
1386+
info!("Loaded interface priority from IROH_INTERFACE_PRIORITY");
1387+
priority
1388+
}
1389+
Ok(None) => InterfacePriority::default(),
1390+
Err(e) => {
1391+
warn!("Failed to parse IROH_INTERFACE_PRIORITY: {}", e);
1392+
InterfacePriority::default()
1393+
}
1394+
}
1395+
} else {
1396+
interface_priority
1397+
};
1398+
13731399
let addr_v4 = addr_v4.unwrap_or_else(|| SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 0));
13741400

13751401
#[cfg(not(wasm_browser))]
@@ -1383,14 +1409,7 @@ impl Handle {
13831409
let ipv6_reported = false;
13841410

13851411
// load the node data
1386-
let node_map = node_map.unwrap_or_default();
1387-
let node_map = NodeMap::load_from_vec(
1388-
node_map,
1389-
#[cfg(any(test, feature = "test-utils"))]
1390-
path_selection,
1391-
ipv6_reported,
1392-
&metrics.magicsock,
1393-
);
1412+
let node_addrs = node_map.unwrap_or_default();
13941413

13951414
let my_relay = Watchable::new(None);
13961415
let ipv6_reported = Arc::new(AtomicBool::new(ipv6_reported));
@@ -1417,6 +1436,35 @@ impl Handle {
14171436
#[cfg(wasm_browser)]
14181437
let transports = Transports::new(relay_transports);
14191438

1439+
// Create network monitor early, so we can build the interface map
1440+
let network_monitor = netmon::Monitor::new()
1441+
.await
1442+
.context(CreateNetmonMonitorSnafu)?;
1443+
1444+
// Build interface map from bind addresses and network state
1445+
#[cfg(not(wasm_browser))]
1446+
let ip_to_interface = {
1447+
let netmon_state = network_monitor.interface_state().get();
1448+
let bind_addrs = transports.ip_bind_addrs();
1449+
interface_priority::build_interface_map(&bind_addrs, &netmon_state)
1450+
};
1451+
#[cfg(wasm_browser)]
1452+
let ip_to_interface = Default::default();
1453+
1454+
// Create NodeMap with the interface map
1455+
let node_map = NodeMap::load_from_vec(
1456+
node_addrs,
1457+
#[cfg(any(test, feature = "test-utils"))]
1458+
path_selection,
1459+
interface_priority.clone(),
1460+
ip_to_interface,
1461+
#[cfg(not(wasm_browser))]
1462+
ipv6,
1463+
#[cfg(wasm_browser)]
1464+
false,
1465+
&metrics.magicsock,
1466+
);
1467+
14201468
let (disco, disco_receiver) = DiscoState::new(secret_encryption_key);
14211469

14221470
let msock = Arc::new(MagicSock {
@@ -1425,7 +1473,7 @@ impl Handle {
14251473
closed: AtomicBool::new(false),
14261474
disco,
14271475
actor_sender: actor_sender.clone(),
1428-
ipv6_reported,
1476+
ipv6_reported: ipv6_reported.clone(),
14291477
node_map,
14301478
ip_mapped_addrs: ip_mapped_addrs.clone(),
14311479
discovery,
@@ -1467,10 +1515,6 @@ impl Handle {
14671515
)
14681516
.context(CreateQuinnEndpointSnafu)?;
14691517

1470-
let network_monitor = netmon::Monitor::new()
1471-
.await
1472-
.context(CreateNetmonMonitorSnafu)?;
1473-
14741518
let qad_endpoint = endpoint.clone();
14751519

14761520
#[cfg(any(test, feature = "test-utils"))]
@@ -1516,6 +1560,7 @@ impl Handle {
15161560
);
15171561

15181562
let netmon_watcher = network_monitor.interface_state();
1563+
15191564
let actor = Actor {
15201565
msg_receiver: actor_receiver,
15211566
msock: msock.clone(),
@@ -2589,6 +2634,7 @@ mod tests {
25892634
insecure_skip_relay_cert_verify: false,
25902635
#[cfg(any(test, feature = "test-utils"))]
25912636
path_selection: PathSelection::default(),
2637+
interface_priority: Default::default(),
25922638
discovery_user_data: None,
25932639
metrics: Default::default(),
25942640
}
@@ -3121,6 +3167,7 @@ mod tests {
31213167
server_config,
31223168
insecure_skip_relay_cert_verify: false,
31233169
path_selection: PathSelection::default(),
3170+
interface_priority: Default::default(),
31243171
metrics: Default::default(),
31253172
};
31263173
let msock = MagicSock::spawn(opts).await?;

0 commit comments

Comments
 (0)