aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorJiri Pirko <jiri@resnulli.us>2014-01-22 03:05:55 -0500
committerDavid S. Miller <davem@davemloft.net>2014-01-23 00:57:05 -0500
commitba7d49b1f0f8e5f24294a880ed576964059af5ef (patch)
treedbd5c9c4418d4a72fe44a5f9af0e51e0d2be747a /net/core
parentdf7dbcbbafc0b8f3fb31a40c6f3c4a7e15cb0b40 (diff)
rtnetlink: provide api for getting and setting slave info
Recent patch bonding: add netlink attributes to slave link dev (1d3ee88ae0d6) 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 <jiri@resnulli.us> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/rtnetlink.c158
1 files changed, 138 insertions, 20 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index cace14962234..a56bccf6629e 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -365,6 +365,22 @@ void rtnl_link_unregister(struct rtnl_link_ops *ops)
365} 365}
366EXPORT_SYMBOL_GPL(rtnl_link_unregister); 366EXPORT_SYMBOL_GPL(rtnl_link_unregister);
367 367
368static 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
368static size_t rtnl_link_get_size(const struct net_device *dev) 384static size_t rtnl_link_get_size(const struct net_device *dev)
369{ 385{
370 const struct rtnl_link_ops *ops = dev->rtnl_link_ops; 386 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)
385 /* IFLA_INFO_XSTATS */ 401 /* IFLA_INFO_XSTATS */
386 size += nla_total_size(ops->get_xstats_size(dev)); 402 size += nla_total_size(ops->get_xstats_size(dev));
387 403
404 size += rtnl_link_get_slave_info_data_size(dev);
405
388 return size; 406 return size;
389} 407}
390 408
@@ -459,40 +477,101 @@ static size_t rtnl_link_get_af_size(const struct net_device *dev)
459 return size; 477 return size;
460} 478}
461 479
462static int rtnl_link_fill(struct sk_buff *skb, const struct net_device *dev) 480static bool rtnl_have_link_slave_info(const struct net_device *dev)
463{ 481{
464 const struct rtnl_link_ops *ops = dev->rtnl_link_ops; 482 struct net_device *master_dev;
465 struct nlattr *linkinfo, *data;
466 int err = -EMSGSIZE;
467 483
468 linkinfo = nla_nest_start(skb, IFLA_LINKINFO); 484 master_dev = netdev_master_upper_dev_get((struct net_device *) dev);
469 if (linkinfo == NULL) 485 if (master_dev && master_dev->rtnl_link_ops &&
470 goto out; 486 master_dev->rtnl_link_ops->fill_slave_info)
487 return true;
488 return false;
489}
490
491static 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;
471 498
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
518err_cancel_slave_data:
519 nla_nest_cancel(skb, slave_data);
520 return err;
521}
522
523static 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;
472 if (nla_put_string(skb, IFLA_INFO_KIND, ops->kind) < 0) 532 if (nla_put_string(skb, IFLA_INFO_KIND, ops->kind) < 0)
473 goto err_cancel_link; 533 return -EMSGSIZE;
474 if (ops->fill_xstats) { 534 if (ops->fill_xstats) {
475 err = ops->fill_xstats(skb, dev); 535 err = ops->fill_xstats(skb, dev);
476 if (err < 0) 536 if (err < 0)
477 goto err_cancel_link; 537 return err;
478 } 538 }
479 if (ops->fill_info) { 539 if (ops->fill_info) {
480 data = nla_nest_start(skb, IFLA_INFO_DATA); 540 data = nla_nest_start(skb, IFLA_INFO_DATA);
481 if (data == NULL) { 541 if (data == NULL)
482 err = -EMSGSIZE; 542 return -EMSGSIZE;
483 goto err_cancel_link;
484 }
485 err = ops->fill_info(skb, dev); 543 err = ops->fill_info(skb, dev);
486 if (err < 0) 544 if (err < 0)
487 goto err_cancel_data; 545 goto err_cancel_data;
488 nla_nest_end(skb, data); 546 nla_nest_end(skb, data);
489 } 547 }
490
491 nla_nest_end(skb, linkinfo);
492 return 0; 548 return 0;
493 549
494err_cancel_data: 550err_cancel_data:
495 nla_nest_cancel(skb, data); 551 nla_nest_cancel(skb, data);
552 return err;
553}
554
555static 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
496err_cancel_link: 575err_cancel_link:
497 nla_nest_cancel(skb, linkinfo); 576 nla_nest_cancel(skb, linkinfo);
498out: 577out:
@@ -1052,10 +1131,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
1052 if (rtnl_port_fill(skb, dev)) 1131 if (rtnl_port_fill(skb, dev))
1053 goto nla_put_failure; 1132 goto nla_put_failure;
1054 1133
1055 if (rtnl_bond_slave_fill(skb, dev)) 1134 if (dev->rtnl_link_ops || rtnl_have_link_slave_info(dev)) {
1056 goto nla_put_failure;
1057
1058 if (dev->rtnl_link_ops) {
1059 if (rtnl_link_fill(skb, dev) < 0) 1135 if (rtnl_link_fill(skb, dev) < 0)
1060 goto nla_put_failure; 1136 goto nla_put_failure;
1061 } 1137 }
@@ -1178,6 +1254,8 @@ EXPORT_SYMBOL(ifla_policy);
1178static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { 1254static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
1179 [IFLA_INFO_KIND] = { .type = NLA_STRING }, 1255 [IFLA_INFO_KIND] = { .type = NLA_STRING },
1180 [IFLA_INFO_DATA] = { .type = NLA_NESTED }, 1256 [IFLA_INFO_DATA] = { .type = NLA_NESTED },
1257 [IFLA_INFO_SLAVE_KIND] = { .type = NLA_STRING },
1258 [IFLA_INFO_SLAVE_DATA] = { .type = NLA_NESTED },
1181}; 1259};
1182 1260
1183static const struct nla_policy ifla_vfinfo_policy[IFLA_VF_INFO_MAX+1] = { 1261static 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)
1765{ 1843{
1766 struct net *net = sock_net(skb->sk); 1844 struct net *net = sock_net(skb->sk);
1767 const struct rtnl_link_ops *ops; 1845 const struct rtnl_link_ops *ops;
1846 const struct rtnl_link_ops *m_ops = NULL;
1768 struct net_device *dev; 1847 struct net_device *dev;
1848 struct net_device *master_dev = NULL;
1769 struct ifinfomsg *ifm; 1849 struct ifinfomsg *ifm;
1770 char kind[MODULE_NAME_LEN]; 1850 char kind[MODULE_NAME_LEN];
1771 char ifname[IFNAMSIZ]; 1851 char ifname[IFNAMSIZ];
@@ -1795,6 +1875,12 @@ replay:
1795 dev = NULL; 1875 dev = NULL;
1796 } 1876 }
1797 1877
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
1798 err = validate_linkmsg(dev, tb); 1884 err = validate_linkmsg(dev, tb);
1799 if (err < 0) 1885 if (err < 0)
1800 return err; 1886 return err;
@@ -1816,7 +1902,10 @@ replay:
1816 } 1902 }
1817 1903
1818 if (1) { 1904 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;
1820 struct net *dest_net; 1909 struct net *dest_net;
1821 1910
1822 if (ops) { 1911 if (ops) {
@@ -1835,6 +1924,24 @@ replay:
1835 } 1924 }
1836 } 1925 }
1837 1926
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
1838 if (dev) { 1945 if (dev) {
1839 int modified = 0; 1946 int modified = 0;
1840 1947
@@ -1854,6 +1961,17 @@ replay:
1854 modified = 1; 1961 modified = 1;
1855 } 1962 }
1856 1963
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
1857 return do_setlink(dev, ifm, tb, ifname, modified); 1975 return do_setlink(dev, ifm, tb, ifname, modified);
1858 } 1976 }
1859 1977