Page MenuHomeFreeBSD

D24237.id70669.diff
No OneTemporary

D24237.id70669.diff

Index: sys/netinet/tcp_input.c
===================================================================
--- sys/netinet/tcp_input.c
+++ sys/netinet/tcp_input.c
@@ -1465,6 +1465,19 @@
return (newsize);
}
+void
+tcp_handle_wakeup(struct socket *so, int read_wakeup, int write_wakeup)
+{
+ if (read_wakeup != 0) {
+ SOCKBUF_UNLOCK_ASSERT(&so->so_rcv);
+ sorwakeup(so);
+ }
+ if (write_wakeup != 0) {
+ SOCKBUF_UNLOCK_ASSERT(&so->so_snd);
+ sowwakeup(so);
+ }
+}
+
void
tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
struct tcpcb *tp, int drop_hdrlen, int tlen, uint8_t iptos)
@@ -1478,6 +1491,8 @@
struct mbuf *mfree;
struct tcpopt to;
int tfo_syn;
+ int read_wakeup = 0;
+ int write_wakeup = 0;
#ifdef TCPDEBUG
/*
@@ -1805,7 +1820,7 @@
else if (!tcp_timer_active(tp, TT_PERSIST))
tcp_timer_activate(tp, TT_REXMT,
tp->t_rxtcur);
- sowwakeup(so);
+ write_wakeup = 1;
if (sbavail(&so->so_snd))
(void) tp->t_fb->tfb_tcp_output(tp);
goto check_delack;
@@ -1861,8 +1876,8 @@
m_adj(m, drop_hdrlen); /* delayed header drop */
sbappendstream_locked(&so->so_rcv, m, 0);
}
- /* NB: sorwakeup_locked() does an implicit unlock. */
- sorwakeup_locked(so);
+ SOCKBUF_UNLOCK(&so->so_rcv);
+ read_wakeup = 1;
if (DELAY_ACK(tp, tlen)) {
tp->t_flags |= TF_DELACK;
} else {
@@ -2405,7 +2420,7 @@
*/
if (tlen == 0 && (thflags & TH_FIN) == 0)
(void) tcp_reass(tp, (struct tcphdr *)0, NULL, 0,
- (struct mbuf *)0);
+ (struct mbuf *)0, &read_wakeup);
tp->snd_wl1 = th->th_seq - 1;
/* FALLTHROUGH */
@@ -2783,8 +2798,8 @@
tp->snd_wnd = 0;
ourfinisacked = 0;
}
- /* NB: sowwakeup_locked() does an implicit unlock. */
- sowwakeup_locked(so);
+ SOCKBUF_UNLOCK(&so->so_snd);
+ write_wakeup = 1;
m_freem(mfree);
/* Detect una wraparound. */
if (!IN_RECOVERY(tp->t_flags) &&
@@ -2997,8 +3012,8 @@
m_freem(m);
else
sbappendstream_locked(&so->so_rcv, m, 0);
- /* NB: sorwakeup_locked() does an implicit unlock. */
- sorwakeup_locked(so);
+ SOCKBUF_UNLOCK(&so->so_rcv);
+ read_wakeup = 1;
} else {
/*
* XXX: Due to the header drop above "th" is
@@ -3007,7 +3022,14 @@
* when trimming from the head.
*/
tcp_seq temp = save_start;
- thflags = tcp_reass(tp, th, &temp, &tlen, m);
+ /*
+ * Bracketing tcp_reass here to prevent
+ * sending of window updates, excessive
+ * (duplicate) ACKs or data packets
+ * which may contain outdated TCP options.
+ */
+ thflags = tcp_reass(tp, th, &temp, &tlen, m,
+ &read_wakeup);
tp->t_flags |= TF_ACKNOW;
}
if ((tp->t_flags & TF_SACK_PERMIT) && (save_tlen > 0)) {
@@ -3130,6 +3152,7 @@
tcp_timer_activate(tp, TT_DELACK, tcp_delacktime);
}
INP_WUNLOCK(tp->t_inpcb);
+ tcp_handle_wakeup(so, read_wakeup, write_wakeup);
return;
dropafterack:
@@ -3162,6 +3185,7 @@
TCP_PROBE3(debug__input, tp, th, m);
tp->t_flags |= TF_ACKNOW;
(void) tp->t_fb->tfb_tcp_output(tp);
+ tcp_handle_wakeup(so, read_wakeup, write_wakeup);
INP_WUNLOCK(tp->t_inpcb);
m_freem(m);
return;
@@ -3169,6 +3193,7 @@
dropwithreset:
if (tp != NULL) {
tcp_dropwithreset(m, th, tp, tlen, rstreason);
+ tcp_handle_wakeup(so, read_wakeup, write_wakeup);
INP_WUNLOCK(tp->t_inpcb);
} else
tcp_dropwithreset(m, th, NULL, tlen, rstreason);
@@ -3184,8 +3209,10 @@
&tcp_savetcp, 0);
#endif
TCP_PROBE3(debug__input, tp, th, m);
- if (tp != NULL)
+ if (tp != NULL) {
+ tcp_handle_wakeup(so, read_wakeup, write_wakeup);
INP_WUNLOCK(tp->t_inpcb);
+ }
m_freem(m);
}
Index: sys/netinet/tcp_reass.c
===================================================================
--- sys/netinet/tcp_reass.c
+++ sys/netinet/tcp_reass.c
@@ -526,7 +526,7 @@
*/
int
tcp_reass(struct tcpcb *tp, struct tcphdr *th, tcp_seq *seq_start,
- int *tlenp, struct mbuf *m)
+ int *tlenp, struct mbuf *m, int *read_wakeup)
{
struct tseg_qent *q, *last, *first;
struct tseg_qent *p = NULL;
@@ -961,7 +961,8 @@
} else {
sbappendstream_locked(&so->so_rcv, m, 0);
}
- sorwakeup_locked(so);
+ SOCKBUF_UNLOCK(&so->so_rcv);
+ *read_wakeup = 1;
return (flags);
}
if (tcp_new_limits) {
@@ -1109,6 +1110,7 @@
#ifdef TCP_REASS_LOGGING
tcp_reass_log_dump(tp);
#endif
- sorwakeup_locked(so);
+ SOCKBUF_UNLOCK(&so->so_rcv);
+ *read_wakeup = 1;
return (flags);
}
Index: sys/netinet/tcp_stacks/bbr.c
===================================================================
--- sys/netinet/tcp_stacks/bbr.c
+++ sys/netinet/tcp_stacks/bbr.c
@@ -8331,6 +8331,7 @@
uint16_t nsegs;
int32_t tfo_syn;
struct tcp_bbr *bbr;
+ int read_wakeup = 0;
bbr = (struct tcp_bbr *)tp->t_fb_ptr;
INP_WLOCK_ASSERT(tp->t_inpcb);
@@ -8518,8 +8519,8 @@
appended =
#endif
sbappendstream_locked(&so->so_rcv, m, 0);
- /* NB: sorwakeup_locked() does an implicit unlock. */
- sorwakeup_locked(so);
+ SOCKBUF_UNLOCK(&so->so_rcv);
+ read_wakeup = 1;
#ifdef NETFLIX_SB_LIMITS
if (so->so_rcv.sb_shlim && appended != mcnt)
counter_fo_release(so->so_rcv.sb_shlim,
@@ -8533,7 +8534,8 @@
* trimming from the head.
*/
tcp_seq temp = save_start;
- thflags = tcp_reass(tp, th, &temp, &tlen, m);
+ thflags = tcp_reass(tp, th, &temp, &tlen, m,
+ &read_wakeup);
tp->t_flags |= TF_ACKNOW;
}
if ((tp->t_flags & TF_SACK_PERMIT) && (save_tlen > 0)) {
@@ -8637,6 +8639,7 @@
(sbavail(&so->so_snd) > ctf_outstanding(tp))) {
bbr->r_wanted_output = 1;
}
+ tcp_handle_wakeup(so, read_wakeup, 0);
INP_WLOCK_ASSERT(tp->t_inpcb);
return (0);
}
@@ -9200,6 +9203,7 @@
int32_t ourfinisacked = 0;
int32_t ret_val;
struct tcp_bbr *bbr;
+ int read_wakeup = 0;
bbr = (struct tcp_bbr *)tp->t_fb_ptr;
ctf_calc_rwin(so, tp);
@@ -9356,9 +9360,11 @@
* If segment contains data or ACK, will call tcp_reass() later; if
* not, do so now to pass queued data to user.
*/
- if (tlen == 0 && (thflags & TH_FIN) == 0)
+ if (tlen == 0 && (thflags & TH_FIN) == 0) {
(void)tcp_reass(tp, (struct tcphdr *)0, NULL, 0,
- (struct mbuf *)0);
+ (struct mbuf *)0, &read_wakeup);
+ tcp_handle_wakeup(so, read_wakeup, 0);
+ }
tp->snd_wl1 = th->th_seq - 1;
if (bbr_process_ack(m, th, so, tp, to, tiwin, tlen, &ourfinisacked, thflags, &ret_val)) {
return (ret_val);
Index: sys/netinet/tcp_stacks/rack.c
===================================================================
--- sys/netinet/tcp_stacks/rack.c
+++ sys/netinet/tcp_stacks/rack.c
@@ -5575,6 +5575,7 @@
int32_t nsegs;
int32_t tfo_syn;
struct tcp_rack *rack;
+ int read_wakeup = 0;
rack = (struct tcp_rack *)tp->t_fb_ptr;
INP_WLOCK_ASSERT(tp->t_inpcb);
@@ -5763,8 +5764,8 @@
appended =
#endif
sbappendstream_locked(&so->so_rcv, m, 0);
- /* NB: sorwakeup_locked() does an implicit unlock. */
- sorwakeup_locked(so);
+ SOCKBUF_UNLOCK(&so->so_rcv);
+ read_wakeup = 1;
#ifdef NETFLIX_SB_LIMITS
if (so->so_rcv.sb_shlim && appended != mcnt)
counter_fo_release(so->so_rcv.sb_shlim,
@@ -5778,7 +5779,8 @@
* trimming from the head.
*/
tcp_seq temp = save_start;
- thflags = tcp_reass(tp, th, &temp, &tlen, m);
+ thflags = tcp_reass(tp, th, &temp, &tlen, m,
+ &read_wakeup);
tp->t_flags |= TF_ACKNOW;
}
if ((tp->t_flags & TF_SACK_PERMIT) && (save_tlen > 0)) {
@@ -5884,6 +5886,7 @@
(sbavail(&so->so_snd) > (tp->snd_max - tp->snd_una))) {
rack->r_wanted_output++;
}
+ tcp_handle_wakeup(so, read_wakeup, 0);
INP_WLOCK_ASSERT(tp->t_inpcb);
return (0);
}
@@ -6431,6 +6434,7 @@
struct tcp_rack *rack;
int32_t ret_val = 0;
int32_t ourfinisacked = 0;
+ int read_wakeup = 0;
ctf_calc_rwin(so, tp);
if ((thflags & TH_ACK) &&
@@ -6566,9 +6570,11 @@
* If segment contains data or ACK, will call tcp_reass() later; if
* not, do so now to pass queued data to user.
*/
- if (tlen == 0 && (thflags & TH_FIN) == 0)
+ if (tlen == 0 && (thflags & TH_FIN) == 0) {
(void) tcp_reass(tp, (struct tcphdr *)0, NULL, 0,
- (struct mbuf *)0);
+ (struct mbuf *)0, &read_wakeup);
+ tcp_handle_wakeup(so, read_wakeup, 0);
+ }
tp->snd_wl1 = th->th_seq - 1;
/* For syn-recv we need to possibly update the rtt */
if ((to->to_flags & TOF_TS) != 0 && to->to_tsecr) {
Index: sys/netinet/tcp_var.h
===================================================================
--- sys/netinet/tcp_var.h
+++ sys/netinet/tcp_var.h
@@ -879,7 +879,8 @@
const void *);
char *tcp_log_vain(struct in_conninfo *, struct tcphdr *, void *,
const void *);
-int tcp_reass(struct tcpcb *, struct tcphdr *, tcp_seq *, int *, struct mbuf *);
+int tcp_reass(struct tcpcb *, struct tcphdr *, tcp_seq *, int *,
+ struct mbuf *, int *);
void tcp_reass_global_init(void);
void tcp_reass_flush(struct tcpcb *);
void tcp_dooptions(struct tcpopt *, u_char *, int, int);
@@ -903,6 +904,7 @@
int tcp_input(struct mbuf **, int *, int);
int tcp_autorcvbuf(struct mbuf *, struct tcphdr *, struct socket *,
struct tcpcb *, int);
+void tcp_handle_wakeup(struct socket *, int, int);
void tcp_do_segment(struct mbuf *, struct tcphdr *,
struct socket *, struct tcpcb *, int, int, uint8_t);

File Metadata

Mime Type
text/plain
Expires
Sun, Feb 1, 1:38 PM (5 h, 2 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28379098
Default Alt Text
D24237.id70669.diff (9 KB)

Event Timeline