hostapd: make it possible to update station airtime weights via ubus
authorFelix Fietkau <nbd@nbd.name>
Tue, 6 Jul 2021 12:11:33 +0000 (14:11 +0200)
committerFelix Fietkau <nbd@nbd.name>
Mon, 12 Jul 2021 11:31:40 +0000 (13:31 +0200)
This allows dynamic tuning based on other runtime information

Signed-off-by: Felix Fietkau <nbd@nbd.name>
package/network/services/hostapd/patches/600-ubus_support.patch
package/network/services/hostapd/src/src/ap/ubus.c

index 71537c9ec6f53c8fc77c3765007400b92eb58de5..005ed54e0c7f78bb644fa43f780a3e0bee301044 100644 (file)
        /* Proceed only if DFS is not offloaded to the driver */
        if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)
                return 0;
+--- a/src/ap/airtime_policy.c
++++ b/src/ap/airtime_policy.c
+@@ -112,8 +112,14 @@ static void set_sta_weights(struct hosta
+ {
+       struct sta_info *sta;
+-      for (sta = hapd->sta_list; sta; sta = sta->next)
+-              sta_set_airtime_weight(hapd, sta, weight);
++      for (sta = hapd->sta_list; sta; sta = sta->next) {
++              unsigned int sta_weight = weight;
++
++              if (sta->dyn_airtime_weight)
++                      sta_weight = (weight * sta->dyn_airtime_weight) / 256;
++
++              sta_set_airtime_weight(hapd, sta, sta_weight);
++      }
+ }
+@@ -244,7 +250,10 @@ int airtime_policy_new_sta(struct hostap
+       unsigned int weight;
+       if (hapd->iconf->airtime_mode == AIRTIME_MODE_STATIC) {
+-              weight = get_weight_for_sta(hapd, sta->addr);
++              if (sta->dyn_airtime_weight)
++                      weight = sta->dyn_airtime_weight;
++              else
++                      weight = get_weight_for_sta(hapd, sta->addr);
+               if (weight)
+                       return sta_set_airtime_weight(hapd, sta, weight);
+       }
+--- a/src/ap/sta_info.h
++++ b/src/ap/sta_info.h
+@@ -324,6 +324,7 @@ struct sta_info {
+ #endif /* CONFIG_TESTING_OPTIONS */
+ #ifdef CONFIG_AIRTIME_POLICY
+       unsigned int airtime_weight;
++      unsigned int dyn_airtime_weight;
+       struct os_reltime backlogged_until;
+ #endif /* CONFIG_AIRTIME_POLICY */
index 6201dfd52405eccde26726dc461cf99c1445efff..85fd6f1cc77e5cc8dc961712f526df2ffb3bd5bd 100644 (file)
@@ -21,6 +21,7 @@
 #include "rrm.h"
 #include "wnm_ap.h"
 #include "taxonomy.h"
+#include "airtime_policy.h"
 
 static struct ubus_context *ctx;
 static struct blob_buf b;
@@ -1326,11 +1327,68 @@ hostapd_wnm_disassoc_imminent(struct ubus_context *ctx, struct ubus_object *obj,
 }
 #endif
 
+#ifdef CONFIG_AIRTIME_POLICY
+enum {
+       UPDATE_AIRTIME_STA,
+       UPDATE_AIRTIME_WEIGHT,
+       __UPDATE_AIRTIME_MAX,
+};
+
+
+static const struct blobmsg_policy airtime_policy[__UPDATE_AIRTIME_MAX] = {
+       [UPDATE_AIRTIME_STA] = { "sta", BLOBMSG_TYPE_STRING },
+       [UPDATE_AIRTIME_WEIGHT] = { "weight", BLOBMSG_TYPE_INT32 },
+};
+
+static int
+hostapd_bss_update_airtime(struct ubus_context *ctx, struct ubus_object *obj,
+                          struct ubus_request_data *ureq, const char *method,
+                          struct blob_attr *msg)
+{
+       struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
+       struct blob_attr *tb[__UPDATE_AIRTIME_MAX];
+       struct sta_info *sta = NULL;
+       u8 addr[ETH_ALEN];
+       int weight;
+
+       blobmsg_parse(airtime_policy, __UPDATE_AIRTIME_MAX, tb, blob_data(msg), blob_len(msg));
+
+       if (!tb[UPDATE_AIRTIME_WEIGHT])
+               return UBUS_STATUS_INVALID_ARGUMENT;
+
+       weight = blobmsg_get_u32(tb[UPDATE_AIRTIME_WEIGHT]);
+
+       if (!tb[UPDATE_AIRTIME_STA]) {
+               if (!weight)
+                       return UBUS_STATUS_INVALID_ARGUMENT;
+
+               hapd->conf->airtime_weight = weight;
+               return 0;
+       }
+
+       if (hwaddr_aton(blobmsg_data(tb[UPDATE_AIRTIME_STA]), addr))
+               return UBUS_STATUS_INVALID_ARGUMENT;
+
+       sta = ap_get_sta(hapd, addr);
+       if (!sta)
+               return UBUS_STATUS_NOT_FOUND;
+
+       sta->dyn_airtime_weight = weight;
+       airtime_policy_new_sta(hapd, sta);
+
+       return 0;
+}
+#endif
+
+
 static const struct ubus_method bss_methods[] = {
        UBUS_METHOD_NOARG("reload", hostapd_bss_reload),
        UBUS_METHOD_NOARG("get_clients", hostapd_bss_get_clients),
        UBUS_METHOD_NOARG("get_status", hostapd_bss_get_status),
        UBUS_METHOD("del_client", hostapd_bss_del_client, del_policy),
+#ifdef CONFIG_AIRTIME_POLICY
+       UBUS_METHOD("update_airtime", hostapd_bss_update_airtime, airtime_policy),
+#endif
        UBUS_METHOD_NOARG("list_bans", hostapd_bss_list_bans),
 #ifdef CONFIG_WPS
        UBUS_METHOD_NOARG("wps_start", hostapd_bss_wps_start),