libnl
3.2.3
|
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