tcp: commonize check for more data to send, style changes

Use SEQ_SUB instead of a plain subtraction, for an implict
type conversion and prevention of a possible overflow.
Use curly brackets in stacked if statements throughout.
Use of the ? operator to enhance readability when clearing
the FIN flag in tcp_output().

None of the above change the function.

Reviewed By:           tuexen, cc, #transport
Sponsored by:          NetApp, Inc.
Differential Revision: https://reviews.freebsd.org/D43539
This commit is contained in:
Richard Scheffenegger 2024-01-26 00:19:30 +01:00
parent 3896a6cc0a
commit 2d05a1c81b
4 changed files with 83 additions and 63 deletions

View file

@ -135,9 +135,11 @@ tcp_ecn_input_syn_sent(struct tcpcb *tp, uint16_t thflags, int iptos)
case 3:
/* FALLTHROUGH */
case 4:
/* decoding Accurate ECN according to
/*
* Decoding Accurate ECN according to
* table in section 3.1.1
* on the SYN,ACK, process the AccECN
*
* On the SYN,ACK, process the AccECN
* flags indicating the state the SYN
* was delivered.
* Reactions to Path ECN mangling can
@ -382,8 +384,7 @@ tcp_ecn_output_syn_sent(struct tcpcb *tp)
thflags = TH_ECE|TH_CWR;
} else
thflags = TH_ECE|TH_CWR;
} else
if (V_tcp_do_ecn == 3) {
} else if (V_tcp_do_ecn == 3) {
/* Send an Accurate ECN setup <SYN> packet */
if (tp->t_rxtshift >= 1) {
if (tp->t_rxtshift <= V_tcp_ecn_maxretries)

View file

@ -1624,13 +1624,14 @@ tcp_do_segment(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th,
*/
if ((to.to_flags & TOF_TS) && (to.to_tsecr != 0)) {
to.to_tsecr -= tp->ts_offset;
if (TSTMP_GT(to.to_tsecr, tcp_ts_getticks()))
if (TSTMP_GT(to.to_tsecr, tcp_ts_getticks())) {
to.to_tsecr = 0;
else if (tp->t_rxtshift == 1 &&
} else if (tp->t_rxtshift == 1 &&
tp->t_flags & TF_PREVVALID &&
tp->t_badrxtwin != 0 &&
TSTMP_LT(to.to_tsecr, tp->t_badrxtwin))
TSTMP_LT(to.to_tsecr, tp->t_badrxtwin)) {
cc_cong_signal(tp, th, CC_RTO_ERR);
}
}
/*
* Process options only when we get SYN/ACK back. The SYN case
@ -1647,8 +1648,9 @@ tcp_do_segment(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th,
!(tp->t_flags & TF_NOOPT)) {
tp->t_flags |= TF_RCVD_SCALE;
tp->snd_scale = to.to_wscale;
} else
} else {
tp->t_flags &= ~TF_REQ_SCALE;
}
/*
* Initial send window. It will be updated with
* the next incoming segment to the scaled value.
@ -1660,30 +1662,36 @@ tcp_do_segment(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th,
tp->t_flags |= TF_RCVD_TSTMP;
tp->ts_recent = to.to_tsval;
tp->ts_recent_age = tcp_ts_getticks();
} else
} else {
tp->t_flags &= ~TF_REQ_TSTMP;
if (to.to_flags & TOF_MSS)
}
if (to.to_flags & TOF_MSS) {
tcp_mss(tp, to.to_mss);
}
if ((tp->t_flags & TF_SACK_PERMIT) &&
(!(to.to_flags & TOF_SACKPERM) ||
(tp->t_flags & TF_NOOPT)))
(tp->t_flags & TF_NOOPT))) {
tp->t_flags &= ~TF_SACK_PERMIT;
}
if (IS_FASTOPEN(tp->t_flags)) {
if ((to.to_flags & TOF_FASTOPEN) &&
!(tp->t_flags & TF_NOOPT)) {
uint16_t mss;
if (to.to_flags & TOF_MSS)
if (to.to_flags & TOF_MSS) {
mss = to.to_mss;
else
if ((inp->inp_vflag & INP_IPV6) != 0)
} else {
if ((inp->inp_vflag & INP_IPV6) != 0) {
mss = TCP6_MSS;
else
} else {
mss = TCP_MSS;
}
}
tcp_fastopen_update_cache(tp, mss,
to.to_tfo_len, to.to_tfo_cookie);
} else
} else {
tcp_fastopen_disable_path(tp);
}
}
}
@ -1872,9 +1880,11 @@ tcp_do_segment(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th,
* is new data available to be sent
* or we need to send an ACK.
*/
if (SEQ_GT(tp->snd_una + sbavail(&so->so_snd),
tp->snd_max) || tp->t_flags & TF_ACKNOW)
if ((tp->t_flags & TF_ACKNOW) ||
(sbavail(&so->so_snd) >=
SEQ_SUB(tp->snd_max, tp->snd_una))) {
(void) tcp_output(tp);
}
goto check_delack;
}
} else if (th->th_ack == tp->snd_una &&
@ -2585,12 +2595,12 @@ tcp_do_segment(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th,
*/
if (th->th_ack != tp->snd_una ||
(tcp_is_sack_recovery(tp, &to) &&
(sack_changed == SACK_NOCHANGE)))
(sack_changed == SACK_NOCHANGE))) {
break;
else if (!tcp_timer_active(tp, TT_REXMT))
} else if (!tcp_timer_active(tp, TT_REXMT)) {
tp->t_dupacks = 0;
else if (++tp->t_dupacks > tcprexmtthresh ||
IN_FASTRECOVERY(tp->t_flags)) {
} else if (++tp->t_dupacks > tcprexmtthresh ||
IN_FASTRECOVERY(tp->t_flags)) {
cc_ack_received(tp, th, nsegs,
CC_DUPACK);
if (V_tcp_do_prr &&
@ -2599,7 +2609,7 @@ tcp_do_segment(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th,
tcp_do_prr_ack(tp, th, &to,
sack_changed, &maxseg);
} else if (tcp_is_sack_recovery(tp, &to) &&
IN_FASTRECOVERY(tp->t_flags)) {
IN_FASTRECOVERY(tp->t_flags)) {
int awnd;
/*
@ -2608,19 +2618,20 @@ tcp_do_segment(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th,
* we have less than 1/2 the original window's
* worth of data in flight.
*/
if (V_tcp_do_newsack)
if (V_tcp_do_newsack) {
awnd = tcp_compute_pipe(tp);
else
} else {
awnd = (tp->snd_nxt - tp->snd_fack) +
tp->sackhint.sack_bytes_rexmit;
}
if (awnd < tp->snd_ssthresh) {
tp->snd_cwnd += maxseg;
if (tp->snd_cwnd > tp->snd_ssthresh)
tp->snd_cwnd = tp->snd_ssthresh;
}
} else
} else {
tp->snd_cwnd += maxseg;
}
(void) tcp_output(tp);
goto drop;
} else if (tp->t_dupacks == tcprexmtthresh ||
@ -2688,13 +2699,13 @@ enter_recovery:
tp->snd_nxt - tp->snd_una);
}
if (tcp_is_sack_recovery(tp, &to)) {
TCPSTAT_INC(
tcps_sack_recovery_episode);
TCPSTAT_INC(tcps_sack_recovery_episode);
tp->snd_recover = tp->snd_nxt;
tp->snd_cwnd = maxseg;
(void) tcp_output(tp);
if (SEQ_GT(th->th_ack, tp->snd_una))
if (SEQ_GT(th->th_ack, tp->snd_una)) {
goto resume_partialack;
}
goto drop;
}
tp->snd_nxt = th->th_ack;
@ -2720,8 +2731,7 @@ enter_recovery:
* segment. Restore the original
* snd_cwnd after packet transmission.
*/
cc_ack_received(tp, th, nsegs,
CC_DUPACK);
cc_ack_received(tp, th, nsegs, CC_DUPACK);
uint32_t oldcwnd = tp->snd_cwnd;
tcp_seq oldsndmax = tp->snd_max;
u_int sent;
@ -2743,12 +2753,14 @@ enter_recovery:
* or we need to send an ACK.
*/
SOCKBUF_LOCK(&so->so_snd);
avail = sbavail(&so->so_snd) -
(tp->snd_nxt - tp->snd_una);
avail = sbavail(&so->so_snd);
SOCKBUF_UNLOCK(&so->so_snd);
if (avail > 0 || tp->t_flags & TF_ACKNOW)
if (tp->t_flags & TF_ACKNOW ||
(avail >=
SEQ_SUB(tp->snd_nxt, tp->snd_una))) {
(void) tcp_output(tp);
sent = tp->snd_max - oldsndmax;
}
sent = SEQ_SUB(tp->snd_max, oldsndmax);
if (sent > maxseg) {
KASSERT((tp->t_dupacks == 2 &&
tp->snd_limited == 0) ||
@ -2757,8 +2769,9 @@ enter_recovery:
("%s: sent too much",
__func__));
tp->snd_limited = 2;
} else if (sent > 0)
} else if (sent > 0) {
++tp->snd_limited;
}
tp->snd_cwnd = oldcwnd;
goto drop;
}
@ -3316,9 +3329,9 @@ dodata: /* XXX */
/*
* Return any desired output.
*/
if (needoutput || (tp->t_flags & TF_ACKNOW))
if (needoutput || (tp->t_flags & TF_ACKNOW)) {
(void) tcp_output(tp);
}
check_delack:
INP_WLOCK_ASSERT(inp);
@ -3982,8 +3995,9 @@ tcp_do_prr_ack(struct tcpcb *tp, struct tcphdr *th, struct tcpopt *to,
tp->sackhint.sack_bytes_rexmit;
} else {
if (tp->sackhint.prr_delivered < (tcprexmtthresh * maxseg +
tp->snd_recover - tp->snd_una))
tp->snd_recover - tp->snd_una)) {
del_data = maxseg;
}
pipe = imax(0, tp->snd_max - tp->snd_una -
imin(INT_MAX / 65536, tp->t_dupacks) * maxseg);
}
@ -4009,13 +4023,14 @@ tcp_do_prr_ack(struct tcpcb *tp, struct tcphdr *th, struct tcpopt *to,
* - Prevent ACK splitting attacks, by being conservative
* when no new data is acked.
*/
if ((sack_changed == SACK_NEWLOSS) || (del_data == 0))
if ((sack_changed == SACK_NEWLOSS) || (del_data == 0)) {
limit = tp->sackhint.prr_delivered -
tp->sackhint.prr_out;
else
} else {
limit = imax(tp->sackhint.prr_delivered -
tp->sackhint.prr_out, del_data) +
maxseg;
}
snd_cnt = imin((tp->snd_ssthresh - pipe), limit);
}
snd_cnt = imax(snd_cnt, 0) / maxseg;
@ -4033,8 +4048,9 @@ tcp_do_prr_ack(struct tcpcb *tp, struct tcphdr *th, struct tcpopt *to,
tp->snd_cwnd = (tp->snd_max - tp->snd_una) +
(snd_cnt * maxseg);
}
} else if (IN_CONGRECOVERY(tp->t_flags))
} else if (IN_CONGRECOVERY(tp->t_flags)) {
tp->snd_cwnd = pipe - del_data + (snd_cnt * maxseg);
}
tp->snd_cwnd = imax(maxseg, tp->snd_cwnd);
}

