Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: bridge: add STP xstats

This adds rx_bpdu, tx_bpdu, rx_tcn, tx_tcn, transition_blk,
transition_fwd xstats counters to the bridge ports copied over via
netlink, providing useful information for STP.

Signed-off-by: Vivien Didelot <vivien.didelot@gmail.com>
Acked-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>

authored by

Vivien Didelot and committed by
Jakub Kicinski
de179966 ea6a5476

+44
+10
include/uapi/linux/if_bridge.h
··· 156 156 __u32 pad2; 157 157 }; 158 158 159 + struct bridge_stp_xstats { 160 + __u64 transition_blk; 161 + __u64 transition_fwd; 162 + __u64 rx_bpdu; 163 + __u64 tx_bpdu; 164 + __u64 rx_tcn; 165 + __u64 tx_tcn; 166 + }; 167 + 159 168 /* Bridge multicast database attributes 160 169 * [MDBA_MDB] = { 161 170 * [MDBA_MDB_ENTRY] = { ··· 271 262 BRIDGE_XSTATS_VLAN, 272 263 BRIDGE_XSTATS_MCAST, 273 264 BRIDGE_XSTATS_PAD, 265 + BRIDGE_XSTATS_STP, 274 266 __BRIDGE_XSTATS_MAX 275 267 }; 276 268 #define BRIDGE_XSTATS_MAX (__BRIDGE_XSTATS_MAX - 1)
+13
net/bridge/br_netlink.c
··· 1607 1607 br_multicast_get_stats(br, p, nla_data(nla)); 1608 1608 } 1609 1609 #endif 1610 + 1611 + if (p) { 1612 + nla = nla_reserve_64bit(skb, BRIDGE_XSTATS_STP, 1613 + sizeof(p->stp_xstats), 1614 + BRIDGE_XSTATS_PAD); 1615 + if (!nla) 1616 + goto nla_put_failure; 1617 + 1618 + spin_lock_bh(&br->lock); 1619 + memcpy(nla_data(nla), &p->stp_xstats, sizeof(p->stp_xstats)); 1620 + spin_unlock_bh(&br->lock); 1621 + } 1622 + 1610 1623 nla_nest_end(skb, nest); 1611 1624 *prividx = 0; 1612 1625
+2
net/bridge/br_private.h
··· 283 283 #endif 284 284 u16 group_fwd_mask; 285 285 u16 backup_redirected_cnt; 286 + 287 + struct bridge_stp_xstats stp_xstats; 286 288 }; 287 289 288 290 #define kobj_to_brport(obj) container_of(obj, struct net_bridge_port, kobj)
+15
net/bridge/br_stp.c
··· 45 45 br_info(p->br, "port %u(%s) entered %s state\n", 46 46 (unsigned int) p->port_no, p->dev->name, 47 47 br_port_state_names[p->state]); 48 + 49 + if (p->br->stp_enabled == BR_KERNEL_STP) { 50 + switch (p->state) { 51 + case BR_STATE_BLOCKING: 52 + p->stp_xstats.transition_blk++; 53 + break; 54 + case BR_STATE_FORWARDING: 55 + p->stp_xstats.transition_fwd++; 56 + break; 57 + } 58 + } 48 59 } 49 60 50 61 /* called under bridge lock */ ··· 495 484 struct net_bridge *br; 496 485 int was_root; 497 486 487 + p->stp_xstats.rx_bpdu++; 488 + 498 489 br = p->br; 499 490 was_root = br_is_root_bridge(br); 500 491 ··· 530 517 /* called under bridge lock */ 531 518 void br_received_tcn_bpdu(struct net_bridge_port *p) 532 519 { 520 + p->stp_xstats.rx_tcn++; 521 + 533 522 if (br_is_designated_port(p)) { 534 523 br_info(p->br, "port %u(%s) received tcn bpdu\n", 535 524 (unsigned int) p->port_no, p->dev->name);
+4
net/bridge/br_stp_bpdu.c
··· 118 118 br_set_ticks(buf+33, bpdu->forward_delay); 119 119 120 120 br_send_bpdu(p, buf, 35); 121 + 122 + p->stp_xstats.tx_bpdu++; 121 123 } 122 124 123 125 /* called under bridge lock */ ··· 135 133 buf[2] = 0; 136 134 buf[3] = BPDU_TYPE_TCN; 137 135 br_send_bpdu(p, buf, 4); 136 + 137 + p->stp_xstats.tx_tcn++; 138 138 } 139 139 140 140 /*