Support forums
Getting started

Primiano Tucci

SourceForge.net Logo

Developer documentation

The lnlb driver has a modular structure that allows developers (some kernel module developing skills required) to write custom session tracking modules.
You can replace the default module (lnlb_mod_default), or you can keep it as default handler and write your own module that will only handle a particular transport protocol (TCP,UDP,...)

The main driver exports two symbols in order to allow external modules to be registered as protocol handlers:

int lnlb_register_ph(uint8_t iProto,struct lnlb_protocol_module *iMod);
void lnlb_unregister_ph(uint8_t iProto);

first argument of both functions specifies the protocol handler you're registering (e.g. 6 for TCP, 17 for UDP). A 0 value means "default handler".

Now let's take a look to the lnlb_protocol_module struct (as defined in if_lnlb.h)

struct lnlb_protocol_module {
 int (*dgram_is_related)(const struct lnlb_struct*,struct sk_buff *,unsigned char *);
 void (*dgram_assigned)(const struct lnlb_struct *,struct sk_buff *,unsigned char *);
 void (*node_died)(const struct lnlb_struct *,unsigned char *);
 void (*interface_created)(const struct lnlb_struct*);
 void (*interface_deleted)(const struct lnlb_struct *);
 uint32_t (*save_status)(const struct lnlb_struct*,char **);
 int (*load_status)(const struct lnlb_struct*,char *,uint32_t);


The struct simply contains some pointers to function prototypes that the handler must expose (remember to set references to funcions in the lnlb_protocol_module struct when registering it).

Please note that all the function has a first parameter pointing to a lnlb_struct structure. This is always passed by the main driver and tells the module to which cluster we're referring (since we can have more than a cluster on a machine, each cluster is associated to a virtual interface... each virtual interface has a lnlb_struct structure... se the if_lnlb.h header for more).
You should not usually need to read parmeters in the passed, lnlb_struct. It should be only useful to you to distinguish between clusters (theorically if you implement some kind of tracking table you should have a table for each lnlb_struct in order to avoid messing tracking info between more clusters).

int dgram_is_related(const struct lnlb_struct*,struct sk_buff *,unsigned char *)
This function is called by the main driver to ask whether the module if the current sk_buff is map ped to a node or not. Module must return a a true/false value (0 is not mapped, 1 is mapped). On true value the node MAC address must be copied out in the unsigned char * parm.

void dgram_assigned(const struct lnlb_struct *,struct sk_buff *,unsigned char *)
The main driver notifies us that the current sk_buff has been assigned to the node (refernced by it's MAC addres passed as an unsigned char *). At this point we should store tracking informations in our tables (or anything else).

void node_died(const struct lnlb_struct *,unsigned char *)
The main driver notifies us that the referenced node is faulty (so we should remove it from our tracking tables).

void interface_created(const struct lnlb_struct*)
The main driver notifies us that a new cluster (and so a new lnlb_struct) has been created. At this point we should usually allocate and initialize our tracking tables.

void interface_deleted(const struct lnlb_struct*)
The main driver notifies us that a the cluster (and so the lnlb_struct) has been removed. At this point we should usually deallocate our tracking tables

uint32_t (*save_status)(const struct lnlb_struct*,char **)
The main driver asks us to serialize the tracking status of this module into a buffer (the function must kmalloc it with GFP_ATOMIC priority). Buffer lenght is returned. Buffer pointer is copied out into the char** param (*param=buf_addr)

int (*load_status)(const struct lnlb_struct*,char *,uint32_t)
The main driver tells us to clear our tracking status and deserialize the buffer (pointed by char * arg) of uint32_t length .