[PATCH] link/neigh: Add flags option to link and neighbor caches

David Ahern dsa at cumulusnetworks.com
Tue Oct 27 15:40:48 PDT 2015


Both link and neighbor cache support specify multiple groups (nl_af_group),
but the alloc_cache functions for both do not set the NL_CACHE_AF_ITER
flag before populating the cache so only the first group is used by
default. This patch adds an API to pass in flags to make that happen
and updates the nl-neigh-list command to make use of it.

Signed-off-by: David Ahern <dsa at cumulusnetworks.com>
---

Noticed this shortcoming testing the NTF_SELF patch. With this patch
I get the bridge fdb as well as the arp and ndisc tables.

 include/netlink/cli/link.h        |  4 ++++
 include/netlink/cli/neigh.h       |  3 ++-
 include/netlink/cli/utils.h       |  4 ++++
 include/netlink/route/link.h      |  3 +++
 include/netlink/route/neighbour.h |  3 +++
 lib/route/link.c                  | 39 +++++++++++++++++++++++++++++++++++++--
 lib/route/neigh.c                 | 32 ++++++++++++++++++++++++++++++++
 libnl-cli-3.sym                   |  7 +++++++
 libnl-route-3.sym                 |  6 ++++++
 src/lib/link.c                    | 17 +++++++++++++++--
 src/lib/utils.c                   | 17 +++++++++++++++++
 src/nl-neigh-list.c               |  2 +-
 12 files changed, 131 insertions(+), 6 deletions(-)

diff --git a/include/netlink/cli/link.h b/include/netlink/cli/link.h
index 3f37948d9713..f2c720bad2d4 100644
--- a/include/netlink/cli/link.h
+++ b/include/netlink/cli/link.h
@@ -17,7 +17,11 @@
 
 extern struct rtnl_link *nl_cli_link_alloc(void);
 extern struct nl_cache *nl_cli_link_alloc_cache_family(struct nl_sock *, int);
+extern struct nl_cache *nl_cli_link_alloc_cache_family_flags(struct nl_sock *, int,
+							     unsigned int);
 extern struct nl_cache *nl_cli_link_alloc_cache(struct nl_sock *);
+extern struct nl_cache *nl_cli_link_alloc_cache_flags(struct nl_sock *,
+						      unsigned int);
 
 extern void nl_cli_link_parse_family(struct rtnl_link *, char *);
 extern void nl_cli_link_parse_name(struct rtnl_link *, char *);
diff --git a/include/netlink/cli/neigh.h b/include/netlink/cli/neigh.h
index 5440012884c8..1c1be91b09bc 100644
--- a/include/netlink/cli/neigh.h
+++ b/include/netlink/cli/neigh.h
@@ -15,7 +15,8 @@
 #include <netlink/route/neighbour.h>
 
 #define nl_cli_neigh_alloc_cache(sk) \
-		nl_cli_alloc_cache((sk), "neighbour", rtnl_neigh_alloc_cache)
+		nl_cli_alloc_cache_flags((sk), "neighbour", NL_CACHE_AF_ITER, \
+					 rtnl_neigh_alloc_cache_flags)
 
 extern struct rtnl_neigh *nl_cli_neigh_alloc(void);
 extern void nl_cli_neigh_parse_dst(struct rtnl_neigh *, char *);
