[RFC PATCH 2/5] Add support for updating objects in the cache

roopa at cumulusnetworks.com roopa at cumulusnetworks.com
Mon Nov 5 08:37:35 EST 2012


From: roopa <roopa at cumulusnetworks.com>

This patch adds support to update a cache object during cache_include instead
of the current approach of deleting the original object and adding a new one.
This operation is conditional on the object implementing the operation. If
the update is not successful, cache_include falls back to the existing cache
inclusion process of deleting and adding the object.

It adds a new object operation called oo_update. oo_update takes two objects
as arguments, first being the existing cache object that needs update, the
second argument being the new object. Currently it is left to the implementor
to use the msg type to decide wether to delete or add the new object attributes
to the old one. But the operation type or msg type can be easily made part of the
object arguments.

The motivation for this change is explained below in the context of including
support for AF_BRIDGE objects into the link cache.

libnl today deletes an object before it includes an identical object.
But for some objects like the AF_BRIDGE objects this does not work well.
link cache uses the ifindex as its key in object searches.
If link cache were to support AF_BRIDGE family objects, todays implementation,
	- will replace the original link object with the bridge port link object
	  for add notifications
	- And a bridge port delete notification from kernel would delete the
	link object from the cache leaving the cache without the link object
	until the kernel sends another notification for that link

The bridge port link notification contains some base link object attributes
plus bridge specific protocol info attributes. In such cases we think an
operation to update the existing object in place in cache might be useful.

This can be made to work for AF_INET6 link objects too.


Signed-off-by: Roopa Prabhu <roopa at cumulusnetworks.com>
Reviewed-by: Nolan Leake <nolan at cumulusnetworks.com>
Reviewed-by: Shrijeet Mukherjee <shm at cumulusnetworks.com>
Reviewed-by: Wilson Kok <wkok at cumulusnetworks.com>
---
 include/netlink/object-api.h |   12 ++++++++++++
 include/netlink/object.h     |    1 +
 lib/cache.c                  |   11 +++++++++++
 lib/object.c                 |   17 +++++++++++++++++
 4 files changed, 41 insertions(+), 0 deletions(-)

diff --git a/include/netlink/object-api.h b/include/netlink/object-api.h
index 70a4ddd..0f0b6bc 100644
--- a/include/netlink/object-api.h
+++ b/include/netlink/object-api.h
@@ -336,6 +336,18 @@ struct nl_object_ops
 			    uint32_t, int);
 
 
+	/**
+	 * update function
+	 *
+	 * Will be called when the object given by first argument
+	 * needs to be updated with the contents of the second object
+	 *
+	 * The function must return 0 for success and error for failure
+	 * to update. In case of failure its assumed that the original
+	 * object is not touched
+	 */
+	int   (*oo_update)(struct nl_object *, struct nl_object *);
+
 	char *(*oo_attrs2str)(int, char *, size_t);
 };
 
diff --git a/include/netlink/object.h b/include/netlink/object.h
index bbda5f5..ad2cf1e 100644
--- a/include/netlink/object.h
+++ b/include/netlink/object.h
@@ -31,6 +31,7 @@ extern int			nl_object_alloc_name(const char *,
 						     struct nl_object **);
 extern void			nl_object_free(struct nl_object *);
 extern struct nl_object *	nl_object_clone(struct nl_object *obj);
+extern int nl_object_update(struct nl_object *dst, struct nl_object *src);
 extern void			nl_object_get(struct nl_object *);
 extern void			nl_object_put(struct nl_object *);
 extern int			nl_object_shared(struct nl_object *);
diff --git a/lib/cache.c b/lib/cache.c
index 45a1a27..f73fedf 100644
--- a/lib/cache.c
+++ b/lib/cache.c
@@ -642,6 +642,17 @@ static int cache_include(struct nl_cache *cache, struct nl_object *obj,
 	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 (nl_object_update(old, obj) == 0) {
+				cb(cache, old, NL_ACT_CHANGE, data);
+				nl_object_put(obj);
+				return 0;
+			}
+
 			nl_cache_remove(old);
 			if (type->mt_act == NL_ACT_DEL) {
 				if (cb)
diff --git a/lib/object.c b/lib/object.c
index 055a208..84eb004 100644
--- a/lib/object.c
+++ b/lib/object.c
@@ -139,6 +139,23 @@ struct nl_object *nl_object_clone(struct nl_object *obj)
 }
 
 /**
+ * Merge a cacheable object
+ * @arg dst		object to be merged into
+ * @arg src		new object to be merged into dst
+ *
+ * @return 0 or a negative error code.
+ */
+int nl_object_update(struct nl_object *dst, struct nl_object *src)
+{
+	struct nl_object_ops *ops = obj_ops(dst);
+
+	if (ops->oo_update)
+		return ops->oo_update(dst, src);
+
+	return -NLE_OPNOTSUPP;
+}
+
+/**
  * Free a cacheable object
  * @arg obj		object to free
  *
-- 
1.7.2.5




More information about the libnl mailing list