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