diff options
Diffstat (limited to 'info_scr.c')
-rw-r--r-- | info_scr.c | 227 |
1 files changed, 120 insertions, 107 deletions
@@ -22,29 +22,45 @@ /* GLOBALS */ static WINDOW *w_levels, *w_stats, *w_if, *w_info, *w_net; -static struct timer dyn_updates; -struct iw_range range; -static struct iw_nl80211_linkstat ls; - -void sampling_init(void (*sampling_handler)(int)) +static pthread_t sampling_thread; +static time_t last_update; +// Global linkstat data, populated by sampling thread. +static struct { + bool run; // enable/disable sampling + pthread_mutex_t mutex; // producer/consumer lock for @data + struct iw_nl80211_linkstat data; +} linkstat; + +/** Sampling pthread shared by info and histogram screen. */ +static void *sampling_loop(void *arg) { - struct itimerval i; - div_t d = div(conf.stat_iv, 1000); /* conf.stat_iv in msec */ + sigset_t blockmask; - xsignal(SIGALRM, SIG_IGN); - iw_getinf_range(conf_ifname(), &range); - i.it_interval.tv_sec = i.it_value.tv_sec = d.quot; - i.it_interval.tv_usec = i.it_value.tv_usec = d.rem * 1000; - xsignal(SIGALRM, sampling_handler); + /* See comment in scan_scr.c for rationale. */ + sigemptyset(&blockmask); + sigaddset(&blockmask, SIGWINCH); + pthread_sigmask(SIG_BLOCK, &blockmask, NULL); + + do { + pthread_mutex_lock(&linkstat.mutex); + iw_nl80211_get_linkstat(&linkstat.data); + pthread_mutex_unlock(&linkstat.mutex); - (*sampling_handler)(0); - setitimer(ITIMER_REAL, &i, NULL); + iw_cache_update(&linkstat.data); + } while (linkstat.run && usleep(conf.stat_iv * 1000) == 0); + return NULL; } -void sampling_do_poll(void) +void sampling_init(void) { - iw_nl80211_get_linkstat(&ls); - iw_cache_update(&ls); + linkstat.run = true; + pthread_create(&sampling_thread, NULL, sampling_loop, NULL); +} + +void sampling_stop(void) +{ + linkstat.run = false; + pthread_join(sampling_thread, NULL); } static void display_levels(void) @@ -59,21 +75,23 @@ static void display_levels(void) lvlscale[2] = { -40, -20}; char tmp[0x100]; int line; - bool noise_data_valid = iw_nl80211_have_survey_data(&ls); - int sig_qual = -1; - int sig_qual_max; - int sig_level = ls.signal_avg ?: ls.signal; + bool noise_data_valid; + int sig_qual = -1, sig_qual_max, sig_level; + + + noise_data_valid = iw_nl80211_have_survey_data(&linkstat.data); + sig_level = linkstat.data.signal_avg ?: linkstat.data.signal; /* See comments in iw_cache_update */ if (sig_level == 0) - sig_level = ls.bss_signal; + sig_level = linkstat.data.bss_signal; for (line = 1; line <= WH_LEVEL; line++) mvwclrtoborder(w_levels, line, 1); - if (ls.bss_signal_qual) { + if (linkstat.data.bss_signal_qual) { /* BSS_SIGNAL_UNSPEC is scaled 0..100 */ - sig_qual = ls.bss_signal_qual; + sig_qual = linkstat.data.bss_signal_qual; sig_qual_max = 100; } else if (sig_level) { if (sig_level < -110) @@ -136,7 +154,7 @@ static void display_levels(void) line++; if (noise_data_valid) { - noise = ewma(noise, ls.survey.noise, conf.meter_decay / 100.0); + noise = ewma(noise, linkstat.data.survey.noise, conf.meter_decay / 100.0); mvwaddstr(w_levels, line++, 1, "noise level: "); sprintf(tmp, "%.0f dBm (%s)", noise, dbm2units(noise)); @@ -147,7 +165,7 @@ static void display_levels(void) } if (noise_data_valid && sig_level) { - ssnr = ewma(ssnr, sig_level - ls.survey.noise, + ssnr = ewma(ssnr, sig_level - linkstat.data.survey.noise, conf.meter_decay / 100.0); mvwaddstr(w_levels, line++, 1, "SNR: "); @@ -161,42 +179,39 @@ done_levels: static void display_stats(void) { - struct if_stat nstat; char tmp[0x100]; - if_getstat(conf_ifname(), &nstat); - /* * Interface RX stats */ mvwaddstr(w_stats, 1, 1, "RX: "); - if (ls.rx_packets) { - sprintf(tmp, "%'u (%s)", ls.rx_packets, - byte_units(ls.rx_bytes)); + if (linkstat.data.rx_packets) { + sprintf(tmp, "%'u (%s)", linkstat.data.rx_packets, + byte_units(linkstat.data.rx_bytes)); waddstr_b(w_stats, tmp); } else { waddstr(w_stats, "n/a"); } - if (iw_nl80211_have_survey_data(&ls)) { - if (ls.rx_bitrate[0]) { + if (iw_nl80211_have_survey_data(&linkstat.data)) { + if (linkstat.data.rx_bitrate[0]) { waddstr(w_stats, ", rate: "); - waddstr_b(w_stats, ls.rx_bitrate); + waddstr_b(w_stats, linkstat.data.rx_bitrate); } - if (ls.expected_thru) { - if (ls.expected_thru >= 1024) - sprintf(tmp, " (exp: %.1f MB/s)", ls.expected_thru/1024.0); + if (linkstat.data.expected_thru) { + if (linkstat.data.expected_thru >= 1024) + sprintf(tmp, " (expected: %.1f MB/s)", linkstat.data.expected_thru/1024.0); else - sprintf(tmp, " (exp: %u kB/s)", ls.expected_thru); + sprintf(tmp, " (expected: %u kB/s)", linkstat.data.expected_thru); waddstr(w_stats, tmp); } } - if (ls.rx_drop_misc) { + if (linkstat.data.rx_drop_misc) { waddstr(w_stats, ", drop: "); - sprintf(tmp, "%'llu", (unsigned long long)ls.rx_drop_misc); + sprintf(tmp, "%'llu", (unsigned long long)linkstat.data.rx_drop_misc); waddstr_b(w_stats, tmp); } @@ -207,28 +222,28 @@ static void display_stats(void) */ mvwaddstr(w_stats, 2, 1, "TX: "); - if (ls.tx_packets) { - sprintf(tmp, "%'u (%s)", ls.tx_packets, - byte_units(ls.tx_bytes)); + if (linkstat.data.tx_packets) { + sprintf(tmp, "%'u (%s)", linkstat.data.tx_packets, + byte_units(linkstat.data.tx_bytes)); waddstr_b(w_stats, tmp); } else { waddstr(w_stats, "n/a"); } - if (iw_nl80211_have_survey_data(&ls) && ls.tx_bitrate[0]) { + if (iw_nl80211_have_survey_data(&linkstat.data) && linkstat.data.tx_bitrate[0]) { waddstr(w_stats, ", rate: "); - waddstr_b(w_stats, ls.tx_bitrate); + waddstr_b(w_stats, linkstat.data.tx_bitrate); } - if (ls.tx_retries) { + if (linkstat.data.tx_retries) { waddstr(w_stats, ", retries: "); - sprintf(tmp, "%'u", ls.tx_retries); + sprintf(tmp, "%'u", linkstat.data.tx_retries); waddstr_b(w_stats, tmp); } - if (ls.tx_failed) { + if (linkstat.data.tx_failed) { waddstr(w_stats, ", failed: "); - sprintf(tmp, "%'u", ls.tx_failed); + sprintf(tmp, "%'u", linkstat.data.tx_failed); waddstr_b(w_stats, tmp); } wclrtoborder(w_stats); @@ -238,11 +253,13 @@ static void display_stats(void) static void display_info(WINDOW *w_if, WINDOW *w_info) { struct iw_dyn_info info; + struct iw_range range; struct iw_nl80211_ifstat ifs; struct iw_nl80211_reg ir; char tmp[0x100]; int i; + iw_getinf_range(conf_ifname(), &range); dyn_info_get(&info, conf_ifname(), &range); iw_nl80211_getifstat(&ifs); iw_nl80211_getreg(&ir); @@ -252,10 +269,7 @@ static void display_info(WINDOW *w_if, WINDOW *w_info) */ wmove(w_if, 1, 1); waddstr_b(w_if, conf_ifname()); - if (range.enc_capa & IW_WPA_MASK) - sprintf(tmp, " (%s, %s)", info.name, format_wpa(&range)); - else - sprintf(tmp, " (%s)", info.name); + sprintf(tmp, " (%s)", info.name); waddstr(w_if, tmp); /* PHY */ @@ -288,10 +302,10 @@ static void display_info(WINDOW *w_if, WINDOW *w_info) waddstr(w_info, "mode: "); waddstr_b(w_info, iftype_name(ifs.iftype)); - if (!ether_addr_is_zero(&ls.bssid)) { + if (!ether_addr_is_zero(&linkstat.data.bssid)) { waddstr_b(w_info, ", "); - switch (ls.status) { + switch (linkstat.data.status) { case NL80211_BSS_STATUS_ASSOCIATED: waddstr(w_info, "connected to: "); break; @@ -304,15 +318,15 @@ static void display_info(WINDOW *w_if, WINDOW *w_info) default: waddstr(w_info, "station: "); } - waddstr_b(w_info, ether_lookup(&ls.bssid)); + waddstr_b(w_info, ether_lookup(&linkstat.data.bssid)); - if (ls.status == NL80211_BSS_STATUS_ASSOCIATED) { + if (linkstat.data.status == NL80211_BSS_STATUS_ASSOCIATED) { waddstr_b(w_info, ","); waddstr(w_info, " time: "); - waddstr_b(w_info, pretty_time(ls.connected_time)); + waddstr_b(w_info, pretty_time(linkstat.data.connected_time)); waddstr(w_info, ", inactive: "); - sprintf(tmp, "%.1fs", (float)ls.inactive_time/1e3); + sprintf(tmp, "%.1fs", (float)linkstat.data.inactive_time/1e3); waddstr_b(w_info, tmp); } } @@ -326,8 +340,8 @@ static void display_info(WINDOW *w_if, WINDOW *w_info) waddstr_b(w_info, tmp); /* The following condition should in theory never happen */ - if (ls.survey.freq && ls.survey.freq != ifs.freq) { - sprintf(tmp, " [survey freq: %d MHz]", ls.survey.freq); + if (linkstat.data.survey.freq && linkstat.data.survey.freq != ifs.freq) { + sprintf(tmp, " [survey freq: %d MHz]", linkstat.data.survey.freq); waddstr(w_info, tmp); } @@ -353,9 +367,9 @@ static void display_info(WINDOW *w_if, WINDOW *w_info) sprintf(tmp, " (%s)", channel_type_name(ifs.chan_type)); waddstr(w_info, tmp); } - } else if (iw_nl80211_have_survey_data(&ls)) { + } else if (iw_nl80211_have_survey_data(&linkstat.data)) { waddstr(w_info, "freq: "); - sprintf(tmp, "%d MHz", ls.survey.freq); + sprintf(tmp, "%d MHz", linkstat.data.survey.freq); waddstr_b(w_info, tmp); } else { waddstr(w_info, "frequency/channel: n/a"); @@ -364,87 +378,87 @@ static void display_info(WINDOW *w_if, WINDOW *w_info) /* Channel data */ wmove(w_info, 3, 1); - if (iw_nl80211_have_survey_data(&ls)) { + if (iw_nl80211_have_survey_data(&linkstat.data)) { waddstr(w_info, "channel "); waddstr(w_info, "active: "); - waddstr_b(w_info, pretty_time_ms(ls.survey.time.active)); + waddstr_b(w_info, pretty_time_ms(linkstat.data.survey.time.active)); waddstr(w_info, ", busy: "); - waddstr_b(w_info, pretty_time_ms(ls.survey.time.busy)); + waddstr_b(w_info, pretty_time_ms(linkstat.data.survey.time.busy)); - if (ls.survey.time.ext_busy) { + if (linkstat.data.survey.time.ext_busy) { waddstr(w_info, ", ext-busy: "); - waddstr_b(w_info, pretty_time_ms(ls.survey.time.ext_busy)); + waddstr_b(w_info, pretty_time_ms(linkstat.data.survey.time.ext_busy)); } waddstr(w_info, ", rx: "); - waddstr_b(w_info, pretty_time_ms(ls.survey.time.rx)); + waddstr_b(w_info, pretty_time_ms(linkstat.data.survey.time.rx)); waddstr(w_info, ", tx: "); - waddstr_b(w_info, pretty_time_ms(ls.survey.time.tx)); + waddstr_b(w_info, pretty_time_ms(linkstat.data.survey.time.tx)); - if (ls.survey.time.scan) { + if (linkstat.data.survey.time.scan) { waddstr(w_info, ", scan: "); - waddstr_b(w_info, pretty_time_ms(ls.survey.time.scan)); + waddstr_b(w_info, pretty_time_ms(linkstat.data.survey.time.scan)); } - } else if (ls.tx_bitrate[0] && ls.rx_bitrate[0]) { + } else if (linkstat.data.tx_bitrate[0] && linkstat.data.rx_bitrate[0]) { waddstr(w_info, "rx rate: "); - waddstr_b(w_info, ls.rx_bitrate); + waddstr_b(w_info, linkstat.data.rx_bitrate); - if (ls.expected_thru) { - if (ls.expected_thru >= 1024) - sprintf(tmp, " (exp: %.1f MB/s)", ls.expected_thru/1024.0); + if (linkstat.data.expected_thru) { + if (linkstat.data.expected_thru >= 1024) + sprintf(tmp, " (exp: %.1f MB/s)", linkstat.data.expected_thru/1024.0); else - sprintf(tmp, " (exp: %u kB/s)", ls.expected_thru); + sprintf(tmp, " (exp: %u kB/s)", linkstat.data.expected_thru); waddstr(w_info, tmp); } waddstr(w_info, ", tx rate: "); - waddstr_b(w_info, ls.tx_bitrate); + waddstr_b(w_info, linkstat.data.tx_bitrate); } /* Beacons */ wmove(w_info, 4, 1); - if (ls.beacons) { + if (linkstat.data.beacons) { waddstr(w_info, "beacons: "); - sprintf(tmp, "%'llu", (unsigned long long)ls.beacons); + sprintf(tmp, "%'llu", (unsigned long long)linkstat.data.beacons); waddstr_b(w_info, tmp); - if (ls.beacon_loss) { + if (linkstat.data.beacon_loss) { waddstr(w_info, ", lost: "); - sprintf(tmp, "%'u", ls.beacon_loss); + sprintf(tmp, "%'u", linkstat.data.beacon_loss); waddstr_b(w_info, tmp); } waddstr(w_info, ", avg sig: "); - sprintf(tmp, "%d dBm", (int8_t)ls.beacon_avg_sig); + sprintf(tmp, "%d dBm", (int8_t)linkstat.data.beacon_avg_sig); waddstr_b(w_info, tmp); waddstr(w_info, ", interval: "); - sprintf(tmp, "%.1fs", (ls.beacon_int * 1024.0)/1e6); + sprintf(tmp, "%.1fs", (linkstat.data.beacon_int * 1024.0)/1e6); waddstr_b(w_info, tmp); waddstr(w_info, ", DTIM: "); - sprintf(tmp, "%u", ls.dtim_period); + sprintf(tmp, "%u", linkstat.data.dtim_period); waddstr_b(w_info, tmp); } else { waddstr(w_info, "station flags:"); - if (ls.cts_protection) + if (linkstat.data.cts_protection) waddstr_b(w_info, " CTS"); - if (ls.wme) + if (linkstat.data.wme) waddstr_b(w_info, " WME"); - if (ls.tdls) + if (linkstat.data.tdls) waddstr_b(w_info, " TDLS"); - if (ls.mfp) + if (linkstat.data.mfp) waddstr_b(w_info, " MFP"); - if (!(ls.cts_protection | ls.wme | ls.tdls | ls.mfp)) + if (!(linkstat.data.cts_protection | linkstat.data.wme | linkstat.data.tdls | linkstat.data.mfp)) waddstr_b(w_info, " (none)"); waddstr(w_info, ", preamble:"); - if (ls.long_preamble) + if (linkstat.data.long_preamble) waddstr_b(w_info, " long"); else waddstr_b(w_info, " short"); waddstr(w_info, ", slot:"); - if (ls.short_slot_time) + if (linkstat.data.short_slot_time) waddstr_b(w_info, " short"); else waddstr_b(w_info, " long"); @@ -657,6 +671,7 @@ static void display_netinfo(WINDOW *w_net) waddstr_b(w_net, inet_ntoa(info.bcast)); } } + wclrtoborder(w_net); /* 802.11 MTU may be greater than Ethernet MTU (1500) */ if (info.mtu && info.mtu != ETH_DATA_LEN) { @@ -668,13 +683,6 @@ static void display_netinfo(WINDOW *w_net) wrefresh(w_net); } -static void redraw_stat_levels(int signum) -{ - sampling_do_poll(); - display_levels(); - display_stats(); -} - void scr_info_init(void) { int line = 0; @@ -692,18 +700,23 @@ void scr_info_init(void) else w_net = newwin_title(line, WH_NET_MAX, "Network", false); - display_info(w_if, w_info); - display_netinfo(w_net); - start_timer(&dyn_updates, conf.info_iv * 1000000); - sampling_init(redraw_stat_levels); + sampling_init(); } int scr_info_loop(WINDOW *w_menu) { - if (end_timer(&dyn_updates)) { + time_t now = time(NULL); + + if (!pthread_mutex_trylock(&linkstat.mutex)) { + display_levels(); + display_stats(); + pthread_mutex_unlock(&linkstat.mutex); + } + + if (now - last_update >= conf.info_iv) { + last_update = now; display_info(w_if, w_info); display_netinfo(w_net); - start_timer(&dyn_updates, conf.info_iv * 1000000); } return wgetch(w_menu); } |