1 /* 2 * This program is free software; you can redistribute it and/or modify 3 * it under the terms of the GNU General Public License as published by 4 * the Free Software Foundation; either version 2 of the License. 5 * 6 * This program is distributed in the hope that it will be useful, 7 * but WITHOUT ANY WARRANTY; without even the implied warranty of 8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 9 * GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License 12 * along with this program; if not, write to the Free Software 13 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. 14 * 15 * Copyright (C) 2022 David Bauer <mail@david-bauer.net> 16 */ 17 18 #include "usteer.h" 19 #include "node.h" 20 21 void usteer_band_steering_sta_update(struct sta_info *si) 22 { 23 if (si->connected == STA_NOT_CONNECTED) { 24 if (si->band_steering.signal_threshold != NO_SIGNAL) { 25 si->band_steering.signal_threshold = NO_SIGNAL; 26 } 27 return; 28 } 29 if (config.band_steering_signal_threshold) 30 { 31 if (si->connected != STA_NOT_CONNECTED && si->band_steering.signal_threshold == NO_SIGNAL) 32 { 33 si->band_steering.signal_threshold = si->signal; 34 MSG(DEBUG, "band steering station " MAC_ADDR_FMT " (%s) set threshold %d\n", MAC_ADDR_DATA(si->sta->addr), usteer_node_name(si->node), si->band_steering.signal_threshold); 35 return; 36 } 37 38 /* Adapt signal threshold to actual signal quality */ 39 if (si->signal < si->band_steering.signal_threshold) { 40 si->band_steering.signal_threshold--; 41 MSG(DEBUG, "band steering station " MAC_ADDR_FMT " (%s) reduce threshold %d, signal: %d\n", MAC_ADDR_DATA(si->sta->addr), usteer_node_name(si->node), si->band_steering.signal_threshold, si->signal); 42 } 43 if (si->signal < si->band_steering.signal_threshold + config.band_steering_signal_threshold) 44 si->band_steering.below_snr = true; 45 } 46 if (si->signal < usteer_snr_to_signal(si->node, config.band_steering_min_snr)) 47 si->band_steering.below_snr = true; 48 } 49 50 bool usteer_band_steering_is_target(struct usteer_local_node *ln, struct usteer_node *node) 51 { 52 if (&ln->node == node) 53 return false; 54 55 if (strcmp(ln->node.ssid, node->ssid)) 56 return false; 57 58 if (node->freq < 4000) 59 return false; 60 61 if (!usteer_policy_node_below_max_assoc(node)) 62 return false; 63 64 /* ToDo: Skip nodes with active load-kick */ 65 66 return true; 67 } 68 69 70 static bool usteer_band_steering_has_target_iface(struct usteer_local_node *ln) 71 { 72 struct usteer_node *node; 73 74 for_each_local_node(node) { 75 if (usteer_band_steering_is_target(ln, node)) 76 return true; 77 } 78 79 return false; 80 } 81 82 void usteer_band_steering_perform_steer(struct usteer_local_node *ln) 83 { 84 unsigned int min_count = DIV_ROUND_UP(config.band_steering_interval, config.local_sta_update); 85 struct sta_info *si; 86 uint32_t disassoc_timer; 87 uint32_t validity_period; 88 89 if (!config.band_steering_interval) 90 return; 91 92 /* Band-Steering is only available on 2.4 GHz interfaces */ 93 if (ln->node.freq > 4000) 94 return; 95 96 /* Check if we have an interface we can steer to */ 97 if (!usteer_band_steering_has_target_iface(ln)) 98 return; 99 100 /* Only steer every interval */ 101 if (ln->band_steering_interval < min_count) { 102 ln->band_steering_interval++; 103 return; 104 } 105 106 ln->band_steering_interval = 0; 107 108 list_for_each_entry(si, &ln->node.sta_info, node_list) { 109 /* Check if client is eligable to be steerd */ 110 if (!usteer_policy_can_perform_roam(si)) 111 continue; 112 113 /* Skip clients with insufficient SNR-state */ 114 if (si->band_steering.below_snr) { 115 si->band_steering.below_snr = false; 116 continue; 117 } 118 119 /* Skip if in validity period */ 120 if (current_time < si->roam_transition_request_validity_end) 121 continue; 122 123 if (si->bss_transition) { 124 si->roam_transition_request_validity_end = current_time + 10000; 125 validity_period = 10000 / usteer_local_node_get_beacon_interval(ln); /* ~ 10 seconds */ 126 if (si->sta->aggressiveness >= 2) { 127 if (!si->kick_time) 128 si->kick_time = current_time + config.roam_kick_delay; 129 if (si->sta->aggressiveness >= 3) 130 disassoc_timer = (si->kick_time - current_time) / usteer_local_node_get_beacon_interval(ln); 131 else 132 disassoc_timer = 0; 133 usteer_ubus_band_steering_request(si, 0, true, disassoc_timer, true, validity_period); 134 } else 135 usteer_ubus_band_steering_request(si, 0, false, 0, true, validity_period); 136 } 137 138 si->band_steering.below_snr = false; 139 } 140 }
This page was automatically generated by LXR 0.3.1. • OpenWrt