[PATCH] hostapd: ubus: add BSS transtiton request method
Andre Valentin
avalentin at marcant.net
Mon Oct 11 13:33:01 PDT 2021
Hi!
I tried this patch and at works as expected. Thank you very much!
André
Am 07.10.21 um 00:27 schrieb David Bauer:
> The existing wnm_disassoc_imminent ubus method only supports issuing a
> bss transition request with the disassoc imminent flag set.
> For use-cases, where the client is requested to roam to another BSS
> without a pending disassoc, this existing method is not suitable.
>
> Add a new bss_transition_request ubus method, which provides a more
> universal way to dispatch a transition request. It takes the following
> arguments:
>
> Required:
> addr: String - MAC-address of the STA to send the request to (colon-seperated)
>
> Optional:
> abridged - Bool - Indicates if the abridged flag is set
> disassociation_imminent: Bool - Whether or not the disassoc_imminent
> flag is set
> disassociation_timer: I32 - number of TBTTs after which the client will
> be disassociated
> validity_period: I32 - number of TBTTs after which the beacon
> candidate list (if included) will be invalid
> neighbors: blob-array - Array of strings containing neighbor reports as
> hex-string
>
> Signed-off-by: David Bauer <mail at david-bauer.net>
> ---
> .../services/hostapd/src/src/ap/ubus.c | 152 +++++++++++++-----
> 1 file changed, 112 insertions(+), 40 deletions(-)
>
> diff --git a/package/network/services/hostapd/src/src/ap/ubus.c b/package/network/services/hostapd/src/src/ap/ubus.c
> index 367e1b652b..1b5c60416f 100644
> --- a/package/network/services/hostapd/src/src/ap/ubus.c
> +++ b/package/network/services/hostapd/src/src/ap/ubus.c
> @@ -1275,60 +1275,30 @@ hostapd_rrm_beacon_req(struct ubus_context *ctx, struct ubus_object *obj,
>
>
> #ifdef CONFIG_WNM_AP
> -enum {
> - WNM_DISASSOC_ADDR,
> - WNM_DISASSOC_DURATION,
> - WNM_DISASSOC_NEIGHBORS,
> - WNM_DISASSOC_ABRIDGED,
> - __WNM_DISASSOC_MAX,
> -};
> -
> -static const struct blobmsg_policy wnm_disassoc_policy[__WNM_DISASSOC_MAX] = {
> - [WNM_DISASSOC_ADDR] = { "addr", BLOBMSG_TYPE_STRING },
> - [WNM_DISASSOC_DURATION] { "duration", BLOBMSG_TYPE_INT32 },
> - [WNM_DISASSOC_NEIGHBORS] { "neighbors", BLOBMSG_TYPE_ARRAY },
> - [WNM_DISASSOC_ABRIDGED] { "abridged", BLOBMSG_TYPE_BOOL },
> -};
>
> static int
> -hostapd_wnm_disassoc_imminent(struct ubus_context *ctx, struct ubus_object *obj,
> - struct ubus_request_data *ureq, const char *method,
> - struct blob_attr *msg)
> +hostapd_bss_tr_send(struct hostapd_data *hapd, u8 *addr, bool disassoc_imminent, bool abridged,
> + u16 disassoc_timer, u8 validity_period, struct blob_attr *neighbors)
> {
> - struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
> - struct blob_attr *tb[__WNM_DISASSOC_MAX];
> struct blob_attr *cur;
> struct sta_info *sta;
> - int duration = 10;
> - int rem;
> int nr_len = 0;
> + int rem;
> u8 *nr = NULL;
> - u8 req_mode = WNM_BSS_TM_REQ_DISASSOC_IMMINENT;
> - u8 addr[ETH_ALEN];
> -
> - blobmsg_parse(wnm_disassoc_policy, __WNM_DISASSOC_MAX, tb, blob_data(msg), blob_len(msg));
> -
> - if (!tb[WNM_DISASSOC_ADDR])
> - return UBUS_STATUS_INVALID_ARGUMENT;
> -
> - if (hwaddr_aton(blobmsg_data(tb[WNM_DISASSOC_ADDR]), addr))
> - return UBUS_STATUS_INVALID_ARGUMENT;
> -
> - if ((cur = tb[WNM_DISASSOC_DURATION]) != NULL)
> - duration = blobmsg_get_u32(cur);
> + u8 req_mode = 0;
>
> sta = ap_get_sta(hapd, addr);
> if (!sta)
> return UBUS_STATUS_NOT_FOUND;
>
> - if (tb[WNM_DISASSOC_NEIGHBORS]) {
> + if (neighbors) {
> u8 *nr_cur;
>
> - if (blobmsg_check_array(tb[WNM_DISASSOC_NEIGHBORS],
> + if (blobmsg_check_array(neighbors,
> BLOBMSG_TYPE_STRING) < 0)
> return UBUS_STATUS_INVALID_ARGUMENT;
>
> - blobmsg_for_each_attr(cur, tb[WNM_DISASSOC_NEIGHBORS], rem) {
> + blobmsg_for_each_attr(cur, neighbors, rem) {
> int len = strlen(blobmsg_get_string(cur));
>
> if (len % 2)
> @@ -1344,7 +1314,7 @@ hostapd_wnm_disassoc_imminent(struct ubus_context *ctx, struct ubus_object *obj,
> }
>
> nr_cur = nr;
> - blobmsg_for_each_attr(cur, tb[WNM_DISASSOC_NEIGHBORS], rem) {
> + blobmsg_for_each_attr(cur, neighbors, rem) {
> int len = strlen(blobmsg_get_string(cur)) / 2;
>
> *nr_cur++ = WLAN_EID_NEIGHBOR_REPORT;
> @@ -1361,15 +1331,116 @@ hostapd_wnm_disassoc_imminent(struct ubus_context *ctx, struct ubus_object *obj,
> if (nr)
> req_mode |= WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED;
>
> - if (tb[WNM_DISASSOC_ABRIDGED] && blobmsg_get_bool(tb[WNM_DISASSOC_ABRIDGED]))
> + if (abridged)
> req_mode |= WNM_BSS_TM_REQ_ABRIDGED;
>
> - if (wnm_send_bss_tm_req(hapd, sta, req_mode, duration, duration, NULL,
> + if (disassoc_imminent)
> + req_mode |= WNM_BSS_TM_REQ_DISASSOC_IMMINENT;
> +
> + if (wnm_send_bss_tm_req(hapd, sta, req_mode, disassoc_timer, validity_period, NULL,
> NULL, nr, nr_len, NULL, 0))
> return UBUS_STATUS_UNKNOWN_ERROR;
>
> return 0;
> }
> +
> +enum {
> + BSS_TR_ADDR,
> + BSS_TR_DA_IMMINENT,
> + BSS_TR_DA_TIMER,
> + BSS_TR_VALID_PERIOD,
> + BSS_TR_NEIGHBORS,
> + BSS_TR_ABRIDGED,
> + __BSS_TR_DISASSOC_MAX
> +};
> +
> +static const struct blobmsg_policy bss_tr_policy[__BSS_TR_DISASSOC_MAX] = {
> + [BSS_TR_ADDR] = { "addr", BLOBMSG_TYPE_STRING },
> + [BSS_TR_DA_IMMINENT] = { "disassociation_imminent", BLOBMSG_TYPE_BOOL },
> + [BSS_TR_DA_TIMER] = { "disassociation_timer", BLOBMSG_TYPE_INT32 },
> + [BSS_TR_VALID_PERIOD] = { "validity_period", BLOBMSG_TYPE_INT32 },
> + [BSS_TR_NEIGHBORS] = { "neighbors", BLOBMSG_TYPE_ARRAY },
> + [BSS_TR_ABRIDGED] = { "abridged", BLOBMSG_TYPE_BOOL },
> +};
> +
> +static int
> +hostapd_bss_transition_request(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[__BSS_TR_DISASSOC_MAX];
> + struct sta_info *sta;
> + u32 da_timer = 0;
> + u32 valid_period = 0;
> + u8 addr[ETH_ALEN];
> + bool abridged;
> + bool da_imminent;
> +
> + blobmsg_parse(bss_tr_policy, __BSS_TR_DISASSOC_MAX, tb, blob_data(msg), blob_len(msg));
> +
> + if (!tb[BSS_TR_ADDR])
> + return UBUS_STATUS_INVALID_ARGUMENT;
> +
> + if (hwaddr_aton(blobmsg_data(tb[BSS_TR_ADDR]), addr))
> + return UBUS_STATUS_INVALID_ARGUMENT;
> +
> + if (tb[BSS_TR_DA_TIMER])
> + da_timer = blobmsg_get_u32(tb[BSS_TR_DA_TIMER]);
> +
> + if (tb[BSS_TR_VALID_PERIOD])
> + valid_period = blobmsg_get_u32(tb[BSS_TR_VALID_PERIOD]);
> +
> + da_imminent = !!(tb[BSS_TR_DA_IMMINENT] && blobmsg_get_bool(tb[BSS_TR_DA_IMMINENT]));
> + abridged = !!(tb[BSS_TR_ABRIDGED] && blobmsg_get_bool(tb[BSS_TR_ABRIDGED]));
> +
> + return hostapd_bss_tr_send(hapd, addr, da_imminent, abridged, da_timer, valid_period,
> + tb[BSS_TR_NEIGHBORS]);
> +}
> +
> +enum {
> + WNM_DISASSOC_ADDR,
> + WNM_DISASSOC_DURATION,
> + WNM_DISASSOC_NEIGHBORS,
> + WNM_DISASSOC_ABRIDGED,
> + __WNM_DISASSOC_MAX,
> +};
> +
> +static const struct blobmsg_policy wnm_disassoc_policy[__WNM_DISASSOC_MAX] = {
> + [WNM_DISASSOC_ADDR] = { "addr", BLOBMSG_TYPE_STRING },
> + [WNM_DISASSOC_DURATION] { "duration", BLOBMSG_TYPE_INT32 },
> + [WNM_DISASSOC_NEIGHBORS] { "neighbors", BLOBMSG_TYPE_ARRAY },
> + [WNM_DISASSOC_ABRIDGED] { "abridged", BLOBMSG_TYPE_BOOL },
> +};
> +
> +static int
> +hostapd_wnm_disassoc_imminent(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[__WNM_DISASSOC_MAX];
> + struct sta_info *sta;
> + int duration = 10;
> + u8 addr[ETH_ALEN];
> + bool abridged;
> +
> + blobmsg_parse(wnm_disassoc_policy, __WNM_DISASSOC_MAX, tb, blob_data(msg), blob_len(msg));
> +
> + if (!tb[WNM_DISASSOC_ADDR])
> + return UBUS_STATUS_INVALID_ARGUMENT;
> +
> + if (hwaddr_aton(blobmsg_data(tb[WNM_DISASSOC_ADDR]), addr))
> + return UBUS_STATUS_INVALID_ARGUMENT;
> +
> + if (tb[WNM_DISASSOC_DURATION])
> + duration = blobmsg_get_u32(tb[WNM_DISASSOC_DURATION]);
> +
> + abridged = !!(tb[WNM_DISASSOC_ABRIDGED] && blobmsg_get_bool(tb[WNM_DISASSOC_ABRIDGED]));
> +
> + return hostapd_bss_tr_send(hapd, addr, true, abridged, duration, duration,
> + tb[WNM_DISASSOC_NEIGHBORS]);
> +}
> #endif
>
> #ifdef CONFIG_AIRTIME_POLICY
> @@ -1454,6 +1525,7 @@ static const struct ubus_method bss_methods[] = {
> UBUS_METHOD("rrm_beacon_req", hostapd_rrm_beacon_req, beacon_req_policy),
> #ifdef CONFIG_WNM_AP
> UBUS_METHOD("wnm_disassoc_imminent", hostapd_wnm_disassoc_imminent, wnm_disassoc_policy),
> + UBUS_METHOD("bss_transition_request", hostapd_bss_transition_request, bss_tr_policy),
> #endif
> };
>
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_signature
Type: application/pgp-signature
Size: 840 bytes
Desc: OpenPGP digital signature
URL: <http://lists.openwrt.org/pipermail/openwrt-devel/attachments/20211011/ded5781b/attachment.sig>
More information about the openwrt-devel
mailing list