Date: Mon, 17 Oct 2011 16:29:54 +0100 From: Ben Hutchings <bhutchings@solarflare.com> To: freebsd-net@freebsd.org Subject: Re: TSO broken with jumbo MTU Message-ID: <1318865394.2784.4.camel@bwh-desktop> In-Reply-To: <1317309906.2743.9.camel@bwh-desktop> References: <1317309906.2743.9.camel@bwh-desktop>
next in thread | previous in thread | raw e-mail | index | archive | help
This is the fix/workaround I used: --- a/netinet/tcp_output.c +++ b/netinet/tcp_output.c @@ -1062,9 +1062,7 @@ * The TCP pseudo header checksum is always provided. * XXX: Fixme: This is currently not the case for IPv6. */ - if (tso) { - KASSERT(len > tp->t_maxopd - optlen, - ("%s: len <= tso_segsz", __func__)); + if (tso && len > tp->t_maxopd - optlen) { m->m_pkthdr.csum_flags |= CSUM_TSO; m->m_pkthdr.tso_segsz = tp->t_maxopd - optlen; } --- END --- But the correct thing to do may be to change the calculation of t_maxopd (untested): --- a/netinet/tcp_input.c +++ b/netinet/tcp_input.c @@ -3087,7 +3087,7 @@ tcp_mss_update(struct tcpcb *tp, int offer, struct hc_metrics_lite *metricptr, int *mtuflags) { - int mss; + int mss, ts_len; u_long maxmtu; struct inpcb *inp = tp->t_inpcb; struct hc_metrics_lite metrics; @@ -3212,22 +3212,17 @@ mss = max(mss, 64); /* - * maxopd stores the maximum length of data AND options - * in a segment; maxseg is the amount of data in a normal - * segment. We need to store this value (maxopd) apart - * from maxseg, because now every segment carries options - * and thus we normally have somewhat less data in segments. - */ - tp->t_maxopd = mss; - - /* * origoffer==-1 indicates that no segments were received yet. * In this case we just guess. */ if ((tp->t_flags & (TF_REQ_TSTMP|TF_NOOPT)) == TF_REQ_TSTMP && (origoffer == -1 || (tp->t_flags & TF_RCVD_TSTMP) == TF_RCVD_TSTMP)) - mss -= TCPOLEN_TSTAMP_APPA; + ts_len = TCPOLEN_TSTAMP_APPA; + else + ts_len = 0; + + mss -= ts_len; #if (MCLBYTES & (MCLBYTES - 1)) == 0 if (mss > MCLBYTES) @@ -3237,6 +3232,15 @@ mss = mss / MCLBYTES * MCLBYTES; #endif tp->t_maxseg = mss; + + /* + * maxopd stores the maximum length of data AND options + * in a segment; maxseg is the amount of data in a normal + * segment. We need to store this value (maxopd) apart + * from maxseg, because now every segment carries options + * and thus we normally have somewhat less data in segments. + */ + tp->t_maxopd = mss + ts_len; } void --- END --- Ben. -- Ben Hutchings, Staff Engineer, Solarflare Not speaking for my employer; that's the marketing department's job. They asked us to note that Solarflare product names are trademarked.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1318865394.2784.4.camel>