OpenWrt – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 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 |