libnl  1.1.4
object-api.h
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  * int line = 1; // We will print at least one line for sure
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, line++);
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  * // Return the number of lines dumped
112  * return line;
113  * }
114  *
115  * struct nl_object_ops my_ops = {
116  * ...
117  * .oo_dump[NL_DUMP_FULL] = my_obj_dump_detailed,
118  * };
119  * @endcode
120  *
121  * @par 4) Object Attributes
122  * @code
123  * // The concept of object attributes is optional but can ease the typical
124  * // case of objects that have optional attributes, e.g. a route may have a
125  * // nexthop assigned but it is not required to.
126  *
127  * // The first step to define your object specific bitmask listing all
128  * // attributes
129  * #define MY_ATTR_FOO (1<<0)
130  * #define MY_ATTR_BAR (1<<1)
131  *
132  * // When assigning an optional attribute to the object, make sure
133  * // to mark its availability.
134  * my_obj->foo = 123123;
135  * my_obj->ce_mask |= MY_ATTR_FOO;
136  *
137  * // At any time you may use this mask to check for the availability
138  * // of the attribute, e.g. while dumping
139  * if (my_obj->ce_mask & MY_ATTR_FOO)
140  * nl_dump(params, "foo %d ", my_obj->foo);
141  *
142  * // One of the big advantages of this concept is that it allows for
143  * // standardized comparisons which make it trivial for caches to
144  * // identify unique objects by use of unified comparison functions.
145  * // In order for it to work, your object implementation must provide
146  * // a comparison function and define a list of attributes which
147  * // combined together make an object unique.
148  *
149  * static int my_obj_compare(struct nl_object *_a, struct nl_object *_b,
150  * uint32_t attrs, int flags)
151  * {
152  * struct my_obj *a = nl_object_priv(_a):
153  * struct my_obj *b = nl_object_priv(_b):
154  * int diff = 0;
155  *
156  * // We help ourselves in defining our own DIFF macro which will
157  * // call ATTR_DIFF() on both objects which will make sure to only
158  * // compare the attributes if required.
159  * #define MY_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, MY_ATTR_##ATTR, a, b, EXPR)
160  *
161  * // Call our own diff macro for each attribute to build a bitmask
162  * // representing the attributes which mismatch.
163  * diff |= MY_DIFF(FOO, a->foo != b->foo)
164  * diff |= MY_DIFF(BAR, strcmp(a->bar, b->bar))
165  *
166  * return diff;
167  * }
168  *
169  * // In order to identify identical objects with differing attributes
170  * // you must specify the attributes required to uniquely identify
171  * // your object. Make sure to not include too many attributes, this
172  * // list is used when caches look for an old version of an object.
173  * struct nl_object_ops my_ops = {
174  * ...
175  * .oo_id_attrs = MY_ATTR_FOO,
176  * .oo_compare = my_obj_compare,
177  * };
178  * @endcode
179  * @{
180  */
181 
182 /**
183  * Common Object Header
184  *
185  * This macro must be included as first member in every object
186  * definition to allow objects to be cached.
187  */
188 #define NLHDR_COMMON \
189  int ce_refcnt; \
190  struct nl_object_ops * ce_ops; \
191  struct nl_cache * ce_cache; \
192  struct nl_list_head ce_list; \
193  int ce_msgtype; \
194  int ce_flags; \
195  uint32_t ce_mask;
196 
197 /**
198  * Return true if attribute is available in both objects
199  * @arg A an object
200  * @arg B another object
201  * @arg ATTR attribute bit
202  *
203  * @return True if the attribute is available, otherwise false is returned.
204  */
205 #define AVAILABLE(A, B, ATTR) (((A)->ce_mask & (B)->ce_mask) & (ATTR))
206 
207 /**
208  * Return true if attributes mismatch
209  * @arg A an object
210  * @arg B another object
211  * @arg ATTR attribute bit
212  * @arg EXPR Comparison expression
213  *
214  * This function will check if the attribute in question is available
215  * in both objects, if not this will count as a mismatch.
216  *
217  * If available the function will execute the expression which must
218  * return true if the attributes mismatch.
219  *
220  * @return True if the attribute mismatch, or false if they match.
221  */
222 #define ATTR_MISMATCH(A, B, ATTR, EXPR) (!AVAILABLE(A, B, ATTR) || (EXPR))
223 
224 /**
225  * Return attribute bit if attribute does not match
226  * @arg LIST list of attributes to be compared
227  * @arg ATTR attribute bit
228  * @arg A an object
229  * @arg B another object
230  * @arg EXPR Comparison expression
231  *
232  * This function will check if the attribute in question is available
233  * in both objects, if not this will count as a mismatch.
234  *
235  * If available the function will execute the expression which must
236  * return true if the attributes mismatch.
237  *
238  * In case the attributes mismatch, the attribute is returned, otherwise
239  * 0 is returned.
240  *
241  * @code
242  * diff |= ATTR_DIFF(attrs, MY_ATTR_FOO, a, b, a->foo != b->foo);
243  * @endcode
244  */
245 #define ATTR_DIFF(LIST, ATTR, A, B, EXPR) \
246 ({ int diff = 0; \
247  if (((LIST) & (ATTR)) && ATTR_MISMATCH(A, B, ATTR, EXPR)) \
248  diff = ATTR; \
249  diff; })
250 
251 /**
252  * Object Operations
253  */
255 {
256  /**
257  * Unique name of object type
258  *
259  * Must be in the form family/name, e.g. "route/addr"
260  */
261  char * oo_name;
262 
263  /** Size of object including its header */
264  size_t oo_size;
265 
266  /* List of attributes needed to uniquely identify the object */
267  uint32_t oo_id_attrs;
268 
269  /**
270  * Constructor function
271  *
272  * Will be called when a new object of this type is allocated.
273  * Can be used to initialize members such as lists etc.
274  */
275  void (*oo_constructor)(struct nl_object *);
276 
277  /**
278  * Destructor function
279  *
280  * Will be called when an object is freed. Must free all
281  * resources which may have been allocated as part of this
282  * object.
283  */
284  void (*oo_free_data)(struct nl_object *);
285 
286  /**
287  * Cloning function
288  *
289  * Will be called when an object needs to be cloned. Please
290  * note that the generic object code will make an exact
291  * copy of the object first, therefore you only need to take
292  * care of members which require reference counting etc.
293  *
294  * May return a negative error code to abort cloning.
295  */
296  int (*oo_clone)(struct nl_object *, struct nl_object *);
297 
298  /**
299  * Dumping functions
300  *
301  * Will be called when an object is dumped. The implementations
302  * have to use nl_dump(), nl_dump_line(), and nl_new_line() to
303  * dump objects.
304  *
305  * The functions must return the number of lines printed.
306  */
307  int (*oo_dump[NL_DUMP_MAX+1])(struct nl_object *,
308  struct nl_dump_params *);
309 
310  /**
311  * Comparison function
312  *
313  * Will be called when two objects of the same type are
314  * compared. It takes the two objects in question, an object
315  * specific bitmask defining which attributes should be
316  * compared and flags to control the behaviour.
317  *
318  * The function must return a bitmask with the relevant bit
319  * set for each attribute that mismatches.
320  */
321  int (*oo_compare)(struct nl_object *, struct nl_object *,
322  uint32_t, int);
323 
324 
325  char *(*oo_attrs2str)(int, char *, size_t);
326 };
327 
328 /** @} */
329 
330 #ifdef __cplusplus
331 }
332 #endif
333 
334 #endif
void(* oo_constructor)(struct nl_object *)
Constructor function.
Definition: object-api.h:275
size_t oo_size
Size of object including its header.
Definition: object-api.h:264
void(* oo_free_data)(struct nl_object *)
Destructor function.
Definition: object-api.h:284
int(* oo_dump[NL_DUMP_MAX+1])(struct nl_object *, struct nl_dump_params *)
Dumping functions.
Definition: object-api.h:307
Object Operations.
Definition: object-api.h:254
int(* oo_compare)(struct nl_object *, struct nl_object *, uint32_t, int)
Comparison function.
Definition: object-api.h:321
int(* oo_clone)(struct nl_object *, struct nl_object *)
Cloning function.
Definition: object-api.h:296
Dumping parameters.
Definition: types.h:36
char * oo_name
Unique name of object type.
Definition: object-api.h:261