Skip to content

Commit 8092b80

Browse files
committed
Only mark timers to update
Timers are updated on every single packet call, but their accuracy is limited to 250ms where currentTime is updated. So just mark timers to update, and update them only once in update_timers.
1 parent db16cad commit 8092b80

File tree

2 files changed

+103
-13
lines changed

2 files changed

+103
-13
lines changed

neptun/src/noise/mod.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -276,10 +276,10 @@ impl Tunn {
276276
if let Some(ref session) = self.sessions[current % N_SESSIONS] {
277277
// Send the packet using an established session
278278
let packet = session.format_packet_data(src, dst);
279-
self.timer_tick(TimerName::TimeLastPacketSent);
279+
self.mark_timer_to_update(TimerName::TimeLastPacketSent);
280280
// Exclude Keepalive packets from timer update.
281281
if !src.is_empty() {
282-
self.timer_tick(TimerName::TimeLastDataPacketSent);
282+
self.mark_timer_to_update(TimerName::TimeLastDataPacketSent);
283283
}
284284
self.tx_bytes += packet.len();
285285
return TunnResult::WriteToNetwork(packet);
@@ -365,8 +365,8 @@ impl Tunn {
365365
let index = session.local_index();
366366
self.sessions[index % N_SESSIONS] = Some(session);
367367

368-
self.timer_tick(TimerName::TimeLastPacketReceived);
369-
self.timer_tick(TimerName::TimeLastPacketSent);
368+
self.mark_timer_to_update(TimerName::TimeLastPacketReceived);
369+
self.mark_timer_to_update(TimerName::TimeLastPacketSent);
370370
self.timer_tick_session_established(false, index); // New session established, we are not the initiator
371371

372372
tracing::debug!(message = "Sending handshake_response", local_idx = index);
@@ -399,7 +399,7 @@ impl Tunn {
399399
let index = l_idx % N_SESSIONS;
400400
self.sessions[index] = Some(session);
401401

402-
self.timer_tick(TimerName::TimeLastPacketReceived);
402+
self.mark_timer_to_update(TimerName::TimeLastPacketReceived);
403403
self.timer_tick_session_established(true, index); // New session established, we are the initiator
404404
self.set_current_session(l_idx);
405405

@@ -424,8 +424,8 @@ impl Tunn {
424424
// Increase the rx_bytes accordingly
425425
self.rx_bytes += COOKIE_REPLY_SZ;
426426

427-
self.timer_tick(TimerName::TimeLastPacketReceived);
428-
self.timer_tick(TimerName::TimeCookieReceived);
427+
self.mark_timer_to_update(TimerName::TimeLastPacketReceived);
428+
self.mark_timer_to_update(TimerName::TimeCookieReceived);
429429

430430
tracing::debug!("Did set cookie");
431431

@@ -469,7 +469,7 @@ impl Tunn {
469469

470470
self.set_current_session(r_idx);
471471

472-
self.timer_tick(TimerName::TimeLastPacketReceived);
472+
self.mark_timer_to_update(TimerName::TimeLastPacketReceived);
473473

474474
Ok(self.validate_decapsulated_packet(decapsulated_packet))
475475
}
@@ -496,9 +496,9 @@ impl Tunn {
496496
tracing::debug!("Sending handshake_initiation");
497497

498498
if starting_new_handshake {
499-
self.timer_tick(TimerName::TimeLastHandshakeStarted);
499+
self.mark_timer_to_update(TimerName::TimeLastHandshakeStarted);
500500
}
501-
self.timer_tick(TimerName::TimeLastPacketSent);
501+
self.mark_timer_to_update(TimerName::TimeLastPacketSent);
502502
self.tx_bytes += packet.len();
503503

504504
TunnResult::WriteToNetwork(packet)
@@ -548,7 +548,7 @@ impl Tunn {
548548
return TunnResult::Err(WireGuardError::InvalidPacket);
549549
}
550550

551-
self.timer_tick(TimerName::TimeLastDataPacketReceived);
551+
self.mark_timer_to_update(TimerName::TimeLastDataPacketReceived);
552552
self.rx_bytes += message_data_len(computed_len);
553553

554554
match src_ip_address {

neptun/src/noise/timers.rs

Lines changed: 92 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use super::errors::WireGuardError;
66
use crate::noise::{safe_duration::SafeDuration as Duration, Tunn, TunnResult};
77
use std::mem;
88
use std::ops::{Index, IndexMut};
9+
use std::sync::atomic::AtomicU16;
910
use std::time::SystemTime;
1011

1112
#[cfg(feature = "mock-instant")]
@@ -42,7 +43,7 @@ pub(crate) const REKEY_TIMEOUT: Duration = Duration::from_secs(5);
4243
const KEEPALIVE_TIMEOUT: Duration = Duration::from_secs(10);
4344
const COOKIE_EXPIRATION_TIME: Duration = Duration::from_secs(120);
4445

45-
#[derive(Debug)]
46+
#[derive(Debug, Clone, Copy)]
4647
pub enum TimerName {
4748
/// Current time, updated each call to `update_timers`
4849
TimeCurrent,
@@ -65,6 +66,20 @@ pub enum TimerName {
6566
Top,
6667
}
6768

69+
impl TimerName {
70+
pub const VALUES: [Self; TimerName::Top as usize] = [
71+
Self::TimeCurrent,
72+
Self::TimeSessionEstablished,
73+
Self::TimeLastHandshakeStarted,
74+
Self::TimeLastPacketReceived,
75+
Self::TimeLastPacketSent,
76+
Self::TimeLastDataPacketReceived,
77+
Self::TimeLastDataPacketSent,
78+
Self::TimeCookieReceived,
79+
Self::TimePersistentKeepalive,
80+
];
81+
}
82+
6883
use self::TimerName::*;
6984

7085
#[derive(Debug)]
@@ -82,6 +97,7 @@ pub struct Timers {
8297
persistent_keepalive: usize,
8398
/// Should this timer call reset rr function (if not a shared rr instance)
8499
pub(super) should_reset_rr: bool,
100+
timers_to_update_mask: AtomicU16,
85101
}
86102

87103
impl Timers {
@@ -95,6 +111,7 @@ impl Timers {
95111
want_handshake_since: Default::default(),
96112
persistent_keepalive: usize::from(persistent_keepalive.unwrap_or(0)),
97113
should_reset_rr: reset_rr,
114+
timers_to_update_mask: Default::default(),
98115
}
99116
}
100117

@@ -128,7 +145,13 @@ impl IndexMut<TimerName> for Timers {
128145
}
129146

130147
impl Tunn {
131-
pub(super) fn timer_tick(&mut self, timer_name: TimerName) {
148+
pub(super) fn mark_timer_to_update(&self, timer_name: TimerName) {
149+
self.timers
150+
.timers_to_update_mask
151+
.fetch_or(1 << timer_name as u16, std::sync::atomic::Ordering::Relaxed);
152+
}
153+
154+
fn timer_tick(&mut self, timer_name: TimerName) {
132155
let time = self.timers[TimeCurrent];
133156
match timer_name {
134157
TimeLastPacketReceived => {
@@ -207,6 +230,21 @@ impl Tunn {
207230
let now = time.duration_since(self.timers.time_started).into();
208231
self.timers[TimeCurrent] = now;
209232

233+
// Check which timers to update, and update them
234+
let timer_mask = self
235+
.timers
236+
.timers_to_update_mask
237+
.load(std::sync::atomic::Ordering::Relaxed);
238+
for timer_name in TimerName::VALUES {
239+
if (timer_mask & (1 << (timer_name as u16))) != 0 {
240+
self.timer_tick(timer_name);
241+
}
242+
}
243+
// Reset all marked bits
244+
self.timers
245+
.timers_to_update_mask
246+
.store(0, std::sync::atomic::Ordering::Relaxed);
247+
210248
self.update_session_timers(now);
211249

212250
// Load timers only once:
@@ -380,3 +418,55 @@ impl Tunn {
380418
self.timers.persistent_keepalive = keepalive as usize;
381419
}
382420
}
421+
422+
#[cfg(test)]
423+
mod tests {
424+
use rand::RngCore;
425+
use rand_core::OsRng;
426+
427+
use crate::noise::{safe_duration::SafeDuration, Tunn};
428+
429+
use super::TimerName;
430+
431+
#[test]
432+
fn create_two_tuns() {
433+
let my_secret_key = x25519_dalek::StaticSecret::random_from_rng(OsRng);
434+
let my_idx = OsRng.next_u32();
435+
436+
let their_secret_key = x25519_dalek::StaticSecret::random_from_rng(OsRng);
437+
let their_public_key = x25519_dalek::PublicKey::from(&their_secret_key);
438+
439+
let mut my_tun =
440+
Tunn::new(my_secret_key, their_public_key, None, None, my_idx, None).unwrap();
441+
442+
// Mark timers to update
443+
my_tun.mark_timer_to_update(super::TimerName::TimeLastDataPacketSent);
444+
my_tun.mark_timer_to_update(super::TimerName::TimeLastDataPacketReceived);
445+
my_tun.mark_timer_to_update(super::TimerName::TimePersistentKeepalive);
446+
447+
// Update timers
448+
my_tun.update_timers(&mut [0]);
449+
450+
// Only those timers marked should be udpated
451+
assert!(!my_tun.timers[TimerName::TimeLastDataPacketSent].is_zero());
452+
assert!(!my_tun.timers[TimerName::TimeLastDataPacketReceived].is_zero());
453+
assert!(!my_tun.timers[TimerName::TimePersistentKeepalive].is_zero());
454+
455+
// Unmarked timers should still be 0
456+
assert!(my_tun.timers[TimerName::TimeCookieReceived].is_zero());
457+
assert!(my_tun.timers[TimerName::TimeLastHandshakeStarted].is_zero());
458+
assert!(my_tun.timers[TimerName::TimeLastPacketReceived].is_zero());
459+
460+
// Reset the timers
461+
my_tun.timers[TimerName::TimeLastDataPacketSent] = SafeDuration::from_millis(0);
462+
my_tun.timers[TimerName::TimeLastDataPacketReceived] = SafeDuration::from_millis(0);
463+
my_tun.timers[TimerName::TimePersistentKeepalive] = SafeDuration::from_millis(0);
464+
465+
my_tun.update_timers(&mut [0]);
466+
467+
// Now the timers should not update
468+
assert!(my_tun.timers[TimerName::TimeLastDataPacketSent].is_zero());
469+
assert!(my_tun.timers[TimerName::TimeLastDataPacketReceived].is_zero());
470+
assert!(my_tun.timers[TimerName::TimePersistentKeepalive].is_zero());
471+
}
472+
}

0 commit comments

Comments
 (0)