Ping Doesn't Work As Execpted, Return ERROR CODE == EAGAIN
Description
Ping command does't work properly, for example ping 8.8.8.8
. I am sure that 8.8.8.8
is reachable.
Console output:
redox login: user
Welcome to Redox OS!
user:~# ping 8.8.8.8
: io error : Try again (os error 11)
user:~# ping www.google.com
: io error : Try again (os error 11)
Environment info
-
git rev-parse HEAD
:34d1ec9c2e9f7904b57547ca16d4c3145c109880
-
rustc -V
:rustc 1.61.0-nightly (58f11791a 2022-03-17)
-
uname -a
:Linux ccs-PC 5.15.0-56-generic #62~20.04.1-Ubuntu SMP Tue Nov 22 21:24:20 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
Steps to reproduce
- Log in (
make FILESYSTEM_SIZE=512 qemu kvm=no vga=no
) - Open terminal
- Input
ping X.X.X.X
Extra
When event_queue.trigger_all
is called, the on_echo_event
callback is triggered. However, the io read function returns EAGAIN
because of nothing to read in ping_fd
's buffer during this period.
// netstack/source/src/smolnetd/scheme/icmp.rs
fn write_buf(
&mut self,
file: &mut SocketFile<Self::DataT>,
buf: &[u8],
) -> SyscallResult<Option<usize>> {
if self.can_send() {
match file.data.socket_type {
IcmpSocketType::Echo => {
if buf.len() < mem::size_of::<u16>() {
return Err(SyscallError::new(syscall::EINVAL));
}
let (seq_buf, payload) = buf.split_at(mem::size_of::<u16>());
let seq_no = NetworkEndian::read_u16(seq_buf);
let icmp_repr = Icmpv4Repr::EchoRequest {
ident: file.data.ident,
seq_no,
data: payload,
};
let icmp_payload = self.send(icmp_repr.buffer_len(), file.data.ip)
.map_err(|_| syscall::Error::new(syscall::EINVAL))?;
let mut icmp_packet = Icmpv4Packet::new_unchecked(icmp_payload);
//TODO: replace Default with actual caps
icmp_repr.emit(&mut icmp_packet, &Default::default());
Ok(Some(buf.len()))
}
IcmpSocketType::Udp => {
Err(SyscallError::new(syscall::EINVAL))
}
}
} else if file.flags & syscall::O_NONBLOCK == syscall::O_NONBLOCK {
Err(SyscallError::new(syscall::EAGAIN))
} else {
Ok(None) // internally scheduled to re-read
}
}
I try to figure it out by triggering time event only, and it seems to work:
diff --git a/src/ping/main.rs b/src/ping/main.rs
index 2c94104..3bbda3a 100644
--- a/src/ping/main.rs
+++ b/src/ping/main.rs
@@ -340,11 +340,11 @@ fn run() -> Result<()> {
move |_| ping_.borrow_mut().on_echo_event())?;
let ping_ = ping.clone();
- event_queue
+ let time_queue_id = event_queue
.add(time_fd as RawFd,
move |_| ping_.borrow_mut().on_time_event())?;
- event_queue.trigger_all(event::Event {
+ event_queue.trigger(time_queue_id, event::Event {
fd: 0,
flags: syscall::EventFlags::empty(),
})?;
Edited by Ivan Tan