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 * // Bit 31 for attributes is reserved for 32-bit API. 130 * 131 * // When assigning an optional attribute to the object, make sure 132 * // to mark its availability. 133 * my_obj->foo = 123123; 134 * my_obj->ce_mask |= MY_ATTR_FOO; 135 * 136 * // At any time you may use this mask to check for the availability 137 * // of the attribute, e.g. while dumping 138 * if (my_obj->ce_mask & MY_ATTR_FOO) 139 * nl_dump(params, "foo %d ", my_obj->foo); 140 * 141 * // One of the big advantages of this concept is that it allows for 142 * // standardized comparisons which make it trivial for caches to 143 * // identify unique objects by use of unified comparison functions. 144 * // In order for it to work, your object implementation must provide 145 * // a comparison function and define a list of attributes which 146 * // combined together make an object unique. 147 * 148 * static int my_obj_compare(struct nl_object *_a, struct nl_object *_b, 149 * uint32_t attrs, int flags) 150 * { 151 * struct my_obj *a = nl_object_priv(_a): 152 * struct my_obj *b = nl_object_priv(_b): 153 * int diff = 0; 154 * 155 * // We help ourselves in defining our own DIFF macro which will 156 * // call ATTR_DIFF() on both objects which will make sure to only 157 * // compare the attributes if required. 158 * #define MY_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, MY_ATTR_##ATTR, a, b, EXPR) 159 * 160 * // Call our own diff macro for each attribute to build a bitmask 161 * // representing the attributes which mismatch. 162 * diff |= MY_DIFF(FOO, a->foo != b->foo) 163 * diff |= MY_DIFF(BAR, strcmp(a->bar, b->bar)) 164 * 165 * return diff; 166 * } 167 * 168 * // In order to identify identical objects with differing attributes 169 * // you must specify the attributes required to uniquely identify 170 * // your object. Make sure to not include too many attributes, this 171 * // list is used when caches look for an old version of an object. 172 * struct nl_object_ops my_ops = { 173 * ... 174 * .oo_id_attrs = MY_ATTR_FOO, 175 * .oo_compare = my_obj_compare, 176 * }; 177 * @endcode 178 * @{ 179 */ 180 181 /** 182 * Common Object Header 183 * 184 * This macro must be included as first member in every object 185 * definition to allow objects to be cached. 186 */ 187 #define NLHDR_COMMON \ 188 int ce_refcnt; \ 189 struct nl_object_ops * ce_ops; \ 190 struct nl_cache * ce_cache; \ 191 struct nl_list_head ce_list; \ 192 int ce_msgtype; \ 193 int ce_flags; \ 194 uint64_t ce_mask; 195 196 struct nl_object 197 { 198 NLHDR_COMMON 199 }; 200 201 202 /** 203 * Return true if attribute is available in both objects 204 * @arg A an object 205 * @arg B another object 206 * @arg ATTR attribute bit 207 * 208 * @return True if the attribute is available, otherwise false is returned. 209 */ 210 #define AVAILABLE(A, B, ATTR) (((A)->ce_mask & (B)->ce_mask) & (ATTR)) 211 212 /** 213 * Return true if attribute is available in only one of both objects 214 * @arg A an object 215 * @arg B another object 216 * @arg ATTR attribute bit 217 * 218 * @return True if the attribute is available in only one of both objects, 219 * otherwise false is returned. 220 */ 221 #define AVAILABLE_MISMATCH(A, B, ATTR) (((A)->ce_mask ^ (B)->ce_mask) & (ATTR)) 222 223 /** 224 * Return true if attributes mismatch 225 * @arg A an object 226 * @arg B another object 227 * @arg ATTR attribute bit 228 * @arg EXPR Comparison expression 229 * 230 * This function will check if the attribute in question is available 231 * in both objects, if not this will count as a mismatch. 232 * 233 * If available the function will execute the expression which must 234 * return true if the attributes mismatch. 235 * 236 * @return True if the attribute mismatch, or false if they match. 237 */ 238 #define ATTR_MISMATCH(A, B, ATTR, EXPR) (AVAILABLE_MISMATCH(A, B, ATTR) || \ 239 (AVAILABLE(A, B, ATTR) && (EXPR))) 240 241 /** 242 * Return attribute bit if attribute does not match 243 * @arg LIST list of attributes to be compared 244 * @arg ATTR attribute bit 245 * @arg A an object 246 * @arg B another object 247 * @arg EXPR Comparison expression 248 * 249 * This function will check if the attribute in question is available 250 * in both objects, if not this will count as a mismatch. 251 * 252 * If available the function will execute the expression which must 253 * return true if the attributes mismatch. 254 * 255 * In case the attributes mismatch, the attribute is returned, otherwise 256 * 0 is returned. 257 * 258 * @code 259 * diff |= ATTR_DIFF(attrs, MY_ATTR_FOO, a, b, a->foo != b->foo); 260 * @endcode 261 */ 262 #define ATTR_DIFF(LIST, ATTR, A, B, EXPR) \ 263 ({ uint64_t diff = 0; \ 264 if (((LIST) & (ATTR)) && ATTR_MISMATCH(A, B, ATTR, EXPR)) \ 265 diff = ATTR; \ 266 diff; }) 267 268 /** 269 * Object Operations 270 */ 271 struct nl_object_ops 272 { 273 /** 274 * Unique name of object type 275 * 276 * Must be in the form family/name, e.g. "route/addr" 277 */ 278 char * oo_name; 279 280 /** Size of object including its header */ 281 size_t oo_size; 282 283 /* List of attributes needed to uniquely identify the object */ 284 uint32_t oo_id_attrs; 285 286 /** 287 * Constructor function 288 * 289 * Will be called when a new object of this type is allocated. 290 * Can be used to initialize members such as lists etc. 291 */ 292 void (*oo_constructor)(struct nl_object *); 293 294 /** 295 * Destructor function 296 * 297 * Will be called when an object is freed. Must free all 298 * resources which may have been allocated as part of this 299 * object. 300 */ 301 void (*oo_free_data)(struct nl_object *); 302 303 /** 304 * Cloning function 305 * 306 * Will be called when an object needs to be cloned. Please 307 * note that the generic object code will make an exact 308 * copy of the object first, therefore you only need to take 309 * care of members which require reference counting etc. 310 * 311 * May return a negative error code to abort cloning. 312 */ 313 int (*oo_clone)(struct nl_object *, struct nl_object *); 314 315 /** 316 * Dumping functions 317 * 318 * Will be called when an object is dumped. The implementations 319 * have to use nl_dump(), nl_dump_line(), and nl_new_line() to 320 * dump objects. 321 * 322 * The functions must return the number of lines printed. 323 */ 324 void (*oo_dump[NL_DUMP_MAX+1])(struct nl_object *, 325 struct nl_dump_params *); 326 327 /** 328 * Comparison function 329 * 330 * Will be called when two objects of the same type are 331 * compared. It takes the two objects in question, an object 332 * specific bitmask defining which attributes should be 333 * compared and flags to control the behaviour. 334 * 335 * The function must return a bitmask with the relevant bit 336 * set for each attribute that mismatches. 337 */ 338 uint64_t (*oo_compare)(struct nl_object *, struct nl_object *, 339 uint64_t, int); 340 341 342 /** 343 * update function 344 * 345 * Will be called when the object given by first argument 346 * needs to be updated with the contents of the second object 347 * 348 * The function must return 0 for success and error for failure 349 * to update. In case of failure its assumed that the original 350 * object is not touched 351 */ 352 int (*oo_update)(struct nl_object *, struct nl_object *); 353 354 /** 355 * Hash Key generator function 356 * 357 * When called returns a hash key for the object being 358 * referenced. This key will be used by higher level hash functions 359 * to build association lists. Each object type gets to specify 360 * it's own key formulation 361 */ 362 void (*oo_keygen)(struct nl_object *, uint32_t *, uint32_t); 363 364 char *(*oo_attrs2str)(int, char *, size_t); 365 366 /** 367 * Get key attributes by family function 368 */ 369 uint32_t (*oo_id_attrs_get)(struct nl_object *); 370 }; 371 372 /** @} */ 373 374 #ifdef __cplusplus 375 } 376 #endif 377 378 #endif 379