usteer: drop usteer_ubus_notify_client_disassoc
[project/usteer.git] / local_node.c
index b12f7fdb70f7e2629fa130507d957350e245aae4..c79fd95b68281d7255e29a38d619052324a81b40 100644 (file)
@@ -180,6 +180,11 @@ usteer_handle_bss_tm_response(struct usteer_local_node *ln, struct blob_attr *ms
        si->bss_transition_response.status_code = blobmsg_get_u8(tb[BSS_TM_RESPONSE_STATUS_CODE]);
        si->bss_transition_response.timestamp = current_time;
 
+       if (si->bss_transition_response.status_code) {
+               /* Cancel imminent kick in case BSS transition was rejected */
+               si->kick_time = 0;
+       }
+
        return 0;
 }
 
@@ -200,8 +205,6 @@ usteer_local_node_handle_beacon_report(struct usteer_local_node *ln, struct blob
                [BR_RSNI] = { .name = "rsni", .type = BLOBMSG_TYPE_INT16 },
        };
        struct blob_attr *tb[__BR_MAX];
-
-       struct usteer_beacon_report br;
        struct usteer_node *node;
        uint8_t *addr;
        struct sta *sta;
@@ -226,10 +229,47 @@ usteer_local_node_handle_beacon_report(struct usteer_local_node *ln, struct blob
        if (!node)
                return 0;
 
-       br.rcpi = (uint8_t)blobmsg_get_u16(tb[BR_RCPI]);
-       br.rsni = (uint8_t)blobmsg_get_u16(tb[BR_RSNI]);
+       usteer_measurement_report_add(sta, node,
+                                     (uint8_t)blobmsg_get_u16(tb[BR_RCPI]),
+                                     (uint8_t)blobmsg_get_u16(tb[BR_RSNI]),
+                                     current_time);
+       return 0;
+}
+
+static int
+usteer_local_node_handle_link_measurement_report(struct usteer_local_node *ln, struct blob_attr *msg)
+{
+       enum {
+               LMR_ADDRESS,
+               LMR_RCPI,
+               LMR_RSNI,
+               __LMR_MAX
+       };
+       struct blobmsg_policy policy[__LMR_MAX] = {
+               [LMR_ADDRESS] = { .name = "address", .type = BLOBMSG_TYPE_STRING },
+               [LMR_RCPI] = { .name = "rcpi", .type = BLOBMSG_TYPE_INT16 },
+               [LMR_RSNI] = { .name = "rsni", .type = BLOBMSG_TYPE_INT16 },
+       };
+       struct blob_attr *tb[__LMR_MAX];
+       uint8_t *addr;
+       struct sta *sta;
 
-       usteer_measurement_report_add_beacon_report(sta, node, &br, current_time);
+       blobmsg_parse(policy, __LMR_MAX, tb, blob_data(msg), blob_len(msg));
+       if (!tb[LMR_ADDRESS] || !tb[LMR_RCPI] || !tb[LMR_RSNI])
+               return 0;
+
+       addr = (uint8_t *) ether_aton(blobmsg_get_string(tb[LMR_ADDRESS]));
+       if (!addr)
+               return 0;
+
+       sta = usteer_sta_get(addr, false);
+       if (!sta)
+               return 0;
+
+       usteer_measurement_report_add(sta, &ln->node,
+                                     (uint8_t)blobmsg_get_u16(tb[LMR_RCPI]),
+                                     (uint8_t)blobmsg_get_u16(tb[LMR_RSNI]),
+                                     current_time);
        return 0;
 }
 
@@ -272,6 +312,8 @@ usteer_handle_event(struct ubus_context *ctx, struct ubus_object *obj,
                return usteer_handle_bss_tm_response(ln, msg);
        } else if(!strcmp(method, "beacon-report")) {
                return usteer_local_node_handle_beacon_report(ln, msg);
+       } else if(!strcmp(method, "link-measurement-report")) {
+               return usteer_local_node_handle_link_measurement_report(ln, msg);
        }
 
        for (i = 0; i < ARRAY_SIZE(event_types); i++) {
@@ -344,28 +386,43 @@ usteer_local_node_assoc_update(struct sta_info *si, struct blob_attr *data)
 }
 
 static void
