Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tcp: kill pointless urg_mode

It all started from me noticing that this urgent check in
tcp_clean_rtx_queue is unnecessarily inside the loop. Then
I took a longer look to it and found out that the users of
urg_mode can trivially do without, well almost, there was
one gotcha.

Bonus: those funny people who use urg with >= 2^31 write_seq -
snd_una could now rejoice too (that's the only purpose for the
between being there, otherwise a simple compare would have done
the thing). Not that I assume that the rest of the tcp code
happily lives with such mind-boggling numbers :-). Alas, it
turned out to be impossible to set wmem to such numbers anyway,
yes I really tried a big sendfile after setting some wmem but
nothing happened :-). ...Tcp_wmem is int and so is sk_sndbuf...
So I hacked a bit variable to long and found out that it seems
to work... :-)

Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Ilpo Järvinen and committed by
David S. Miller
33f5f57e 654bed16

+24 -19
+4 -5
include/linux/tcp.h
··· 312 312 u32 retrans_out; /* Retransmitted packets out */ 313 313 314 314 u16 urg_data; /* Saved octet of OOB data and control flags */ 315 - u8 urg_mode; /* In urgent mode */ 316 315 u8 ecn_flags; /* ECN status bits. */ 316 + u8 reordering; /* Packet reordering metric. */ 317 + u32 snd_up; /* Urgent pointer */ 318 + 319 + u8 keepalive_probes; /* num of allowed keep alive probes */ 317 320 /* 318 321 * Options received (usually on last packet, some only on SYN packets). 319 322 */ ··· 364 361 365 362 u32 lost_retrans_low; /* Sent seq after any rxmit (lowest) */ 366 363 367 - u8 reordering; /* Packet reordering metric. */ 368 - u8 keepalive_probes; /* num of allowed keep alive probes */ 369 364 u32 prior_ssthresh; /* ssthresh saved at recovery start */ 370 365 u32 high_seq; /* snd_nxt at onset of congestion */ 371 366 ··· 375 374 u32 total_retrans; /* Total retransmits for entire connection */ 376 375 377 376 u32 urg_seq; /* Seq of received urgent pointer */ 378 - u32 snd_up; /* Urgent pointer */ 379 - 380 377 unsigned int keepalive_time; /* time before keep alive takes place */ 381 378 unsigned int keepalive_intvl; /* time interval between keep alive probes */ 382 379
+1 -3
net/ipv4/tcp.c
··· 497 497 static inline void tcp_mark_urg(struct tcp_sock *tp, int flags, 498 498 struct sk_buff *skb) 499 499 { 500 - if (flags & MSG_OOB) { 501 - tp->urg_mode = 1; 500 + if (flags & MSG_OOB) 502 501 tp->snd_up = tp->write_seq; 503 - } 504 502 } 505 503 506 504 static inline void tcp_push(struct sock *sk, int flags, int mss_now,
+6 -5
net/ipv4/tcp_input.c
··· 2836 2836 * is before the ack sequence we can discard it as it's confirmed to have 2837 2837 * arrived at the other end. 2838 2838 */ 2839 - static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets) 2839 + static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets, 2840 + u32 prior_snd_una) 2840 2841 { 2841 2842 struct tcp_sock *tp = tcp_sk(sk); 2842 2843 const struct inet_connection_sock *icsk = inet_csk(sk); ··· 2904 2903 if (sacked & TCPCB_LOST) 2905 2904 tp->lost_out -= acked_pcount; 2906 2905 2907 - if (unlikely(tp->urg_mode && !before(end_seq, tp->snd_up))) 2908 - tp->urg_mode = 0; 2909 - 2910 2906 tp->packets_out -= acked_pcount; 2911 2907 pkts_acked += acked_pcount; 2912 2908 ··· 2932 2934 if (skb == tp->lost_skb_hint) 2933 2935 tp->lost_skb_hint = NULL; 2934 2936 } 2937 + 2938 + if (likely(between(tp->snd_up, prior_snd_una, tp->snd_una))) 2939 + tp->snd_up = tp->snd_una; 2935 2940 2936 2941 if (skb && (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)) 2937 2942 flag |= FLAG_SACK_RENEGING; ··· 3312 3311 goto no_queue; 3313 3312 3314 3313 /* See if we can take anything off of the retransmit queue. */ 3315 - flag |= tcp_clean_rtx_queue(sk, prior_fackets); 3314 + flag |= tcp_clean_rtx_queue(sk, prior_fackets, prior_snd_una); 3316 3315 3317 3316 if (tp->frto_counter) 3318 3317 frto_cwnd = tcp_process_frto(sk, flag);
+1
net/ipv4/tcp_minisocks.c
··· 395 395 newtp->pred_flags = 0; 396 396 newtp->rcv_wup = newtp->copied_seq = newtp->rcv_nxt = treq->rcv_isn + 1; 397 397 newtp->snd_sml = newtp->snd_una = newtp->snd_nxt = treq->snt_isn + 1; 398 + newtp->snd_up = treq->snt_isn + 1; 398 399 399 400 tcp_prequeue_init(newtp); 400 401
+12 -6
net/ipv4/tcp_output.c
··· 345 345 TCP_SKB_CB(skb)->end_seq = seq; 346 346 } 347 347 348 + static inline int tcp_urg_mode(const struct tcp_sock *tp) 349 + { 350 + return tp->snd_una != tp->snd_up; 351 + } 352 + 348 353 #define OPTION_SACK_ADVERTISE (1 << 0) 349 354 #define OPTION_TS (1 << 1) 350 355 #define OPTION_MD5 (1 << 2) ··· 651 646 th->check = 0; 652 647 th->urg_ptr = 0; 653 648 654 - if (unlikely(tp->urg_mode && 649 + /* The urg_mode check is necessary during a below snd_una win probe */ 650 + if (unlikely(tcp_urg_mode(tp) && 655 651 between(tp->snd_up, tcb->seq + 1, tcb->seq + 0xFFFF))) { 656 652 th->urg_ptr = htons(tp->snd_up - tcb->seq); 657 653 th->urg = 1; ··· 1018 1012 /* Compute the current effective MSS, taking SACKs and IP options, 1019 1013 * and even PMTU discovery events into account. 1020 1014 * 1021 - * LARGESEND note: !urg_mode is overkill, only frames up to snd_up 1015 + * LARGESEND note: !tcp_urg_mode is overkill, only frames up to snd_up 1022 1016 * cannot be large. However, taking into account rare use of URG, this 1023 1017 * is not a big flaw. 1024 1018 */ ··· 1035 1029 1036 1030 mss_now = tp->mss_cache; 1037 1031 1038 - if (large_allowed && sk_can_gso(sk) && !tp->urg_mode) 1032 + if (large_allowed && sk_can_gso(sk) && !tcp_urg_mode(tp)) 1039 1033 doing_tso = 1; 1040 1034 1041 1035 if (dst) { ··· 1199 1193 /* Don't use the nagle rule for urgent data (or for the final FIN). 1200 1194 * Nagle can be ignored during F-RTO too (see RFC4138). 1201 1195 */ 1202 - if (tp->urg_mode || (tp->frto_counter == 2) || 1196 + if (tcp_urg_mode(tp) || (tp->frto_counter == 2) || 1203 1197 (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN)) 1204 1198 return 1; 1205 1199 ··· 2364 2358 tcp_init_wl(tp, tp->write_seq, 0); 2365 2359 tp->snd_una = tp->write_seq; 2366 2360 tp->snd_sml = tp->write_seq; 2361 + tp->snd_up = tp->write_seq; 2367 2362 tp->rcv_nxt = 0; 2368 2363 tp->rcv_wup = 0; 2369 2364 tp->copied_seq = 0; ··· 2574 2567 tcp_event_new_data_sent(sk, skb); 2575 2568 return err; 2576 2569 } else { 2577 - if (tp->urg_mode && 2578 - between(tp->snd_up, tp->snd_una + 1, tp->snd_una + 0xFFFF)) 2570 + if (between(tp->snd_up, tp->snd_una + 1, tp->snd_una + 0xFFFF)) 2579 2571 tcp_xmit_probe_skb(sk, 1); 2580 2572 return tcp_xmit_probe_skb(sk, 0); 2581 2573 }