libnl  3.2.7
cache.c
1 /*
2  * lib/cache.c Caching Module
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-2008 Thomas Graf <tgraf@suug.ch>
10  */
11 
12 /**
13  * @ingroup cache_mngt
14  * @defgroup cache Cache
15  *
16  * @code
17  * Cache Management | | Type Specific Cache Operations
18  *
19  * | | +----------------+ +------------+
20  * | request update | | msg_parser |
21  * | | +----------------+ +------------+
22  * +- - - - -^- - - - - - - -^- -|- - - -
23  * nl_cache_update: | | | |
24  * 1) --------- co_request_update ------+ | |
25  * | | |
26  * 2) destroy old cache +----------- pp_cb ---------|---+
27  * | | |
28  * 3) ---------- nl_recvmsgs ----------+ +- cb_valid -+
29  * +--------------+ | | | |
30  * | nl_cache_add |<-----+ + - - -v- -|- - - - - - - - - - -
31  * +--------------+ | | +-------------+
32  * | nl_recvmsgs |
33  * | | +-----|-^-----+
34  * +---v-|---+
35  * | | | nl_recv |
36  * +---------+
37  * | | Core Netlink
38  * @endcode
39  *
40  * @{
41  */
42 
43 #include <netlink-local.h>
44 #include <netlink/netlink.h>
45 #include <netlink/cache.h>
46 #include <netlink/object.h>
47 #include <netlink/utils.h>
48 
49 /**
50  * @name Access Functions
51  * @{
52  */
53 
54 /**
55  * Return the number of items in the cache
56  * @arg cache cache handle
57  */
58 int nl_cache_nitems(struct nl_cache *cache)
59 {
60  return cache->c_nitems;
61 }
62 
63 /**
64  * Return the number of items matching a filter in the cache
65  * @arg cache Cache object.
66  * @arg filter Filter object.
67  */
68 int nl_cache_nitems_filter(struct nl_cache *cache, struct nl_object *filter)
69 {
70  struct nl_object *obj;
71  int nitems = 0;
72 
73  if (cache->c_ops == NULL)
74  BUG();
75 
76  nl_list_for_each_entry(obj, &cache->c_items, ce_list) {
77  if (filter && !nl_object_match_filter(obj, filter))
78  continue;
79 
80  nitems++;
81  }
82 
83  return nitems;
84 }
85 
86 /**
87  * Returns \b true if the cache is empty.
88  * @arg cache Cache to check
89  * @return \a true if the cache is empty, otherwise \b false is returned.
90  */
91 int nl_cache_is_empty(struct nl_cache *cache)
92 {
93  return nl_list_empty(&cache->c_items);
94 }
95 
96 /**
97  * Return the operations set of the cache
98  * @arg cache cache handle
99  */
100 struct nl_cache_ops *nl_cache_get_ops(struct nl_cache *cache)
101 {
102  return cache->c_ops;
103 }
104 
105 /**
106  * Return the first element in the cache
107  * @arg cache cache handle
108  */
109 struct nl_object *nl_cache_get_first(struct nl_cache *cache)
110 {
111  if (nl_list_empty(&cache->c_items))
112  return NULL;
113 
114  return nl_list_entry(cache->c_items.next,
115  struct nl_object, ce_list);
116 }
117 
118 /**
119  * Return the last element in the cache
120  * @arg cache cache handle
121  */
122 struct nl_object *nl_cache_get_last(struct nl_cache *cache)
123 {
124  if (nl_list_empty(&cache->c_items))
125  return NULL;
126 
127  return nl_list_entry(cache->c_items.prev,
128  struct nl_object, ce_list);
129 }
130 
131 /**
132  * Return the next element in the cache
133  * @arg obj current object
134  */
136 {
137  if (nl_list_at_tail(obj, &obj->ce_cache->c_items, ce_list))
138  return NULL;
139  else
140  return nl_list_entry(obj->ce_list.next,
141  struct nl_object, ce_list);
142 }
143 
144 /**
145  * Return the previous element in the cache
146  * @arg obj current object
147  */
149 {
150  if (nl_list_at_head(obj, &obj->ce_cache->c_items, ce_list))
151  return NULL;
152  else
153  return nl_list_entry(obj->ce_list.prev,
154  struct nl_object, ce_list);
155 }
156 
157 /** @} */
158 
159 /**
160  * @name Cache Allocation/Deletion
161  * @{
162  */
163 
164 /**
165  * Allocate new cache
166  * @arg ops Cache operations
167  *
168  * Allocate and initialize a new cache based on the cache operations
169  * provided.
170  *
171  * @return Allocated cache or NULL if allocation failed.
172  */
173 struct nl_cache *nl_cache_alloc(struct nl_cache_ops *ops)
174 {
175  struct nl_cache *cache;
176 
177  cache = calloc(1, sizeof(*cache));
178  if (!cache)
179  return NULL;
180 
181  nl_init_list_head(&cache->c_items);
182  cache->c_ops = ops;
183 
184  NL_DBG(2, "Allocated cache %p <%s>.\n", cache, nl_cache_name(cache));
185 
186  return cache;
187 }
188 
189 /**
190  * Allocate new cache and fill it
191  * @arg ops Cache operations
192  * @arg sock Netlink socket
193  * @arg result Result pointer
194  *
195  * Allocate new cache and fill it. Equivalent to calling:
196  * @code
197  * cache = nl_cache_alloc(ops);
198  * nl_cache_refill(sock, cache);
199  * @endcode
200  *
201  * @see nl_cache_alloc
202  *
203  * @return 0 on success or a negative error code.
204  */
205 int nl_cache_alloc_and_fill(struct nl_cache_ops *ops, struct nl_sock *sock,
206  struct nl_cache **result)
207 {
208  struct nl_cache *cache;
209  int err;
210 
211  if (!(cache = nl_cache_alloc(ops)))
212  return -NLE_NOMEM;
213 
214  if (sock && (err = nl_cache_refill(sock, cache)) < 0) {
215  nl_cache_free(cache);
216  return err;
217  }
218 
219  *result = cache;
220  return 0;
221 }
222 
223 /**
224  * Allocate new cache based on type name
225  * @arg kind Name of cache type
226  * @arg result Result pointer
227  *
228  * Lookup cache ops via nl_cache_ops_lookup() and allocate the cache
229  * by calling nl_cache_alloc(). Stores the allocated cache in the
230  * result pointer provided.
231  *
232  * @see nl_cache_alloc
233  *
234  * @return 0 on success or a negative error code.
235  */
236 int nl_cache_alloc_name(const char *kind, struct nl_cache **result)
237 {
238  struct nl_cache_ops *ops;
239  struct nl_cache *cache;
240 
241  ops = nl_cache_ops_lookup(kind);
242  if (!ops)
243  return -NLE_NOCACHE;
244 
245  if (!(cache = nl_cache_alloc(ops)))
246  return -NLE_NOMEM;
247 
248  *result = cache;
249  return 0;
250 }
251 
252 /**
253  * Allocate new cache containing a subset of an existing cache
254  * @arg orig Original cache to base new cache on
255  * @arg filter Filter defining the subset to be filled into the new cache
256  *
257  * Allocates a new cache matching the type of the cache specified by
258  * \p orig. Iterates over the \p orig cache applying the specified
259  * \p filter and copies all objects that match to the new cache.
260  *
261  * The copied objects are clones but do not contain a reference to each
262  * other. Later modifications to objects in the original cache will
263  * not affect objects in the new cache.
264  *
265  * @return A newly allocated cache or NULL.
266  */
267 struct nl_cache *nl_cache_subset(struct nl_cache *orig,
268  struct nl_object *filter)
269 {
270  struct nl_cache *cache;
271  struct nl_object *obj;
272 
273  if (!filter)
274  BUG();
275 
276  cache = nl_cache_alloc(orig->c_ops);
277  if (!cache)
278  return NULL;
279 
280  nl_list_for_each_entry(obj, &orig->c_items, ce_list) {
281  if (!nl_object_match_filter(obj, filter))
282  continue;
283 
284  nl_cache_add(cache, obj);
285  }
286 
287  return cache;
288 }
289 
290 /**
291  * Remove all objects of a cache.
292  * @arg cache Cache to clear
293  *
294  * The objects are unliked/removed from the cache by calling
295  * nl_cache_remove() on each object in the cache. If any of the objects
296  * to not contain any further references to them, those objects will
297  * be freed.
298  *
299  * Unlike with nl_cache_free(), the cache is not freed just emptied.
300  */
301 void nl_cache_clear(struct nl_cache *cache)
302 {
303  struct nl_object *obj, *tmp;
304 
305  NL_DBG(1, "Clearing cache %p <%s>...\n", cache, nl_cache_name(cache));
306 
307  nl_list_for_each_entry_safe(obj, tmp, &cache->c_items, ce_list)
308  nl_cache_remove(obj);
309 }
310 
311 /**
312  * Free a cache.
313  * @arg cache Cache to free.
314  *
315  * Calls nl_cache_clear() to remove all objects associated with the
316  * cache and frees the cache afterwards.
317  *
318  * @see nl_cache_clear()
319  */
320 void nl_cache_free(struct nl_cache *cache)
321 {
322  if (!cache)
323  return;
324 
325  nl_cache_clear(cache);
326  NL_DBG(1, "Freeing cache %p <%s>...\n", cache, nl_cache_name(cache));
327  free(cache);
328 }
329 
330 /** @} */
331 
332 /**
333  * @name Cache Modifications
334  * @{
335  */
336 
337 static int __cache_add(struct nl_cache *cache, struct nl_object *obj)
338 {
339  obj->ce_cache = cache;
340 
341  nl_list_add_tail(&obj->ce_list, &cache->c_items);
342  cache->c_nitems++;
343 
344  NL_DBG(1, "Added %p to cache %p <%s>.\n",
345  obj, cache, nl_cache_name(cache));
346 
347  return 0;
348 }
349 
350 /**
351  * Add object to cache.
352  * @arg cache Cache
353  * @arg obj Object to be added to the cache
354  *
355  * Adds the object \p obj to the specified \p cache. In case the object
356  * is already associated with another cache, the object is cloned before
357  * adding it to the cache. In this case, the sole reference to the object
358  * will be the one of the cache. Therefore clearing/freeing the cache
359  * will result in the object being freed again.
360  *
361  * If the object has not been associated with a cache yet, the reference
362  * counter of the object is incremented to account for the additional
363  * reference.
364  *
365  * The type of the object and cache must match, otherwise an error is
366  * returned (-NLE_OBJ_MISMATCH).
367  *
368  * @see nl_cache_move()
369  *
370  * @return 0 or a negative error code.
371  */
372 int nl_cache_add(struct nl_cache *cache, struct nl_object *obj)
373 {
374  struct nl_object *new;
375 
376  if (cache->c_ops->co_obj_ops != obj->ce_ops)
377  return -NLE_OBJ_MISMATCH;
378 
379  if (!nl_list_empty(&obj->ce_list)) {
380  new = nl_object_clone(obj);
381  if (!new)
382  return -NLE_NOMEM;
383  } else {
384  nl_object_get(obj);
385  new = obj;
386  }
387 
388  return __cache_add(cache, new);
389 }
390 
391 /**
392  * Move object from one cache to another
393  * @arg cache Cache to move object to.
394  * @arg obj Object subject to be moved
395  *
396  * Removes the the specified object \p obj from its associated cache
397  * and moves it to another cache.
398  *
399  * If the object is not associated with a cache, the function behaves
400  * just like nl_cache_add().
401  *
402  * The type of the object and cache must match, otherwise an error is
403  * returned (-NLE_OBJ_MISMATCH).
404  *
405  * @see nl_cache_add()
406  *
407  * @return 0 on success or a negative error code.
408  */
409 int nl_cache_move(struct nl_cache *cache, struct nl_object *obj)
410 {
411  if (cache->c_ops->co_obj_ops != obj->ce_ops)
412  return -NLE_OBJ_MISMATCH;
413 
414  NL_DBG(3, "Moving object %p to cache %p\n", obj, cache);
415 
416  /* Acquire reference, if already in a cache this will be
417  * reverted during removal */
418  nl_object_get(obj);
419 
420  if (!nl_list_empty(&obj->ce_list))
421  nl_cache_remove(obj);
422 
423  return __cache_add(cache, obj);
424 }
425 
426 /**
427  * Remove object from cache.
428  * @arg obj Object to remove from cache
429  *
430  * Removes the object \c obj from the cache it is associated with. The
431  * reference counter of the object will be decremented. If the reference
432  * to the object was the only one remaining, the object will be freed.
433  *
434  * If no cache is associated with the object, this function is a NOP.
435  */
436 void nl_cache_remove(struct nl_object *obj)
437 {
438  struct nl_cache *cache = obj->ce_cache;
439 
440  if (cache == NULL)
441  return;
442 
443  nl_list_del(&obj->ce_list);
444  obj->ce_cache = NULL;
445  nl_object_put(obj);
446  cache->c_nitems--;
447 
448  NL_DBG(1, "Deleted %p from cache %p <%s>.\n",
449  obj, cache, nl_cache_name(cache));
450 }
451 
452 /** @} */
453 
454 /**
455  * @name Synchronization
456  * @{
457  */
458 
459 /**
460  * Set synchronization arg1 of cache
461  * @arg cache Cache
462  * @arg arg argument
463  *
464  * Synchronization arguments are used to specify filters when
465  * requesting dumps from the kernel.
466  */
467 void nl_cache_set_arg1(struct nl_cache *cache, int arg)
468 {
469  cache->c_iarg1 = arg;
470 }
471 
472 /**
473  * Set synchronization arg2 of cache
474  * @arg cache Cache
475  * @arg arg argument
476  *
477  * Synchronization arguments are used to specify filters when
478  * requesting dumps from the kernel.
479  */
480 void nl_cache_set_arg2(struct nl_cache *cache, int arg)
481 {
482  cache->c_iarg2 = arg;
483 }
484 
485 /**
486  * Invoke the request-update operation
487  * @arg sk Netlink socket.
488  * @arg cache Cache
489  *
490  * This function causes the \e request-update function of the cache
491  * operations to be invoked. This usually causes a dump request to
492  * be sent over the netlink socket which triggers the kernel to dump
493  * all objects of a specific type to be dumped onto the netlink
494  * socket for pickup.
495  *
496  * The behaviour of this function depends on the implemenation of
497  * the \e request_update function of each individual type of cache.
498  *
499  * This function will not have any effects on the cache (unless the
500  * request_update implementation of the cache operations does so).
501  *
502  * Use nl_cache_pickup() to pick-up (read) the objects from the socket
503  * and fill them into the cache.
504  *
505  * @see nl_cache_pickup(), nl_cache_resync()
506  *
507  * @return 0 on success or a negative error code.
508  */
509 static int nl_cache_request_full_dump(struct nl_sock *sk,
510  struct nl_cache *cache)
511 {
512  NL_DBG(2, "Requesting dump from kernel for cache %p <%s>...\n",
513  cache, nl_cache_name(cache));
514 
515  if (cache->c_ops->co_request_update == NULL)
516  return -NLE_OPNOTSUPP;
517 
518  return cache->c_ops->co_request_update(cache, sk);
519 }
520 
521 /** @cond SKIP */
522 struct update_xdata {
523  struct nl_cache_ops *ops;
524  struct nl_parser_param *params;
525 };
526 
527 static int update_msg_parser(struct nl_msg *msg, void *arg)
528 {
529  struct update_xdata *x = arg;
530 
531  return nl_cache_parse(x->ops, &msg->nm_src, msg->nm_nlh, x->params);
532 }
533 /** @endcond */
534 
535 /**
536  * Pick-up a netlink request-update with your own parser
537  * @arg sk Netlink socket
538  * @arg cache Cache
539  * @arg param Parser parameters
540  */
541 static int __cache_pickup(struct nl_sock *sk, struct nl_cache *cache,
542  struct nl_parser_param *param)
543 {
544  int err;
545  struct nl_cb *cb;
546  struct update_xdata x = {
547  .ops = cache->c_ops,
548  .params = param,
549  };
550 
551  NL_DBG(1, "Picking up answer for cache %p <%s>...\n",
552  cache, nl_cache_name(cache));
553 
554  cb = nl_cb_clone(sk->s_cb);
555  if (cb == NULL)
556  return -NLE_NOMEM;
557 
558  nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, update_msg_parser, &x);
559 
560  err = nl_recvmsgs(sk, cb);
561  if (err < 0)
562  NL_DBG(2, "While picking up for %p <%s>, recvmsgs() returned " \
563  "%d: %s", cache, nl_cache_name(cache),
564  err, nl_geterror(err));
565 
566  nl_cb_put(cb);
567 
568  return err;
569 }
570 
571 static int pickup_cb(struct nl_object *c, struct nl_parser_param *p)
572 {
573  return nl_cache_add((struct nl_cache *) p->pp_arg, c);
574 }
575 
576 /**
577  * Pickup a netlink dump response and put it into a cache.
578  * @arg sk Netlink socket.
579  * @arg cache Cache to put items into.
580  *
581  * Waits for netlink messages to arrive, parses them and puts them into
582  * the specified cache.
583  *
584  * @return 0 on success or a negative error code.
585  */
586 int nl_cache_pickup(struct nl_sock *sk, struct nl_cache *cache)
587 {
588  struct nl_parser_param p = {
589  .pp_cb = pickup_cb,
590  .pp_arg = cache,
591  };
592 
593  return __cache_pickup(sk, cache, &p);
594 }
595 
596 static int cache_include(struct nl_cache *cache, struct nl_object *obj,
597  struct nl_msgtype *type, change_func_t cb, void *data)
598 {
599  struct nl_object *old;
600 
601  switch (type->mt_act) {
602  case NL_ACT_NEW:
603  case NL_ACT_DEL:
604  old = nl_cache_search(cache, obj);
605  if (old) {
606  nl_cache_remove(old);
607  if (type->mt_act == NL_ACT_DEL) {
608  if (cb)
609  cb(cache, old, NL_ACT_DEL, data);
610  nl_object_put(old);
611  }
612  }
613 
614  if (type->mt_act == NL_ACT_NEW) {
615  nl_cache_move(cache, obj);
616  if (old == NULL && cb)
617  cb(cache, obj, NL_ACT_NEW, data);
618  else if (old) {
619  if (nl_object_diff(old, obj) && cb)
620  cb(cache, obj, NL_ACT_CHANGE, data);
621 
622  nl_object_put(old);
623  }
624  }
625  break;
626  default:
627  NL_DBG(2, "Unknown action associated to object %p\n", obj);
628  return 0;
629  }
630 
631  return 0;
632 }
633 
634 int nl_cache_include(struct nl_cache *cache, struct nl_object *obj,
635  change_func_t change_cb, void *data)
636 {
637  struct nl_cache_ops *ops = cache->c_ops;
638  int i;
639 
640  if (ops->co_obj_ops != obj->ce_ops)
641  return -NLE_OBJ_MISMATCH;
642 
643  for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++)
644  if (ops->co_msgtypes[i].mt_id == obj->ce_msgtype)
645  return cache_include(cache, obj, &ops->co_msgtypes[i],
646  change_cb, data);
647 
648  return -NLE_MSGTYPE_NOSUPPORT;
649 }
650 
651 static int resync_cb(struct nl_object *c, struct nl_parser_param *p)
652 {
653  struct nl_cache_assoc *ca = p->pp_arg;
654 
655  return nl_cache_include(ca->ca_cache, c, ca->ca_change, ca->ca_change_data);
656 }
657 
658 int nl_cache_resync(struct nl_sock *sk, struct nl_cache *cache,
659  change_func_t change_cb, void *data)
660 {
661  struct nl_object *obj, *next;
662  struct nl_cache_assoc ca = {
663  .ca_cache = cache,
664  .ca_change = change_cb,
665  .ca_change_data = data,
666  };
667  struct nl_parser_param p = {
668  .pp_cb = resync_cb,
669  .pp_arg = &ca,
670  };
671  int err;
672 
673  NL_DBG(1, "Resyncing cache %p <%s>...\n", cache, nl_cache_name(cache));
674 
675 restart:
676  /* Mark all objects so we can see if some of them are obsolete */
677  nl_cache_mark_all(cache);
678 
679  err = nl_cache_request_full_dump(sk, cache);
680  if (err < 0)
681  goto errout;
682 
683  err = __cache_pickup(sk, cache, &p);
684  if (err == -NLE_DUMP_INTR)
685  goto restart;
686  else if (err < 0)
687  goto errout;
688 
689  nl_list_for_each_entry_safe(obj, next, &cache->c_items, ce_list) {
690  if (nl_object_is_marked(obj)) {
691  nl_object_get(obj);
692  nl_cache_remove(obj);
693  if (change_cb)
694  change_cb(cache, obj, NL_ACT_DEL, data);
695  nl_object_put(obj);
696  }
697  }
698 
699  NL_DBG(1, "Finished resyncing %p <%s>\n", cache, nl_cache_name(cache));
700 
701  err = 0;
702 errout:
703  return err;
704 }
705 
706 /** @} */
707 
708 /**
709  * @name Parsing
710  * @{
711  */
712 
713 /** @cond SKIP */
714 int nl_cache_parse(struct nl_cache_ops *ops, struct sockaddr_nl *who,
715  struct nlmsghdr *nlh, struct nl_parser_param *params)
716 {
717  int i, err;
718 
719  if (!nlmsg_valid_hdr(nlh, ops->co_hdrsize))
720  return -NLE_MSG_TOOSHORT;
721 
722  for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++) {
723  if (ops->co_msgtypes[i].mt_id == nlh->nlmsg_type) {
724  err = ops->co_msg_parser(ops, who, nlh, params);
725  if (err != -NLE_OPNOTSUPP)
726  goto errout;
727  }
728  }
729 
730 
731  err = -NLE_MSGTYPE_NOSUPPORT;
732 errout:
733  return err;
734 }
735 /** @endcond */
736 
737 /**
738  * Parse a netlink message and add it to the cache.
739  * @arg cache cache to add element to
740  * @arg msg netlink message
741  *
742  * Parses a netlink message by calling the cache specific message parser
743  * and adds the new element to the cache.
744  *
745  * @return 0 or a negative error code.
746  */
747 int nl_cache_parse_and_add(struct nl_cache *cache, struct nl_msg *msg)
748 {
749  struct nl_parser_param p = {
750  .pp_cb = pickup_cb,
751  .pp_arg = cache,
752  };
753 
754  return nl_cache_parse(cache->c_ops, NULL, nlmsg_hdr(msg), &p);
755 }
756 
757 /**
758  * (Re)fill a cache with the contents in the kernel.
759  * @arg sk Netlink socket.
760  * @arg cache cache to update
761  *
762  * Clears the specified cache and fills it with the current state in
763  * the kernel.
764  *
765  * @return 0 or a negative error code.
766  */
767 int nl_cache_refill(struct nl_sock *sk, struct nl_cache *cache)
768 {
769  int err;
770 
771 restart:
772  err = nl_cache_request_full_dump(sk, cache);
773  if (err < 0)
774  return err;
775 
776  NL_DBG(2, "Upading cache %p <%s>, request sent, waiting for dump...\n",
777  cache, nl_cache_name(cache));
778  nl_cache_clear(cache);
779 
780  err = nl_cache_pickup(sk, cache);
781  if (err == -NLE_DUMP_INTR) {
782  fprintf(stderr, "dump interrupted, restarting!\n");
783  goto restart;
784  }
785 
786  return err;
787 }
788 
789 /** @} */
790 
791 /**
792  * @name Utillities
793  * @{
794  */
795 
796 /**
797  * Search object in cache
798  * @arg cache Cache
799  * @arg needle Object to look for.
800  *
801  * Searches the cache for an object which matches the object \p needle.
802  * The function nl_object_identical() is used to determine if the
803  * objects match. If a matching object is found, the reference counter
804  * is incremented and the object is returned.
805  *
806  * Therefore, if an object is returned, the reference to the object
807  * must be returned by calling nl_object_put() after usage.
808  *
809  * @return Reference to object or NULL if not found.
810  */
811 struct nl_object *nl_cache_search(struct nl_cache *cache,
812  struct nl_object *needle)
813 {
814  struct nl_object *obj;
815 
816  nl_list_for_each_entry(obj, &cache->c_items, ce_list) {
817  if (nl_object_identical(obj, needle)) {
818  nl_object_get(obj);
819  return obj;
820  }
821  }
822 
823  return NULL;
824 }
825 
826 /**
827  * Mark all objects of a cache
828  * @arg cache Cache
829  *
830  * Marks all objects of a cache by calling nl_object_mark() on each
831  * object associated with the cache.
832  */
833 void nl_cache_mark_all(struct nl_cache *cache)
834 {
835  struct nl_object *obj;
836 
837  NL_DBG(2, "Marking all objects in cache %p <%s>...\n",
838  cache, nl_cache_name(cache));
839 
840  nl_list_for_each_entry(obj, &cache->c_items, ce_list)
841  nl_object_mark(obj);
842 }
843 
844 /** @} */
845 
846 /**
847  * @name Dumping
848  * @{
849  */
850 
851 /**
852  * Dump all elements of a cache.
853  * @arg cache cache to dump
854  * @arg params dumping parameters
855  *
856  * Dumps all elements of the \a cache to the file descriptor \a fd.
857  */
858 void nl_cache_dump(struct nl_cache *cache, struct nl_dump_params *params)
859 {
860  nl_cache_dump_filter(cache, params, NULL);
861 }
862 
863 /**
864  * Dump all elements of a cache (filtered).
865  * @arg cache cache to dump
866  * @arg params dumping parameters (optional)
867  * @arg filter filter object
868  *
869  * Dumps all elements of the \a cache to the file descriptor \a fd
870  * given they match the given filter \a filter.
871  */
872 void nl_cache_dump_filter(struct nl_cache *cache,
873  struct nl_dump_params *params,
874  struct nl_object *filter)
875 {
876  int type = params ? params->dp_type : NL_DUMP_DETAILS;
877  struct nl_object_ops *ops;
878  struct nl_object *obj;
879 
880  NL_DBG(2, "Dumping cache %p <%s> filter %p\n",
881  cache, nl_cache_name(cache), filter);
882 
883  if (type > NL_DUMP_MAX || type < 0)
884  BUG();
885 
886  if (cache->c_ops == NULL)
887  BUG();
888 
889  ops = cache->c_ops->co_obj_ops;
890  if (!ops->oo_dump[type])
891  return;
892 
893  nl_list_for_each_entry(obj, &cache->c_items, ce_list) {
894  if (filter && !nl_object_match_filter(obj, filter))
895  continue;
896 
897  NL_DBG(4, "Dumping object %p...\n", obj);
898  dump_from_ops(obj, params);
899  }
900 }
901 
902 /** @} */
903 
904 /**
905  * @name Iterators
906  * @{
907  */
908 
909 /**
910  * Call a callback on each element of the cache.
911  * @arg cache cache to iterate on
912  * @arg cb callback function
913  * @arg arg argument passed to callback function
914  *
915  * Calls a callback function \a cb on each element of the \a cache.
916  * The argument \a arg is passed on the callback function.
917  */
918 void nl_cache_foreach(struct nl_cache *cache,
919  void (*cb)(struct nl_object *, void *), void *arg)
920 {
921  nl_cache_foreach_filter(cache, NULL, cb, arg);
922 }
923 
924 /**
925  * Call a callback on each element of the cache (filtered).
926  * @arg cache cache to iterate on
927  * @arg filter filter object
928  * @arg cb callback function
929  * @arg arg argument passed to callback function
930  *
931  * Calls a callback function \a cb on each element of the \a cache
932  * that matches the \a filter. The argument \a arg is passed on
933  * to the callback function.
934  */
935 void nl_cache_foreach_filter(struct nl_cache *cache, struct nl_object *filter,
936  void (*cb)(struct nl_object *, void *), void *arg)
937 {
938  struct nl_object *obj, *tmp;
939 
940  if (cache->c_ops == NULL)
941  BUG();
942 
943  nl_list_for_each_entry_safe(obj, tmp, &cache->c_items, ce_list) {
944  if (filter) {
945  int diff = nl_object_match_filter(obj, filter);
946 
947  NL_DBG(3, "%p<->%p object difference: %x\n",
948  obj, filter, diff);
949 
950  if (!diff)
951  continue;
952  }
953 
954  /* Caller may hold obj for a long time */
955  nl_object_get(obj);
956 
957  cb(obj, arg);
958 
959  nl_object_put(obj);
960  }
961 }
962 
963 /** @} */
964 
965 /** @} */