[PATCH libnl v2 2/5] cache: modify nl_cache_search to look at cache provided attributes for search

David Ahern dsa at cumulusnetworks.com
Sat Jun 18 15:30:06 PDT 2016


From: Roopa Prabhu <roopa at cumulusnetworks.com>

This patch adds a new cache operation co_cache_search_attrs_get to request for
attributes to use in the search. This gives the cache an opportunity to
use search attributes based on netlink message flags.

This is mainly to give the route cache an ability to decide on the cache
inclusion depending on the netlink header flags like NLM_F_APPEND and
NLM_F_REPLACE.

Signed-off-by: Roopa Prabhu <roopa at cumulusnetworks.com>
---
 include/netlink-private/cache-api.h | 15 ++++++++++
 include/netlink/cache.h             |  3 ++
 include/netlink/hashtable.h         |  2 ++
 include/netlink/object.h            |  3 ++
 lib/cache.c                         | 56 +++++++++++++++++++++++++++++++++++++
 lib/hashtable.c                     | 34 ++++++++++++++++++++++
 lib/object.c                        | 11 ++++++++
 7 files changed, 124 insertions(+)

diff --git a/include/netlink-private/cache-api.h b/include/netlink-private/cache-api.h
index f3d9f01..0b39bfa 100644
--- a/include/netlink-private/cache-api.h
+++ b/include/netlink-private/cache-api.h
@@ -239,6 +239,21 @@ struct nl_cache_ops
 	int   (*co_include_event)(struct nl_cache *cache, struct nl_object *obj,
 				  change_func_t change_cb, void *data);
 
+	/**
+	 * The function registered under this callback is called when an
+	 * a nl_cache_search is to performed on the cache.
+	 *
+	 * The callback if implemented by a cache must return an attribute
+	 * mask to be used for the cache search
+	 *
+	 * If no function is registered, nl_cache_search will internally use
+	 * oo_id_attrs_get to get its attributes for matching objects
+	 *
+	 * @see nl_cache_search()
+	 */
+	uint32_t (*co_cache_search_attrs_get)(struct nl_cache *cache,
+					      struct nl_object *needle);
+
 	void (*reserved_1)(void);
 	void (*reserved_2)(void);
 	void (*reserved_3)(void);
diff --git a/include/netlink/cache.h b/include/netlink/cache.h
index 71eaceb..7077f2e 100644
--- a/include/netlink/cache.h
+++ b/include/netlink/cache.h
@@ -96,6 +96,9 @@ extern void			nl_cache_set_flags(struct nl_cache *, unsigned int);
 extern int			nl_cache_is_empty(struct nl_cache *);
 extern struct nl_object *	nl_cache_search(struct nl_cache *,
 						struct nl_object *);
+extern struct nl_object *       nl_cache_search_mask(struct nl_cache *,
+						     struct nl_object *,
+						     uint32_t);
 extern struct nl_object *nl_cache_find(struct nl_cache *,
 				       struct nl_object *);
 extern void			nl_cache_mark_all(struct nl_cache *);
