[PATCH 1/3] Allow override of message type during link change

Jef Oliver jef.oliver at intel.com
Fri Aug 26 19:19:49 PDT 2016


When rtnl_link_build_change_request() builds a change request,
it sets the message type to RTM_NEWLINK by default. If the
request fails, it changes the type to RTM_SETLINK, and resubmits.

For some address families, this will result in a requested change
never being applied by the kernel. An exmaple of this is the Linux
bridge. When a netlink message of type RTM_NEWLINK is recieved,
rather than failing, it simply ignores the message and does not
return a failure.

To fix this, this patch implements an override for address
families that require it. The override can be set when an address
family registers itself in libnl.

This patch adds ao_override_rtm to the rtnl_link_af_ops structure.
This patch adds a static function named af_request_type.
This patch modifies rtnl_link_build_change_request to call
  af_request_type to properly set the request type if an address
  family wishes to override.

Signed-off-by: Jef Oliver <jef.oliver at intel.com>
---
 include/netlink-private/route/link/api.h |  8 ++++++++
 lib/route/link.c                         | 17 +++++++++++++++--
 2 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/include/netlink-private/route/link/api.h b/include/netlink-private/route/link/api.h
index 1a793c8..1cda72e 100644
--- a/include/netlink-private/route/link/api.h
+++ b/include/netlink-private/route/link/api.h
@@ -146,6 +146,14 @@ struct rtnl_link_af_ops
 	 */
 	int		      (*ao_compare)(struct rtnl_link *,
 					    struct rtnl_link *, int, uint32_t, int);
+
+	/* RTM_NEWLINK override
+	 *
+	 * Called if a change link request is set to the kernel. If this is set
+	 * to anything other than zero, RTM_NEWLINK will be overriden with
+	 * RTM_SETLINK when rtnl_link_build_change_request() is called.
+	 */
+	const int ao_override_rtm;
 };
 
 extern struct rtnl_link_af_ops *rtnl_link_af_ops_lookup(unsigned int);
diff --git a/lib/route/link.c b/lib/route/link.c
index a18e885..7b687e9 100644
--- a/lib/route/link.c
+++ b/lib/route/link.c
@@ -108,6 +108,17 @@ static int af_free(struct rtnl_link *link, struct rtnl_link_af_ops *ops,
 	return 0;
 }
 
+static int af_request_type(int af_type)
+{
+	struct rtnl_link_af_ops *ops;
+
+	ops = rtnl_link_af_ops_lookup(af_type);
+	if (ops && ops->ao_override_rtm)
+		return RTM_SETLINK;
+
+	return RTM_NEWLINK;
+}
+
 static int af_clone(struct rtnl_link *link, struct rtnl_link_af_ops *ops,
 		    void *data, void *arg)
 {
@@ -1576,7 +1587,7 @@ int rtnl_link_build_change_request(struct rtnl_link *orig,
 		.ifi_family = orig->l_family,
 		.ifi_index = orig->l_index,
 	};
-	int err;
+	int err, rt;
 
 	if (changes->ce_mask & LINK_ATTR_FLAGS) {
 		ifi.ifi_flags = orig->l_flags & ~changes->l_flag_mask;
@@ -1596,7 +1607,9 @@ int rtnl_link_build_change_request(struct rtnl_link *orig,
 	    !strcmp(orig->l_name, changes->l_name))
 		changes->ce_mask &= ~LINK_ATTR_IFNAME;
 
-	if ((err = build_link_msg(RTM_NEWLINK, &ifi, changes, flags, result)) < 0)
+	rt = af_request_type(orig->l_family);
+
+	if ((err = build_link_msg(rt, &ifi, changes, flags, result)) < 0)
 		goto errout;
 
 	return 0;
-- 
2.9.3




More information about the libnl mailing list