Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/tcp_stacks/fastpath.c
Show First 20 Lines • Show All 166 Lines • ▼ Show 20 Lines | |||||
* in sequence the window was also updated. | * in sequence the window was also updated. | ||||
*/ | */ | ||||
static void | static void | ||||
tcp_do_fastack(struct mbuf *m, struct tcphdr *th, struct socket *so, | tcp_do_fastack(struct mbuf *m, struct tcphdr *th, struct socket *so, | ||||
struct tcpcb *tp, struct tcpopt *to, int drop_hdrlen, int tlen, | struct tcpcb *tp, struct tcpopt *to, int drop_hdrlen, int tlen, | ||||
int ti_locked, u_long tiwin) | int ti_locked, u_long tiwin) | ||||
{ | { | ||||
int acked; | int acked; | ||||
uint16_t nsegs; | |||||
int winup_only=0; | int winup_only=0; | ||||
nsegs = max(1, m->m_pkthdr.lro_nsegs); | |||||
#ifdef TCPDEBUG | #ifdef TCPDEBUG | ||||
/* | /* | ||||
* The size of tcp_saveipgen must be the size of the max ip header, | * The size of tcp_saveipgen must be the size of the max ip header, | ||||
* now IPv6. | * now IPv6. | ||||
*/ | */ | ||||
u_char tcp_saveipgen[IP6_HDR_LEN]; | u_char tcp_saveipgen[IP6_HDR_LEN]; | ||||
struct tcphdr tcp_savetcp; | struct tcphdr tcp_savetcp; | ||||
short ostate = 0; | short ostate = 0; | ||||
▲ Show 20 Lines • Show All 89 Lines • ▼ Show 20 Lines | if (SEQ_GT(tp->snd_una, tp->snd_recover) && | ||||
tp->snd_recover = th->th_ack - 1; | tp->snd_recover = th->th_ack - 1; | ||||
/* | /* | ||||
* Let the congestion control algorithm update | * Let the congestion control algorithm update | ||||
* congestion control related information. This | * congestion control related information. This | ||||
* typically means increasing the congestion | * typically means increasing the congestion | ||||
* window. | * window. | ||||
*/ | */ | ||||
cc_ack_received(tp, th, CC_ACK); | cc_ack_received(tp, th, nsegs, CC_ACK); | ||||
tp->snd_una = th->th_ack; | tp->snd_una = th->th_ack; | ||||
/* | /* | ||||
* Pull snd_wl2 up to prevent seq wrap relative | * Pull snd_wl2 up to prevent seq wrap relative | ||||
* to th_ack. | * to th_ack. | ||||
*/ | */ | ||||
tp->snd_wl2 = th->th_ack; | tp->snd_wl2 = th->th_ack; | ||||
tp->t_dupacks = 0; | tp->t_dupacks = 0; | ||||
▲ Show 20 Lines • Show All 207 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
static void | static void | ||||
tcp_do_slowpath(struct mbuf *m, struct tcphdr *th, struct socket *so, | tcp_do_slowpath(struct mbuf *m, struct tcphdr *th, struct socket *so, | ||||
struct tcpcb *tp, struct tcpopt *to, int drop_hdrlen, int tlen, | struct tcpcb *tp, struct tcpopt *to, int drop_hdrlen, int tlen, | ||||
int ti_locked, u_long tiwin, int thflags) | int ti_locked, u_long tiwin, int thflags) | ||||
{ | { | ||||
int acked, ourfinisacked, needoutput = 0; | int acked, ourfinisacked, needoutput = 0; | ||||
int rstreason, todrop, win; | int rstreason, todrop, win; | ||||
uint16_t nsegs; | |||||
char *s; | char *s; | ||||
struct in_conninfo *inc; | struct in_conninfo *inc; | ||||
struct mbuf *mfree = NULL; | struct mbuf *mfree = NULL; | ||||
nsegs = max(1, m->m_pkthdr.lro_nsegs); | |||||
#ifdef TCPDEBUG | #ifdef TCPDEBUG | ||||
/* | /* | ||||
* The size of tcp_saveipgen must be the size of the max ip header, | * The size of tcp_saveipgen must be the size of the max ip header, | ||||
* now IPv6. | * now IPv6. | ||||
*/ | */ | ||||
u_char tcp_saveipgen[IP6_HDR_LEN]; | u_char tcp_saveipgen[IP6_HDR_LEN]; | ||||
struct tcphdr tcp_savetcp; | struct tcphdr tcp_savetcp; | ||||
short ostate = 0; | short ostate = 0; | ||||
▲ Show 20 Lines • Show All 564 Lines • ▼ Show 20 Lines | if (SEQ_LEQ(th->th_ack, tp->snd_una)) { | ||||
* When using TCP ECN, notify the peer that | * When using TCP ECN, notify the peer that | ||||
* we reduced the cwnd. | * we reduced the cwnd. | ||||
*/ | */ | ||||
if (!tcp_timer_active(tp, TT_REXMT) || | if (!tcp_timer_active(tp, TT_REXMT) || | ||||
th->th_ack != tp->snd_una) | th->th_ack != tp->snd_una) | ||||
tp->t_dupacks = 0; | tp->t_dupacks = 0; | ||||
else if (++tp->t_dupacks > tcprexmtthresh || | else if (++tp->t_dupacks > tcprexmtthresh || | ||||
IN_FASTRECOVERY(tp->t_flags)) { | IN_FASTRECOVERY(tp->t_flags)) { | ||||
cc_ack_received(tp, th, CC_DUPACK); | cc_ack_received(tp, th, nsegs, | ||||
CC_DUPACK); | |||||
if ((tp->t_flags & TF_SACK_PERMIT) && | if ((tp->t_flags & TF_SACK_PERMIT) && | ||||
IN_FASTRECOVERY(tp->t_flags)) { | IN_FASTRECOVERY(tp->t_flags)) { | ||||
int awnd; | int awnd; | ||||
/* | /* | ||||
* Compute the amount of data in flight first. | * Compute the amount of data in flight first. | ||||
* We can inject new data into the pipe iff | * We can inject new data into the pipe iff | ||||
* we have less than 1/2 the original window's | * we have less than 1/2 the original window's | ||||
Show All 33 Lines | if (SEQ_LEQ(th->th_ack, tp->snd_una)) { | ||||
if (SEQ_LEQ(th->th_ack, | if (SEQ_LEQ(th->th_ack, | ||||
tp->snd_recover)) { | tp->snd_recover)) { | ||||
tp->t_dupacks = 0; | tp->t_dupacks = 0; | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
/* Congestion signal before ack. */ | /* Congestion signal before ack. */ | ||||
cc_cong_signal(tp, th, CC_NDUPACK); | cc_cong_signal(tp, th, CC_NDUPACK); | ||||
cc_ack_received(tp, th, CC_DUPACK); | cc_ack_received(tp, th, nsegs, | ||||
CC_DUPACK); | |||||
tcp_timer_activate(tp, TT_REXMT, 0); | tcp_timer_activate(tp, TT_REXMT, 0); | ||||
tp->t_rtttime = 0; | tp->t_rtttime = 0; | ||||
if (tp->t_flags & TF_SACK_PERMIT) { | if (tp->t_flags & TF_SACK_PERMIT) { | ||||
TCPSTAT_INC( | TCPSTAT_INC( | ||||
tcps_sack_recovery_episode); | tcps_sack_recovery_episode); | ||||
tp->sack_newdata = tp->snd_nxt; | tp->sack_newdata = tp->snd_nxt; | ||||
tp->snd_cwnd = tp->t_maxseg; | tp->snd_cwnd = tp->t_maxseg; | ||||
(void) tp->t_fb->tfb_tcp_output(tp); | (void) tp->t_fb->tfb_tcp_output(tp); | ||||
Show All 17 Lines | if (SEQ_LEQ(th->th_ack, tp->snd_una)) { | ||||
* ACKs. Each indicates a segment | * ACKs. Each indicates a segment | ||||
* leaving the network, creating room | * leaving the network, creating room | ||||
* for more. Make sure we can send a | * for more. Make sure we can send a | ||||
* packet on reception of each duplicate | * packet on reception of each duplicate | ||||
* ACK by increasing snd_cwnd by one | * ACK by increasing snd_cwnd by one | ||||
* segment. Restore the original | * segment. Restore the original | ||||
* snd_cwnd after packet transmission. | * snd_cwnd after packet transmission. | ||||
*/ | */ | ||||
cc_ack_received(tp, th, CC_DUPACK); | cc_ack_received(tp, th, nsegs, | ||||
CC_DUPACK); | |||||
u_long oldcwnd = tp->snd_cwnd; | u_long oldcwnd = tp->snd_cwnd; | ||||
tcp_seq oldsndmax = tp->snd_max; | tcp_seq oldsndmax = tp->snd_max; | ||||
u_int sent; | u_int sent; | ||||
int avail; | int avail; | ||||
KASSERT(tp->t_dupacks == 1 || | KASSERT(tp->t_dupacks == 1 || | ||||
tp->t_dupacks == 2, | tp->t_dupacks == 2, | ||||
("%s: dupacks not 1 or 2", | ("%s: dupacks not 1 or 2", | ||||
▲ Show 20 Lines • Show All 137 Lines • ▼ Show 20 Lines | process_ACK: | ||||
if (acked == 0) | if (acked == 0) | ||||
goto step6; | goto step6; | ||||
/* | /* | ||||
* Let the congestion control algorithm update congestion | * Let the congestion control algorithm update congestion | ||||
* control related information. This typically means increasing | * control related information. This typically means increasing | ||||
* the congestion window. | * the congestion window. | ||||
*/ | */ | ||||
cc_ack_received(tp, th, CC_ACK); | cc_ack_received(tp, th, nsegs, CC_ACK); | ||||
SOCKBUF_LOCK(&so->so_snd); | SOCKBUF_LOCK(&so->so_snd); | ||||
if (acked > sbavail(&so->so_snd)) { | if (acked > sbavail(&so->so_snd)) { | ||||
tp->snd_wnd -= sbavail(&so->so_snd); | tp->snd_wnd -= sbavail(&so->so_snd); | ||||
mfree = sbcut_locked(&so->so_snd, | mfree = sbcut_locked(&so->so_snd, | ||||
(int)sbavail(&so->so_snd)); | (int)sbavail(&so->so_snd)); | ||||
ourfinisacked = 1; | ourfinisacked = 1; | ||||
} else { | } else { | ||||
▲ Show 20 Lines • Show All 418 Lines • ▼ Show 20 Lines | |||||
void | void | ||||
tcp_do_segment_fastslow(struct mbuf *m, struct tcphdr *th, struct socket *so, | tcp_do_segment_fastslow(struct mbuf *m, struct tcphdr *th, struct socket *so, | ||||
struct tcpcb *tp, int drop_hdrlen, int tlen, uint8_t iptos, | struct tcpcb *tp, int drop_hdrlen, int tlen, uint8_t iptos, | ||||
int ti_locked) | int ti_locked) | ||||
{ | { | ||||
int thflags; | int thflags; | ||||
u_long tiwin; | u_long tiwin; | ||||
char *s; | char *s; | ||||
uint16_t nsegs; | |||||
int can_enter; | int can_enter; | ||||
struct in_conninfo *inc; | struct in_conninfo *inc; | ||||
struct tcpopt to; | struct tcpopt to; | ||||
thflags = th->th_flags; | thflags = th->th_flags; | ||||
tp->sackhint.last_sack_ack = 0; | tp->sackhint.last_sack_ack = 0; | ||||
inc = &tp->t_inpcb->inp_inc; | inc = &tp->t_inpcb->inp_inc; | ||||
nsegs = max(1, m->m_pkthdr.lro_nsegs); | |||||
/* | /* | ||||
* If this is either a state-changing packet or current state isn't | * If this is either a state-changing packet or current state isn't | ||||
* established, we require a write lock on tcbinfo. Otherwise, we | * established, we require a write lock on tcbinfo. Otherwise, we | ||||
* allow the tcbinfo to be in either alocked or unlocked, as the | * allow the tcbinfo to be in either alocked or unlocked, as the | ||||
* caller may have unnecessarily acquired a write lock due to a race. | * caller may have unnecessarily acquired a write lock due to a race. | ||||
*/ | */ | ||||
if ((thflags & (TH_SYN | TH_FIN | TH_RST)) != 0 || | if ((thflags & (TH_SYN | TH_FIN | TH_RST)) != 0 || | ||||
tp->t_state != TCPS_ESTABLISHED) { | tp->t_state != TCPS_ESTABLISHED) { | ||||
▲ Show 20 Lines • Show All 202 Lines • ▼ Show 20 Lines | |||||
* slow-path. | * slow-path. | ||||
*/ | */ | ||||
static int | static int | ||||
tcp_fastack(struct mbuf *m, struct tcphdr *th, struct socket *so, | tcp_fastack(struct mbuf *m, struct tcphdr *th, struct socket *so, | ||||
struct tcpcb *tp, struct tcpopt *to, int drop_hdrlen, int tlen, | struct tcpcb *tp, struct tcpopt *to, int drop_hdrlen, int tlen, | ||||
int ti_locked, u_long tiwin) | int ti_locked, u_long tiwin) | ||||
{ | { | ||||
int acked; | int acked; | ||||
uint16_t nsegs; | |||||
int winup_only=0; | int winup_only=0; | ||||
nsegs = max(1, m->m_pkthdr.lro_nsegs); | |||||
#ifdef TCPDEBUG | #ifdef TCPDEBUG | ||||
/* | /* | ||||
* The size of tcp_saveipgen must be the size of the max ip header, | * The size of tcp_saveipgen must be the size of the max ip header, | ||||
* now IPv6. | * now IPv6. | ||||
*/ | */ | ||||
u_char tcp_saveipgen[IP6_HDR_LEN]; | u_char tcp_saveipgen[IP6_HDR_LEN]; | ||||
struct tcphdr tcp_savetcp; | struct tcphdr tcp_savetcp; | ||||
short ostate = 0; | short ostate = 0; | ||||
▲ Show 20 Lines • Show All 128 Lines • ▼ Show 20 Lines | if (SEQ_GT(tp->snd_una, tp->snd_recover) && | ||||
tp->snd_recover = th->th_ack - 1; | tp->snd_recover = th->th_ack - 1; | ||||
/* | /* | ||||
* Let the congestion control algorithm update | * Let the congestion control algorithm update | ||||
* congestion control related information. This | * congestion control related information. This | ||||
* typically means increasing the congestion | * typically means increasing the congestion | ||||
* window. | * window. | ||||
*/ | */ | ||||
cc_ack_received(tp, th, CC_ACK); | cc_ack_received(tp, th, nsegs, CC_ACK); | ||||
tp->snd_una = th->th_ack; | tp->snd_una = th->th_ack; | ||||
tp->t_dupacks = 0; | tp->t_dupacks = 0; | ||||
/* | /* | ||||
* If all outstanding data are acked, stop | * If all outstanding data are acked, stop | ||||
* retransmit timer, otherwise restart timer | * retransmit timer, otherwise restart timer | ||||
* using current (possibly backed-off) value. | * using current (possibly backed-off) value. | ||||
▲ Show 20 Lines • Show All 297 Lines • Show Last 20 Lines |