[From nobody Sun May 29 05:38:44 2016
Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO
 zmta03.collab.prod.int.phx2.redhat.com) (10.5.81.10) by
 zmail21.collab.prod.int.phx2.redhat.com with LMTP; Mon, 2 Nov 2015 17:29:06
 -0500 (EST)
Received: from int-mx09.intmail.prod.int.phx2.redhat.com
 (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by
 zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 8349342E5F
 for &lt;thaller@mail.corp.redhat.com&gt;; Mon,  2 Nov 2015 17:29:06 -0500 (EST)
Received: from mx1.redhat.com (ext-mx07.extmail.prod.ext.phx2.redhat.com
 [10.5.110.31]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4)
 with ESMTP id tA2MT6X6016317 (version=TLSv1/SSLv3
 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for
 &lt;thaller@redhat.com&gt;; Mon, 2 Nov 2015 17:29:06 -0500
Received: from mail-pa0-f47.google.com (mail-pa0-f47.google.com
 [209.85.220.47]) by mx1.redhat.com (Postfix) with ESMTPS id 597D7C1C74E2
 for &lt;thaller@redhat.com&gt;; Mon,  2 Nov 2015 22:29:05 +0000 (UTC)
Received: by pacfv9 with SMTP id fv9so167698384pac.3 for
 &lt;thaller@redhat.com&gt;; Mon, 02 Nov 2015 14:29:04 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
 d=cumulusnetworks.com; s=google; h=from:to:cc:subject:date:message-id;
 bh=tnccFOIM2mFrqqTXGPCSh1cMYtWXyVlMFuWOV3LGLmM=;
 b=J3mKvrcZlKkgYDjX1yF9wS/me5axe/Ng9YttddT4WVYogOaVqONnY0fAaqYVo2YeAZ
 GvD1Y543vG2V6rSbIPDqO3DLnUM0yxJ9/l8q8ZiNLU46j1P5pMU6Cf5Nowm2/93klU2+
 5Ieu2bNRmMg4z5tWvh5+fzkkUdTtZH5pXVn1U=
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net;
 s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id;
 bh=tnccFOIM2mFrqqTXGPCSh1cMYtWXyVlMFuWOV3LGLmM=;
 b=HYiwJ1BLTz4Hosid4hRA9lrQdMwjZ9tg8dgCuV/jMD+bAz1jZlnmsrC5Nu91flHiiC
 FMga5iedVGsi6XbygaXj7T99ICJ7963mb4YOiiviJ2uG9K0niLGdAxTCGyIN6rUJf8j3
 BnTXfo+vfDPejm+mdgZ9uTuRe70XcFa9S5tT0KwmFkU91cpAy+5klKh7yToKheyJPRLM
 JNpO2F4t9dM8vNfwY41cm2Yze8N4Z7OhE1OecLTuw9cmX/PgUh7QkxbrRmPG8mrNMQ5L
 sk+uUiHENDNItVR+AGbtFevuIHMNSFwzBRdWzLFBD2FRbExswzRTJAbWLkMl/bepASip jR1A==
X-Gm-Message-State: ALoCoQm0E2UKopF41hHB36BQTIbxeUcYlEBxPf8R8+I7lxeKTmQOSFOjHXoizV1m5V1+gNHZcfXr
X-Received: by 10.68.94.100 with SMTP id db4mr11101901pbb.67.1446501938384;
 Mon, 02 Nov 2015 14:05:38 -0800 (PST)
Received: from hydra-01.cumulusnetworks.com ([216.129.126.126]) by
 smtp.googlemail.com with ESMTPSA id bz1sm25892966pab.20.2015.11.02.14.05.37
 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 02
 Nov 2015 14:05:37 -0800 (PST)
From: Roopa Prabhu &lt;roopa@cumulusnetworks.com&gt;
X-Google-Original-From: Roopa Prabhu
To: libnl@lists.infradead.org
Cc: thaller@redhat.com, roopa@cumulusnetworks.com
Subject: [PATCH 3/6] cache: modify nl_cache_search to look at cache
 provided attributes for search
Date: Mon,  2 Nov 2015 14:05:26 -0800
Message-Id: &lt;1446501929-32003-4-git-send-email-roopa@cumulusnetworks.com&gt;
X-RedHat-Spam-Score: 2.099 **
 (ANY_BOUNCE_MESSAGE, BAYES_50, BOUNCE_MESSAGE, DCC_REPUT_13_19, DKIM_SIGNED,
 DKIM_VALID, DKIM_VALID_AU, DSN_NO_MIMEVERSION, RCVD_IN_DNSWL_LOW,
 RCVD_IN_MSPIKE_H2, URIBL_BLOCKED)
 209.85.220.47 mail-pa0-f47.google.com 209.85.220.47 mail-pa0-f47.google.com
 &lt;&gt;
X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22
X-Scanned-By: MIMEDefang 2.78 on 10.5.110.31
Mime-Version: 1.0
Content-Transfer-Encoding: quoted-printable

From: Roopa Prabhu &lt;roopa@cumulusnetworks.com&gt;

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 &lt;roopa@cumulusnetworks.com&gt;
---
 include/netlink-private/cache-api.h |   15 ++++++++++
 include/netlink/cache.h             |    3 ++
 include/netlink/hashtable.h         |    2 ++
 include/netlink/object.h            |    2 ++
 lib/cache.c                         |   56 +++++++++++++++++++++++++++++++=
++++
 lib/hashtable.c                     |   34 +++++++++++++++++++++
 lib/object.c                        |   11 +++++++
 7 files changed, 123 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);
=20
+	/**
+	 * 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 *, unsig=
ned 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,
=20
 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);
=20
diff --git a/include/netlink/object.h b/include/netlink/object.h
index a95feda..c28f712 100644
--- a/include/netlink/object.h
+++ b/include/netlink/object.h
@@ -43,6 +43,8 @@ extern int			nl_object_identical(struct nl_object *,
 						    struct nl_object *);
 extern uint32_t			nl_object_diff(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 =3D nl_hash_table_lookup_mask(cache-&gt;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-&gt;hashtable)
+		return __cache_fast_lookup_mask(cache, needle, mask);
+
+	nl_list_for_each_entry(obj, &amp;cache-&gt;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 *c=
ache,
 				  struct nl_object *needle)
 {
 	struct nl_object *obj;
+	uint32_t mask;
+
+	if (cache-&gt;c_ops-&gt;co_cache_search_attrs_get) {
+		mask =3D cache-&gt;c_ops-&gt;co_cache_search_attrs_get(cache, needle);
+		if (mask)
+			return nl_cache_search_mask(cache, needle, mask);
+	}
=20
 	if (cache-&gt;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,
 }
=20
 /**
+ * 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 calli=
ng
+ * `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, &amp;key_hash, ht-&gt;size);
+	head =3D ht-&gt;nodes[key_hash];
+
+	if (!head)
+		return NULL;
+
+	nl_list_for_each_entry(node, &amp;head-&gt;list, list) {
+	       if (!nl_object_diff_mask(node-&gt;obj, obj, mask))
+		   return node-&gt;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 cad24e0..bf9c084 100644
--- a/lib/object.c
+++ b/lib/object.c
@@ -368,6 +368,17 @@ uint32_t nl_object_diff(struct nl_object *a, struct nl=
_object *b)
 	return ops-&gt;oo_compare(a, b, ~0, 0);
 }
=20
+uint32_t nl_object_diff_mask(struct nl_object *a, struct nl_object *b,
+		uint32_t mask)
+{
+	struct nl_object_ops *ops =3D obj_ops(a);
+
+	if (ops !=3D obj_ops(b) || ops-&gt;oo_compare =3D=3D NULL)
+		return UINT_MAX;
+
+	return ops-&gt;oo_compare(a, b, mask, 0);
+}
+
 /**
  * Match a filter against an object
  * @arg obj		object to check
--=20
1.7.10.4

]