xref: /aosp_15_r20/external/libnl/include/nl-priv-dynamic-core/object-api.h (revision 4dc78e53d49367fa8e61b07018507c90983a077d)
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