Object API
[Object]

Data Structures

struct  nl_object_ops
 Object Operations. More...

Defines

#define NLHDR_COMMON
 Common Object Header.
#define AVAILABLE(A, B, ATTR)   (((A)->ce_mask & (B)->ce_mask) & (ATTR))
 Return true if attribute is available in both objects.
#define ATTR_MISMATCH(A, B, ATTR, EXPR)   (!AVAILABLE(A, B, ATTR) || (EXPR))
 Return true if attributes mismatch.
#define ATTR_DIFF(LIST, ATTR, A, B, EXPR)
 Return attribute bit if attribute does not match.

Detailed Description

1) Object Definition
 // Define your object starting with the common object header
 struct my_obj {
        NLHDR_COMMON
        int             my_data;
 };

 // Fill out the object operations structure
 struct nl_object_ops my_ops = {
        .oo_name        = "my_obj",
        .oo_size        = sizeof(struct my_obj),
 };

 // At this point the object can be allocated, you may want to provide a
 // separate _alloc() function to ease allocting objects of this kind.
 struct nl_object *obj = nl_object_alloc(&my_ops);

 // And release it again...
 nl_object_put(obj);
2) Allocating additional data
 // You may require to allocate additional data and store it inside
 // object, f.e. assuming there is a field `ptr'.
 struct my_obj {
        NLHDR_COMMON
        void *          ptr;
 };

 // And at some point you may assign allocated data to this field:
 my_obj->ptr = calloc(1, ...);

 // In order to not introduce any memory leaks you have to release
 // this data again when the last reference is given back.
 static void my_obj_free_data(struct nl_object *obj)
 {
        struct my_obj *my_obj = nl_object_priv(obj);

        free(my_obj->ptr);
 }

 // Also when the object is cloned, you must ensure for your pointer
 // stay valid even if one of the clones is freed by either making
 // a clone as well or increase the reference count.
 static int my_obj_clone(struct nl_object *src, struct nl_object *dst)
 {
        struct my_obj *my_src = nl_object_priv(src);
        struct my_obj *my_dst = nl_object_priv(dst);

        if (src->ptr) {
                dst->ptr = calloc(1, ...);
                memcpy(dst->ptr, src->ptr, ...);
        }
 }

 struct nl_object_ops my_ops = {
        ...
        .oo_free_data   = my_obj_free_data,
        .oo_clone       = my_obj_clone,
 };
3) Object Dumping
 static int my_obj_dump_detailed(struct nl_object *obj,
                                   struct nl_dump_params *params)
 {
        struct my_obj *my_obj = nl_object_priv(obj);
        int line = 1;   // We will print at least one line for sure

        // It is absolutely essential to use nl_dump() when printing
        // any text to make sure the dumping parameters are respected.
        nl_dump(params, "Obj Integer: %d\n", my_obj->my_int);

        // Before we can dump the next line, make sure to prefix
        // this line correctly.
        nl_new_line(params, line++);

        // You may also split a line into multiple nl_dump() calls.
        nl_dump(params, "String: %s ", my_obj->my_string);
        nl_dump(params, "String-2: %s\n", my_obj->another_string);

        // Return the number of lines dumped
        return line;
 }

 struct nl_object_ops my_ops = {
        ...
        .oo_dump[NL_DUMP_FULL]  = my_obj_dump_detailed,
 };
4) Object Attributes
 // The concept of object attributes is optional but can ease the typical
 // case of objects that have optional attributes, e.g. a route may have a
 // nexthop assigned but it is not required to.

 // The first step to define your object specific bitmask listing all
 // attributes
 #define MY_ATTR_FOO            (1<<0)
 #define MY_ATTR_BAR            (1<<1)

 // When assigning an optional attribute to the object, make sure
 // to mark its availability.
 my_obj->foo = 123123;
 my_obj->ce_mask |= MY_ATTR_FOO;

 // At any time you may use this mask to check for the availability
 // of the attribute, e.g. while dumping
 if (my_obj->ce_mask & MY_ATTR_FOO)
        nl_dump(params, "foo %d ", my_obj->foo);

 // One of the big advantages of this concept is that it allows for
 // standardized comparisons which make it trivial for caches to
 // identify unique objects by use of unified comparison functions.
 // In order for it to work, your object implementation must provide
 // a comparison function and define a list of attributes which
 // combined together make an object unique.

 static int my_obj_compare(struct nl_object *_a, struct nl_object *_b,
                             uint32_t attrs, int flags)
 {
        struct my_obj *a = nl_object_priv(_a):
        struct my_obj *b = nl_object_priv(_b):
        int diff = 0;

        // We help ourselves in defining our own DIFF macro which will
        // call ATTR_DIFF() on both objects which will make sure to only
        // compare the attributes if required.
        #define MY_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, MY_ATTR_##ATTR, a, b, EXPR)

        // Call our own diff macro for each attribute to build a bitmask
        // representing the attributes which mismatch.
        diff |= MY_DIFF(FOO, a->foo != b->foo)
        diff |= MY_DIFF(BAR, strcmp(a->bar, b->bar))

        return diff;
 }

 // In order to identify identical objects with differing attributes
 // you must specify the attributes required to uniquely identify
 // your object. Make sure to not include too many attributes, this
 // list is used when caches look for an old version of an object.
 struct nl_object_ops my_ops = {
        ...
        .oo_id_attrs            = MY_ATTR_FOO,
        .oo_compare             = my_obj_compare,
 };

Define Documentation

#define NLHDR_COMMON
Value:
int                     ce_refcnt;      \
        struct nl_object_ops *  ce_ops;         \
        struct nl_cache *       ce_cache;       \
        struct nl_list_head     ce_list;        \
        int                     ce_msgtype;     \
        int                     ce_flags;       \
        uint32_t                ce_mask;

This macro must be included as first member in every object definition to allow objects to be cached.

Definition at line 188 of file object-api.h.

#define AVAILABLE ( A,
B,
ATTR   )     (((A)->ce_mask & (B)->ce_mask) & (ATTR))
Parameters:
A an object
B another object
ATTR attribute bit
Returns:
True if the attribute is available, otherwise false is returned.

Definition at line 205 of file object-api.h.

#define ATTR_MISMATCH ( A,
B,
ATTR,
EXPR   )     (!AVAILABLE(A, B, ATTR) || (EXPR))
Parameters:
A an object
B another object
ATTR attribute bit
EXPR Comparison expression

This function will check if the attribute in question is available in both objects, if not this will count as a mismatch.

If available the function will execute the expression which must return true if the attributes mismatch.

Returns:
True if the attribute mismatch, or false if they match.

Definition at line 222 of file object-api.h.

#define ATTR_DIFF ( LIST,
ATTR,
A,
B,
EXPR   ) 
Value:
({      int diff = 0; \
        if (((LIST) & (ATTR)) && ATTR_MISMATCH(A, B, ATTR, EXPR)) \
                diff = ATTR; \
        diff; })
Parameters:
LIST list of attributes to be compared
ATTR attribute bit
A an object
B another object
EXPR Comparison expression

This function will check if the attribute in question is available in both objects, if not this will count as a mismatch.

If available the function will execute the expression which must return true if the attributes mismatch.

In case the attributes mismatch, the attribute is returned, otherwise 0 is returned.

 diff |= ATTR_DIFF(attrs, MY_ATTR_FOO, a, b, a->foo != b->foo);

Definition at line 245 of file object-api.h.


Generated on 30 Oct 2009 for libnl by  doxygen 1.6.1