History

tcp: refine tcp_write_queue_empty() implementation

Due to how tcp_sendmsg() is implemented, we can have an empty skb at the tail of the write queue. Most [1] tcp_write_queue_empty() callers want to know if there is anything to send (payload and/or FIN) Instead of checking if the sk_write_queue is empty, we need to test if tp->write_seq == tp->snd_nxt [1] tcp_send_fin() was the only caller that expected to see if an skb was in the write queue, I have changed the code to reuse the tcp_write_queue_tail() result.

Eric Dumazet committed 6 years ago

Commit ee2aabd1 parent 1f85e622 files · +13 −3Browse files

Unified · Split

2 files
  1. include/net/tcp.h +10 −1
  2. net/ipv4/tcp_output.c +3 −2
include/net/tcp.h+10−1
@@ -1766,9 +1766,18 @@ static inline bool tcp_skb_is_last(const struct sock *sk, · 1765 unmodified lines
17661766 return skb_queue_is_last(&sk->sk_write_queue, skb);
17671767 }
17681768
1769+/**
1770+ * tcp_write_queue_empty - test if any payload (or FIN) is available in write queue
1771+ * @sk: socket
1772+ *
1773+ * Since the write queue can have a temporary empty skb in it,
1774+ * we must not use "return skb_queue_empty(&sk->sk_write_queue)"
1775+ */
17691776 static inline bool tcp_write_queue_empty(const struct sock *sk)
17701777 {
1771− return skb_queue_empty(&sk->sk_write_queue);
1778+ const struct tcp_sock *tp = tcp_sk(sk);
1779+
1780+ return tp->write_seq == tp->snd_nxt;
17721781 }
17731782
17741783 static inline bool tcp_rtx_queue_empty(const struct sock *sk)
net/ipv4/tcp_output.c+3−2
@@ -3129,7 +3129,7 @@ void sk_forced_mem_schedule(struct sock *sk, int size) · 3128 unmodified lines
31293129 */
31303130 void tcp_send_fin(struct sock *sk)
31313131 {
3132− struct sk_buff *skb, *tskb = tcp_write_queue_tail(sk);
3132+ struct sk_buff *skb, *tskb, *tail = tcp_write_queue_tail(sk);
31333133 struct tcp_sock *tp = tcp_sk(sk);
31343134
31353135 /* Optimization, tack on the FIN if we have one skb in write queue and
@@ -3137,6 +3137,7 @@ void tcp_send_fin(struct sock *sk) · 1 unmodified line
31373137 * Note: in the latter case, FIN packet will be sent after a timeout,
31383138 * as TCP stack thinks it has already been transmitted.
31393139 */
3140+ tskb = tail;
31403141 if (!tskb && tcp_under_memory_pressure(sk))
31413142 tskb = skb_rb_last(&sk->tcp_rtx_queue);
31423143
@@ -3144,7 +3145,7 @@ void tcp_send_fin(struct sock *sk) · 1 unmodified line
31443145 TCP_SKB_CB(tskb)->tcp_flags |= TCPHDR_FIN;
31453146 TCP_SKB_CB(tskb)->end_seq++;
31463147 tp->write_seq++;
3147− if (tcp_write_queue_empty(sk)) {
3148+ if (!tail) {
31483149 /* This means tskb was already sent.
31493150 * Pretend we included the FIN on previous transmit.
31503151 * We need to set tp->snd_nxt to the value it would have

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t