Skip to content

Commit ba7d49b

Browse files
jpirkodavem330
authored andcommitted
rtnetlink: provide api for getting and setting slave info
Recent patch bonding: add netlink attributes to slave link dev (1d3ee88) Introduced yet another device specific way to access slave information over rtnetlink. There is one already there for bridge. This patch introduces generic way to do this, for getting and setting info as well by extending link_ops. Later on, this new interface will be used for bridge ports as well. Signed-off-by: Jiri Pirko <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent df7dbcb commit ba7d49b

File tree

3 files changed

+154
-20
lines changed

3 files changed

+154
-20
lines changed

include/net/rtnetlink.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,20 @@ struct rtnl_link_ops {
7979
const struct net_device *dev);
8080
unsigned int (*get_num_tx_queues)(void);
8181
unsigned int (*get_num_rx_queues)(void);
82+
83+
int slave_maxtype;
84+
const struct nla_policy *slave_policy;
85+
int (*slave_validate)(struct nlattr *tb[],
86+
struct nlattr *data[]);
87+
int (*slave_changelink)(struct net_device *dev,
88+
struct net_device *slave_dev,
89+
struct nlattr *tb[],
90+
struct nlattr *data[]);
91+
size_t (*get_slave_size)(const struct net_device *dev,
92+
const struct net_device *slave_dev);
93+
int (*fill_slave_info)(struct sk_buff *skb,
94+
const struct net_device *dev,
95+
const struct net_device *slave_dev);
8296
};
8397

8498
int __rtnl_link_register(struct rtnl_link_ops *ops);

include/uapi/linux/if_link.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,8 @@ enum {
241241
IFLA_INFO_KIND,
242242
IFLA_INFO_DATA,
243243
IFLA_INFO_XSTATS,
244+
IFLA_INFO_SLAVE_KIND,
245+
IFLA_INFO_SLAVE_DATA,
244246
__IFLA_INFO_MAX,
245247
};
246248

net/core/rtnetlink.c

Lines changed: 138 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,22 @@ void rtnl_link_unregister(struct rtnl_link_ops *ops)
365365
}
366366
EXPORT_SYMBOL_GPL(rtnl_link_unregister);
367367

368+
static size_t rtnl_link_get_slave_info_data_size(const struct net_device *dev)
369+
{
370+
struct net_device *master_dev;
371+
const struct rtnl_link_ops *ops;
372+
373+
master_dev = netdev_master_upper_dev_get((struct net_device *) dev);
374+
if (!master_dev)
375+
return 0;
376+
ops = master_dev->rtnl_link_ops;
377+
if (!ops->get_slave_size)
378+
return 0;
379+
/* IFLA_INFO_SLAVE_DATA + nested data */
380+
return nla_total_size(sizeof(struct nlattr)) +
381+
ops->get_slave_size(master_dev, dev);
382+
}
383+
368384
static size_t rtnl_link_get_size(const struct net_device *dev)
369385
{
370386
const struct rtnl_link_ops *ops = dev->rtnl_link_ops;
@@ -385,6 +401,8 @@ static size_t rtnl_link_get_size(const struct net_device *dev)
385401
/* IFLA_INFO_XSTATS */
386402
size += nla_total_size(ops->get_xstats_size(dev));
387403

404+
size += rtnl_link_get_slave_info_data_size(dev);
405+
388406
return size;
389407
}
390408

@@ -459,40 +477,101 @@ static size_t rtnl_link_get_af_size(const struct net_device *dev)
459477
return size;
460478
}
461479

