Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 27 Mar 2003 15:33:52 -0800
From:      Luigi Rizzo <rizzo@icir.org>
To:        Sam Leffler <sam@errno.com>
Cc:        cvs-all@FreeBSD.org
Subject:   Re: cvs commit: src/sys/conf options src/sys/netinet ip_output.c
Message-ID:  <20030327153352.A66323@xorpc.icir.org>
In-Reply-To: <031301c2f49b$09d2bfb0$52557f42@errno.com>; from sam@errno.com on Thu, Mar 27, 2003 at 11:56:47AM -0800
References:  <200303260452.h2Q4quap015364@www.ambrisko.com> <20030326114030.U2075@odysseus.silby.com> <20030326183351.GJ57674@elvis.mu.org> <20030326130903.G2075@odysseus.silby.com> <20030327013224.P7674@odysseus.silby.com> <031301c2f49b$09d2bfb0$52557f42@errno.com>

next in thread | previous in thread | raw e-mail | index | archive | help
[about coalescing long chains of mbufs...]

On Thu, Mar 27, 2003 at 11:56:47AM -0800, Sam Leffler wrote:

[have read the rest of the thread too]

> I thought about this some more.  If the purpose of m_defrag* is to handle
...
> driver unless you make a second pass.  Given that this problem should happen
> infrequently and that you're just trying to avoid discarding the packet I
> think you're best off doing a best effort job where you coalesce only mbufs
> and leave clusters/ext's alone.  Then if the subsequent bus_dma_load_mbuf
> call fails you discard the packet.  Other than the read/write requirements

the problem is that the code path leading to these situation behave
sistematically like this -- ie. you are likely to keep dropping the packet
again and again, so dropping may not be an option.

Anyways, one path where this came out was

	tcp_usr_send() --> sbappend() --> sbcompress()

and i think if the code decides to call sbcompress(),
then the latter should try and do its job as good as it can,
including allocating a cluster when the caller does a
pathological number of short writes, or merging segments
trying to reduce the waste factor to something reasonable

E.g. note that sbcompress() does the following:

	while (m) {
		...
                if (n && (n->m_flags & M_EOR) == 0 &&
                    M_WRITABLE(n) &&
                    m->m_len <= MCLBYTES / 4 && /* XXX: Don't copy too much */
                    m->m_len <= M_TRAILINGSPACE(n) &&
                    n->m_type == m->m_type) {
			... do the copy and free m
			continue;
		}
		...
	}

so individual writes of 513+ bytes will result in wasting up to 75%
of the socket buffer space. At the very least, i would drop the
'm->m_len <= MCLBYTES / 4' check to reduce the waste.

	cheers
	luigi



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030327153352.A66323>