diff --git a/bcm/bcm.c b/bcm/bcm.c index 382392b07ddfb962e8e1c5bf13cf6fa56c3fd40f..d8edf2f65529c33c5d35abb840492751e4d85f19 100644 --- a/bcm/bcm.c +++ b/bcm/bcm.c @@ -474,6 +474,31 @@ int bcm_eth_get_rmon_stats(const char *ifname, struct eth_rmon_stats *rmon) return 0; } +int bcm_eth_clear_stats(const char *ifname) +{ + int ret, unit = -1, port = -1; + struct ethswctl_data data; + + memset(&data, 0, sizeof(struct ethswctl_data)); + + ret = bcm_eth_get_unit_port(ifname, &unit, &port); + if (ret) + return -1; + + data.op = ETHSWSTATPORTCLR; + data.port = port; + data.unit = unit; + + ret = eth_ioctl(ifname, SIOCETHSWCTLOPS, &data, + sizeof(struct ethswctl_data)); + if (ret != 0) { + libethernet_err("ioctl failed! ret = %d\n", ret); + return -1; + } + + return 0; +} + const struct eth_ops bcm_eth_ops = { .ifname = "eth", //.up = bcm_eth_up, @@ -485,4 +510,5 @@ const struct eth_ops bcm_eth_ops = { .poweron_phy = bcm_eth_poweron_phy, .poweroff_phy = bcm_eth_poweroff_phy, .reset_phy = bcm_eth_reset_phy, + .clear_stats = bcm_eth_clear_stats, }; diff --git a/econet/econet.c b/econet/econet.c index 42cc04f3b315f2b0b3e893f32f4abe662b55a810..b965dfd0eee0ba2a35d1d96d1d58ff66b6caba38 100644 --- a/econet/econet.c +++ b/econet/econet.c @@ -138,6 +138,27 @@ int econet_eth_reset_phy(const char *name, int phy_id) return 0; } +int econet_clear_stats(const char *ifname) +{ + char clear_stats_filename[128] = {0}; + FILE *fp = NULL; + + // clear stats files are named as eth0.1_clear_stats etc. + snprintf(clear_stats_filename, sizeof(clear_stats_filename), "/proc/tc3162/%s_clear_stats", ifname); + + fp = fopen(clear_stats_filename, "w"); + if (!fp) { + libethernet_err("%s(): fopen() failed for %s\n", __func__, clear_stats_filename); + return -1; + } else { + // just write 1 to clear the stats + fprintf(fp, "1"); + fclose(fp); + } + + return 0; +} + /* Declare separate eth ops for all known Econet interfaces */ #define ECNT_ETH_OPS(__name, __interface_name) \ const struct eth_ops __name = { \ @@ -149,6 +170,7 @@ const struct eth_ops __name = { \ .poweron_phy = econet_eth_poweron_phy, \ .poweroff_phy = econet_eth_poweroff_phy, \ .reset_phy = econet_eth_reset_phy, \ + .clear_stats = econet_clear_stats, \ } ECNT_ETH_OPS(econet_gen_eth_ops, "eth"); diff --git a/ethernet.c b/ethernet.c index 8c81568fd9ab3fd778f4f205f125e2d21a93cb69..aea13efe61b9ef3d0e8f33cc9d2441b2764ff7a7 100644 --- a/ethernet.c +++ b/ethernet.c @@ -165,6 +165,16 @@ int eth_get_rmon_stats(const char *ifname, struct eth_rmon_stats *rmon) return -1; } +int eth_clear_stats(const char *ifname) +{ + const struct eth_ops *eth = get_eth_driver(ifname); + + if (eth && eth->clear_stats) + return eth->clear_stats(ifname); + + return -1; +} + int eth_poweron_phy(const char *ifname, struct eth_phy p) { const struct eth_ops *eth = get_eth_driver(ifname); diff --git a/ethernet.h b/ethernet.h index 3f1dd4e491ba3cc77d637d9ec3e81609b68a909d..b08fdeda90ca17c0e8bd30247ebe71ec2eed951a 100644 --- a/ethernet.h +++ b/ethernet.h @@ -207,6 +207,8 @@ struct eth_ops { int (*get_stats)(const char *ifname, struct eth_stats *s); int (*get_info)(const char *ifname, struct eth_info *info); int (*get_rmon_stats)(const char *ifname, struct eth_rmon_stats *rmon); + + int (*clear_stats)(const char *ifname); }; @@ -220,6 +222,7 @@ int eth_set_operstate(const char *ifname, ifopstatus_t s); int eth_get_stats(const char *ifname, struct eth_stats *c); int eth_get_info(const char *ifname, struct eth_info *info); int eth_get_rmon_stats(const char *ifname, struct eth_rmon_stats *rmon); +int eth_clear_stats(const char *ifname); int eth_reset_phy(const char *ifname, int phy_id); int eth_poweroff_phy(const char *ifname, struct eth_phy p);