2007-09-15 19:55:38 +02:00
|
|
|
/*
|
2013-01-24 13:51:24 +01:00
|
|
|
* netlink-private/object-api.c Object API
|
2007-09-15 19:55:38 +02:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation version 2.1
|
|
|
|
* of the License.
|
|
|
|
*
|
2013-01-24 13:51:24 +01:00
|
|
|
* Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
|
2007-09-15 19:55:38 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef NETLINK_OBJECT_API_H_
|
|
|
|
#define NETLINK_OBJECT_API_H_
|
|
|
|
|
|
|
|
#include <netlink/netlink.h>
|
|
|
|
#include <netlink/utils.h>
|
2013-01-24 13:51:24 +01:00
|
|
|
#include <netlink/object.h>
|
2007-09-15 19:55:38 +02:00
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @ingroup object
|
|
|
|
* @defgroup object_api Object API
|
|
|
|
* @brief
|
|
|
|
*
|
|
|
|
* @par 1) Object Definition
|
|
|
|
* @code
|
|
|
|
* // 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);
|
|
|
|
* @endcode
|
|
|
|
*
|
|
|
|
* @par 2) Allocating additional data
|
|
|
|
* @code
|
|
|
|
* // 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,
|
|
|
|
* };
|
|
|
|
* @endcode
|
|
|
|
*
|
|
|
|
* @par 3) Object Dumping
|
|
|
|
* @code
|
|
|
|
* 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.
|
2008-05-23 23:45:14 +02:00
|
|
|
* nl_new_line(params);
|
2007-09-15 19:55:38 +02:00
|
|
|
*
|
|
|
|
* // 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,
|
|
|
|
* };
|
|
|
|
* @endcode
|
|
|
|
*
|
|
|
|
* @par 4) Object Attributes
|
|
|
|
* @code
|
|
|
|
* // 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,
|
|
|
|
* };
|
|
|
|
* @endcode
|
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Common Object Header
|
|
|
|
*
|
|
|
|
* This macro must be included as first member in every object
|
|
|
|
* definition to allow objects to be cached.
|
|
|
|
*/
|
|
|
|
#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;
|
|
|
|
|
2011-03-17 14:44:56 +01:00
|
|
|
struct nl_object
|
|
|
|
{
|
|
|
|
NLHDR_COMMON
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2007-09-15 19:55:38 +02:00
|
|
|
/**
|
|
|
|
* Return true if attribute is available in both objects
|
|
|
|
* @arg A an object
|
|
|
|
* @arg B another object
|
|
|
|
* @arg ATTR attribute bit
|
|
|
|
*
|
|
|
|
* @return True if the attribute is available, otherwise false is returned.
|
|
|
|
*/
|
2010-04-07 19:15:40 +02:00
|
|
|
#define AVAILABLE(A, B, ATTR) (((A)->ce_mask & (B)->ce_mask) & (ATTR))
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return true if attribute is available in only one of both objects
|
|
|
|
* @arg A an object
|
|
|
|
* @arg B another object
|
|
|
|
* @arg ATTR attribute bit
|
|
|
|
*
|
|
|
|
* @return True if the attribute is available in only one of both objects,
|
|
|
|
* otherwise false is returned.
|
|
|
|
*/
|
|
|
|
#define AVAILABLE_MISMATCH(A, B, ATTR) (((A)->ce_mask ^ (B)->ce_mask) & (ATTR))
|
2007-09-15 19:55:38 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Return true if attributes mismatch
|
|
|
|
* @arg A an object
|
|
|
|
* @arg B another object
|
|
|
|
* @arg ATTR attribute bit
|
|
|
|
* @arg 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.
|
|
|
|
*
|
|
|
|
* @return True if the attribute mismatch, or false if they match.
|
|
|
|
*/
|
2010-04-07 19:15:40 +02:00
|
|
|
#define ATTR_MISMATCH(A, B, ATTR, EXPR) (AVAILABLE_MISMATCH(A, B, ATTR) || \
|
|
|
|
(AVAILABLE(A, B, ATTR) && (EXPR)))
|
2007-09-15 19:55:38 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Return attribute bit if attribute does not match
|
|
|
|
* @arg LIST list of attributes to be compared
|
|
|
|
* @arg ATTR attribute bit
|
|
|
|
* @arg A an object
|
|
|
|
* @arg B another object
|
|
|
|
* @arg 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.
|
|
|
|
*
|
|
|
|
* @code
|
|
|
|
* diff |= ATTR_DIFF(attrs, MY_ATTR_FOO, a, b, a->foo != b->foo);
|
|
|
|
* @endcode
|
|
|
|
*/
|
|
|
|
#define ATTR_DIFF(LIST, ATTR, A, B, EXPR) \
|
|
|
|
({ int diff = 0; \
|
|
|
|
if (((LIST) & (ATTR)) && ATTR_MISMATCH(A, B, ATTR, EXPR)) \
|
|
|
|
diff = ATTR; \
|
|
|
|
diff; })
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Object Operations
|
|
|
|
*/
|
|
|
|
struct nl_object_ops
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* Unique name of object type
|
|
|
|
*
|
|
|
|
* Must be in the form family/name, e.g. "route/addr"
|
|
|
|
*/
|
|
|
|
char * oo_name;
|
|
|
|
|
|
|
|
/** Size of object including its header */
|
|
|
|
size_t oo_size;
|
|
|
|
|
|
|
|
/* List of attributes needed to uniquely identify the object */
|
|
|
|
uint32_t oo_id_attrs;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor function
|
|
|
|
*
|
|
|
|
* Will be called when a new object of this type is allocated.
|
|
|
|
* Can be used to initialize members such as lists etc.
|
|
|
|
*/
|
|
|
|
void (*oo_constructor)(struct nl_object *);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Destructor function
|
|
|
|
*
|
|
|
|
* Will be called when an object is freed. Must free all
|
|
|
|
* resources which may have been allocated as part of this
|
|
|
|
* object.
|
|
|
|
*/
|
|
|
|
void (*oo_free_data)(struct nl_object *);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Cloning function
|
|
|
|
*
|
|
|
|
* Will be called when an object needs to be cloned. Please
|
|
|
|
* note that the generic object code will make an exact
|
|
|
|
* copy of the object first, therefore you only need to take
|
|
|
|
* care of members which require reference counting etc.
|
|
|
|
*
|
|
|
|
* May return a negative error code to abort cloning.
|
|
|
|
*/
|
|
|
|
int (*oo_clone)(struct nl_object *, struct nl_object *);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Dumping functions
|
|
|
|
*
|
|
|
|
* Will be called when an object is dumped. The implementations
|
|
|
|
* have to use nl_dump(), nl_dump_line(), and nl_new_line() to
|
|
|
|
* dump objects.
|
|
|
|
*
|
|
|
|
* The functions must return the number of lines printed.
|
|
|
|
*/
|
2008-05-23 23:45:14 +02:00
|
|
|
void (*oo_dump[NL_DUMP_MAX+1])(struct nl_object *,
|
|
|
|
struct nl_dump_params *);
|
2007-09-15 19:55:38 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Comparison function
|
|
|
|
*
|
|
|
|
* Will be called when two objects of the same type are
|
|
|
|
* compared. It takes the two objects in question, an object
|
|
|
|
* specific bitmask defining which attributes should be
|
|
|
|
* compared and flags to control the behaviour.
|
|
|
|
*
|
|
|
|
* The function must return a bitmask with the relevant bit
|
|
|
|
* set for each attribute that mismatches.
|
|
|
|
*/
|
|
|
|
int (*oo_compare)(struct nl_object *, struct nl_object *,
|
|
|
|
uint32_t, int);
|
|
|
|
|
|
|
|
|
2012-11-01 14:13:30 -07:00
|
|
|
/**
|
|
|
|
* update function
|
|
|
|
*
|
|
|
|
* Will be called when the object given by first argument
|
|
|
|
* needs to be updated with the contents of the second object
|
|
|
|
*
|
|
|
|
* The function must return 0 for success and error for failure
|
|
|
|
* to update. In case of failure its assumed that the original
|
|
|
|
* object is not touched
|
|
|
|
*/
|
|
|
|
int (*oo_update)(struct nl_object *, struct nl_object *);
|
|
|
|
|
2012-11-09 14:41:32 -08:00
|
|
|
/**
|
|
|
|
* Hash Key generator function
|
|
|
|
*
|
|
|
|
* When called returns a hash key for the object being
|
|
|
|
* referenced. This key will be used by higher level hash functions
|
|
|
|
* to build association lists. Each object type gets to specify
|
|
|
|
* it's own key formulation
|
|
|
|
*/
|
|
|
|
void (*oo_keygen)(struct nl_object *, uint32_t *, uint32_t);
|
|
|
|
|
2007-09-15 19:55:38 +02:00
|
|
|
char *(*oo_attrs2str)(int, char *, size_t);
|
2012-11-01 07:15:28 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Get key attributes by family function
|
|
|
|
*/
|
|
|
|
uint32_t (*oo_id_attrs_get)(struct nl_object *);
|
2007-09-15 19:55:38 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
/** @} */
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif
|