History

bonding: add support for xstats and export 3ad stats

This patch adds support for extended statistics (xstats) call to the bonding. The first user would be the 3ad code which counts the following events: - LACPDU Rx/Tx - LACPDU unknown type Rx - LACPDU illegal Rx - Marker Rx/Tx - Marker response Rx/Tx - Marker unknown type Rx All of these are exported via netlink as separate attributes to be easily extensible as we plan to add more in the future. Similar to how the bridge and other xstats exports, the structure inside is: [ IFLA_STATS_LINK_XSTATS ] -> [ LINK_XSTATS_TYPE_BOND ] -> [ BOND_XSTATS_3AD ] -> [ 3ad stats attributes ] With this structure it's easy to add more stat types later.

Nikolay Aleksandrov committed 7 years ago

Commit a258aea1 parent 267c0955 files · +182 −0Browse files

Unified · Split

5 files
  1. drivers/net/bonding/bond_3ad.c +83 −0
  2. drivers/net/bonding/bond_netlink.c +71 −0
  3. include/net/bond_3ad.h +3 −0
  4. include/uapi/linux/if_bonding.h +24 −0
  5. include/uapi/linux/if_link.h +1 −0
drivers/net/bonding/bond_3ad.c+83−0
@@ -31,6 +31,7 @@ · 30 unmodified lines
31#include <net/net_namespace.h>31#include <net/net_namespace.h>
32#include <net/bonding.h>32#include <net/bonding.h>
33#include <net/bond_3ad.h>33#include <net/bond_3ad.h>
34#include <net/netlink.h>
34 35
35/* General definitions */36/* General definitions */
36#define AD_SHORT_TIMEOUT 137#define AD_SHORT_TIMEOUT 1
@@ -2696,3 +2697,85 @@ void bond_3ad_update_lacp_rate(struct bonding *bond) · 2659 unmodified lines
2696 }2697 }
2697 spin_unlock_bh(&bond->mode_lock);2698 spin_unlock_bh(&bond->mode_lock);
2698}2699}
2700
2701void bond_3ad_stats_add(struct slave *slave, struct bond_3ad_stats *stats)
2702{
2703 struct bond_3ad_stats *rstats = &SLAVE_AD_INFO(slave)->stats;
2704 u64 stat;
2705
2706 atomic64_add(atomic64_read(&rstats->lacpdu_rx), &stats->lacpdu_rx);
2707 atomic64_add(atomic64_read(&rstats->lacpdu_tx), &stats->lacpdu_tx);
2708
2709 stat = atomic64_read(&rstats->lacpdu_unknown_rx);
2710 atomic64_add(stat, &stats->lacpdu_unknown_rx);
2711 stat = atomic64_read(&rstats->lacpdu_illegal_rx);
2712 atomic64_add(stat, &stats->lacpdu_illegal_rx);
2713
2714 atomic64_add(atomic64_read(&rstats->marker_rx), &stats->marker_rx);
2715 atomic64_add(atomic64_read(&rstats->marker_tx), &stats->marker_tx);
2716
2717 stat = atomic64_read(&rstats->marker_resp_rx);
2718 atomic64_add(stat, &stats->marker_resp_rx);
2719 stat = atomic64_read(&rstats->marker_resp_tx);
2720 atomic64_add(stat, &stats->marker_resp_tx);
2721 stat = atomic64_read(&rstats->marker_unknown_rx);
2722 atomic64_add(stat, &stats->marker_unknown_rx);
2723}
2724
2725size_t bond_3ad_stats_size(void)
2726{
2727 return nla_total_size_64bit(sizeof(u64)) + /* BOND_3AD_STAT_LACPDU_RX */
2728 nla_total_size_64bit(sizeof(u64)) + /* BOND_3AD_STAT_LACPDU_TX */
2729 nla_total_size_64bit(sizeof(u64)) + /* BOND_3AD_STAT_LACPDU_UNKNOWN_RX */
2730 nla_total_size_64bit(sizeof(u64)) + /* BOND_3AD_STAT_LACPDU_ILLEGAL_RX */
2731 nla_total_size_64bit(sizeof(u64)) + /* BOND_3AD_STAT_MARKER_RX */
2732 nla_total_size_64bit(sizeof(u64)) + /* BOND_3AD_STAT_MARKER_TX */
2733 nla_total_size_64bit(sizeof(u64)) + /* BOND_3AD_STAT_MARKER_RESP_RX */
2734 nla_total_size_64bit(sizeof(u64)) + /* BOND_3AD_STAT_MARKER_RESP_TX */
2735 nla_total_size_64bit(sizeof(u64)); /* BOND_3AD_STAT_MARKER_UNKNOWN_RX */
2736}
2737
2738int bond_3ad_stats_fill(struct sk_buff *skb, struct bond_3ad_stats *stats)
2739{
2740 u64 val;
2741
2742 val = atomic64_read(&stats->lacpdu_rx);
2743 if (nla_put_u64_64bit(skb, BOND_3AD_STAT_LACPDU_RX, val,
2744 BOND_3AD_STAT_PAD))
2745 return -EMSGSIZE;
2746 val = atomic64_read(&stats->lacpdu_tx);
2747 if (nla_put_u64_64bit(skb, BOND_3AD_STAT_LACPDU_TX, val,
2748 BOND_3AD_STAT_PAD))
2749 return -EMSGSIZE;
2750 val = atomic64_read(&stats->lacpdu_unknown_rx);
2751 if (nla_put_u64_64bit(skb, BOND_3AD_STAT_LACPDU_UNKNOWN_RX, val,
2752 BOND_3AD_STAT_PAD))
2753 return -EMSGSIZE;
2754 val = atomic64_read(&stats->lacpdu_illegal_rx);
2755 if (nla_put_u64_64bit(skb, BOND_3AD_STAT_LACPDU_ILLEGAL_RX, val,
2756 BOND_3AD_STAT_PAD))
2757 return -EMSGSIZE;
2758
2759 val = atomic64_read(&stats->marker_rx);
2760 if (nla_put_u64_64bit(skb, BOND_3AD_STAT_MARKER_RX, val,
2761 BOND_3AD_STAT_PAD))
2762 return -EMSGSIZE;
2763 val = atomic64_read(&stats->marker_tx);
2764 if (nla_put_u64_64bit(skb, BOND_3AD_STAT_MARKER_TX, val,
2765 BOND_3AD_STAT_PAD))
2766 return -EMSGSIZE;
2767 val = atomic64_read(&stats->marker_resp_rx);
2768 if (nla_put_u64_64bit(skb, BOND_3AD_STAT_MARKER_RESP_RX, val,
2769 BOND_3AD_STAT_PAD))
2770 return -EMSGSIZE;
2771 val = atomic64_read(&stats->marker_resp_tx);
2772 if (nla_put_u64_64bit(skb, BOND_3AD_STAT_MARKER_RESP_TX, val,
2773 BOND_3AD_STAT_PAD))
2774 return -EMSGSIZE;
2775 val = atomic64_read(&stats->marker_unknown_rx);
2776 if (nla_put_u64_64bit(skb, BOND_3AD_STAT_MARKER_UNKNOWN_RX, val,
2777 BOND_3AD_STAT_PAD))
2778 return -EMSGSIZE;
2779
2780 return 0;
2781}
drivers/net/bonding/bond_netlink.c+71−0
@@ -675,6 +675,75 @@ nla_put_failure: · 674 unmodified lines
675 return -EMSGSIZE;675 return -EMSGSIZE;
676}676}
677 677
678static size_t bond_get_linkxstats_size(const struct net_device *dev, int attr)
679{
680 switch (attr) {
681 case IFLA_STATS_LINK_XSTATS:
682 case IFLA_STATS_LINK_XSTATS_SLAVE:
683 break;
684 default:
685 return 0;
686 }
687
688 return bond_3ad_stats_size() + nla_total_size(0);
689}
690
691static int bond_fill_linkxstats(struct sk_buff *skb,
692 const struct net_device *dev,
693 int *prividx, int attr)
694{
695 struct nlattr *nla __maybe_unused;
696 struct slave *slave = NULL;
697 struct nlattr *nest, *nest2;
698 struct bonding *bond;
699
700 switch (attr) {
701 case IFLA_STATS_LINK_XSTATS:
702 bond = netdev_priv(dev);
703 break;
704 case IFLA_STATS_LINK_XSTATS_SLAVE:
705 slave = bond_slave_get_rtnl(dev);
706 if (!slave)
707 return 0;
708 bond = slave->bond;
709 break;
710 default:
711 return -EINVAL;
712 }
713
714 nest = nla_nest_start(skb, LINK_XSTATS_TYPE_BOND);
715 if (!nest)
716 return -EMSGSIZE;
717 if (BOND_MODE(bond) == BOND_MODE_8023AD) {
718 struct bond_3ad_stats stats;
719 struct list_head *iter;
720
721 memset(&stats, 0, sizeof(stats));
722 if (slave) {
723 bond_3ad_stats_add(slave, &stats);
724 } else {
725 bond_for_each_slave(bond, slave, iter)
726 bond_3ad_stats_add(slave, &stats);
727 }
728
729 nest2 = nla_nest_start(skb, BOND_XSTATS_3AD);
730 if (!nest2) {
731 nla_nest_end(skb, nest);
732 return -EMSGSIZE;
733 }
734
735 if (bond_3ad_stats_fill(skb, &stats)) {
736 nla_nest_cancel(skb, nest2);
737 nla_nest_end(skb, nest);
738 return -EMSGSIZE;
739 }
740 nla_nest_end(skb, nest2);
741 }
742 nla_nest_end(skb, nest);
743
744 return 0;
745}
746
678struct rtnl_link_ops bond_link_ops __read_mostly = {747struct rtnl_link_ops bond_link_ops __read_mostly = {
679 .kind = "bond",748 .kind = "bond",
680 .priv_size = sizeof(struct bonding),749 .priv_size = sizeof(struct bonding),
@@ -689,6 +758,8 @@ struct rtnl_link_ops bond_link_ops __read_mostly = { · 8 unmodified lines
689 .get_num_tx_queues = bond_get_num_tx_queues,758 .get_num_tx_queues = bond_get_num_tx_queues,
690 .get_num_rx_queues = bond_get_num_tx_queues, /* Use the same number759 .get_num_rx_queues = bond_get_num_tx_queues, /* Use the same number
691 as for TX queues */760 as for TX queues */
761 .fill_linkxstats = bond_fill_linkxstats,
762 .get_linkxstats_size = bond_get_linkxstats_size,
692 .slave_maxtype = IFLA_BOND_SLAVE_MAX,763 .slave_maxtype = IFLA_BOND_SLAVE_MAX,
693 .slave_policy = bond_slave_policy,764 .slave_policy = bond_slave_policy,
694 .slave_changelink = bond_slave_changelink,765 .slave_changelink = bond_slave_changelink,
include/net/bond_3ad.h+3−0
@@ -321,5 +321,8 @@ int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond, · 320 unmodified lines
321int bond_3ad_set_carrier(struct bonding *bond);321int bond_3ad_set_carrier(struct bonding *bond);
322void bond_3ad_update_lacp_rate(struct bonding *bond);322void bond_3ad_update_lacp_rate(struct bonding *bond);
323void bond_3ad_update_ad_actor_settings(struct bonding *bond);323void bond_3ad_update_ad_actor_settings(struct bonding *bond);
324void bond_3ad_stats_add(struct slave *slave, struct bond_3ad_stats *stats);
325int bond_3ad_stats_fill(struct sk_buff *skb, struct bond_3ad_stats *stats);
326size_t bond_3ad_stats_size(void);
324#endif /* _NET_BOND_3AD_H */327#endif /* _NET_BOND_3AD_H */
325 328
include/uapi/linux/if_bonding.h+24−0
@@ -117,6 +117,30 @@ struct ad_info { · 116 unmodified lines
117 __u8 partner_system[ETH_ALEN];117 __u8 partner_system[ETH_ALEN];
118};118};
119 119
120/* Embedded inside LINK_XSTATS_TYPE_BOND */
121enum {
122 BOND_XSTATS_UNSPEC,
123 BOND_XSTATS_3AD,
124 __BOND_XSTATS_MAX
125};
126#define BOND_XSTATS_MAX (__BOND_XSTATS_MAX - 1)
127
128/* Embedded inside BOND_XSTATS_3AD */
129enum {
130 BOND_3AD_STAT_LACPDU_RX,
131 BOND_3AD_STAT_LACPDU_TX,
132 BOND_3AD_STAT_LACPDU_UNKNOWN_RX,
133 BOND_3AD_STAT_LACPDU_ILLEGAL_RX,
134 BOND_3AD_STAT_MARKER_RX,
135 BOND_3AD_STAT_MARKER_TX,
136 BOND_3AD_STAT_MARKER_RESP_RX,
137 BOND_3AD_STAT_MARKER_RESP_TX,
138 BOND_3AD_STAT_MARKER_UNKNOWN_RX,
139 BOND_3AD_STAT_PAD,
140 __BOND_3AD_STAT_MAX
141};
142#define BOND_3AD_STAT_MAX (__BOND_3AD_STAT_MAX - 1)
143
120#endif /* _LINUX_IF_BONDING_H */144#endif /* _LINUX_IF_BONDING_H */
121 145
122/*146/*
include/uapi/linux/if_link.h+1−0
@@ -925,6 +925,7 @@ enum { · 924 unmodified lines
925enum {925enum {
926 LINK_XSTATS_TYPE_UNSPEC,926 LINK_XSTATS_TYPE_UNSPEC,
927 LINK_XSTATS_TYPE_BRIDGE,927 LINK_XSTATS_TYPE_BRIDGE,
928 LINK_XSTATS_TYPE_BOND,
928 __LINK_XSTATS_TYPE_MAX929 __LINK_XSTATS_TYPE_MAX
929};930};
930#define LINK_XSTATS_TYPE_MAX (__LINK_XSTATS_TYPE_MAX - 1)931#define LINK_XSTATS_TYPE_MAX (__LINK_XSTATS_TYPE_MAX - 1)