if (!si)
continue;
- usteer_ubus_bss_transition_request(si, query->dialog_token, false, false, validity_period);
+ usteer_ubus_bss_transition_request(si, query->dialog_token, false, false, validity_period, NULL);
}
/* Free pending queries we can not handle */
static struct sta_info *
find_better_candidate(struct sta_info *si_ref, struct uevent *ev, uint32_t required_criteria, uint64_t max_age)
{
- struct sta_info *si;
+ struct sta_info *si, *candidate = NULL;
struct sta *sta = si_ref->sta;
uint32_t reasons;
ev->select_reasons = reasons;
}
- return si;
+ if (candidate && si->signal > candidate->signal)
+ candidate = si;
}
- return NULL;
+ return candidate;
}
int
usteer_roam_set_state(si, ROAM_TRIGGER_IDLE, ev);
}
-static bool
+static struct sta_info *
usteer_roam_sm_found_better_node(struct sta_info *si, struct uevent *ev, enum roam_trigger_state next_state)
{
uint64_t max_age = 2 * config.roam_scan_interval;
+ struct sta_info *candidate;
if (max_age > current_time - si->roam_scan_start)
max_age = current_time - si->roam_scan_start;
- if (find_better_candidate(si, ev, (1 << UEV_SELECT_REASON_SIGNAL), max_age)) {
+ candidate = find_better_candidate(si, ev, (1 << UEV_SELECT_REASON_SIGNAL), max_age);
+ if (candidate)
usteer_roam_set_state(si, next_state, ev);
- return true;
- }
- return false;
+ return candidate;
}
static bool
usteer_roam_trigger_sm(struct usteer_local_node *ln, struct sta_info *si)
{
+ struct sta_info *candidate;
struct uevent ev = {
.si_cur = si,
};
break;
case ROAM_TRIGGER_SCAN_DONE:
- usteer_ubus_bss_transition_request(si, 1, false, false, 100);
+ 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);
+
+ usteer_ubus_bss_transition_request(si, 1, false, false, 100, candidate->node);
si->kick_time = current_time;
usteer_roam_set_state(si, ROAM_TRIGGER_IDLE, &ev);
break;
return true;
}
+static void
+usteer_ubus_disassoc_add_neighbor(struct sta_info *si, struct usteer_node *node)
+{
+ void *c;
+
+ c = blobmsg_open_array(&b, "neighbors");
+ usteer_add_nr_entry(si->node, node);
+ blobmsg_close_array(&b, c);
+}
+
static void
usteer_ubus_disassoc_add_neighbors(struct sta_info *si)
{
uint8_t dialog_token,
bool disassoc_imminent,
bool abridged,
- uint8_t validity_period)
+ uint8_t validity_period,
+ struct usteer_node *target_node)
{
struct usteer_local_node *ln = container_of(si->node, struct usteer_local_node, node);
blobmsg_add_u8(&b, "disassociation_imminent", disassoc_imminent);
blobmsg_add_u8(&b, "abridged", abridged);
blobmsg_add_u32(&b, "validity_period", validity_period);
- usteer_ubus_disassoc_add_neighbors(si);
+ if (!target_node) {
+ usteer_ubus_disassoc_add_neighbors(si);
+ } else {
+ usteer_ubus_disassoc_add_neighbor(si, target_node);
+ }
return ubus_invoke(ubus_ctx, ln->obj_id, "bss_transition_request", b.head, NULL, 0, 100);
}
uint8_t dialog_token,
bool disassoc_imminent,
bool abridged,
- uint8_t validity_period);
+ uint8_t validity_period,
+ struct usteer_node *target_node);
struct sta *usteer_sta_get(const uint8_t *addr, bool create);
struct sta_info *usteer_sta_info_get(struct sta *sta, struct usteer_node *node, bool *create);