I have now copied and made minor changes to the source files I need. They compile, and with just a few warnings. One of these involves the dtom() macro, which is called in one place in tcp_close() in tcp_subr.c
Ignoring the details of the call for now, let's consider the macro. It is found in mbuf.h
#define dtom(x) ((struct mbuf *)((int)(x) & ~(MSIZE-1))) #define mtod(m,t) ((t)((m)->m_data))Note that mtod() is just fine, with the fringe benefit of casting the m_data field to whatever type is appropriate.
The dtom() macro gets XXX notes even in the original BSD files. My compiler warns that I am converting a pointer to an integer and then warns that I am converting it back again. This clearly will not work on some architectures and is a somewhat questionable trick that depends on the alignment of the mbuf structures when they are allocated.
Looking at code in NetBSD-2.0, dtom() had already been done away with.
Looking at code in NetBSD-1.3, the call that used dtom() in tcp_close() had been rewritten without a call to dtom(). It now looks like this:
if (tp->t_template) FREE(tp->t_template, M_MBUF);In the Net/3 code it is:
if (tp->t_template) (void) m_free(dtom(tp->t_template));In NetBSD-1.3 "FREE" is a macro in sys/malloc.h.
But why the dtom in the first place. Does t_template point to something of a different sort? Do they actually do something smart and keep track of the mbuf itself in NetBSD? In either case, tp is a pointer to a "struct tcpcb" and in both cases we see:
struct tcpiphdr *t_template;
Aha! The vital change is in tcp_template(). In the Net/3 code, the code uses m_get() to allocate an mbuf then does n = mtod(m, struct tcpiphdr *); to get a pointer to the innards. But in NetBSD, the code does this:
MALLOC(n, struct tcpiphdr *, sizeof (struct tcpiphdr), M_MBUF, M_NOWAIT);It allocates just the tcpip header it needs, so there is no need to use dtom to find the enclosing mbuf.
There are interesting issues with FREE and MALLOC in sys/malloc.h -- in particular the M_MBUF "type" thing. Just how the tcpip header qualifies as an mbuf in this context is foggy to me. What it is doing is to keep a "cache" of MBUF objects that have been freed in a linked list so they can just be handed out again. This makes sense and is a fine idea, but is the tcpiphdr big enough to serve as an mbuf in some future allocation? Apparently so.
I solve this in my own way. I put a static tcpip structure inside of the tcpcb structure and modify tcp_template to simply set the pointer to this. It will never need to be deallocated. Then I do away with the dtom macro entirely.
I have to reorder the header files in almost all the C source files so they include tcpip.h before tcp_var.h and then things are good.
Kyu / [email protected]