Skip to content

Commit cc47bcd

Browse files
q2venPaolo Abeni
authored andcommitted
rtnetlink: Factorise do_setlink() path from __rtnl_newlink().
__rtnl_newlink() got too long to maintain. For example, netdev_master_upper_dev_get()->rtnl_link_ops is fetched even when IFLA_INFO_SLAVE_DATA is not specified. Let's factorise the single dev do_setlink() path to a separate function. Signed-off-by: Kuniyuki Iwashima <[email protected]> Reviewed-by: Eric Dumazet <[email protected]> Signed-off-by: Paolo Abeni <[email protected]>
1 parent a5838cf commit cc47bcd

File tree

1 file changed

+74
-68
lines changed

1 file changed

+74
-68
lines changed

net/core/rtnetlink.c

Lines changed: 74 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -3505,6 +3505,78 @@ struct net_device *rtnl_create_link(struct net *net, const char *ifname,
35053505
}
35063506
EXPORT_SYMBOL(rtnl_create_link);
35073507

3508+
struct rtnl_newlink_tbs {
3509+
struct nlattr *tb[IFLA_MAX + 1];
3510+
struct nlattr *linkinfo[IFLA_INFO_MAX + 1];
3511+
struct nlattr *attr[RTNL_MAX_TYPE + 1];
3512+
struct nlattr *slave_attr[RTNL_SLAVE_MAX_TYPE + 1];
3513+
};
3514+
3515+
static int rtnl_changelink(const struct sk_buff *skb, struct nlmsghdr *nlh,
3516+
const struct rtnl_link_ops *ops,
3517+
struct net_device *dev,
3518+
struct rtnl_newlink_tbs *tbs,
3519+
struct nlattr **data,
3520+
struct netlink_ext_ack *extack)
3521+
{
3522+
struct nlattr ** const linkinfo = tbs->linkinfo;
3523+
struct nlattr ** const tb = tbs->tb;
3524+
int status = 0;
3525+
int err;
3526+
3527+
if (nlh->nlmsg_flags & NLM_F_EXCL)
3528+
return -EEXIST;
3529+
3530+
if (nlh->nlmsg_flags & NLM_F_REPLACE)
3531+
return -EOPNOTSUPP;
3532+
3533+
if (linkinfo[IFLA_INFO_DATA]) {
3534+
if (!ops || ops != dev->rtnl_link_ops || !ops->changelink)
3535+
return -EOPNOTSUPP;
3536+
3537+
err = ops->changelink(dev, tb, data, extack);
3538+
if (err < 0)
3539+
return err;
3540+
3541+
status |= DO_SETLINK_NOTIFY;
3542+
}
3543+
3544+
if (linkinfo[IFLA_INFO_SLAVE_DATA]) {
3545+
const struct rtnl_link_ops *m_ops = NULL;
3546+
struct nlattr **slave_data = NULL;
3547+
struct net_device *master_dev;
3548+
3549+
master_dev = netdev_master_upper_dev_get(dev);
3550+
if (master_dev)
3551+
m_ops = master_dev->rtnl_link_ops;
3552+
3553+
if (!m_ops || !m_ops->slave_changelink)
3554+
return -EOPNOTSUPP;
3555+
3556+
if (m_ops->slave_maxtype > RTNL_SLAVE_MAX_TYPE)
3557+
return -EINVAL;
3558+
3559+
if (m_ops->slave_maxtype) {
3560+
err = nla_parse_nested_deprecated(tbs->slave_attr,
3561+
m_ops->slave_maxtype,
3562+
linkinfo[IFLA_INFO_SLAVE_DATA],
3563+
m_ops->slave_policy, extack);
3564+
if (err < 0)
3565+
return err;
3566+
3567+
slave_data = tbs->slave_attr;
3568+
}
3569+
3570+
err = m_ops->slave_changelink(master_dev, dev, tb, slave_data, extack);
3571+
if (err < 0)
3572+
return err;
3573+
3574+
status |= DO_SETLINK_NOTIFY;
3575+
}
3576+
3577+
return do_setlink(skb, dev, nlmsg_data(nlh), extack, tb, status);
3578+
}
3579+
35083580
static int rtnl_group_changelink(const struct sk_buff *skb,
35093581
struct net *net, int group,
35103582
struct ifinfomsg *ifm,
@@ -3617,24 +3689,14 @@ static int rtnl_newlink_create(struct sk_buff *skb, struct ifinfomsg *ifm,
36173689
goto out;
36183690
}
36193691

3620-
struct rtnl_newlink_tbs {
3621-
struct nlattr *tb[IFLA_MAX + 1];
3622-
struct nlattr *linkinfo[IFLA_INFO_MAX + 1];
3623-
struct nlattr *attr[RTNL_MAX_TYPE + 1];
3624-
struct nlattr *slave_attr[RTNL_SLAVE_MAX_TYPE + 1];
3625-
};
3626-
36273692
static int __rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
36283693
struct rtnl_newlink_tbs *tbs,
36293694
struct netlink_ext_ack *extack)
36303695
{
36313696
struct nlattr ** const linkinfo = tbs->linkinfo;
36323697
struct nlattr ** const tb = tbs->tb;
3633-
const struct rtnl_link_ops *m_ops;
3634-
struct net_device *master_dev;
36353698
struct net *net = sock_net(skb->sk);
36363699
const struct rtnl_link_ops *ops;
3637-
struct nlattr **slave_data;
36383700
char kind[MODULE_NAME_LEN];
36393701
struct net_device *dev;
36403702
struct ifinfomsg *ifm;
@@ -3669,14 +3731,6 @@ static int __rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
36693731
dev = NULL;
36703732
}
36713733