-usteer_local_node_update_sta_rrm(const uint8_t *addr, struct blob_attr *client_attr)
+usteer_local_node_update_sta_rrm_wnm(struct sta_info *si, struct blob_attr *client_attr)
 {
        static const struct blobmsg_policy rrm_policy = {
                .name = "rrm",
                .type = BLOBMSG_TYPE_ARRAY,
        };
-       struct blob_attr *sta_blob = NULL;
-       struct sta *sta;
+       static const struct blobmsg_policy ext_capa_policy = {
+               .name = "extended_capabilities",
+               .type = BLOBMSG_TYPE_ARRAY,
+       };
+       struct blob_attr *rrm_blob = NULL, *wnm_blob = NULL, *cur;
+       int rem;
+       int i = 0;
 
-       if (!addr)
+       /* RRM */
+       blobmsg_parse(&rrm_policy, 1, &rrm_blob, blobmsg_data(client_attr), blobmsg_data_len(client_attr));
+       if (!rrm_blob)
                return;
 
-       /* Don't create the STA */
-       sta = usteer_sta_get(addr, false);
-       if (!sta)
-               return;
+       si->rrm = blobmsg_get_u32(blobmsg_data(rrm_blob));
 
-       blobmsg_parse(&rrm_policy, 1, &sta_blob, blobmsg_data(client_attr), blobmsg_data_len(client_attr));
-       if (!sta_blob)
+       /* Extended Capabilities / WNM */
+       blobmsg_parse(&ext_capa_policy, 1, &wnm_blob, blobmsg_data(client_attr), blobmsg_data_len(client_attr));
+       if (!wnm_blob)
                return;
 
-       sta->rrm = blobmsg_get_u32(blobmsg_data(sta_blob));
+       blobmsg_for_each_attr(cur, wnm_blob, rem) {
+               if (blobmsg_type(cur) != BLOBMSG_TYPE_INT32)
+                       return;
+               
+               if (i == 2) {
+                       if (blobmsg_get_u32(cur) & (1 << 3))
+                               si->bss_transition = true;
+               }
+
+               i++;
+       }
 }
 
 static void
@@ -408,7 +465,7 @@ usteer_local_node_set_assoc(struct usteer_local_node *ln, struct blob_attr *cl)
                }
 
                /* Read RRM information */
-               usteer_local_node_update_sta_rrm(addr, cur);
+               usteer_local_node_update_sta_rrm_wnm(si, cur);
        }
 
        node->n_assoc = n_assoc;
@@ -602,6 +659,33 @@ usteer_local_node_state_next(struct uloop_timeout *timeout)
        ubus_complete_request_async(ubus_ctx, &ln->req);
 }
 
+static void
+usteer_local_node_request_link_measurement(struct usteer_local_node *ln)
+{
+       unsigned int min_count = DIV_ROUND_UP(config.link_measurement_interval, config.local_sta_update);
+       struct usteer_node *node;
+       struct sta_info *si;
+
+       node = &ln->node;
+
+       if (ln->link_measurement_tries < min_count) {
+               ln->link_measurement_tries++;
+               return;
+       }
+       
+       ln->link_measurement_tries = 0;
+
+       if (!config.link_measurement_interval)
+               return;
+
+       list_for_each_entry(si, &node->sta_info, node_list) {
+               if (si->connected != STA_CONNECTED)
+                       continue;
+
+               usteer_ubus_trigger_link_measurement(si);
+       }
+}
+
 static void
 usteer_local_node_update(struct uloop_timeout *timeout)
 {
@@ -622,6 +706,9 @@ usteer_local_node_update(struct uloop_timeout *timeout)
        usteer_local_node_state_reset(ln);
        uloop_timeout_set(&ln->req_timer, 1);
        usteer_local_node_kick(ln);
+       usteer_band_steering_perform_steer(ln);
+       usteer_local_node_request_link_measurement(ln);
+
        uloop_timeout_set(timeout, config.local_sta_update);
 }
 
@@ -649,7 +736,7 @@ usteer_local_node_process_bss_tm_queries(struct uloop_timeout *timeout)
                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 */
@@ -762,6 +849,7 @@ usteer_register_node(struct ubus_context *ctx, const char *name, uint32_t id)
 
        blob_buf_init(&b, 0);
        blobmsg_add_u8(&b, "neighbor_report", 1);
+       blobmsg_add_u8(&b, "link_measurement", 1);
        blobmsg_add_u8(&b, "beacon_report", 1);
        blobmsg_add_u8(&b, "bss_transition", 1);
        ubus_invoke(ctx, id, "bss_mgmt_enable", b.head, NULL, NULL, 1000);