libnl  3.2.3
/build/buildd/libnl3-3.2.3/include/netlink/object-api.h
00001 /*
00002  * netlink/object-api.c         Object API
00003  *
00004  *      This library is free software; you can redistribute it and/or
00005  *      modify it under the terms of the GNU Lesser General Public
00006  *      License as published by the Free Software Foundation version 2.1
00007  *      of the License.
00008  *
00009  * Copyright (c) 2003-2007 Thomas Graf <tgraf@suug.ch>
00010  */
00011 
00012 #ifndef NETLINK_OBJECT_API_H_
00013 #define NETLINK_OBJECT_API_H_
00014 
00015 #include <netlink/netlink.h>
00016 #include <netlink/utils.h>
00017 
00018 #ifdef __cplusplus
00019 extern "C" {
00020 #endif
00021 
00022 /**
00023  * @ingroup object
00024  * @defgroup object_api Object API
00025  * @brief
00026  *
00027  * @par 1) Object Definition
00028  * @code
00029  * // Define your object starting with the common object header
00030  * struct my_obj {
00031  *      NLHDR_COMMON
00032  *      int             my_data;
00033  * };
00034  *
00035  * // Fill out the object operations structure
00036  * struct nl_object_ops my_ops = {
00037  *      .oo_name        = "my_obj",
00038  *      .oo_size        = sizeof(struct my_obj),
00039  * };
00040  *
00041  * // At this point the object can be allocated, you may want to provide a
00042  * // separate _alloc() function to ease allocting objects of this kind.
00043  * struct nl_object *obj = nl_object_alloc(&my_ops);
00044  *
00045  * // And release it again...
00046  * nl_object_put(obj);
00047  * @endcode
00048  *
00049  * @par 2) Allocating additional data
00050  * @code
00051  * // You may require to allocate additional data and store it inside
00052  * // object, f.e. assuming there is a field `ptr'.
00053  * struct my_obj {
00054  *      NLHDR_COMMON
00055  *      void *          ptr;
00056  * };
00057  *
00058  * // And at some point you may assign allocated data to this field:
00059  * my_obj->ptr = calloc(1, ...);
00060  *
00061  * // In order to not introduce any memory leaks you have to release
00062  * // this data again when the last reference is given back.
00063  * static void my_obj_free_data(struct nl_object *obj)
00064  * {
00065  *      struct my_obj *my_obj = nl_object_priv(obj);
00066  *
00067  *      free(my_obj->ptr);
00068  * }
00069  *
00070  * // Also when the object is cloned, you must ensure for your pointer
00071  * // stay valid even if one of the clones is freed by either making
00072  * // a clone as well or increase the reference count.
00073  * static int my_obj_clone(struct nl_object *src, struct nl_object *dst)
00074  * {
00075  *      struct my_obj *my_src = nl_object_priv(src);
00076  *      struct my_obj *my_dst = nl_object_priv(dst);
00077  *
00078  *      if (src->ptr) {
00079  *              dst->ptr = calloc(1, ...);
00080  *              memcpy(dst->ptr, src->ptr, ...);
00081  *      }
00082  * }
00083  *
00084  * struct nl_object_ops my_ops = {
00085  *      ...
00086  *      .oo_free_data   = my_obj_free_data,
00087  *      .oo_clone       = my_obj_clone,
00088  * };
00089  * @endcode
00090  *
00091  * @par 3) Object Dumping
00092  * @code
00093  * static int my_obj_dump_detailed(struct nl_object *obj,
00094  *                                 struct nl_dump_params *params)
00095  * {
00096  *      struct my_obj *my_obj = nl_object_priv(obj);
00097  *
00098  *      // It is absolutely essential to use nl_dump() when printing
00099  *      // any text to make sure the dumping parameters are respected.
00100  *      nl_dump(params, "Obj Integer: %d\n", my_obj->my_int);
00101  *
00102  *      // Before we can dump the next line, make sure to prefix
00103  *      // this line correctly.
00104  *      nl_new_line(params);
00105  *
00106  *      // You may also split a line into multiple nl_dump() calls.
00107  *      nl_dump(params, "String: %s ", my_obj->my_string);
00108  *      nl_dump(params, "String-2: %s\n", my_obj->another_string);
00109  * }
00110  *
00111  * struct nl_object_ops my_ops = {
00112  *      ...
00113  *      .oo_dump[NL_DUMP_FULL]  = my_obj_dump_detailed,
00114  * };
00115  * @endcode
00116  *
00117  * @par 4) Object Attributes
00118  * @code
00119  * // The concept of object attributes is optional but can ease the typical
00120  * // case of objects that have optional attributes, e.g. a route may have a
00121  * // nexthop assigned but it is not required to.
00122  *
00123  * // The first step to define your object specific bitmask listing all
00124  * // attributes
00125  * #define MY_ATTR_FOO          (1<<0)
00126  * #define MY_ATTR_BAR          (1<<1)
00127  *
00128  * // When assigning an optional attribute to the object, make sure
00129  * // to mark its availability.
00130  * my_obj->foo = 123123;
00131  * my_obj->ce_mask |= MY_ATTR_FOO;
00132  *
00133  * // At any time you may use this mask to check for the availability
00134  * // of the attribute, e.g. while dumping
00135  * if (my_obj->ce_mask & MY_ATTR_FOO)
00136  *      nl_dump(params, "foo %d ", my_obj->foo);
00137  *
00138  * // One of the big advantages of this concept is that it allows for
00139  * // standardized comparisons which make it trivial for caches to
00140  * // identify unique objects by use of unified comparison functions.
00141  * // In order for it to work, your object implementation must provide
00142  * // a comparison function and define a list of attributes which
00143  * // combined together make an object unique.
00144  *
00145  * static int my_obj_compare(struct nl_object *_a, struct nl_object *_b,
00146  *                           uint32_t attrs, int flags)
00147  * {
00148  *      struct my_obj *a = nl_object_priv(_a):
00149  *      struct my_obj *b = nl_object_priv(_b):
00150  *      int diff = 0;
00151  *
00152  *      // We help ourselves in defining our own DIFF macro which will
00153  *      // call ATTR_DIFF() on both objects which will make sure to only
00154  *      // compare the attributes if required.
00155  *      #define MY_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, MY_ATTR_##ATTR, a, b, EXPR)
00156  *
00157  *      // Call our own diff macro for each attribute to build a bitmask
00158  *      // representing the attributes which mismatch.
00159  *      diff |= MY_DIFF(FOO, a->foo != b->foo)
00160  *      diff |= MY_DIFF(BAR, strcmp(a->bar, b->bar))
00161  *
00162  *      return diff;
00163  * }
00164  *
00165  * // In order to identify identical objects with differing attributes
00166  * // you must specify the attributes required to uniquely identify
00167  * // your object. Make sure to not include too many attributes, this
00168  * // list is used when caches look for an old version of an object.
00169  * struct nl_object_ops my_ops = {
00170  *      ...
00171  *      .oo_id_attrs            = MY_ATTR_FOO,
00172  *      .oo_compare             = my_obj_compare,
00173  * };
00174  * @endcode
00175  * @{
00176  */
00177 
00178 /**
00179  * Common Object Header
00180  *
00181  * This macro must be included as first member in every object
00182  * definition to allow objects to be cached.
00183  */
00184 #define NLHDR_COMMON                            \
00185         int                     ce_refcnt;      \
00186         struct nl_object_ops *  ce_ops;         \
00187         struct nl_cache *       ce_cache;       \
00188         struct nl_list_head     ce_list;        \
00189         int                     ce_msgtype;     \
00190         int                     ce_flags;       \
00191         uint32_t                ce_mask;
00192 
00193 struct nl_object
00194 {
00195         NLHDR_COMMON
00196 };
00197 
00198 
00199 /**
00200  * Return true if attribute is available in both objects
00201  * @arg A               an object
00202  * @arg B               another object
00203  * @arg ATTR            attribute bit
00204  *
00205  * @return True if the attribute is available, otherwise false is returned.
00206  */
00207 #define AVAILABLE(A, B, ATTR)           (((A)->ce_mask & (B)->ce_mask) & (ATTR))
00208 
00209 /**
00210  * Return true if attribute is available in only one of both objects
00211  * @arg A               an object
00212  * @arg B               another object
00213  * @arg ATTR            attribute bit
00214  *
00215  * @return True if the attribute is available in only one of both objects,
00216  * otherwise false is returned.
00217  */
00218 #define AVAILABLE_MISMATCH(A, B, ATTR)  (((A)->ce_mask ^ (B)->ce_mask) & (ATTR))
00219 
00220 /**
00221  * Return true if attributes mismatch
00222  * @arg A               an object
00223  * @arg B               another object
00224  * @arg ATTR            attribute bit
00225  * @arg EXPR            Comparison expression
00226  *
00227  * This function will check if the attribute in question is available
00228  * in both objects, if not this will count as a mismatch.
00229  *
00230  * If available the function will execute the expression which must
00231  * return true if the attributes mismatch.
00232  *
00233  * @return True if the attribute mismatch, or false if they match.
00234  */
00235 #define ATTR_MISMATCH(A, B, ATTR, EXPR) (AVAILABLE_MISMATCH(A, B, ATTR) || \
00236                                          (AVAILABLE(A, B, ATTR) && (EXPR)))
00237 
00238 /**
00239  * Return attribute bit if attribute does not match
00240  * @arg LIST            list of attributes to be compared
00241  * @arg ATTR            attribute bit
00242  * @arg A               an object
00243  * @arg B               another object
00244  * @arg EXPR            Comparison expression
00245  *
00246  * This function will check if the attribute in question is available
00247  * in both objects, if not this will count as a mismatch.
00248  *
00249  * If available the function will execute the expression which must
00250  * return true if the attributes mismatch.
00251  *
00252  * In case the attributes mismatch, the attribute is returned, otherwise
00253  * 0 is returned.
00254  *
00255  * @code
00256  * diff |= ATTR_DIFF(attrs, MY_ATTR_FOO, a, b, a->foo != b->foo);
00257  * @endcode
00258  */
00259 #define ATTR_DIFF(LIST, ATTR, A, B, EXPR) \
00260 ({      int diff = 0; \
00261         if (((LIST) & (ATTR)) && ATTR_MISMATCH(A, B, ATTR, EXPR)) \
00262                 diff = ATTR; \
00263         diff; })
00264 
00265 /**
00266  * Object Operations
00267  */
00268 struct nl_object_ops
00269 {
00270         /**
00271          * Unique name of object type
00272          *
00273          * Must be in the form family/name, e.g. "route/addr"
00274          */
00275         char *          oo_name;
00276 
00277         /** Size of object including its header */
00278         size_t          oo_size;
00279 
00280         /* List of attributes needed to uniquely identify the object */
00281         uint32_t        oo_id_attrs;
00282 
00283         /**
00284          * Constructor function
00285          *
00286          * Will be called when a new object of this type is allocated.
00287          * Can be used to initialize members such as lists etc.
00288          */
00289         void  (*oo_constructor)(struct nl_object *);
00290 
00291         /**
00292          * Destructor function
00293          *
00294          * Will be called when an object is freed. Must free all
00295          * resources which may have been allocated as part of this
00296          * object.
00297          */
00298         void  (*oo_free_data)(struct nl_object *);
00299 
00300         /**
00301          * Cloning function
00302          *
00303          * Will be called when an object needs to be cloned. Please
00304          * note that the generic object code will make an exact
00305          * copy of the object first, therefore you only need to take
00306          * care of members which require reference counting etc.
00307          *
00308          * May return a negative error code to abort cloning.
00309          */
00310         int  (*oo_clone)(struct nl_object *, struct nl_object *);
00311 
00312         /**
00313          * Dumping functions
00314          *
00315          * Will be called when an object is dumped. The implementations
00316          * have to use nl_dump(), nl_dump_line(), and nl_new_line() to
00317          * dump objects.
00318          *
00319          * The functions must return the number of lines printed.
00320          */
00321         void (*oo_dump[NL_DUMP_MAX+1])(struct nl_object *,
00322                                        struct nl_dump_params *);
00323 
00324         /**
00325          * Comparison function
00326          *
00327          * Will be called when two objects of the same type are
00328          * compared. It takes the two objects in question, an object
00329          * specific bitmask defining which attributes should be
00330          * compared and flags to control the behaviour.
00331          *
00332          * The function must return a bitmask with the relevant bit
00333          * set for each attribute that mismatches.
00334          */
00335         int   (*oo_compare)(struct nl_object *, struct nl_object *,
00336                             uint32_t, int);
00337 
00338 
00339         char *(*oo_attrs2str)(int, char *, size_t);
00340 };
00341 
00342 /** @} */
00343 
00344 #ifdef __cplusplus
00345 }
00346 #endif
00347 
00348 #endif