Changeset View
Changeset View
Standalone View
Standalone View
head/sys/netinet/tcp_reass.c
Show First 20 Lines • Show All 573 Lines • ▼ Show 20 Lines | |||||
#endif | #endif | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Will it fit? | * Will it fit? | ||||
*/ | */ | ||||
lenofoh = tcp_reass_overhead_of_chain(m, &mlast); | lenofoh = tcp_reass_overhead_of_chain(m, &mlast); | ||||
sb = &tp->t_inpcb->inp_socket->so_rcv; | sb = &tp->t_inpcb->inp_socket->so_rcv; | ||||
if ((sb->sb_mbcnt + tp->t_segqmbuflen + lenofoh) > sb->sb_mbmax) { | if ((th->th_seq != tp->rcv_nxt || !TCPS_HAVEESTABLISHED(tp->t_state)) && | ||||
(sb->sb_mbcnt + tp->t_segqmbuflen + lenofoh) > sb->sb_mbmax) { | |||||
/* No room */ | /* No room */ | ||||
TCPSTAT_INC(tcps_rcvreassfull); | TCPSTAT_INC(tcps_rcvreassfull); | ||||
#ifdef TCP_REASS_COUNTERS | #ifdef TCP_REASS_COUNTERS | ||||
counter_u64_add(reass_nospace, 1); | counter_u64_add(reass_nospace, 1); | ||||
#endif | #endif | ||||
#ifdef TCP_REASS_LOGGING | #ifdef TCP_REASS_LOGGING | ||||
tcp_log_reassm(tp, NULL, NULL, th->th_seq, lenofoh, TCP_R_LOG_LIMIT_REACHED, 0); | tcp_log_reassm(tp, NULL, NULL, th->th_seq, lenofoh, TCP_R_LOG_LIMIT_REACHED, 0); | ||||
#endif | #endif | ||||
if ((s = tcp_log_addrs(&tp->t_inpcb->inp_inc, th, NULL, NULL))) { | |||||
log(LOG_DEBUG, "%s; %s: mbuf count limit reached, " | |||||
"segment dropped\n", s, __func__); | |||||
free(s, M_TCPLOG); | |||||
} | |||||
m_freem(m); | m_freem(m); | ||||
*tlenp = 0; | *tlenp = 0; | ||||
#ifdef TCP_REASS_LOGGING | #ifdef TCP_REASS_LOGGING | ||||
tcp_reass_log_dump(tp); | tcp_reass_log_dump(tp); | ||||
#endif | #endif | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 332 Lines • ▼ Show 20 Lines | #endif | ||||
* can tolerate stale information here. | * can tolerate stale information here. | ||||
* | * | ||||
* XXXLAS: Using sbspace(so->so_rcv) instead of so->so_rcv.sb_hiwat | * XXXLAS: Using sbspace(so->so_rcv) instead of so->so_rcv.sb_hiwat | ||||
* should work but causes packets to be dropped when they shouldn't. | * should work but causes packets to be dropped when they shouldn't. | ||||
* Investigate why and re-evaluate the below limit after the behaviour | * Investigate why and re-evaluate the below limit after the behaviour | ||||
* is understood. | * is understood. | ||||
*/ | */ | ||||
new_entry: | new_entry: | ||||
if (th->th_seq == tp->rcv_nxt && TCPS_HAVEESTABLISHED(tp->t_state)) { | |||||
tp->rcv_nxt += *tlenp; | |||||
flags = th->th_flags & TH_FIN; | |||||
TCPSTAT_INC(tcps_rcvoopack); | |||||
TCPSTAT_ADD(tcps_rcvoobyte, *tlenp); | |||||
SOCKBUF_LOCK(&so->so_rcv); | |||||
if (so->so_rcv.sb_state & SBS_CANTRCVMORE) { | |||||
m_freem(m); | |||||
} else { | |||||
sbappendstream_locked(&so->so_rcv, m, 0); | |||||
} | |||||
sorwakeup_locked(so); | |||||
return (flags); | |||||
} | |||||
if (tcp_new_limits) { | if (tcp_new_limits) { | ||||
if ((tp->t_segqlen > tcp_reass_queue_guard) && | if ((tp->t_segqlen > tcp_reass_queue_guard) && | ||||
(*tlenp < MSIZE)) { | (*tlenp < MSIZE)) { | ||||
/* | /* | ||||
* This is really a lie, we are not full but | * This is really a lie, we are not full but | ||||
* are getting a segment that is above | * are getting a segment that is above | ||||
* guard threshold. If it is and its below | * guard threshold. If it is and its below | ||||
* a mbuf size (256) we drop it if it | * a mbuf size (256) we drop it if it | ||||
* can't fill in some place. | * can't fill in some place. | ||||
*/ | */ | ||||
TCPSTAT_INC(tcps_rcvreassfull); | TCPSTAT_INC(tcps_rcvreassfull); | ||||
*tlenp = 0; | *tlenp = 0; | ||||
if ((s = tcp_log_addrs(&tp->t_inpcb->inp_inc, th, NULL, NULL))) { | if ((s = tcp_log_addrs(&tp->t_inpcb->inp_inc, th, NULL, NULL))) { | ||||
log(LOG_DEBUG, "%s; %s: queue limit reached, " | log(LOG_DEBUG, "%s; %s: queue limit reached, " | ||||
"segment dropped\n", s, __func__); | "segment dropped\n", s, __func__); | ||||
free(s, M_TCPLOG); | free(s, M_TCPLOG); | ||||
} | } | ||||
m_freem(m); | m_freem(m); | ||||
#ifdef TCP_REASS_LOGGING | #ifdef TCP_REASS_LOGGING | ||||
tcp_reass_log_dump(tp); | tcp_reass_log_dump(tp); | ||||
#endif | #endif | ||||
return (0); | return (0); | ||||
} | } | ||||
} else { | } else { | ||||
if (tp->t_segqlen >= min((so->so_rcv.sb_hiwat / tp->t_maxseg) + 1, | |||||
if ((th->th_seq != tp->rcv_nxt || !TCPS_HAVEESTABLISHED(tp->t_state)) && | |||||
tp->t_segqlen >= min((so->so_rcv.sb_hiwat / tp->t_maxseg) + 1, | |||||
tcp_reass_maxqueuelen)) { | tcp_reass_maxqueuelen)) { | ||||
TCPSTAT_INC(tcps_rcvreassfull); | TCPSTAT_INC(tcps_rcvreassfull); | ||||
*tlenp = 0; | *tlenp = 0; | ||||
if ((s = tcp_log_addrs(&tp->t_inpcb->inp_inc, th, NULL, NULL))) { | if ((s = tcp_log_addrs(&tp->t_inpcb->inp_inc, th, NULL, NULL))) { | ||||
log(LOG_DEBUG, "%s; %s: queue limit reached, " | log(LOG_DEBUG, "%s; %s: queue limit reached, " | ||||
"segment dropped\n", s, __func__); | "segment dropped\n", s, __func__); | ||||
free(s, M_TCPLOG); | free(s, M_TCPLOG); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 103 Lines • Show Last 20 Lines |