[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