diff --git a/include/netlink/hashtable.h b/include/netlink/hashtable.h
index 70d8c0f..c52f6e1 100644
--- a/include/netlink/hashtable.h
+++ b/include/netlink/hashtable.h
@@ -42,6 +42,8 @@ extern int			nl_hash_table_del(nl_hash_table_t *ht,
 
 extern struct nl_object *	nl_hash_table_lookup(nl_hash_table_t *ht,
 						     struct nl_object *obj);
+extern struct nl_object *	nl_hash_table_lookup_mask(nl_hash_table_t *ht,
+						     struct nl_object *obj, uint32_t);
 extern uint32_t 		nl_hash(void *k, size_t length,
 					uint32_t initval);
 
diff --git a/include/netlink/object.h b/include/netlink/object.h
index b0c32c9..e442f0f 100644
--- a/include/netlink/object.h
+++ b/include/netlink/object.h
@@ -45,6 +45,9 @@ extern uint32_t			nl_object_diff(struct nl_object *,
 					       struct nl_object *);
 extern uint64_t			nl_object_diff64(struct nl_object *,
 						 struct nl_object *);
+extern uint32_t			nl_object_diff_mask(struct nl_object *,
+						    struct nl_object *,
+						    uint32_t);
 extern int			nl_object_match_filter(struct nl_object *,
 						       struct nl_object *);
 extern char *			nl_object_attrs2str(struct nl_object *,
diff --git a/lib/cache.c b/lib/cache.c
index 9aba0c9..9b69fe8 100644
--- a/lib/cache.c
+++ b/lib/cache.c
@@ -1031,6 +1031,21 @@ restart:
  * @name Utillities
  * @{
  */
+static struct nl_object *__cache_fast_lookup_mask(struct nl_cache *cache,
+						  struct nl_object *needle,
+						  uint32_t mask)
+{
+	struct nl_object *obj;
+
+	obj = nl_hash_table_lookup_mask(cache->hashtable, needle, mask);
+	if (obj) {
+	    nl_object_get(obj);
+	    return obj;
+	}
+
+	return NULL;
+}
+
 static struct nl_object *__cache_fast_lookup(struct nl_cache *cache,
 					     struct nl_object *needle)
 {
@@ -1049,6 +1064,40 @@ static struct nl_object *__cache_fast_lookup(struct nl_cache *cache,
  * Search object in cache
  * @arg cache		Cache
  * @arg needle		Object to look for.
+ * @arg mask		Attribute mask to use during object comparision
+ *
+ * Searches the cache for an object which matches the object \p needle.
+ * The function nl_object_diff_mask() is used to determine if the
+ * objects match. If a matching object is found, the reference counter
+ * is incremented and the object is returned.
+ *
+ * Therefore, if an object is returned, the reference to the object
+ * must be returned by calling nl_object_put() after usage.
+ *
+ * @return Reference to object or NULL if not found.
+ */
+struct nl_object *nl_cache_search_mask(struct nl_cache *cache,
+				       struct nl_object *needle, uint32_t mask)
+{
+	struct nl_object *obj;
+
+	if (cache->hashtable)
+		return __cache_fast_lookup_mask(cache, needle, mask);
+
+	nl_list_for_each_entry(obj, &cache->c_items, ce_list) {
+		if (!nl_object_diff_mask(obj, needle, mask)) {
+			nl_object_get(obj);
+			return obj;
+		}
+	}
+
+	return NULL;
+}
+
+/**
+ * Search object in cache
+ * @arg cache		Cache
+ * @arg needle		Object to look for.
  *
  * Searches the cache for an object which matches the object \p needle.
  * The function nl_object_identical() is used to determine if the
@@ -1064,6 +1113,13 @@ struct nl_object *nl_cache_search(struct nl_cache *cache,
 				  struct nl_object *needle)
 {
 	struct nl_object *obj;
+	uint32_t mask;
+
+	if (cache->c_ops->co_cache_search_attrs_get) {
+		mask = cache->c_ops->co_cache_search_attrs_get(cache, needle);
+		if (mask)
+			return nl_cache_search_mask(cache, needle, mask);
+	}
 
 	if (cache->hashtable)
 		return __cache_fast_lookup(cache, needle);
diff --git a/lib/hashtable.c b/lib/hashtable.c
index 75e9fda..7652e6b 100644
--- a/lib/hashtable.c
+++ b/lib/hashtable.c
@@ -116,6 +116,40 @@ struct nl_object* nl_hash_table_lookup(nl_hash_table_t *ht,
 }
 
 /**
+ * Lookup identical object in hashtable
+ * @arg ht		Hashtable
+ * @arg obj		Object to lookup
+ * @arg mask		Attribute mask to use during lookup
+ *
+ * Generates hashkey for `obj` and traverses the corresponding chain calling
+ * `nl_object_diff_mask()` on each trying to find a match. similar to
+ * nl_hash_table_lookup but uses an user provided attribute mask.
+ *
+ * @return Pointer to object if match was found or NULL.
+ */
+
+struct nl_object* nl_hash_table_lookup_mask(nl_hash_table_t *ht,
+					    struct nl_object *obj,
+					    uint32_t mask)
+{
+	nl_hash_node_t *node, *head;
+	uint32_t key_hash;
+
+	nl_object_keygen(obj, &key_hash, ht->size);
+	head = ht->nodes[key_hash];
+
+	if (!head)
+		return NULL;
+
+	nl_list_for_each_entry(node, &head->list, list) {
+	       if (!nl_object_diff_mask(node->obj, obj, mask))
+		   return node->obj;
+	}
+
+	return NULL;
+}
+
+/**
  * Add object to hashtable
  * @arg ht		Hashtable
  * @arg obj		Object to add
diff --git a/lib/object.c b/lib/object.c
index a88ac00..c2bc9c5 100644
--- a/lib/object.c
+++ b/lib/object.c
@@ -393,6 +393,17 @@ uint32_t nl_object_diff(struct nl_object *a, struct nl_object *b)
 		: (uint32_t) diff;
 }
 
+uint32_t nl_object_diff_mask(struct nl_object *a, struct nl_object *b,
+		uint32_t mask)
+{
+	struct nl_object_ops *ops = obj_ops(a);
+
+	if (ops != obj_ops(b) || ops->oo_compare == NULL)
+		return UINT_MAX;
+
+	return ops->oo_compare(a, b, mask, 0);
+}
+
 /**
  * Match a filter against an object
  * @arg obj		object to check
-- 
2.1.4




More information about the libnl mailing list