[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