Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/tcp_stacks/bbr.c
Context not available. | |||||
struct tcp_bbr *bbr; | struct tcp_bbr *bbr; | ||||
INP_WLOCK_ASSERT(tp->t_inpcb); | INP_WLOCK_ASSERT(tp->t_inpcb); | ||||
#ifdef STATS | |||||
stats_voi_update_abs_u32(tp->t_stats, VOI_TCP_CSIG, type); | |||||
#endif | |||||
bbr = (struct tcp_bbr *)tp->t_fb_ptr; | bbr = (struct tcp_bbr *)tp->t_fb_ptr; | ||||
switch (type) { | switch (type) { | ||||
case CC_NDUPACK: | case CC_NDUPACK: | ||||
Context not available. | |||||
nrsm->r_start = start; | nrsm->r_start = start; | ||||
nrsm->r_end = rsm->r_end; | nrsm->r_end = rsm->r_end; | ||||
nrsm->r_rtr_cnt = rsm->r_rtr_cnt; | nrsm->r_rtr_cnt = rsm->r_rtr_cnt; | ||||
nrsm-> r_rtt_not_allowed = rsm->r_rtt_not_allowed; | |||||
nrsm->r_flags = rsm->r_flags; | nrsm->r_flags = rsm->r_flags; | ||||
/* We don't transfer forward the SYN flag */ | /* We don't transfer forward the SYN flag */ | ||||
nrsm->r_flags &= ~BBR_HAS_SYN; | nrsm->r_flags &= ~BBR_HAS_SYN; | ||||
Context not available. | |||||
bbr->r_ctl.bbr_smallest_srtt_this_state = rtt; | bbr->r_ctl.bbr_smallest_srtt_this_state = rtt; | ||||
} | } | ||||
static void | |||||
bbr_earlier_retran(struct tcpcb *tp, struct tcp_bbr *bbr, struct bbr_sendmap *rsm, | |||||
uint32_t t, uint32_t cts, int ack_type) | |||||
{ | |||||
/* | |||||
* For this RSM, we acknowledged the data from a previous | |||||
* transmission, not the last one we made. This means we did a false | |||||
* retransmit. | |||||
*/ | |||||
if (rsm->r_flags & BBR_HAS_FIN) { | |||||
/* | |||||
* The sending of the FIN often is multiple sent when we | |||||
* have everything outstanding ack'd. We ignore this case | |||||
* since its over now. | |||||
*/ | |||||
return; | |||||
} | |||||
if (rsm->r_flags & BBR_TLP) { | |||||
/* | |||||
* We expect TLP's to have this occur often | |||||
*/ | |||||
bbr->rc_tlp_rtx_out = 0; | |||||
return; | |||||
} | |||||
if (ack_type != BBR_CUM_ACKED) { | |||||
/* | |||||
* If it was not a cum-ack we | |||||
* don't really know for sure since | |||||
* the timestamp could be from some | |||||
* other transmission. | |||||
*/ | |||||
return; | |||||
} | |||||
if (rsm->r_flags & BBR_WAS_SACKPASS) { | |||||
/* | |||||
* We retransmitted based on a sack and the earlier | |||||
* retransmission ack'd it - re-ordering is occuring. | |||||
*/ | |||||
BBR_STAT_INC(bbr_reorder_seen); | |||||
bbr->r_ctl.rc_reorder_ts = cts; | |||||
} | |||||
/* Back down the loss count */ | |||||
if (rsm->r_flags & BBR_MARKED_LOST) { | |||||
bbr->r_ctl.rc_lost -= rsm->r_end - rsm->r_start; | |||||
bbr->r_ctl.rc_lost_bytes -= rsm->r_end - rsm->r_start; | |||||
rsm->r_flags &= ~BBR_MARKED_LOST; | |||||
if (SEQ_GT(bbr->r_ctl.rc_lt_lost, bbr->r_ctl.rc_lost)) | |||||
/* LT sampling also needs adjustment */ | |||||
bbr->r_ctl.rc_lt_lost = bbr->r_ctl.rc_lost; | |||||
} | |||||
/***** RRS HERE ************************/ | |||||
/* Do we need to do this??? */ | |||||
/* bbr_reset_lt_bw_sampling(bbr, cts); */ | |||||
/***** RRS HERE ************************/ | |||||
BBR_STAT_INC(bbr_badfr); | |||||
BBR_STAT_ADD(bbr_badfr_bytes, (rsm->r_end - rsm->r_start)); | |||||
} | |||||
static void | static void | ||||
bbr_set_reduced_rtt(struct tcp_bbr *bbr, uint32_t cts, uint32_t line) | bbr_set_reduced_rtt(struct tcp_bbr *bbr, uint32_t cts, uint32_t line) | ||||
{ | { | ||||
Context not available. | |||||
/* Already done */ | /* Already done */ | ||||
return (0); | return (0); | ||||
} | } | ||||
if (rsm->r_rtt_not_allowed) { | |||||
/* Not allowed */ | |||||
return (0); | |||||
} | |||||
if (rsm->r_rtr_cnt == 1) { | if (rsm->r_rtr_cnt == 1) { | ||||
/* | /* | ||||
* Only one transmit. Hopefully the normal case. | * Only one transmit. Hopefully the normal case. | ||||
Context not available. | |||||
rsm->r_tim_lastsent[i], ack_type, to); | rsm->r_tim_lastsent[i], ack_type, to); | ||||
if ((i + 1) < rsm->r_rtr_cnt) { | if ((i + 1) < rsm->r_rtr_cnt) { | ||||
/* Likely */ | /* Likely */ | ||||
bbr_earlier_retran(tp, bbr, rsm, t, cts, ack_type); | return (0); | ||||
} else if (rsm->r_flags & BBR_TLP) { | } else if (rsm->r_flags & BBR_TLP) { | ||||
bbr->rc_tlp_rtx_out = 0; | bbr->rc_tlp_rtx_out = 0; | ||||
} | } | ||||
Context not available. | |||||
t = 1; | t = 1; | ||||
bbr_update_bbr_info(bbr, rsm, t, cts, to->to_tsecr, uts, BBR_RTT_BY_EARLIER_RET, | bbr_update_bbr_info(bbr, rsm, t, cts, to->to_tsecr, uts, BBR_RTT_BY_EARLIER_RET, | ||||
rsm->r_tim_lastsent[i], ack_type, to); | rsm->r_tim_lastsent[i], ack_type, to); | ||||
bbr_earlier_retran(tp, bbr, rsm, t, cts, ack_type); | return (0); | ||||
} else { | } else { | ||||
/* | /* | ||||
* Too many prior transmissions, just | * Too many prior transmissions, just | ||||
Context not available. | |||||
tp->t_fb_ptr = NULL; | tp->t_fb_ptr = NULL; | ||||
return (ENOMEM); | return (ENOMEM); | ||||
} | } | ||||
rsm->r_flags = BBR_OVERMAX; | rsm->r_rtt_not_allowed = 1; | ||||
rsm->r_tim_lastsent[0] = cts; | rsm->r_tim_lastsent[0] = cts; | ||||
rsm->r_rtr_cnt = 1; | rsm->r_rtr_cnt = 1; | ||||
rsm->r_rtr_bytes = 0; | rsm->r_rtr_bytes = 0; | ||||
Context not available. | |||||
counter_u64_add(bbr_flows_whdwr_pacing, -1); | counter_u64_add(bbr_flows_whdwr_pacing, -1); | ||||
else | else | ||||
counter_u64_add(bbr_flows_nohdwr_pacing, -1); | counter_u64_add(bbr_flows_nohdwr_pacing, -1); | ||||
if (bbr->r_ctl.crte != NULL) { | |||||
tcp_rel_pacing_rate(bbr->r_ctl.crte, tp); | |||||
bbr->r_ctl.crte = NULL; | |||||
} | |||||
rsm = TAILQ_FIRST(&bbr->r_ctl.rc_map); | rsm = TAILQ_FIRST(&bbr->r_ctl.rc_map); | ||||
while (rsm) { | while (rsm) { | ||||
TAILQ_REMOVE(&bbr->r_ctl.rc_map, rsm, r_next); | TAILQ_REMOVE(&bbr->r_ctl.rc_map, rsm, r_next); | ||||
Context not available. | |||||
th->th_seq = htonl(tp->snd_max); | th->th_seq = htonl(tp->snd_max); | ||||
bbr_seq = tp->snd_max; | bbr_seq = tp->snd_max; | ||||
} | } | ||||
} else if (flags & TH_RST) { | |||||
/* | |||||
* For a Reset send the last cum ack in sequence | |||||
* (this like any other choice may still generate a | |||||
* challenge ack, if a ack-update packet is in | |||||
* flight). | |||||
*/ | |||||
th->th_seq = htonl(tp->snd_una); | |||||
bbr_seq = tp->snd_una; | |||||
} else { | } else { | ||||
/* | /* | ||||
* len == 0 and not persist we use snd_max, sending | * len == 0 and not persist we use snd_max, sending | ||||
Context not available. | |||||
} else { | } else { | ||||
bbr->bbr_hdw_pace_ena = 0; | bbr->bbr_hdw_pace_ena = 0; | ||||
#ifdef RATELIMIT | #ifdef RATELIMIT | ||||
if (bbr->bbr_hdrw_pacing) { | if (bbr->r_ctl.crte != NULL) { | ||||
bbr->bbr_hdrw_pacing = 0; | tcp_rel_pacing_rate(bbr->r_ctl.crte, tp); | ||||
in_pcbdetach_txrtlmt(bbr->rc_inp); | bbr->r_ctl.crte = NULL; | ||||
} | } | ||||
#endif | #endif | ||||
} | } | ||||
Context not available. |