-
Notifications
You must be signed in to change notification settings - Fork 4
feat: introduce rtt_hints for opening paths #278
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -556,6 +556,7 @@ impl Connection { | |
| remote: SocketAddr, | ||
| initial_status: PathStatus, | ||
| now: Instant, | ||
| rtt_hint: Option<Duration>, | ||
| ) -> Result<(PathId, bool), PathError> { | ||
| match self | ||
| .paths | ||
|
|
@@ -564,7 +565,7 @@ impl Connection { | |
| { | ||
| Some((path_id, _state)) => Ok((*path_id, true)), | ||
| None => self | ||
| .open_path(remote, initial_status, now) | ||
| .open_path(remote, initial_status, now, rtt_hint) | ||
| .map(|id| (id, false)), | ||
| } | ||
| } | ||
|
|
@@ -578,6 +579,7 @@ impl Connection { | |
| remote: SocketAddr, | ||
| initial_status: PathStatus, | ||
| now: Instant, | ||
| rtt_hint: Option<Duration>, | ||
| ) -> Result<PathId, PathError> { | ||
| if !self.is_multipath_negotiated() { | ||
| return Err(PathError::MultipathNotNegotiated); | ||
|
|
@@ -608,7 +610,7 @@ impl Connection { | |
| return Err(PathError::RemoteCidsExhausted); | ||
| } | ||
|
|
||
| let path = self.ensure_path(path_id, remote, now, None); | ||
| let path = self.ensure_path(path_id, remote, now, None, rtt_hint); | ||
| path.status.local_update(initial_status); | ||
|
|
||
| Ok(path_id) | ||
|
|
@@ -828,6 +830,7 @@ impl Connection { | |
| remote: SocketAddr, | ||
| now: Instant, | ||
| pn: Option<u64>, | ||
| rtt_hint: Option<Duration>, | ||
| ) -> &mut PathData { | ||
| let vacant_entry = match self.paths.entry(path_id) { | ||
| btree_map::Entry::Vacant(vacant_entry) => vacant_entry, | ||
|
|
@@ -851,7 +854,14 @@ impl Connection { | |
| &self.config, | ||
| ); | ||
|
|
||
| let pto = self.ack_frequency.max_ack_delay_for_pto() + data.rtt.pto_base(); | ||
| let pto = match rtt_hint { | ||
| Some(rtt_hint) => rtt_hint, | ||
| None => { | ||
| // Fallback to the pessimistic calculation | ||
| // TODO: we could consider using known PTOs in this case | ||
| self.ack_frequency.max_ack_delay_for_pto() + data.rtt.pto_base() | ||
| } | ||
| }; | ||
| self.timers.set( | ||
| Timer::PerPath(path_id, PathTimer::PathOpen), | ||
| now + 3 * pto, | ||
|
|
@@ -3699,7 +3709,7 @@ impl Connection { | |
|
|
||
| if self.side().is_server() && !self.abandoned_paths.contains(&path_id) { | ||
| // Only the client is allowed to open paths | ||
| self.ensure_path(path_id, remote, now, number); | ||
| self.ensure_path(path_id, remote, now, number, None); | ||
| } | ||
| if self.paths.contains_key(&path_id) { | ||
| self.on_packet_authenticated( | ||
|
|
@@ -6262,10 +6272,14 @@ impl Connection { | |
| /// initiated, the previous one is cancelled, and paths that have not been opened are closed. | ||
| /// | ||
| /// Returns the server addresses that are now being probed. | ||
| pub fn initiate_nat_traversal_round( | ||
| pub fn initiate_nat_traversal_round<F>( | ||
| &mut self, | ||
| now: Instant, | ||
| ) -> Result<Vec<SocketAddr>, iroh_hp::Error> { | ||
| rtt_hints: F, | ||
| ) -> Result<Vec<SocketAddr>, iroh_hp::Error> | ||
| where | ||
| F: Fn(&SocketAddr) -> Option<Duration>, | ||
| { | ||
|
Comment on lines
+6275
to
+6282
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This gives you a lot of control in theory. But I'd have preferred to keep it simple with only a single RTT hint for all probes. This RTT would then be set to the worst RTT you expect to get. E.g. when we haven't hole-punched an IP path yet, then this should be set to the relay path's RTT, and if we have some IP paths already, then this should be set to the worst IP path's RTT.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. a single value seems bad imho, making it a lot less useful, as we might be using multiple transports between different probes |
||
| if self.state.is_closed() { | ||
| return Err(iroh_hp::Error::Closed); | ||
| } | ||
|
|
@@ -6314,7 +6328,8 @@ impl Connection { | |
| continue; | ||
| } | ||
| }; | ||
| match self.open_path_ensure(remote, PathStatus::Backup, now) { | ||
| let rtt_hint = rtt_hints(&remote); | ||
| match self.open_path_ensure(remote, PathStatus::Backup, now, rtt_hint) { | ||
| Ok((path_id, path_was_known)) if !path_was_known => { | ||
| path_ids.push(path_id); | ||
| probed_addresses.push(remote); | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That seems more correct to me...
We don't want to only change the PathOpen timer, we also want to change the time at which we resend path challenges, and change when we consider packets lost, etc.
Also, the PTO would actually be a different value in this case, because we make assumptions about variance, and add the max ACK delay. It surprises me that all of that would be skipped in your version.