when tcp retransmission only double conn->timer in Karn(tcp_timer.c L602), after retransmission in Jacobson
M is is now rtt test will become a negative value.
```
signed char m;
m = conn->rto - conn->timer; // M is now rtt test
/* This is taken directly from VJs original code in his paper */
m = m - (conn->sa >> 3);
conn->sa += m; //conn->sa is a negative value
if (m < 0)
{
m = -m;
}
m = m - (conn->sv >> 2);
conn->sv += m;
conn->rto = (conn->sa >> 3) + conn->sv; //rto
```
For example,we lost one ack packet, we will set conn->timer = 6 by backoff,conn->rto still 3.
After retransmission we will Do RTT estimation, then will get
```
conn->sa = 253
conn->rto = 46
```
Then if any packets lost it will wait for a long time before triggering a retransmission.
Test method.
We can reproduce this issue by adding drop ACK packets in tcp_input, and debug conn->rto after Jacobson.
Signed-off-by: meijian <meijian@xiaomi.com>
Now the HAVE_PFINET(6)_SOCKETS depends on NET_TCP/UDP_HAVE_STACK, which
is previously defined in net/ folder and cannot be included.
Considering many places use this check, maybe moving them to netconfig.h
could be better.
Signed-off-by: Zhe Weng <wengzhe@xiaomi.com>
assert: tcp conn and didn't recv ack, tcp_free will assert in L909
and no need to tcp free because tcp close will free by lpwork.
Signed-off-by: meijian <meijian@xiaomi.com>
Problem Description:
Problem occurrence when Thread1 creat connect/recv socket and Thread2 cancel Thread1.
1. Thread2 cancel when Thread1 connect event, will cause DEBUGASSERT in devif_callback_free.Because cb in g_cbfreelist.
2. Thread2 cancel when Thread1 recvfrom sem-wait, when the FIN packet input and will trigger tcp_recvhandler and will crash.Becuase some thread stack data was freed.
Signed-off-by: meijian <meijian@xiaomi.com>
The current receive data needs to be handled by following
tcp_recvhandler or tcp_data_event. Notify driver to send the
message and marked as rexmit
Signed-off-by: zhanghongyu <zhanghongyu@xiaomi.com>
we will drop packet when tcp_close_eventhandler
is register and invoke by tcp_input. then we will always early return and
never stop, the peer will only close the connection if we send reset packet.
precondition:
close -> register tcp_close_eventhandler;
tcp_input -> tcp_callback(TCP_NEWDATA) -> devif_conn_event -> tcp_close_eventhandler
-> flags &= ~TCP_NEWDATA -> NOT entry tcp_data_event -> conn->recvreq NOT increase
old flow:
tcp_input -> tcp->seqno greater than conn->rcvseq -> tcp_send(TCP_ACK)
with this patch:
tcp_input -> tcp->seqno greater than conn->rcvseq -> !TCP_ESTABLISHED
-> case TCP_FIN_WAIT_1 -> dev->d_len greater than 0 -> tcp_reset
Signed-off-by: zhanghongyu <zhanghongyu@xiaomi.com>
According to RFC793, Section 3.4, Page 33. In the SYN_SENT state, if receive a ACK without the SYN, we should reset the connection and retransmit the SYN.
Signed-off-by: liqinhui <liqinhui@xiaomi.com>
Some app with same code runs on different cores in AMP mode,
need the physical core on which the function is called.
Signed-off-by: hujun5 <hujun5@xiaomi.com>
Signed-off-by: fangxinyong <fangxinyong@xiaomi.com>
Summary:
The conn->keeptimer units is decisecond,but its unit is treated as
half-second in the tcp_timer & tcp_get_timeout function.
Therefore conn>keeptimer needs to be divided by 5(DSEC_PER_HSEC)
to match half-second units.
Signed-off-by: zhangshuai39 <zhangshuai39@xiaomi.com>
Most tools used for compliance and SBOM generation use SPDX identifiers
This change brings us a step closer to an easy SBOM generation.
Signed-off-by: Alin Jerpelea <alin.jerpelea@sony.com>
when tcp socket stays in TCP_FIN_WAIT_1 or TCP_FIN_WAIT_2,not actively calling tcp_close_eventhandler,can reuslt in some TCP socket being set to a closed state,but nofosegs are not directly released,leading to IOB resource leakage.
Signed-off-by: wangchen <wangchen41@xiaomi.com>
1. Tcp will idle loop by tcp_timer when have no packet to send. This will cause low-power devices to be frequently woken up.
2. We should add tcp_timer when timer has been canceled and have packet to send.
Signed-off-by: meijian <meijian@xiaomi.com>
The Bluetooth network on N62 does not retransmit packet, so no packet
retransmition if we drop one, we will drop packet when tcp_close_eventhandler
is register and invoke by tcp_input. then we will always early return and
never stop, the peer will only close the connection if we send reset packet.
precondition:
close -> register tcp_close_eventhandler;
tcp_input -> tcp_callback(TCP_NEWDATA) -> devif_conn_event -> tcp_close_eventhandler
-> flags &= ~TCP_NEWDATA -> NOT entry tcp_data_event -> conn->recvreq NOT increase
old flow:
tcp_input -> tcp->seqno greater than conn->rcvseq -> tcp_send(TCP_ACK)
with this patch:
tcp_input -> tcp->seqno greater than conn->rcvseq -> !TCP_ESTABLISHED
-> case TCP_FIN_WAIT_1 -> dev->d_len greater than 0 -> tcp_reset
Signed-off-by: zhanghongyu <zhanghongyu@xiaomi.com>
In "psock_send_eventhandler",when retransmit count bigger TCP_MAXRTX nuttx will set release wrb. But before this it will also set "conn->tx_unacked = 0" if we only retransmit one packet(conn->tx_unacked == sent),and In func "tcp_timer" only "conn->tx_unacked > 0" will close the tcp conn. So app will never close if nuttx retransmit over max timers.
Signed-off-by: meijian <meijian@xiaomi.com>
To prepare for future IPv6 NAT functions.
- Rename common ipv4_nat_xxx to nat_xxx
- Move some common definitions into header
Signed-off-by: Zhe Weng <wengzhe@xiaomi.com>
If we only enable one of `CONFIG_NET_ARP_SEND` and
`CONFIG_NET_ICMPv6_NEIGHBOR`, both IPv4 and IPv6 traffic will send
ARP or NDP, which causes problem.
Example:
`CONFIG_NET_ARP_SEND=n`
`CONFIG_NET_ICMPv6_NEIGHBOR=y`
Wrong:
IPv4 traffic (`PF_INET`) goes into `icmpv6_neighbor`, which
definitely causes problem.
Correct:
IPv4 traffic doesn't call anything, IPv6 traffic calls `icmpv6_neighbor`
Signed-off-by: Zhe Weng <wengzhe@xiaomi.com>
When CONFIG_NET_TCP_WRITE_BUFFERS is enabled, iobs are used for
both queuing data from application, and for assembling packets
for sending. If there is a system-wide shortage of iobs, it could
happen that there is not enough free space to form any packets
to send. The buffers allocated for TCP data also can't be released
until the packet is sent.
Normally this should be avoided by setting suitable values for
CONFIG_IOB_NBUFFERS and CONFIG_IOB_THROTTLE. The default values
are ok for light usage, but can run out when using multiple
simultaneous TCP streams.
Before this commit, iob shortage would cause TCP connections to
get stuck and eventually timeout. With this change, TCP stack
sends smaller packets, eventually freeing some buffers from the
write queue.
Previously ipv6 multi-address support decided packet source
address based on its destination. This doesn't work if NuttX
device has multiple addresses within same subnet.
Instead when a packet is a response to existing connection,
the source address should be based on the destination address
used in the received packet.
Note that user-space related code, like procfs and lifreq related ioctl commands, are not touched in this commit.
Signed-off-by: Zhe Weng <wengzhe@xiaomi.com>
Some use cases, such as VPN, use both the device's network
stack with the Usrsock daemon and the Kernel's network stack.
Therefore, remove NET_TCP_NO_STACK/NET_UDP_NO_STACK select
from Usrsock's Kconfig.
The previous iob_trimhead added dev->iob->io_offset, so if the
input frame is not merged into the ofo segment, we need to reset
dev->iob->io_offset so that the subsequent tcp_send can properly
assemble packets.
Signed-off-by: zhanghongyu <zhanghongyu@xiaomi.com>
We may just free some TCP connections before monitor stopped, e.g.
sacrificie a TCP conn in `tcp_alloc` will just call `tcp_free` and reuse
the connection. But we noticed that the TCP monitor is not released in
`tcp_free` because it is mounted on `conn->connevents` instead of
`conn->sconn.list` while `tcp_free` only release the latter.
Signed-off-by: Zhe Weng <wengzhe@xiaomi.com>
with nonblocking sockets, POLLOUT is returned when the application
calls poll even if the send buffer is full
Signed-off-by: zhanghongyu <zhanghongyu@xiaomi.com>
Normally, `SO_ERROR` for disconn events will be set by `tcp_poll_eventhandler`, but when the socket is closed before poll, we should also set the `SO_ERROR`.
On Linux, `tcp_poll` returns `EPOLLERR` event when `sk->sk_err` has value but doesn't let `poll` fail (doesn't set `errno`). https://github.com/torvalds/linux/blob/v6.5/net/ipv4/tcp.c#L594-L596
Note: `sk->sk_err` can be get by socket option `SO_ERROR` on Linux, so `POLLERR` will always be together with `SO_ERROR`.
Common libs like curl may try to read `SO_ERROR` on `POLLERR`.
Signed-off-by: Zhe Weng <wengzhe@xiaomi.com>
After the sack is enabled and the ofosegs has gap, tcp cannot update the
tx_unacked, so the peer received packets are retransmitted after the
timer timeout.
So update tx_unacked first.
Signed-off-by: zhanghongyu <zhanghongyu@xiaomi.com>