Skip to content

Commit 66d032a

Browse files
Tobias Jungelthom311
authored andcommitted
cache_mngr: add include callback v2
This patch adds change_func_v2_t to add a more detailed callback in case of a cache change. The change function is registered using the new nl_cache_mngr_add_cache_v2. In case the new change function is set, nl_cache_include_v2 and thus cache_include_v2 will be used to perform the cache inclusion. The parameter of change_func_v2_t are the following: * struct nl_cache * => cache * struct nl_object * => the old/deleted nl_object * struct nl_object * => the new nl_object * uint64_t => the result of nl_object_diff64 in case of a change * int => NL_ACT_* * void * => data #71 http://lists.infradead.org/pipermail/libnl/2016-September/002214.html http://lists.infradead.org/pipermail/libnl/2016-October/002229.html http://lists.infradead.org/pipermail/libnl/2016-November/002250.html
1 parent 55ea6e6 commit 66d032a

File tree

7 files changed

+204
-19
lines changed

7 files changed

+204
-19
lines changed

include/netlink-private/cache-api.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,8 @@ struct nl_cache_ops
237237
* @see nl_cache_include()
238238
*/
239239
int (*co_include_event)(struct nl_cache *cache, struct nl_object *obj,
240-
change_func_t change_cb, void *data);
240+
change_func_t change_cb, change_func_v2_t change_cb_v2,
241+
void *data);
241242

242243
void (*reserved_1)(void);
243244
void (*reserved_2)(void);

include/netlink-private/types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ struct nl_cache_assoc
9999
{
100100
struct nl_cache * ca_cache;
101101
change_func_t ca_change;
102+
change_func_v2_t ca_change_v2;
102103
void * ca_change_data;
103104
};
104105

include/netlink/cache.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ enum {
3535

3636
struct nl_cache;
3737
typedef void (*change_func_t)(struct nl_cache *, struct nl_object *, int, void *);
38+
typedef void (*change_func_v2_t)(struct nl_cache *, struct nl_object *old_obj,
39+
struct nl_object *new_obj, uint64_t, int, void *);
3840

3941
/**
4042
* @ingroup cache
@@ -88,6 +90,10 @@ extern int nl_cache_include(struct nl_cache *,
8890
struct nl_object *,
8991
change_func_t,
9092
void *);
93+
extern int nl_cache_include_v2(struct nl_cache *,
94+
struct nl_object *,
95+
change_func_v2_t,
96+
void *);
9197
extern void nl_cache_set_arg1(struct nl_cache *, int);
9298
extern void nl_cache_set_arg2(struct nl_cache *, int);
9399
extern void nl_cache_set_flags(struct nl_cache *, unsigned int);
@@ -154,6 +160,9 @@ extern int nl_cache_mngr_add(struct nl_cache_mngr *,
154160
extern int nl_cache_mngr_add_cache(struct nl_cache_mngr *mngr,
155161
struct nl_cache *cache,
156162
change_func_t cb, void *data);
163+
extern int nl_cache_mngr_add_cache_v2(struct nl_cache_mngr *mngr,
164+
struct nl_cache *cache,
165+
change_func_v2_t cb, void *data);
157166
extern int nl_cache_mngr_get_fd(struct nl_cache_mngr *);
158167
extern int nl_cache_mngr_poll(struct nl_cache_mngr *,
159168
int);

lib/cache.c

Lines changed: 59 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -784,41 +784,66 @@ int nl_cache_pickup(struct nl_sock *sk, struct nl_cache *cache)
784784
}
785785

786786
static int cache_include(struct nl_cache *cache, struct nl_object *obj,
787-
struct nl_msgtype *type, change_func_t cb, void *data)
787+
struct nl_msgtype *type, change_func_t cb,
788+
change_func_v2_t cb_v2, void *data)
788789
{
789790
struct nl_object *old;
791+
struct nl_object *clone = NULL;
792+
uint64_t diff;
790793

791794
switch (type->mt_act) {
792795
case NL_ACT_NEW:
793796
case NL_ACT_DEL:
794797
old = nl_cache_search(cache, obj);
795798
if (old) {
799+
if (cb_v2 && old->ce_ops->oo_update) {
800+
clone = nl_object_clone(old);
801+
diff = nl_object_diff64(old, obj);
802+
}
796803
/*
797804
* Some objects types might support merging the new
798805
* object with the old existing cache object.
799806
* Handle them first.
800807
*/
801808
if (nl_object_update(old, obj) == 0) {
802-
if (cb)
809+
if (cb_v2) {
810+
cb_v2(cache, clone, obj, diff,
811+
NL_ACT_CHANGE, data);
812+
nl_object_put(clone);
813+
} else if (cb)
803814
cb(cache, old, NL_ACT_CHANGE, data);
804815
nl_object_put(old);
805816
return 0;
806817
}
818+
nl_object_put(clone);
807819

808820
nl_cache_remove(old);
809821
if (type->mt_act == NL_ACT_DEL) {
810-
if (cb)
822+
if (cb_v2)
823+
cb_v2(cache, old, NULL, 0, NL_ACT_DEL,
824+
data);
825+
else if (cb)
811826
cb(cache, old, NL_ACT_DEL, data);
812827
nl_object_put(old);
813828
}
814829
}
815830

