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