rtnetlink: place link af dump into own helper

next patch will rcu-ify rtnl af_ops, i.e. allow af_ops
lookup and function calls with rcu read lock held instead
of rtnl mutex.

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Florian Westphal 2017-10-16 15:44:35 +02:00 committed by David S. Miller
parent d85969f1a9
commit 070cbf5be7
1 changed files with 42 additions and 30 deletions

View File

@ -1382,6 +1382,47 @@ static int rtnl_fill_link_netnsid(struct sk_buff *skb,
return 0;
}
static int rtnl_fill_link_af(struct sk_buff *skb,
const struct net_device *dev,
u32 ext_filter_mask)
{
const struct rtnl_af_ops *af_ops;
struct nlattr *af_spec;
af_spec = nla_nest_start(skb, IFLA_AF_SPEC);
if (!af_spec)
return -EMSGSIZE;
list_for_each_entry(af_ops, &rtnl_af_ops, list) {
struct nlattr *af;
int err;
if (!af_ops->fill_link_af)
continue;
af = nla_nest_start(skb, af_ops->family);
if (!af)
return -EMSGSIZE;
err = af_ops->fill_link_af(skb, dev, ext_filter_mask);
/*
* Caller may return ENODATA to indicate that there
* was no data to be dumped. This is not an error, it
* means we should trim the attribute header and
* continue.
*/
if (err == -ENODATA)
nla_nest_cancel(skb, af);
else if (err < 0)
return -EMSGSIZE;
nla_nest_end(skb, af);
}
nla_nest_end(skb, af_spec);
return 0;
}
static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
int type, u32 pid, u32 seq, u32 change,
unsigned int flags, u32 ext_filter_mask,
@ -1389,8 +1430,6 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
{
struct ifinfomsg *ifm;
struct nlmsghdr *nlh;
struct nlattr *af_spec;
struct rtnl_af_ops *af_ops;
ASSERT_RTNL();
nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifm), flags);
@ -1477,36 +1516,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
nla_put_s32(skb, IFLA_NEW_NETNSID, *new_nsid) < 0)
goto nla_put_failure;
if (!(af_spec = nla_nest_start(skb, IFLA_AF_SPEC)))
if (rtnl_fill_link_af(skb, dev, ext_filter_mask))
goto nla_put_failure;
list_for_each_entry(af_ops, &rtnl_af_ops, list) {
if (af_ops->fill_link_af) {
struct nlattr *af;
int err;
if (!(af = nla_nest_start(skb, af_ops->family)))
goto nla_put_failure;
err = af_ops->fill_link_af(skb, dev, ext_filter_mask);
/*
* Caller may return ENODATA to indicate that there
* was no data to be dumped. This is not an error, it
* means we should trim the attribute header and
* continue.
*/
if (err == -ENODATA)
nla_nest_cancel(skb, af);
else if (err < 0)
goto nla_put_failure;
nla_nest_end(skb, af);
}
}
nla_nest_end(skb, af_spec);
nlmsg_end(skb, nlh);
return 0;