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