object-api.h 11 KB

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