This commit implements simple rate-limiting for Neighbor Reachability
Hints in TCP module to prevent the potentially costly process of
frequent neighbor searches in the table, enhancing system performance.
Signed-off-by: Łukasz Duda <lukasz.duda@nordicsemi.no>
Add a function callback that is called when the TCP connection
is closed. This is only available if doing network tests.
Signed-off-by: Jukka Rissanen <jukka.rissanen@nordicsemi.no>
When a TCP connection is established, if there is no data exchange
between the two parties within the set time, the side that enables
TCP Keep-alive will send a TCP probe packet with the same sequence
number as the previous TCP packet. This TCP probe packet is an empty
ACK packet (the specification recommends that it should not contain
any data, but can also contain 1 nonsense byte, such as 0x00.). If
there is no response from the other side after several consecutive
probe packets are sent, it is determined that the tcp connection has
failed, and the connection is closed.
The keep-alive default parameters are aligned with Linux defaults.
Signed-off-by: Horse Ma <mawei@coltsmart.com>
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
Eliminate race between TCP input thread and TCP work queue, when
dereferencing connection. This normally would not manifest itself during
standard TCP operation, but could be a potential opening for abuse, when
the already closed TCP connection is kept being spammed with packets.
The test scenario involved sending multiple TCP RST packets as a
response to establishing the connection, which could result in system
crash. The following changes in the TCP stack made it stable in such
scenario:
1. Use `tcp_lock` when searching for active connections, to avoid
potential data corruption when connection is being removed when
iterating.
2. Avoid memset() during connection dereference, not to destroy mutex
associated with the connection. The connection context is only
cleared during allocation now.
3. Lock the connection mutex while releasing connection.
4. In tcp_in(), after locking the mutex, verify the connection state,
and quit early if the connection has already been dereferenced.
5. When closing connection from the TCP stack as a result of RST or
malformed packet, verify connection state to make sure it's only done
once, even if multiple RST packets were received.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
Fix the possible race between TCP work items already scheduled for
execution, and tcp_conn_unref(), by moving the actual TCP context
releasing to the workqueue itself. That way we can be certain, that when
the work items are cancelled, they won't execute. It could be the case,
that the work item was already being processed by the work queue, so
clearing the context could lead to a crash.
Remove the comments around the mutex lock in the work handlers regarding
the race, as it's not the case anymore. I've kept the locks however, as
they do make sense in those places.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
Instead of strlen() use sizeof() in FL() macro. This way
all the checks are done at compile time instead of runtime.
Signed-off-by: Jukka Rissanen <jukka.rissanen@nordicsemi.no>
Add a helper function which allows to send a RST packet in response to
an unexpected TCP packet, w/o associated connection or net context.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
To avoid a TCP connection from collapsing a link, implement a collision
avoidance algorithm. Initially TCP new Reno is implemented for its
simplicity.
Signed-off-by: Sjors Hettinga <s.a.hettinga@gmail.com>
Added a feature of socket connect
being asynchronous. If socket is set
to nonblock with O_NONBLOCK flag,
then connect() is non-blocking aswell.
App can normally poll the socket to
test when the connection is established.
Signed-off-by: Daniel Nejezchleb <dnejezchleb@hwg.cz>
TCP packet allocation timeout is currently 100ms, but there are cases
where it is not enough and as a side effect, the kernel internals are
printing some errors on the log before retrying again, create a
Kconfig parameter to be able to tune this value.
Signed-off-by: Luca Fancellu <luca.fancellu@arm.com>
SO_RCVBUF option processing at the TCP level was broken. The option
value was only checked once, when the TCP context was allocated. This
made little sense, as at this point the option would not even get a
chance to have custom value. If the user modified the option after the
socket (net_context) was created, it had no effect on the TCP operation.
This commit fixes this, by checking the option value whenever new packet
is processed, so that the configured window size is updated at the TCP
level before we report it in the TCP ACK. In order to achieve this,
introduce a new helper function, to refresh the configured window sizes,
to avoid bloating `tcp_in()` even further.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
Clean up occurrences of "#if IS_ENABLED(CONFIG_FOO)" an replace
with classical "#if defined(CONFIG_FOO)".
Signed-off-by: Erwan Gouriou <erwan.gouriou@linaro.org>
In order to avoid using multiple sources of truth for the platfom's
endianness, convert the in-tree code to use the (BIG|LITTLE)_ENDIAN
Kconfig variables exclusively, instead of the compiler's
__BYTE_ORDER__.
Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>
Instead of waiting for the retransmit timeout, retransmit as soon as
missing data is deduced based on a triple-duplicate ACK.
Increase the number of buffers in the testcase, to allow for at least 4
packets in flight to trigger the triple-duplicate ACK.
Signed-off-by: Sjors Hettinga <s.a.hettinga@gmail.com>
Persist timer should implement exponential backoff, as per RFC 1122:
The transmitting host SHOULD send the first zero-window
probe when a zero window has existed for the retransmission
timeout period (see Section 4.2.2.15), and SHOULD increase
exponentially the interval between successive probes.
Implement this, by following Linux behaviour, and simply double the
timeout or each probe transmission.
Additionally, prevent reseting the persist timer in case an
acknowledgment is received with zero window size, and the timer is
already running.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
In case peer does not send the MSS option, the TCP stack should assume
default peer MSS value of 536, as per RFC 1122:
If an MSS option is not received at connection setup, TCP
MUST assume a default send MSS of 536.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
It can happen that two similar stacks enter a retransmission cycle
due to a packet collision. If the transmission timeout is the same
both stacks will retry at the same moment resulting in another
collision.
By introducing a randomized retry timeout, the chance of
a second collision is reduced and it reduces furter the more
retransmissions occur.
Signed-off-by: Sjors Hettinga <s.a.hettinga@gmail.com>
Implement a mechanism, according to RFC 813, which allows to prevent so
called "Silly Window Syndrome" - a scenario where the TCP receiver keeps
reporting small window sizes in the acknowledgments, effectively
limiting the connection throughput. This allows to improve performance
in low-buffer configurations, where the maximum window size is small,
and the issue was hitting quite often.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
To improve the performance with small chunks send, implement Nagle's
algorithm. Provide the option TCP_NODELAY to disable the algorithm.
Signed-off-by: Sjors Hettinga <s.a.hettinga@gmail.com>
In the existing the value received from the other side by the TCP options
is used as MSS for transmission. Since the MSS options are an
announcement rather then a negotionation, it is likely the receiver will
have a different and possibly bigger MSS than allowed by our side.
This allow potentially for different a MSS in the receive and transmit
path.
Directly using the received MSS could cause problems when our MSS is only
allowed to be small. At transmission, for that reason take the minimum of
the received MSS and our desired MSS to find a value compatible to both
sides of the link.
Rename the function to net_tcp_get_recv_mss to net_tcp_get_supported_mss
to better reflect its function in the new situation.
Signed-off-by: Sjors Hettinga <s.a.hettinga@gmail.com>
Instead of sending ZWP from send context, when it is detected that
window is full due to zero-window, implement a proper persistent timer,
that is scheduled once zero-window is detected. The timer is responsible
for sending ZWP to the peer and is canceled once non-zero-window is
notified by the peer.
Additionally, in case peer reported zero-window, do not trigger
retransmission from net_tcp_queue_data(), as it won't be transmitted
anyway by the stack.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
The semaphore is reset when TCP layer would normally reject transfer
request (either due to TX window being full or entering retransmission
mode). Once data is acnowledged, or the reatransmission is done, the
semaphore is set again.
Upper layers can monitor the semaphore with `k_poll()` instead of
waiting blindly before attempting to transmit again.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
TCP2 is no longer needed as it is the unique implementation since the
legacy one has been removed.
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>