* TLP Timer, here we simply setup what segment we want to * have the TLP expire on, the normal bbr_output_wtime() will then * send it out. * * We return 1, saying don't proceed with bbr_output_wtime only * when all timers have been stopped (destroyed PCB?). */
| 4553 | * when all timers have been stopped (destroyed PCB?). |
| 4554 | */ |
| 4555 | static int |
| 4556 | bbr_timeout_tlp(struct tcpcb *tp, struct tcp_bbr *bbr, uint32_t cts) |
| 4557 | { |
| 4558 | /* |
| 4559 | * Tail Loss Probe. |
| 4560 | */ |
| 4561 | struct bbr_sendmap *rsm = NULL; |
| 4562 | struct socket *so; |
| 4563 | uint32_t amm; |
| 4564 | uint32_t out, avail; |
| 4565 | uint32_t maxseg; |
| 4566 | int collapsed_win = 0; |
| 4567 | |
| 4568 | if (bbr->rc_all_timers_stopped) { |
| 4569 | return (1); |
| 4570 | } |
| 4571 | if (TSTMP_LT(cts, bbr->r_ctl.rc_timer_exp)) { |
| 4572 | /* Its not time yet */ |
| 4573 | return (0); |
| 4574 | } |
| 4575 | if (ctf_progress_timeout_check(tp, true)) { |
| 4576 | bbr_log_progress_event(bbr, tp, tick, PROGRESS_DROP, __LINE__); |
| 4577 | tcp_set_inp_to_drop(bbr->rc_inp, ETIMEDOUT); |
| 4578 | return (1); |
| 4579 | } |
| 4580 | /* Did we somehow get into persists? */ |
| 4581 | if (bbr->rc_in_persist) { |
| 4582 | return (0); |
| 4583 | } |
| 4584 | if (bbr->r_state && (bbr->r_state != tp->t_state)) |
| 4585 | bbr_set_state(tp, bbr, 0); |
| 4586 | BBR_STAT_INC(bbr_tlp_tot); |
| 4587 | maxseg = tp->t_maxseg - bbr->rc_last_options; |
| 4588 | /* |
| 4589 | * A TLP timer has expired. We have been idle for 2 rtts. So we now |
| 4590 | * need to figure out how to force a full MSS segment out. |
| 4591 | */ |
| 4592 | so = tp->t_inpcb->inp_socket; |
| 4593 | avail = sbavail(&so->so_snd); |
| 4594 | out = ctf_outstanding(tp); |
| 4595 | if (out > tp->snd_wnd) { |
| 4596 | /* special case, we need a retransmission */ |
| 4597 | collapsed_win = 1; |
| 4598 | goto need_retran; |
| 4599 | } |
| 4600 | if (avail > out) { |
| 4601 | /* New data is available */ |
| 4602 | amm = avail - out; |
| 4603 | if (amm > maxseg) { |
| 4604 | amm = maxseg; |
| 4605 | } else if ((amm < maxseg) && ((tp->t_flags & TF_NODELAY) == 0)) { |
| 4606 | /* not enough to fill a MTU and no-delay is off */ |
| 4607 | goto need_retran; |
| 4608 | } |
| 4609 | /* Set the send-new override */ |
| 4610 | if ((out + amm) <= tp->snd_wnd) { |
| 4611 | bbr->rc_tlp_new_data = 1; |
| 4612 | } else { |
no test coverage detected