Hi,
To remove pressure from the exclusive netlock, I would like to run
tcp_slowtimo() with a mutex only. That means that all the consumers
have to read tcp_now only once to get consistent time. Same for
tcp_iss, update it with mutex, read it once.
ok?
bluhm
Index: net/pf.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/net/pf.c,v
retrieving revision 1.1138
diff -u -p -r1.1138 pf.c
--- net/pf.c 30 Aug 2022 11:53:03 -0000 1.1138
+++ net/pf.c 1 Sep 2022 14:59:14 -0000
@@ -3562,7 +3562,7 @@ pf_tcp_iss(struct pf_pdesc *pd)
}
SHA512Final(digest.bytes, &ctx);
pf_tcp_iss_off += 4096;
- return (digest.words[0] + tcp_iss + pf_tcp_iss_off);
+ return (digest.words[0] + READ_ONCE(tcp_iss) + pf_tcp_iss_off);
}
void
Index: netinet/tcp_input.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/tcp_input.c,v
retrieving revision 1.379
diff -u -p -r1.379 tcp_input.c
--- netinet/tcp_input.c 30 Aug 2022 11:53:04 -0000 1.379
+++ netinet/tcp_input.c 1 Sep 2022 15:40:18 -0000
@@ -190,7 +190,7 @@ void tcp_newreno_partialack(struct tcpc
void syn_cache_put(struct syn_cache *);
void syn_cache_rm(struct syn_cache *);
-int syn_cache_respond(struct syn_cache *, struct mbuf *);
+int syn_cache_respond(struct syn_cache *, struct mbuf *, uint32_t);
void syn_cache_timer(void *);
void syn_cache_reaper(void *);
void syn_cache_insert(struct syn_cache *, struct tcpcb *);
@@ -198,10 +198,10 @@ void syn_cache_reset(struct sockaddr *,
struct tcphdr *, u_int);
int syn_cache_add(struct sockaddr *, struct sockaddr *, struct tcphdr *,
unsigned int, struct socket *, struct mbuf *, u_char *, int,
- struct tcp_opt_info *, tcp_seq *);
+ struct tcp_opt_info *, tcp_seq *, uint32_t);
struct socket *syn_cache_get(struct sockaddr *, struct sockaddr *,
struct tcphdr *, unsigned int, unsigned int, struct socket *,
- struct mbuf *);
+ struct mbuf *, uint32_t);
struct syn_cache *syn_cache_lookup(struct sockaddr *, struct sockaddr *,
struct syn_cache_head **, u_int);
@@ -375,6 +375,7 @@ tcp_input(struct mbuf **mp, int *offp, i
short ostate;
caddr_t saveti;
tcp_seq iss, *reuse = NULL;
+ uint32_t now;
u_long tiwin;
struct tcp_opt_info opti;
struct tcphdr *th;
@@ -389,6 +390,7 @@ tcp_input(struct mbuf **mp, int *offp, i
opti.ts_present = 0;
opti.maxseg = 0;
+ now = READ_ONCE(tcp_now);
/*
* RFC1122 4.2.3.10, p. 104: discard bcast/mcast SYN
@@ -698,7 +700,7 @@ findpcb:
case TH_ACK:
so = syn_cache_get(&src.sa, &dst.sa,
- th, iphlen, tlen, so, m);
+ th, iphlen, tlen, so, m, now);
if (so == NULL) {
/*
* We don't have a SYN for
@@ -830,7 +832,8 @@ findpcb:
*/
if (so->so_qlen > so->so_qlimit ||
syn_cache_add(&src.sa, &dst.sa, th, iphlen,
- so, m, optp, optlen, &opti, reuse) == -1) {
+ so, m, optp, optlen, &opti, reuse, now)
+ == -1) {
tcpstat_inc(tcps_dropsyn);
goto drop;
}
@@ -857,7 +860,7 @@ findpcb:
* Segment received on connection.
* Reset idle time and keep-alive timer.
*/
- tp->t_rcvtime = tcp_now;
+ tp->t_rcvtime = now;
if (TCPS_HAVEESTABLISHED(tp->t_state))
TCP_TIMER_ARM(tp, TCPT_KEEP, tcp_keepidle);
@@ -873,7 +876,7 @@ findpcb:
if (optp)
#endif
if (tcp_dooptions(tp, optp, optlen, th, m, iphlen, &opti,
- m->m_pkthdr.ph_rtableid))
+ m->m_pkthdr.ph_rtableid, now))
goto drop;
if (opti.ts_present && opti.ts_ecr) {
@@ -883,7 +886,7 @@ findpcb:
opti.ts_ecr -= tp->ts_modulate;
/* make sure ts_ecr is sensible */
- rtt_test = tcp_now - opti.ts_ecr;
+ rtt_test = now - opti.ts_ecr;
if (rtt_test < 0 || rtt_test > TCP_RTT_MAX)
opti.ts_ecr = 0;
}
@@ -926,7 +929,7 @@ findpcb:
* Fix from Braden, see Stevens p. 870
*/
if (opti.ts_present && SEQ_LEQ(th->th_seq, tp->last_ack_sent)) {
- tp->ts_recent_age = tcp_now;
+ tp->ts_recent_age = now;
tp->ts_recent = opti.ts_val;
}
@@ -940,15 +943,14 @@ findpcb:
*/
tcpstat_inc(tcps_predack);
if (opti.ts_present && opti.ts_ecr)
- tcp_xmit_timer(tp, tcp_now -
opti.ts_ecr);
+ tcp_xmit_timer(tp, now - opti.ts_ecr);
else if (tp->t_rtttime &&
SEQ_GT(th->th_ack, tp->t_rtseq))
- tcp_xmit_timer(tp,
- tcp_now - tp->t_rtttime);
+ tcp_xmit_timer(tp, now - tp->t_rtttime);
acked = th->th_ack - tp->snd_una;
tcpstat_pkt(tcps_rcvackpack, tcps_rcvackbyte,
acked);
- tp->t_rcvacktime = tcp_now;
+ tp->t_rcvacktime = now;
ND6_HINT(tp);
sbdrop(so, &so->so_snd, acked);
@@ -1189,7 +1191,7 @@ findpcb:
* use its rtt as our initial srtt & rtt var.
*/
if (tp->t_rtttime)
- tcp_xmit_timer(tp, tcp_now - tp->t_rtttime);
+ tcp_xmit_timer(tp, now - tp->t_rtttime);
/*
* Since new data was acked (the SYN), open the
* congestion window by one MSS. We do this
@@ -1270,7 +1272,7 @@ trimthenstep6:
TSTMP_LT(opti.ts_val, tp->ts_recent)) {
/* Check to see if ts_recent is over 24 days old. */
- if ((int)(tcp_now - tp->ts_recent_age) > TCP_PAWS_IDLE) {
+ if ((int)(now - tp->ts_recent_age) > TCP_PAWS_IDLE) {
/*
* Invalidate ts_recent. If this segment updates
* ts_recent, the age will be reset later and ts_recent
@@ -1380,7 +1382,7 @@ trimthenstep6:
*/
if (opti.ts_present && TSTMP_GEQ(opti.ts_val, tp->ts_recent) &&
SEQ_LEQ(th->th_seq, tp->last_ack_sent)) {
- tp->ts_recent_age = tcp_now;
+ tp->ts_recent_age = now;
tp->ts_recent = opti.ts_val;
}
@@ -1683,7 +1685,7 @@ trimthenstep6:
}
acked = th->th_ack - tp->snd_una;
tcpstat_pkt(tcps_rcvackpack, tcps_rcvackbyte, acked);
- tp->t_rcvacktime = tcp_now;
+ tp->t_rcvacktime = now;
/*
* If we have a timestamp reply, update smoothed
@@ -1695,9 +1697,9 @@ trimthenstep6:
* Recompute the initial retransmit timer.
*/
if (opti.ts_present && opti.ts_ecr)
- tcp_xmit_timer(tp, tcp_now - opti.ts_ecr);
+ tcp_xmit_timer(tp, now - opti.ts_ecr);
else if (tp->t_rtttime && SEQ_GT(th->th_ack, tp->t_rtseq))
- tcp_xmit_timer(tp, tcp_now - tp->t_rtttime);
+ tcp_xmit_timer(tp, now - tp->t_rtttime);
/*
* If all outstanding data is acked, stop retransmit
@@ -2092,12 +2094,12 @@ dropwithreset:
goto drop;
if (tiflags & TH_ACK) {
tcp_respond(tp, mtod(m, caddr_t), th, (tcp_seq)0, th->th_ack,
- TH_RST, m->m_pkthdr.ph_rtableid);
+ TH_RST, m->m_pkthdr.ph_rtableid, now);
} else {
if (tiflags & TH_SYN)
tlen++;
tcp_respond(tp, mtod(m, caddr_t), th, th->th_seq + tlen,
- (tcp_seq)0, TH_RST|TH_ACK, m->m_pkthdr.ph_rtableid);
+ (tcp_seq)0, TH_RST|TH_ACK, m->m_pkthdr.ph_rtableid, now);
}
m_freem(m);
in_pcbunref(inp);
@@ -2118,7 +2120,7 @@ drop:
int
tcp_dooptions(struct tcpcb *tp, u_char *cp, int cnt, struct tcphdr *th,
struct mbuf *m, int iphlen, struct tcp_opt_info *oi,
- u_int rtableid)
+ u_int rtableid, uint32_t now)
{
u_int16_t mss = 0;
int opt, optlen;
@@ -2187,7 +2189,7 @@ tcp_dooptions(struct tcpcb *tp, u_char *
*/
tp->t_flags |= TF_RCVD_TSTMP;
tp->ts_recent = oi->ts_val;
- tp->ts_recent_age = tcp_now;
+ tp->ts_recent_age = now;
break;
case TCPOPT_SACK_PERMITTED:
@@ -3169,8 +3171,6 @@ do {
\
timeout_add(&(sc)->sc_timer, (sc)->sc_rxtcur * (hz / PR_SLOWHZ)); \
} while (/*CONSTCOND*/0)
-#define SYN_CACHE_TIMESTAMP(sc) tcp_now + (sc)->sc_modulate
-
void
syn_cache_init(void)
{
@@ -3335,11 +3335,14 @@ void
syn_cache_timer(void *arg)
{
struct syn_cache *sc = arg;
+ uint32_t now;
NET_LOCK();
if (sc->sc_flags & SCF_DEAD)
goto out;
+ now = READ_ONCE(tcp_now);
+
if (__predict_false(sc->sc_rxtshift == TCP_MAXRXTSHIFT)) {
/* Drop it -- too many retransmissions. */
goto dropit;
@@ -3355,7 +3358,7 @@ syn_cache_timer(void *arg)
goto dropit;
tcpstat_inc(tcps_sc_retransmitted);
- (void) syn_cache_respond(sc, NULL);
+ (void) syn_cache_respond(sc, NULL, now);
/* Advance the timer back-off. */
sc->sc_rxtshift++;
@@ -3466,7 +3469,7 @@ syn_cache_lookup(struct sockaddr *src, s
*/
struct socket *
syn_cache_get(struct sockaddr *src, struct sockaddr *dst, struct tcphdr *th,
- u_int hlen, u_int tlen, struct socket *so, struct mbuf *m)
+ u_int hlen, u_int tlen, struct socket *so, struct mbuf *m, uint32_t now)
{
struct syn_cache *sc;
struct syn_cache_head *scp;
@@ -3488,7 +3491,7 @@ syn_cache_get(struct sockaddr *src, stru
if ((th->th_ack != sc->sc_iss + 1) ||
SEQ_LEQ(th->th_seq, sc->sc_irs) ||
SEQ_GT(th->th_seq, sc->sc_irs + 1 + sc->sc_win)) {
- (void) syn_cache_respond(sc, m);
+ (void) syn_cache_respond(sc, m, now);
return ((struct socket *)(-1));
}
@@ -3622,10 +3625,10 @@ syn_cache_get(struct sockaddr *src, stru
#endif
tcp_rcvseqinit(tp);
tp->t_state = TCPS_SYN_RECEIVED;
- tp->t_rcvtime = tcp_now;
- tp->t_sndtime = tcp_now;
- tp->t_rcvacktime = tcp_now;
- tp->t_sndacktime = tcp_now;
+ tp->t_rcvtime = now;
+ tp->t_sndtime = now;
+ tp->t_rcvacktime = now;
+ tp->t_sndacktime = now;
TCP_TIMER_ARM(tp, TCPT_KEEP, tcptv_keep_init);
tcpstat_inc(tcps_accepts);
@@ -3655,7 +3658,7 @@ syn_cache_get(struct sockaddr *src, stru
resetandabort:
tcp_respond(NULL, mtod(m, caddr_t), th, (tcp_seq)0, th->th_ack, TH_RST,
- m->m_pkthdr.ph_rtableid);
+ m->m_pkthdr.ph_rtableid, now);
abort:
m_freem(m);
if (so != NULL)
@@ -3741,7 +3744,7 @@ syn_cache_unreach(struct sockaddr *src,
int
syn_cache_add(struct sockaddr *src, struct sockaddr *dst, struct tcphdr *th,
u_int iphlen, struct socket *so, struct mbuf *m, u_char *optp, int optlen,
- struct tcp_opt_info *oi, tcp_seq *issp)
+ struct tcp_opt_info *oi, tcp_seq *issp, uint32_t now)
{
struct tcpcb tb, *tp;
long win;
@@ -3779,7 +3782,7 @@ syn_cache_add(struct sockaddr *src, stru
#endif
tb.t_state = TCPS_LISTEN;
if (tcp_dooptions(&tb, optp, optlen, th, m, iphlen, oi,
- sotoinpcb(so)->inp_rtableid))
+ sotoinpcb(so)->inp_rtableid, now))
return (-1);
}
@@ -3811,7 +3814,7 @@ syn_cache_add(struct sockaddr *src, stru
sc->sc_ipopts = ipopts;
}
sc->sc_timestamp = tb.ts_recent;
- if (syn_cache_respond(sc, m) == 0) {
+ if (syn_cache_respond(sc, m, now) == 0) {
tcpstat_inc(tcps_sndacks);
tcpstat_inc(tcps_sndtotal);
}
@@ -3895,7 +3898,7 @@ syn_cache_add(struct sockaddr *src, stru
sc->sc_flags |= SCF_SIGNATURE;
#endif
sc->sc_tp = tp;
- if (syn_cache_respond(sc, m) == 0) {
+ if (syn_cache_respond(sc, m, now) == 0) {
syn_cache_insert(sc, tp);
tcpstat_inc(tcps_sndacks);
tcpstat_inc(tcps_sndtotal);
@@ -3908,7 +3911,7 @@ syn_cache_add(struct sockaddr *src, stru
}
int
-syn_cache_respond(struct syn_cache *sc, struct mbuf *m)
+syn_cache_respond(struct syn_cache *sc, struct mbuf *m, uint32_t now)
{
u_int8_t *optp;
int optlen, error;
@@ -4034,7 +4037,7 @@ syn_cache_respond(struct syn_cache *sc,
u_int32_t *lp = (u_int32_t *)(optp);
/* Form timestamp option as shown in appendix A of RFC 1323. */
*lp++ = htonl(TCPOPT_TSTAMP_HDR);
- *lp++ = htonl(SYN_CACHE_TIMESTAMP(sc));
+ *lp++ = htonl(now + sc->sc_modulate);
*lp = htonl(sc->sc_timestamp);
optp += TCPOLEN_TSTAMP_APPA;
}
Index: netinet/tcp_output.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/tcp_output.c,v
retrieving revision 1.132
diff -u -p -r1.132 tcp_output.c
--- netinet/tcp_output.c 11 Aug 2022 09:13:21 -0000 1.132
+++ netinet/tcp_output.c 1 Sep 2022 14:47:22 -0000
@@ -203,6 +203,7 @@ tcp_output(struct tcpcb *tp)
int idle, sendalot = 0;
int i, sack_rxmit = 0;
struct sackhole *p;
+ uint32_t now;
#ifdef TCP_SIGNATURE
unsigned int sigoff;
#endif /* TCP_SIGNATURE */
@@ -221,6 +222,8 @@ tcp_output(struct tcpcb *tp)
return (EINVAL);
#endif /* defined(TCP_SIGNATURE) && defined(DIAGNOSTIC) */
+ now = READ_ONCE(tcp_now);
+
/*
* Determine length of data that should be transmitted,
* and flags that will be used.
@@ -228,7 +231,7 @@ tcp_output(struct tcpcb *tp)
* to send, then transmit; otherwise, investigate further.
*/
idle = (tp->t_flags & TF_LASTIDLE) || (tp->snd_max == tp->snd_una);
- if (idle && (tcp_now - tp->t_rcvtime) >= tp->t_rxtcur)
+ if (idle && (now - tp->t_rcvtime) >= tp->t_rxtcur)
/*
* We have been idle for "a while" and no acks are
* expected to clock out any data we send --
@@ -539,13 +542,13 @@ send:
/* Form timestamp option as shown in appendix A of RFC 1323. */
*lp++ = htonl(TCPOPT_TSTAMP_HDR);
- *lp++ = htonl(tcp_now + tp->ts_modulate);
+ *lp++ = htonl(now + tp->ts_modulate);
*lp = htonl(tp->ts_recent);
optlen += TCPOLEN_TSTAMP_APPA;
/* Set receive buffer autosizing timestamp. */
if (tp->rfbuf_ts == 0)
- tp->rfbuf_ts = tcp_now;
+ tp->rfbuf_ts = now;
}
@@ -691,7 +694,7 @@ send:
*/
if (off + len == so->so_snd.sb_cc && !soissending(so))
flags |= TH_PUSH;
- tp->t_sndtime = tcp_now;
+ tp->t_sndtime = now;
} else {
if (tp->t_flags & TF_ACKNOW)
tcpstat_inc(tcps_sndacks);
@@ -924,7 +927,7 @@ send:
* not currently timing anything.
*/
if (tp->t_rtttime == 0) {
- tp->t_rtttime = tcp_now;
+ tp->t_rtttime = now;
tp->t_rtseq = startseq;
tcpstat_inc(tcps_segstimed);
}
@@ -1123,7 +1126,7 @@ out:
if (win > 0 && SEQ_GT(tp->rcv_nxt+win, tp->rcv_adv))
tp->rcv_adv = tp->rcv_nxt + win;
tp->last_ack_sent = tp->rcv_nxt;
- tp->t_sndacktime = tcp_now;
+ tp->t_sndacktime = now;
tp->t_flags &= ~TF_ACKNOW;
TCP_TIMER_DISARM(tp, TCPT_DELACK);
if (sendalot)
Index: netinet/tcp_subr.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/tcp_subr.c,v
retrieving revision 1.186
diff -u -p -r1.186 tcp_subr.c
--- netinet/tcp_subr.c 30 Aug 2022 11:53:04 -0000 1.186
+++ netinet/tcp_subr.c 1 Sep 2022 14:47:22 -0000
@@ -71,6 +71,7 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
+#include <sys/mutex.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/timeout.h>
@@ -98,6 +99,14 @@
#include <crypto/md5.h>
#include <crypto/sha2.h>
+/*
+ * Locks used to protect struct members in this file:
+ * I immutable after creation
+ * T tcp_timer_mtx global tcp timer data structures
+ */
+
+struct mutex tcp_timer_mtx;
+
/* patchable/settable parameters for tcp */
int tcp_mssdflt = TCP_MSS;
int tcp_rttdflt = TCPTV_SRTTDFLT / PR_SLOWHZ;
@@ -111,8 +120,6 @@ int tcp_do_ecn = 0; /* RFC3168 ECN enab
#endif
int tcp_do_rfc3390 = 2; /* Increase TCP's Initial Window to 10*mss */
-u_int32_t tcp_now = 1;
-
#ifndef TCB_INITIAL_HASH_SIZE
#define TCB_INITIAL_HASH_SIZE 128
#endif
@@ -126,9 +133,10 @@ struct pool sackhl_pool;
struct cpumem *tcpcounters; /* tcp statistics */
-u_char tcp_secret[16];
-SHA2_CTX tcp_secret_ctx;
-tcp_seq tcp_iss;
+u_char tcp_secret[16]; /* [I] */
+SHA2_CTX tcp_secret_ctx; /* [I] */
+tcp_seq tcp_iss; /* [T] updated by timer and connection
*/
+uint32_t tcp_now; /* [T] incremented by slow timer */
/*
* Tcp initialization
@@ -137,6 +145,7 @@ void
tcp_init(void)
{
tcp_iss = 1; /* wrong */
+ tcp_now = 1;
pool_init(&tcpcb_pool, sizeof(struct tcpcb), 0, IPL_SOFTNET, 0,
"tcpcb", NULL);
pool_init(&tcpqe_pool, sizeof(struct tcpqent), 0, IPL_SOFTNET, 0,
@@ -281,7 +290,7 @@ tcp_template(struct tcpcb *tp)
*/
void
tcp_respond(struct tcpcb *tp, caddr_t template, struct tcphdr *th0,
- tcp_seq ack, tcp_seq seq, int flags, u_int rtableid)
+ tcp_seq ack, tcp_seq seq, int flags, u_int rtableid, uint32_t now)
{
int tlen;
int win = 0;
@@ -362,7 +371,7 @@ tcp_respond(struct tcpcb *tp, caddr_t te
u_int32_t *lp = (u_int32_t *)(th + 1);
/* Form timestamp option as shown in appendix A of RFC 1323. */
*lp++ = htonl(TCPOPT_TSTAMP_HDR);
- *lp++ = htonl(tcp_now + tp->ts_modulate);
+ *lp++ = htonl(now + tp->ts_modulate);
*lp = htonl(tp->ts_recent);
tlen += TCPOLEN_TSTAMP_APPA;
th->th_off = (sizeof(struct tcphdr) + TCPOLEN_TSTAMP_APPA) >> 2;
@@ -913,6 +922,12 @@ tcp_set_iss_tsm(struct tcpcb *tp)
uint32_t words[2];
} digest;
u_int rdomain = rtable_l2(tp->t_inpcb->inp_rtableid);
+ tcp_seq iss;
+
+ mtx_enter(&tcp_timer_mtx);
+ tcp_iss += TCP_ISS_CONN_INC;
+ iss = tcp_iss;
+ mtx_leave(&tcp_timer_mtx);
ctx = tcp_secret_ctx;
SHA512Update(&ctx, &rdomain, sizeof(rdomain));
@@ -930,8 +945,7 @@ tcp_set_iss_tsm(struct tcpcb *tp)
sizeof(struct in_addr));
}
SHA512Final(digest.bytes, &ctx);
- tcp_iss += TCP_ISS_CONN_INC;
- tp->iss = digest.words[0] + tcp_iss;
+ tp->iss = digest.words[0] + iss;
tp->ts_modulate = digest.words[1];
}
Index: netinet/tcp_timer.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/tcp_timer.c,v
retrieving revision 1.69
diff -u -p -r1.69 tcp_timer.c
--- netinet/tcp_timer.c 2 Jan 2022 22:36:04 -0000 1.69
+++ netinet/tcp_timer.c 1 Sep 2022 14:47:22 -0000
@@ -55,11 +55,16 @@
#include <netinet/ip_icmp.h>
#include <netinet/tcp_seq.h>
+/*
+ * Locks used to protect struct members in this file:
+ * T tcp_timer_mtx global tcp timer data structures
+ */
+
int tcp_always_keepalive;
int tcp_keepidle;
int tcp_keepintvl;
int tcp_maxpersistidle; /* max idle time in persist */
-int tcp_maxidle;
+int tcp_maxidle; /* [T] max idle time for keep alive */
/*
* Time to delay the ACK. This is initialized in tcp_init(), unless
@@ -144,13 +149,11 @@ tcp_timer_delack(void *arg)
void
tcp_slowtimo(void)
{
- NET_LOCK();
-
+ mtx_enter(&tcp_timer_mtx);
tcp_maxidle = TCPTV_KEEPCNT * tcp_keepintvl;
tcp_iss += TCP_ISSINCR2/PR_SLOWHZ; /* increment iss */
tcp_now++; /* for timestamps */
-
- NET_UNLOCK();
+ mtx_leave(&tcp_timer_mtx);
}
/*
@@ -392,6 +395,7 @@ tcp_timer_persist(void *arg)
struct tcpcb *otp = NULL, *tp = arg;
uint32_t rto;
short ostate;
+ uint32_t now;
NET_LOCK();
/* Ignore canceled timeouts or timeouts that have been rescheduled. */
@@ -418,9 +422,10 @@ tcp_timer_persist(void *arg)
rto = TCP_REXMTVAL(tp);
if (rto < tp->t_rttmin)
rto = tp->t_rttmin;
+ now = READ_ONCE(tcp_now);
if (tp->t_rxtshift == TCP_MAXRXTSHIFT &&
- ((tcp_now - tp->t_rcvtime) >= tcp_maxpersistidle ||
- (tcp_now - tp->t_rcvtime) >= rto * tcp_totbackoff)) {
+ ((now - tp->t_rcvtime) >= tcp_maxpersistidle ||
+ (now - tp->t_rcvtime) >= rto * tcp_totbackoff)) {
tcpstat_inc(tcps_persistdrop);
tp = tcp_drop(tp, ETIMEDOUT);
goto out;
@@ -458,8 +463,13 @@ tcp_timer_keep(void *arg)
if ((tcp_always_keepalive ||
tp->t_inpcb->inp_socket->so_options & SO_KEEPALIVE) &&
tp->t_state <= TCPS_CLOSING) {
- if ((tcp_maxidle > 0) &&
- ((tcp_now - tp->t_rcvtime) >= tcp_keepidle + tcp_maxidle))
+ int maxidle;
+ uint32_t now;
+
+ maxidle = READ_ONCE(tcp_maxidle);
+ now = READ_ONCE(tcp_now);
+ if ((maxidle > 0) &&
+ ((now - tp->t_rcvtime) >= tcp_keepidle + maxidle))
goto dropit;
/*
* Send a packet designed to force a response
@@ -475,7 +485,7 @@ tcp_timer_keep(void *arg)
*/
tcpstat_inc(tcps_keepprobe);
tcp_respond(tp, mtod(tp->t_template, caddr_t),
- NULL, tp->rcv_nxt, tp->snd_una - 1, 0, 0);
+ NULL, tp->rcv_nxt, tp->snd_una - 1, 0, 0, now);
TCP_TIMER_ARM(tp, TCPT_KEEP, tcp_keepintvl);
} else
TCP_TIMER_ARM(tp, TCPT_KEEP, tcp_keepidle);
@@ -496,6 +506,8 @@ tcp_timer_2msl(void *arg)
{
struct tcpcb *otp = NULL, *tp = arg;
short ostate;
+ int maxidle;
+ uint32_t now;
NET_LOCK();
/* Ignore canceled timeouts or timeouts that have been rescheduled. */
@@ -510,8 +522,10 @@ tcp_timer_2msl(void *arg)
}
tcp_timer_freesack(tp);
+ maxidle = READ_ONCE(tcp_maxidle);
+ now = READ_ONCE(tcp_now);
if (tp->t_state != TCPS_TIME_WAIT &&
- ((tcp_maxidle == 0) || ((tcp_now - tp->t_rcvtime) <= tcp_maxidle)))
+ ((maxidle == 0) || ((now - tp->t_rcvtime) <= maxidle)))
TCP_TIMER_ARM(tp, TCPT_2MSL, tcp_keepintvl);
else
tp = tcp_close(tp);
Index: netinet/tcp_usrreq.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/tcp_usrreq.c,v
retrieving revision 1.202
diff -u -p -r1.202 tcp_usrreq.c
--- netinet/tcp_usrreq.c 31 Aug 2022 21:23:02 -0000 1.202
+++ netinet/tcp_usrreq.c 1 Sep 2022 14:47:22 -0000
@@ -274,6 +274,7 @@ tcp_fill_info(struct tcpcb *tp, struct s
struct proc *p = curproc;
struct tcp_info *ti;
u_int t = 1000000 / PR_SLOWHZ;
+ uint32_t now;
if (sizeof(*ti) > MLEN) {
MCLGETL(m, M_WAITOK, sizeof(*ti));
@@ -283,6 +284,7 @@ tcp_fill_info(struct tcpcb *tp, struct s
ti = mtod(m, struct tcp_info *);
m->m_len = sizeof(*ti);
memset(ti, 0, sizeof(*ti));
+ now = READ_ONCE(tcp_now);
ti->tcpi_state = tp->t_state;
if ((tp->t_flags & TF_REQ_TSTMP) && (tp->t_flags & TF_RCVD_TSTMP))
@@ -303,10 +305,10 @@ tcp_fill_info(struct tcpcb *tp, struct s
ti->tcpi_snd_mss = tp->t_maxseg;
ti->tcpi_rcv_mss = tp->t_peermss;
- ti->tcpi_last_data_sent = (tcp_now - tp->t_sndtime) * t;
- ti->tcpi_last_ack_sent = (tcp_now - tp->t_sndacktime) * t;
- ti->tcpi_last_data_recv = (tcp_now - tp->t_rcvtime) * t;
- ti->tcpi_last_ack_recv = (tcp_now - tp->t_rcvacktime) * t;
+ ti->tcpi_last_data_sent = (now - tp->t_sndtime) * t;
+ ti->tcpi_last_ack_sent = (now - tp->t_sndacktime) * t;
+ ti->tcpi_last_data_recv = (now - tp->t_rcvtime) * t;
+ ti->tcpi_last_ack_recv = (now - tp->t_rcvacktime) * t;
ti->tcpi_rtt = ((uint64_t)tp->t_srtt * t) >>
(TCP_RTT_SHIFT + TCP_RTT_BASE_SHIFT);
@@ -344,9 +346,9 @@ tcp_fill_info(struct tcpcb *tp, struct s
ti->tcpi_snd_max = tp->snd_max - tp->iss;
ti->tcpi_ts_recent = tp->ts_recent; /* XXX value from the wire */
- ti->tcpi_ts_recent_age = (tcp_now - tp->ts_recent_age) * t;
+ ti->tcpi_ts_recent_age = (now - tp->ts_recent_age) * t;
ti->tcpi_rfbuf_cnt = tp->rfbuf_cnt;
- ti->tcpi_rfbuf_ts = (tcp_now - tp->rfbuf_ts) * t;
+ ti->tcpi_rfbuf_ts = (now - tp->rfbuf_ts) * t;
ti->tcpi_so_rcv_sb_cc = so->so_rcv.sb_cc;
ti->tcpi_so_rcv_sb_hiwat = so->so_rcv.sb_hiwat;
Index: netinet/tcp_var.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/tcp_var.h,v
retrieving revision 1.153
diff -u -p -r1.153 tcp_var.h
--- netinet/tcp_var.h 31 Aug 2022 21:23:02 -0000 1.153
+++ netinet/tcp_var.h 1 Sep 2022 14:47:22 -0000
@@ -638,10 +638,11 @@ tcpstat_pkt(enum tcpstat_counters pcount
counters_pkt(tcpcounters, pcounter, bcounter, v);
}
+extern struct mutex tcp_timer_mtx;
extern const struct pr_usrreqs tcp_usrreqs;
extern struct pool tcpcb_pool;
extern struct inpcbtable tcbtable; /* head of queue of active tcpcb's */
-extern u_int32_t tcp_now; /* for RFC 1323 timestamps */
+extern uint32_t tcp_now; /* for RFC 1323 timestamps */
extern int tcp_do_rfc1323; /* enabled/disabled? */
extern int tcptv_keep_init; /* time to keep alive the initial SYN packet */
extern int tcp_mssdflt; /* default maximum segment size */
@@ -677,7 +678,7 @@ struct tcpcb *
struct tcpcb *
tcp_drop(struct tcpcb *, int);
int tcp_dooptions(struct tcpcb *, u_char *, int, struct tcphdr *,
- struct mbuf *, int, struct tcp_opt_info *, u_int);
+ struct mbuf *, int, struct tcp_opt_info *, u_int, uint32_t);
void tcp_init(void);
int tcp_input(struct mbuf **, int *, int, int);
int tcp_mss(struct tcpcb *, int);
@@ -697,7 +698,7 @@ void tcp_pulloutofband(struct socket *,
int tcp_reass(struct tcpcb *, struct tcphdr *, struct mbuf *, int *);
void tcp_rscale(struct tcpcb *, u_long);
void tcp_respond(struct tcpcb *, caddr_t, struct tcphdr *, tcp_seq,
- tcp_seq, int, u_int);
+ tcp_seq, int, u_int, uint32_t);
void tcp_setpersist(struct tcpcb *);
void tcp_update_sndspace(struct tcpcb *);
void tcp_update_rcvspace(struct tcpcb *);