[RFC] solution for the inet_ntoa problem, buffer allocator

From: Olaf Titz (olaf@bigred.inka.de)
Date: Wed Jul 05 2000 - 07:08:49 EST


Ideally, we would be able to do something like:
  printk(KERN_DEBUG "foo: src=%s dst=%s\n", inet_ntoa(src), inet_ntoa(dst));
but the inet_ntoa() API doesn't work that way. Providing a buffer to
that function needs additional code over and over again, and that is
exactly what such library functions should eliminate.
The NIPQUAD solution is (a) cumbersome to handle, (b) conceptually
wrong since an IP address is _one_ item to print, not four, and (c)
even worse when dealing with IPv6 addresses.

Some kind of dynamic allocation of buffers would be in order.
Unfortunately, alloca() can not be used in this context.

I'm presenting a simple routine to dynamically allocate buffers and
implementations of
 char *kinet_ntoa(__u32 a) and
 char *kinet6_ntoa(const struct in6_addr *a)
which use this allocation. With those routines, it is possible to call
printk() in the natural way. For the IPv6 case, the address is
displayed in compressed format. It is easy to add any other
"foo-to-string" conversion routine.

The buffer allocation works as follows: every conversion routine has
its own chain (salloc_t) of buffers (scope_buf_t). Whenever a buffer
is needed, it looks for a free one in the chain. Each buffer is tagged
with the return address of the caller (here called "scope"). A buffer
is considered free when its scope doesn't match the current one.
Additionally, since one buffer can be used several times in a row by
one caller, a buffer is considered free if it is older than an hour.
When no free buffer is found, a new one is allocated. A routine to
free the whole chain is provided too.
Each chain is protected by its own spinlock and the whole thing is
(assumed to be) SMP-safe.

I assume that using __builtin_frame_address(0) as scope instead of
__builtin_return_address(0) would lead to less collisions, but this is
not tested and using __builtin_frame_address in a function seems to
automatically turn on -fno-omit-frame-pointer for that function, so
this is prone to hurt more than it helps.

The central salloc() routine is non-reentrant wrt. one chain and the
buffers it returns are assumed to be short-lived. It is constructed
precisely for the printk("%s", foo(bar)) or strcpy(dest, foo(bar))
situation where foo() calls salloc() to get its buffer and probably
unsuited for other uses.

The buffer chains are like micro-slabs but using a kmem_cache for each
one of them, which is assumed to hold only 3-4 objects of size 16
bytes (for kinet_ntoa), would probably be overkill.

I currently use this module in CIPE and it works. (The IPv6 part is
more a demo by now, since CIPE doesn't use IPv6, but it is tested.)

Olaf





-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Fri Jul 07 2000 - 21:00:16 EST