Date: Wed, 01 Sep 2010 14:57:36 +0200 From: Andre Oppermann <andre@freebsd.org> To: ben wilber <ben@desync.com> Cc: FreeBSD Current <freebsd-current@freebsd.org> Subject: Re: TSO panic Message-ID: <4C7E4DC0.5040608@freebsd.org> In-Reply-To: <20100831231314.GA9637@exodus.desync.com> References: <20100831231314.GA9637@exodus.desync.com>
next in thread | previous in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format. --------------090308050905070202030506 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit On 01.09.2010 01:13, ben wilber wrote: > Hi, > > I just upgraded from r210042 to r212073 and keep getting the panic > introduced in r211317: > > panic: tcp_output: len<= tso_segsz Please try the attached patch and report back whether it fixes the issue. I'm a bit in a hurry right now and can respond again later in the evening. -- Andre > db:0:kdb.enter.default> bt > Tracing pid 12 tid 100063 td 0xffffff001881b000 > kdb_enter() at kdb_enter+0x3d > panic() at panic+0x1c8 > tcp_output() at tcp_output+0x1445 > tcp_do_segment() at tcp_do_segment+0x252d > tcp_input() at tcp_input+0x1044 > ip_input() at ip_input+0x5cd > netisr_dispatch_src() at netisr_dispatch_src+0xc1 > netisr_dispatch() at netisr_dispatch+0x11 > ether_demux() at ether_demux+0x19a > ether_input() at ether_input+0x36a > mxge_intr() at mxge_intr+0x5be > intr_event_execute_handlers() at intr_event_execute_handlers+0x107 > ithread_loop() at ithread_loop+0xb5 > fork_exit() at fork_exit+0x147 > fork_trampoline() at fork_trampoline+0xe > --- trap 0, rip = 0, rsp = 0xffffff8810df2cf0, rbp = 0 --- > > If there's someone interested in debugging this further, please let me > know what I can do to help. > _______________________________________________ > freebsd-current@freebsd.org mailing list > http://lists.freebsd.org/mailman/listinfo/freebsd-current > To unsubscribe, send any mail to "freebsd-current-unsubscribe@freebsd.org" > > --------------090308050905070202030506 Content-Type: text/plain; name="tcp_tso-fix.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="tcp_tso-fix.diff" Index: netinet/tcp_output.c =================================================================== --- netinet/tcp_output.c (revision 211958) +++ netinet/tcp_output.c (working copy) @@ -466,9 +466,8 @@ } /* - * Truncate to the maximum segment length or enable TCP Segmentation - * Offloading (if supported by hardware) and ensure that FIN is removed - * if the length no longer contains the last data byte. + * Decide if we can use TCP Segmentation Offloading (if supported by + * hardware). * * TSO may only be used if we are in a pure bulk sending state. The * presence of TCP-MD5, SACK retransmits, SACK advertizements and @@ -476,10 +475,6 @@ * (except for the sequence number) for all generated packets. This * makes it impossible to transmit any options which vary per generated * segment or packet. - * - * The length of TSO bursts is limited to TCP_MAXWIN. That limit and - * removal of FIN (if not already catched here) are handled later after - * the exact length of the TCP options are known. */ #ifdef IPSEC /* @@ -488,22 +483,15 @@ */ ipsec_optlen = ipsec_hdrsiz_tcp(tp); #endif - if (len > tp->t_maxseg) { - if ((tp->t_flags & TF_TSO) && V_tcp_do_tso && - ((tp->t_flags & TF_SIGNATURE) == 0) && - tp->rcv_numsacks == 0 && sack_rxmit == 0 && - tp->t_inpcb->inp_options == NULL && - tp->t_inpcb->in6p_options == NULL + if ((tp->t_flags & TF_TSO) && V_tcp_do_tso && len > tp->t_maxseg && + ((tp->t_flags & TF_SIGNATURE) == 0) && + tp->rcv_numsacks == 0 && sack_rxmit == 0 && #ifdef IPSEC - && ipsec_optlen == 0 + ipsec_optlen == 0 && #endif - ) { - tso = 1; - } else { - len = tp->t_maxseg; - sendalot = 1; - } - } + tp->t_inpcb->inp_options == NULL && + tp->t_inpcb->in6p_options == NULL) + tso = 1; if (sack_rxmit) { if (SEQ_LT(p->rxmit + len, tp->snd_una + so->so_snd.sb_cc)) @@ -733,28 +747,54 @@ * bump the packet length beyond the t_maxopd length. * Clear the FIN bit because we cut off the tail of * the segment. - * - * When doing TSO limit a burst to TCP_MAXWIN minus the - * IP, TCP and Options length to keep ip->ip_len from - * overflowing. Prevent the last segment from being - * fractional thus making them all equal sized and set - * the flag to continue sending. TSO is disabled when - * IP options or IPSEC are present. */ if (len + optlen + ipoptlen > tp->t_maxopd) { flags &= ~TH_FIN; + + /* + * TSO is disabled when IP options or IPSEC are present. + */ if (tso) { - if (len > TCP_MAXWIN - hdrlen - optlen) { - len = TCP_MAXWIN - hdrlen - optlen; - len = len - (len % (tp->t_maxopd - optlen)); + KASSERT(ipoptlen == 0, + ("%s: TSO can't do IP options", __func__)); + + /* + * When doing TSO limit a burst to IP_MAXPACKET + * IP, TCP and Options length to keep ip->ip_len + * from overflowing. + */ + if (len > IP_MAXPACKET - hdrlen) { + len = IP_MAXPACKET - hdrlen; sendalot = 1; - } else if (tp->t_flags & TF_NEEDFIN) + } + + /* + * Prevent the last segment from being + * fractional unless there is no further + * data and the send sockbuf can be emptied. + */ + if (sendalot && off + len < so->so_snd.sb_cc) { + len -= len % (tp->t_maxopd - optlen); sendalot = 1; + } + + /* + * Send the FIN in a separate segment + * after the bulk sending is done. + * We don't trust the TSO implementations + * to clear the FIN flag on all but the + * last segment. + */ + if (tp->t_flags & TF_NEEDFIN) + sendalot = 1; + } else { len = tp->t_maxopd - optlen - ipoptlen; sendalot = 1; } } + KASSERT(len + hdrlen + ipoptlen <= IP_MAXPACKET, + ("%s: len too big", __func__)); /*#ifdef DIAGNOSTIC*/ #ifdef INET6 --------------090308050905070202030506--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4C7E4DC0.5040608>