Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/tcp_input.c
Show First 20 Lines • Show All 291 Lines • ▼ Show 20 Lines | hhook_run_tcp_est_in(struct tcpcb *tp, struct tcphdr *th, struct tcpopt *to) | ||||
struct tcp_hhook_data hhook_data; | struct tcp_hhook_data hhook_data; | ||||
if (V_tcp_hhh[HHOOK_TCP_EST_IN]->hhh_nhooks > 0) { | if (V_tcp_hhh[HHOOK_TCP_EST_IN]->hhh_nhooks > 0) { | ||||
hhook_data.tp = tp; | hhook_data.tp = tp; | ||||
hhook_data.th = th; | hhook_data.th = th; | ||||
hhook_data.to = to; | hhook_data.to = to; | ||||
hhook_run_hooks(V_tcp_hhh[HHOOK_TCP_EST_IN], &hhook_data, | hhook_run_hooks(V_tcp_hhh[HHOOK_TCP_EST_IN], &hhook_data, | ||||
tp->osd); | &tp->t_osd); | ||||
} | } | ||||
} | } | ||||
#endif | #endif | ||||
/* | /* | ||||
* CC wrapper hook functions | * CC wrapper hook functions | ||||
*/ | */ | ||||
void | void | ||||
cc_ack_received(struct tcpcb *tp, struct tcphdr *th, uint16_t nsegs, | cc_ack_received(struct tcpcb *tp, struct tcphdr *th, uint16_t nsegs, | ||||
uint16_t type) | uint16_t type) | ||||
{ | { | ||||
struct inpcb *inp = tptoinpcb(tp); | struct inpcb *inp = tptoinpcb(tp); | ||||
#ifdef STATS | #ifdef STATS | ||||
int32_t gput; | int32_t gput; | ||||
#endif | #endif | ||||
INP_WLOCK_ASSERT(inp); | INP_WLOCK_ASSERT(inp); | ||||
tp->ccv->nsegs = nsegs; | tp->t_ccv.nsegs = nsegs; | ||||
tp->ccv->bytes_this_ack = BYTES_THIS_ACK(tp, th); | tp->t_ccv.bytes_this_ack = BYTES_THIS_ACK(tp, th); | ||||
if ((!V_tcp_do_newcwv && (tp->snd_cwnd <= tp->snd_wnd)) || | if ((!V_tcp_do_newcwv && (tp->snd_cwnd <= tp->snd_wnd)) || | ||||
(V_tcp_do_newcwv && (tp->snd_cwnd <= tp->snd_wnd) && | (V_tcp_do_newcwv && (tp->snd_cwnd <= tp->snd_wnd) && | ||||
(tp->snd_cwnd < (tcp_compute_pipe(tp) * 2)))) | (tp->snd_cwnd < (tcp_compute_pipe(tp) * 2)))) | ||||
tp->ccv->flags |= CCF_CWND_LIMITED; | tp->t_ccv.flags |= CCF_CWND_LIMITED; | ||||
else | else | ||||
tp->ccv->flags &= ~CCF_CWND_LIMITED; | tp->t_ccv.flags &= ~CCF_CWND_LIMITED; | ||||
if (type == CC_ACK) { | if (type == CC_ACK) { | ||||
#ifdef STATS | #ifdef STATS | ||||
stats_voi_update_abs_s32(tp->t_stats, VOI_TCP_CALCFRWINDIFF, | stats_voi_update_abs_s32(tp->t_stats, VOI_TCP_CALCFRWINDIFF, | ||||
((int32_t)tp->snd_cwnd) - tp->snd_wnd); | ((int32_t)tp->snd_cwnd) - tp->snd_wnd); | ||||
if (!IN_RECOVERY(tp->t_flags)) | if (!IN_RECOVERY(tp->t_flags)) | ||||
stats_voi_update_abs_u32(tp->t_stats, VOI_TCP_ACKLEN, | stats_voi_update_abs_u32(tp->t_stats, VOI_TCP_ACKLEN, | ||||
tp->ccv->bytes_this_ack / (tcp_maxseg(tp) * nsegs)); | tp->t_ccv.bytes_this_ack / (tcp_maxseg(tp) * nsegs)); | ||||
if ((tp->t_flags & TF_GPUTINPROG) && | if ((tp->t_flags & TF_GPUTINPROG) && | ||||
SEQ_GEQ(th->th_ack, tp->gput_ack)) { | SEQ_GEQ(th->th_ack, tp->gput_ack)) { | ||||
/* | /* | ||||
* Compute goodput in bits per millisecond. | * Compute goodput in bits per millisecond. | ||||
*/ | */ | ||||
gput = (((int64_t)SEQ_SUB(th->th_ack, tp->gput_seq)) << 3) / | gput = (((int64_t)SEQ_SUB(th->th_ack, tp->gput_seq)) << 3) / | ||||
max(1, tcp_ts_getticks() - tp->gput_ts); | max(1, tcp_ts_getticks() - tp->gput_ts); | ||||
stats_voi_update_abs_u32(tp->t_stats, VOI_TCP_GPUT, | stats_voi_update_abs_u32(tp->t_stats, VOI_TCP_GPUT, | ||||
gput); | gput); | ||||
/* | /* | ||||
* XXXLAS: This is a temporary hack, and should be | * XXXLAS: This is a temporary hack, and should be | ||||
* chained off VOI_TCP_GPUT when stats(9) grows an API | * chained off VOI_TCP_GPUT when stats(9) grows an API | ||||
* to deal with chained VOIs. | * to deal with chained VOIs. | ||||
*/ | */ | ||||
if (tp->t_stats_gput_prev > 0) | if (tp->t_stats_gput_prev > 0) | ||||
stats_voi_update_abs_s32(tp->t_stats, | stats_voi_update_abs_s32(tp->t_stats, | ||||
VOI_TCP_GPUT_ND, | VOI_TCP_GPUT_ND, | ||||
((gput - tp->t_stats_gput_prev) * 100) / | ((gput - tp->t_stats_gput_prev) * 100) / | ||||
tp->t_stats_gput_prev); | tp->t_stats_gput_prev); | ||||
tp->t_flags &= ~TF_GPUTINPROG; | tp->t_flags &= ~TF_GPUTINPROG; | ||||
tp->t_stats_gput_prev = gput; | tp->t_stats_gput_prev = gput; | ||||
} | } | ||||
#endif /* STATS */ | #endif /* STATS */ | ||||
if (tp->snd_cwnd > tp->snd_ssthresh) { | if (tp->snd_cwnd > tp->snd_ssthresh) { | ||||
tp->t_bytes_acked += tp->ccv->bytes_this_ack; | tp->t_bytes_acked += tp->t_ccv.bytes_this_ack; | ||||
if (tp->t_bytes_acked >= tp->snd_cwnd) { | if (tp->t_bytes_acked >= tp->snd_cwnd) { | ||||
tp->t_bytes_acked -= tp->snd_cwnd; | tp->t_bytes_acked -= tp->snd_cwnd; | ||||
tp->ccv->flags |= CCF_ABC_SENTAWND; | tp->t_ccv.flags |= CCF_ABC_SENTAWND; | ||||
} | } | ||||
} else { | } else { | ||||
tp->ccv->flags &= ~CCF_ABC_SENTAWND; | tp->t_ccv.flags &= ~CCF_ABC_SENTAWND; | ||||
tp->t_bytes_acked = 0; | tp->t_bytes_acked = 0; | ||||
} | } | ||||
} | } | ||||
if (CC_ALGO(tp)->ack_received != NULL) { | if (CC_ALGO(tp)->ack_received != NULL) { | ||||
/* XXXLAS: Find a way to live without this */ | /* XXXLAS: Find a way to live without this */ | ||||
tp->ccv->curack = th->th_ack; | tp->t_ccv.curack = th->th_ack; | ||||
CC_ALGO(tp)->ack_received(tp->ccv, type); | CC_ALGO(tp)->ack_received(&tp->t_ccv, type); | ||||
} | } | ||||
#ifdef STATS | #ifdef STATS | ||||
stats_voi_update_abs_ulong(tp->t_stats, VOI_TCP_LCWIN, tp->snd_cwnd); | stats_voi_update_abs_ulong(tp->t_stats, VOI_TCP_LCWIN, tp->snd_cwnd); | ||||
#endif | #endif | ||||
} | } | ||||
void | void | ||||
cc_conn_init(struct tcpcb *tp) | cc_conn_init(struct tcpcb *tp) | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | cc_conn_init(struct tcpcb *tp) | ||||
* requiring us to be cautious. | * requiring us to be cautious. | ||||
*/ | */ | ||||
if (tp->snd_cwnd == 1) | if (tp->snd_cwnd == 1) | ||||
tp->snd_cwnd = maxseg; /* SYN(-ACK) lost */ | tp->snd_cwnd = maxseg; /* SYN(-ACK) lost */ | ||||
else | else | ||||
tp->snd_cwnd = tcp_compute_initwnd(maxseg); | tp->snd_cwnd = tcp_compute_initwnd(maxseg); | ||||
if (CC_ALGO(tp)->conn_init != NULL) | if (CC_ALGO(tp)->conn_init != NULL) | ||||
CC_ALGO(tp)->conn_init(tp->ccv); | CC_ALGO(tp)->conn_init(&tp->t_ccv); | ||||
} | } | ||||
void inline | void inline | ||||
cc_cong_signal(struct tcpcb *tp, struct tcphdr *th, uint32_t type) | cc_cong_signal(struct tcpcb *tp, struct tcphdr *th, uint32_t type) | ||||
{ | { | ||||
INP_WLOCK_ASSERT(tptoinpcb(tp)); | INP_WLOCK_ASSERT(tptoinpcb(tp)); | ||||
#ifdef STATS | #ifdef STATS | ||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | case CC_RTO_ERR: | ||||
tp->snd_nxt = tp->snd_max; | tp->snd_nxt = tp->snd_max; | ||||
tp->t_flags &= ~TF_PREVVALID; | tp->t_flags &= ~TF_PREVVALID; | ||||
tp->t_badrxtwin = 0; | tp->t_badrxtwin = 0; | ||||
break; | break; | ||||
} | } | ||||
if (CC_ALGO(tp)->cong_signal != NULL) { | if (CC_ALGO(tp)->cong_signal != NULL) { | ||||
if (th != NULL) | if (th != NULL) | ||||
tp->ccv->curack = th->th_ack; | tp->t_ccv.curack = th->th_ack; | ||||
CC_ALGO(tp)->cong_signal(tp->ccv, type); | CC_ALGO(tp)->cong_signal(&tp->t_ccv, type); | ||||
} | } | ||||
} | } | ||||
void inline | void inline | ||||
cc_post_recovery(struct tcpcb *tp, struct tcphdr *th) | cc_post_recovery(struct tcpcb *tp, struct tcphdr *th) | ||||
{ | { | ||||
INP_WLOCK_ASSERT(tptoinpcb(tp)); | INP_WLOCK_ASSERT(tptoinpcb(tp)); | ||||
/* XXXLAS: KASSERT that we're in recovery? */ | /* XXXLAS: KASSERT that we're in recovery? */ | ||||
if (CC_ALGO(tp)->post_recovery != NULL) { | if (CC_ALGO(tp)->post_recovery != NULL) { | ||||
tp->ccv->curack = th->th_ack; | tp->t_ccv.curack = th->th_ack; | ||||
CC_ALGO(tp)->post_recovery(tp->ccv); | CC_ALGO(tp)->post_recovery(&tp->t_ccv); | ||||
} | } | ||||
/* XXXLAS: EXIT_RECOVERY ? */ | /* XXXLAS: EXIT_RECOVERY ? */ | ||||
tp->t_bytes_acked = 0; | tp->t_bytes_acked = 0; | ||||
tp->sackhint.delivered_data = 0; | tp->sackhint.delivered_data = 0; | ||||
tp->sackhint.prr_out = 0; | tp->sackhint.prr_out = 0; | ||||
} | } | ||||
/* | /* | ||||
Show All 14 Lines | |||||
void inline | void inline | ||||
cc_ecnpkt_handler_flags(struct tcpcb *tp, uint16_t flags, uint8_t iptos) | cc_ecnpkt_handler_flags(struct tcpcb *tp, uint16_t flags, uint8_t iptos) | ||||
{ | { | ||||
INP_WLOCK_ASSERT(tptoinpcb(tp)); | INP_WLOCK_ASSERT(tptoinpcb(tp)); | ||||
if (CC_ALGO(tp)->ecnpkt_handler != NULL) { | if (CC_ALGO(tp)->ecnpkt_handler != NULL) { | ||||
switch (iptos & IPTOS_ECN_MASK) { | switch (iptos & IPTOS_ECN_MASK) { | ||||
case IPTOS_ECN_CE: | case IPTOS_ECN_CE: | ||||
tp->ccv->flags |= CCF_IPHDR_CE; | tp->t_ccv.flags |= CCF_IPHDR_CE; | ||||
break; | break; | ||||
case IPTOS_ECN_ECT0: | case IPTOS_ECN_ECT0: | ||||
/* FALLTHROUGH */ | /* FALLTHROUGH */ | ||||
case IPTOS_ECN_ECT1: | case IPTOS_ECN_ECT1: | ||||
/* FALLTHROUGH */ | /* FALLTHROUGH */ | ||||
case IPTOS_ECN_NOTECT: | case IPTOS_ECN_NOTECT: | ||||
tp->ccv->flags &= ~CCF_IPHDR_CE; | tp->t_ccv.flags &= ~CCF_IPHDR_CE; | ||||
break; | break; | ||||
} | } | ||||
if (flags & TH_CWR) | if (flags & TH_CWR) | ||||
tp->ccv->flags |= CCF_TCPHDR_CWR; | tp->t_ccv.flags |= CCF_TCPHDR_CWR; | ||||
else | else | ||||
tp->ccv->flags &= ~CCF_TCPHDR_CWR; | tp->t_ccv.flags &= ~CCF_TCPHDR_CWR; | ||||
CC_ALGO(tp)->ecnpkt_handler(tp->ccv); | CC_ALGO(tp)->ecnpkt_handler(&tp->t_ccv); | ||||
if (tp->ccv->flags & CCF_ACKNOW) { | if (tp->t_ccv.flags & CCF_ACKNOW) { | ||||
tcp_timer_activate(tp, TT_DELACK, tcp_delacktime); | tcp_timer_activate(tp, TT_DELACK, tcp_delacktime); | ||||
tp->t_flags |= TF_ACKNOW; | tp->t_flags |= TF_ACKNOW; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
void inline | void inline | ||||
cc_ecnpkt_handler(struct tcpcb *tp, struct tcphdr *th, uint8_t iptos) | cc_ecnpkt_handler(struct tcpcb *tp, struct tcphdr *th, uint8_t iptos) | ||||
▲ Show 20 Lines • Show All 3,557 Lines • Show Last 20 Lines |