Skip to content

Commit 3df684c

Browse files
edumazetdavem330
authored andcommitted
tcp: avoid indirect calls to sock_rfree
TCP uses sk_eat_skb() when skbs can be removed from receive queue. However, the call to 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 <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent b96c51b commit 3df684c

File tree

1 file changed

+15
-5
lines changed

1 file changed

+15
-5
lines changed

net/ipv4/tcp.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1580,6 +1580,16 @@ void tcp_cleanup_rbuf(struct sock *sk, int copied)
15801580
tcp_send_ack(sk);
15811581
}
15821582

1583+
static void tcp_eat_recv_skb(struct sock *sk, struct sk_buff *skb)
1584+
{
1585+
if (likely(skb->destructor == sock_rfree)) {
1586+
sock_rfree(skb);
1587+
skb->destructor = NULL;
1588+
skb->sk = NULL;
1589+
}
1590+
sk_eat_skb(sk, skb);
1591+
}
1592+
15831593
static struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off)
15841594
{
15851595
struct sk_buff *skb;
@@ -1599,7 +1609,7 @@ static struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off)
15991609
* splitted a fat GRO packet, while we released socket lock
16001610
* in skb_splice_bits()
16011611
*/
1602-
sk_eat_skb(sk, skb);
1612+
tcp_eat_recv_skb(sk, skb);
16031613
}
16041614
return NULL;
16051615
}
@@ -1665,11 +1675,11 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
16651675
continue;
16661676
}
16671677
if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN) {
1668-
sk_eat_skb(sk, skb);
1678+
tcp_eat_recv_skb(sk, skb);
16691679
++seq;
16701680
break;
16711681
}
1672-
sk_eat_skb(sk, skb);
1682+
tcp_eat_recv_skb(sk, skb);
16731683
if (!desc->count)
16741684
break;
16751685
WRITE_ONCE(tp->copied_seq, seq);
@@ -2481,14 +2491,14 @@ static int tcp_recvmsg_locked(struct sock *sk, struct msghdr *msg, size_t len,
24812491
if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN)
24822492
goto found_fin_ok;
24832493
if (!(flags & MSG_PEEK))
2484-
sk_eat_skb(sk, skb);
2494+
tcp_eat_recv_skb(sk, skb);
24852495
continue;
24862496

24872497
found_fin_ok:
24882498
/* Process the FIN. */
24892499
WRITE_ONCE(*seq, *seq + 1);
24902500
if (!(flags & MSG_PEEK))
2491-
sk_eat_skb(sk, skb);
2501+
tcp_eat_recv_skb(sk, skb);
24922502
break;
24932503
} while (len > 0);
24942504

0 commit comments

Comments
 (0)