The new accessor functions were designed as a mean of safely accessing
protocol headers in mbuf chains, to replace the existing calls to
mtod. Therefore, they are suitable for code which needs to access such
headers in possibly fragmented mbufs, mainly the input path of network
protocol implementations, so I concentrated on converting those.
There are many cases where the new API does not apply.
The output path of networking protocols usually allocates or prepends
new headers. In this case the data are guaranteed to be contiguous and
it would be pointless to replace the mtod calls immediately following
such allocations by mptr_rw.
There are cases when access to the headers inside is not needed,
rather the mbuf contents needs to be manipulated more directly, which
is currently done by using mtod with a type such as caddr_t or
u_int8_t* and by directly accessing struct mbuf members like m_data
and m_len. The new API is not suitable for such code, but a more
low-level API could be provided if accessing struct mbuf members is
deemed undesirable - here are some
thoughts about that. I have even tried to convert one of the
problematic files (net/if_sl.c) to such API (without actually
implementing it) and it looked promising.
Examples of such code include:
This happens usually while a new mbuf is constructed or the packet is
being output and needs to be copied to another data structure such as
the tty output queue (in case of SLIP and PPP) or to hardware.
Another case is when the data need to be decrypted or encrypted (as in
net80211/ieee80211_crypto*.c or IPSEC).
netsmb/ has its own abstraction on top of mbufs, called mbchain, and does
not use mtod() for obtaining pointers to data structures.
FAST_IPSEC (netipsec/*) also has its own mbuf API, found in
netipsec/ipsec_mbuf.c . It has some utility functions which are not
part of the standard API and accesses mbuf internals directly. It
includes m_clone function which is called at the start of ipsec
output routines and makes a writable copy of a mbuf chain, while
compacting it to make the crypto operations more efficient. This
obviates the need for checking writability farther in the output
The mptr*() macros by using sizeof are not suitable for cases when
only a part of the structure will be accessed, because they use sizeof
and would think that the mbuf is too short. There is such code in the
ieee80211_input() function with this comment:
* Bit of a cheat here, we use a pointer for a 3-address
* frame format but don't reference fields past outside
* ieee80211_frame_min w/o first validating the data is
wh = mtod(m, struct ieee80211_frame *);
Similar issue arises with variable-sized structures when the sizeof
is the maximum size of all the variants. This happens for struct
icmp_header in icmp_input().
In surprisingly many cases, some data is inserted or removed from
inside the mbuf chain. There is no standartized function for this. It
could be worthwhile to centralize it in a common routine. FAST_IPSEC
already does that - it has the m_striphdr and m_makespace functions in
Insertion happens at least in:
in the 802.11 encrypting functions ccmp_encap(), tkip_encap(),
icmp6_reflect(), icmp6_input(), icmp_reflect(), vlan_input(),
802.11 decrypting functions tkip_decap, ccmp_decap, wep_decap().
A question is if it is worth changing code shared with other
projects. Changes would introduce divergence and complicate later
merging, so it may be better to wait for the API to stabilize and make
a decision based on its acceptance (or lack thereof) by other
projects. As an example I have converted net80211 which seem to be
well suited for the new API, but not FAST_IPSEC, which has a number of
private mbuf manipulation routines and is being extended to support
IPv6 in the meantime. The IPv6 stack won't be probably merged with
upstream version due to the conclusion of KAME, so this won't probably
be an issue.
A related limitation is that as NetBSD will likely want to continue
importing networking code from other projects, we are limited by
backward compatibility and we can't remove widely used functions, or
change their meaning, or in other ways more radically refactor the
current API. An example is provided by IPFilter and m_copyback. The
m_copyback function does not rearrange the mbuf chain, which means
that it must panic if it encounters a read-only mbuf. Changing this is
not possible, for example IPFilter would break because it keeps
pointers to mbuf contents which would be invalidated by rearranging
the mbuf chain. In NetBSD, a new function m_copyback_cow was added