Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions lib/poller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub struct Poller<'poller> {
poller: polling::Poller,
events: polling::Events,
timeout: Duration,
last_periodic_tick: coarsetime::Instant,
vm_fd: BorrowedFd<'poller>,
host_fd: BorrowedFd<'poller>,
control_fd: Option<BorrowedFd<'poller>>,
Expand Down Expand Up @@ -37,6 +38,7 @@ impl Poller<'_> {
poller,
events: polling::Events::new(),
timeout,
last_periodic_tick: coarsetime::Instant::recent(),
vm_fd: unsafe { BorrowedFd::borrow_raw(vm_fd) },
host_fd: unsafe { BorrowedFd::borrow_raw(host_fd) },
control_fd: control_fd.map(|fd| unsafe { BorrowedFd::borrow_raw(fd) }),
Expand Down Expand Up @@ -94,6 +96,16 @@ impl Poller<'_> {
Ok((vm_readable, host_readable, interrupt))
}

pub fn periodic_tick_due(&mut self) -> bool {
let due = self.last_periodic_tick.elapsed_since_recent() >= self.timeout.into();

if due {
self.last_periodic_tick = coarsetime::Instant::recent();
}

due
}

pub fn remove_control(&mut self) -> Result<()> {
if let Some(control_fd) = self.control_fd.take() {
self.poller.delete(control_fd)?;
Expand Down
14 changes: 7 additions & 7 deletions lib/proxy/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,6 @@ impl Proxy<'_> {
loop {
let (vm_readable, host_readable, interrupt) = self.poller.wait()?;

// kqueue does not report peer disconnects for Unix datagram sockets.
if !self.vm.is_connected()? {
return Ok(());
}

// Update coarse time for DHCP snooping and flows
coarsetime::Instant::update();

Expand All @@ -133,8 +128,13 @@ impl Proxy<'_> {
return Ok(());
}

// Timeout
if !vm_readable && !host_readable && !interrupt {
// Periodic maintenance
if self.poller.periodic_tick_due() {
// kqueue(2) does not report peer disconnects for Unix datagram sockets
if !self.vm.is_connected()? {
return Ok(());
}

self.port_forwarder
.tick(&mut self.host, self.dhcp_snooper.lease());
Comment on lines +132 to 139

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Run periodic maintenance inside unbounded drain loops

When VM or host traffic arrives continuously enough that read_from_vm never observes WouldBlock, or read_from_host never observes VmnetReadNothing, these unbounded drain loops never return to this check. Since this remains the only port_forwarder.tick call in the repository, forwarding installation, updates, and lease-expiry cleanup can still be postponed indefinitely under the sustained-traffic condition this change is intended to handle; check the deadline while draining packets or otherwise bound each drain iteration.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's handle this separately in #199.

Again, this seems out-of-scope because this PR didn't introduce this issue in the first place.

}
Expand Down