Skip to content

Commit

Permalink
Merge pull request #1398 from stlankes/tcp
Browse files Browse the repository at this point in the history
add option to increase queue limit for incoming connections
  • Loading branch information
mkroening authored Nov 4, 2024
2 parents 7074c1b + a8a9cae commit c94a597
Show file tree
Hide file tree
Showing 20 changed files with 820 additions and 866 deletions.
7 changes: 0 additions & 7 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ bitflags = "2.6"
build-time = "0.1.3"
cfg-if = "1"
crossbeam-utils = { version = "0.8", default-features = false }
dyn-clone = "1.0"
fdt = { version = "0.1", features = ["pretty-printing"] }
free-list = "0.3"
fuse-abi = { version = "0.2", features = ["linux", "zerocopy"], optional = true }
Expand Down
6 changes: 4 additions & 2 deletions src/executor/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ impl<'a> NetworkInterface<'a> {
return NetworkState::InitializationFailed;
};

let mut device = HermitNet::new(mtu, checksums);
let mut device = HermitNet::new(mtu, checksums.clone());

if hermit_var!("HERMIT_IP").is_some() {
warn!("A static IP address is specified with the environment variable HERMIT_IP, but the device is configured to use DHCPv4!");
Expand All @@ -62,6 +62,7 @@ impl<'a> NetworkInterface<'a> {
let hardware_addr = HardwareAddress::Ethernet(ethernet_addr);

info!("MAC address {}", hardware_addr);
info!("{:?}", checksums);
info!("MTU: {} bytes", mtu);

let dhcp = dhcpv4::Socket::new();
Expand Down Expand Up @@ -100,7 +101,7 @@ impl<'a> NetworkInterface<'a> {
return NetworkState::InitializationFailed;
};

let mut device = HermitNet::new(mtu, checksums);
let mut device = HermitNet::new(mtu, checksums.clone());

let myip = Ipv4Address::from_str(hermit_var_or!("HERMIT_IP", "10.0.5.3")).unwrap();
let mygw = Ipv4Address::from_str(hermit_var_or!("HERMIT_GATEWAY", "10.0.5.1")).unwrap();
Expand Down Expand Up @@ -141,6 +142,7 @@ impl<'a> NetworkInterface<'a> {
info!("MAC address {}", hardware_addr);
info!("Configure network interface with address {}", ip_addrs[0]);
info!("Configure gateway with address {}", mygw);
info!("{:?}", checksums);
info!("MTU: {} bytes", mtu);

// use the current time based on the wall-clock time as seed
Expand Down
161 changes: 55 additions & 106 deletions src/executor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ use crate::drivers::mmio::get_network_driver;
use crate::drivers::net::NetworkDriver;
#[cfg(all(any(feature = "tcp", feature = "udp"), feature = "pci"))]
use crate::drivers::pci::get_network_driver;
#[cfg(any(feature = "tcp", feature = "udp"))]
use crate::executor::network::network_delay;
use crate::executor::task::AsyncTask;
use crate::io;
#[cfg(any(feature = "tcp", feature = "udp"))]
Expand Down Expand Up @@ -97,30 +95,11 @@ pub fn init() {
crate::executor::vsock::init();
}

#[inline]
pub(crate) fn now() -> u64 {
crate::arch::kernel::systemtime::now_micros()
}

/// Blocks the current thread on `f`, running the executor when idling.
pub(crate) fn poll_on<F, T>(future: F, timeout: Option<Duration>) -> io::Result<T>
pub(crate) fn poll_on<F, T>(future: F) -> io::Result<T>
where
F: Future<Output = io::Result<T>>,
{
#[cfg(any(feature = "tcp", feature = "udp"))]
let nic = get_network_driver();

// disable network interrupts
#[cfg(any(feature = "tcp", feature = "udp"))]
let no_retransmission = if let Some(nic) = nic {
let mut guard = nic.lock();
guard.set_polling_mode(true);
guard.get_checksums().tcp.tx()
} else {
true
};

let start = now();
let mut cx = Context::from_waker(Waker::noop());
let mut future = pin!(future);

Expand All @@ -129,42 +108,8 @@ where
run();

if let Poll::Ready(t) = future.as_mut().poll(&mut cx) {
#[cfg(any(feature = "tcp", feature = "udp"))]
if !no_retransmission {
let wakeup_time =
network_delay(Instant::from_micros_const(now().try_into().unwrap()))
.map(|d| crate::arch::processor::get_timer_ticks() + d.total_micros());
core_scheduler().add_network_timer(wakeup_time);
}

// allow network interrupts
#[cfg(any(feature = "tcp", feature = "udp"))]
if let Some(nic) = nic {
nic.lock().set_polling_mode(false);
}

return t;
}

if let Some(duration) = timeout {
if Duration::from_micros(now() - start) >= duration {
#[cfg(any(feature = "tcp", feature = "udp"))]
if !no_retransmission {
let wakeup_time =
network_delay(Instant::from_micros_const(now().try_into().unwrap()))
.map(|d| crate::arch::processor::get_timer_ticks() + d.total_micros());
core_scheduler().add_network_timer(wakeup_time);
}

// allow network interrupts
#[cfg(any(feature = "tcp", feature = "udp"))]
if let Some(nic) = nic {
nic.lock().set_polling_mode(false);
}

return Err(io::Error::ETIME);
}
}
}
}

Expand All @@ -174,98 +119,102 @@ where
F: Future<Output = io::Result<T>>,
{
#[cfg(any(feature = "tcp", feature = "udp"))]
let nic = get_network_driver();

// disable network interrupts
#[cfg(any(feature = "tcp", feature = "udp"))]
let no_retransmission = if let Some(nic) = nic {
let mut guard = nic.lock();
guard.set_polling_mode(true);
!guard.get_checksums().tcp.tx()
} else {
true
};
let device = get_network_driver();

let backoff = Backoff::new();
let start = now();
let start = crate::arch::kernel::systemtime::now_micros();
let task_notify = Arc::new(TaskNotify::new());
let waker = task_notify.clone().into();
let mut cx = Context::from_waker(&waker);
let mut future = pin!(future);

loop {
// run background tasks
run();
// check future
let result = future.as_mut().poll(&mut cx);

let now = now();
if let Poll::Ready(t) = future.as_mut().poll(&mut cx) {
#[cfg(any(feature = "tcp", feature = "udp"))]
if !no_retransmission {
let network_timer =
network_delay(Instant::from_micros_const(now.try_into().unwrap()))
.map(|d| crate::arch::processor::get_timer_ticks() + d.total_micros());
core_scheduler().add_network_timer(network_timer);
}
// run background all tasks, which poll also the network device
run();

let now = crate::arch::kernel::systemtime::now_micros();
if let Poll::Ready(t) = result {
// allow network interrupts
#[cfg(any(feature = "tcp", feature = "udp"))]
if let Some(nic) = nic {
nic.lock().set_polling_mode(false);
{
let delay = if let Ok(nic) = crate::executor::network::NIC.lock().as_nic_mut() {
nic.poll_delay(Instant::from_micros_const(now.try_into().unwrap()))
.map(|d| d.total_micros())
} else {
None
};
core_scheduler().add_network_timer(
delay.map(|d| crate::arch::processor::get_timer_ticks() + d),
);

if let Some(device) = device {
device.lock().set_polling_mode(false);
}
}

return t;
}

if let Some(duration) = timeout {
if Duration::from_micros(now - start) >= duration {
#[cfg(any(feature = "tcp", feature = "udp"))]
if !no_retransmission {
let network_timer =
network_delay(Instant::from_micros_const(now.try_into().unwrap()))
.map(|d| crate::arch::processor::get_timer_ticks() + d.total_micros());
core_scheduler().add_network_timer(network_timer);
}

// allow network interrupts
#[cfg(any(feature = "tcp", feature = "udp"))]
if let Some(nic) = nic {
nic.lock().set_polling_mode(false);
{
let delay = if let Ok(nic) = crate::executor::network::NIC.lock().as_nic_mut() {
nic.poll_delay(Instant::from_micros_const(now.try_into().unwrap()))
.map(|d| d.total_micros())
} else {
None
};
core_scheduler().add_network_timer(
delay.map(|d| crate::arch::processor::get_timer_ticks() + d),
);

if let Some(device) = device {
device.lock().set_polling_mode(false);
}
}

return Err(io::Error::ETIME);
}
}

#[cfg(any(feature = "tcp", feature = "udp"))]
{
let delay = network_delay(Instant::from_micros_const(now.try_into().unwrap()))
.map(|d| d.total_micros());
if backoff.is_completed() {
let delay = if let Ok(nic) = crate::executor::network::NIC.lock().as_nic_mut() {
nic.poll_delay(Instant::from_micros_const(now.try_into().unwrap()))
.map(|d| d.total_micros())
} else {
None
};

if backoff.is_completed() && delay.unwrap_or(10_000_000) > 10_000 {
if delay.unwrap_or(10_000_000) > 10_000 {
core_scheduler().add_network_timer(
delay.map(|d| crate::arch::processor::get_timer_ticks() + d),
);
let wakeup_time =
timeout.map(|duration| start + u64::try_from(duration.as_micros()).unwrap());
if !no_retransmission {
let ticks = crate::arch::processor::get_timer_ticks();
let network_timer = delay.map(|d| ticks + d);
core_scheduler().add_network_timer(network_timer);
}

// allow network interrupts
if let Some(nic) = nic {
nic.lock().set_polling_mode(false);
if let Some(device) = device {
device.lock().set_polling_mode(false);
}

// switch to another task
task_notify.wait(wakeup_time);

// restore default values
if let Some(nic) = nic {
nic.lock().set_polling_mode(true);
if let Some(device) = device {
device.lock().set_polling_mode(true);
}

backoff.reset();
} else {
backoff.snooze();
}
} else {
backoff.snooze();
}

#[cfg(not(any(feature = "tcp", feature = "udp")))]
Expand Down
Loading

0 comments on commit c94a597

Please sign in to comment.