Commit 3922fb93 authored by Bruno Randolf's avatar Bruno Randolf

Add function to estimate PHY rate and use for max BPS

parent d7a1ff84
......@@ -24,6 +24,7 @@
#include "ifctrl.h"
#include "channel.h"
#include "ieee80211_util.h"
#include "wlan_util.h"
static struct timeval last_channelchange;
......@@ -181,6 +182,7 @@ bool channel_change(int idx, enum chan_width width, bool ht40plus)
conf.channel_idx = idx;
conf.channel_width = width;
conf.channel_ht40plus = ht40plus;
conf.max_phy_rate = get_phy_thruput(width, channel_get_band_from_idx(idx).streams_rx);
last_channelchange = the_time;
return true;
}
......@@ -288,6 +290,7 @@ bool channel_init(void)
} else {
conf.channel_set_width = conf.channel_width;
conf.channel_set_ht40plus = conf.channel_ht40plus;
conf.max_phy_rate = get_phy_thruput(conf.channel_width, b.streams_rx);
}
}
return true;
......
......@@ -169,7 +169,7 @@ static void update_status_win(struct packet_info* p)
get_per_second(stats.bytes, stats.duration, stats.packets, stats.retries,
&bps, &dps, &pps, &rps);
bps *= 8;
bpsn = normalize(bps, 32000000, max_stat_bar); //theoretical: 54000000
bpsn = normalize(bps, conf.max_phy_rate * 100000 / 3 * 2, max_stat_bar);
use = dps * 1.0 / 10000; /* usec, in percent */
usen = normalize(use, 100, max_stat_bar);
......
......@@ -340,6 +340,7 @@ struct config {
int if_type;
int if_phy;
unsigned int if_freq;
unsigned int max_phy_rate;
};
extern struct config conf;
......
......@@ -146,7 +146,7 @@ int rate_index_to_rate(int idx)
}
/* return rate in 100kbps */
int mcs_index_to_rate(int mcs, int ht20, int lgi)
int mcs_index_to_rate(int mcs, bool ht20, bool lgi)
{
/* MCS Index, http://en.wikipedia.org/wiki/IEEE_802.11n-2009#Data_rates */
switch (mcs) {
......@@ -186,6 +186,62 @@ int mcs_index_to_rate(int mcs, int ht20, int lgi)
return 0;
}
/* return rate in 100kbps
*
* Formula from http://equicom.hu/uploads/file/fluke/pros/how_fast_80211ac_poster.PDF
* may not be 100% exact, but good enough
*/
int vht_mcs_index_to_rate(enum chan_width width, int streams, int mcs, bool sgi)
{
int wf;
float mf;
switch (width) {
case CHAN_WIDTH_UNSPEC:
case CHAN_WIDTH_20_NOHT:
return -1; /* not supported */
case CHAN_WIDTH_20:
wf = 52; break;
case CHAN_WIDTH_40:
wf = 108; break;
case CHAN_WIDTH_80:
wf = 234; break;
case CHAN_WIDTH_160:
case CHAN_WIDTH_8080:
wf = 468; break;
}
switch (mcs) {
case 0: mf = 0.5; break;
case 1: mf = 1.0; break;
case 2: mf = 1.5; break;
case 3: mf = 2.0; break;
case 4: mf = 3.0; break;
case 5: mf = 4.0; break;
case 6: mf = 4.5; break;
case 7: mf = 5.0; break;
case 8: mf = 6.0; break;
case 9: mf = 6.67; break;
default: return -1; /* not supported */
}
/* special unsupported cases */
if (width == CHAN_WIDTH_20 && mcs == 9 && streams != 3)
return -1;
if (width == CHAN_WIDTH_80 && mcs == 6 && streams == 3)
return -1;
if (width == CHAN_WIDTH_160 && mcs == 9 && streams == 3)
return -1;
if (width < CHAN_WIDTH_80 && streams > 4)
return -1;
if (width == CHAN_WIDTH_80 && mcs == 9 && streams == 6)
return -1;
if (width == CHAN_WIDTH_80 && mcs == 6 && streams == 7)
return -1;
return 10.0 /* kpbs */ * streams * wf * mf / (sgi ? 3.6 : 4.0);
}
enum chan_width chan_width_from_vht_capab(uint32_t vht)
{
switch (((vht & WLAN_IE_VHT_CAPAB_INFO_CHAN_WIDTH) >> 2)) {
......@@ -254,3 +310,22 @@ const char* get_80211std(enum chan_width width, int chan)
return "?";
}
}
/* in 100kbps or -1 when unsupported */
int get_phy_thruput(enum chan_width width, unsigned char streams_rx)
{
switch (width) {
case CHAN_WIDTH_UNSPEC:
case CHAN_WIDTH_20_NOHT:
return 540;
case CHAN_WIDTH_20:
return mcs_index_to_rate(streams_rx * 8 - 1, true, false);
case CHAN_WIDTH_40:
return mcs_index_to_rate(streams_rx * 8 - 1, false, false);
case CHAN_WIDTH_80:
case CHAN_WIDTH_160:
case CHAN_WIDTH_8080:
return vht_mcs_index_to_rate(width, streams_rx, 9, true);
}
return 0;
}
......@@ -20,6 +20,10 @@
#ifndef _WLAN_UTIL_H_
#define _WLAN_UTIL_H_
#include <stdbool.h>
enum chan_width;
struct pkt_name {
const char c;
const char* name;
......@@ -38,10 +42,12 @@ char get_packet_type_char(uint16_t type);
const char* get_packet_type_name(uint16_t type);
int rate_to_index(int rate);
int rate_index_to_rate(int idx);
int mcs_index_to_rate(int mcs, int ht20, int lgi);
int mcs_index_to_rate(int mcs, bool ht20, bool lgi);
int vht_mcs_index_to_rate(enum chan_width width, int streams, int mcs, bool sgi);
enum chan_width chan_width_from_vht_capab(uint32_t vht);
void ht_streams_from_mcs_set(unsigned char* mcs, unsigned char* rx, unsigned char* tx);
void vht_streams_from_mcs_set(unsigned char* mcs, unsigned char* rx, unsigned char* tx);
const char* get_80211std(enum chan_width width, int chan);
int get_phy_thruput(enum chan_width width, unsigned char streams_rx);
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment