When using TSO and sending more than TCP_MAXWIN sendalot is set

and we loop back to 'again'.  If the remainder is less or equal
to one full segment, the TSO flag was not cleared even though
it isn't necessary anymore.  Enabling the TSO flag on a segment
that doesn't require any offloaded segmentation by the NIC may
cause confusion in the driver or hardware.

Reset the internal tso flag in tcp_output() on every iteration
of sendalot.

PR:		kern/132832
Submitted by:	Renaud Lienhart <renaud-at-vmware com>
MFC after:	1 week
This commit is contained in:
Andre Oppermann 2010-08-14 21:41:33 +00:00
parent 40fe9eff47
commit 153e5b57af

View File

@ -153,7 +153,7 @@ tcp_output(struct tcpcb *tp)
int idle, sendalot;
int sack_rxmit, sack_bytes_rxmt;
struct sackhole *p;
int tso = 0;
int tso;
struct tcpopt to;
#if 0
int maxburst = TCP_MAXBURST;
@ -211,6 +211,7 @@ tcp_output(struct tcpcb *tp)
SEQ_LT(tp->snd_nxt, tp->snd_max))
tcp_sack_adjust(tp);
sendalot = 0;
tso = 0;
off = tp->snd_nxt - tp->snd_una;
sendwin = min(tp->snd_wnd, tp->snd_cwnd);
sendwin = min(sendwin, tp->snd_bwnd);
@ -490,9 +491,9 @@ tcp_output(struct tcpcb *tp)
} else {
len = tp->t_maxseg;
sendalot = 1;
tso = 0;
}
}
if (sack_rxmit) {
if (SEQ_LT(p->rxmit + len, tp->snd_una + so->so_snd.sb_cc))
flags &= ~TH_FIN;
@ -1051,6 +1052,8 @@ tcp_output(struct tcpcb *tp)
* XXX: Fixme: This is currently not the case for IPv6.
*/
if (tso) {
KASSERT(len > tp->t_maxopd - optlen,
("%s: len <= tso_segsz", __func__));
m->m_pkthdr.csum_flags |= CSUM_TSO;
m->m_pkthdr.tso_segsz = tp->t_maxopd - optlen;
}