Skip to content

Commit cc648f8

Browse files
committed
Merge branch 'bonding-add-3ad-stats-and-export-them-via-xstats'
Nikolay Aleksandrov says: ==================== bonding: add 3ad stats and export them via xstats This set adds support for counting some 3ad-specific packet types and exports the new stats via the xstats API. atomic64 counters are used since these are not fastpaths and we can avoid the per-cpu allocations. Each 3ad counter is exported as a separate attribute to be easily extensible since we plan to add more later. The stats are per-slave and when the master stats are requested the slaves' stats are summed up. Patches 01 and 02 do minor cleanups in preparation for the new stats API. Patch 03 adds the new stats and patch 04 adds xstats support to export them. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents 1435d99 + a258aea commit cc648f8

File tree

5 files changed

+264
-50
lines changed

5 files changed

+264
-50
lines changed

drivers/net/bonding/bond_3ad.c

Lines changed: 151 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include <net/net_namespace.h>
3232
#include <net/bonding.h>
3333
#include <net/bond_3ad.h>
34+
#include <net/netlink.h>
3435

3536
/* General definitions */
3637
#define AD_SHORT_TIMEOUT 1
@@ -851,6 +852,8 @@ static int ad_lacpdu_send(struct port *port)
851852
if (!skb)
852853
return -ENOMEM;
853854

855+
atomic64_inc(&SLAVE_AD_INFO(slave)->stats.lacpdu_tx);
856+
854857
skb->dev = slave->dev;
855858
skb_reset_mac_header(skb);
856859
skb->network_header = skb->mac_header + ETH_HLEN;
@@ -892,6 +895,15 @@ static int ad_marker_send(struct port *port, struct bond_marker *marker)
892895
if (!skb)
893896
return -ENOMEM;
894897

898+
switch (marker->tlv_type) {
899+
case AD_MARKER_INFORMATION_SUBTYPE:
900+
atomic64_inc(&SLAVE_AD_INFO(slave)->stats.marker_tx);
901+
break;
902+
case AD_MARKER_RESPONSE_SUBTYPE:
903+
atomic64_inc(&SLAVE_AD_INFO(slave)->stats.marker_resp_tx);
904+
break;
905+
}
906+
895907
skb_reserve(skb, 16);
896908

897909
skb->dev = slave->dev;
@@ -1086,6 +1098,9 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
10861098
*/
10871099
last_state = port->sm_rx_state;
10881100

1101+
if (lacpdu)
1102+
atomic64_inc(&SLAVE_AD_INFO(port->slave)->stats.lacpdu_rx);
1103+
10891104
/* check if state machine should change state */
10901105

