asterinas / asterinas

Asterinas is a secure, fast, and general-purpose OS kernel, written in Rust and providing Linux-compatible ABI.
https://asterinas.github.io/
Other
682 stars 70 forks source link

Polling ifaces may not ensure packets be transmitted #819

Open StevenJiang1110 opened 1 month ago

StevenJiang1110 commented 1 month ago

The problem occurs when I trying to send two messages to the same TCP socket, and trying to receive the two messages at once.

TEST_RES(sendmsg(sk_accepted, &msg, 0), _ret == strlen(message));
TEST_RES(sendmsg(sk_accepted, &msg, 0), _ret == strlen(message));

// Ensure two messages are ready for receiving
sleep(1);

TEST_RES(recvmsg(sk_connected, &msg, 0), _ret == strlen(message) * 2);

The test program always succeeds when running on Linux.

However, when running on Asterinas, sk_connected can only accept the first message.

The problem disappears when I running in set log level as TRACE. So it may be some problems with timeout.......

Possible solution

This problem may be related to the nagle-enabled feature, which disables small packets to be transmitted. If set nagle-enabled as false, the problem will also disappear.

But totally disabling this feature may affect performance. This feature is same as the TCP_NODELAY option in Linux, but Linux keeps this option on by default.

StevenJiang1110 commented 2 weeks ago

The original solution is to change the code

https://github.com/asterinas/asterinas/blob/a997785166f451eecdfd2b98ff5a3620df2ffada/kernel/aster-nix/src/net/iface/common.rs#L170

like follows

if old_instant == 0 || new_instant < old_instant {

It works 40 days ago (2024.5.8). But it will break the send_buf_full test in the main branch now(2024.6.18).