[PATCH] cache_mngr: add include callback v2 - RFC

Tobias Jungel tobias.jungel at bisdn.de
Thu Sep 8 06:01:12 PDT 2016


This patch adds change_func_v2_t to add a more detailed callback in
case of a cache change. In case the new change function is set using
nl_cache_mngr_set_change_func_v2, nl_cache_include_v2 and thus
cache_include_v2 will be used 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

I guess cache_include and cache_include_v2 could be merged.

todo: update resync_cb, docs

best
Tobi

Signed-off-by: Tobias Jungel <tobias.jungel at bisdn.de>
---
 include/netlink-private/cache-api.h |  1 +
 include/netlink-private/types.h     |  1 +
 include/netlink/cache.h             | 10 +++++
 lib/cache.c                         | 82 +++++++++++++++++++++++++++++++++++++
 lib/cache_mngr.c                    | 43 ++++++++++++++++++-
 libnl-3.sym                         |  2 +
 6 files changed, 137 insertions(+), 2 deletions(-)

diff --git a/include/netlink-private/cache-api.h b/include/netlink-private/cache-api.h
index f3d9f01..c306eb5 100644
--- a/include/netlink-private/cache-api.h
+++ b/include/netlink-private/cache-api.h
@@ -236,6 +236,7 @@ struct nl_cache_ops
 	 *
 	 * @see nl_cache_include()
 	 */
+	// TODO this has to be updated as well to support cb_v2
 	int   (*co_include_event)(struct nl_cache *cache, struct nl_object *obj,
 				  change_func_t change_cb, void *data);
 
diff --git a/include/netlink-private/types.h b/include/netlink-private/types.h
index e80c8a1..4702162 100644
--- a/include/netlink-private/types.h
+++ b/include/netlink-private/types.h
@@ -96,6 +96,7 @@ struct nl_cache_assoc
 {
 	struct nl_cache *	ca_cache;
 	change_func_t		ca_change;
+	change_func_v2_t	ca_change_v2;
 	void *			ca_change_data;
 };
 
diff --git a/include/netlink/cache.h b/include/netlink/cache.h
index 71eaceb..ad8da60 100644
--- a/include/netlink/cache.h
+++ b/include/netlink/cache.h
@@ -35,6 +35,8 @@ enum {
 
 struct nl_cache;
 typedef void (*change_func_t)(struct nl_cache *, struct nl_object *, int, void *);
+typedef void (*change_func_v2_t)(struct nl_cache *, struct nl_object *,
+	      struct nl_object *, uint64_t, int, void *);
 
 /**
  * @ingroup cache
@@ -88,6 +90,10 @@ extern int			nl_cache_include(struct nl_cache *,
 						 struct nl_object *,
 						 change_func_t,
 						 void *);
+extern int			nl_cache_include_v2(struct nl_cache *,
+						    struct nl_object *,
+						    change_func_v2_t,
+						    void *);
 extern void			nl_cache_set_arg1(struct nl_cache *, int);
 extern void			nl_cache_set_arg2(struct nl_cache *, int);
 extern void			nl_cache_set_flags(struct nl_cache *, unsigned int);
@@ -154,6 +160,10 @@ extern int			nl_cache_mngr_add(struct nl_cache_mngr *,
 extern int			nl_cache_mngr_add_cache(struct nl_cache_mngr *mngr,
 							struct nl_cache *cache,
 							change_func_t cb, void *data);
+extern int			nl_cache_mngr_set_change_func_v2(struct nl_cache_mngr *mngr,
+								 struct nl_cache *cache,
+								 change_func_v2_t cb,
+								 void *data);
 extern int			nl_cache_mngr_get_fd(struct nl_cache_mngr *);
 extern int			nl_cache_mngr_poll(struct nl_cache_mngr *,
 						   int);
diff --git a/lib/cache.c b/lib/cache.c
index d8592b6..0bdb4bd 100644
--- a/lib/cache.c
+++ b/lib/cache.c
@@ -833,6 +833,68 @@ static int cache_include(struct nl_cache *cache, struct nl_object *obj,
 	return 0;
 }
 
+static int cache_include_v2(struct nl_cache *cache, struct nl_object *obj,
+			    struct nl_msgtype *type, change_func_v2_t cb,
+			    void *data)
+{
+	struct nl_object *old;
+	struct nl_object *clone = NULL; 
+	uint64_t diff;
+
+	switch (type->mt_act) {
+	case NL_ACT_NEW:
+	case NL_ACT_DEL:
+		old = nl_cache_search(cache, obj);
+		if (old) {
+			/*
+			 * Some objects types might support merging the new
+			 * object with the old existing cache object.
+			 * Handle them first.
+			 */
+			if (cb) {
+				clone = nl_object_clone(old);
+				diff = nl_object_diff64(old, obj);
+			}
+			if (nl_object_update(old, obj) == 0) {
+				if (cb)
+					cb(cache, clone, obj, diff, NL_ACT_CHANGE, data);
+				nl_object_put(clone);
+				nl_object_put(old);
+				return 0;
+			}
+                        nl_object_put(clone);
+
+                        nl_cache_remove(old);
+                        if (type->mt_act == NL_ACT_DEL) {
+				if (cb)
+					cb(cache, old, NULL, 0, NL_ACT_DEL, data);
+				nl_object_put(old);
+			}
+		}
+
+		if (type->mt_act == NL_ACT_NEW) {
+			nl_cache_move(cache, obj);
+			if (old == NULL && cb)
+				cb(cache, NULL, obj, 0, NL_ACT_NEW, data);
+			else if (old) {
+				if (cb) {
+					uint64_t diff = nl_object_diff64(old, obj);
+					if (diff)
+						cb(cache, old, obj, diff, NL_ACT_CHANGE, data);
+				}
+
+				nl_object_put(old);
+			}
+		}
+		break;
+	default:
+		NL_DBG(2, "Unknown action associated to object %p\n", obj);
+		return 0;
+	}
+
+	return 0;
+}
+
 int nl_cache_include(struct nl_cache *cache, struct nl_object *obj,
 		     change_func_t change_cb, void *data)
 {
@@ -853,6 +915,26 @@ int nl_cache_include(struct nl_cache *cache, struct nl_object *obj,
 	return -NLE_MSGTYPE_NOSUPPORT;
 }
 
+int nl_cache_include_v2(struct nl_cache *cache, struct nl_object *obj,
+			change_func_v2_t change_cb, void *data)
+{
+	struct nl_cache_ops *ops = cache->c_ops;
+	int i;
+
+	if (ops->co_obj_ops != obj->ce_ops)
+		return -NLE_OBJ_MISMATCH;
+
+	for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++)
+		if (ops->co_msgtypes[i].mt_id == obj->ce_msgtype)
+			return cache_include_v2(cache, obj, &ops->co_msgtypes[i],
+						change_cb, data);
+
+	NL_DBG(3, "Object %p does not seem to belong to cache %p <%s>\n",
+	       obj, cache, nl_cache_name(cache));
+
+	return -NLE_MSGTYPE_NOSUPPORT;
+}
+
 static int resync_cb(struct nl_object *c, struct nl_parser_param *p)
 {
 	struct nl_cache_assoc *ca = p->pp_arg;
diff --git a/lib/cache_mngr.c b/lib/cache_mngr.c
index 1f23eb1..92e212a 100644
--- a/lib/cache_mngr.c
+++ b/lib/cache_mngr.c
@@ -61,8 +61,13 @@ static int include_cb(struct nl_object *obj, struct nl_parser_param *p)
 	if (ops->co_include_event)
 		return ops->co_include_event(ca->ca_cache, obj, ca->ca_change,
 					     ca->ca_change_data);
-	else
-		return nl_cache_include(ca->ca_cache, obj, ca->ca_change, ca->ca_change_data);
+	else {
+		if (ca->ca_change_v2)
+			return nl_cache_include_v2(ca->ca_cache, obj, ca->ca_change_v2, ca->ca_change_data);
+		else	
+			return nl_cache_include(ca->ca_cache, obj, ca->ca_change, ca->ca_change_data);
+	}
+
 }
 
 static int event_input(struct nl_msg *msg, void *arg)
