Commit Graph

495 Commits

Author SHA1 Message Date
Petro Karashchenko
9551de7115 net: use HTONS, NTOHS, HTONL, NTOHL macro in kernel code
Signed-off-by: Petro Karashchenko <petro.karashchenko@gmail.com>
2022-01-18 10:59:47 +01:00
Alexander Lunev
5b13797cce net/tcp/tcp_send*: reliably obtain the TCP connection pointer in TCP event handlers
Do not use pvconn argument to get the TCP connection pointer because pvconn is
normally NULL for some events like NETDEV_DOWN. Instead, the TCP connection pointer
can be reliably obtained from the corresponding TCP socket.
2022-01-18 16:14:38 +08:00
Alexander Lunev
f61f276120 net/tcp/sendfile: TCP retransmission could not start because of incorrect snd_ackcb callback handling:
Both the snd_ackcb and snd_datacb callbacks were created and destroyed right after sending every packet.
Whenever TCP_REXMIT event occurred due to TCP send timeout, TCP_REXMIT was ignored because
snd_ackcb callback had been destroyed by the time.
The issue is fixed as follows:
- both the snd_ackcb and snd_datacb callbacks are combined into one snd_cb callback
  (the same way as in tcp_send_unbuffered.c).
- the snd_cb callback lives until all requested data (via sendfile) is sent,
  including all ACKs and possible retransmissions.

As a positive side effect of the code optimization / fix, sendfile TCP payload throughput is increased.
2022-01-18 02:03:40 +08:00
Alexander Lunev
0f080cdeaf net/tcp/sendfile: NET_TCP_WRITE_BUFFERS and NET_SENDFILE were inconsistent with each other:
tcp_sendfile() reads data directly from a file and does not use NET_TCP_WRITE_BUFFERS data flow
even if CONFIG_NET_TCP_WRITE_BUFFERS option is enabled.
Despite this, tcp_sendfile relied on NET_TCP_WRITE_BUFFERS specific flow control variables that
were idle during sendfile operation. Thus it was a total inconsistency.

E.g. because of the issue, TCP socket used by sendfile() operation never issued
FIN packet on close() command, and the TCP connection hung up.

As a result of the fix, simultaneously enabled CONFIG_NET_TCP_WRITE_BUFFERS and
CONFIG_NET_SENDFILE options can coexist.
2022-01-17 01:42:41 +08:00
Petro Karashchenko
8d3bf05fd2 include: fix double include pre-processor guards
Signed-off-by: Petro Karashchenko <petro.karashchenko@gmail.com>
2022-01-16 11:11:14 -03:00
Alexander Lunev
e9ab3adf23 net/tcp(unbuffered): advance sndseq by +1 because SYN and FIN occupy one sequence number (RFC 793) 2022-01-03 12:18:44 +09:00
Alexander Lunev
0afb1d8dbb net/tcp(unbuffered): fast retransmit on duplicate acknowledgments 2022-01-02 23:25:09 +08:00
chao.an
38b7b3d26a net/tcp: add support for CONFIG_NET_ALLOC_CONNS 2022-01-01 20:40:02 +08:00
Alexander Lunev
2b60468845 net/tcp(unbuffered): removed excessive overwrites of conn->sndseq
(conn->sndseq was updated in multiple places that was unreasonable and complicated).
2021-12-29 05:35:23 -06:00
Alexander Lunev
e68ffb9f99 net/tcp(unbuffered): fixed an issue with unackseq calculation.
Wrong unackseq calculation locked conn->tx_unacked at non-zero values
even if all ACKs were received. Thus unbuffered psock_tcp_send() never completed.
2021-12-27 20:59:48 -06:00
Alexander Lunev
19dc121a4f net/tcp(unbuffered): fixed an issue with tx_unacked overflow that occurred if NET_TCP_WINDOW_SCALE option was enabled.
If the remote TCP receiver advertised TCP window size greater than 64 KB
and TCP ACK packets returned to the NuttX TCP sender with a significant delay,
tx_unacked variable overflowed and further TCP send stalled forever
(until TCP re-connection).
2021-12-27 11:05:01 -06:00
chao.an
0ee7400fdf net/tcp: fix send deadlock if disconnect
Signed-off-by: chao.an <anchao@xiaomi.com>
2021-12-16 01:29:10 -06:00
Alexander Lunev
1e07b6d528 net/tcp(unbuffered): retransmit only one the earliest not acknowledged segment
(according to RFC 6298 (5.4)).
2021-11-10 12:21:07 -06:00
YAMAMOTO Takashi
ecd6a3572b net/tcp/Kconfig: Remove NET_TCP_SPLIT
While it's a neat idea, it doesn't work well in reality.

