PERFORCE change 134972 for review
Andre Oppermann
andre at FreeBSD.org
Thu Feb 7 01:29:25 PST 2008
http://perforce.freebsd.org/chv.cgi?CH=134972
Change 134972 by andre at andre_flirtbox on 2008/02/07 09:28:38
Copy TCP header information into local variables as the mbuf portion
where it resides is technically gone. When using m_collapse() will
be truely gone and accessing it will give a page fault.
Affected files ...
.. //depot/projects/tcp_reass/netinet/tcp_reass.c#17 edit
Differences ...
==== //depot/projects/tcp_reass/netinet/tcp_reass.c#17 (text+ko) ====
@@ -175,6 +175,7 @@
struct socket *so = tp->t_inpcb->inp_socket;
struct mbuf *n;
int i, thflags = 0, mcnt;
+ tcp_seq th_seq;
struct trq tqes;
INP_LOCK_ASSERT(tp->t_inpcb);
@@ -192,7 +193,14 @@
return (0);
goto present;
}
+
+ /*
+ * Store TCP header information in local variables as
+ * we may lose access to it after mbuf compacting.
+ */
thflags = (th->th_flags & TH_FIN);
+ th_seq = th->th_seq;
+ th = NULL; /* Prevent further use. */
/* Check if it is really neccessary to do all the work. */
if (!tcp_reass_enabled && TAILQ_EMPTY(&tp->t_trq)) {
@@ -209,9 +217,9 @@
KASSERT(*tlenp > 0,
("%s: segment doesn't contain any data", __func__));
- KASSERT(SEQ_LEQ(tp->rcv_nxt, th->th_seq),
+ KASSERT(SEQ_LEQ(tp->rcv_nxt, th_seq),
("%s: sequence number below rcv_nxt", __func__));
- KASSERT(!(tp->rcv_nxt == th->th_seq) || !(TAILQ_EMPTY(&tp->t_trq)),
+ KASSERT(!(tp->rcv_nxt == th_seq) || !(TAILQ_EMPTY(&tp->t_trq)),
("%s: got missing segment but queue is empty", __func__));
#ifdef INVARIANTS
@@ -253,8 +261,8 @@
* vs. actual real data with 2k clusters and 1500 byte packets.
* This shouldn't be too much of a problem though.
*/
- if (th->th_seq != tp->rcv_nxt &&
- tp->t_trqmcnt > sbspace(&so->so_rcv)) {
+ if (th_seq != tp->rcv_nxt &&
+ tp->t_trqmcnt > (sbspace(&so->so_rcv) / 4 * 5)) {
tcpstat.tcps_reass_overflow++;
tcpstat.tcps_rcvmemdrop++;
m_freem(m);
@@ -281,9 +289,9 @@
/* Check if we've already received FIN; we can't accept data beyond it. */
tqe = TAILQ_LAST(&tp->t_trq, trq_head);
- if (tqe && (tqe->trq_thflags & TH_FIN) && SEQ_LEQ(tqe->trq_seq, th->th_seq)) {
+ if (tqe && (tqe->trq_thflags & TH_FIN) && SEQ_LEQ(tqe->trq_seq, th_seq)) {
/* Properly count retransmitted perfect matching FIN. */
- if (tqe->trq_seq == th->th_seq && *tlenp > 0)
+ if (tqe->trq_seq == th_seq && *tlenp > 0)
tcpstat.tcps_rcvoopack++;
else {
tcpstat.tcps_rcvpackafterfin++;
@@ -296,7 +304,7 @@
/* Check if this segments FIN is before the end of the last block. */
if (tqe && (thflags & TH_FIN) &&
- SEQ_GT(tqe->trq_seq + tqe->trq_len, th->th_seq + *tlenp)) {
+ SEQ_GT(tqe->trq_seq + tqe->trq_len, th_seq + *tlenp)) {
/* TCP statistics. */
tcpstat.tcps_rcvpackafterfin++;
tcpstat.tcps_rcvbyteafterfin += *tlenp;
@@ -306,7 +314,7 @@
}
/* Check if this segment directly attaches to the end. */
- if (tqe && tqe->trq_seq + tqe->trq_len == th->th_seq) {
+ if (tqe && tqe->trq_seq + tqe->trq_len == th_seq) {
tqe->trq_len += *tlenp;
tqe->trq_mcnt += mcnt;
tp->t_trqmcnt += mcnt;
@@ -326,7 +334,7 @@
}
/* Check if beyond last block. */
- if (tqe && SEQ_LT(tqe->trq_seq + tqe->trq_len, th->th_seq))
+ if (tqe && SEQ_LT(tqe->trq_seq + tqe->trq_len, th_seq))
goto insert;
/* Check if this is the first segment. */
@@ -334,14 +342,14 @@
goto insert;
/* Check if this is the missing segment. */
- if (tp->rcv_nxt == th->th_seq) {
+ if (tp->rcv_nxt == th_seq) {
tqe = TAILQ_FIRST(&tp->t_trq);
- KASSERT(SEQ_GT(tqe->trq_seq, th->th_seq),
+ KASSERT(SEQ_GT(tqe->trq_seq, th_seq),
("%s: first block starts below missing segment", __func__));
/* Check if segment prepends first block. */
- if (SEQ_LEQ(tqe->trq_seq, th->th_seq + *tlenp)) {
+ if (SEQ_LEQ(tqe->trq_seq, th_seq + *tlenp)) {
/* Trim tail of segment. */
- if ((i = SEQ_DELTA(tqe->trq_seq, th->th_seq + *tlenp))) {
+ if ((i = SEQ_DELTA(tqe->trq_seq, th_seq + *tlenp))) {
m_adj(m, -i);
*tlenp -= i;
/* TCP statistics. */
@@ -356,7 +364,7 @@
tqe->trq_mcnt += mcnt;
tp->t_trqmcnt += mcnt;
tcp_reass_mcnt += mcnt;
- tqe->trq_seq = th->th_seq;
+ tqe->trq_seq = th_seq;
n = m_last(m);
n->m_next = tqe->trq_m;
tqe->trq_m = m;
@@ -372,15 +380,15 @@
/* See where it fits. */
TAILQ_FOREACH_SAFE(tqe, &tp->t_trq, trq_q, tqen) {
/* Segment is after this blocks coverage. */
- if (SEQ_LT(tqe->trq_seq + tqe->trq_len, th->th_seq))
+ if (SEQ_LT(tqe->trq_seq + tqe->trq_len, th_seq))
continue;
/* Segment is after the previous one but before this one. */
- if (SEQ_GT(tqe->trq_seq, th->th_seq + *tlenp))
+ if (SEQ_GT(tqe->trq_seq, th_seq + *tlenp))
break; /* Insert as new block. */
/* Segment is already fully covered. */
- if (SEQ_LEQ(tqe->trq_seq, th->th_seq) &&
- SEQ_GEQ(tqe->trq_seq + tqe->trq_len, th->th_seq + *tlenp)) {
+ if (SEQ_LEQ(tqe->trq_seq, th_seq) &&
+ SEQ_GEQ(tqe->trq_seq + tqe->trq_len, th_seq + *tlenp)) {
tcpstat.tcps_rcvduppack++;
tcpstat.tcps_rcvdupbyte += *tlenp;
tcpstat.tcps_reass_covered++;
@@ -396,8 +404,8 @@
}
/* Segment covers and extends on both ends. */
- if (SEQ_GT(tqe->trq_seq, th->th_seq) &&
- SEQ_LT(tqe->trq_seq + tqe->trq_len, th->th_seq + *tlenp)) {
+ if (SEQ_GT(tqe->trq_seq, th_seq) &&
+ SEQ_LT(tqe->trq_seq + tqe->trq_len, th_seq + *tlenp)) {
/* Replace block content. */
tp->t_trqmcnt -= tqe->trq_mcnt;
m_freem(tqe->trq_m);
@@ -405,7 +413,7 @@
tqe->trq_mcnt = mcnt;
tp->t_trqmcnt += mcnt;
tcp_reass_mcnt += mcnt;
- tqe->trq_seq = th->th_seq;
+ tqe->trq_seq = th_seq;
tqe->trq_m = m;
tqe->trq_ml = m_last(m);
tqe->trq_thflags |= thflags;
@@ -422,13 +430,13 @@
}
/* Segment prepends to this block. */
- if (SEQ_GT(tqe->trq_seq, th->th_seq) &&
- SEQ_LEQ(tqe->trq_seq, th->th_seq + *tlenp) &&
- SEQ_GEQ(tqe->trq_seq + tqe->trq_len, th->th_seq + *tlenp)) {
+ if (SEQ_GT(tqe->trq_seq, th_seq) &&
+ SEQ_LEQ(tqe->trq_seq, th_seq + *tlenp) &&
+ SEQ_GEQ(tqe->trq_seq + tqe->trq_len, th_seq + *tlenp)) {
KASSERT(!(thflags & TH_FIN),
("%s: new segment with FIN can't prepend", __func__));
/* Trim tail of segment. */
- if ((i = SEQ_DELTA(tqe->trq_seq, th->th_seq + *tlenp))) {
+ if ((i = SEQ_DELTA(tqe->trq_seq, th_seq + *tlenp))) {
m_adj(m, -i);
*tlenp -= i;
/* TCP statistics. */
@@ -443,7 +451,7 @@
tqe->trq_mcnt += mcnt;
tp->t_trqmcnt += mcnt;
tcp_reass_mcnt += mcnt;
- tqe->trq_seq = th->th_seq;
+ tqe->trq_seq = th_seq;
n = m_last(m);
n->m_next = tqe->trq_m;
tqe->trq_m = m;
@@ -456,11 +464,11 @@
}
/* Segment appends to this block. */
- if (SEQ_LT(tqe->trq_seq + tqe->trq_len, th->th_seq + *tlenp) &&
- SEQ_LEQ(tqe->trq_seq, th->th_seq) &&
- SEQ_GEQ(tqe->trq_seq + tqe->trq_len, th->th_seq)) {
+ if (SEQ_LT(tqe->trq_seq + tqe->trq_len, th_seq + *tlenp) &&
+ SEQ_LEQ(tqe->trq_seq, th_seq) &&
+ SEQ_GEQ(tqe->trq_seq + tqe->trq_len, th_seq)) {
/* Trim head of segment. */
- if ((i = SEQ_DELTA(tqe->trq_seq + tqe->trq_len, th->th_seq))) {
+ if ((i = SEQ_DELTA(tqe->trq_seq + tqe->trq_len, th_seq))) {
m_adj(m, i);
*tlenp -= i;
/* TCP Statistics. */
@@ -489,7 +497,7 @@
insert:
/* Prepare to insert into block queue. */
- if (tp->rcv_nxt == th->th_seq) {
+ if (tp->rcv_nxt == th_seq) {
/*
* Use temporary struct trq on the stack for missing
* segment to prevent blocking of all reassembly queues
@@ -507,7 +515,7 @@
tcpstat.tcps_reass_blocks++;
}
tcp_reass_qsize++;
- tqen->trq_seq = th->th_seq;
+ tqen->trq_seq = th_seq;
tqen->trq_len = *tlenp;
tqen->trq_mcnt = mcnt;
tp->t_trqmcnt += mcnt;
@@ -517,7 +525,7 @@
tqen->trq_thflags |= thflags;
/* Where to insert. */
- if (tqe != NULL && SEQ_LT(tqe->trq_seq + tqe->trq_len, th->th_seq))
+ if (tqe != NULL && SEQ_LT(tqe->trq_seq + tqe->trq_len, th_seq))
TAILQ_INSERT_AFTER(&tp->t_trq, tqe, tqen, trq_q);
else if (tqe != NULL)
TAILQ_INSERT_BEFORE(tqe, tqen, trq_q);
@@ -535,7 +543,7 @@
LIST_INSERT_HEAD(&tp->t_trq_sack, tqen, trq_s);
/* Missing segment? */
- if (tp->rcv_nxt != th->th_seq)
+ if (tp->rcv_nxt != th_seq)
return (0);
present:
/*
More information about the p4-projects
mailing list