462-
static int rtnl_link_fill(struct sk_buff *skb, const struct net_device *dev)
480+
static bool rtnl_have_link_slave_info(const struct net_device *dev)
463481
{
464-
const struct rtnl_link_ops *ops = dev->rtnl_link_ops;
465-
struct nlattr *linkinfo, *data;
466-
int err = -EMSGSIZE;
482+
struct net_device *master_dev;
467483

468-
linkinfo = nla_nest_start(skb, IFLA_LINKINFO);
469-
if (linkinfo == NULL)
470-
goto out;
484+
master_dev = netdev_master_upper_dev_get((struct net_device *) dev);
485+
if (master_dev && master_dev->rtnl_link_ops &&
486+
master_dev->rtnl_link_ops->fill_slave_info)
487+
return true;
488+
return false;
489+
}
490+
491+
static int rtnl_link_slave_info_fill(struct sk_buff *skb,
492+
const struct net_device *dev)
493+
{
494+
struct net_device *master_dev;
495+
const struct rtnl_link_ops *ops;
496+
struct nlattr *slave_data;
497+
int err;
471498

499+
master_dev = netdev_master_upper_dev_get((struct net_device *) dev);
500+
if (!master_dev)
501+
return 0;
502+
ops = master_dev->rtnl_link_ops;
503+
if (!ops)
504+
return 0;
505+
if (nla_put_string(skb, IFLA_INFO_SLAVE_KIND, ops->kind) < 0)
506+
return -EMSGSIZE;
507+
if (ops->fill_slave_info) {
508+
slave_data = nla_nest_start(skb, IFLA_INFO_SLAVE_DATA);
509+
if (!slave_data)
510+
return -EMSGSIZE;
511+
err = ops->fill_slave_info(skb, master_dev, dev);
512+
if (err < 0)
513+
goto err_cancel_slave_data;
514+
nla_nest_end(skb, slave_data);
515+
}
516+
return 0;
517+
518+
err_cancel_slave_data:
519+
nla_nest_cancel(skb, slave_data);
520+
return err;
521+
}
522+
523+
static int rtnl_link_info_fill(struct sk_buff *skb,
524+
const struct net_device *dev)
525+
{
526+
const struct rtnl_link_ops *ops = dev->rtnl_link_ops;
527+
struct nlattr *data;
528+
int err;
529+
530+
if (!ops)
531+
return 0;
472532
if (nla_put_string(skb, IFLA_INFO_KIND, ops->kind) < 0)
473-
goto err_cancel_link;
533+
return -EMSGSIZE;
474534
if (ops->fill_xstats) {
475535
err = ops->fill_xstats(skb, dev);
476536
if (err < 0)
477-
goto err_cancel_link;
537+
return err;
478538
}
479539
if (ops->fill_info) {
480540
data = nla_nest_start(skb, IFLA_INFO_DATA);
481-
if (data == NULL) {
482-
err = -EMSGSIZE;
483-
goto err_cancel_link;
484-
}
541+
if (data == NULL)
542+
return -EMSGSIZE;
485543
err = ops->fill_info(skb, dev);
486544
if (err < 0)
487545
goto err_cancel_data;
488546
nla_nest_end(skb, data);
489547
}
490-
491-
nla_nest_end(skb, linkinfo);
492548
return 0;
493549

494550
err_cancel_data:
495551
nla_nest_cancel(skb, data);
552+
return err;
553+
}
554+
555+
static int rtnl_link_fill(struct sk_buff *skb, const struct net_device *dev)
556+
{
557+
struct nlattr *linkinfo;
558+
int err = -EMSGSIZE;
559+
560+
linkinfo = nla_nest_start(skb, IFLA_LINKINFO);
561+
if (linkinfo == NULL)
562+
goto out;
563+
564+
err = rtnl_link_info_fill(skb, dev);
565+
if (err < 0)
566+
goto err_cancel_link;
567+
568+
err = rtnl_link_slave_info_fill(skb, dev);
569+
if (err < 0)
570+
goto err_cancel_link;
571+
572+
nla_nest_end(skb, linkinfo);
573+
return 0;
574+
496575
err_cancel_link:
497576
nla_nest_cancel(skb, linkinfo);
498577
out:
@@ -1052,10 +1131,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
10521131
if (rtnl_port_fill(skb, dev))
10531132
goto nla_put_failure;
10541133

1055-
if (rtnl_bond_slave_fill(skb, dev))
1056-
goto nla_put_failure;
1057-
1058-
if (dev->rtnl_link_ops) {
1134+
if (dev->rtnl_link_ops || rtnl_have_link_slave_info(dev)) {
10591135
if (rtnl_link_fill(skb, dev) < 0)
10601136
goto nla_put_failure;
10611137
}
@@ -1178,6 +1254,8 @@ EXPORT_SYMBOL(ifla_policy);
11781254
static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
11791255
[IFLA_INFO_KIND] = { .type = NLA_STRING },
11801256
[IFLA_INFO_DATA] = { .type = NLA_NESTED },
1257+
[IFLA_INFO_SLAVE_KIND] = { .type = NLA_STRING },
1258+
[IFLA_INFO_SLAVE_DATA] = { .type = NLA_NESTED },
11811259
};
11821260

11831261
static const struct nla_policy ifla_vfinfo_policy[IFLA_VF_INFO_MAX+1] = {
@@ -1765,7 +1843,9 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh)
17651843
{
17661844
struct net *net = sock_net(skb->sk);
17671845
const struct rtnl_link_ops *ops;
1846+
const struct rtnl_link_ops *m_ops = NULL;
17681847
struct net_device *dev;
1848+
struct net_device *master_dev = NULL;
17691849
struct ifinfomsg *ifm;
17701850
char kind[MODULE_NAME_LEN];
17711851
char ifname[IFNAMSIZ];
@@ -1795,6 +1875,12 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh)
17951875
dev = NULL;
17961876
}
17971877

