netfilter
firewalling, NAT, and packet mangling for linux
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
Object API
Collaboration diagram for Object API:

Data Structures

struct  nl_object_ops
 Object Operations. More...
 

Macros

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

Detailed Description

1) Object Definition
// Define your object starting with the common object header
struct my_obj {
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...
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 {
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);
// 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);
// 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);
}
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.
...
.oo_id_attrs = MY_ATTR_FOO,
.oo_compare = my_obj_compare,
};

Macro Definition Documentation

#define ATTR_DIFF (   LIST,
  ATTR,
  A,
  B,
  EXPR 
)
Value:
({ int diff = 0; \
if (((LIST) & (ATTR)) && ATTR_MISMATCH(A, B, ATTR, EXPR)) \
diff = ATTR; \
diff; })
#define ATTR_MISMATCH(A, B, ATTR, EXPR)
Return true if attributes mismatch.
Definition: object-api.h:229

Return attribute bit if attribute does not match.

  • 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.

1 diff |= ATTR_DIFF(attrs, MY_ATTR_FOO, a, b, a->foo != b->foo);
#define ATTR_MISMATCH (   A,
  B,
  ATTR,
  EXPR 
)
Value:
(AVAILABLE_MISMATCH(A, B, ATTR) || \
(AVAILABLE(A, B, ATTR) && (EXPR)))
#define AVAILABLE_MISMATCH(A, B, ATTR)
Return true if attribute is available in only one of both objects.
Definition: object-api.h:212
#define AVAILABLE(A, B, ATTR)
Return true if attribute is available in both objects.
Definition: object-api.h:201

Return true if attributes mismatch.

  • 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.
#define AVAILABLE (   A,
  B,
  ATTR 
)    (((A)->ce_mask & (B)->ce_mask) & (ATTR))

Return true if attribute is available in both objects.

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

Return true if attribute is available in only one of both objects.

  • A an object
  • B another object
  • ATTR attribute bit
Returns
True if the attribute is available in only one of both objects, otherwise false is returned.
#define NLHDR_COMMON
Value:
int ce_refcnt; \
struct nl_cache * ce_cache; \
int ce_msgtype; \
int ce_flags; \
uint32_t ce_mask;
Object Operations.
Definition: object-api.h:262
Definition: netlink-types.h:74
Definition: list.h:15

Common Object Header.

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