mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-10-30 18:07:52 +00:00
WiFi-1827. Updates for RRM Channel Hop based on Noise Floor threshold
Average Noise Floor is calcluated for the last few samples based on the configured Noise Floor time. This calculated avg Noise Floor is compared against the configured Noise Floor threshold to decide if a Channel hop is required. While calculating the average, each noise sample is first converted from dBm to milliWatts, an avaerage of the all the noise samples in milliWatt is calculated, then the average is converted back to dBm. Signed-off-by: ravi vaishnav <ravi.vaishnav@netexperience.com>
This commit is contained in:
committed by
Rick Sommerville
parent
3881ec638b
commit
7569b618ff
@@ -42,4 +42,6 @@ extern int net_get_mac(char *iface, char *mac);
|
||||
extern int net_is_bridge(char *iface);
|
||||
extern char* get_max_channel_bw_channel(int channel_freq, const char* htmode);
|
||||
int phy_find_hwmon_helper(char *dir, char *file, char *hwmon);
|
||||
extern double dBm_to_mwatts(double dBm);
|
||||
extern double mWatts_to_dBm(double mW);
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <glob.h>
|
||||
#include <libgen.h>
|
||||
#include <fcntl.h>
|
||||
@@ -693,3 +694,14 @@ bool vif_get_key_for_key_distr(const char *secret, char *key_str)
|
||||
fclose(fp);
|
||||
return err;
|
||||
}
|
||||
|
||||
double dBm_to_mwatts(double dBm)
|
||||
{
|
||||
return (pow(10,(dBm/10)));
|
||||
}
|
||||
|
||||
double mWatts_to_dBm(double mW)
|
||||
{
|
||||
return (10*log10(mW));
|
||||
}
|
||||
|
||||
|
||||
@@ -48,6 +48,12 @@ typedef struct
|
||||
ds_tree_node_t node;
|
||||
} rrm_vif_state_t;
|
||||
|
||||
#define RRM_CHANNEL_INTERVAL 15
|
||||
|
||||
#define RRM_MAX_NF_SAMPLES 100
|
||||
#define RRM_OBSS_HOP_MODE_NON_WIFI 1
|
||||
#define RRM_OBSS_HOP_MODE_NON_WIFI_AND_OBSS 2
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// Cached data
|
||||
@@ -59,9 +65,17 @@ typedef struct
|
||||
uint32_t min_load;
|
||||
uint32_t beacon_rate;
|
||||
uint32_t mcast_rate;
|
||||
int32_t noise_floor_thresh;
|
||||
uint32_t noise_floor_time;
|
||||
int32_t non_wifi_thresh;
|
||||
uint32_t non_wifi_time;
|
||||
uint32_t obss_hop_mode;
|
||||
|
||||
// Internal state data
|
||||
int32_t noise_lwm;
|
||||
int32_t avg_nf;
|
||||
int32_t rrm_chan_nf_next_el;
|
||||
int32_t rrm_chan_nf_num_el;
|
||||
double rrm_chan_nf_samples[RRM_MAX_NF_SAMPLES];
|
||||
} rrm_entry_t;
|
||||
|
||||
typedef struct
|
||||
@@ -80,5 +94,6 @@ void set_rrm_parameters(rrm_entry_t *rrm_data);
|
||||
ds_tree_t* rrm_get_rrm_config_list(void);
|
||||
ds_tree_t* rrm_get_radio_list(void);
|
||||
ds_tree_t* rrm_get_vif_list(void);
|
||||
void rrm_reset_noise_floor_samples(rrm_entry_t *rrm_data);
|
||||
|
||||
#endif /* RRM_H_INCLUDED */
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
#include "uci.h"
|
||||
#include "utils.h"
|
||||
|
||||
#define RRM_CHANNEL_INTERVAL 15.0
|
||||
|
||||
struct blob_buf b = { };
|
||||
struct blob_buf del = { };
|
||||
struct uci_context *uci;
|
||||
@@ -103,6 +101,57 @@ void get_channel_bandwidth(const char* htmode, int *channel_bandwidth)
|
||||
else if(!strcmp(htmode, "HT80"))
|
||||
*channel_bandwidth=80;
|
||||
}
|
||||
/*
|
||||
* A simple average is calculated against the Noise floor samples.
|
||||
* - Returns a zero, if there are not enough samples in the list.
|
||||
* - Or, returns a calculated avg of the noise samples.
|
||||
* - A circular buffer is considered for storing the samples. New elements replace the
|
||||
* old ones in this buffer.
|
||||
* - The number of samples required is an integer value calculated based on the
|
||||
* configuration time and the sample time.
|
||||
* Example: If the config_time is 120 sec, and sample time is 15 sec, then number of
|
||||
* samples required for averaging is 120/15 = 8 samples.
|
||||
*/
|
||||
int rrm_calculate_avg_noise_floor(rrm_entry_t *rrm_data, int nf, int config_time, int sample_time)
|
||||
{
|
||||
int ii;
|
||||
double avg_mW = 0;
|
||||
int num_samples = config_time/sample_time;
|
||||
|
||||
if (num_samples >= RRM_MAX_NF_SAMPLES)
|
||||
num_samples = RRM_MAX_NF_SAMPLES;
|
||||
|
||||
/*
|
||||
* Convert dBm to milliWatts,
|
||||
* and replace the oldest element in the list with the new element
|
||||
*/
|
||||
rrm_data->rrm_chan_nf_samples[rrm_data->rrm_chan_nf_next_el] = dBm_to_mwatts(nf);
|
||||
|
||||
/* Update the index to the oldest element index taking care of the boundary */
|
||||
rrm_data->rrm_chan_nf_next_el = (rrm_data->rrm_chan_nf_next_el+1)%num_samples;
|
||||
|
||||
if (rrm_data->rrm_chan_nf_num_el < num_samples)
|
||||
{
|
||||
rrm_data->rrm_chan_nf_num_el++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* calculate average */
|
||||
for (ii = 0; ii < num_samples; ii++)
|
||||
{
|
||||
avg_mW += rrm_data->rrm_chan_nf_samples[ii];
|
||||
}
|
||||
avg_mW = avg_mW/num_samples;
|
||||
|
||||
/* convert the averaged milliWats back to dBm */
|
||||
return ((int)(mWatts_to_dBm(avg_mW)));
|
||||
}
|
||||
|
||||
void rrm_reset_noise_floor_samples(rrm_entry_t *rrm_data)
|
||||
{
|
||||
rrm_data->rrm_chan_nf_next_el = 0;
|
||||
rrm_data->rrm_chan_nf_num_el = 0;
|
||||
}
|
||||
|
||||
void rrm_nf_timer_handler(struct ev_loop *loop, ev_timer *timer, int revents)
|
||||
{
|
||||
@@ -113,7 +162,6 @@ void rrm_nf_timer_handler(struct ev_loop *loop, ev_timer *timer, int revents)
|
||||
rrm_radio_state_t *radio = NULL;
|
||||
uint32_t noise;
|
||||
int32_t nf;
|
||||
int32_t nf_drop_threshold;
|
||||
rrm_config_t *rrm_config;
|
||||
|
||||
ds_tree_t *radio_list = rrm_get_radio_list();
|
||||
@@ -122,14 +170,13 @@ void rrm_nf_timer_handler(struct ev_loop *loop, ev_timer *timer, int revents)
|
||||
{
|
||||
noise = 0;
|
||||
rrm_config = NULL;
|
||||
nf_drop_threshold = 0;
|
||||
|
||||
if (ubus_get_noise(radio->config.if_name, &noise))
|
||||
continue;
|
||||
|
||||
nf = (int32_t)noise;
|
||||
|
||||
if (nf > -1 || nf < -120)
|
||||
if ((nf > -10) || (nf < -120))
|
||||
continue;
|
||||
|
||||
rrm_config = rrm_get_rrm_config(radio->config.type);
|
||||
@@ -137,43 +184,39 @@ void rrm_nf_timer_handler(struct ev_loop *loop, ev_timer *timer, int revents)
|
||||
if (rrm_config == NULL)
|
||||
continue;
|
||||
|
||||
if (nf < rrm_config->rrm_data.noise_lwm )
|
||||
{
|
||||
rrm_config->rrm_data.noise_lwm = nf;
|
||||
LOGD("[%s] noise_lwm set to %d", radio->config.if_name, nf);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rrm_config->rrm_data.snr_percentage_drop == 0)
|
||||
if ((rrm_config->rrm_data.backup_channel == 0) ||
|
||||
(rrm_config->rrm_data.backup_channel == radio->config.chan))
|
||||
continue;
|
||||
|
||||
if (rrm_config->rrm_data.backup_channel == 0)
|
||||
if (rrm_config->rrm_data.noise_floor_thresh == 0)
|
||||
continue;
|
||||
|
||||
nf_drop_threshold = ((int32_t)(100 - rrm_config->rrm_data.snr_percentage_drop) *
|
||||
rrm_config->rrm_data.noise_lwm) / 100;
|
||||
if (rrm_config->rrm_data.noise_floor_time == 0)
|
||||
continue;
|
||||
|
||||
LOGD("[%s] backup=%d nf=%d nf_lwm=%d drop=%d thresh=%d",
|
||||
LOGD("[%s] backup=%d nf=%d nf_thresh=%d",
|
||||
radio->config.if_name,
|
||||
rrm_config->rrm_data.backup_channel,
|
||||
nf,
|
||||
rrm_config->rrm_data.noise_lwm,
|
||||
rrm_config->rrm_data.snr_percentage_drop,
|
||||
nf_drop_threshold);
|
||||
rrm_config->rrm_data.noise_floor_thresh);
|
||||
|
||||
if (nf > nf_drop_threshold)
|
||||
rrm_config->rrm_data.avg_nf = rrm_calculate_avg_noise_floor(&(rrm_config->rrm_data),
|
||||
nf, rrm_config->rrm_data.noise_floor_time, RRM_CHANNEL_INTERVAL);
|
||||
|
||||
if (rrm_config->rrm_data.avg_nf &&
|
||||
(rrm_config->rrm_data.avg_nf > rrm_config->rrm_data.noise_floor_thresh))
|
||||
{
|
||||
LOGI("Interference detected on [%s], switching to backup_channel=%d nf=%d nf_lwm=%d drop=%d thresh=%d",
|
||||
LOGI("Interference detected on [%s],"
|
||||
" switching to backup_channel=%d avg_nf=%d nfthresh=%d",
|
||||
radio->config.if_name,
|
||||
rrm_config->rrm_data.backup_channel,
|
||||
nf,
|
||||
rrm_config->rrm_data.noise_lwm,
|
||||
rrm_config->rrm_data.snr_percentage_drop,
|
||||
nf_drop_threshold);
|
||||
rrm_config->rrm_data.avg_nf,
|
||||
rrm_config->rrm_data.noise_floor_thresh);
|
||||
int channel_bandwidth;
|
||||
int sec_chan_offset=0;
|
||||
struct mode_map *m = mode_map_get_uci(radio->schema.freq_band, get_max_channel_bw_channel(ieee80211_channel_to_frequency(rrm_config->rrm_data.backup_channel),
|
||||
radio->schema.ht_mode), radio->schema.hw_mode);
|
||||
struct mode_map *m = mode_map_get_uci(radio->schema.freq_band,
|
||||
get_max_channel_bw_channel(ieee80211_channel_to_frequency(rrm_config->rrm_data.backup_channel),
|
||||
radio->schema.ht_mode), radio->schema.hw_mode);
|
||||
if (m) {
|
||||
sec_chan_offset = m->sec_channel_offset;
|
||||
} else
|
||||
@@ -183,6 +226,8 @@ void rrm_nf_timer_handler(struct ev_loop *loop, ev_timer *timer, int revents)
|
||||
radio->schema.ht_mode), &channel_bandwidth);
|
||||
ubus_set_channel_switch(radio->config.if_name,
|
||||
ieee80211_channel_to_frequency(rrm_config->rrm_data.backup_channel), channel_bandwidth, sec_chan_offset);
|
||||
|
||||
rrm_reset_noise_floor_samples(&(rrm_config->rrm_data));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,6 +124,21 @@ void rrm_config_update(void)
|
||||
rrm_data.min_load = rrm->schema.min_load;
|
||||
rrm_data.beacon_rate = rrm->schema.beacon_rate;
|
||||
rrm_data.mcast_rate = rrm->schema.mcast_rate;
|
||||
rrm_data.noise_floor_thresh = rrm->schema.noise_floor_thresh;
|
||||
rrm_data.noise_floor_time = rrm->schema.noise_floor_time;
|
||||
if (rrm_data.noise_floor_time/RRM_CHANNEL_INTERVAL > RRM_MAX_NF_SAMPLES)
|
||||
{
|
||||
LOG(WARN, "RRM Config: Noise floor time too high."
|
||||
" nf_time:%d, sampling_interval:%d, max_num_samples:%d",
|
||||
rrm_data.noise_floor_time, RRM_CHANNEL_INTERVAL,
|
||||
RRM_MAX_NF_SAMPLES);
|
||||
}
|
||||
rrm_data.non_wifi_thresh = rrm->schema.non_wifi_thresh;
|
||||
rrm_data.non_wifi_time = rrm->schema.non_wifi_time;
|
||||
rrm_data.obss_hop_mode = rrm->schema.obss_hop_mode;
|
||||
|
||||
rrm_data.avg_nf = 0;
|
||||
rrm_reset_noise_floor_samples(&rrm_data);
|
||||
|
||||
/* Update cache config */
|
||||
rrm->rrm_data = rrm_data;
|
||||
@@ -408,13 +423,7 @@ void rrm_update_rrm_config_cb(ovsdb_update_monitor_t *self)
|
||||
return;
|
||||
}
|
||||
/* Reset configuration */
|
||||
rrm_config->schema.backup_channel = 0;
|
||||
rrm_config->schema.min_load = 0;
|
||||
rrm_config->schema.beacon_rate = 0;
|
||||
rrm_config->schema.mcast_rate = 0;
|
||||
rrm_config->schema.snr_percentage_drop = 0;
|
||||
rrm_config->schema.client_disconnect_threshold = 0;
|
||||
rrm_config->schema.probe_resp_threshold = 0;
|
||||
memset(&(rrm_config->schema), 0, sizeof(rrm_config->schema));
|
||||
|
||||
ds_tree_remove(&rrm_config_list, rrm_config);
|
||||
free(rrm_config);
|
||||
|
||||
Reference in New Issue
Block a user