@@ -349,6 +354,40 @@ errout_free_cache:
 }
 
 /**
+ * TODO
+ */
+int nl_cache_mngr_set_change_func_v2(struct nl_cache_mngr *mngr,
+				     struct nl_cache *cache,
+				     change_func_v2_t cb, void *data)
+{
+	struct nl_cache_ops *ops;
+	int i;
+
+	ops = cache->c_ops;
+	if (!ops)
+		return -NLE_INVAL;
+
+	if (ops->co_protocol != mngr->cm_protocol)
+		return -NLE_PROTO_MISMATCH;
+
+	if (ops->co_groups == NULL)
+		return -NLE_OPNOTSUPP;
+
+	for (i = 0; i < mngr->cm_nassocs; i++)
+		if (mngr->cm_assocs[i].ca_cache == cache)
+			break;
+
+	if (i >= mngr->cm_nassocs) {
+		return -NLE_RANGE;
+	}
+
+	mngr->cm_assocs[i].ca_change_v2 = cb;
+	mngr->cm_assocs[i].ca_change_data = data; // TODO different data for v2?
+
+	return 0;
+}
+
+/**
  * Get socket file descriptor
  * @arg mngr		Cache Manager
  *
diff --git a/libnl-3.sym b/libnl-3.sym
index 9119e66..0ba82e0 100644
--- a/libnl-3.sym
+++ b/libnl-3.sym
@@ -68,6 +68,7 @@ global:
 	nl_cache_get_ops;
 	nl_cache_get_prev;
 	nl_cache_include;
+	nl_cache_include_v2;
 	nl_cache_is_empty;
 	nl_cache_mark_all;
 	nl_cache_mngr_add;
@@ -82,6 +83,7 @@ global:
 	nl_cache_mngt_register;
 	nl_cache_mngt_require;
 	nl_cache_mngt_require_safe;
+	nl_cache_mngr_set_change_func_v2;
 	nl_cache_mngt_unprovide;
 	nl_cache_mngt_unregister;
 	nl_cache_move;
-- 
2.7.4




More information about the libnl mailing list