Skip to content

Commit 8c2cef1

Browse files
committed
Limiting the number of poll loops to prevent DoS events
Updating process loop to be defined by socket buffers when possible Further changes after hardware testing Fixing test Adding CHANGELOG entry Expanding comment after review Update src/iface/interface/mod.rs Co-authored-by: Catherine <[email protected]> Removing redundant phrasing in comment Updating verbiage to remove references to unsafe and safe
1 parent 7b125ef commit 8c2cef1

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)