hostapd: add support for specifying the maxassoc parameter as a device option
authorFelix Fietkau <nbd@nbd.name>
Wed, 26 May 2021 12:34:46 +0000 (14:34 +0200)
committerFelix Fietkau <nbd@nbd.name>
Wed, 2 Jun 2021 07:33:12 +0000 (09:33 +0200)
It allows enforcing a limit on associated stations to be enforced for the
full device, e.g. in order to deal with hardware/driver limitations

Signed-off-by: Felix Fietkau <nbd@nbd.name>
package/network/services/hostapd/files/hostapd.sh
package/network/services/hostapd/patches/720-iface_max_num_sta.patch [new file with mode: 0644]

index 8d12683a394d831826d6a17aff994f62200c7f7c..9993bc90479988a5e6017e1f8d5c647f63b8c139 100644 (file)
@@ -103,6 +103,7 @@ hostapd_common_add_device_config() {
        config_add_int rts_threshold
        config_add_int rssi_reject_assoc_rssi
        config_add_int rssi_ignore_probe_request
+       config_add_int maxassoc
 
        config_add_string acs_chan_bias
        config_add_array hostapd_options
@@ -120,7 +121,7 @@ hostapd_prepare_device_config() {
 
        json_get_vars country country_ie beacon_int:100 dtim_period:2 doth require_mode legacy_rates \
                acs_chan_bias local_pwr_constraint spectrum_mgmt_required airtime_mode cell_density \
-               rts_threshold beacon_rate rssi_reject_assoc_rssi rssi_ignore_probe_request
+               rts_threshold beacon_rate rssi_reject_assoc_rssi rssi_ignore_probe_request maxassoc
 
        hostapd_set_log_options base_cfg
 
@@ -220,6 +221,7 @@ hostapd_prepare_device_config() {
        [ -n "$rts_threshold" ] && append base_cfg "rts_threshold=$rts_threshold" "$N"
        append base_cfg "dtim_period=$dtim_period" "$N"
        [ "$airtime_mode" -gt 0 ] && append base_cfg "airtime_mode=$airtime_mode" "$N"
+       [ -n "$maxassoc" ] && append base_cfg "iface_max_num_sta=$maxassoc" "$N"
 
        json_get_values opts hostapd_options
        for val in $opts; do
diff --git a/package/network/services/hostapd/patches/720-iface_max_num_sta.patch b/package/network/services/hostapd/patches/720-iface_max_num_sta.patch
new file mode 100644 (file)
index 0000000..b93a0bc
--- /dev/null
@@ -0,0 +1,82 @@
+--- a/hostapd/config_file.c
++++ b/hostapd/config_file.c
+@@ -2873,6 +2873,14 @@ static int hostapd_config_fill(struct ho
+                                  line, bss->max_num_sta, MAX_STA_COUNT);
+                       return 1;
+               }
++      } else if (os_strcmp(buf, "iface_max_num_sta") == 0) {
++              conf->max_num_sta = atoi(pos);
++              if (conf->max_num_sta < 0 ||
++                  conf->max_num_sta > MAX_STA_COUNT) {
++                      wpa_printf(MSG_ERROR, "Line %d: Invalid max_num_sta=%d; allowed range 0..%d",
++                                 line, conf->max_num_sta, MAX_STA_COUNT);
++                      return 1;
++              }
+       } else if (os_strcmp(buf, "wpa") == 0) {
+               bss->wpa = atoi(pos);
+       } else if (os_strcmp(buf, "extended_key_id") == 0) {
+--- a/src/ap/hostapd.h
++++ b/src/ap/hostapd.h
+@@ -648,6 +648,7 @@ void hostapd_cleanup_cs_params(struct ho
+ void hostapd_periodic_iface(struct hostapd_iface *iface);
+ int hostapd_owe_trans_get_info(struct hostapd_data *hapd);
+ void hostapd_ocv_check_csa_sa_query(void *eloop_ctx, void *timeout_ctx);
++int hostapd_check_max_sta(struct hostapd_data *hapd);
+ /* utils.c */
+ int hostapd_register_probereq_cb(struct hostapd_data *hapd,
+--- a/src/ap/hostapd.c
++++ b/src/ap/hostapd.c
+@@ -236,6 +236,30 @@ static int hostapd_iface_conf_changed(st
+ }
++static inline int hostapd_iface_num_sta(struct hostapd_iface *iface)
++{
++      int num_sta = 0;
++      int i;
++
++      for (i = 0; i < iface->num_bss; i++)
++              num_sta += iface->bss[i]->num_sta;
++
++      return num_sta;
++}
++
++
++int hostapd_check_max_sta(struct hostapd_data *hapd)
++{
++      if (hapd->num_sta >= hapd->conf->max_num_sta)
++              return 1;
++
++      if (hapd->iconf->max_num_sta &&
++          hostapd_iface_num_sta(hapd->iface) >= hapd->iconf->max_num_sta)
++              return 1;
++
++      return 0;
++}
++
+ int hostapd_reload_config(struct hostapd_iface *iface, int reconf)
+ {
+       struct hapd_interfaces *interfaces = iface->interfaces;
+--- a/src/ap/beacon.c
++++ b/src/ap/beacon.c
+@@ -1039,7 +1039,7 @@ void handle_probe_req(struct hostapd_dat
+       if (hapd->conf->no_probe_resp_if_max_sta &&
+           is_multicast_ether_addr(mgmt->da) &&
+           is_multicast_ether_addr(mgmt->bssid) &&
+-          hapd->num_sta >= hapd->conf->max_num_sta &&
++          hostapd_check_max_sta(hapd) &&
+           !ap_get_sta(hapd, mgmt->sa)) {
+               wpa_printf(MSG_MSGDUMP, "%s: Ignore Probe Request from " MACSTR
+                          " since no room for additional STA",
+--- a/src/ap/ap_config.h
++++ b/src/ap/ap_config.h
+@@ -976,6 +976,8 @@ struct hostapd_config {
+       unsigned int track_sta_max_num;
+       unsigned int track_sta_max_age;
++      int max_num_sta;
++
+       char country[3]; /* first two octets: country code as described in
+                         * ISO/IEC 3166-1. Third octet:
+                         * ' ' (ascii 32): all environments