From 39bedc9a25bbe3f8a43ff4f093464ac73804c7ce Mon Sep 17 00:00:00 2001
From: Rahul <rahul.thakur@iopsys.eu>
Date: Tue, 9 Mar 2021 11:07:58 +0530
Subject: [PATCH] libethernet: add support to read stats for bridge
* Read stats and extended stats for bridge in ethernet.
Note: Supported only for broadcom for now
---
bcm/bcm.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
ethernet.c | 8 ++++++
2 files changed, 84 insertions(+), 2 deletions(-)
diff --git a/bcm/bcm.c b/bcm/bcm.c
index ef96e64..589bfc3 100644
--- a/bcm/bcm.c
+++ b/bcm/bcm.c
@@ -276,12 +276,13 @@ static int bcm_eth_get_stats_from_proc(const char *ifname, struct eth_stats *s)
return 0;
}
-int bcm_eth_get_stats(const char *ifname, struct eth_stats *s)
+
+static int read_eth_stats(const char *ifname, struct eth_stats *s)
{
+ int ret_proc;
struct ethswctl_data data;
int unit = -1;
int port = -1;
- int ret_proc;
int ret;
/* get from proc first */
@@ -331,6 +332,79 @@ int bcm_eth_get_stats(const char *ifname, struct eth_stats *s)
return 0;
}
+
+static void reinit_extended_stats_for_bridge(struct eth_stats *to)
+{
+ // In case of bridge, function to read all stats has already
+ // been called once, which might have stored garbage in the
+ // extended stats, so important to reinit here.
+ to->tx_ucast_packets = 0;
+ to->rx_ucast_packets = 0;
+ to->tx_mcast_packets = 0;
+ to->rx_mcast_packets = 0;
+ to->tx_bcast_packets = 0;
+ to->rx_bcast_packets = 0;
+ to->rx_unknown_packets = 0;
+}
+
+
+// This function adds up the extended stats to get cumulative stats
+// for the bridge type interfaces.
+static void add_to_stats(struct eth_stats *to, struct eth_stats *from)
+{
+ to->tx_ucast_packets += from->tx_ucast_packets;
+ to->rx_ucast_packets += from->rx_ucast_packets;
+ to->tx_mcast_packets += from->tx_mcast_packets;
+ to->rx_mcast_packets += from->rx_mcast_packets;
+ to->tx_bcast_packets += from->tx_bcast_packets;
+ to->rx_bcast_packets += from->rx_bcast_packets;
+ to->rx_unknown_packets += from->rx_unknown_packets;
+}
+
+
+int bcm_eth_get_stats(const char *ifname, struct eth_stats *s)
+{
+
+ if (read_eth_stats(ifname, s)) {
+ libethernet_err("error in reading stats for interface %s\n", ifname);
+ return -1;
+ }
+
+ if (if_isbridge(ifname)) {
+ // read stats for each interface in bridge and add them to get
+ // bridge stats
+ struct eth_stats temp;
+ int ret = 0;
+ char ifnames[32][16] = {0};
+ int count, i;
+
+ ret = br_get_iflist(ifname, &count, ifnames);
+ if ((count <= 0) || (ret < 0)) // empty bridge
+ return 0;
+
+ // only extended stats are not available for bridge interfaces,
+ // we have already read the available stats above and now loop
+ // on the member ports to get the extended stats for each port
+ // and add those up to get the extended stats for the bridge
+ reinit_extended_stats_for_bridge(s);
+ for (i = 0; i < count; i++) {
+ memset(&temp, 0, sizeof(struct eth_stats));
+
+ if (strncmp("eth", ifnames[i], 3) != 0)
+ continue;
+
+ if (read_eth_stats(ifnames[i], &temp)) {
+ libethernet_err("error in reading stats for interface %s\n", ifnames[i]);
+ continue; // no need to add this to bridge stats
+ }
+
+ add_to_stats(s, &temp);
+ }
+ }
+
+ return 0;
+}
+
int bcm_eth_get_rmon_stats(const char *ifname, struct eth_rmon_stats *rmon)
{
struct ethswctl_data data;
diff --git a/ethernet.c b/ethernet.c
index 9fb105b..a159365 100644
--- a/ethernet.c
+++ b/ethernet.c
@@ -66,6 +66,14 @@ const struct eth_ops *get_eth_driver(const char *ifname)
return eth_ops[i];
}
+ // The plan is to have this support in broadcom only for now, that is,
+ // we will present bridge level stats for broadcom only for now, hence,
+ // this, in the long term, we should add this support for all platforms.
+#ifdef IOPSYS_BROADCOM
+ if (if_isbridge(ifname)) {
+ return eth_ops[0];
+ }
+#endif
return NULL;
}
--
GitLab