-
Notifications
You must be signed in to change notification settings - Fork 30
Updates Roaming and Band-Steering #10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
ff1e72d
efb5aa9
22e31ac
edd1f09
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,7 +20,24 @@ | |
|
|
||
| void usteer_band_steering_sta_update(struct sta_info *si) | ||
| { | ||
| if (si->signal < usteer_snr_to_signal(si->node, config.band_steering_min_snr)) | ||
| if (si->connected == STA_NOT_CONNECTED) { | ||
| if (si->band_steering.signal_threshold != NO_SIGNAL) { | ||
| si->band_steering.signal_threshold = NO_SIGNAL; | ||
| } | ||
| return; | ||
| } | ||
| if (si->connected != STA_NOT_CONNECTED && si->band_steering.signal_threshold == NO_SIGNAL) { | ||
| si->band_steering.signal_threshold = si->signal; | ||
| 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); | ||
| return; | ||
| } | ||
|
|
||
| /* Adapt signal threshold to actual signal quality */ | ||
| if (si->signal < si->band_steering.signal_threshold) { | ||
| si->band_steering.signal_threshold--; | ||
| 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); | ||
| } | ||
| if (si->signal < usteer_snr_to_signal(si->node, config.band_steering_min_snr) || si->signal < si->band_steering.signal_threshold + config.band_steering_signal_threshold) | ||
| si->band_steering.below_snr = true; | ||
| } | ||
|
|
||
|
|
@@ -60,6 +77,8 @@ void usteer_band_steering_perform_steer(struct usteer_local_node *ln) | |
| { | ||
| unsigned int min_count = DIV_ROUND_UP(config.band_steering_interval, config.local_sta_update); | ||
| struct sta_info *si; | ||
| uint32_t disassoc_timer; | ||
| uint32_t validity_period; | ||
|
|
||
| if (!config.band_steering_interval) | ||
| return; | ||
|
|
@@ -91,8 +110,24 @@ void usteer_band_steering_perform_steer(struct usteer_local_node *ln) | |
| continue; | ||
| } | ||
|
|
||
| if (si->bss_transition) | ||
| usteer_ubus_band_steering_request(si); | ||
| /* Skip if in validity period */ | ||
| if (current_time < si->roam_transition_request_validity_end) | ||
| continue; | ||
|
|
||
| if (si->bss_transition) { | ||
| si->roam_transition_request_validity_end = current_time + 10000; | ||
| validity_period = 10000 / usteer_local_node_get_beacon_interval(ln); /* ~ 10 seconds */ | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is that comment supposed to be at the line above? And where do the 10 seconds come from? They are not explained anywhere.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, its for the line. The validity period is calculated by beacon interval so is not exactly 10s.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Then what does the the
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 10000ms have to be split up by beacons (e.g. every 150ms). The interval could be set in hostap config. So if the result of the division has to be rounded the beacon interval count does not exactly reflecting 10s anymore.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But that means that Also it still does not explain where the 10 seconds value come from. How was this chosen? Should this be configurable?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes and good question. This is the common standard and also fixed value within e.g. DAWN. Its related to disassociation imminent timer, that if the disassociation is planned within 30s every 10s a new BSS_TM_REQ is send like a timer and to update the neighbor list if the STA moved to another place. Could make sense for experts (it is available in Cisco Controllers) to change it but not relevant for common usage in my opinion. Not everything should be configurable without need and testing. This can be done in another iteration but with this PR I do not plan to add more functionality. |
||
| if (si->sta->aggressiveness >= 2) { | ||
| if (!si->kick_time) | ||
| si->kick_time = current_time + config.roam_kick_delay; | ||
| if (si->sta->aggressiveness >= 3) | ||
| disassoc_timer = (si->kick_time - current_time) / usteer_local_node_get_beacon_interval(ln); | ||
| else | ||
| disassoc_timer = 0; | ||
| usteer_ubus_band_steering_request(si, 0, true, disassoc_timer, true, validity_period); | ||
| } else | ||
| usteer_ubus_band_steering_request(si, 0, false, 0, true, validity_period); | ||
| } | ||
|
|
||
| si->band_steering.below_snr = false; | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -96,11 +96,14 @@ void usteer_init_defaults(void) | |
| config.remote_update_interval = 1000; | ||
| config.initial_connect_delay = 0; | ||
| config.remote_node_timeout = 10; | ||
| config.aggressiveness = 3; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The default should be (IMHO) whatever is the current behavior. The new behavior should be opt-in, not opt-out. Also maybe use an enum or defines for the different levels so its obvious what they mean?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In my opinion it would be better to switch to a new default to have a better roaming for everybody. According the test results in the forum roaming behave much better with the new default which is aligned to DAWNs implementation. Passive roaming is too friendly for most devices. Anyway, I can also see a benefit to stay at the old default that nothing is changed after an upgrade but the default should be the best behavior for most cases... So open for a discussion what would be the best for the start...could be also changed later if we stay on the old behavior for the beginning. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree that it makes more sense to actually activate the new feature instead of leaving it deactivated. Usteer is not a default package anyway and people installing it expect it to actually make clients roam. This PR adds a new feature to improve roaming for certain clients like Intel wifi cards. Yes, it's a new kind of default and it's good to bring up that this might change how usteer works/handles certain situations (good feedback by @KanjiMonster). Looking forward to hear how other people feel about this :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I totally agree with @Djfe. This should come with new default., the release could have a breaking change note with some settings attached to be used by the people that want to keep the old behavior. |
||
| config.reassociation_delay = 30; | ||
NilsRo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| config.steer_reject_timeout = 60000; | ||
|
|
||
| config.band_steering_interval = 120000; | ||
| config.band_steering_interval = 30000; | ||
NilsRo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| config.band_steering_min_snr = -60; | ||
| config.band_steering_signal_threshold = 5; | ||
|
|
||
| config.link_measurement_interval = 30000; | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -322,6 +322,8 @@ static bool | |
| usteer_roam_trigger_sm(struct usteer_local_node *ln, struct sta_info *si) | ||
| { | ||
| struct sta_info *candidate; | ||
| uint32_t disassoc_timer; | ||
| uint32_t validity_period; | ||
| struct uevent ev = { | ||
| .si_cur = si, | ||
| }; | ||
|
|
@@ -343,10 +345,9 @@ usteer_roam_trigger_sm(struct usteer_local_node *ln, struct sta_info *si) | |
| /* Check if no node was found within roam_scan_tries tries */ | ||
| if (config.roam_scan_tries && si->roam_tries >= config.roam_scan_tries) { | ||
| if (!config.roam_scan_timeout) { | ||
| /* Prepare to kick client */ | ||
| usteer_roam_set_state(si, ROAM_TRIGGER_SCAN_DONE, &ev); | ||
| } else { | ||
| /* Kick in scan timeout */ | ||
| /* Set timeout until roam_scans are paused */ | ||
| si->roam_scan_timeout_start = current_time; | ||
| usteer_roam_set_state(si, ROAM_TRIGGER_IDLE, &ev); | ||
| } | ||
|
|
@@ -363,16 +364,44 @@ usteer_roam_trigger_sm(struct usteer_local_node *ln, struct sta_info *si) | |
| break; | ||
|
|
||
| case ROAM_TRIGGER_SCAN_DONE: | ||
| /* Roaming time over, switch back to ROAM_TRIGGER_IDLE */ | ||
| if (si->roam_transition_start && current_time - si->roam_transition_start > config.roam_kick_delay) { | ||
| si->roam_transition_start = 0; | ||
| usteer_roam_set_state(si, ROAM_TRIGGER_IDLE, &ev); | ||
| break; | ||
| } | ||
|
|
||
| candidate = usteer_roam_sm_found_better_node(si, &ev, ROAM_TRIGGER_SCAN_DONE); | ||
| /* Kick back in case no better node is found */ | ||
| if (!candidate) { | ||
| usteer_roam_set_state(si, ROAM_TRIGGER_IDLE, &ev); | ||
| break; | ||
| } | ||
|
|
||
| usteer_ubus_bss_transition_request(si, 1, false, false, 100, candidate->node); | ||
| si->kick_time = current_time + config.roam_kick_delay; | ||
| usteer_roam_set_state(si, ROAM_TRIGGER_IDLE, &ev); | ||
| if (!candidate->node->rrm_nr) | ||
| MSG(VERBOSE, "Candidates node rrm nr not returned from hostapd. Neighbor list empty!"); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the meaning of this check / message? Is the user supposed to do something about it?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is an bug in hostap daemon that it sometimes does not return the rrm numbers which breaks supported roaming. Log messages describes the the error and not the solution as this could be different in many cases even if it are not caused by the software itself. Should be documented in OpenWrt Wiki if published but anyhow the solution must be searched in hostap. Mostly fixed with a restart of the deamon or sometimes on its own.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If it's a bug that breaks roaming does it mean it prevents STAs from connecting to a different SSID? If it breaks stuff, then it should be probably INFO and not VERBOSE, and the message should say something of that effect. As a user, I wouldn't have any idea what rrm nr means or if that is important, so it would just be noise and confusing. Also if it breaks stuff, shouldn't usteer then try to handle that? It doesn't make sense continuing if this won't work, right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
To me the bug @NilsRo found in hostapd sounds more like a follow up that can be tackled now that the behavior was noticed. @NilsRo Was this bug affecting usteer already before your PR and you just added a message so you could restart hostapd when it happened? Where can the bug be reported, on this mailing list? https://w1.fi/ The rest could be better answered by NilsRo himself than me.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It described here in detail. openwrt/openwrt#16875 It breaks "controlled" steering also before the PR for DAWN, Usteer, ... The wifi controller software could not get the identifiers anymore to send the target AP to the STA. So the bss transition request if more or less a "I_DONT_LIKE_YOU" but without any additional information. I added the log message to inform the user about it. Sometimes it fixes on its own but sometimes the hostap daemon has to be restarted or whole AP. What do you suggest to have a better understanding of the message? As it happens from time to time and fixes itself it could be irritating so I put it to VERBOSE. But anyway if this is broken in general it is not visible without changing the logging level.... |
||
|
|
||
| if (!si->roam_transition_start) | ||
| si->roam_transition_start = current_time; | ||
| si->roam_transition_request_validity_end = current_time + 10000; | ||
| validity_period = 10000 / usteer_local_node_get_beacon_interval(ln); /* ~ 10 seconds */ | ||
| if (si->sta->aggressiveness >= 2) { | ||
| if (!si->kick_time) | ||
| si->kick_time = current_time + config.roam_kick_delay; | ||
| if (si->sta->aggressiveness >= 3) | ||
| disassoc_timer = (si->kick_time - current_time) / usteer_local_node_get_beacon_interval(ln); | ||
| else | ||
| disassoc_timer = 0; | ||
| usteer_ubus_bss_transition_request(si, 1, true, disassoc_timer, true, validity_period, candidate->node); | ||
| /* Countdown end */ | ||
| if (disassoc_timer < validity_period) { | ||
| si->roam_transition_start = 0; | ||
| usteer_roam_set_state(si, ROAM_TRIGGER_IDLE, &ev); | ||
| } | ||
| } else { | ||
| usteer_ubus_bss_transition_request(si, 1, false, 0, true, validity_period, candidate->node); | ||
| usteer_roam_set_state(si, ROAM_TRIGGER_IDLE, &ev); | ||
| } | ||
| break; | ||
| } | ||
|
|
||
|
|
@@ -385,22 +414,34 @@ bool usteer_policy_can_perform_roam(struct sta_info *si) | |
| if (si->connected != STA_CONNECTED) | ||
| return false; | ||
|
|
||
| /* Only trigger for STA with active roaming */ | ||
| if (!si->sta->aggressiveness) | ||
| return false; | ||
|
|
||
| /* Skip on pending kick */ | ||
| if (si->kick_time) | ||
| if (si->kick_time && si->kick_time <= current_time) | ||
| return false; | ||
|
|
||
| /* Skip if in validity period */ | ||
| if (current_time < si->roam_transition_request_validity_end) | ||
| return false; | ||
|
|
||
| /* Skip on rejected transition */ | ||
| if (si->bss_transition_response.status_code && current_time - si->bss_transition_response.timestamp < config.steer_reject_timeout) | ||
| return false; | ||
|
|
||
| /* Skip if transition accepted */ | ||
| if (!si->bss_transition_response.status_code && current_time - si->bss_transition_response.timestamp < config.roam_kick_delay) | ||
| return false; | ||
|
|
||
| /* Skip on previous kick attempt */ | ||
| if (current_time - si->roam_kick < config.roam_trigger_interval) | ||
| return false; | ||
|
|
||
| /* Skip if connection is established shorter than the trigger-interval */ | ||
| if (current_time - si->connected_since < config.roam_trigger_interval) | ||
| return false; | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
|
|
@@ -483,7 +524,7 @@ usteer_local_node_snr_kick(struct usteer_local_node *ln) | |
| ev.count = si->kick_count; | ||
| usteer_event(&ev); | ||
|
|
||
| usteer_ubus_kick_client(si); | ||
| usteer_ubus_kick_client(si, KICK_REASON_UNSPECIFIED); | ||
| return; | ||
| } | ||
| } | ||
|
|
@@ -567,7 +608,7 @@ usteer_local_node_load_kick(struct usteer_local_node *ln) | |
| ev.si_other = candidate; | ||
| ev.count = kick1->kick_count; | ||
|
|
||
| usteer_ubus_kick_client(kick1); | ||
| usteer_ubus_kick_client(kick1, config.load_kick_reason_code); | ||
|
|
||
| out: | ||
| usteer_event(&ev); | ||
|
|
@@ -582,7 +623,7 @@ usteer_local_node_perform_kick(struct usteer_local_node *ln) | |
| if (!si->kick_time || si->kick_time > current_time) | ||
| continue; | ||
|
|
||
| usteer_ubus_kick_client(si); | ||
| usteer_ubus_kick_client(si, KICK_REASON_BSS_TRANSITION); | ||
| } | ||
| } | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.