Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/tcp_stacks/bbr.c
- This file is larger than 256 KB, so syntax highlighting is disabled by default.
Show First 20 Lines • Show All 7,870 Lines • ▼ Show 20 Lines | if (tp->t_flags & TF_PREVVALID) { | ||||
if (tp->t_rxtshift == 1 && | if (tp->t_rxtshift == 1 && | ||||
(int)(ticks - tp->t_badrxtwin) < 0) | (int)(ticks - tp->t_badrxtwin) < 0) | ||||
bbr_cong_signal(tp, th, CC_RTO_ERR, NULL); | bbr_cong_signal(tp, th, CC_RTO_ERR, NULL); | ||||
} | } | ||||
SOCKBUF_LOCK(&so->so_snd); | SOCKBUF_LOCK(&so->so_snd); | ||||
acked_amount = min(acked, (int)sbavail(&so->so_snd)); | acked_amount = min(acked, (int)sbavail(&so->so_snd)); | ||||
tp->snd_wnd -= acked_amount; | tp->snd_wnd -= acked_amount; | ||||
mfree = sbcut_locked(&so->so_snd, acked_amount); | mfree = sbcut_locked(&so->so_snd, acked_amount); | ||||
/* NB: sowwakeup_locked() does an implicit unlock. */ | SOCKBUF_UNLOCK(&so->so_snd); | ||||
sowwakeup_locked(so); | tp->t_flags |= TF_WAKESOW; | ||||
m_freem(mfree); | m_freem(mfree); | ||||
if (SEQ_GT(th->th_ack, tp->snd_una)) { | if (SEQ_GT(th->th_ack, tp->snd_una)) { | ||||
bbr_collapse_rtt(tp, bbr, TCP_REXMTVAL(tp)); | bbr_collapse_rtt(tp, bbr, TCP_REXMTVAL(tp)); | ||||
} | } | ||||
tp->snd_una = th->th_ack; | tp->snd_una = th->th_ack; | ||||
bbr_ack_received(tp, bbr, th, acked, sack_changed, prev_acked, __LINE__, (bbr->r_ctl.rc_lost - lost)); | bbr_ack_received(tp, bbr, th, acked, sack_changed, prev_acked, __LINE__, (bbr->r_ctl.rc_lost - lost)); | ||||
if (IN_RECOVERY(tp->t_flags)) { | if (IN_RECOVERY(tp->t_flags)) { | ||||
if (SEQ_LT(th->th_ack, tp->snd_recover) && | if (SEQ_LT(th->th_ack, tp->snd_recover) && | ||||
▲ Show 20 Lines • Show All 459 Lines • ▼ Show 20 Lines | #endif | ||||
SOCKBUF_LOCK(&so->so_rcv); | SOCKBUF_LOCK(&so->so_rcv); | ||||
if (so->so_rcv.sb_state & SBS_CANTRCVMORE) | if (so->so_rcv.sb_state & SBS_CANTRCVMORE) | ||||
m_freem(m); | m_freem(m); | ||||
else | else | ||||
#ifdef NETFLIX_SB_LIMITS | #ifdef NETFLIX_SB_LIMITS | ||||
appended = | appended = | ||||
#endif | #endif | ||||
sbappendstream_locked(&so->so_rcv, m, 0); | sbappendstream_locked(&so->so_rcv, m, 0); | ||||
/* NB: sorwakeup_locked() does an implicit unlock. */ | SOCKBUF_UNLOCK(&so->so_rcv); | ||||
sorwakeup_locked(so); | tp->t_flags |= TF_WAKESOR; | ||||
#ifdef NETFLIX_SB_LIMITS | #ifdef NETFLIX_SB_LIMITS | ||||
if (so->so_rcv.sb_shlim && appended != mcnt) | if (so->so_rcv.sb_shlim && appended != mcnt) | ||||
counter_fo_release(so->so_rcv.sb_shlim, | counter_fo_release(so->so_rcv.sb_shlim, | ||||
mcnt - appended); | mcnt - appended); | ||||
#endif | #endif | ||||
} else { | } else { | ||||
/* | /* | ||||
* XXX: Due to the header drop above "th" is | * XXX: Due to the header drop above "th" is | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | #endif | ||||
/* | /* | ||||
* If FIN is received ACK the FIN and let the user know that the | * If FIN is received ACK the FIN and let the user know that the | ||||
* connection is closing. | * connection is closing. | ||||
*/ | */ | ||||
if (thflags & TH_FIN) { | if (thflags & TH_FIN) { | ||||
if (TCPS_HAVERCVDFIN(tp->t_state) == 0) { | if (TCPS_HAVERCVDFIN(tp->t_state) == 0) { | ||||
socantrcvmore(so); | socantrcvmore(so); | ||||
/* The socket upcall is handled by socantrcvmore. */ | |||||
tp->t_flags &= ~TF_WAKESOR; | |||||
/* | /* | ||||
* If connection is half-synchronized (ie NEEDSYN | * If connection is half-synchronized (ie NEEDSYN | ||||
* flag on) then delay ACK, so it may be piggybacked | * flag on) then delay ACK, so it may be piggybacked | ||||
* when SYN is sent. Otherwise, since we received a | * when SYN is sent. Otherwise, since we received a | ||||
* FIN then no more input can be expected, send ACK | * FIN then no more input can be expected, send ACK | ||||
* now. | * now. | ||||
*/ | */ | ||||
if (tp->t_flags & TF_NEEDSYN) { | if (tp->t_flags & TF_NEEDSYN) { | ||||
▲ Show 20 Lines • Show All 174 Lines • ▼ Show 20 Lines | if (so->so_rcv.sb_state & SBS_CANTRCVMORE) { | ||||
m_adj(m, drop_hdrlen); /* delayed header drop */ | m_adj(m, drop_hdrlen); /* delayed header drop */ | ||||
#ifdef NETFLIX_SB_LIMITS | #ifdef NETFLIX_SB_LIMITS | ||||
appended = | appended = | ||||
#endif | #endif | ||||
sbappendstream_locked(&so->so_rcv, m, 0); | sbappendstream_locked(&so->so_rcv, m, 0); | ||||
ctf_calc_rwin(so, tp); | ctf_calc_rwin(so, tp); | ||||
} | } | ||||
/* NB: sorwakeup_locked() does an implicit unlock. */ | SOCKBUF_UNLOCK(&so->so_rcv); | ||||
sorwakeup_locked(so); | tp->t_flags |= TF_WAKESOR; | ||||
#ifdef NETFLIX_SB_LIMITS | #ifdef NETFLIX_SB_LIMITS | ||||
if (so->so_rcv.sb_shlim && mcnt != appended) | if (so->so_rcv.sb_shlim && mcnt != appended) | ||||
counter_fo_release(so->so_rcv.sb_shlim, mcnt - appended); | counter_fo_release(so->so_rcv.sb_shlim, mcnt - appended); | ||||
#endif | #endif | ||||
if (DELAY_ACK(tp, bbr, nsegs)) { | if (DELAY_ACK(tp, bbr, nsegs)) { | ||||
bbr->bbr_segs_rcvd += max(1, nsegs); | bbr->bbr_segs_rcvd += max(1, nsegs); | ||||
tp->t_flags |= TF_DELACK; | tp->t_flags |= TF_DELACK; | ||||
bbr_timer_cancel(bbr, __LINE__, bbr->r_ctl.rc_rcvtime); | bbr_timer_cancel(bbr, __LINE__, bbr->r_ctl.rc_rcvtime); | ||||
▲ Show 20 Lines • Show All 174 Lines • ▼ Show 20 Lines | #endif | ||||
*/ | */ | ||||
#ifdef TCPDEBUG | #ifdef TCPDEBUG | ||||
if (so->so_options & SO_DEBUG) | if (so->so_options & SO_DEBUG) | ||||
tcp_trace(TA_INPUT, ostate, tp, | tcp_trace(TA_INPUT, ostate, tp, | ||||
(void *)tcp_saveipgen, | (void *)tcp_saveipgen, | ||||
&tcp_savetcp, 0); | &tcp_savetcp, 0); | ||||
#endif | #endif | ||||
/* Wake up the socket if we have room to write more */ | /* Wake up the socket if we have room to write more */ | ||||
sowwakeup(so); | tp->t_flags |= TF_WAKESOW; | ||||
if (tp->snd_una == tp->snd_max) { | if (tp->snd_una == tp->snd_max) { | ||||
/* Nothing left outstanding */ | /* Nothing left outstanding */ | ||||
bbr_log_progress_event(bbr, tp, ticks, PROGRESS_CLEAR, __LINE__); | bbr_log_progress_event(bbr, tp, ticks, PROGRESS_CLEAR, __LINE__); | ||||
if (sbavail(&tp->t_inpcb->inp_socket->so_snd) == 0) | if (sbavail(&tp->t_inpcb->inp_socket->so_snd) == 0) | ||||
bbr->rc_tp->t_acktime = 0; | bbr->rc_tp->t_acktime = 0; | ||||
bbr_timer_cancel(bbr, __LINE__, bbr->r_ctl.rc_rcvtime); | bbr_timer_cancel(bbr, __LINE__, bbr->r_ctl.rc_rcvtime); | ||||
if (bbr->rc_in_persist == 0) { | if (bbr->rc_in_persist == 0) { | ||||
bbr->r_ctl.rc_went_idle_time = bbr->r_ctl.rc_rcvtime; | bbr->r_ctl.rc_went_idle_time = bbr->r_ctl.rc_rcvtime; | ||||
▲ Show 20 Lines • Show All 2,927 Lines • ▼ Show 20 Lines | if (m->m_flags & M_TSTMP_LRO) { | ||||
tv.tv_sec = m->m_pkthdr.rcv_tstmp /1000000000; | tv.tv_sec = m->m_pkthdr.rcv_tstmp /1000000000; | ||||
tv.tv_usec = (m->m_pkthdr.rcv_tstmp % 1000000000)/1000; | tv.tv_usec = (m->m_pkthdr.rcv_tstmp % 1000000000)/1000; | ||||
} else { | } else { | ||||
/* Should not be should we kassert instead? */ | /* Should not be should we kassert instead? */ | ||||
tcp_get_usecs(&tv); | tcp_get_usecs(&tv); | ||||
} | } | ||||
retval = bbr_do_segment_nounlock(m, th, so, tp, | retval = bbr_do_segment_nounlock(m, th, so, tp, | ||||
drop_hdrlen, tlen, iptos, 0, &tv); | drop_hdrlen, tlen, iptos, 0, &tv); | ||||
if (retval == 0) | if (retval == 0) { | ||||
tcp_handle_wakeup(tp, so); | |||||
INP_WUNLOCK(tp->t_inpcb); | INP_WUNLOCK(tp->t_inpcb); | ||||
} | |||||
rrs: I am not sure this is right. When retval != 0 then it is possible (not always the case) that… | |||||
Done Inline ActionsIf tcpcb is destroyed, the socket would no longer be connected - which I check in the tcp_handle_wakeup() function using the so [socket], before trying to access tp [tcpcb]. What speaks against to adding the tcp_handle_wakeup() call in rack_bbr_common.c ctf_do_queued_segments() outside the close loop of handling the pending mbufs, rather than adding the socket handling in tcp_hpts.c? rscheff: If tcpcb is destroyed, the socket would no longer be connected - which I check in the… | |||||
} | } | ||||
/* | /* | ||||
* Return how much data can be sent without violating the | * Return how much data can be sent without violating the | ||||
* cwnd or rwnd. | * cwnd or rwnd. | ||||
*/ | */ | ||||
static inline uint32_t | static inline uint32_t | ||||
▲ Show 20 Lines • Show All 3,211 Lines • Show Last 20 Lines |
I am not sure this is right. When retval != 0 then it is possible (not always the case) that
the tp is no longer valid. It often is destroyed (or scheduled to be destroyed). Your check
in the wakeup function to make sure the socket is still connected may be good enough however
I need to think about that.
You are also missing changes in tcp_hpts.c
Let me find the lines for you.
Ok you need to add the tcp_handle_wakeup() in tcp_hpts.c after the calls to
tp->t_tfb->tfb_do_queued_segments()
in the function tcp_input_data() this is after it finishes releasing the reference I suspect.
For the other spot its in tcp_hptsi(), I think this should be near the tag skip_pacing
though if you goto that tag, then likely the tcb is destroyed.. not sure how this effects
the function.