[usteer] New aggressive roaming to support Intel Wifi Cards (and also, other devices)

Paul Oranje phoranje at gmail.com
Sun Oct 20 01:43:10 PDT 2024


Please keep white space and indent changes in a separate commit.
Regards,
Paul

> Op 19 okt 2024, om 21:24 heeft Nils Rottgardt <n.rottgardt at gmail.com> het volgende geschreven:
> 
> From c43d6699e3a618a3269f3b299ee7673eb8f44099 Mon Sep 17 00:00:00 2001
> From: Nils Hendrik Rottgardt <n.rottgardt at gmail.com>
> Date: Sat, 19 Oct 2024 21:20:36 +0200
> Subject: [usteer] New aggressive roaming to support Intel Wifi Cards
> (and also
>    other devices)
> 
> Intel Wifi Cards does not understand the actual implementation because
> of missing disassociation_timer and disassociation_imminent = true. So
> they and other devices send a BSS-TM-RESP with status=1 (error).
> This patch with add some new options to correct this behavior and also
> fix the wrong bss_transition_request call.
> 
> - Added aggressive roaming (disaccociation_timer) and corrected calling
> bss_transition_request with disassociation_imminent = false.
> - Added 3 new options in config to control aggressive roaming for all or
> specific MAC addresses.
> 
> Signed-off-by: Nils Hendrik Rottgardt <n.rottgardt at gmail.com>
> ---
>  band_steering.c                        | 11 ++++-
>  local_node.c                           | 21 +++++++--
>  main.c                                 |  2 +
>  openwrt/usteer/files/etc/config/usteer |  9 ++++
>  openwrt/usteer/files/etc/init.d/usteer |  4 +-
>  policy.c                               | 20 +++++++--
>  sta.c                                  | 26 +++++++++++
>  ubus.c                                 | 61 +++++++++++++++++++-------
>  usteer.h                               | 30 ++++++++++---
>  9 files changed, 152 insertions(+), 32 deletions(-)
> 
> diff --git a/band_steering.c b/band_steering.c
> index 7fce1df..7b2ee00 100644
> --- a/band_steering.c
> +++ b/band_steering.c
> @@ -86,13 +86,20 @@ void usteer_band_steering_perform_steer(struct
> usteer_local_node *ln)
>              continue;
>  
>          /* Skip clients with insufficient SNR-state */
> -        if (si->band_steering.below_snr) {
> +        if (si->band_steering.below_snr)
> +        {
>              si->band_steering.below_snr = false;
>              continue;
>          }
>  
>          if (si->bss_transition)
> -            usteer_ubus_band_steering_request(si);
> +        {
> +            // usteer_ubus_band_steering_request(si, 0, false, 100,
> true, 100);
> +            if (si->sta->aggressive)
> +                usteer_ubus_band_steering_request(si, 0, true,
> config.aggressive_disassoc_timer, true, config.aggressive_disassoc_timer);
> +            else
> +                usteer_ubus_band_steering_request(si, 0, false, 0,
> true, 100);
> +        }
>  
>          si->band_steering.below_snr = false;
>      }
> diff --git a/local_node.c b/local_node.c
> index e74d945..6aa7008 100644
> --- a/local_node.c
> +++ b/local_node.c
> @@ -748,7 +748,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, NULL);
> +        usteer_ubus_bss_transition_request(si, query->dialog_token,
> config.aggressive_all, validity_period, true, validity_period, NULL);
>      }
>  
>      /* Free pending queries we can not handle */
> @@ -977,8 +977,23 @@ void config_get_ssid_list(struct blob_buf *buf)
>          blobmsg_add_blob(buf, config.ssid_list);
>  }
>  
> -void
> -usteer_local_nodes_init(struct ubus_context *ctx)
> +void config_set_aggressive_mac_list(struct blob_attr *data)
> +{
> +    free(config.aggressive_mac_list);
> +
> +    if (data && blobmsg_len(data))
> +        config.aggressive_mac_list = blob_memdup(data);
> +    else
> +        config.aggressive_mac_list = NULL;
> +}
> +
> +void config_get_aggressive_mac_list(struct blob_buf *buf)
> +{
> +    if (config.aggressive_mac_list)
> +        blobmsg_add_blob(buf, config.aggressive_mac_list);
> +}
> +
> +void usteer_local_nodes_init(struct ubus_context *ctx)
>  {
>      usteer_register_events(ctx);
>      ubus_lookup(ctx, "hostapd.*", node_list_cb, NULL);
> diff --git a/main.c b/main.c
> index 99aa6ad..b07b624 100644
> --- a/main.c
> +++ b/main.c
> @@ -96,6 +96,8 @@ void usteer_init_defaults(void)
>      config.remote_update_interval = 1000;
>      config.initial_connect_delay = 0;
>      config.remote_node_timeout = 10;
> +    config.aggressive_all = false;
> +    config.aggressive_disassoc_timer = 100;
>  
>      config.steer_reject_timeout = 60000;
>  
> diff --git a/openwrt/usteer/files/etc/config/usteer
> b/openwrt/usteer/files/etc/config/usteer
> index f53c338..2fe47f3 100644
> --- a/openwrt/usteer/files/etc/config/usteer
> +++ b/openwrt/usteer/files/etc/config/usteer
> @@ -71,6 +71,15 @@ config usteer
>      # Timeout (ms) for which a client will not be steered after
> rejecting a BSS-transition-request
>      #option steer_reject_timeout 60000
>  
> +    # Use aggressvice roaming to push clients to another AP
> +    #option aggressive_all 0
> +
> +    # List of MACs to enable aggressive roaming on. If not set all macs
> will handled aggressive
> +    #list aggressive_mac_list ''
> +
> +    # Disassociation imminent tuner - in aggresive mode the time a
> client has to roam away before disconnected hardly
> +    #option aggressive_disassoc_timer 100
> +
>      # Timeout (in ms) after which a association following a
> disassociation is not seen
>      # as a roam
>      #option roam_process_timeout 5000
> diff --git a/openwrt/usteer/files/etc/init.d/usteer
> b/openwrt/usteer/files/etc/init.d/usteer
> index 07fd99e..fdc8211 100755
> --- a/openwrt/usteer/files/etc/init.d/usteer
> +++ b/openwrt/usteer/files/etc/init.d/usteer
> @@ -69,8 +69,10 @@ uci_usteer() {
>      uci_option_to_json_bool "$cfg" local_mode
>      uci_option_to_json_bool "$cfg" load_kick_enabled
>      uci_option_to_json_bool "$cfg" assoc_steering
> +    uci_option_to_json_bool "$cfg" aggressive_all
>      uci_option_to_json_string "$cfg" node_up_script
>      uci_option_to_json_string_array "$cfg" ssid_list
> +    uci_option_to_json_string_array "$cfg" aggressive_mac_list
>      uci_option_to_json_string_array "$cfg" event_log_types
>  
>      for opt in \
> @@ -84,7 +86,7 @@ uci_usteer() {
>          initial_connect_delay steer_reject_timeout roam_process_timeout\
>          roam_kick_delay roam_scan_tries roam_scan_timeout \
>          roam_scan_snr roam_scan_interval \
> -        roam_trigger_snr roam_trigger_interval \
> +        roam_trigger_snr roam_trigger_interval aggressive_disassoc_timer\
>          band_steering_interval band_steering_min_snr
> link_measurement_interval \
>          load_kick_threshold load_kick_delay load_kick_min_clients \
>          load_kick_reason_code
> diff --git a/policy.c b/policy.c
> index 8c5d244..856c03e 100644
> --- a/policy.c
> +++ b/policy.c
> @@ -370,8 +370,18 @@ usteer_roam_trigger_sm(struct usteer_local_node
> *ln, struct sta_info *si)
>              break;
>          }
>  
> -        usteer_ubus_bss_transition_request(si, 1, false, false, 100,
> candidate->node);
> -        si->kick_time = current_time + config.roam_kick_delay;
> +        if (si->sta->aggressive)
> +        {
> +            // TODO: Disaccociation Timer noch konfigurierbar machen
> +            usteer_ubus_bss_transition_request(si, 1, true,
> config.aggressive_disassoc_timer, true,
> config.aggressive_disassoc_timer, candidate->node);
> +            si->roam_disassoc_time = current_time + (100 * 100);
> +        }
> +        else
> +        {
> +            usteer_ubus_bss_transition_request(si, 1, false, 0, true,
> 100, candidate->node);
> +            si->kick_time = current_time + config.roam_kick_delay;
> +        }
> +
>          usteer_roam_set_state(si, ROAM_TRIGGER_IDLE, &ev);
>          break;
>      }
> @@ -400,7 +410,11 @@ bool usteer_policy_can_perform_roam(struct sta_info
> *si)
>      /* Skip if connection is established shorter than the
> trigger-interval */
>      if (current_time - si->connected_since < config.roam_trigger_interval)
>          return false;
> -    
> +
> +    /* Skip on aggressive roaming in progress - wait 10s after
> disassociation event*/
> +    if (current_time - si->roam_disassoc_time < 10000)
> +        return false;
> +
>      return true;
>  }
>  
> diff --git a/sta.c b/sta.c
> index ed7e40e..ee8cbb1 100644
> --- a/sta.c
> +++ b/sta.c
> @@ -76,6 +76,30 @@ usteer_sta_info_timeout(struct usteer_timeout_queue
> *q, struct usteer_timeout *t
>      usteer_sta_info_del(si);
>  }
>  
> +static void
> +usteer_sta_update_aggressive(struct sta *sta)
> +{
> +    struct blob_attr *cur;
> +    int rem;
> +    char sta_mac[18];
> +    sprintf(sta_mac, MAC_ADDR_FMT, MAC_ADDR_DATA(sta->addr));
> +
> +    if (config.aggressive_all)
> +        sta->aggressive = true;
> +    else
> +    {
> +        sta->aggressive = false;
> +        blobmsg_for_each_attr(cur, config.aggressive_mac_list, rem)
> +        {
> +            if (strcmp(blobmsg_get_string(cur), sta_mac) != 0)
> +                continue;
> +
> +            sta->aggressive = true;
> +            break;
> +        }
> +    }
> +}
> +
>  struct sta_info *
>  usteer_sta_info_get(struct sta *sta, struct usteer_node *node, bool
> *create)
>  {
> @@ -105,6 +129,8 @@ usteer_sta_info_get(struct sta *sta, struct
> usteer_node *node, bool *create)
>      si->created = current_time;
>      *create = true;
>  
> +    usteer_sta_update_aggressive(sta);
> +
>      /* Node is by default not connected. */
>      usteer_sta_disconnected(si);
>  
> diff --git a/ubus.c b/ubus.c
> index 40daf74..918255c 100644
> --- a/ubus.c
> +++ b/ubus.c
> @@ -162,6 +162,9 @@ struct cfg_item {
>      _cfg(U32, remote_update_interval), \
>      _cfg(U32, remote_node_timeout), \
>      _cfg(BOOL, assoc_steering), \
> +    _cfg(BOOL, aggressive_all), \
> +    _cfg(ARRAY_CB, aggressive_mac_list), \
> +    _cfg(U32, aggressive_disassoc_timer), \
>      _cfg(I32, min_connect_snr), \
>      _cfg(I32, min_snr), \
>      _cfg(U32, min_snr_kick_delay), \
> @@ -668,11 +671,12 @@ usteer_ubus_disassoc_add_neighbors(struct sta_info
> *si)
>  }
>  
>  int usteer_ubus_bss_transition_request(struct sta_info *si,
> -                       uint8_t dialog_token,
> -                       bool disassoc_imminent,
> -                       bool abridged,
> -                       uint8_t validity_period,
> -                       struct usteer_node *target_node)
> +                                       uint8_t dialog_token,
> +                                       bool disassoc_imminent,
> +                                       uint8_t disassoc_timer,
> +                                       bool abridged,
> +                                       uint8_t validity_period,
> +                                       struct usteer_node *target_node)
>  {
>      struct usteer_local_node *ln = container_of(si->node, struct
> usteer_local_node, node);
>  
> @@ -680,17 +684,32 @@ int usteer_ubus_bss_transition_request(struct
> sta_info *si,
>      blobmsg_printf(&b, "addr", MAC_ADDR_FMT, MAC_ADDR_DATA(si->sta->addr));
>      blobmsg_add_u32(&b, "dialog_token", dialog_token);
>      blobmsg_add_u8(&b, "disassociation_imminent", disassoc_imminent);
> +    if (disassoc_imminent)
> +    {
> +        blobmsg_add_u32(&b, "disassociation_timer", disassoc_timer);
> +    }
>      blobmsg_add_u8(&b, "abridged", abridged);
>      blobmsg_add_u32(&b, "validity_period", validity_period);
> -    if (!target_node) {
> +    if (!target_node)
> +    {
> +        // Add all known neighbors if no specific target set
> +        MSG(DEBUG, "ROAMING requested for sta=" MAC_ADDR_FMT " without
> target\n", MAC_ADDR_DATA(si->sta->addr));
>          usteer_ubus_disassoc_add_neighbors(si);
> -    } else {
> +    }
> +    else
> +    {
> +        MSG(DEBUG, "ROAMING requested for sta=" MAC_ADDR_FMT " to %s
> with disassociation timer %i\n", MAC_ADDR_DATA(si->sta->addr),
> usteer_node_name(target_node), disassoc_timer);
>          usteer_ubus_disassoc_add_neighbor(si, target_node);
>      }
>      return ubus_invoke(ubus_ctx, ln->obj_id, "bss_transition_request",
> b.head, NULL, 0, 100);
>  }
>  
> -int usteer_ubus_band_steering_request(struct sta_info *si)
> +int usteer_ubus_band_steering_request(struct sta_info *si,
> +                                      uint8_t dialog_token,
> +                                      bool disassoc_imminent,
> +                                      uint8_t disassoc_timer,
> +                                      bool abridged,
> +                                      uint8_t validity_period)
>  {
>      struct usteer_local_node *ln = container_of(si->node, struct
> usteer_local_node, node);
>      struct usteer_node *node;
> @@ -698,21 +717,31 @@ int usteer_ubus_band_steering_request(struct
> sta_info *si)
>  
>      blob_buf_init(&b, 0);
>      blobmsg_printf(&b, "addr", MAC_ADDR_FMT, MAC_ADDR_DATA(si->sta->addr));
> -    blobmsg_add_u32(&b, "dialog_token", 0);
> -    blobmsg_add_u8(&b, "disassociation_imminent", false);
> -    blobmsg_add_u8(&b, "abridged", false);
> -    blobmsg_add_u32(&b, "validity_period", 100);
> +    blobmsg_add_u32(&b, "dialog_token", dialog_token);
> +    blobmsg_add_u8(&b, "disassociation_imminent", disassoc_imminent);
> +    if (disassoc_imminent)
> +    {
> +        blobmsg_add_u32(&b, "disassociation_timer", disassoc_timer);
> +    }
> +    blobmsg_add_u8(&b, "abridged", abridged);
> +    blobmsg_add_u32(&b, "validity_period", validity_period);
>  
>      c = blobmsg_open_array(&b, "neighbors");
> -    for_each_local_node(node) {
> +    for_each_local_node(node)
> +    {
>          if (!usteer_band_steering_is_target(ln, node))
>              continue;
> -    
> +        // TODO: Funktioniert nicht, Targets werden nicht korrekt
> ausgewiesen.
>          usteer_add_nr_entry(si->node, node);
>      }
>      blobmsg_close_array(&b, c);
> -
> -    return ubus_invoke(ubus_ctx, ln->obj_id, "bss_transition_request",
> b.head, NULL, 0, 100);
> +    if (sizeof(si->node) > 0)
> +    {
> +        MSG(DEBUG, "BAND STEERING requested for sta=" MAC_ADDR_FMT "
> with disassociation timer %i\n", MAC_ADDR_DATA(si->sta->addr),
> disassoc_timer);
> +        return ubus_invoke(ubus_ctx, ln->obj_id,
> "bss_transition_request", b.head, NULL, 0, 100);
> +    }
> +    else
> +        MSG(DEBUG, "BAND STEERING no targets found for sta="
> MAC_ADDR_FMT "\n", MAC_ADDR_DATA(si->sta->addr));
>  }
>  
>  int usteer_ubus_trigger_link_measurement(struct sta_info *si)
> diff --git a/usteer.h b/usteer.h
> index f692fb8..7a5739c 100644
> --- a/usteer.h
> +++ b/usteer.h
> @@ -170,6 +170,10 @@ struct usteer_config {
>      uint32_t remote_update_interval;
>      uint32_t remote_node_timeout;
>  
> +    bool aggressive_all;
> +    struct blob_attr *aggressive_mac_list;
> +    uint32_t aggressive_disassoc_timer;
> +
>      int32_t min_snr;
>      uint32_t min_snr_kick_delay;
>      int32_t min_connect_snr;
> @@ -190,7 +194,7 @@ struct usteer_config {
>      uint32_t roam_kick_delay;
>  
>      uint32_t band_steering_interval;
> -    int32_t band_steering_min_snr;
> +    int32_t band_steering_min_snr;
>  
>      uint32_t link_measurement_interval;
>  
> @@ -255,6 +259,7 @@ struct sta_info {
>      uint8_t roam_tries;
>      uint64_t roam_event;
>      uint64_t roam_kick;
> +    uint64_t roam_disassoc_time;
>      uint64_t roam_scan_start;
>      uint64_t roam_scan_timeout_start;
>  
> @@ -285,6 +290,8 @@ struct sta {
>      uint8_t seen_2ghz : 1;
>      uint8_t seen_5ghz : 1;
>  
> +    bool aggressive;
> +
>      uint8_t addr[6];
>  };
>  
> @@ -336,13 +343,19 @@ bool usteer_band_steering_is_target(struct
> usteer_local_node *ln, struct usteer_
>  void usteer_ubus_init(struct ubus_context *ctx);
>  void usteer_ubus_kick_client(struct sta_info *si);
>  int usteer_ubus_trigger_client_scan(struct sta_info *si);
> -int usteer_ubus_band_steering_request(struct sta_info *si);
> +int usteer_ubus_band_steering_request(struct sta_info *si,
> +                                      uint8_t dialog_token,
> +                                      bool disassoc_imminent,
> +                                      uint8_t disassoc_timer,
> +                                      bool abridged,
> +                                      uint8_t validity_period);
>  int usteer_ubus_bss_transition_request(struct sta_info *si,
> -                       uint8_t dialog_token,
> -                       bool disassoc_imminent,
> -                       bool abridged,
> -                       uint8_t validity_period,
> -                       struct usteer_node *target_node);
> +                                       uint8_t dialog_token,
> +                                       bool disassoc_imminent,
> +                                       uint8_t disassoc_timer,
> +                                       bool abridged,
> +                                       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);
> @@ -376,6 +389,9 @@ void config_get_node_up_script(struct blob_buf *buf);
>  void config_set_ssid_list(struct blob_attr *data);
>  void config_get_ssid_list(struct blob_buf *buf);
>  
> +void config_set_aggressive_mac_list(struct blob_attr *data);
> +void config_get_aggressive_mac_list(struct blob_buf *buf);
> +
>  int usteer_interface_init(void);
>  void usteer_interface_add(const char *name);
>  void usteer_sta_node_cleanup(struct usteer_node *node);
> -- 
> 2.39.5
> 
> 
> 
> _______________________________________________
> openwrt-devel mailing list
> openwrt-devel at lists.openwrt.org
> https://lists.openwrt.org/mailman/listinfo/openwrt-devel




More information about the openwrt-devel mailing list