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. |
// 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);
// 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, };
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, };
// 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 NLHDR_COMMON |
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)) |
A | an object | |
B | another object | |
ATTR | attribute bit |
Definition at line 205 of file object-api.h.
#define ATTR_MISMATCH | ( | A, | |||
B, | |||||
ATTR, | |||||
EXPR | ) | (!AVAILABLE(A, B, ATTR) || (EXPR)) |
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.
Definition at line 222 of file object-api.h.
#define ATTR_DIFF | ( | LIST, | |||
ATTR, | |||||
A, | |||||
B, | |||||
EXPR | ) |
({ int diff = 0; \ if (((LIST) & (ATTR)) && ATTR_MISMATCH(A, B, ATTR, EXPR)) \ diff = ATTR; \ diff; })
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.