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