816831
if (type->mt_act == NL_ACT_NEW) {
817832
nl_cache_move(cache, obj);
818-
if (old == NULL && cb)
819-
cb(cache, obj, NL_ACT_NEW, data);
820-
else if (old) {
821-
if (nl_object_diff(old, obj) && cb)
833+
if (old == NULL) {
834+
if (cb_v2) {
835+
cb_v2(cache, NULL, obj, 0, NL_ACT_NEW,
836+
data);
837+
} else if (cb)
838+
cb(cache, obj, NL_ACT_NEW, data);
839+
} else if (old) {
840+
uint64_t diff = 0;
841+
if (cb || cb_v2)
842+
diff = nl_object_diff64(old, obj);
843+
if (diff && cb_v2) {
844+
cb_v2(cache, old, obj, diff, NL_ACT_CHANGE,
845+
data);
846+
} else if (diff && cb)
822847
cb(cache, obj, NL_ACT_CHANGE, data);
823848

824849
nl_object_put(old);
@@ -845,7 +870,27 @@ int nl_cache_include(struct nl_cache *cache, struct nl_object *obj,
845870
for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++)
846871
if (ops->co_msgtypes[i].mt_id == obj->ce_msgtype)
847872
return cache_include(cache, obj, &ops->co_msgtypes[i],
848-
change_cb, data);
873+
change_cb, NULL, data);
874+
875+
NL_DBG(3, "Object %p does not seem to belong to cache %p <%s>\n",
876+
obj, cache, nl_cache_name(cache));
877+
878+
return -NLE_MSGTYPE_NOSUPPORT;
879+
}
880+
881+
int nl_cache_include_v2(struct nl_cache *cache, struct nl_object *obj,
882+
change_func_v2_t change_cb, void *data)
883+
{
884+
struct nl_cache_ops *ops = cache->c_ops;
885+
int i;
886+
887+
if (ops->co_obj_ops != obj->ce_ops)
888+
return -NLE_OBJ_MISMATCH;
889+
890+
for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++)
891+
if (ops->co_msgtypes[i].mt_id == obj->ce_msgtype)
892+
return cache_include(cache, obj, &ops->co_msgtypes[i],
893+
NULL, change_cb, data);
849894

850895
NL_DBG(3, "Object %p does not seem to belong to cache %p <%s>\n",
851896
obj, cache, nl_cache_name(cache));
@@ -857,7 +902,12 @@ static int resync_cb(struct nl_object *c, struct nl_parser_param *p)
857902
{
858903
struct nl_cache_assoc *ca = p->pp_arg;
859904

860-
return nl_cache_include(ca->ca_cache, c, ca->ca_change, ca->ca_change_data);
905+
if (ca->ca_change_v2)
906+
return nl_cache_include_v2(ca->ca_cache, c, ca->ca_change_v2,
907+
ca->ca_change_data);
908+
else
909+
return nl_cache_include(ca->ca_cache, c, ca->ca_change,
910+
ca->ca_change_data);
861911
}
862912

863913
int nl_cache_resync(struct nl_sock *sk, struct nl_cache *cache,

lib/cache_mngr.c

Lines changed: 107 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,15 @@ static int include_cb(struct nl_object *obj, struct nl_parser_param *p)
6060

6161
if (ops->co_include_event)
6262
return ops->co_include_event(ca->ca_cache, obj, ca->ca_change,
63+
ca->ca_change_v2,
6364
ca->ca_change_data);
64-
else
65-
return nl_cache_include(ca->ca_cache, obj, ca->ca_change, ca->ca_change_data);
65+
else {
66+
if (ca->ca_change_v2)
67+
return nl_cache_include_v2(ca->ca_cache, obj, ca->ca_change_v2, ca->ca_change_data);
68+
else
69+
return nl_cache_include(ca->ca_cache, obj, ca->ca_change, ca->ca_change_data);
70+
}
71+
6672
}
6773

6874
static int event_input(struct nl_msg *msg, void *arg)
@@ -194,6 +200,70 @@ int nl_cache_mngr_alloc(struct nl_sock *sk, int protocol, int flags,
194200
return err;
195201
}
196202

203+
/**
204+
* Set change_func_v2 for cache manager
205+
* @arg mngr Cache manager.
206+
* @arg cache Cache associated with the callback
207+
* @arg cb Function to be called upon changes.
208+
* @arg data Argument passed on to change callback
209+
*
210+
* Adds callback change_func_v2 to a registered cache. This callback provides
211+
* in like the standard change_func the added or remove netlink object. In case
212+
* of a change the old and the new object is provided as well as the according
213+
* diff. If this callback is registered this has a higher priority then the
214+
* change_func registered during cache registration. Hence only one callback is
215+
* executed.
216+
*
217+
* The first netlink object in the callback is refering to the old object and
218+
* the second to the new. This means on NL_ACT_CHANGE the first is the previous
219+
* object in the cache and the second the updated version. On NL_ACT_DEL the
220+
* first is the deleted object the second is NULL. On NL_ACT_NEW the first is
221+
* NULL and the second the new netlink object.
222+
*
223+
* The user is responsible for calling nl_cache_mngr_poll() or monitor
224+
* the socket and call nl_cache_mngr_data_ready() to allow the library
225+
* to process netlink notification events.
226+
*
227+
* @see nl_cache_mngr_poll()
228+
* @see nl_cache_mngr_data_ready()
229+
*
230+
* @return 0 on success or a negative error code.
231+
* @return -NLE_PROTO_MISMATCH Protocol mismatch between cache manager and
232+
* cache type
233+
* @return -NLE_OPNOTSUPP Cache type does not support updates
234+
* @return -NLE_RANGE Cache of this type is not registered
235+
*/
236+
static int nl_cache_mngr_set_change_func_v2(struct nl_cache_mngr *mngr,
237+
struct nl_cache *cache,
238+
change_func_v2_t cb, void *data)
239+
{
240+
struct nl_cache_ops *ops;
241+
int i;
242+
243+
ops = cache->c_ops;
244+
if (!ops)
245+
return -NLE_INVAL;
246+
247+
if (ops->co_protocol != mngr->cm_protocol)
248+
return -NLE_PROTO_MISMATCH;
249+
250+
if (ops->co_groups == NULL)
251+
return -NLE_OPNOTSUPP;
252+
253+
for (i = 0; i < mngr->cm_nassocs; i++)
254+
if (mngr->cm_assocs[i].ca_cache == cache)
255+
break;
256+
257+
if (i >= mngr->cm_nassocs) {
258+
return -NLE_RANGE;
259+
}
260+
261+
mngr->cm_assocs[i].ca_change_v2 = cb;
262+
mngr->cm_assocs[i].ca_change_data = data;
263+
264+
return 0;
265+
}
266+
197267
/**
198268
* Add cache to cache manager
199269
* @arg mngr Cache manager.
@@ -291,6 +361,41 @@ int nl_cache_mngr_add_cache(struct nl_cache_mngr *mngr, struct nl_cache *cache,
291361
return err;
292362
}
293363

364+
/**
365+
* Add cache to cache manager
366+
* @arg mngr Cache manager.
367+
* @arg cache Cache to be added to cache manager
368+
* @arg cb V2 function to be called upon changes.
369+
* @arg data Argument passed on to change callback
370+
*
371+
* Adds cache to the manager. The operation will trigger a full
372+
* dump request from the kernel to initially fill the contents
373+
* of the cache. The manager will subscribe to the notification group
374+
* of the cache and keep track of any further changes.
375+
*
376+
* The user is responsible for calling nl_cache_mngr_poll() or monitor
377+
* the socket and call nl_cache_mngr_data_ready() to allow the library
378+
* to process netlink notification events.
379+
*
380+
* @see nl_cache_mngr_poll()
381+
* @see nl_cache_mngr_data_ready()
382+
*
383+
* @return 0 on success or a negative error code.
384+
* @return -NLE_PROTO_MISMATCH Protocol mismatch between cache manager and
385+
* cache type
386+
* @return -NLE_OPNOTSUPP Cache type does not support updates
387+
* @return -NLE_EXIST Cache of this type already being managed
388+
*/
389+
int nl_cache_mngr_add_cache_v2(struct nl_cache_mngr *mngr, struct nl_cache *cache,
390+
change_func_v2_t cb, void *data) {
391+
int err;
392+
err = nl_cache_mngr_add_cache(mngr, cache, NULL, NULL);
393+
if (err < 0)
394+
return err;
395+
396+
return nl_cache_mngr_set_change_func_v2(mngr, cache, cb, data);
397+
}
398+
294399
/**
295400
* Add cache to cache manager
296401
* @arg mngr Cache manager.

lib/xfrm/sa.c

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -918,7 +918,8 @@ int xfrmnl_sa_parse(struct nlmsghdr *n, struct xfrmnl_sa **result)
918918
}
919919

920920
static int xfrm_sa_update_cache (struct nl_cache *cache, struct nl_object *obj,
921-
change_func_t change_cb, void *data)
921+
change_func_t change_cb, change_func_v2_t change_cb_v2,
922+
void *data)
922923
{
923924
struct nl_object* old_sa;
924925
struct xfrmnl_sa* sa = (struct xfrmnl_sa*)obj;
@@ -947,26 +948,39 @@ static int xfrm_sa_update_cache (struct nl_cache *cache, struct nl_object *obj,
947948
* cache and notify application of the expiry event. */
948949
nl_cache_move (cache, obj);
949950

950-
if (old_sa == NULL && change_cb)
951+
if (old_sa == NULL)
951952
{
952953
/* Application CB present, no previous instance of SA object present.
953954
* Notify application CB as a NEW event */
954-
change_cb (cache, obj, NL_ACT_NEW, data);
955+
if (change_cb_v2)
956+
change_cb_v2(cache, NULL, obj, 0, NL_ACT_NEW, data);
957+
else if (change_cb)
958+
change_cb(cache, obj, NL_ACT_NEW, data);
955959
}
956960
else if (old_sa)
957961
{
962+
uint64_t diff = 0;
963+
if (change_cb || change_cb_v2)
964+
diff = nl_object_diff64(old_sa, obj);
965+
958966
/* Application CB present, a previous instance of SA object present.
959967
* Notify application CB as a CHANGE1 event */
960-
if (nl_object_diff (old_sa, obj) && change_cb)
961-
change_cb (cache, obj, NL_ACT_CHANGE, data);
968+
if (diff) {
969+
if (change_cb_v2) {
970+
change_cb_v2(cache, old_sa, obj, diff, NL_ACT_CHANGE, data);
971+
} else if (change_cb)
972+
change_cb(cache, obj, NL_ACT_CHANGE, data);
973+
}
962974
nl_object_put (old_sa);
963975
}
964976
}
965977
else
966978
{
967979
/* Hard expiry event: Delete the object from the
968980
* cache and notify application of the expiry event. */
969-
if (change_cb)
981+
if (change_cb_v2)
982+
change_cb_v2(cache, obj, NULL, 0, NL_ACT_DEL, data);
983+
else if (change_cb)
970984
change_cb (cache, obj, NL_ACT_DEL, data);
971985
nl_object_put (old_sa);
972986
}
@@ -978,7 +992,10 @@ static int xfrm_sa_update_cache (struct nl_cache *cache, struct nl_object *obj,
978992
{
979993
/* All other messages other than Expire, let the standard Libnl cache
980994
* module handle it. */
981-
return nl_cache_include (cache, obj, change_cb, data);
995+
if (change_cb_v2)
996+
return nl_cache_include_v2(cache, obj, change_cb_v2, data);
997+
else
998+
return nl_cache_include (cache, obj, change_cb, data);
982999
}
9831000
}
9841001

libnl-3.sym

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,5 +354,7 @@ global:
354354

355355
libnl_3_2_29 {
356356
global:
357+
nl_cache_include_v2;
358+
nl_cache_mngr_add_cache_v2;
357359
nl_strerror_l;
358360
} libnl_3_2_28;

0 commit comments

Comments
 (0)