1878+
if (dev) {
1879+
master_dev = netdev_master_upper_dev_get(dev);
1880+
if (master_dev)
1881+
m_ops = master_dev->rtnl_link_ops;
1882+
}
1883+
17981884
err = validate_linkmsg(dev, tb);
17991885
if (err < 0)
18001886
return err;
@@ -1816,7 +1902,10 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh)
18161902
}
18171903

18181904
if (1) {
1819-
struct nlattr *attr[ops ? ops->maxtype + 1 : 0], **data = NULL;
1905+
struct nlattr *attr[ops ? ops->maxtype + 1 : 0];
1906+
struct nlattr *slave_attr[m_ops ? m_ops->slave_maxtype + 1 : 0];
1907+
struct nlattr **data = NULL;
1908+
struct nlattr **slave_data = NULL;
18201909
struct net *dest_net;
18211910

18221911
if (ops) {
@@ -1835,6 +1924,24 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh)
18351924
}
18361925
}
18371926

1927+
if (m_ops) {
1928+
if (m_ops->slave_maxtype &&
1929+
linkinfo[IFLA_INFO_SLAVE_DATA]) {
1930+
err = nla_parse_nested(slave_attr,
1931+
m_ops->slave_maxtype,
1932+
linkinfo[IFLA_INFO_SLAVE_DATA],
1933+
m_ops->slave_policy);
1934+
if (err < 0)
1935+
return err;
1936+
slave_data = slave_attr;
1937+
}
1938+
if (m_ops->slave_validate) {
1939+
err = m_ops->slave_validate(tb, slave_data);
1940+
if (err < 0)
1941+
return err;
1942+
}
1943+
}
1944+
18381945
if (dev) {
18391946
int modified = 0;
18401947

@@ -1854,6 +1961,17 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh)
18541961
modified = 1;
18551962
}
18561963

1964+
if (linkinfo[IFLA_INFO_SLAVE_DATA]) {
1965+
if (!m_ops || !m_ops->slave_changelink)
1966+
return -EOPNOTSUPP;
1967+
1968+
err = m_ops->slave_changelink(master_dev, dev,
1969+
tb, slave_data);
1970+
if (err < 0)
1971+
return err;
1972+
modified = 1;
1973+
}
1974+
18571975
return do_setlink(dev, ifm, tb, ifname, modified);
18581976
}
18591977

0 commit comments

Comments
 (0)