summaryrefslogtreecommitdiffstats
path: root/drivers/net/bonding/bond_netlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/bonding/bond_netlink.c')
-rw-r--r--drivers/net/bonding/bond_netlink.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/drivers/net/bonding/bond_netlink.c b/drivers/net/bonding/bond_netlink.c
index 6b9ad8673218..d1338fbe1830 100644
--- a/drivers/net/bonding/bond_netlink.c
+++ b/drivers/net/bonding/bond_netlink.c
@@ -675,6 +675,75 @@ nla_put_failure:
return -EMSGSIZE;
}
+static size_t bond_get_linkxstats_size(const struct net_device *dev, int attr)
+{
+ switch (attr) {
+ case IFLA_STATS_LINK_XSTATS:
+ case IFLA_STATS_LINK_XSTATS_SLAVE:
+ break;
+ default:
+ return 0;
+ }
+
+ return bond_3ad_stats_size() + nla_total_size(0);
+}
+
+static int bond_fill_linkxstats(struct sk_buff *skb,
+ const struct net_device *dev,
+ int *prividx, int attr)
+{
+ struct nlattr *nla __maybe_unused;
+ struct slave *slave = NULL;
+ struct nlattr *nest, *nest2;
+ struct bonding *bond;
+
+ switch (attr) {
+ case IFLA_STATS_LINK_XSTATS:
+ bond = netdev_priv(dev);
+ break;
+ case IFLA_STATS_LINK_XSTATS_SLAVE:
+ slave = bond_slave_get_rtnl(dev);
+ if (!slave)
+ return 0;
+ bond = slave->bond;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ nest = nla_nest_start(skb, LINK_XSTATS_TYPE_BOND);
+ if (!nest)
+ return -EMSGSIZE;
+ if (BOND_MODE(bond) == BOND_MODE_8023AD) {
+ struct bond_3ad_stats stats;
+ struct list_head *iter;
+
+ memset(&stats, 0, sizeof(stats));
+ if (slave) {
+ bond_3ad_stats_add(slave, &stats);
+ } else {
+ bond_for_each_slave(bond, slave, iter)
+ bond_3ad_stats_add(slave, &stats);
+ }
+
+ nest2 = nla_nest_start(skb, BOND_XSTATS_3AD);
+ if (!nest2) {
+ nla_nest_end(skb, nest);
+ return -EMSGSIZE;
+ }
+
+ if (bond_3ad_stats_fill(skb, &stats)) {
+ nla_nest_cancel(skb, nest2);
+ nla_nest_end(skb, nest);
+ return -EMSGSIZE;
+ }
+ nla_nest_end(skb, nest2);
+ }
+ nla_nest_end(skb, nest);
+
+ return 0;
+}
+
struct rtnl_link_ops bond_link_ops __read_mostly = {
.kind = "bond",
.priv_size = sizeof(struct bonding),
@@ -689,6 +758,8 @@ struct rtnl_link_ops bond_link_ops __read_mostly = {
.get_num_tx_queues = bond_get_num_tx_queues,
.get_num_rx_queues = bond_get_num_tx_queues, /* Use the same number
as for TX queues */
+ .fill_linkxstats = bond_fill_linkxstats,
+ .get_linkxstats_size = bond_get_linkxstats_size,
.slave_maxtype = IFLA_BOND_SLAVE_MAX,
.slave_policy = bond_slave_policy,
.slave_changelink = bond_slave_changelink,