diff --git a/include/netlink/cli/utils.h b/include/netlink/cli/utils.h
index da41c10ef8ea..ea89fc63f1c9 100644
--- a/include/netlink/cli/utils.h
+++ b/include/netlink/cli/utils.h
@@ -73,6 +73,10 @@ extern int		nl_cli_confirm(struct nl_object *,
 extern struct nl_cache *nl_cli_alloc_cache(struct nl_sock *, const char *,
 			     int (*ac)(struct nl_sock *, struct nl_cache **));
 
+extern struct nl_cache *nl_cli_alloc_cache_flags(struct nl_sock *, const char *,
+			     unsigned int flags,
+			     int (*ac)(struct nl_sock *, struct nl_cache **, unsigned int));
+
 extern void		nl_cli_load_module(const char *, const char *);
 
 #ifdef __cplusplus
diff --git a/include/netlink/route/link.h b/include/netlink/route/link.h
index f7303f2ffd69..23b018368aee 100644
--- a/include/netlink/route/link.h
+++ b/include/netlink/route/link.h
@@ -109,6 +109,9 @@ extern struct rtnl_link *rtnl_link_alloc(void);
 extern void	rtnl_link_put(struct rtnl_link *);
 
 extern int	rtnl_link_alloc_cache(struct nl_sock *, int, struct nl_cache **);
+extern int	rtnl_link_alloc_cache_flags(struct nl_sock *, int,
+					    struct nl_cache **,
+					    unsigned int flags);
 extern struct rtnl_link *rtnl_link_get(struct nl_cache *, int);
 extern struct rtnl_link *rtnl_link_get_by_name(struct nl_cache *, const char *);
 
diff --git a/include/netlink/route/neighbour.h b/include/netlink/route/neighbour.h
index b653cff9672a..fb98113ac766 100644
--- a/include/netlink/route/neighbour.h
+++ b/include/netlink/route/neighbour.h
@@ -26,6 +26,9 @@ extern struct rtnl_neigh *rtnl_neigh_alloc(void);
 extern void	rtnl_neigh_put(struct rtnl_neigh *);
 
 extern int	rtnl_neigh_alloc_cache(struct nl_sock *, struct nl_cache **);
+extern int	rtnl_neigh_alloc_cache_flags(struct nl_sock *,
+					     struct nl_cache **,
+					     unsigned int);
 extern struct rtnl_neigh *rtnl_neigh_get(struct nl_cache *, int,
 					       struct nl_addr *);
 
diff --git a/lib/route/link.c b/lib/route/link.c
index 5c3255022dff..6dc416b22f0d 100644
--- a/lib/route/link.c
+++ b/lib/route/link.c
@@ -1008,6 +1008,7 @@ static char *link_attrs2str(int attrs, char *buf, size_t len)
  * @arg sk		Netlink socket.
  * @arg family		Link address family or AF_UNSPEC
  * @arg result		Pointer to store resulting cache.
+ * @arg flags		Flags to set in link cache before filling
  *
  * Allocates and initializes a new link cache. If \c sk is valid, a netlink
  * message is sent to the kernel requesting a full dump of all configured
@@ -1027,7 +1028,8 @@ static char *link_attrs2str(int attrs, char *buf, size_t len)
  * @see rtnl_link_get_by_name()
  * @return 0 on success or a negative error code.
  */
-int rtnl_link_alloc_cache(struct nl_sock *sk, int family, struct nl_cache **result)
+int rtnl_link_alloc_cache_flags(struct nl_sock *sk, int family,
+				struct nl_cache **result, unsigned int flags)
 {
 	struct nl_cache * cache;
 	int err;
@@ -1037,7 +1039,10 @@ int rtnl_link_alloc_cache(struct nl_sock *sk, int family, struct nl_cache **resu
 		return -NLE_NOMEM;
 
 	cache->c_iarg1 = family;
-	
+
+	if (flags)
+		nl_cache_set_flags(cache, flags);
+
 	if (sk && (err = nl_cache_refill(sk, cache)) < 0) {
 		nl_cache_free(cache);
 		return err;
@@ -1048,6 +1053,36 @@ int rtnl_link_alloc_cache(struct nl_sock *sk, int family, struct nl_cache **resu
 }
 
 /**
+ * Allocate link cache and fill in all configured links.
+ * @arg sk		Netlink socket.
+ * @arg family		Link address family or AF_UNSPEC
+ * @arg result		Pointer to store resulting cache.
+ *
+ * Allocates and initializes a new link cache. If \c sk is valid, a netlink
+ * message is sent to the kernel requesting a full dump of all configured
+ * links. The returned messages are parsed and filled into the cache. If
+ * the operation succeeds, the resulting cache will contain a link object for
+ * each link configured in the kernel. If \c sk is NULL, returns 0 but the
+ * cache is still empty.
+ *
+ * If \c family is set to an address family other than \c AF_UNSPEC the
+ * contents of the cache can be limited to a specific address family.
+ * Currently the following address families are supported:
+ * - AF_BRIDGE
+ * - AF_INET6
+ *
+ * @route_doc{link_list, Get List of Links}
+ * @see rtnl_link_get()
+ * @see rtnl_link_get_by_name()
+ * @return 0 on success or a negative error code.
+ */
+int rtnl_link_alloc_cache(struct nl_sock *sk, int family, struct nl_cache **result)
+{
+	return rtnl_link_alloc_cache_flags(sk, family, result, 0);
+}
+
+
+/**
  * Lookup link in cache by interface index
  * @arg cache		Link cache
  * @arg ifindex		Interface index
diff --git a/lib/route/neigh.c b/lib/route/neigh.c
index ab07ec9cc8d3..6059e7f4d8f3 100644
--- a/lib/route/neigh.c
+++ b/lib/route/neigh.c
@@ -546,6 +546,38 @@ int rtnl_neigh_alloc_cache(struct nl_sock *sock, struct nl_cache **result)
 }
 
 /**
+ * Build a neighbour cache including all neighbours currently configured in the kernel.
+ * @arg sock		Netlink socket.
+ * @arg result		Pointer to store resulting cache.
+ * @arg flags		Flags to apply to cache before filling
+ *
+ * Allocates a new neighbour cache, initializes it properly and updates it
+ * to include all neighbours currently configured in the kernel.
+ *
+ * @return 0 on success or a negative error code.
+ */
+int rtnl_neigh_alloc_cache_flags(struct nl_sock *sock, struct nl_cache **result,
+				 unsigned int flags)
+{
+	struct nl_cache * cache;
+	int err;
+
+	cache = nl_cache_alloc(&rtnl_neigh_ops);
+	if (!cache)
+		return -NLE_NOMEM;
+
+	nl_cache_set_flags(cache, flags);
+
+	if (sock && (err = nl_cache_refill(sock, cache)) < 0) {
+		nl_cache_free(cache);
+		return err;
+	}
+
+	*result = cache;
+	return 0;
+}
+
+/**
  * Look up a neighbour by interface index and destination address
  * @arg cache		neighbour cache
  * @arg ifindex		interface index the neighbour is on
diff --git a/libnl-cli-3.sym b/libnl-cli-3.sym
index 3d433f642af9..71ff2ebebaa2 100644
--- a/libnl-cli-3.sym
+++ b/libnl-cli-3.sym
@@ -108,3 +108,10 @@ libnl_3 {
 local:
 	*;
 };
+
+libnl_3_2_28 {
+global:
+	nl_cli_alloc_cache_flags;
+	nl_cli_link_alloc_cache_flags;
+	nl_cli_link_alloc_cache_family_flags;
+} libnl_3;
diff --git a/libnl-route-3.sym b/libnl-route-3.sym
index c6a7832ac6dc..8107d8fa775c 100644
--- a/libnl-route-3.sym
+++ b/libnl-route-3.sym
@@ -884,3 +884,9 @@ libnl_3_2_27 {
 	rtnl_link_ipvlan_get_mode;
 	rtnl_link_set_link_netnsid;
 } libnl_3_2_26;
+
+libnl_3_2_28 {
+global:
+	rtnl_link_alloc_cache_flags;
+	rtnl_neigh_alloc_cache_flags;
+} libnl_3_2_27;
diff --git a/src/lib/link.c b/src/lib/link.c
index 5bce82404f62..eb5b54bf5742 100644
--- a/src/lib/link.c
+++ b/src/lib/link.c
@@ -31,12 +31,14 @@ struct rtnl_link *nl_cli_link_alloc(void)
 	return link;
 }
 
-struct nl_cache *nl_cli_link_alloc_cache_family(struct nl_sock *sock, int family)
+struct nl_cache *nl_cli_link_alloc_cache_family_flags(struct nl_sock *sock,
+						      int family,
+						      unsigned int flags)
 {
 	struct nl_cache *cache;
 	int err;
 
-	if ((err = rtnl_link_alloc_cache(sock, family, &cache)) < 0)
+	if ((err = rtnl_link_alloc_cache_flags(sock, family, &cache, flags)) < 0)
 		nl_cli_fatal(err, "Unable to allocate link cache: %s",
 			     nl_geterror(err));
 
@@ -45,11 +47,22 @@ struct nl_cache *nl_cli_link_alloc_cache_family(struct nl_sock *sock, int family
 	return cache;
 }
 
+struct nl_cache *nl_cli_link_alloc_cache_family(struct nl_sock *sock, int family)
+{
+	return nl_cli_link_alloc_cache_family_flags(sock, family, 0);
+}
+
 struct nl_cache *nl_cli_link_alloc_cache(struct nl_sock *sock)
 {
 	return nl_cli_link_alloc_cache_family(sock, AF_UNSPEC);
 }
 
+struct nl_cache *nl_cli_link_alloc_cache_flags(struct nl_sock *sock,
+						unsigned int flags)
+{
+	return nl_cli_link_alloc_cache_family_flags(sock, AF_UNSPEC, flags);
+}
+
 void nl_cli_link_parse_family(struct rtnl_link *link, char *arg)
 {
 	int family;
diff --git a/src/lib/utils.c b/src/lib/utils.c
index e5eacdec3fc1..467aaed91b1e 100644
--- a/src/lib/utils.c
+++ b/src/lib/utils.c
@@ -180,6 +180,23 @@ struct nl_cache *nl_cli_alloc_cache(struct nl_sock *sock, const char *name,
 	return cache;
 }
 
+struct nl_cache *nl_cli_alloc_cache_flags(struct nl_sock *sock,
+			    const char *name, unsigned int flags,
+			    int (*ac)(struct nl_sock *, struct nl_cache **,
+				      unsigned int))
+{
+	struct nl_cache *cache;
+	int err;
+
+	if ((err = ac(sock, &cache, flags)) < 0)
+		nl_cli_fatal(err, "Unable to allocate %s cache: %s",
+			     name, nl_geterror(err));
+
+	nl_cache_mngt_provide(cache);
+
+	return cache;
+}
+
 void nl_cli_load_module(const char *prefix, const char *name)
 {
 	char path[FILENAME_MAX+1];
diff --git a/src/nl-neigh-list.c b/src/nl-neigh-list.c
index ebf54863a8e8..8390d4b2db28 100644
--- a/src/nl-neigh-list.c
+++ b/src/nl-neigh-list.c
@@ -45,7 +45,7 @@ int main(int argc, char *argv[])
  
 	sock = nl_cli_alloc_socket();
 	nl_cli_connect(sock, NETLINK_ROUTE);
-	link_cache = nl_cli_link_alloc_cache(sock);
+	link_cache = nl_cli_link_alloc_cache_flags(sock, NL_CACHE_AF_ITER);
 	neigh_cache = nl_cli_neigh_alloc_cache(sock);
  	neigh = nl_cli_neigh_alloc();
  
-- 
2.1.4




More information about the libnl mailing list