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