* Many of modern tcp stacks don't obey the "ack every other packet"
  rule these days. (Linux, macOS, ...)

* Even if a traditional TCP implementation is assumed, we can't
  predict/control which packets are acked reliably. For example,
  window updates can easily mess up our strategy.
2021-11-04 13:32:57 -05:00
YAMAMOTO Takashi
28d168e1b8 tcp_send_unbuffered.c: Fix nxstyle errors 2021-11-04 13:32:57 -05:00
YAMAMOTO Takashi
1550a525e9 tcp_send_unbuffered.c: unifdef -UCONFIG_NET_TCP_SPLIT 2021-11-04 13:32:57 -05:00
Alexander Lunev
1e25602678 net/can,icmp,icmpv6,tcp,tcp_timer,udp: device should poll only those connections that are bound to the device.
tcp_timer: eliminated false decrements of conn->timer in case of multiple network adapters.
The false timer decrements sometimes provoked TCP spurious retransmissions due to premature timeouts.
2021-10-11 23:09:00 -07:00
chao.an
c132e5bed4 net/tcp: sanity check for the listen address
Signed-off-by: chao.an <anchao@xiaomi.com>
2021-09-23 23:07:57 -07:00
Alexander Lunev
36fbedcbfc net/devif/devif_callback.c: corrected the connection event list to work as FIFO instead of LIFO.
In case of enabled packet forwarding mode, packets were forwarded in a reverse order
because of LIFO behavior of the connection event list.
The issue exposed only during high network traffic. Thus the event list started to grow
that resulted in changing the order of packets inside of groups of several packets
like the following: 3, 2, 1, 6, 5, 4, 8, 7 etc.

Remarks concerning the connection event list implementation:
* Now the queue (list) is FIFO as it should be.
* The list is singly linked.
* The list has a head pointer (inside of outer net_driver_s structure),
  and a tail pointer is added into outer net_driver_s structure.
* The list item is devif_callback_s structure.
  It still has two pointers to two different list chains (*nxtconn and *nxtdev).
* As before the first argument (*dev) of the list functions can be NULL,
  while the other argument (*list) is effective (not NULL).
* An extra (*tail) argument is added to devif_callback_alloc()
  and devif_conn_callback_free() functions.
* devif_callback_alloc() time complexity is O(1) (i.e. O(n) to fill the whole list).
* devif_callback_free() time complexity is O(n) (i.e. O(n^2) to empty the whole list).
* devif_conn_event() time complexity is O(n).
2021-09-18 21:01:39 -05:00
Alin Jerpelea
91a5f90a7f author: UVC Ingenieure : update licenses to Apache
Gregory Nutt has submitted the SGA
UVC Ingenieure has submitted the SGA
Max Holtzberg has submitted the ICLA

as a result we can migrate the licenses to Apache.

Signed-off-by: Alin Jerpelea <alin.jerpelea@sony.com>
2021-09-15 15:57:55 +08:00
YAMAMOTO Takashi
42f1851ca6 tcp_send_buffered.c: Fix snd_wnd
snd_wnd is an offset from the acked sequence number.
2021-08-25 20:56:05 +08:00
YAMAMOTO Takashi
1b82f1c749 tcp_input: snd_wnd processing
* Do not accept the window in old segments.
  Implement SND.WL1/WL2 things in the RFC.

