mirror of
https://github.com/torvalds/linux.git
synced 2026-06-01 02:53:36 +02:00
Merge branch 'tcp-take-care-of-tcp_get_timestamping_opt_stats-races'
Eric Dumazet says: ==================== tcp: take care of tcp_get_timestamping_opt_stats() races tcp_get_timestamping_opt_stats() does not own the socket lock, this is intentional. It calls tcp_get_info_chrono_stats() while other threads could change chrono fields in tcp_chrono_set(). It also reads many tcp socket fields that can be modified by other cpus/threads. I do not think we need coherent TCP socket state snapshot in tcp_get_timestamping_opt_stats(). Add READ_ONCE()/WRITE_ONCE() or data_race() annotations. Note that icsk_ca_state is a bitfield, thus not covered in this series. ==================== Link: https://patch.msgid.link/20260416200319.3608680-1-edumazet@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
f3a0e90d4d
|
|
@ -1513,7 +1513,7 @@ static inline u32 tcp_snd_cwnd(const struct tcp_sock *tp)
|
|||
static inline void tcp_snd_cwnd_set(struct tcp_sock *tp, u32 val)
|
||||
{
|
||||
WARN_ON_ONCE((int)val <= 0);
|
||||
tp->snd_cwnd = val;
|
||||
WRITE_ONCE(tp->snd_cwnd, val);
|
||||
}
|
||||
|
||||
static inline bool tcp_in_slow_start(const struct tcp_sock *tp)
|
||||
|
|
@ -2208,10 +2208,14 @@ static inline void tcp_chrono_set(struct tcp_sock *tp, const enum tcp_chrono new
|
|||
const u32 now = tcp_jiffies32;
|
||||
enum tcp_chrono old = tp->chrono_type;
|
||||
|
||||
/* Following WRITE_ONCE()s pair with READ_ONCE()s in
|
||||
* tcp_get_info_chrono_stats().
|
||||
*/
|
||||
if (old > TCP_CHRONO_UNSPEC)
|
||||
tp->chrono_stat[old - 1] += now - tp->chrono_start;
|
||||
tp->chrono_start = now;
|
||||
tp->chrono_type = new;
|
||||
WRITE_ONCE(tp->chrono_stat[old - 1],
|
||||
tp->chrono_stat[old - 1] + now - tp->chrono_start);
|
||||
WRITE_ONCE(tp->chrono_start, now);
|
||||
WRITE_ONCE(tp->chrono_type, new);
|
||||
}
|
||||
|
||||
static inline void tcp_chrono_start(struct sock *sk, const enum tcp_chrono type)
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ static inline void tcp_accecn_third_ack(struct sock *sk,
|
|||
tcp_accecn_validate_syn_feedback(sk, ace, sent_ect)) {
|
||||
if ((tcp_accecn_extract_syn_ect(ace) == INET_ECN_CE) &&
|
||||
!tp->delivered_ce)
|
||||
tp->delivered_ce++;
|
||||
WRITE_ONCE(tp->delivered_ce, 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5396,7 +5396,7 @@ static int bpf_sol_tcp_setsockopt(struct sock *sk, int optname,
|
|||
if (val <= 0)
|
||||
return -EINVAL;
|
||||
tp->snd_cwnd_clamp = val;
|
||||
tp->snd_ssthresh = val;
|
||||
WRITE_ONCE(tp->snd_ssthresh, val);
|
||||
break;
|
||||
case TCP_BPF_DELACK_MAX:
|
||||
timeout = usecs_to_jiffies(val);
|
||||
|
|
|
|||
|
|
@ -3425,7 +3425,7 @@ int tcp_disconnect(struct sock *sk, int flags)
|
|||
icsk->icsk_rto = TCP_TIMEOUT_INIT;
|
||||
WRITE_ONCE(icsk->icsk_rto_min, TCP_RTO_MIN);
|
||||
WRITE_ONCE(icsk->icsk_delack_max, TCP_DELACK_MAX);
|
||||
tp->snd_ssthresh = TCP_INFINITE_SSTHRESH;
|
||||
WRITE_ONCE(tp->snd_ssthresh, TCP_INFINITE_SSTHRESH);
|
||||
tcp_snd_cwnd_set(tp, TCP_INIT_CWND);
|
||||
tp->snd_cwnd_cnt = 0;
|
||||
tp->is_cwnd_limited = 0;
|
||||
|
|
@ -3623,7 +3623,8 @@ static void tcp_enable_tx_delay(struct sock *sk, int val)
|
|||
if (delta && sk->sk_state == TCP_ESTABLISHED) {
|
||||
s64 srtt = (s64)tp->srtt_us + delta;
|
||||
|
||||
tp->srtt_us = clamp_t(s64, srtt, 1, ~0U);
|
||||
WRITE_ONCE(tp->srtt_us,
|
||||
clamp_t(s64, srtt, 1, ~0U));
|
||||
|
||||
/* Note: does not deal with non zero icsk_backoff */
|
||||
tcp_set_rto(sk);
|
||||
|
|
@ -4191,12 +4192,18 @@ static void tcp_get_info_chrono_stats(const struct tcp_sock *tp,
|
|||
struct tcp_info *info)
|
||||
{
|
||||
u64 stats[__TCP_CHRONO_MAX], total = 0;
|
||||
enum tcp_chrono i;
|
||||
enum tcp_chrono i, cur;
|
||||
|
||||
/* Following READ_ONCE()s pair with WRITE_ONCE()s in tcp_chrono_set().
|
||||
* This is because socket lock might not be owned by us at this point.
|
||||
* This is best effort, tcp_get_timestamping_opt_stats() can
|
||||
* see wrong values. A real fix would be too costly for TCP fast path.
|
||||
*/
|
||||
cur = READ_ONCE(tp->chrono_type);
|
||||
for (i = TCP_CHRONO_BUSY; i < __TCP_CHRONO_MAX; ++i) {
|
||||
stats[i] = tp->chrono_stat[i - 1];
|
||||
if (i == tp->chrono_type)
|
||||
stats[i] += tcp_jiffies32 - tp->chrono_start;
|
||||
stats[i] = READ_ONCE(tp->chrono_stat[i - 1]);
|
||||
if (i == cur)
|
||||
stats[i] += tcp_jiffies32 - READ_ONCE(tp->chrono_start);
|
||||
stats[i] *= USEC_PER_SEC / HZ;
|
||||
total += stats[i];
|
||||
}
|
||||
|
|
@ -4428,9 +4435,9 @@ struct sk_buff *tcp_get_timestamping_opt_stats(const struct sock *sk,
|
|||
nla_put_u64_64bit(stats, TCP_NLA_SNDBUF_LIMITED,
|
||||
info.tcpi_sndbuf_limited, TCP_NLA_PAD);
|
||||
nla_put_u64_64bit(stats, TCP_NLA_DATA_SEGS_OUT,
|
||||
tp->data_segs_out, TCP_NLA_PAD);
|
||||
READ_ONCE(tp->data_segs_out), TCP_NLA_PAD);
|
||||
nla_put_u64_64bit(stats, TCP_NLA_TOTAL_RETRANS,
|
||||
tp->total_retrans, TCP_NLA_PAD);
|
||||
READ_ONCE(tp->total_retrans), TCP_NLA_PAD);
|
||||
|
||||
rate = READ_ONCE(sk->sk_pacing_rate);
|
||||
rate64 = (rate != ~0UL) ? rate : ~0ULL;
|
||||
|
|
@ -4439,37 +4446,42 @@ struct sk_buff *tcp_get_timestamping_opt_stats(const struct sock *sk,
|
|||
rate64 = tcp_compute_delivery_rate(tp);
|
||||
nla_put_u64_64bit(stats, TCP_NLA_DELIVERY_RATE, rate64, TCP_NLA_PAD);
|
||||
|
||||
nla_put_u32(stats, TCP_NLA_SND_CWND, tcp_snd_cwnd(tp));
|
||||
nla_put_u32(stats, TCP_NLA_REORDERING, tp->reordering);
|
||||
nla_put_u32(stats, TCP_NLA_MIN_RTT, tcp_min_rtt(tp));
|
||||
nla_put_u32(stats, TCP_NLA_SND_CWND, READ_ONCE(tp->snd_cwnd));
|
||||
nla_put_u32(stats, TCP_NLA_REORDERING, READ_ONCE(tp->reordering));
|
||||
nla_put_u32(stats, TCP_NLA_MIN_RTT, data_race(tcp_min_rtt(tp)));
|
||||
|
||||
nla_put_u8(stats, TCP_NLA_RECUR_RETRANS,
|
||||
READ_ONCE(inet_csk(sk)->icsk_retransmits));
|
||||
nla_put_u8(stats, TCP_NLA_DELIVERY_RATE_APP_LMT, !!tp->rate_app_limited);
|
||||
nla_put_u32(stats, TCP_NLA_SND_SSTHRESH, tp->snd_ssthresh);
|
||||
nla_put_u32(stats, TCP_NLA_DELIVERED, tp->delivered);
|
||||
nla_put_u32(stats, TCP_NLA_DELIVERED_CE, tp->delivered_ce);
|
||||
nla_put_u8(stats, TCP_NLA_DELIVERY_RATE_APP_LMT, data_race(!!tp->rate_app_limited));
|
||||
nla_put_u32(stats, TCP_NLA_SND_SSTHRESH, READ_ONCE(tp->snd_ssthresh));
|
||||
nla_put_u32(stats, TCP_NLA_DELIVERED, READ_ONCE(tp->delivered));
|
||||
nla_put_u32(stats, TCP_NLA_DELIVERED_CE, READ_ONCE(tp->delivered_ce));
|
||||
|
||||
nla_put_u32(stats, TCP_NLA_SNDQ_SIZE, tp->write_seq - tp->snd_una);
|
||||
nla_put_u32(stats, TCP_NLA_SNDQ_SIZE,
|
||||
max_t(int, 0,
|
||||
READ_ONCE(tp->write_seq) - READ_ONCE(tp->snd_una)));
|
||||
nla_put_u8(stats, TCP_NLA_CA_STATE, inet_csk(sk)->icsk_ca_state);
|
||||
|
||||
nla_put_u64_64bit(stats, TCP_NLA_BYTES_SENT, tp->bytes_sent,
|
||||
nla_put_u64_64bit(stats, TCP_NLA_BYTES_SENT, READ_ONCE(tp->bytes_sent),
|
||||
TCP_NLA_PAD);
|
||||
nla_put_u64_64bit(stats, TCP_NLA_BYTES_RETRANS, tp->bytes_retrans,
|
||||
TCP_NLA_PAD);
|
||||
nla_put_u32(stats, TCP_NLA_DSACK_DUPS, tp->dsack_dups);
|
||||
nla_put_u32(stats, TCP_NLA_REORD_SEEN, tp->reord_seen);
|
||||
nla_put_u32(stats, TCP_NLA_SRTT, tp->srtt_us >> 3);
|
||||
nla_put_u16(stats, TCP_NLA_TIMEOUT_REHASH, tp->timeout_rehash);
|
||||
nla_put_u64_64bit(stats, TCP_NLA_BYTES_RETRANS,
|
||||
READ_ONCE(tp->bytes_retrans), TCP_NLA_PAD);
|
||||
nla_put_u32(stats, TCP_NLA_DSACK_DUPS, READ_ONCE(tp->dsack_dups));
|
||||
nla_put_u32(stats, TCP_NLA_REORD_SEEN, READ_ONCE(tp->reord_seen));
|
||||
nla_put_u32(stats, TCP_NLA_SRTT, READ_ONCE(tp->srtt_us) >> 3);
|
||||
nla_put_u16(stats, TCP_NLA_TIMEOUT_REHASH,
|
||||
READ_ONCE(tp->timeout_rehash));
|
||||
nla_put_u32(stats, TCP_NLA_BYTES_NOTSENT,
|
||||
max_t(int, 0, tp->write_seq - tp->snd_nxt));
|
||||
max_t(int, 0,
|
||||
READ_ONCE(tp->write_seq) - READ_ONCE(tp->snd_nxt)));
|
||||
nla_put_u64_64bit(stats, TCP_NLA_EDT, orig_skb->skb_mstamp_ns,
|
||||
TCP_NLA_PAD);
|
||||
if (ack_skb)
|
||||
nla_put_u8(stats, TCP_NLA_TTL,
|
||||
tcp_skb_ttl_or_hop_limit(ack_skb));
|
||||
|
||||
nla_put_u32(stats, TCP_NLA_REHASH, tp->plb_rehash + tp->timeout_rehash);
|
||||
nla_put_u32(stats, TCP_NLA_REHASH,
|
||||
READ_ONCE(tp->plb_rehash) + READ_ONCE(tp->timeout_rehash));
|
||||
return stats;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -897,8 +897,8 @@ static void bbr_check_drain(struct sock *sk, const struct rate_sample *rs)
|
|||
|
||||
if (bbr->mode == BBR_STARTUP && bbr_full_bw_reached(sk)) {
|
||||
bbr->mode = BBR_DRAIN; /* drain queue we created */
|
||||
tcp_sk(sk)->snd_ssthresh =
|
||||
bbr_inflight(sk, bbr_max_bw(sk), BBR_UNIT);
|
||||
WRITE_ONCE(tcp_sk(sk)->snd_ssthresh,
|
||||
bbr_inflight(sk, bbr_max_bw(sk), BBR_UNIT));
|
||||
} /* fall through to check if in-flight is already small: */
|
||||
if (bbr->mode == BBR_DRAIN &&
|
||||
bbr_packets_in_net_at_edt(sk, tcp_packets_in_flight(tcp_sk(sk))) <=
|
||||
|
|
@ -1043,7 +1043,7 @@ __bpf_kfunc static void bbr_init(struct sock *sk)
|
|||
struct bbr *bbr = inet_csk_ca(sk);
|
||||
|
||||
bbr->prior_cwnd = 0;
|
||||
tp->snd_ssthresh = TCP_INFINITE_SSTHRESH;
|
||||
WRITE_ONCE(tp->snd_ssthresh, TCP_INFINITE_SSTHRESH);
|
||||
bbr->rtt_cnt = 0;
|
||||
bbr->next_rtt_delivered = tp->delivered;
|
||||
bbr->prev_ca_state = TCP_CA_Open;
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ static void bictcp_init(struct sock *sk)
|
|||
bictcp_reset(ca);
|
||||
|
||||
if (initial_ssthresh)
|
||||
tcp_sk(sk)->snd_ssthresh = initial_ssthresh;
|
||||
WRITE_ONCE(tcp_sk(sk)->snd_ssthresh, initial_ssthresh);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ static void tcp_cdg_hystart_update(struct sock *sk)
|
|||
NET_ADD_STATS(sock_net(sk),
|
||||
LINUX_MIB_TCPHYSTARTTRAINCWND,
|
||||
tcp_snd_cwnd(tp));
|
||||
tp->snd_ssthresh = tcp_snd_cwnd(tp);
|
||||
WRITE_ONCE(tp->snd_ssthresh, tcp_snd_cwnd(tp));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -181,7 +181,7 @@ static void tcp_cdg_hystart_update(struct sock *sk)
|
|||
NET_ADD_STATS(sock_net(sk),
|
||||
LINUX_MIB_TCPHYSTARTDELAYCWND,
|
||||
tcp_snd_cwnd(tp));
|
||||
tp->snd_ssthresh = tcp_snd_cwnd(tp);
|
||||
WRITE_ONCE(tp->snd_ssthresh, tcp_snd_cwnd(tp));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ __bpf_kfunc static void cubictcp_init(struct sock *sk)
|
|||
bictcp_hystart_reset(sk);
|
||||
|
||||
if (!hystart && initial_ssthresh)
|
||||
tcp_sk(sk)->snd_ssthresh = initial_ssthresh;
|
||||
WRITE_ONCE(tcp_sk(sk)->snd_ssthresh, initial_ssthresh);
|
||||
}
|
||||
|
||||
__bpf_kfunc static void cubictcp_cwnd_event_tx_start(struct sock *sk)
|
||||
|
|
@ -420,7 +420,7 @@ static void hystart_update(struct sock *sk, u32 delay)
|
|||
NET_ADD_STATS(sock_net(sk),
|
||||
LINUX_MIB_TCPHYSTARTTRAINCWND,
|
||||
tcp_snd_cwnd(tp));
|
||||
tp->snd_ssthresh = tcp_snd_cwnd(tp);
|
||||
WRITE_ONCE(tp->snd_ssthresh, tcp_snd_cwnd(tp));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -440,7 +440,7 @@ static void hystart_update(struct sock *sk, u32 delay)
|
|||
NET_ADD_STATS(sock_net(sk),
|
||||
LINUX_MIB_TCPHYSTARTDELAYCWND,
|
||||
tcp_snd_cwnd(tp));
|
||||
tp->snd_ssthresh = tcp_snd_cwnd(tp);
|
||||
WRITE_ONCE(tp->snd_ssthresh, tcp_snd_cwnd(tp));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ static void dctcp_react_to_loss(struct sock *sk)
|
|||
struct tcp_sock *tp = tcp_sk(sk);
|
||||
|
||||
ca->loss_cwnd = tcp_snd_cwnd(tp);
|
||||
tp->snd_ssthresh = max(tcp_snd_cwnd(tp) >> 1U, 2U);
|
||||
WRITE_ONCE(tp->snd_ssthresh, max(tcp_snd_cwnd(tp) >> 1U, 2U));
|
||||
}
|
||||
|
||||
__bpf_kfunc static void dctcp_state(struct sock *sk, u8 new_state)
|
||||
|
|
|
|||
|
|
@ -476,14 +476,14 @@ static bool tcp_accecn_process_option(struct tcp_sock *tp,
|
|||
|
||||
static void tcp_count_delivered_ce(struct tcp_sock *tp, u32 ecn_count)
|
||||
{
|
||||
tp->delivered_ce += ecn_count;
|
||||
WRITE_ONCE(tp->delivered_ce, tp->delivered_ce + ecn_count);
|
||||
}
|
||||
|
||||
/* Updates the delivered and delivered_ce counts */
|
||||
static void tcp_count_delivered(struct tcp_sock *tp, u32 delivered,
|
||||
bool ece_ack)
|
||||
{
|
||||
tp->delivered += delivered;
|
||||
WRITE_ONCE(tp->delivered, tp->delivered + delivered);
|
||||
if (tcp_ecn_mode_rfc3168(tp) && ece_ack)
|
||||
tcp_count_delivered_ce(tp, delivered);
|
||||
}
|
||||
|
|
@ -1132,7 +1132,7 @@ static void tcp_rtt_estimator(struct sock *sk, long mrtt_us)
|
|||
|
||||
tcp_bpf_rtt(sk, mrtt_us, srtt);
|
||||
}
|
||||
tp->srtt_us = max(1U, srtt);
|
||||
WRITE_ONCE(tp->srtt_us, max(1U, srtt));
|
||||
}
|
||||
|
||||
void tcp_update_pacing_rate(struct sock *sk)
|
||||
|
|
@ -1246,7 +1246,7 @@ static u32 tcp_dsack_seen(struct tcp_sock *tp, u32 start_seq,
|
|||
else if (tp->tlp_high_seq && tp->tlp_high_seq == end_seq)
|
||||
state->flag |= FLAG_DSACK_TLP;
|
||||
|
||||
tp->dsack_dups += dup_segs;
|
||||
WRITE_ONCE(tp->dsack_dups, tp->dsack_dups + dup_segs);
|
||||
/* Skip the DSACK if dup segs weren't retransmitted by sender */
|
||||
if (tp->dsack_dups > tp->total_retrans)
|
||||
return 0;
|
||||
|
|
@ -1293,12 +1293,13 @@ static void tcp_check_sack_reordering(struct sock *sk, const u32 low_seq,
|
|||
tp->sacked_out,
|
||||
tp->undo_marker ? tp->undo_retrans : 0);
|
||||
#endif
|
||||
tp->reordering = min_t(u32, (metric + mss - 1) / mss,
|
||||
READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_max_reordering));
|
||||
WRITE_ONCE(tp->reordering,
|
||||
min_t(u32, (metric + mss - 1) / mss,
|
||||
READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_max_reordering)));
|
||||
}
|
||||
|
||||
/* This exciting event is worth to be remembered. 8) */
|
||||
tp->reord_seen++;
|
||||
WRITE_ONCE(tp->reord_seen, tp->reord_seen + 1);
|
||||
NET_INC_STATS(sock_net(sk),
|
||||
ts ? LINUX_MIB_TCPTSREORDER : LINUX_MIB_TCPSACKREORDER);
|
||||
}
|
||||
|
|
@ -2439,9 +2440,10 @@ static void tcp_check_reno_reordering(struct sock *sk, const int addend)
|
|||
if (!tcp_limit_reno_sacked(tp))
|
||||
return;
|
||||
|
||||
tp->reordering = min_t(u32, tp->packets_out + addend,
|
||||
READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_max_reordering));
|
||||
tp->reord_seen++;
|
||||
WRITE_ONCE(tp->reordering,
|
||||
min_t(u32, tp->packets_out + addend,
|
||||
READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_max_reordering)));
|
||||
WRITE_ONCE(tp->reord_seen, tp->reord_seen + 1);
|
||||
NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPRENOREORDER);
|
||||
}
|
||||
|
||||
|
|
@ -2565,7 +2567,7 @@ void tcp_enter_loss(struct sock *sk)
|
|||
(icsk->icsk_ca_state == TCP_CA_Loss && !icsk->icsk_retransmits)) {
|
||||
tp->prior_ssthresh = tcp_current_ssthresh(sk);
|
||||
tp->prior_cwnd = tcp_snd_cwnd(tp);
|
||||
tp->snd_ssthresh = icsk->icsk_ca_ops->ssthresh(sk);
|
||||
WRITE_ONCE(tp->snd_ssthresh, icsk->icsk_ca_ops->ssthresh(sk));
|
||||
tcp_ca_event(sk, CA_EVENT_LOSS);
|
||||
tcp_init_undo(tp);
|
||||
}
|
||||
|
|
@ -2579,8 +2581,8 @@ void tcp_enter_loss(struct sock *sk)
|
|||
reordering = READ_ONCE(net->ipv4.sysctl_tcp_reordering);
|
||||
if (icsk->icsk_ca_state <= TCP_CA_Disorder &&
|
||||
tp->sacked_out >= reordering)
|
||||
tp->reordering = min_t(unsigned int, tp->reordering,
|
||||
reordering);
|
||||
WRITE_ONCE(tp->reordering,
|
||||
min_t(unsigned int, tp->reordering, reordering));
|
||||
|
||||
tcp_set_ca_state(sk, TCP_CA_Loss);
|
||||
tp->high_seq = tp->snd_nxt;
|
||||
|
|
@ -2858,7 +2860,7 @@ static void tcp_undo_cwnd_reduction(struct sock *sk, bool unmark_loss)
|
|||
tcp_snd_cwnd_set(tp, icsk->icsk_ca_ops->undo_cwnd(sk));
|
||||
|
||||
if (tp->prior_ssthresh > tp->snd_ssthresh) {
|
||||
tp->snd_ssthresh = tp->prior_ssthresh;
|
||||
WRITE_ONCE(tp->snd_ssthresh, tp->prior_ssthresh);
|
||||
tcp_ecn_withdraw_cwr(tp);
|
||||
}
|
||||
}
|
||||
|
|
@ -2976,7 +2978,7 @@ static void tcp_init_cwnd_reduction(struct sock *sk)
|
|||
tp->prior_cwnd = tcp_snd_cwnd(tp);
|
||||
tp->prr_delivered = 0;
|
||||
tp->prr_out = 0;
|
||||
tp->snd_ssthresh = inet_csk(sk)->icsk_ca_ops->ssthresh(sk);
|
||||
WRITE_ONCE(tp->snd_ssthresh, inet_csk(sk)->icsk_ca_ops->ssthresh(sk));
|
||||
tcp_ecn_queue_cwr(tp);
|
||||
}
|
||||
|
||||
|
|
@ -3118,7 +3120,7 @@ static void tcp_non_congestion_loss_retransmit(struct sock *sk)
|
|||
|
||||
if (icsk->icsk_ca_state != TCP_CA_Loss) {
|
||||
tp->high_seq = tp->snd_nxt;
|
||||
tp->snd_ssthresh = tcp_current_ssthresh(sk);
|
||||
WRITE_ONCE(tp->snd_ssthresh, tcp_current_ssthresh(sk));
|
||||
tp->prior_ssthresh = 0;
|
||||
tp->undo_marker = 0;
|
||||
tcp_set_ca_state(sk, TCP_CA_Loss);
|
||||
|
|
@ -3910,7 +3912,7 @@ static void tcp_snd_una_update(struct tcp_sock *tp, u32 ack)
|
|||
sock_owned_by_me((struct sock *)tp);
|
||||
tp->bytes_acked += delta;
|
||||
tcp_snd_sne_update(tp, ack);
|
||||
tp->snd_una = ack;
|
||||
WRITE_ONCE(tp->snd_una, ack);
|
||||
}
|
||||
|
||||
static void tcp_rcv_sne_update(struct tcp_sock *tp, u32 seq)
|
||||
|
|
@ -6777,7 +6779,7 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack,
|
|||
NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPFASTOPENACTIVE);
|
||||
/* SYN-data is counted as two separate packets in tcp_ack() */
|
||||
if (tp->delivered > 1)
|
||||
--tp->delivered;
|
||||
WRITE_ONCE(tp->delivered, tp->delivered - 1);
|
||||
}
|
||||
|
||||
tcp_fastopen_add_skb(sk, synack);
|
||||
|
|
@ -7210,7 +7212,7 @@ tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb)
|
|||
SKB_DR_SET(reason, NOT_SPECIFIED);
|
||||
switch (sk->sk_state) {
|
||||
case TCP_SYN_RECV:
|
||||
tp->delivered++; /* SYN-ACK delivery isn't tracked in tcp_ack */
|
||||
WRITE_ONCE(tp->delivered, tp->delivered + 1); /* SYN-ACK delivery isn't tracked in tcp_ack */
|
||||
if (!tp->srtt_us)
|
||||
tcp_synack_rtt_meas(sk, req);
|
||||
|
||||
|
|
@ -7238,7 +7240,7 @@ tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb)
|
|||
if (sk->sk_socket)
|
||||
sk_wake_async(sk, SOCK_WAKE_IO, POLL_OUT);
|
||||
|
||||
tp->snd_una = TCP_SKB_CB(skb)->ack_seq;
|
||||
WRITE_ONCE(tp->snd_una, TCP_SKB_CB(skb)->ack_seq);
|
||||
tp->snd_wnd = ntohs(th->window) << tp->rx_opt.snd_wscale;
|
||||
tcp_init_wl(tp, TCP_SKB_CB(skb)->seq);
|
||||
|
||||
|
|
|
|||
|
|
@ -490,13 +490,13 @@ void tcp_init_metrics(struct sock *sk)
|
|||
val = READ_ONCE(net->ipv4.sysctl_tcp_no_ssthresh_metrics_save) ?
|
||||
0 : tcp_metric_get(tm, TCP_METRIC_SSTHRESH);
|
||||
if (val) {
|
||||
tp->snd_ssthresh = val;
|
||||
WRITE_ONCE(tp->snd_ssthresh, val);
|
||||
if (tp->snd_ssthresh > tp->snd_cwnd_clamp)
|
||||
tp->snd_ssthresh = tp->snd_cwnd_clamp;
|
||||
WRITE_ONCE(tp->snd_ssthresh, tp->snd_cwnd_clamp);
|
||||
}
|
||||
val = tcp_metric_get(tm, TCP_METRIC_REORDERING);
|
||||
if (val && tp->reordering != val)
|
||||
tp->reordering = val;
|
||||
WRITE_ONCE(tp->reordering, val);
|
||||
|
||||
crtt = tcp_metric_get(tm, TCP_METRIC_RTT);
|
||||
rcu_read_unlock();
|
||||
|
|
|
|||
|
|
@ -396,8 +396,8 @@ static void tcpnv_acked(struct sock *sk, const struct ack_sample *sample)
|
|||
|
||||
/* We have enough data to determine we are congested */
|
||||
ca->nv_allow_cwnd_growth = 0;
|
||||
tp->snd_ssthresh =
|
||||
(nv_ssthresh_factor * max_win) >> 3;
|
||||
WRITE_ONCE(tp->snd_ssthresh,
|
||||
(nv_ssthresh_factor * max_win) >> 3);
|
||||
if (tcp_snd_cwnd(tp) - max_win > 2) {
|
||||
/* gap > 2, we do exponential cwnd decrease */
|
||||
int dec;
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ void tcp_cwnd_restart(struct sock *sk, s32 delta)
|
|||
|
||||
tcp_ca_event(sk, CA_EVENT_CWND_RESTART);
|
||||
|
||||
tp->snd_ssthresh = tcp_current_ssthresh(sk);
|
||||
WRITE_ONCE(tp->snd_ssthresh, tcp_current_ssthresh(sk));
|
||||
restart_cwnd = min(restart_cwnd, cwnd);
|
||||
|
||||
while ((delta -= inet_csk(sk)->icsk_rto) > 0 && cwnd > restart_cwnd)
|
||||
|
|
@ -1688,8 +1688,10 @@ static int __tcp_transmit_skb(struct sock *sk, struct sk_buff *skb,
|
|||
|
||||
if (skb->len != tcp_header_size) {
|
||||
tcp_event_data_sent(tp, sk);
|
||||
tp->data_segs_out += tcp_skb_pcount(skb);
|
||||
tp->bytes_sent += skb->len - tcp_header_size;
|
||||
WRITE_ONCE(tp->data_segs_out,
|
||||
tp->data_segs_out + tcp_skb_pcount(skb));
|
||||
WRITE_ONCE(tp->bytes_sent,
|
||||
tp->bytes_sent + skb->len - tcp_header_size);
|
||||
}
|
||||
|
||||
if (after(tcb->end_seq, tp->snd_nxt) || tcb->seq == tcb->end_seq)
|
||||
|
|
@ -2142,7 +2144,7 @@ static void tcp_cwnd_application_limited(struct sock *sk)
|
|||
u32 init_win = tcp_init_cwnd(tp, __sk_dst_get(sk));
|
||||
u32 win_used = max(tp->snd_cwnd_used, init_win);
|
||||
if (win_used < tcp_snd_cwnd(tp)) {
|
||||
tp->snd_ssthresh = tcp_current_ssthresh(sk);
|
||||
WRITE_ONCE(tp->snd_ssthresh, tcp_current_ssthresh(sk));
|
||||
tcp_snd_cwnd_set(tp, (tcp_snd_cwnd(tp) + win_used) >> 1);
|
||||
}
|
||||
tp->snd_cwnd_used = 0;
|
||||
|
|
@ -3642,8 +3644,8 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb, int segs)
|
|||
TCP_ADD_STATS(sock_net(sk), TCP_MIB_RETRANSSEGS, segs);
|
||||
if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_SYN)
|
||||
__NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPSYNRETRANS);
|
||||
tp->total_retrans += segs;
|
||||
tp->bytes_retrans += skb->len;
|
||||
WRITE_ONCE(tp->total_retrans, tp->total_retrans + segs);
|
||||
WRITE_ONCE(tp->bytes_retrans, tp->bytes_retrans + skb->len);
|
||||
|
||||
/* make sure skb->data is aligned on arches that require it
|
||||
* and check if ack-trimming & collapsing extended the headroom
|
||||
|
|
@ -4152,7 +4154,7 @@ static void tcp_connect_init(struct sock *sk)
|
|||
tp->snd_wnd = 0;
|
||||
tcp_init_wl(tp, 0);
|
||||
tcp_write_queue_purge(sk);
|
||||
tp->snd_una = tp->write_seq;
|
||||
WRITE_ONCE(tp->snd_una, tp->write_seq);
|
||||
tp->snd_sml = tp->write_seq;
|
||||
tp->snd_up = tp->write_seq;
|
||||
WRITE_ONCE(tp->snd_nxt, tp->write_seq);
|
||||
|
|
@ -4646,7 +4648,8 @@ int tcp_rtx_synack(const struct sock *sk, struct request_sock *req)
|
|||
* However in this case, we are dealing with a passive fastopen
|
||||
* socket thus we can change total_retrans value.
|
||||
*/
|
||||
tcp_sk_rw(sk)->total_retrans++;
|
||||
WRITE_ONCE(tcp_sk_rw(sk)->total_retrans,
|
||||
tcp_sk_rw(sk)->total_retrans + 1);
|
||||
}
|
||||
trace_tcp_retransmit_synack(sk, req);
|
||||
WRITE_ONCE(req->num_retrans, req->num_retrans + 1);
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ void tcp_plb_check_rehash(struct sock *sk, struct tcp_plb_state *plb)
|
|||
|
||||
sk_rethink_txhash(sk);
|
||||
plb->consec_cong_rounds = 0;
|
||||
tcp_sk(sk)->plb_rehash++;
|
||||
WRITE_ONCE(tcp_sk(sk)->plb_rehash, tcp_sk(sk)->plb_rehash + 1);
|
||||
NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPPLBREHASH);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tcp_plb_check_rehash);
|
||||
|
|
|
|||
|
|
@ -297,7 +297,7 @@ static int tcp_write_timeout(struct sock *sk)
|
|||
}
|
||||
|
||||
if (sk_rethink_txhash(sk)) {
|
||||
tp->timeout_rehash++;
|
||||
WRITE_ONCE(tp->timeout_rehash, tp->timeout_rehash + 1);
|
||||
__NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPTIMEOUTREHASH);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -245,7 +245,8 @@ static void tcp_vegas_cong_avoid(struct sock *sk, u32 ack, u32 acked)
|
|||
*/
|
||||
tcp_snd_cwnd_set(tp, min(tcp_snd_cwnd(tp),
|
||||
(u32)target_cwnd + 1));
|
||||
tp->snd_ssthresh = tcp_vegas_ssthresh(tp);
|
||||
WRITE_ONCE(tp->snd_ssthresh,
|
||||
tcp_vegas_ssthresh(tp));
|
||||
|
||||
} else if (tcp_in_slow_start(tp)) {
|
||||
/* Slow start. */
|
||||
|
|
@ -261,8 +262,8 @@ static void tcp_vegas_cong_avoid(struct sock *sk, u32 ack, u32 acked)
|
|||
* we slow down.
|
||||
*/
|
||||
tcp_snd_cwnd_set(tp, tcp_snd_cwnd(tp) - 1);
|
||||
tp->snd_ssthresh
|
||||
= tcp_vegas_ssthresh(tp);
|
||||
WRITE_ONCE(tp->snd_ssthresh,
|
||||
tcp_vegas_ssthresh(tp));
|
||||
} else if (diff < alpha) {
|
||||
/* We don't have enough extra packets
|
||||
* in the network, so speed up.
|
||||
|
|
@ -280,7 +281,7 @@ static void tcp_vegas_cong_avoid(struct sock *sk, u32 ack, u32 acked)
|
|||
else if (tcp_snd_cwnd(tp) > tp->snd_cwnd_clamp)
|
||||
tcp_snd_cwnd_set(tp, tp->snd_cwnd_clamp);
|
||||
|
||||
tp->snd_ssthresh = tcp_current_ssthresh(sk);
|
||||
WRITE_ONCE(tp->snd_ssthresh, tcp_current_ssthresh(sk));
|
||||
}
|
||||
|
||||
/* Wipe the slate clean for the next RTT. */
|
||||
|
|
|
|||
|
|
@ -244,11 +244,11 @@ static void tcp_westwood_event(struct sock *sk, enum tcp_ca_event event)
|
|||
|
||||
switch (event) {
|
||||
case CA_EVENT_COMPLETE_CWR:
|
||||
tp->snd_ssthresh = tcp_westwood_bw_rttmin(sk);
|
||||
WRITE_ONCE(tp->snd_ssthresh, tcp_westwood_bw_rttmin(sk));
|
||||
tcp_snd_cwnd_set(tp, tp->snd_ssthresh);
|
||||
break;
|
||||
case CA_EVENT_LOSS:
|
||||
tp->snd_ssthresh = tcp_westwood_bw_rttmin(sk);
|
||||
WRITE_ONCE(tp->snd_ssthresh, tcp_westwood_bw_rttmin(sk));
|
||||
/* Update RTT_min when next ack arrives */
|
||||
w->reset_rtt_min = 1;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -147,7 +147,8 @@ static void tcp_yeah_cong_avoid(struct sock *sk, u32 ack, u32 acked)
|
|||
tcp_snd_cwnd_set(tp, max(tcp_snd_cwnd(tp),
|
||||
yeah->reno_count));
|
||||
|
||||
tp->snd_ssthresh = tcp_snd_cwnd(tp);
|
||||
WRITE_ONCE(tp->snd_ssthresh,
|
||||
tcp_snd_cwnd(tp));
|
||||
}
|
||||
|
||||
if (yeah->reno_count <= 2)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user