3672-
master_dev = NULL;
3673-
m_ops = NULL;
3674-
if (dev) {
3675-
master_dev = netdev_master_upper_dev_get(dev);
3676-
if (master_dev)
3677-
m_ops = master_dev->rtnl_link_ops;
3678-
}
3679-
36803734
if (tb[IFLA_LINKINFO]) {
36813735
err = nla_parse_nested_deprecated(linkinfo, IFLA_INFO_MAX,
36823736
tb[IFLA_LINKINFO],
@@ -3715,56 +3769,8 @@ static int __rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
37153769
}
37163770
}
37173771

3718-
slave_data = NULL;
3719-
if (m_ops) {
3720-
if (m_ops->slave_maxtype > RTNL_SLAVE_MAX_TYPE)
3721-
return -EINVAL;
3722-
3723-
if (m_ops->slave_maxtype &&
3724-
linkinfo[IFLA_INFO_SLAVE_DATA]) {
3725-
err = nla_parse_nested_deprecated(tbs->slave_attr,
3726-
m_ops->slave_maxtype,
3727-
linkinfo[IFLA_INFO_SLAVE_DATA],
3728-
m_ops->slave_policy,
3729-
extack);
3730-
if (err < 0)
3731-
return err;
3732-
slave_data = tbs->slave_attr;
3733-
}
3734-
}
3735-
3736-
if (dev) {
3737-
int status = 0;
3738-
3739-
if (nlh->nlmsg_flags & NLM_F_EXCL)
3740-
return -EEXIST;
3741-
if (nlh->nlmsg_flags & NLM_F_REPLACE)
3742-
return -EOPNOTSUPP;
3743-
3744-
if (linkinfo[IFLA_INFO_DATA]) {
3745-
if (!ops || ops != dev->rtnl_link_ops ||
3746-
!ops->changelink)
3747-
return -EOPNOTSUPP;
3748-
3749-
err = ops->changelink(dev, tb, data, extack);
3750-
if (err < 0)
3751-
return err;
3752-
status |= DO_SETLINK_NOTIFY;
3753-
}
3754-
3755-
if (linkinfo[IFLA_INFO_SLAVE_DATA]) {
3756-
if (!m_ops || !m_ops->slave_changelink)
3757-
return -EOPNOTSUPP;
3758-
3759-
err = m_ops->slave_changelink(master_dev, dev, tb,
3760-
slave_data, extack);
3761-
if (err < 0)
3762-
return err;
3763-
status |= DO_SETLINK_NOTIFY;
3764-
}
3765-
3766-
return do_setlink(skb, dev, ifm, extack, tb, status);
3767-
}
3772+
if (dev)
3773+
return rtnl_changelink(skb, nlh, ops, dev, tbs, data, extack);
37683774

37693775
if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
37703776
/* No dev found and NLM_F_CREATE not set. Requested dev does not exist,

0 commit comments

Comments
 (0)