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