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@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