Skip to content

Commit

Permalink
tcp: avoid indirect calls to sock_rfree
Browse files Browse the repository at this point in the history
TCP uses sk_eat_skb() when skbs can be removed from receive queue.
However, the call so skb_orphan() from __kfree_skb() incurs
an indirect call so sock_rfee(), which is more expensive than
a direct call, especially for CONFIG_RETPOLINE=y.

Add tcp_eat_recv_skb() function to make the call before
__kfree_skb().

Signed-off-by: Eric Dumazet <edumazet@google.com>
  • Loading branch information
Eric Dumazet authored and xanmod committed Jan 12, 2022
1 parent 3b47a3a commit bb1c0c8
Showing 1 changed file with 15 additions and 5 deletions.
20 changes: 15 additions & 5 deletions net/ipv4/tcp.c
Expand Up @@ -1581,6 +1581,16 @@ void tcp_cleanup_rbuf(struct sock *sk, int copied)
tcp_send_ack(sk);
}

static void tcp_eat_recv_skb(struct sock *sk, struct sk_buff *skb)
{
if (likely(skb->destructor == sock_rfree)) {
sock_rfree(skb);
skb->destructor = NULL;
skb->sk = NULL;
}
sk_eat_skb(sk, skb);
}

static struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off)
{
struct sk_buff *skb;
Expand All @@ -1600,7 +1610,7 @@ static struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off)
* splitted a fat GRO packet, while we released socket lock
* in skb_splice_bits()
*/
sk_eat_skb(sk, skb);
tcp_eat_recv_skb(sk, skb);
}
return NULL;
}
Expand Down Expand Up @@ -1666,11 +1676,11 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
continue;
}
if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN) {
sk_eat_skb(sk, skb);
tcp_eat_recv_skb(sk, skb);
++seq;
break;
}
sk_eat_skb(sk, skb);
tcp_eat_recv_skb(sk, skb);
if (!desc->count)
break;
WRITE_ONCE(tp->copied_seq, seq);
Expand Down Expand Up @@ -2485,14 +2495,14 @@ static int tcp_recvmsg_locked(struct sock *sk, struct msghdr *msg, size_t len,
if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN)
goto found_fin_ok;
if (!(flags & MSG_PEEK))
sk_eat_skb(sk, skb);
tcp_eat_recv_skb(sk, skb);
continue;

found_fin_ok:
/* Process the FIN. */
WRITE_ONCE(*seq, *seq + 1);
if (!(flags & MSG_PEEK))
sk_eat_skb(sk, skb);
tcp_eat_recv_skb(sk, skb);
break;
} while (len > 0);

Expand Down

0 comments on commit bb1c0c8

Please sign in to comment.