Subject: Re: SoC ideas - mbuf API
To: None <tech-net@NetBSD.org>
From: David Young <dyoung@pobox.com>
List: tech-net
Date: 06/27/2006 11:54:21
On Wed, Jun 21, 2006 at 09:47:49AM +0200, Pavel Cahyna wrote:
> I would like to present some proposals about planned modifications to the
> mbuf API for my SoC project.
>
> In short, I think that the current mbuf code makes too difficult to write
> correct code, and too easy to make mistakes, as noted in this post:
>
> http://permalink.gmane.org/gmane.os.netbsd.devel.network/7299
>
> My proposal precises my reply in that thread:
>
> http://permalink.gmane.org/gmane.os.netbsd.devel.network/7302
>
> I see basically two problems with the current mbuf API:
>
> The 1st problem: if the code does not use m_pullup/pulldown when it should, it
> works in most cases, but when it encounters a packet fragmented in a right
> way, it malfunctions.
>
> Example: kern/29014.
>
> The 2nd problem: mbufs can be read-only, and there are cases when they are
> overwritten without checking for writability. See the above-referenced
> thread for an example, or PR kern/33162.
>
> Moreover, m_pullup always copies from the mbuf cluster, even if the data
> are contiguous, for historical reasons, so the current code avoids calling
> it if not necessary making it even more complicated. The result looks like:
>
> if (m->m_len < sizeof(struct ether_header)) {
> m = m_pullup(m, sizeof(struct ether_header));
> if (m == NULL)
> return NULL;
> }
> eh = mtod(m, struct ether_header *);
>
> Such code is present in about hundred of places in the kernel.
>
> Solution: simplify this common idiom. Let's make a mptr(m, type) macro which
> would be used like:
>
> eh = mptr_pullup(m, struct ether_header, 0)
> if (eh == NULL)
> recovery from error;
>
>
> where the mptr_pullup(struct mbuf *m, type, off)
>
> and it would return the pointer to data in m starting at off, cast to
> const type * (in tis case to const struct ether_header *), and make the
> mbuf contiguous for sizeof (type) bytes, like m_pulldown does.
>
> Then deprecate mtod from all the code which does not have to deal with mbuf
> internals.
>
> For the code which "knows" that the packet is already contiguous it would
> be enough to have a mptr() which would not do m_pulldown but check
> and panic if DIAGNOSTIC. (The goal is to pull-up early and make this the
> common case.)
>
> For most of the uses the version returning const should be enough. Code
> which needs a writable pointer to the mbuf could use a mptr_rw macro,
> which would do a m_makewritable on the returned region. Or such code
> should be converted to m_copyback, then mptr_rw wouldn't be needed. There
> shouldn't be many places where writing to mbufs is necessary.
Careful: m_makewritable does not guarantee that the mbuf is contiguous,
only that each segment is writable. That deserves to be explicitly
mentioned in mbuf(9); I keep forgetting to add that.
Dave
--
David Young OJC Technologies
dyoung@ojctech.com Urbana, IL * (217) 278-3933