khelp(9) Kernel Helper Framework

Other Alias

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

SYNOPSIS

In sys/khelp.h In sys/module_khelp.h Fn int khelp_init_osd uint32_t classes struct osd *hosd Fn int khelp_destroy_osd struct osd *hosd Fn int32_t khelp_get_id char *hname Fn void * khelp_get_osd struct osd *hosd int32_t id Fn int khelp_add_hhook struct hookinfo *hki uint32_t flags Fn int khelp_remove_hhook struct hookinfo *hki Fn KHELP_DECLARE_MOD hname hdata hhooks version Fn KHELP_DECLARE_MOD_UMA hname hdata hhooks version ctor dtor

DESCRIPTION

provides a framework for managing 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 module may be able to associate per-object data for maintaining relevant state between hook calls. The hhook(9) and frameworks are tightly integrated and anyone interested in should also read the hhook(9) manual page thoroughly.

Information for Khelp Module Implementors

modules are represented within the framework by a Vt 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 Vt 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 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 framework during the deregistration process, after the module has been deregistered by the framework. The return value is currently ignored. Valid classes are defined in In sys/khelp.h . Valid flags are defined in In sys/module_khelp.h . The HELPER_NEEDS_OSD flag should be set in the h_flags field if the module requires persistent per-object data storage. There is no programmatic way (yet) to check if a class provides the ability for modules to associate persistent per-object data, so a manual check is required.

The Fn KHELP_DECLARE_MOD and Fn KHELP_DECLARE_MOD_UMA macros provide convenient wrappers around the DECLARE_MODULE9 macro, and are used to register a module with the framework. Fn 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 Vt struct helper Ns 's h_flags field.

The first four arguments common to both macros are as follows. The Fa hname argument specifies the unique ascii(7) name for the module. It should be no longer than HELPER_NAME_MAXLEN-1 characters in length. The Fa hdata argument is a pointer to the module's Vt struct helper . The Fa hhooks argument points to a static array of Vt struct hookinfo structures. The array should contain a Vt 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 Fa version argument specifies a version number for the module which will be passed to MODULE_VERSION9. The Fn KHELP_DECLARE_MOD_UMA macro takes the additional Fa ctor and Fa dtor arguments, which specify optional uma(9) constructor and destructor functions. NULL should be passed where the functionality is not required.

The Fn khelp_get_id function returns the numeric identifier for the module with name Fa hname .

The Fn khelp_get_osd function is used to obtain the per-object data pointer for a specified module. The Fa hosd argument is a pointer to the underlying subsystem object's Vt struct osd . This is provided by the hhook(9) framework when calling into a module's hook function. The Fa id argument specifies the numeric identifier for the module to extract the data pointer from Fa hosd for. The Fa id is obtained using the Fn khelp_get_id function.

The Fn khelp_add_hhook and Fn khelp_remove_hhook functions allow a module to dynamically hook/unhook hhook(9) points at run time. The Fa hki argument specifies a pointer to a Vt 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 Fa flags argument of Fn 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 modules to do useful things relates to defining and instantiating suitable hhook(9) points for modules to hook into. The only additional decision a subsystem needs to make is whether it wants to allow modules to associate persistent per-object data. Providing support for persistent data storage can allow 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 Vt struct osd pointer in the structure definition for the object.
  • Add calls to Fn khelp_init_osd and Fn khelp_destroy_osd to the subsystem code paths which are responsible for respectively initialising and destroying the object.

The Fn khelp_init_osd function initialises the per-object data storage for all currently loaded modules of appropriate classes which have set the HELPER_NEEDS_OSD flag in their h_flags field. The Fa classes argument specifies a bitmask of classes which this subsystem associates with. If a module matches any of the classes in the bitmask, that module will be associated with the object. The Fa hosd argument specifies the pointer to the object's Vt struct osd which will be used to provide the persistent storage for use by modules.

The Fn khelp_destroy_osd function frees all memory that was associated with an object's Vt struct osd by a previous call to Fn khelp_init_osd . The Fa hosd argument specifies the pointer to the object's Vt struct osd which will be purged in preparation for destruction.

IMPLEMENTATION NOTES

modules are protected from being prematurely unloaded by a reference count. The count is incremented each time a subsystem calls Fn khelp_init_osd causing persistent storage to be allocated for the module, and decremented for each corresponding call to Fn khelp_destroy_osd . Only when a module's reference count has dropped to zero can the module be unloaded.

RETURN VALUES

The Fn khelp_init_osd function returns zero if no errors occurred. It returns ENOMEM if a module which requires per-object storage fails to allocate the necessary memory.

The Fn khelp_destroy_osd function only returns zero to indicate that no errors occurred.

The Fn khelp_get_id function returns the unique numeric identifier for the registered module with name Fa hname . It return -1 if no module with the specified name is currently registered.

The Fn khelp_get_osd function returns the pointer to the module's persistent object storage memory. If the module identified by Fa id does not have persistent object storage registered with the object's Fa hosd Vt struct osd , NULL is returned.

The Fn 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 Fn 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_ertt4 module provides a more complex example of what is possible.

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 kernel helper framework first appeared in Fx 9.0 .

The 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

An -nosplit The framework was written by An Lawrence Stewart Aq [email protected] .

This manual page was written by An David Hayes Aq [email protected] and An Lawrence Stewart Aq [email protected] .