How to use exported characters optionally only if they are present in the Linux kernel kernel module?

I am modifying the Linux kernel to add some features to the Linux virtual server (LVS).

I developed a module (which I named net/netfilter/ipvs/ip_vs_utils.c) with some functions that will be used in load balancing. All functions here are exported using EXPORT_SYMBOL().

This module does not logically load all the time. My intention is to let the user decide whether he wants to use this additional functionality or not (loading or unloading the module).

My question is how can I call these OPTIONALLY functions (depending on whether the module works or not) from an existing (and, of course, modified) module ( net/netfilter/ipvs/ip_vs_core.c). Something like that:

if(ip_vs_utils_IsLoaded)
{
  function1(arg1, arg2, arg3); // being function1 defined on ip_vs_utils.c
}
+5
source share
1 answer

I think you need a trampoline always (or almost always) loaded into the kernel.

In the trampoline code, you need such variables.

struct module *ip_vs_utils_mod;
EXPORT_SYMBOL(ip_vs_utils_mod);

/* function pointers */
ret_type (*ip_vs_utils_afunc_ptr)(func_arg_list); /* Add static if you put it in a header file! */
EXPORT_SYMBOL(ip_vs_utils_afunc_ptr); /*  ******EXPORTED***** */

When ip_vs_utils loads, you need to initialize all the variables, the initialization code is in the ip_vs_utils.c file:

ip_vs_utils_mod = THIS_MODULE;

/* init function pointers */

/* ip_vs_utils_afunc_impl is the real implementation
 * of the function, it is *****NOT***** needed to export it
 */
ip_vs_utils_afunc_ptr = ip_vs_utils_afunc_impl;

And add trampoline functions to the trampoline code:

ret_type ip_vs_utils_afunc(func_arg_list)
{
   ret_type ret = DEFAULT_RET;

   if (try_module_get(ip_vs_utils_mod)) {
       ret = (*ip_vs_utils_afunc_ptr)(func_arg_list);
       module_put(ip_vs_utils_mod);
   }
   return ret;
}

try_module_get () is needed to protect the module from sudden unloading when ip_vs_utils_afunc_ptr () is called. You can also use RCU to reduce the overhead of try_module_get () / module_put (). (But it is difficult)

- -, ( Linux)

+4

All Articles