Page MenuHomeFreeBSD

D35446.diff
No OneTemporary

D35446.diff

Index: sys/netinet/tcp_output.c
===================================================================
--- sys/netinet/tcp_output.c
+++ sys/netinet/tcp_output.c
@@ -60,6 +60,7 @@
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/sysctl.h>
+#include <sys/syslog.h>
#include <sys/stats.h>
#include <net/if.h>
@@ -200,6 +201,7 @@
{
struct socket *so = tp->t_inpcb->inp_socket;
int32_t len;
+ tcp_seq top;
uint32_t recwin, sendwin;
uint16_t flags;
int off, error = 0; /* Keep compiler happy */
@@ -1569,6 +1571,14 @@
tp->snd_nxt += len;
if (SEQ_GT(tp->snd_nxt, tp->snd_max)) {
tp->snd_max = tp->snd_nxt;
+ top = tp->snd_una + sbused(&so->so_snd);
+ KASSERT(SEQ_LEQ(tp->snd_max, top + 1),
+ ("%s: snd_max beyond so_snd", __func__));
+ if (SEQ_GT(tp->snd_max, top + 1)) {
+ log(LOG_CRIT, "%s#%d: snd_max %u > so_snd+1 %u adjusting.\n",
+ __func__, __LINE__, tp->snd_max, top + 1);
+ tp->snd_max = top + 1;
+ }
/*
* Time this transmission if not a retransmission and
* not currently timing anything.
@@ -1644,8 +1654,17 @@
++xlen;
tp->t_flags |= TF_SENTFIN;
}
- if (SEQ_GT(tp->snd_nxt + xlen, tp->snd_max))
+ if (SEQ_GT(tp->snd_nxt + xlen, tp->snd_max)) {
tp->snd_max = tp->snd_nxt + xlen;
+ top = tp->snd_una + sbused(&so->so_snd);
+ KASSERT(SEQ_LEQ(tp->snd_max, top + 1),
+ ("%s: snd_max beyond so_snd", __func__));
+ if (SEQ_GT(tp->snd_max, top + 1)) {
+ log(LOG_CRIT, "%s#%d: snd_max %u > so_snd+1 %u adjusting.\n",
+ __func__, __LINE__, tp->snd_max, top + 1);
+ tp->snd_max = top + 1;
+ }
+ }
}
if ((error == 0) &&
(TCPS_HAVEESTABLISHED(tp->t_state) &&
@@ -1681,8 +1700,14 @@
tp->sackhint.sack_bytes_rexmit -= len;
KASSERT(tp->sackhint.sack_bytes_rexmit >= 0,
("sackhint bytes rtx >= 0"));
- } else
+ } else {
tp->snd_nxt -= len;
+ if (flags & TH_FIN) {
+ log(LOG_CRIT, "%s#%d: rewinding FIN bit after TCP send error\n",
+ __func__, __LINE__);
+ tp->snd_nxt--;
+ }
+ }
}
SOCKBUF_UNLOCK_ASSERT(&so->so_snd); /* Check gotos. */
switch (error) {
Index: sys/netinet/tcp_sack.c
===================================================================
--- sys/netinet/tcp_sack.c
+++ sys/netinet/tcp_sack.c
@@ -853,7 +853,9 @@
tcp_sack_partialack(struct tcpcb *tp, struct tcphdr *th)
{
int num_segs = 1;
+ tcp_seq top;
u_int maxseg = tcp_maxseg(tp);
+ struct socket *so = tp->t_inpcb->inp_socket;
INP_WLOCK_ASSERT(tp->t_inpcb);
tcp_timer_activate(tp, TT_REXMT, 0);
@@ -898,8 +900,19 @@
highdata--;
if (th->th_ack != highdata) {
tp->snd_fack = th->th_ack;
- (void)tcp_sackhole_insert(tp, SEQ_MAX(th->th_ack,
- highdata - maxseg), highdata, NULL);
+ top = tp->snd_una + sbused(&so->so_snd);
+ KASSERT(SEQ_LEQ(highdata, top),
+ ("%s: rescue.end > so_snd, NEEDFIN:%d SENTFIN:%d\n",
+ __func__, (tp->t_flags & TF_NEEDFIN) != 0,
+ (tp->t_flags & TF_SENTFIN) != 0));
+ if (SEQ_GT(highdata, top)) {
+ log(LOG_CRIT,"%s#%d: rescue (%u-%u) > so_snd %u skipping.\n",
+ __func__, __LINE__,
+ SEQ_MAX(th->th_ack, highdata - maxseg),
+ highdata, top);
+ } else
+ (void)tcp_sackhole_insert(tp, SEQ_MAX(th->th_ack,
+ highdata - maxseg), highdata, NULL);
}
}
(void) tcp_output(tp);
@@ -952,6 +965,8 @@
tcp_sack_output(struct tcpcb *tp, int *sack_bytes_rexmt)
{
struct sackhole *hole = NULL;
+ struct socket *so = tp->t_inpcb->inp_socket;
+ tcp_seq top = tp->snd_una + sbused(&so->so_snd);
INP_WLOCK_ASSERT(tp->t_inpcb);
*sack_bytes_rexmt = tp->sackhint.sack_bytes_rexmit;
@@ -970,18 +985,16 @@
}
}
KASSERT(SEQ_LT(hole->start, hole->end), ("%s: hole.start >= hole.end", __func__));
- if (!(V_tcp_do_newsack)) {
- KASSERT(SEQ_LT(hole->start, tp->snd_fack), ("%s: hole.start >= snd.fack", __func__));
- KASSERT(SEQ_LT(hole->end, tp->snd_fack), ("%s: hole.end >= snd.fack", __func__));
- KASSERT(SEQ_LT(hole->rxmit, tp->snd_fack), ("%s: hole.rxmit >= snd.fack", __func__));
- if (SEQ_GEQ(hole->start, hole->end) ||
- SEQ_GEQ(hole->start, tp->snd_fack) ||
- SEQ_GEQ(hole->end, tp->snd_fack) ||
- SEQ_GEQ(hole->rxmit, tp->snd_fack)) {
- log(LOG_CRIT,"tcp: invalid SACK hole (%u-%u,%u) vs fwd ack %u, ignoring.\n",
- hole->start, hole->end, hole->rxmit, tp->snd_fack);
- return (NULL);
- }
+ KASSERT(SEQ_LEQ(hole->start, top), ("%s: hole.start >= so_snd", __func__));
+ KASSERT(SEQ_LEQ(hole->end, top), ("%s: hole.end >= so_snd", __func__));
+ KASSERT(SEQ_LEQ(hole->rxmit, top), ("%s: hole.rxmit >= so_snd", __func__));
+ if (SEQ_GEQ(hole->start, hole->end) ||
+ SEQ_GT(hole->start, top) ||
+ SEQ_GT(hole->end, top) ||
+ SEQ_GT(hole->rxmit, top)) {
+ log(LOG_CRIT, "%s#%d: invalid SACK hole (%u-%u,%u) vs so_snd %u ignoring.\n",
+ __func__, __LINE__, hole->start, hole->end, hole->rxmit, top);
+ return (NULL);
}
return (hole);
}

File Metadata

Mime Type
text/plain
Expires
Tue, Jan 14, 5:23 AM (21 h, 40 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15791377
Default Alt Text
D35446.diff (4 KB)

Event Timeline