NAME¶
khelp
,
khelp_init_osd
,
khelp_destroy_osd
,
khelp_get_id
,
khelp_get_osd
,
khelp_add_hhook
,
khelp_remove_hhook
,
KHELP_DECLARE_MOD
,
KHELP_DECLARE_MOD_UMA
—
Kernel Helper Framework
SYNOPSIS¶
#include
<sys/khelp.h>
#include
<sys/module_khelp.h>
int
khelp_init_osd
(
uint32_t
classes,
struct
osd *hosd);
int
khelp_destroy_osd
(
struct
osd *hosd);
int32_t
khelp_get_id
(
char
*hname);
void *
khelp_get_osd
(
struct
osd *hosd,
int32_t id);
int
khelp_add_hhook
(
struct
hookinfo *hki,
uint32_t flags);
int
khelp_remove_hhook
(
struct
hookinfo *hki);
KHELP_DECLARE_MOD
(
hname,
hdata,
hhooks,
version);
KHELP_DECLARE_MOD_UMA
(
hname,
hdata,
hhooks,
version,
ctor,
dtor);
DESCRIPTION¶
khelp
provides a framework for managing
khelp
modules, which indirectly use the
hhook(9) KPI to register their hook functions
with hook points of interest within the kernel. Khelp modules aim to provide a
structured way to dynamically extend the kernel at runtime in an ABI
preserving manner. Depending on the subsystem providing hook points, a
khelp
module may be able to associate
per-object data for maintaining relevant state between hook calls. The
hhook(9) and
khelp
frameworks are tightly integrated and
anyone interested in
khelp
should also read
the
hhook(9) manual page thoroughly.
khelp
modules are represented within the
khelp
framework by a
struct helper which has the following
members:
struct helper {
int (*mod_init) (void);
int (*mod_destroy) (void);
#define HELPER_NAME_MAXLEN 16
char h_name[HELPER_NAME_MAXLEN];
uma_zone_t h_zone;
struct hookinfo *h_hooks;
uint32_t h_nhooks;
uint32_t h_classes;
int32_t h_id;
volatile uint32_t h_refcount;
uint16_t h_flags;
TAILQ_ENTRY(helper) h_next;
};
Modules must instantiate a
struct helper, but
are only required to set the
h_classes field,
and may optionally set the
h_flags,
mod_init and
mod_destroy fields where required. The
framework takes care of all other fields and modules should refrain from
manipulating them. Using the C99 designated initialiser feature to set fields
is encouraged.
If specified, the
mod_init function will be run
by the
khelp
framework prior to completing
the registration process. Returning a non-zero value from the
mod_init function will abort the registration
process and fail to load the module. If specified, the
mod_destroy function will be run by the
khelp
framework during the deregistration
process, after the module has been deregistered by the
khelp
framework. The return value is
currently ignored. Valid
khelp
classes are
defined in
<sys/khelp.h>
.
Valid flags are defined in
<sys/module_khelp.h>
.
The HELPER_NEEDS_OSD flag should be set in the
h_flags field if the
khelp
module requires persistent per-object
data storage. There is no programmatic way (yet) to check if a
khelp
class provides the ability for
khelp
modules to associate persistent
per-object data, so a manual check is required.
The
KHELP_DECLARE_MOD
() and
KHELP_DECLARE_MOD_UMA
() macros provide
convenient wrappers around the
DECLARE_MODULE(9)
macro, and are used to register a
khelp
module with the
khelp
framework.
KHELP_DECLARE_MOD_UMA
() should only be used
by modules which require the use of persistent per-object storage i.e. modules
which set the HELPER_NEEDS_OSD flag in their
struct
helper's
h_flags field.
The first four arguments common to both macros are as follows. The
hname argument specifies the unique
ascii(7) name for the
khelp
module. It should be no longer than
HELPER_NAME_MAXLEN-1 characters in length. The
hdata argument is a pointer to the module's
struct helper. The
hhooks argument points to a static array of
struct hookinfo structures. The array should
contain a
struct hookinfo for each
hhook(9) point the module wishes to hook, even
when using the same hook function multiple times for different
hhook(9) points. The
version argument specifies a version number
for the module which will be passed to
MODULE_VERSION(9). The
KHELP_DECLARE_MOD_UMA
() macro takes the
additional
ctor and
dtor arguments, which specify optional
uma(9) constructor and destructor functions. NULL
should be passed where the functionality is not required.
The
khelp_get_id
() function returns the
numeric identifier for the
khelp
module
with name
hname.
The
khelp_get_osd
() function is used to
obtain the per-object data pointer for a specified
khelp
module. The
hosd argument is a pointer to the underlying
subsystem object's
struct osd. This is
provided by the
hhook(9) framework when calling
into a
khelp
module's hook function. The
id argument specifies the numeric identifier
for the
khelp
module to extract the data
pointer from
hosd for. The
id is obtained using the
khelp_get_id
() function.
The
khelp_add_hhook
() and
khelp_remove_hhook
() functions allow a
khelp
module to dynamically hook/unhook
hhook(9) points at run time. The
hki argument specifies a pointer to a
struct hookinfo which encapsulates the
required information about the
hhook(9) point and
hook function being manipulated. The HHOOK_WAITOK flag may be passed in via
the
flags argument of
khelp_add_hhook
() if
malloc(9) is allowed to sleep waiting for memory
to become available.
Integrating Khelp Into a Kernel Subsystem¶
Most of the work required to allow
khelp
modules to do useful things relates to defining and instantiating suitable
hhook(9) points for
khelp
modules to hook into. The only
additional decision a subsystem needs to make is whether it wants to allow
khelp
modules to associate persistent
per-object data. Providing support for persistent data storage can allow
khelp
modules to perform more complex
functionality which may be desirable. Subsystems which want to allow Khelp
modules to associate persistent per-object data with one of the subsystem's
data structures need to make the following two key changes:
- Embed a struct osd pointer in the
structure definition for the object.
- Add calls to
khelp_init_osd
() and
khelp_destroy_osd
() to the subsystem
code paths which are responsible for respectively initialising and
destroying the object.
The
khelp_init_osd
() function initialises the
per-object data storage for all currently loaded
khelp
modules of appropriate classes which
have set the HELPER_NEEDS_OSD flag in their
h_flags field. The
classes argument specifies a bitmask of
khelp
classes which this subsystem
associates with. If a
khelp
module matches
any of the classes in the bitmask, that module will be associated with the
object. The
hosd argument specifies the
pointer to the object's
struct osd which will
be used to provide the persistent storage for use by
khelp
modules.
The
khelp_destroy_osd
() function frees all
memory that was associated with an object's
struct
osd by a previous call to
khelp_init_osd
(). The
hosd argument specifies the pointer to the
object's
struct osd which will be purged in
preparation for destruction.
IMPLEMENTATION NOTES¶
khelp
modules are protected from being
prematurely unloaded by a reference count. The count is incremented each time
a subsystem calls
khelp_init_osd
() causing
persistent storage to be allocated for the module, and decremented for each
corresponding call to
khelp_destroy_osd
().
Only when a module's reference count has dropped to zero can the module be
unloaded.
RETURN VALUES¶
The
khelp_init_osd
() function returns zero if
no errors occurred. It returns ENOMEM if a
khelp
module which requires per-object
storage fails to allocate the necessary memory.
The
khelp_destroy_osd
() function only returns
zero to indicate that no errors occurred.
The
khelp_get_id
() function returns the
unique numeric identifier for the registered
khelp
module with name
hname. It return -1 if no module with the
specified name is currently registered.
The
khelp_get_osd
() function returns the
pointer to the
khelp
module's persistent
object storage memory. If the module identified by
id does not have persistent object storage
registered with the object's
hosd
struct osd, NULL is returned.
The
khelp_add_hhook
() function returns zero
if no errors occurred. It returns ENOENT if it could not find the requested
hhook(9) point. It returns ENOMEM if
malloc(9) failed to allocate memory. It returns
EEXIST if attempting to register the same hook function more than once for the
same
hhook(9) point.
The
khelp_remove_hhook
() function returns
zero if no errors occurred. It returns ENOENT if it could not find the
requested
hhook(9) point.
EXAMPLES¶
A well commented example Khelp module can be found at:
/usr/share/examples/kld/khelp/h_example.c
The Enhanced Round Trip Time (ERTT)
h_ertt(4)
khelp
module provides a more complex
example of what is possible.
SEE ALSO¶
h_ertt(4),
hhook(9),
osd(9)
ACKNOWLEDGEMENTS¶
Development and testing of this software were made possible in part by grants
from the FreeBSD Foundation and Cisco University Research Program Fund at
Community Foundation Silicon Valley.
HISTORY¶
The
khelp
kernel helper framework first
appeared in
FreeBSD 9.0.
The
khelp
framework was first released in
2010 by Lawrence Stewart whilst studying at Swinburne University of
Technology's Centre for Advanced Internet Architectures, Melbourne, Australia.
More details are available at:
http://caia.swin.edu.au/urp/newtcp/
AUTHORS¶
The
khelp
framework was written by
Lawrence Stewart
⟨lstewart@FreeBSD.org⟩.
This manual page was written by
David Hayes
⟨david.hayes@ieee.org⟩ and
Lawrence
Stewart ⟨lstewart@FreeBSD.org⟩.