From 73931706e74ea2bc06d452599a20be583104ccc7 Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Wed, 16 Mar 2016 02:07:04 +0000 Subject: [PATCH] [net80211] Begin implementing rate control module stats. * Implement a new ratectl method, which defaults to returning nothing; * Add a top level sysctl (net.wlan.X.rate_stats) to extract it; * Add ratectl info for the 'amrr' module. Tested: * urtwn(4), STA mode Differential Revision: https://reviews.freebsd.org/D5630 --- sys/net80211/ieee80211_amrr.c | 31 ++++++++++++++++++++++++ sys/net80211/ieee80211_ratectl.c | 41 ++++++++++++++++++++++++++++++++ sys/net80211/ieee80211_ratectl.h | 11 +++++++++ 3 files changed, 83 insertions(+) diff --git a/sys/net80211/ieee80211_amrr.c b/sys/net80211/ieee80211_amrr.c index f50334e9af1b..7460223556bc 100644 --- a/sys/net80211/ieee80211_amrr.c +++ b/sys/net80211/ieee80211_amrr.c @@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -75,6 +76,7 @@ static void amrr_tx_update(const struct ieee80211vap *vap, const struct ieee80211_node *, void *, void *, void *); static void amrr_sysctlattach(struct ieee80211vap *, struct sysctl_ctx_list *, struct sysctl_oid *); +static void amrr_node_stats(struct ieee80211_node *ni, struct sbuf *s); /* number of references from net80211 layer */ static int nrefs = 0; @@ -91,6 +93,7 @@ static const struct ieee80211_ratectl amrr = { .ir_tx_complete = amrr_tx_complete, .ir_tx_update = amrr_tx_update, .ir_setinterval = amrr_setinterval, + .ir_node_stats = amrr_node_stats, }; IEEE80211_RATECTL_MODULE(amrr, 1); IEEE80211_RATECTL_ALG(amrr, IEEE80211_RATECTL_AMRR, amrr); @@ -410,3 +413,31 @@ amrr_sysctlattach(struct ieee80211vap *vap, "amrr_min_sucess_threshold", CTLFLAG_RW, &amrr->amrr_min_success_threshold, 0, ""); } + +static void +amrr_node_stats(struct ieee80211_node *ni, struct sbuf *s) +{ + int rate; + struct ieee80211_amrr_node *amn = ni->ni_rctls; + struct ieee80211_rateset *rs; + + /* XXX TODO: check locking? */ + + /* XXX TODO: this should be a method */ + if (amrr_node_is_11n(ni)) { + rs = (struct ieee80211_rateset *) &ni->ni_htrates; + rate = rs->rs_rates[amn->amn_rix] & IEEE80211_RATE_VAL; + sbuf_printf(s, "rate: MCS %d\n", rate); + } else { + rs = &ni->ni_rates; + rate = rs->rs_rates[amn->amn_rix] & IEEE80211_RATE_VAL; + sbuf_printf(s, "rate: %d Mbit\n", rate / 2); + } + + sbuf_printf(s, "ticks: %d\n", amn->amn_ticks); + sbuf_printf(s, "txcnt: %u\n", amn->amn_txcnt); + sbuf_printf(s, "success: %u\n", amn->amn_success); + sbuf_printf(s, "success_threshold: %u\n", amn->amn_success_threshold); + sbuf_printf(s, "recovery: %u\n", amn->amn_recovery); + sbuf_printf(s, "retry_cnt: %u\n", amn->amn_retrycnt); +} diff --git a/sys/net80211/ieee80211_ratectl.c b/sys/net80211/ieee80211_ratectl.c index 3eff898ecd46..e9a0e2f9279d 100644 --- a/sys/net80211/ieee80211_ratectl.c +++ b/sys/net80211/ieee80211_ratectl.c @@ -28,6 +28,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -68,12 +69,52 @@ ieee80211_ratectl_unregister(int type) ratectls[type] = NULL; } +static void +ieee80211_ratectl_sysctl_stats_node_iter(void *arg, struct ieee80211_node *ni) +{ + + struct sbuf *sb = (struct sbuf *) arg; + sbuf_printf(sb, "MAC: %6D\n", ni->ni_macaddr, ":"); + ieee80211_ratectl_node_stats(ni, sb); + sbuf_printf(sb, "\n"); +} + +static int +ieee80211_ratectl_sysctl_stats(SYSCTL_HANDLER_ARGS) +{ + struct ieee80211vap *vap = arg1; + struct ieee80211com *ic = vap->iv_ic; + struct sbuf sb; + int error; + + error = sysctl_wire_old_buffer(req, 0); + if (error) + return (error); + sbuf_new_for_sysctl(&sb, NULL, 8, req); + sbuf_clear_flags(&sb, SBUF_INCLUDENUL); + + IEEE80211_LOCK(ic); + ieee80211_iterate_nodes(&ic->ic_sta, + ieee80211_ratectl_sysctl_stats_node_iter, + &sb); + IEEE80211_UNLOCK(ic); + + error = sbuf_finish(&sb); + sbuf_delete(&sb); + return (error); +} + void ieee80211_ratectl_init(struct ieee80211vap *vap) { if (vap->iv_rate == ratectls[IEEE80211_RATECTL_NONE]) ieee80211_ratectl_set(vap, IEEE80211_RATECTL_AMRR); vap->iv_rate->ir_init(vap); + + /* Attach generic stats sysctl */ + SYSCTL_ADD_PROC(vap->iv_sysctl, SYSCTL_CHILDREN(vap->iv_oid), OID_AUTO, + "rate_stats", CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, vap, + 0, ieee80211_ratectl_sysctl_stats, "A", "ratectl node stats"); } void diff --git a/sys/net80211/ieee80211_ratectl.h b/sys/net80211/ieee80211_ratectl.h index 56035094db54..9765fe7acbcd 100644 --- a/sys/net80211/ieee80211_ratectl.h +++ b/sys/net80211/ieee80211_ratectl.h @@ -53,6 +53,7 @@ struct ieee80211_ratectl { const struct ieee80211_node *, void *, void *, void *); void (*ir_setinterval)(const struct ieee80211vap *, int); + void (*ir_node_stats)(struct ieee80211_node *ni, struct sbuf *s); }; void ieee80211_ratectl_register(int, const struct ieee80211_ratectl *); @@ -115,3 +116,13 @@ ieee80211_ratectl_setinterval(const struct ieee80211vap *vap, int msecs) return; vap->iv_rate->ir_setinterval(vap, msecs); } + +static __inline void +ieee80211_ratectl_node_stats(struct ieee80211_node *ni, struct sbuf *s) +{ + const struct ieee80211vap *vap = ni->ni_vap; + + if (vap->iv_rate->ir_node_stats == NULL) + return; + vap->iv_rate->ir_node_stats(ni, s); +}