Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/tcp_input.c
Context not available. | |||||
#define tcb6 tcb /* for KAME src sync over BSD*'s */ | #define tcb6 tcb /* for KAME src sync over BSD*'s */ | ||||
VNET_DEFINE(struct inpcbinfo, tcbinfo); | VNET_DEFINE(struct inpcbinfo, tcbinfo); | ||||
static void tcp_dooptions(struct tcpopt *, u_char *, int, int); | |||||
static void tcp_do_segment(struct mbuf *, struct tcphdr *, | |||||
struct socket *, struct tcpcb *, int, int, uint8_t, | |||||
int); | |||||
static void tcp_dropwithreset(struct mbuf *, struct tcphdr *, | |||||
struct tcpcb *, int, int); | |||||
static void tcp_pulloutofband(struct socket *, | |||||
struct tcphdr *, struct mbuf *, int); | |||||
static void tcp_xmit_timer(struct tcpcb *, int); | |||||
static void tcp_newreno_partial_ack(struct tcpcb *, struct tcphdr *); | |||||
static void inline cc_ack_received(struct tcpcb *tp, struct tcphdr *th, | |||||
uint16_t type); | |||||
static void inline cc_conn_init(struct tcpcb *tp); | |||||
static void inline cc_post_recovery(struct tcpcb *tp, struct tcphdr *th); | |||||
static void inline hhook_run_tcp_est_in(struct tcpcb *tp, | |||||
struct tcphdr *th, struct tcpopt *to); | |||||
/* | /* | ||||
jtl: This is already defined in tcp_var.h. Why add a non-static declaration to tcp_input.c? | |||||
Not Done Inline ActionsThat may have been a cut and paste error since I have no memory of rrs: That may have been a cut and paste error since I have no memory of
adding it explicitly :-) | |||||
* TCP statistics are stored in an "array" of counter(9)s. | * TCP statistics are stored in an "array" of counter(9)s. | ||||
Not Done Inline ActionsShouldn't globally-visible functions normally go in a .h? jtl: Shouldn't globally-visible functions normally go in a .h? | |||||
*/ | */ | ||||
Context not available. | |||||
/* | /* | ||||
* Wrapper for the TCP established input helper hook. | * Wrapper for the TCP established input helper hook. | ||||
*/ | */ | ||||
static void inline | void | ||||
hhook_run_tcp_est_in(struct tcpcb *tp, struct tcphdr *th, struct tcpopt *to) | 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; | ||||
Context not available. | |||||
/* | /* | ||||
* CC wrapper hook functions | * CC wrapper hook functions | ||||
*/ | */ | ||||
static void inline | void | ||||
cc_ack_received(struct tcpcb *tp, struct tcphdr *th, uint16_t type) | cc_ack_received(struct tcpcb *tp, struct tcphdr *th, uint16_t type) | ||||
{ | { | ||||
INP_WLOCK_ASSERT(tp->t_inpcb); | INP_WLOCK_ASSERT(tp->t_inpcb); | ||||
Context not available. | |||||
} | } | ||||
} | } | ||||
static void inline | void | ||||
cc_conn_init(struct tcpcb *tp) | cc_conn_init(struct tcpcb *tp) | ||||
{ | { | ||||
struct hc_metrics_lite metrics; | struct hc_metrics_lite metrics; | ||||
Context not available. | |||||
} | } | ||||
} | } | ||||
static 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(tp->t_inpcb); | INP_WLOCK_ASSERT(tp->t_inpcb); | ||||
Context not available. | |||||
struct tcpopt to; /* options in this segment */ | struct tcpopt to; /* options in this segment */ | ||||
char *s = NULL; /* address and port logging */ | char *s = NULL; /* address and port logging */ | ||||
int ti_locked; | int ti_locked; | ||||
#define TI_UNLOCKED 1 | |||||
#define TI_RLOCKED 2 | |||||
#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, | ||||
Context not available. | |||||
* contains. tcp_do_segment() consumes | * contains. tcp_do_segment() consumes | ||||
* the mbuf chain and unlocks the inpcb. | * the mbuf chain and unlocks the inpcb. | ||||
*/ | */ | ||||
tcp_do_segment(m, th, so, tp, drop_hdrlen, tlen, | tp->t_fb->tfb_tcp_do_segment(m, th, so, tp, drop_hdrlen, tlen, | ||||
iptos, ti_locked); | iptos, ti_locked); | ||||
INP_INFO_UNLOCK_ASSERT(&V_tcbinfo); | INP_INFO_UNLOCK_ASSERT(&V_tcbinfo); | ||||
return (IPPROTO_DONE); | return (IPPROTO_DONE); | ||||
Context not available. | |||||
* state. tcp_do_segment() always consumes the mbuf chain, unlocks | * state. tcp_do_segment() always consumes the mbuf chain, unlocks | ||||
* the inpcb, and unlocks pcbinfo. | * the inpcb, and unlocks pcbinfo. | ||||
*/ | */ | ||||
tcp_do_segment(m, th, so, tp, drop_hdrlen, tlen, iptos, ti_locked); | tp->t_fb->tfb_tcp_do_segment(m, th, so, tp, drop_hdrlen, tlen, iptos, ti_locked); | ||||
INP_INFO_UNLOCK_ASSERT(&V_tcbinfo); | INP_INFO_UNLOCK_ASSERT(&V_tcbinfo); | ||||
return (IPPROTO_DONE); | return (IPPROTO_DONE); | ||||
Not Done Inline ActionsThis should probably be converted to an appropriate debug statement. jtl: This should probably be converted to an appropriate debug statement. | |||||
Not Done Inline ActionsActually its a printf I forgot to purge.. it has been removed now :-) rrs: Actually its a printf I forgot to purge.. it has been removed now :-) | |||||
Context not available. | |||||
return (IPPROTO_DONE); | return (IPPROTO_DONE); | ||||
} | } | ||||
static void | void | ||||
tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, | tcp_do_segment(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) | ||||
Context not available. | |||||
tp->t_rxtcur); | tp->t_rxtcur); | ||||
sowwakeup(so); | sowwakeup(so); | ||||
Not Done Inline ActionsIt looks like there is an accidental whitespace change here. jtl: It looks like there is an accidental whitespace change here. | |||||
Not Done Inline Actionsack rrs: ack | |||||
if (sbavail(&so->so_snd)) | if (sbavail(&so->so_snd)) | ||||
(void) tcp_output(tp); | (void) tp->t_fb->tfb_tcp_output(tp); | ||||
goto check_delack; | goto check_delack; | ||||
} | } | ||||
} else if (th->th_ack == tp->snd_una && | } else if (th->th_ack == tp->snd_una && | ||||
Context not available. | |||||
tp->t_flags |= TF_DELACK; | tp->t_flags |= TF_DELACK; | ||||
} else { | } else { | ||||
tp->t_flags |= TF_ACKNOW; | tp->t_flags |= TF_ACKNOW; | ||||
tcp_output(tp); | tp->t_fb->tfb_tcp_output(tp); | ||||
} | } | ||||
goto check_delack; | goto check_delack; | ||||
} | } | ||||
Context not available. | |||||
} | } | ||||
} else | } else | ||||
tp->snd_cwnd += tp->t_maxseg; | tp->snd_cwnd += tp->t_maxseg; | ||||
(void) tcp_output(tp); | (void) tp->t_fb->tfb_tcp_output(tp); | ||||
goto drop; | goto drop; | ||||
} else if (tp->t_dupacks == tcprexmtthresh) { | } else if (tp->t_dupacks == tcprexmtthresh) { | ||||
tcp_seq onxt = tp->snd_nxt; | tcp_seq onxt = tp->snd_nxt; | ||||
Context not available. | |||||
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) tcp_output(tp); | (void) tp->t_fb->tfb_tcp_output(tp); | ||||
goto drop; | goto drop; | ||||
} | } | ||||
tp->snd_nxt = th->th_ack; | tp->snd_nxt = th->th_ack; | ||||
tp->snd_cwnd = tp->t_maxseg; | tp->snd_cwnd = tp->t_maxseg; | ||||
(void) tcp_output(tp); | (void) tp->t_fb->tfb_tcp_output(tp); | ||||
KASSERT(tp->snd_limited <= 2, | KASSERT(tp->snd_limited <= 2, | ||||
("%s: tp->snd_limited too big", | ("%s: tp->snd_limited too big", | ||||
__func__)); | __func__)); | ||||
Context not available. | |||||
(tp->snd_nxt - tp->snd_una); | (tp->snd_nxt - tp->snd_una); | ||||
SOCKBUF_UNLOCK(&so->so_snd); | SOCKBUF_UNLOCK(&so->so_snd); | ||||
if (avail > 0) | if (avail > 0) | ||||
(void) tcp_output(tp); | (void) tp->t_fb->tfb_tcp_output(tp); | ||||
sent = tp->snd_max - oldsndmax; | sent = tp->snd_max - oldsndmax; | ||||
if (sent > tp->t_maxseg) { | if (sent > tp->t_maxseg) { | ||||
KASSERT((tp->t_dupacks == 2 && | KASSERT((tp->t_dupacks == 2 && | ||||
Context not available. | |||||
* Return any desired output. | * Return any desired output. | ||||
*/ | */ | ||||
if (needoutput || (tp->t_flags & TF_ACKNOW)) | if (needoutput || (tp->t_flags & TF_ACKNOW)) | ||||
(void) tcp_output(tp); | (void) tp->t_fb->tfb_tcp_output(tp); | ||||
check_delack: | check_delack: | ||||
KASSERT(ti_locked == TI_UNLOCKED, ("%s: check_delack ti_locked %d", | KASSERT(ti_locked == TI_UNLOCKED, ("%s: check_delack ti_locked %d", | ||||
Context not available. | |||||
ti_locked = TI_UNLOCKED; | ti_locked = TI_UNLOCKED; | ||||
tp->t_flags |= TF_ACKNOW; | tp->t_flags |= TF_ACKNOW; | ||||
(void) tcp_output(tp); | (void) tp->t_fb->tfb_tcp_output(tp); | ||||
INP_WUNLOCK(tp->t_inpcb); | INP_WUNLOCK(tp->t_inpcb); | ||||
m_freem(m); | m_freem(m); | ||||
return; | return; | ||||
Context not available. | |||||
* The mbuf must still include the original packet header. | * The mbuf must still include the original packet header. | ||||
* tp may be NULL. | * tp may be NULL. | ||||
*/ | */ | ||||
static void | void | ||||
tcp_dropwithreset(struct mbuf *m, struct tcphdr *th, struct tcpcb *tp, | tcp_dropwithreset(struct mbuf *m, struct tcphdr *th, struct tcpcb *tp, | ||||
int tlen, int rstreason) | int tlen, int rstreason) | ||||
{ | { | ||||
Context not available. | |||||
/* | /* | ||||
* Parse TCP options and place in tcpopt. | * Parse TCP options and place in tcpopt. | ||||
*/ | */ | ||||
static void | void | ||||
tcp_dooptions(struct tcpopt *to, u_char *cp, int cnt, int flags) | tcp_dooptions(struct tcpopt *to, u_char *cp, int cnt, int flags) | ||||
{ | { | ||||
int opt, optlen; | int opt, optlen; | ||||
Context not available. | |||||
* It is still reflected in the segment length for | * It is still reflected in the segment length for | ||||
* sequencing purposes. | * sequencing purposes. | ||||
*/ | */ | ||||
static void | void | ||||
tcp_pulloutofband(struct socket *so, struct tcphdr *th, struct mbuf *m, | tcp_pulloutofband(struct socket *so, struct tcphdr *th, struct mbuf *m, | ||||
int off) | int off) | ||||
{ | { | ||||
Context not available. | |||||
* Collect new round-trip time estimate | * Collect new round-trip time estimate | ||||
* and update averages and current timeout. | * and update averages and current timeout. | ||||
*/ | */ | ||||
static void | void | ||||
tcp_xmit_timer(struct tcpcb *tp, int rtt) | tcp_xmit_timer(struct tcpcb *tp, int rtt) | ||||
{ | { | ||||
int delta; | int delta; | ||||
Context not available. | |||||
* By setting snd_nxt to ti_ack, this forces retransmission timer to | * By setting snd_nxt to ti_ack, this forces retransmission timer to | ||||
* be started again. | * be started again. | ||||
*/ | */ | ||||
static void | void | ||||
tcp_newreno_partial_ack(struct tcpcb *tp, struct tcphdr *th) | tcp_newreno_partial_ack(struct tcpcb *tp, struct tcphdr *th) | ||||
{ | { | ||||
tcp_seq onxt = tp->snd_nxt; | tcp_seq onxt = tp->snd_nxt; | ||||
Context not available. | |||||
*/ | */ | ||||
tp->snd_cwnd = tp->t_maxseg + BYTES_THIS_ACK(tp, th); | tp->snd_cwnd = tp->t_maxseg + BYTES_THIS_ACK(tp, th); | ||||
tp->t_flags |= TF_ACKNOW; | tp->t_flags |= TF_ACKNOW; | ||||
(void) tcp_output(tp); | (void) tp->t_fb->tfb_tcp_output(tp); | ||||
tp->snd_cwnd = ocwnd; | tp->snd_cwnd = ocwnd; | ||||
if (SEQ_GT(onxt, tp->snd_nxt)) | if (SEQ_GT(onxt, tp->snd_nxt)) | ||||
tp->snd_nxt = onxt; | tp->snd_nxt = onxt; | ||||
Context not available. |
This is already defined in tcp_var.h. Why add a non-static declaration to tcp_input.c?