sock_orphan() call to sk_set_socket() implies clearing the sock TX queue. This might cause unexpected out-of-order transmit, as outstanding packets can pick a different TX queue and bypass the ones already queued. This is undesired in general. More specifically, it breaks the in-order scheduling property guarantee for device-offloaded TLS sockets.
Introduce a function variation __sk_set_socket() that does not clear the TX queue, and call it from sock_orphan(). All other callers of sk_set_socket() do not operate on an active socket, so they do not need this change. Fixes: e022f0b4a03f ("net: Introduce sk_tx_queue_mapping") Signed-off-by: Tariq Toukan <tar...@mellanox.com> Reviewed-by: Boris Pismenny <bor...@mellanox.com> --- include/net/sock.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) Please queue for -stable. diff --git a/include/net/sock.h b/include/net/sock.h index c53cc42b5ab9..23e43f3d79f0 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1846,10 +1846,15 @@ static inline int sk_rx_queue_get(const struct sock *sk) } #endif +static inline void __sk_set_socket(struct sock *sk, struct socket *sock) +{ + sk->sk_socket = sock; +} + static inline void sk_set_socket(struct sock *sk, struct socket *sock) { sk_tx_queue_clear(sk); - sk->sk_socket = sock; + __sk_set_socket(sk, sock); } static inline wait_queue_head_t *sk_sleep(struct sock *sk) @@ -1868,7 +1873,7 @@ static inline void sock_orphan(struct sock *sk) { write_lock_bh(&sk->sk_callback_lock); sock_set_flag(sk, SOCK_DEAD); - sk_set_socket(sk, NULL); + __sk_set_socket(sk, NULL); sk->sk_wq = NULL; write_unlock_bh(&sk->sk_callback_lock); } -- 1.8.3.1