10911106
/* first, check if port was reinitialized */
@@ -1922,6 +1937,8 @@ static void ad_marker_info_received(struct bond_marker *marker_info,
19221937
{
19231938
struct bond_marker marker;
19241939

1940+
atomic64_inc(&SLAVE_AD_INFO(port->slave)->stats.marker_rx);
1941+
19251942
/* copy the received marker data to the response marker */
19261943
memcpy(&marker, marker_info, sizeof(struct bond_marker));
19271944
/* change the marker subtype to marker response */
@@ -1946,6 +1963,8 @@ static void ad_marker_info_received(struct bond_marker *marker_info,
19461963
static void ad_marker_response_received(struct bond_marker *marker,
19471964
struct port *port)
19481965
{
1966+
atomic64_inc(&SLAVE_AD_INFO(port->slave)->stats.marker_resp_rx);
1967+
19491968
/* DO NOTHING, SINCE WE DECIDED NOT TO IMPLEMENT THIS FEATURE FOR NOW */
19501969
}
19511970

@@ -2348,66 +2367,64 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
23482367
* bond_3ad_rx_indication - handle a received frame
23492368
* @lacpdu: received lacpdu
23502369
* @slave: slave struct to work on
2351-
* @length: length of the data received
23522370
*
23532371
* It is assumed that frames that were sent on this NIC don't returned as new
23542372
* received frames (loopback). Since only the payload is given to this
23552373
* function, it check for loopback.
23562374
*/
2357-
static int bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave,
2358-
u16 length)
2375+
static int bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave)
23592376
{
2360-
struct port *port;
23612377
int ret = RX_HANDLER_ANOTHER;
2378+
struct bond_marker *marker;
2379+
struct port *port;
2380+
atomic64_t *stat;
23622381

2363-
if (length >= sizeof(struct lacpdu)) {
2364-
2365-
port = &(SLAVE_AD_INFO(slave)->port);
2366-
2367-
if (!port->slave) {
2368-
net_warn_ratelimited("%s: Warning: port of slave %s is uninitialized\n",
2369-
slave->dev->name, slave->bond->dev->name);
2370-
return ret;
2371-
}
2382+
port = &(SLAVE_AD_INFO(slave)->port);
2383+
if (!port->slave) {
2384+
net_warn_ratelimited("%s: Warning: port of slave %s is uninitialized\n",
2385+
slave->dev->name, slave->bond->dev->name);
2386+
return ret;
2387+
}
23722388

2373-
switch (lacpdu->subtype) {
2374-
case AD_TYPE_LACPDU:
2375-
ret = RX_HANDLER_CONSUMED;
2376-
netdev_dbg(slave->bond->dev,
2377-
"Received LACPDU on port %d slave %s\n",
2378-
port->actor_port_number,
2379-
slave->dev->name);
2380-
/* Protect against concurrent state machines */
2381-
spin_lock(&slave->bond->mode_lock);
2382-
ad_rx_machine(lacpdu, port);
2383-
spin_unlock(&slave->bond->mode_lock);
2389+
switch (lacpdu->subtype) {
2390+
case AD_TYPE_LACPDU:
2391+
ret = RX_HANDLER_CONSUMED;
2392+
netdev_dbg(slave->bond->dev,
2393+
"Received LACPDU on port %d slave %s\n",
2394+
port->actor_port_number, slave->dev->name);
2395+
/* Protect against concurrent state machines */
2396+
spin_lock(&slave->bond->mode_lock);
2397+
ad_rx_machine(lacpdu, port);
2398+
spin_unlock(&slave->bond->mode_lock);
2399+
break;
2400+
case AD_TYPE_MARKER:
2401+
ret = RX_HANDLER_CONSUMED;
2402+
/* No need to convert fields to Little Endian since we
2403+
* don't use the marker's fields.
2404+
*/
2405+
marker = (struct bond_marker *)lacpdu;
2406+
switch (marker->tlv_type) {
2407+
case AD_MARKER_INFORMATION_SUBTYPE:
2408+
netdev_dbg(slave->bond->dev, "Received Marker Information on port %d\n",
2409+
port->actor_port_number);
2410+
ad_marker_info_received(marker, port);
23842411
break;
2385-
2386-
case AD_TYPE_MARKER:
2387-
ret = RX_HANDLER_CONSUMED;
2388-
/* No need to convert fields to Little Endian since we
2389-
* don't use the marker's fields.
2390-
*/
2391-
2392-
switch (((struct bond_marker *)lacpdu)->tlv_type) {
2393-
case AD_MARKER_INFORMATION_SUBTYPE:
2394-
netdev_dbg(slave->bond->dev, "Received Marker Information on port %d\n",
2395-
port->actor_port_number);
2396-
ad_marker_info_received((struct bond_marker *)lacpdu, port);
2397-
break;
2398-
2399-
case AD_MARKER_RESPONSE_SUBTYPE:
2400-
netdev_dbg(slave->bond->dev, "Received Marker Response on port %d\n",
2401-
port->actor_port_number);
2402-
ad_marker_response_received((struct bond_marker *)lacpdu, port);
2403-
break;
2404-
2405-
default:
2406-
netdev_dbg(slave->bond->dev, "Received an unknown Marker subtype on slot %d\n",
2407-
port->actor_port_number);
2408-
}
2412+
case AD_MARKER_RESPONSE_SUBTYPE:
2413+
netdev_dbg(slave->bond->dev, "Received Marker Response on port %d\n",
2414+
port->actor_port_number);
2415+
ad_marker_response_received(marker, port);
2416+
break;
2417+
default:
2418+
netdev_dbg(slave->bond->dev, "Received an unknown Marker subtype on slot %d\n",
2419+
port->actor_port_number);
2420+
stat = &SLAVE_AD_INFO(slave)->stats.marker_unknown_rx;
2421+
atomic64_inc(stat);
24092422
}
2423+
break;
2424+
default:
2425+
atomic64_inc(&SLAVE_AD_INFO(slave)->stats.lacpdu_unknown_rx);
24102426
}
2427+
24112428
return ret;
24122429
}
24132430

@@ -2643,10 +2660,12 @@ int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond,
26432660
return RX_HANDLER_ANOTHER;
26442661

26452662
lacpdu = skb_header_pointer(skb, 0, sizeof(_lacpdu), &_lacpdu);
2646-
if (!lacpdu)
2663+
if (!lacpdu) {
2664+
atomic64_inc(&SLAVE_AD_INFO(slave)->stats.lacpdu_illegal_rx);
26472665
return RX_HANDLER_ANOTHER;
2666+
}
26482667

2649-
return bond_3ad_rx_indication(lacpdu, slave, skb->len);
2668+
return bond_3ad_rx_indication(lacpdu, slave);
26502669
}
26512670

26522671
/**
@@ -2678,3 +2697,85 @@ void bond_3ad_update_lacp_rate(struct bonding *bond)
26782697
}
26792698
spin_unlock_bh(&bond->mode_lock);
26802699
}
2700+
2701+
void 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+
2725+
size_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+
2738+
int 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

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,75 @@ static int bond_fill_info(struct sk_buff *skb,
675675
return -EMSGSIZE;
676676
}
677677

678+
static 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+
691+
static 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+
678747
struct rtnl_link_ops bond_link_ops __read_mostly = {
679748
.kind = "bond",
680749
.priv_size = sizeof(struct bonding),
@@ -689,6 +758,8 @@ struct rtnl_link_ops bond_link_ops __read_mostly = {
689758
.get_num_tx_queues = bond_get_num_tx_queues,
690759
.get_num_rx_queues = bond_get_num_tx_queues, /* Use the same number
691760
as for TX queues */
761+
.fill_linkxstats = bond_fill_linkxstats,
762+
.get_linkxstats_size = bond_get_linkxstats_size,
692763
.slave_maxtype = IFLA_BOND_SLAVE_MAX,
693764
.slave_policy = bond_slave_policy,
694765
.slave_changelink = bond_slave_changelink,

include/net/bond_3ad.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,19 @@ struct port;
180180
#pragma pack(8)
181181
#endif
182182

183+
struct bond_3ad_stats {
184+
atomic64_t lacpdu_rx;
185+
atomic64_t lacpdu_tx;
186+
atomic64_t lacpdu_unknown_rx;
187+
atomic64_t lacpdu_illegal_rx;
188+
189+
atomic64_t marker_rx;
190+
atomic64_t marker_tx;
191+
atomic64_t marker_resp_rx;
192+
atomic64_t marker_resp_tx;
193+
atomic64_t marker_unknown_rx;
194+
};
195+
183196
/* aggregator structure(43.4.5 in the 802.3ad standard) */
184197
typedef struct aggregator {
185198
struct mac_addr aggregator_mac_address;
@@ -272,6 +285,7 @@ struct ad_bond_info {
272285
struct ad_slave_info {
273286
struct aggregator aggregator; /* 802.3ad aggregator structure */
274287
struct port port; /* 802.3ad port structure */
288+
struct bond_3ad_stats stats;
275289
u16 id;
276290
};
277291

@@ -307,5 +321,8 @@ int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond,
307321
int bond_3ad_set_carrier(struct bonding *bond);
308322
void bond_3ad_update_lacp_rate(struct bonding *bond);
309323
void bond_3ad_update_ad_actor_settings(struct bonding *bond);
324+
void bond_3ad_stats_add(struct slave *slave, struct bond_3ad_stats *stats);
325+
int bond_3ad_stats_fill(struct sk_buff *skb, struct bond_3ad_stats *stats);
326+
size_t bond_3ad_stats_size(void);
310327
#endif /* _NET_BOND_3AD_H */
311328

0 commit comments

Comments
 (0)