Skip to content

Commit 53caf70

Browse files
authored
Merge pull request #954 from quartiq/issue/848/infinite-poll
Limiting the number of poll loops to prevent DoS events
2 parents 7b125ef + 8c2cef1 commit 53caf70

File tree

2 files changed

+64
-69
lines changed

2 files changed

+64
-69
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
## [Unreleased]
88

9-
No unreleased changes yet.
9+
### Changed
10+
- iface: The `poll` function now only performs a single cycle of processing sockets ([#954](https://github.com/smoltcp-rs/smoltcp/pull/954))
1011

1112
## [0.11.0] - 2023-12-23
1213

src/iface/interface/mod.rs

Lines changed: 62 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,13 @@ impl Interface {
396396
/// This function returns a boolean value indicating whether any packets were
397397
/// processed or emitted, and thus, whether the readiness of any socket might
398398
/// have changed.
399+
///
400+
/// # Note
401+
/// This function performs a bounded amount of work per call to avoid
402+
/// starving other tasks of CPU time. If it returns true, there may still be
403+
/// packets to be received or transmitted. Depending on system design,
404+
/// calling this function in a loop may cause a denial of service if
405+
/// packets cannot be processed faster than they arrive.
399406
pub fn poll<D>(
400407
&mut self,
401408
timestamp: Instant,
@@ -429,23 +436,12 @@ impl Interface {
429436
}
430437
}
431438

432-
let mut readiness_may_have_changed = false;
433-
434-
loop {
435-
let mut did_something = false;
436-
did_something |= self.socket_ingress(device, sockets);
437-
did_something |= self.socket_egress(device, sockets);
438-
439-
#[cfg(feature = "proto-igmp")]
440-
{
441-
did_something |= self.igmp_egress(device);
442-
}
439+
let mut readiness_may_have_changed = self.socket_ingress(device, sockets);
440+
readiness_may_have_changed |= self.socket_egress(device, sockets);
443441

444-
if did_something {
445-
readiness_may_have_changed = true;
446-
} else {
447-
break;
448-
}
442+
#[cfg(feature = "proto-igmp")]
443+
{
444+
readiness_may_have_changed |= self.igmp_egress(device);
449445
}
450446

451447
readiness_may_have_changed
@@ -507,67 +503,65 @@ impl Interface {
507503
{
508504
let mut processed_any = false;
509505

510-
while let Some((rx_token, tx_token)) = device.receive(self.inner.now) {
511-
let rx_meta = rx_token.meta();
512-
rx_token.consume(|frame| {
513-
if frame.is_empty() {
514-
return;
515-
}
506+
let Some((rx_token, tx_token)) = device.receive(self.inner.now) else {
507+
return processed_any;
508+
};
516509

517-
match self.inner.caps.medium {
518-
#[cfg(feature = "medium-ethernet")]
519-
Medium::Ethernet => {
520-
if let Some(packet) = self.inner.process_ethernet(
521-
sockets,
522-
rx_meta,
523-
frame,
524-
&mut self.fragments,
525-
) {
526-
if let Err(err) =
527-
self.inner.dispatch(tx_token, packet, &mut self.fragmenter)
528-
{
529-
net_debug!("Failed to send response: {:?}", err);
530-
}
510+
let rx_meta = rx_token.meta();
511+
rx_token.consume(|frame| {
512+
if frame.is_empty() {
513+
return;
514+
}
515+
516+
match self.inner.caps.medium {
517+
#[cfg(feature = "medium-ethernet")]
518+
Medium::Ethernet => {
519+
if let Some(packet) =
520+
self.inner
521+
.process_ethernet(sockets, rx_meta, frame, &mut self.fragments)
522+
{
523+
if let Err(err) =
524+
self.inner.dispatch(tx_token, packet, &mut self.fragmenter)
525+
{
526+
net_debug!("Failed to send response: {:?}", err);
531527
}
532528
}
533-
#[cfg(feature = "medium-ip")]
534-
Medium::Ip => {
535-
if let Some(packet) =
536-
self.inner
537-
.process_ip(sockets, rx_meta, frame, &mut self.fragments)
538-
{
539-
if let Err(err) = self.inner.dispatch_ip(
540-
tx_token,
541-
PacketMeta::default(),
542-
packet,
543-
&mut self.fragmenter,
544-
) {
545-
net_debug!("Failed to send response: {:?}", err);
546-
}
529+
}
530+
#[cfg(feature = "medium-ip")]
531+
Medium::Ip => {
532+
if let Some(packet) =
533+
self.inner
534+
.process_ip(sockets, rx_meta, frame, &mut self.fragments)
535+
{
536+
if let Err(err) = self.inner.dispatch_ip(
537+
tx_token,
538+
PacketMeta::default(),
539+
packet,
540+
&mut self.fragmenter,
541+
) {
542+
net_debug!("Failed to send response: {:?}", err);
547543
}
548544
}
549-
#[cfg(feature = "medium-ieee802154")]
550-
Medium::Ieee802154 => {
551-
if let Some(packet) = self.inner.process_ieee802154(
552-
sockets,
553-
rx_meta,
554-
frame,
555-
&mut self.fragments,
545+
}
546+
#[cfg(feature = "medium-ieee802154")]
547+
Medium::Ieee802154 => {
548+
if let Some(packet) =
549+
self.inner
550+
.process_ieee802154(sockets, rx_meta, frame, &mut self.fragments)
551+
{
552+
if let Err(err) = self.inner.dispatch_ip(
553+
tx_token,
554+
PacketMeta::default(),
555+
packet,
556+
&mut self.fragmenter,
556557
) {
557-
if let Err(err) = self.inner.dispatch_ip(
558-
tx_token,
559-
PacketMeta::default(),
560-
packet,
561-
&mut self.fragmenter,
562-
) {
563-
net_debug!("Failed to send response: {:?}", err);
564-
}
558+
net_debug!("Failed to send response: {:?}", err);
565559
}
566560
}
567561
}
568-
processed_any = true;
569-
});
570-
}
562+
}
563+
processed_any = true;
564+
});
571565

572566
processed_any
573567
}

0 commit comments

Comments
 (0)