Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/tcp_reass.c
Show First 20 Lines • Show All 536 Lines • ▼ Show 20 Lines | tcp_reass(struct tcpcb *tp, struct tcphdr *th, tcp_seq *seq_start, | ||||
int flags, i, lenofoh; | int flags, i, lenofoh; | ||||
INP_WLOCK_ASSERT(tp->t_inpcb); | INP_WLOCK_ASSERT(tp->t_inpcb); | ||||
/* | /* | ||||
* XXX: tcp_reass() is rather inefficient with its data structures | * XXX: tcp_reass() is rather inefficient with its data structures | ||||
* and should be rewritten (see NetBSD for optimizations). | * and should be rewritten (see NetBSD for optimizations). | ||||
*/ | */ | ||||
KASSERT(th == NULL || (seq_start != NULL && tlenp != NULL), | |||||
("tcp_reass called with illegal parameter combination " | |||||
"(tp=%p, th=%p, seq_start=%p, tlenp=%p, m=%p)", | |||||
tp, th, seq_start, tlenp, m)); | |||||
/* | /* | ||||
bz: Please add %p and others to the printf so people will be able to have pointers to the tp, th, .. | |||||
Done Inline ActionsGood suggestion.Diff updated. tuexen: Good suggestion.Diff updated. | |||||
* Call with th==NULL after become established to | * Call with th==NULL after become established to | ||||
* force pre-ESTABLISHED data up to user socket. | * force pre-ESTABLISHED data up to user socket. | ||||
*/ | */ | ||||
if (th == NULL) | if (th == NULL) | ||||
goto present; | goto present; | ||||
KASSERT(SEQ_GEQ(th->th_seq, tp->rcv_nxt), | KASSERT(SEQ_GEQ(th->th_seq, tp->rcv_nxt), | ||||
("Attempt to add old entry to reassembly queue (th=%p, tp=%p)", | ("Attempt to add old entry to reassembly queue (th=%p, tp=%p)", | ||||
th, tp)); | th, tp)); | ||||
▲ Show 20 Lines • Show All 503 Lines • ▼ Show 20 Lines | do { | ||||
flags = q->tqe_flags & TH_FIN; | flags = q->tqe_flags & TH_FIN; | ||||
nq = TAILQ_NEXT(q, tqe_q); | nq = TAILQ_NEXT(q, tqe_q); | ||||
TAILQ_REMOVE(&tp->t_segq, q, tqe_q); | TAILQ_REMOVE(&tp->t_segq, q, tqe_q); | ||||
if (so->so_rcv.sb_state & SBS_CANTRCVMORE) { | if (so->so_rcv.sb_state & SBS_CANTRCVMORE) { | ||||
m_freem(q->tqe_m); | m_freem(q->tqe_m); | ||||
} else { | } else { | ||||
#ifdef TCP_REASS_LOGGING | #ifdef TCP_REASS_LOGGING | ||||
tcp_reass_log_new_in(tp, q->tqe_start, q->tqe_len, q->tqe_m, TCP_R_LOG_READ, q); | tcp_reass_log_new_in(tp, q->tqe_start, q->tqe_len, q->tqe_m, TCP_R_LOG_READ, q); | ||||
if (th != NULL) { | |||||
tcp_log_reassm(tp, q, NULL, th->th_seq, *tlenp, TCP_R_LOG_READ, 1); | tcp_log_reassm(tp, q, NULL, th->th_seq, *tlenp, TCP_R_LOG_READ, 1); | ||||
} else { | |||||
tcp_log_reassm(tp, q, NULL, 0, 0, TCP_R_LOG_READ, 1); | |||||
} | |||||
#endif | #endif | ||||
sbappendstream_locked(&so->so_rcv, q->tqe_m, 0); | sbappendstream_locked(&so->so_rcv, q->tqe_m, 0); | ||||
} | } | ||||
#ifdef TCP_REASS_LOGGING | #ifdef TCP_REASS_LOGGING | ||||
if (th != NULL) { | |||||
tcp_log_reassm(tp, q, NULL, th->th_seq, *tlenp, TCP_R_LOG_READ, 2); | tcp_log_reassm(tp, q, NULL, th->th_seq, *tlenp, TCP_R_LOG_READ, 2); | ||||
} else { | |||||
tcp_log_reassm(tp, q, NULL, 0, 0, TCP_R_LOG_READ, 2); | |||||
} | |||||
#endif | #endif | ||||
KASSERT(tp->t_segqmbuflen >= q->tqe_mbuf_cnt, | KASSERT(tp->t_segqmbuflen >= q->tqe_mbuf_cnt, | ||||
("tp:%p seg queue goes negative", tp)); | ("tp:%p seg queue goes negative", tp)); | ||||
tp->t_segqmbuflen -= q->tqe_mbuf_cnt; | tp->t_segqmbuflen -= q->tqe_mbuf_cnt; | ||||
uma_zfree(tcp_reass_zone, q); | uma_zfree(tcp_reass_zone, q); | ||||
tp->t_segqlen--; | tp->t_segqlen--; | ||||
q = nq; | q = nq; | ||||
} while (q && q->tqe_start == tp->rcv_nxt); | } while (q && q->tqe_start == tp->rcv_nxt); | ||||
if (TAILQ_EMPTY(&tp->t_segq) && | if (TAILQ_EMPTY(&tp->t_segq) && | ||||
(tp->t_segqmbuflen != 0)) { | (tp->t_segqmbuflen != 0)) { | ||||
#ifdef INVARIANTS | #ifdef INVARIANTS | ||||
panic("tp:%p segq:%p len:%d queue empty", | panic("tp:%p segq:%p len:%d queue empty", | ||||
tp, &tp->t_segq, tp->t_segqmbuflen); | tp, &tp->t_segq, tp->t_segqmbuflen); | ||||
#else | #else | ||||
#ifdef TCP_REASS_LOGGING | #ifdef TCP_REASS_LOGGING | ||||
if (th != NULL) { | |||||
tcp_log_reassm(tp, NULL, NULL, th->th_seq, *tlenp, TCP_R_LOG_ZERO, 0); | tcp_log_reassm(tp, NULL, NULL, th->th_seq, *tlenp, TCP_R_LOG_ZERO, 0); | ||||
} else { | |||||
tcp_log_reassm(tp, NULL, NULL, 0, 0, TCP_R_LOG_ZERO, 0); | |||||
} | |||||
#endif | #endif | ||||
tp->t_segqmbuflen = 0; | tp->t_segqmbuflen = 0; | ||||
#endif | #endif | ||||
} | } | ||||
#ifdef TCP_REASS_LOGGING | #ifdef TCP_REASS_LOGGING | ||||
tcp_reass_log_dump(tp); | tcp_reass_log_dump(tp); | ||||
#endif | #endif | ||||
sorwakeup_locked(so); | sorwakeup_locked(so); | ||||
return (flags); | return (flags); | ||||
} | } |
Please add %p and others to the printf so people will be able to have pointers to the tp, th, ..., m for debugging in case this fires.
Will also help them to find out which illegal combination it was.