* Do not accept the window in the segment w/o ACK bit set.
  The window is an offset from the ack seq.
  (maybe it's simpler to just drop segments w/o ACK though)

* Subtract snd_wnd by the amount of the ack advancement.
2021-08-25 20:56:05 +08:00
chao.an
9701a678bd net/tcp: add nonblock connect(2) support
Signed-off-by: chao.an <anchao@xiaomi.com>
2021-08-19 19:19:05 -07:00
YAMAMOTO Takashi
b815a2c3a8 tcp_input: Don't put back sndseq on an old ack 2021-08-06 21:17:25 -07:00
YAMAMOTO Takashi
e53f989997 tcp_rexmit: advance conn->sndseq
Otherwise, we use an old sequence number when sending
non-data segment. (eg. window update)
The peer might consider such a segment stale and ignore.
2021-08-06 21:17:25 -07:00
YAMAMOTO Takashi
b5bb0d56ad tcp: fix an assertion in "fix iob allocation deadlock" commit
Fix a wrong assertion in:

```
commit 98ec46d726
Author: YAMAMOTO Takashi <yamamoto@midokura.com>
Date:   Tue Jul 20 09:10:43 2021 +0900

    tcp_send_buffered.c: fix iob allocation deadlock

    Ensure to put the wrb back onto the write_q when blocking
    on iob allocation. Otherwise, it can deadlock with other
    threads doing the same thing.
```

I forget to submit this with https://github.com/apache/incubator-nuttx/pull/4257
2021-08-05 23:50:06 -07:00
YAMAMOTO Takashi
1d3594ba07 tcp_send_buffered.c: Fix broken retransmit
With an applictation using mbedtls, I observed retransmitted segments
with corrupted user data, detected by the peer tls during mac processing.

Looking at the packet dump, I suspect that a wrb which has been put back
onto the write_q for retransmission was partially sent but fully acked.
Note: it's normal for a retransmission to be acked before sent.

In that case, the bug fixed in this commit would cause the wrb have
a wrong sequence number, possibly the same as the next wrb. It matches
what I saw in the packet dump. That is, the broken segments contain the
payload identical to one of the previous segment.
2021-08-02 11:30:01 -07:00
YAMAMOTO Takashi
98ec46d726 tcp_send_buffered.c: fix iob allocation deadlock
Ensure to put the wrb back onto the write_q when blocking
on iob allocation. Otherwise, it can deadlock with other
threads doing the same thing.
2021-08-02 11:25:55 -07:00
chao.an
7d4502aca6 net/socket: add SO_SNDBUF support
Signed-off-by: chao.an <anchao@xiaomi.com>
2021-07-20 20:24:58 -07:00
chao.an
f52757f90a net/wrb: add tcp/udp_inqueue_wrb_size() interface
Signed-off-by: chao.an <anchao@xiaomi.com>
2021-07-20 20:24:58 -07:00
YAMAMOTO Takashi
09f3a1ec8e tcp_send_buffered: throttle IOB allocations for send
Consider a bi-directional TCP connection:

1. we use all IOBs for tx queue
2. we advertize zero recv window because we have no free IOBs
3. if the peer tcp does the same thing,
   both sides advertize zero window and can not drain the tx queue.

For a similar stall to happen, the peer doesn't need to be
a naive tcp implementation like nuttx. A naive application blocking
on send() without draining its read buffer is enough.
(Probably such an application should be fixed to drain rx even
when tx is full. However, it's another story.)

This commit avoids the situation by prevent tx from grabbing
the all IOBs in the first place. (assuming CONFIG_IOB_THROTTLE > 0)
2021-07-14 15:08:18 +08:00
chao.an
83f7c08f65 net/tcp: only print the error when disable the TCP_NODELAY
Since we do not have the Nagle's algorithm,
the TCP_NODELAY socket option is enabled by default.

Change-Id: I0c8619bb06cf418f7eded5bd72ac512b349cacc5
Signed-off-by: chao.an <anchao@xiaomi.com>
2021-07-13 09:44:19 -03:00
Huang Qi
e5c278981a net: Rename IP_TTL to IP_TTL_DEFAULT
Since a SOL option IP_TTL exist, we should rename this IP_TTL
in netconfig.h to avoid confusion.

Signed-off-by: Huang Qi <huangqi3@xiaomi.com>
Change-Id: Ib04c36553f23bce8d362e97294a8b83eaa050cf3
2021-07-12 16:30:37 -03:00
Xiang Xiao
906cb8b0f4 net/tcp: tcp_sendfile need restore the file location at the end
quote from https://man7.org/linux/man-pages/man2/sendfile.2.html:
If offset is not NULL, then it points to a variable holding the
file offset from which sendfile() will start reading data from
in_fd.  When sendfile() returns, this variable will be set to the
offset of the byte following the last byte that was read.  If
offset is not NULL, then sendfile() does not modify the file
offset of in_fd; otherwise the file offset is adjusted to reflect
the number of bytes read from in_fd.
If offset is NULL, then data will be read from in_fd starting at
the file offset, and the file offset will be updated by the call.

The change also align with the implementation at:
libs/libc/misc/lib_sendfile.c

Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
Change-Id: I607944f40b04f76731af7b205dcd319b0637fa04
2021-07-12 05:20:45 -07:00
chao.an
d4ce70979e net/tcp: change all window relative value type to uint32_t
1. change all window relative value type to uint32_t
2. move window range validity check(UINT16_MAX) before assembling TCP header

Signed-off-by: chao.an <anchao@xiaomi.com>
2021-07-07 03:55:41 -05:00
chao.an
aab03ef86d net/tcp: add window scale support
Reference here:
https://tools.ietf.org/html/rfc1323

Signed-off-by: chao.an <anchao@xiaomi.com>
2021-07-07 03:55:41 -05:00
chao.an
a5cdc4e69b net/tcp: change the tcp optdata to dynamic arrays
Signed-off-by: chao.an <anchao@xiaomi.com>
2021-07-07 03:55:41 -05:00
chao.an
87bffc190c net/tcp: remove the invalid break during tcp option loop
Signed-off-by: chao.an <anchao@xiaomi.com>
2021-07-07 03:55:41 -05:00
chao.an
b901f22c27 net/socket: add SO_RCVBUF support
Signed-off-by: chao.an <anchao@xiaomi.com>
2021-07-06 01:44:55 -05:00
chao.an
eabe535de7 net/inet: add support of FIONREAD
Signed-off-by: chao.an <anchao@xiaomi.com>
2021-07-05 06:20:52 -05:00
Anthony Merlino
a885b24cc1 Attempt to fix race condition reported in issue #3647 2021-07-04 08:54:15 -05:00
YAMAMOTO Takashi
669619a06a tcp_close: Fix a race with passive close
tcp_close disposes the connection immediately if it's called in
TCP_LAST_ACK. If it happens, we will end up with responding the
last ACK with a RST.

This commit fixes it by making tcp_close wait for the completion
of the passive close.
2021-07-02 13:54:15 +09:00
YAMAMOTO Takashi
c7ba75697c tcp_recvwindow.c: Use iob_tailroom to replace the home grown one 2021-06-30 06:40:13 -05:00
YAMAMOTO Takashi
52c237cb5f net/tcp/tcp.h: Update a comment about readahead 2021-06-30 06:40:13 -05:00
YAMAMOTO Takashi
08e9dff0e9 tcp_close: disable send callback before sending FIN
This fixes connection closing issues with CONFIG_NET_TCP_WRITE_BUFFERS.

Because TCP_CLOSE is used for both of input and output for tcp_callback,
the close callback and the send callback confuses each other as
the following. As it effectively disposes the connection immediately,
we end up with responding to the consequent ACK and FIN/ACK from the peer
with RSTs.

tcp_timer
    -> tcp_close_eventhandler
        returns TCP_CLOSE (meaning an active close)
    -> psock_send_eventhandler
        called with TCP_CLOSE from tcp_close_eventhandler, misinterpet as
        a passive close.
        -> tcp_lost_connection
            -> tcp_shutdown_monitor
                -> tcp_callback
                    -> tcp_close_eventhandler
                        misinterpret TCP_CLOSE from itself as
                        a passive close
2021-06-30 06:39:13 -05:00
YAMAMOTO Takashi
326a8ef0a2 tcp_close_disconnect: don't nullify sndcb
It isn't necessary and I plan to use the value later in
the close processing.
2021-06-30 06:39:13 -05:00
YAMAMOTO Takashi
8472430f22 tcp_close: replace scaring comments 2021-06-30 06:39:13 -05:00
YAMAMOTO Takashi
1ce13ee731 tcp_reset: Don't copy the peer window
The current code just leave the window value from the segment
from the peer. It doesn't make sense.

Instead, always use 0.
This matches what NetBSD and Linux do.
(As far as I read their code correctly.)
2021-06-29 22:23:48 -05:00
YAMAMOTO Takashi
98e7c6924d tcp: always responds to keep-alive segments
* It doesn't make sense to have this conditional on our own
  SO_KEEPALIVE support. (CONFIG_NET_TCP_KEEPALIVE)
  Actually we don't have a control on the peer tcp stack,
  who decides to send us keep-alive probes.

* We should respond them for non ESTABLISHED states. eg. FIN_WAIT_2
  See also:
  https://github.com/apache/incubator-nuttx/pull/3919#issuecomment-868248576
2021-06-30 11:52:08 +09:00
YAMAMOTO Takashi
4878b7729c tcp: simplify readahead
Do not bother to preserve segment boundaries in the tcp
readahead queues.

* Avoid wasting the tail IOB space for each segments.
  Instead, pack the newly received data into the tail space
  of the last IOB. Also, advertise the tail space as
  a part of the window.

* Use IOB chain directly. Eliminate IOB queue overhead.

* Allow to accept only a part of a segment.

* This change improves the memory efficiency.
  And probably more importantly, allows less-confusing
  recv window advertisement behavior.
  Previously, even when we advertise N bytes window,
  we often couldn't actually accept N bytes. Depending on
  the segment sizes and IOB configurations, it was causing
  segment drops.
  Also, the previous code was moving the right edge of the
  window back and forth too often, even when nothing in
  the system was competing on the IOBs. Shrinking the
  window that way is a kinda well known recipe to confuse
  the peer stack.
2021-06-30 06:22:14 +09:00