git: c7c325d01de4 - main - tcp: pass maxseg around instead of calculating locally
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 24 Jan 2024 16:41:17 UTC
The branch main has been updated by rscheff: URL: https://cgit.FreeBSD.org/src/commit/?id=c7c325d01de4a1509e0a978f28275279de692130 commit c7c325d01de4a1509e0a978f28275279de692130 Author: Richard Scheffenegger <rscheff@FreeBSD.org> AuthorDate: 2024-01-24 15:42:29 +0000 Commit: Richard Scheffenegger <rscheff@FreeBSD.org> CommitDate: 2024-01-24 15:43:29 +0000 tcp: pass maxseg around instead of calculating locally Improve slowpath processing (reordering, retransmissions) slightly by calculating maxseg only once. This typically saves one of two calls to tcp_maxseg(). Reviewed By: glebius, tuexen, cc, #transport Sponsored by: NetApp, Inc. Differential Revision: https://reviews.freebsd.org/D43536 --- sys/netinet/tcp_input.c | 37 +++++++++++++++++++++++++------------ sys/netinet/tcp_sack.c | 9 +++++++-- sys/netinet/tcp_var.h | 8 +++++--- 3 files changed, 37 insertions(+), 17 deletions(-) diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index ed5f28490852..02b042fd3273 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -1529,7 +1529,7 @@ tcp_do_segment(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th, struct mbuf *mfree; struct tcpopt to; int tfo_syn; - u_int maxseg; + u_int maxseg = 0; thflags = tcp_get_flags(th); tp->sackhint.last_sack_ack = 0; @@ -2596,7 +2596,8 @@ tcp_do_segment(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th, if (V_tcp_do_prr && IN_FASTRECOVERY(tp->t_flags) && (tp->t_flags & TF_SACK_PERMIT)) { - tcp_do_prr_ack(tp, th, &to, sack_changed); + tcp_do_prr_ack(tp, th, &to, + sack_changed, &maxseg); } else if (tcp_is_sack_recovery(tp, &to) && IN_FASTRECOVERY(tp->t_flags)) { int awnd; @@ -2801,19 +2802,24 @@ resume_partialack: */ if (IN_FASTRECOVERY(tp->t_flags)) { if (SEQ_LT(th->th_ack, tp->snd_recover)) { - if (tp->t_flags & TF_SACK_PERMIT) + if (tp->t_flags & TF_SACK_PERMIT) { if (V_tcp_do_prr && to.to_flags & TOF_SACK) { tcp_timer_activate(tp, TT_REXMT, 0); tp->t_rtttime = 0; - tcp_do_prr_ack(tp, th, &to, sack_changed); + tcp_do_prr_ack(tp, th, &to, + sack_changed, &maxseg); tp->t_flags |= TF_ACKNOW; (void) tcp_output(tp); - } else - tcp_sack_partialack(tp, th); - else + } else { + tcp_sack_partialack(tp, th, + &maxseg); + } + } else { tcp_newreno_partial_ack(tp, th); - } else + } + } else { cc_post_recovery(tp, th); + } } else if (IN_CONGRECOVERY(tp->t_flags)) { if (SEQ_LT(th->th_ack, tp->snd_recover)) { if (V_tcp_do_prr) { @@ -2823,11 +2829,13 @@ resume_partialack: * During ECN cwnd reduction * always use PRR-SSRB */ - tcp_do_prr_ack(tp, th, &to, SACK_CHANGE); + tcp_do_prr_ack(tp, th, &to, SACK_CHANGE, + &maxseg); (void) tcp_output(tp); } - } else + } else { cc_post_recovery(tp, th); + } } /* * If we reach this point, ACK is not a duplicate, @@ -3946,13 +3954,18 @@ tcp_mssopt(struct in_conninfo *inc) } void -tcp_do_prr_ack(struct tcpcb *tp, struct tcphdr *th, struct tcpopt *to, sackstatus_t sack_changed) +tcp_do_prr_ack(struct tcpcb *tp, struct tcphdr *th, struct tcpopt *to, + sackstatus_t sack_changed, u_int *maxsegp) { int snd_cnt = 0, limit = 0, del_data = 0, pipe = 0; - int maxseg = tcp_maxseg(tp); + u_int maxseg; INP_WLOCK_ASSERT(tptoinpcb(tp)); + if (*maxsegp == 0) { + *maxsegp = tcp_maxseg(tp); + } + maxseg = *maxsegp; /* * Compute the amount of data that this ACK is indicating * (del_data) and an estimate of how many bytes are in the diff --git a/sys/netinet/tcp_sack.c b/sys/netinet/tcp_sack.c index f9ca83850c09..f517bb9fcdb7 100644 --- a/sys/netinet/tcp_sack.c +++ b/sys/netinet/tcp_sack.c @@ -936,13 +936,18 @@ tcp_resend_sackholes(struct tcpcb *tp) * the midst of sack recovery. */ void -tcp_sack_partialack(struct tcpcb *tp, struct tcphdr *th) +tcp_sack_partialack(struct tcpcb *tp, struct tcphdr *th, u_int *maxsegp) { struct sackhole *temp; int num_segs = 1; - u_int maxseg = tcp_maxseg(tp); + u_int maxseg; INP_WLOCK_ASSERT(tptoinpcb(tp)); + + if (*maxsegp == 0) { + *maxsegp = tcp_maxseg(tp); + } + maxseg = *maxsegp; tcp_timer_activate(tp, TT_REXMT, 0); tp->t_rtttime = 0; /* Send one or 2 segments based on how much new data was acked. */ diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h index f9b3d1a5c3ee..cbe8de7988c7 100644 --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -1481,14 +1481,16 @@ sackstatus_t tcp_sack_doack(struct tcpcb *, struct tcpopt *, tcp_seq); int tcp_dsack_block_exists(struct tcpcb *); void tcp_update_dsack_list(struct tcpcb *, tcp_seq, tcp_seq); -void tcp_update_sack_list(struct tcpcb *tp, tcp_seq rcv_laststart, tcp_seq rcv_lastend); +void tcp_update_sack_list(struct tcpcb *tp, tcp_seq rcv_laststart, + tcp_seq rcv_lastend); void tcp_clean_dsack_blocks(struct tcpcb *tp); void tcp_clean_sackreport(struct tcpcb *tp); void tcp_sack_adjust(struct tcpcb *tp); struct sackhole *tcp_sack_output(struct tcpcb *tp, int *sack_bytes_rexmt); -void tcp_do_prr_ack(struct tcpcb *, struct tcphdr *, struct tcpopt *, sackstatus_t); +void tcp_do_prr_ack(struct tcpcb *, struct tcphdr *, struct tcpopt *, + sackstatus_t, u_int *); void tcp_lost_retransmission(struct tcpcb *, struct tcphdr *); -void tcp_sack_partialack(struct tcpcb *, struct tcphdr *); +void tcp_sack_partialack(struct tcpcb *, struct tcphdr *, u_int *); void tcp_resend_sackholes(struct tcpcb *tp); void tcp_free_sackholes(struct tcpcb *tp); void tcp_sack_lost_retransmission(struct tcpcb *, struct tcphdr *);