View file

@ -392,10 +392,10 @@ after_sack_rexmit:
* in which case len is already set.
*/
if (sack_rxmit == 0) {
if (sack_bytes_rxmt == 0)
if (sack_bytes_rxmt == 0) {
len = ((int32_t)min(sbavail(&so->so_snd), sendwin) -
off);
else {
} else {
int32_t cwin;
/*
@ -558,12 +558,8 @@ after_sack_rexmit:
ipoptlen == 0 && !(flags & TH_SYN))
tso = 1;
if (sack_rxmit) {
if (SEQ_LT(p->rxmit + len, tp->snd_una + sbused(&so->so_snd)))
flags &= ~TH_FIN;
} else {
if (SEQ_LT(tp->snd_nxt + len, tp->snd_una +
sbused(&so->so_snd)))
if (SEQ_LT((sack_rxmit ? p->rxmit : tp->snd_nxt) + len,
tp->snd_una + sbused(&so->so_snd))) {
flags &= ~TH_FIN;
}

View file

@ -988,12 +988,13 @@ tcp_sack_partialack(struct tcpcb *tp, struct tcphdr *th, u_int *maxsegp)
if (tp->t_flags & TF_SENTFIN)
highdata--;
highdata = SEQ_MIN(highdata, tp->snd_recover);
if (th->th_ack != highdata) {
if (SEQ_LT(th->th_ack, highdata)) {
tp->snd_fack = th->th_ack;
if ((temp = tcp_sackhole_insert(tp, SEQ_MAX(th->th_ack,
highdata - maxseg), highdata, NULL)) != NULL)
tp->sackhint.hole_bytes += temp->end -
temp->start;
highdata - maxseg), highdata, NULL)) != NULL) {
tp->sackhint.hole_bytes +=
temp->end - temp->start;
}
}
}
(void) tcp_output(tp);
@ -1065,27 +1066,33 @@ tcp_sack_adjust(struct tcpcb *tp)
struct sackhole *p, *cur = TAILQ_FIRST(&tp->snd_holes);
INP_WLOCK_ASSERT(tptoinpcb(tp));
if (cur == NULL)
return; /* No holes */
if (SEQ_GEQ(tp->snd_nxt, tp->snd_fack))
return; /* We're already beyond any SACKed blocks */
if (cur == NULL) {
/* No holes */
return;
}
if (SEQ_GEQ(tp->snd_nxt, tp->snd_fack)) {
/* We're already beyond any SACKed blocks */
return;
}
/*-
* Two cases for which we want to advance snd_nxt:
* i) snd_nxt lies between end of one hole and beginning of another
* ii) snd_nxt lies between end of last hole and snd_fack
*/
while ((p = TAILQ_NEXT(cur, scblink)) != NULL) {
if (SEQ_LT(tp->snd_nxt, cur->end))
if (SEQ_LT(tp->snd_nxt, cur->end)) {
return;
if (SEQ_GEQ(tp->snd_nxt, p->start))
}
if (SEQ_GEQ(tp->snd_nxt, p->start)) {
cur = p;
else {
} else {
tp->snd_nxt = p->start;
return;
}
}
if (SEQ_LT(tp->snd_nxt, cur->end))
if (SEQ_LT(tp->snd_nxt, cur->end)) {
return;
}
tp->snd_nxt = tp->snd_fack;
}