In the stack both unacked_len and send_data_total track the amount
of data for retransmission. send_data_total actually accounts the
total bytes in the buffer, where unacked_len is used to control the
retransmission progress.
Using unacked_len is sometimes reset to 0, this can lead to more data
being allowd in the send_data buffer. In worse case this can cause
depletion of the net buffers, causing a stall and crash of the connection.
The value send_data_total actually accounts the total amount of data in
the send_data buffer, so it is the proper value to used in the
tcp_window_full function.
Signed-off-by: Sjors Hettinga <s.a.hettinga@gmail.com>
In the function tcp_send_data, the variable conn->unacked_len in copied
into a local variable pos. This value is only used in one location and
used mixed with the original conn->unacked_len.
This fix removes pos and switches to use conn->unacked_len everywhere
to reduce the chance of confusion. This does not functionally change the
code.
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>
Make use of the status argument in the recv_cb() callback function -
instead of blindly reporting ECONNRESET whenever TCP context is
dereferenced, indicate whether an actual error condition happened (by
setting respective errno value) or a graceful shutdown took place (by
setting status to 0).
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
Remove NET_TCP_BACKLOG_SIZE from KConfig and from test,
because it's not present anymore in current version of TCP stack.
Signed-off-by: Andrey Dodonov <Andrey.Dodonov@endress.com>
After introducing SO_SNDBUF socket option, a possible deadlock situation
slipped into the TCP implementation. The scenario for the deadlock:
* application thread tries to send some data, it enters
net_context_send() which locks the context mutex,
* internal context_sendto() blocks on a TX packet allocation, if the
TX pool is empty rescheduling takes place,
* now, if at the same time some incoming packet has arrived (ACK for
example), TCP stack enters tcp_in() function from a different
thread. The function locks the TCP connection mutex, and tries to
obtain the SNDBUF option value. net_context_get_option() tries to
lock the context mutex, but it is already held by the transmitting
thread, so the receiver thread blocks
* when TX packet is available again, the transmitting thread unblocks
and tries to pass the packet down to TCP stack. net_tcp_queue_data()
is called which attempts to lock the TCP connection mutex, but it is
already held by the receiving thread. Both threads are in a deadlock
now with no chance to recover.
Fix this, by obtaining the SNDBUF option value in tcp_in() before
locking the TCP connection mutex.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
In order to bring consistency in-tree, migrate all subsystems code to
the new prefix <zephyr/...>. Note that the conversion has been scripted,
refer to zephyrproject-rtos#45388 for more details.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
This complements the Kconfig possibility, and allows setting an
interface as default on runtime. Changing the default interface also
works around limitations when trying to use an offloaded interface
together with a native one.
Signed-off-by: Ole Morten Haaland <omh@icsys.no>
Instead of using a fixed fin timeout, compute it based on the number
of retries. Fixes issue found by PR 44545.
Signed-off-by: Sjors Hettinga <s.a.hettinga@gmail.com>
Introduce set/get SO_SNDBUF option using the setsockopt
function. In addition, for TCP, check the sndbuf value
before queuing data.
Signed-off-by: Mohan Kumar Kumar <mohankm@fb.com>
Log an error when allocating a network packet for transmission fails.
This is a problem which can be solved by increasing
`CONFIG_NET_PKT_TX_COUNT`, but is currently hard to diagnose.
Signed-off-by: Jordan Yates <jordan.yates@data61.csiro.au>
Introduce set/get SO_RCVBUF option using the setsockopt
function. In addition, use the rcvbuf value to set the
tcp recv window.
Signed-off-by: Mohan Kumar Kumar <mohankm@fb.com>
When connect() is called on a TCP socket, tcp_in() is called with a NULL
packet to start establishing a connection. That in turn leads to a SYN
packet being produced which, depending on the Ethernet driver, may
result in a synchronous transmit of that packet. After that, the
connect() implementation, which at this point is executing
net_tcp_connect() starts waiting to take a semaphore until the
connection timeout is reached. However, if the transmit of the SYN
packet results in a RST packet being returned from the connection
destination (due to there being no listening socket) very quickly on a
local network, the device driver may deliver an interrupt which can
cause the receive path of the network stack to run, resulting in the
tcp_in() of the RST packet via the network RX thread. That can cause
tcp_conn_unref() to be called before the connecting thread has gotten
to the point of acquiring (or failing to) the semaphore, which results
in a deinitialized semaphore being accessed.
This commit fixes the possible race condition by ensuring that the
connection lock mutex is held until after the connection state moves
to "in connect."
Fixes#44186
Signed-off-by: Berend Ozceri <berend@recogni.com>
When TCP stack enters retransmission mode, the variable tracking the
amount of unacknowledged data is cleared. This prevents the stack from
detecting when TX window is full, which could lead to queueing unlimited
amount of data, effectively consuming all of the avaiable network
buffers.
Prevent this, by returning early from net_tcp_queue_data() in case TCP
stack is in retransmission mode. The socket layer will take care of
retrying just as in case the window is full.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
In case a loopback or own address is used in TCP connection, the TCP
stack delegates the acatual data send to a workqueue. This is fine,
however it could lead to some aritificial delays in case a lot of data
is being sent before the workqueue has a chance to execute queued work
items. In such case, we only sent a single packet, when many could've
already been queued.
Fix this, by resubmitting the queue in case a local address is used, and
there's still more packets pending for send.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
When peer reports a zero length receive window, the TCP stack block any
outgoing data from being queued. In case no further ACK comes from the
peer, the whole communication could stall. Fix this by sending a simple
Zero Window Probe, when we detect a Zero Length Window.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
The ARRAY_SIZE macro uses sizeof and thus the return
type should be an unsigned value. size_t is typically
the type used for sizeof and fits well for the
ARRAY_SIZE macro as well.
Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
Closing a listening socket will set the accept callback to NULL.
This could lead to a crash, in case an already received packet,
finalizing the connection handshake, was processed after the socket was
closed. Thereby, it's needed to verify if the callback is actually set
before processing it.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
TCP processed IPv4/IPv6 packets w/o verifying first if IPv4/IPv6 is
enabled in the system. This could lead to problems especially for IPv6,
where in case it's disabled the sockaddr structure is not large enough
to accomodate IPv6 address, leading to possible out-of-bound access on
the sockaddr structure.
Fix this by adding appropriate checks where applicable.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
As the receive window is now decreased at the TCP module level, other
direct net_context users are also responsible for acknowledging the
received data with net_context_update_recv_wnd() - otherwise, the
communication will stall.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
According to Kconfig guidelines, boolean prompts must not start with
"Enable...". The following command has been used to automate the changes
in this patch:
sed -i "s/bool \"[Ee]nables\? \(\w\)/bool \"\U\1/g" **/Kconfig*
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
Peer may send a zero-length keepalive message, probing the recv window
size - TCP stack should still reply for such packets, otherwise
connection will stall.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
Add implementation of net_tcp_update_recv_wnd() function.
Move the window deacreasing code to the tcp module - receive window
has to be decreased before sending ACK, which was not possible when
window was decreased in the receive callback function.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
This reverts commit e7489d8de7.
And fixes the deadlock by allowing only 1 thread to actualy clean up
the connection when the ref_count is 0.
Signed-off-by: Daniel Nejezchleb <dnejezchleb@hwg.cz>
Unlock tcp_lock when calling the recv_cb. In case when
a connection is being closed from both the tcp stack
and the application, a race condition can happen resulting
in locking each other out on tcp_lock and socket lock.
Signed-off-by: Daniel Nejezchleb <dnejezchleb@hwg.cz>
Increments send retry every time
after the tcp_send_data when resending.
That way unhandled return values can time
out after set amount of tcp_retries.
Signed-off-by: Daniel Nejezchleb <dnejezchleb@hwg.cz>
A common pattern here was to take the work item as the subfield of a
containing object. But the contained field is not a k_work, it's a
k_work_delayable.
Things were working only because the work field was first, so the
pointers had the same value. Do things right and fix things to
produce correct code if/when that field ever moves within delayable.
Signed-off-by: Yong Cong Sin <yongcong.sin@gmail.com>
In a similar way as its done for IPv6. This allows to rejoin the group
once the interface is up again.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
Conceptually the net_mgmt_lock should be a mutex instead of a
semaphore. It is easier to identify the owner of a mutex and
debug when deadlock happens, so convert it.
Signed-off-by: Yong Cong Sin <yongcong.sin@gmail.com>
The strtol() function use errno to return error code.
However, it is not being initialized in the parser_arg()
function before calling the strtol(). Thus, hitting error
when performing net ping command with -c / -i parameters.
Signed-off-by: Kweh Hock Leong <hock.leong.kweh@intel.com>
Log_strdup was used in NET_ASSERT macro which is not logging.
As a result linking fails when logging is disabled but asserts
are enabled.
Signed-off-by: Krzysztof Chruscinski <krzysztof.chruscinski@nordicsemi.no>
For instance, DHCP (UDP protocol) can send broadcasted packet and if we
no not serve the requested destination port, let's not send an error
back.
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
Invert src/dst strings, the icmpv4 error is sent from the dst (us) to
src (sender of the ipv4 packet that generated the error).
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
This provides the infrastructure to create network packet filter rules
and to apply them to the RX and TX packet paths. Rules are made of
simple condition tests that can be linked together, creating a facility
similarly to the Linux iptables functionality.
A couple of generic and Ethernet-specific condition tests are also
provided.
Additional tests can be easily created on top of this.
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
Since most of the functions will access non thread-safe resources like
SLIST, and can be invoked from different threads (like the expiry timer
delayed work), add mutex protection to the function calls.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
Implement a concept of Route Preference, as specified in RFC 4191. The
Zephyr host will prefer routes with higher preference, if they lead to
the same prefix through different neighbours.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
Add support for route lifetime, as defined in RFC 4191. The existing
route adding logic remains the same, if not specified, lifetime is set
to infinite. For routes added with Route Info option from ICMPv6 RA
message, set the expiration timer, according to the route lifetime value
received.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
This commits adds handling of the Route Information option from
the Router Advertisement message. This option allows to add/delete
routes in the host based on the information sent by the router.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
When new route is allocated, a corresponding NBR entry (containing
`struct net_route_nexthop` data) is allocated from
`net_route_nexthop_pool`. When the route was deleted however, the entry
was not freed - only the "core" neighbor entry from the neighbor
management module (nbr.c) was dereferenced. This lead to a resource
leak, effecitevly leaking one `net_route_nexthop_pool` entry for each
deleted route.
Fix this, by defreferencing the NBR entry corresponding to the `struct
net_route_nexthop` data of the deleted route when route is removed.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
Verify the `ref` value of the neighbor entry in `net_route_foreach()`,
so that it only executes the callback on routes in use. Otherwise, the
function could call the callback for the route that has already been
deleted.
This could be encountered when executing `net route` shell command,
which printed the already deleted routes along the existing ones.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>