• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/libnl-tiny/include/netlink/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  *
 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 attributes mismatch
205  * @arg A               an object
206  * @arg B               another object
207  * @arg ATTR            attribute bit
208  * @arg EXPR            Comparison expression
209  *
210  * This function will check if the attribute in question is available
211  * in both objects, if not this will count as a mismatch.
212  *
213  * If available the function will execute the expression which must
214  * return true if the attributes mismatch.
215  *
216  * @return True if the attribute mismatch, or false if they match.
217  */
218 #define ATTR_MISMATCH(A, B, ATTR, EXPR) (!AVAILABLE(A, B, ATTR) || (EXPR))
219 
220 /**
221  * Return attribute bit if attribute does not match
222  * @arg LIST            list of attributes to be compared
223  * @arg ATTR            attribute bit
224  * @arg A               an object
225  * @arg B               another object
226  * @arg EXPR            Comparison expression
227  *
228  * This function will check if the attribute in question is available
229  * in both objects, if not this will count as a mismatch.
230  *
231  * If available the function will execute the expression which must
232  * return true if the attributes mismatch.
233  *
234  * In case the attributes mismatch, the attribute is returned, otherwise
235  * 0 is returned.
236  *
237  * @code
238  * diff |= ATTR_DIFF(attrs, MY_ATTR_FOO, a, b, a->foo != b->foo);
239  * @endcode
240  */
241 #define ATTR_DIFF(LIST, ATTR, A, B, EXPR) \
242 ({      int diff = 0; \
243         if (((LIST) & (ATTR)) && ATTR_MISMATCH(A, B, ATTR, EXPR)) \
244                 diff = ATTR; \
245         diff; })
246 
247 /**
248  * Object Operations
249  */
250 struct nl_object;
251 struct nl_object_ops
252 {
253         /**
254          * Unique name of object type
255          *
256          * Must be in the form family/name, e.g. "route/addr"
257          */
258         char *          oo_name;
259 
260         /** Size of object including its header */
261         size_t          oo_size;
262 
263         /* List of attributes needed to uniquely identify the object */
264         uint32_t        oo_id_attrs;
265 
266         /**
267          * Constructor function
268          *
269          * Will be called when a new object of this type is allocated.
270          * Can be used to initialize members such as lists etc.
271          */
272         void  (*oo_constructor)(struct nl_object *);
273 
274         /**
275          * Destructor function
276          *
277          * Will be called when an object is freed. Must free all
278          * resources which may have been allocated as part of this
279          * object.
280          */
281         void  (*oo_free_data)(struct nl_object *);
282 
283         /**
284          * Cloning function
285          *
286          * Will be called when an object needs to be cloned. Please
287          * note that the generic object code will make an exact
288          * copy of the object first, therefore you only need to take
289          * care of members which require reference counting etc.
290          *
291          * May return a negative error code to abort cloning.
292          */
293         int  (*oo_clone)(struct nl_object *, struct nl_object *);
294 
295         /**
296          * Dumping functions
297          *
298          * Will be called when an object is dumped. The implementations
299          * have to use nl_dump(), nl_dump_line(), and nl_new_line() to
300          * dump objects.
301          *
302          * The functions must return the number of lines printed.
303          */
304         void (*oo_dump[NL_DUMP_MAX+1])(struct nl_object *,
305                                        struct nl_dump_params *);
306 
307         /**
308          * Comparison function
309          *
310          * Will be called when two objects of the same type are
311          * compared. It takes the two objects in question, an object
312          * specific bitmask defining which attributes should be
313          * compared and flags to control the behaviour.
314          *
315          * The function must return a bitmask with the relevant bit
316          * set for each attribute that mismatches.
317          */
318         int   (*oo_compare)(struct nl_object *, struct nl_object *,
319                             uint32_t, int);
320 
321 
322         char *(*oo_attrs2str)(int, char *, size_t);
323 };
324 
325 /** @} */
326 
327 #ifdef __cplusplus
328 }
329 #endif
330 
331 #endif
332 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt