Home | History | Annotate | Download | only in netlink-private
      1 /*
      2  * netlink-private/object-api.c		Object API
      3  *
      4  *	This library is free software; you can redistribute it and/or
      5  *	modify it under the terms of the GNU Lesser General Public
      6  *	License as published by the Free Software Foundation version 2.1
      7  *	of the License.
      8  *
      9  * Copyright (c) 2003-2013 Thomas Graf <tgraf (at) suug.ch>
     10  */
     11 
     12 #ifndef NETLINK_OBJECT_API_H_
     13 #define NETLINK_OBJECT_API_H_
     14 
     15 #include <netlink/netlink.h>
     16 #include <netlink/utils.h>
     17 #include <netlink/object.h>
     18 
     19 #ifdef __cplusplus
     20 extern "C" {
     21 #endif
     22 
     23 /**
     24  * @ingroup object
     25  * @defgroup object_api Object API
     26  * @brief
     27  *
     28  * @par 1) Object Definition
     29  * @code
     30  * // Define your object starting with the common object header
     31  * struct my_obj {
     32  * 	NLHDR_COMMON
     33  * 	int		my_data;
     34  * };
     35  *
     36  * // Fill out the object operations structure
     37  * struct nl_object_ops my_ops = {
     38  * 	.oo_name	= "my_obj",
     39  * 	.oo_size	= sizeof(struct my_obj),
     40  * };
     41  *
     42  * // At this point the object can be allocated, you may want to provide a
     43  * // separate _alloc() function to ease allocting objects of this kind.
     44  * struct nl_object *obj = nl_object_alloc(&my_ops);
     45  *
     46  * // And release it again...
     47  * nl_object_put(obj);
     48  * @endcode
     49  *
     50  * @par 2) Allocating additional data
     51  * @code
     52  * // You may require to allocate additional data and store it inside
     53  * // object, f.e. assuming there is a field `ptr'.
     54  * struct my_obj {
     55  * 	NLHDR_COMMON
     56  * 	void *		ptr;
     57  * };
     58  *
     59  * // And at some point you may assign allocated data to this field:
     60  * my_obj->ptr = calloc(1, ...);
     61  *
     62  * // In order to not introduce any memory leaks you have to release
     63  * // this data again when the last reference is given back.
     64  * static void my_obj_free_data(struct nl_object *obj)
     65  * {
     66  * 	struct my_obj *my_obj = nl_object_priv(obj);
     67  *
     68  * 	free(my_obj->ptr);
     69  * }
     70  *
     71  * // Also when the object is cloned, you must ensure for your pointer
     72  * // stay valid even if one of the clones is freed by either making
     73  * // a clone as well or increase the reference count.
     74  * static int my_obj_clone(struct nl_object *src, struct nl_object *dst)
     75  * {
     76  * 	struct my_obj *my_src = nl_object_priv(src);
     77  * 	struct my_obj *my_dst = nl_object_priv(dst);
     78  *
     79  * 	if (src->ptr) {
     80  * 		dst->ptr = calloc(1, ...);
     81  * 		memcpy(dst->ptr, src->ptr, ...);
     82  * 	}
     83  * }
     84  *
     85  * struct nl_object_ops my_ops = {
     86  * 	...
     87  * 	.oo_free_data	= my_obj_free_data,
     88  * 	.oo_clone	= my_obj_clone,
     89  * };
     90  * @endcode
     91  *
     92  * @par 3) Object Dumping
     93  * @code
     94  * static int my_obj_dump_detailed(struct nl_object *obj,
     95  * 				   struct nl_dump_params *params)
     96  * {
     97  * 	struct my_obj *my_obj = nl_object_priv(obj);
     98  *
     99  * 	// It is absolutely essential to use nl_dump() when printing
    100  *	// any text to make sure the dumping parameters are respected.
    101  * 	nl_dump(params, "Obj Integer: %d\n", my_obj->my_int);
    102  *
    103  * 	// Before we can dump the next line, make sure to prefix
    104  *	// this line correctly.
    105  * 	nl_new_line(params);
    106  *
    107  * 	// You may also split a line into multiple nl_dump() calls.
    108  * 	nl_dump(params, "String: %s ", my_obj->my_string);
    109  * 	nl_dump(params, "String-2: %s\n", my_obj->another_string);
    110  * }
    111  *
    112  * struct nl_object_ops my_ops = {
    113  * 	...
    114  * 	.oo_dump[NL_DUMP_FULL]	= my_obj_dump_detailed,
    115  * };
    116  * @endcode
    117  *
    118  * @par 4) Object Attributes
    119  * @code
    120  * // The concept of object attributes is optional but can ease the typical
    121  * // case of objects that have optional attributes, e.g. a route may have a
    122  * // nexthop assigned but it is not required to.
    123  *
    124  * // The first step to define your object specific bitmask listing all
    125  * // attributes
    126  * #define MY_ATTR_FOO		(1<<0)
    127  * #define MY_ATTR_BAR		(1<<1)
    128  *
    129  * // When assigning an optional attribute to the object, make sure
    130  * // to mark its availability.
    131  * my_obj->foo = 123123;
    132  * my_obj->ce_mask |= MY_ATTR_FOO;
    133  *
    134  * // At any time you may use this mask to check for the availability
    135  * // of the attribute, e.g. while dumping
    136  * if (my_obj->ce_mask & MY_ATTR_FOO)
    137  * 	nl_dump(params, "foo %d ", my_obj->foo);
    138  *
    139  * // One of the big advantages of this concept is that it allows for
    140  * // standardized comparisons which make it trivial for caches to
    141  * // identify unique objects by use of unified comparison functions.
    142  * // In order for it to work, your object implementation must provide
    143  * // a comparison function and define a list of attributes which
    144  * // combined together make an object unique.
    145  *
    146  * static int my_obj_compare(struct nl_object *_a, struct nl_object *_b,
    147  * 			     uint32_t attrs, int flags)
    148  * {
    149  * 	struct my_obj *a = nl_object_priv(_a):
    150  * 	struct my_obj *b = nl_object_priv(_b):
    151  * 	int diff = 0;
    152  *
    153  * 	// We help ourselves in defining our own DIFF macro which will
    154  *	// call ATTR_DIFF() on both objects which will make sure to only
    155  *	// compare the attributes if required.
    156  * 	#define MY_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, MY_ATTR_##ATTR, a, b, EXPR)
    157  *
    158  * 	// Call our own diff macro for each attribute to build a bitmask
    159  *	// representing the attributes which mismatch.
    160  * 	diff |= MY_DIFF(FOO, a->foo != b->foo)
    161  * 	diff |= MY_DIFF(BAR, strcmp(a->bar, b->bar))
    162  *
    163  * 	return diff;
    164  * }
    165  *
    166  * // In order to identify identical objects with differing attributes
    167  * // you must specify the attributes required to uniquely identify
    168  * // your object. Make sure to not include too many attributes, this
    169  * // list is used when caches look for an old version of an object.
    170  * struct nl_object_ops my_ops = {
    171  * 	...
    172  * 	.oo_id_attrs		= MY_ATTR_FOO,
    173  * 	.oo_compare		= my_obj_compare,
    174  * };
    175  * @endcode
    176  * @{
    177  */
    178 
    179 /**
    180  * Common Object Header
    181  *
    182  * This macro must be included as first member in every object
    183  * definition to allow objects to be cached.
    184  */
    185 #define NLHDR_COMMON				\
    186 	int			ce_refcnt;	\
    187 	struct nl_object_ops *	ce_ops;		\
    188 	struct nl_cache *	ce_cache;	\
    189 	struct nl_list_head	ce_list;	\
    190 	int			ce_msgtype;	\
    191 	int			ce_flags;	\
    192 	uint32_t		ce_mask;
    193 
    194 struct nl_object
    195 {
    196 	NLHDR_COMMON
    197 };
    198 
    199 
    200 /**
    201  * Return true if attribute is available in both objects
    202  * @arg A		an object
    203  * @arg B		another object
    204  * @arg ATTR		attribute bit
    205  *
    206  * @return True if the attribute is available, otherwise false is returned.
    207  */
    208 #define AVAILABLE(A, B, ATTR)		(((A)->ce_mask & (B)->ce_mask) & (ATTR))
    209 
    210 /**
    211  * Return true if attribute is available in only one of both objects
    212  * @arg A		an object
    213  * @arg B		another object
    214  * @arg ATTR		attribute bit
    215  *
    216  * @return True if the attribute is available in only one of both objects,
    217  * otherwise false is returned.
    218  */
    219 #define AVAILABLE_MISMATCH(A, B, ATTR)	(((A)->ce_mask ^ (B)->ce_mask) & (ATTR))
    220 
    221 /**
    222  * Return true if attributes mismatch
    223  * @arg A		an object
    224  * @arg B		another object
    225  * @arg ATTR		attribute bit
    226  * @arg EXPR		Comparison expression
    227  *
    228  * This function will check if the attribute in question is available
    229  * in both objects, if not this will count as a mismatch.
    230  *
    231  * If available the function will execute the expression which must
    232  * return true if the attributes mismatch.
    233  *
    234  * @return True if the attribute mismatch, or false if they match.
    235  */
    236 #define ATTR_MISMATCH(A, B, ATTR, EXPR)	(AVAILABLE_MISMATCH(A, B, ATTR) || \
    237 					 (AVAILABLE(A, B, ATTR) && (EXPR)))
    238 
    239 /**
    240  * Return attribute bit if attribute does not match
    241  * @arg LIST		list of attributes to be compared
    242  * @arg ATTR		attribute bit
    243  * @arg A		an object
    244  * @arg B		another object
    245  * @arg EXPR		Comparison expression
    246  *
    247  * This function will check if the attribute in question is available
    248  * in both objects, if not this will count as a mismatch.
    249  *
    250  * If available the function will execute the expression which must
    251  * return true if the attributes mismatch.
    252  *
    253  * In case the attributes mismatch, the attribute is returned, otherwise
    254  * 0 is returned.
    255  *
    256  * @code
    257  * diff |= ATTR_DIFF(attrs, MY_ATTR_FOO, a, b, a->foo != b->foo);
    258  * @endcode
    259  */
    260 #define ATTR_DIFF(LIST, ATTR, A, B, EXPR) \
    261 ({	int diff = 0; \
    262 	if (((LIST) & (ATTR)) && ATTR_MISMATCH(A, B, ATTR, EXPR)) \
    263 		diff = ATTR; \
    264 	diff; })
    265 
    266 /**
    267  * Object Operations
    268  */
    269 struct nl_object_ops
    270 {
    271 	/**
    272 	 * Unique name of object type
    273 	 *
    274 	 * Must be in the form family/name, e.g. "route/addr"
    275 	 */
    276 	char *		oo_name;
    277 
    278 	/** Size of object including its header */
    279 	size_t		oo_size;
    280 
    281 	/* List of attributes needed to uniquely identify the object */
    282 	uint32_t	oo_id_attrs;
    283 
    284 	/**
    285 	 * Constructor function
    286 	 *
    287 	 * Will be called when a new object of this type is allocated.
    288 	 * Can be used to initialize members such as lists etc.
    289 	 */
    290 	void  (*oo_constructor)(struct nl_object *);
    291 
    292 	/**
    293 	 * Destructor function
    294 	 *
    295 	 * Will be called when an object is freed. Must free all
    296 	 * resources which may have been allocated as part of this
    297 	 * object.
    298 	 */
    299 	void  (*oo_free_data)(struct nl_object *);
    300 
    301 	/**
    302 	 * Cloning function
    303 	 *
    304 	 * Will be called when an object needs to be cloned. Please
    305 	 * note that the generic object code will make an exact
    306 	 * copy of the object first, therefore you only need to take
    307 	 * care of members which require reference counting etc.
    308 	 *
    309 	 * May return a negative error code to abort cloning.
    310 	 */
    311 	int  (*oo_clone)(struct nl_object *, struct nl_object *);
    312 
    313 	/**
    314 	 * Dumping functions
    315 	 *
    316 	 * Will be called when an object is dumped. The implementations
    317 	 * have to use nl_dump(), nl_dump_line(), and nl_new_line() to
    318 	 * dump objects.
    319 	 *
    320 	 * The functions must return the number of lines printed.
    321 	 */
    322 	void (*oo_dump[NL_DUMP_MAX+1])(struct nl_object *,
    323 				       struct nl_dump_params *);
    324 
    325 	/**
    326 	 * Comparison function
    327 	 *
    328 	 * Will be called when two objects of the same type are
    329 	 * compared. It takes the two objects in question, an object
    330 	 * specific bitmask defining which attributes should be
    331 	 * compared and flags to control the behaviour.
    332 	 *
    333 	 * The function must return a bitmask with the relevant bit
    334 	 * set for each attribute that mismatches.
    335 	 */
    336 	int   (*oo_compare)(struct nl_object *, struct nl_object *,
    337 			    uint32_t, int);
    338 
    339 
    340 	/**
    341 	 * update function
    342 	 *
    343 	 * Will be called when the object given by first argument
    344 	 * needs to be updated with the contents of the second object
    345 	 *
    346 	 * The function must return 0 for success and error for failure
    347 	 * to update. In case of failure its assumed that the original
    348 	 * object is not touched
    349 	 */
    350 	int   (*oo_update)(struct nl_object *, struct nl_object *);
    351 
    352 	/**
    353 	 * Hash Key generator function
    354 	 *
    355 	 * When called returns a hash key for the object being
    356 	 * referenced. This key will be used by higher level hash functions
    357 	 * to build association lists. Each object type gets to specify
    358 	 * it's own key formulation
    359 	 */
    360 	void   (*oo_keygen)(struct nl_object *, uint32_t *, uint32_t);
    361 
    362 	char *(*oo_attrs2str)(int, char *, size_t);
    363 
    364 	/**
    365 	 * Get key attributes by family function
    366 	 */
    367 	uint32_t   (*oo_id_attrs_get)(struct nl_object *);
    368 };
    369 
    370 /** @} */
    371 
    372 #ifdef __cplusplus
    373 }
    374 #endif
    375 
    376 #endif
    377