diff options
author | sfeldma@cumulusnetworks.com <sfeldma@cumulusnetworks.com> | 2014-01-17 01:57:56 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-01-17 21:51:58 -0500 |
commit | 1d3ee88ae0d605629bf369ab0b868dae8ca62a48 (patch) | |
tree | 7d547bb8ba12b9417a8f0055a08f1026d6392cf2 /net/core | |
parent | 07699f9a7c8d1002e07011d5aa382cd63241eea8 (diff) |
bonding: add netlink attributes to slave link dev
If link is IFF_SLAVE, extend link dev netlink attributes to include
slave attributes with new IFLA_SLAVE nest. Add netlink notification
(RTM_NEWLINK) when slave status changes from backup to active, or
visa-versa.
Adds new ndo_get_slave op to net_device_ops to fill skb with IFLA_SLAVE
attributes. Currently only used by bonding driver, but could be
used by other aggregating devices with slaves.
Signed-off-by: Scott Feldman <sfeldma@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/rtnetlink.c | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index e6e7d582f901..4f85de7aca33 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -721,6 +721,28 @@ static size_t rtnl_port_size(const struct net_device *dev) | |||
721 | return port_self_size; | 721 | return port_self_size; |
722 | } | 722 | } |
723 | 723 | ||
724 | static size_t rtnl_bond_slave_size(const struct net_device *dev) | ||
725 | { | ||
726 | struct net_device *bond; | ||
727 | size_t slave_size = | ||
728 | nla_total_size(sizeof(struct nlattr)) + /* IFLA_SLAVE */ | ||
729 | nla_total_size(1) + /* IFLA_SLAVE_STATE */ | ||
730 | nla_total_size(1) + /* IFLA_SLAVE_MII_STATUS */ | ||
731 | nla_total_size(4) + /* IFLA_SLAVE_LINK_FAILURE_COUNT */ | ||
732 | nla_total_size(MAX_ADDR_LEN) + /* IFLA_SLAVE_PERM_HWADDR */ | ||
733 | nla_total_size(2) + /* IFLA_SLAVE_QUEUE_ID */ | ||
734 | nla_total_size(2) + /* IFLA_SLAVE_AD_AGGREGATOR_ID */ | ||
735 | 0; | ||
736 | |||
737 | if (netif_is_bond_slave((struct net_device *)dev)) { | ||
738 | bond = netdev_master_upper_dev_get((struct net_device *)dev); | ||
739 | if (bond && bond->netdev_ops->ndo_get_slave) | ||
740 | return slave_size; | ||
741 | } | ||
742 | |||
743 | return 0; | ||
744 | } | ||
745 | |||
724 | static noinline size_t if_nlmsg_size(const struct net_device *dev, | 746 | static noinline size_t if_nlmsg_size(const struct net_device *dev, |
725 | u32 ext_filter_mask) | 747 | u32 ext_filter_mask) |
726 | { | 748 | { |
@@ -750,6 +772,7 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev, | |||
750 | + rtnl_port_size(dev) /* IFLA_VF_PORTS + IFLA_PORT_SELF */ | 772 | + rtnl_port_size(dev) /* IFLA_VF_PORTS + IFLA_PORT_SELF */ |
751 | + rtnl_link_get_size(dev) /* IFLA_LINKINFO */ | 773 | + rtnl_link_get_size(dev) /* IFLA_LINKINFO */ |
752 | + rtnl_link_get_af_size(dev) /* IFLA_AF_SPEC */ | 774 | + rtnl_link_get_af_size(dev) /* IFLA_AF_SPEC */ |
775 | + rtnl_bond_slave_size(dev) /* IFLA_SLAVE */ | ||
753 | + nla_total_size(MAX_PHYS_PORT_ID_LEN); /* IFLA_PHYS_PORT_ID */ | 776 | + nla_total_size(MAX_PHYS_PORT_ID_LEN); /* IFLA_PHYS_PORT_ID */ |
754 | } | 777 | } |
755 | 778 | ||
@@ -847,6 +870,34 @@ static int rtnl_phys_port_id_fill(struct sk_buff *skb, struct net_device *dev) | |||
847 | return 0; | 870 | return 0; |
848 | } | 871 | } |
849 | 872 | ||
873 | static size_t rtnl_bond_slave_fill(struct sk_buff *skb, struct net_device *dev) | ||
874 | { | ||
875 | struct net_device *bond; | ||
876 | struct nlattr *nest; | ||
877 | int err; | ||
878 | |||
879 | if (!netif_is_bond_slave(dev)) | ||
880 | return 0; | ||
881 | |||
882 | bond = netdev_master_upper_dev_get(dev); | ||
883 | if (!bond || !bond->netdev_ops->ndo_get_slave) | ||
884 | return 0; | ||
885 | |||
886 | nest = nla_nest_start(skb, IFLA_SLAVE); | ||
887 | if (!nest) | ||
888 | return -EMSGSIZE; | ||
889 | |||
890 | err = bond->netdev_ops->ndo_get_slave(dev, skb); | ||
891 | if (err) { | ||
892 | nla_nest_cancel(skb, nest); | ||
893 | return (err == -EMSGSIZE) ? err : 0; | ||
894 | } | ||
895 | |||
896 | nla_nest_end(skb, nest); | ||
897 | |||
898 | return 0; | ||
899 | } | ||
900 | |||
850 | static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, | 901 | static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, |
851 | int type, u32 pid, u32 seq, u32 change, | 902 | int type, u32 pid, u32 seq, u32 change, |
852 | unsigned int flags, u32 ext_filter_mask) | 903 | unsigned int flags, u32 ext_filter_mask) |
@@ -1001,6 +1052,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, | |||
1001 | if (rtnl_port_fill(skb, dev)) | 1052 | if (rtnl_port_fill(skb, dev)) |
1002 | goto nla_put_failure; | 1053 | goto nla_put_failure; |
1003 | 1054 | ||
1055 | if (rtnl_bond_slave_fill(skb, dev)) | ||
1056 | goto nla_put_failure; | ||
1057 | |||
1004 | if (dev->rtnl_link_ops) { | 1058 | if (dev->rtnl_link_ops) { |
1005 | if (rtnl_link_fill(skb, dev) < 0) | 1059 | if (rtnl_link_fill(skb, dev) < 0) |
1006 | goto nla_put_failure; | 1060 | goto nla_put_failure; |