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