blobmsg_add_u8(&b, sta_flags[i].name,
!!(sta->flags & sta_flags[i].flag));
+#ifdef CONFIG_MBO
+ blobmsg_add_u8(&b, "mbo", !!(sta->cell_capa));
+#endif
+
r = blobmsg_open_array(&b, "rrm");
for (i = 0; i < ARRAY_SIZE(sta->rrm_enabled_capa); i++)
blobmsg_add_u32(&b, "", sta->rrm_enabled_capa[i]);
return 0;
}
-/* Imported from iw/util.c
- * https://git.kernel.org/pub/scm/linux/kernel/git/jberg/iw.git/tree/util.c?id=4b25ae3537af48dbf9d0abf94132e5ba01b32c18#n200
- */
-int ieee80211_frequency_to_channel(int freq)
-{
- /* see 802.11-2007 17.3.8.3.2 and Annex J */
- if (freq == 2484)
- return 14;
- /* see 802.11ax D6.1 27.3.23.2 and Annex E */
- else if (freq == 5935)
- return 2;
- else if (freq < 2484)
- return (freq - 2407) / 5;
- else if (freq >= 4910 && freq <= 4980)
- return (freq - 4000) / 5;
- else if (freq < 5950)
- return (freq - 5000) / 5;
- else if (freq <= 45000) /* DMG band lower limit */
- /* see 802.11ax D6.1 27.3.23.2 */
- return (freq - 5950) / 5;
- else if (freq >= 58320 && freq <= 70200)
- return (freq - 56160) / 2160;
- else
- return 0;
-}
-
static int
hostapd_bss_get_status(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
blobmsg_add_u32(&b, "channel", channel);
blobmsg_add_u32(&b, "op_class", op_class);
blobmsg_add_u32(&b, "beacon_interval", hapd->iconf->beacon_int);
+#ifdef CONFIG_IEEE80211AX
+ blobmsg_add_u32(&b, "bss_color", hapd->iface->conf->he_op.he_bss_color_disabled ? -1 :
+ hapd->iface->conf->he_op.he_bss_color);
+#else
+ blobmsg_add_u32(&b, "bss_color", -1);
+#endif
snprintf(phy_name, 17, "%s", hapd->iface->phy);
blobmsg_add_string(&b, "phy", phy_name);
css.freq_params.ht_enabled,
css.freq_params.vht_enabled,
css.freq_params.he_enabled,
+ css.freq_params.eht_enabled,
css.freq_params.sec_channel_offset,
chwidth, seg0, seg1,
iconf->vht_capab,
mode ? &mode->he_capab[IEEE80211_MODE_AP] :
+ NULL,
+ mode ? &mode->eht_capab[IEEE80211_MODE_AP] :
NULL);
for (i = 0; i < hapd->iface->num_bss; i++) {
}
__hostapd_bss_mgmt_enable(hapd, flags);
+
+ return 0;
}
static int
hostapd_bss_tr_send(struct hostapd_data *hapd, u8 *addr, bool disassoc_imminent, bool abridged,
u16 disassoc_timer, u8 validity_period, u8 dialog_token,
- struct blob_attr *neighbors)
+ struct blob_attr *neighbors, u8 mbo_reason, u8 cell_pref, u8 reassoc_delay)
{
struct blob_attr *cur;
struct sta_info *sta;
int rem;
u8 *nr = NULL;
u8 req_mode = 0;
+ u8 mbo[10];
+ size_t mbo_len = 0;
sta = ap_get_sta(hapd, addr);
if (!sta)
if (disassoc_imminent)
req_mode |= WNM_BSS_TM_REQ_DISASSOC_IMMINENT;
+#ifdef CONFIG_MBO
+ u8 *mbo_pos = mbo;
+
+ if (mbo_reason > MBO_TRANSITION_REASON_PREMIUM_AP)
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ if (cell_pref != 0 && cell_pref != 1 && cell_pref != 255)
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ if (reassoc_delay > 65535 || (reassoc_delay && !disassoc_imminent))
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ *mbo_pos++ = MBO_ATTR_ID_TRANSITION_REASON;
+ *mbo_pos++ = 1;
+ *mbo_pos++ = mbo_reason;
+ *mbo_pos++ = MBO_ATTR_ID_CELL_DATA_PREF;
+ *mbo_pos++ = 1;
+ *mbo_pos++ = cell_pref;
+
+ if (reassoc_delay) {
+ *mbo_pos++ = MBO_ATTR_ID_ASSOC_RETRY_DELAY;
+ *mbo_pos++ = 2;
+ WPA_PUT_LE16(mbo_pos, reassoc_delay);
+ mbo_pos += 2;
+ }
+
+ mbo_len = mbo_pos - mbo;
+#endif
+
if (wnm_send_bss_tm_req(hapd, sta, req_mode, disassoc_timer, validity_period, NULL,
- dialog_token, NULL, nr, nr_len, NULL, 0))
+ dialog_token, NULL, nr, nr_len, mbo_len ? mbo : NULL, mbo_len))
return UBUS_STATUS_UNKNOWN_ERROR;
return 0;
BSS_TR_NEIGHBORS,
BSS_TR_ABRIDGED,
BSS_TR_DIALOG_TOKEN,
+#ifdef CONFIG_MBO
+ BSS_TR_MBO_REASON,
+ BSS_TR_CELL_PREF,
+ BSS_TR_REASSOC_DELAY,
+#endif
__BSS_TR_DISASSOC_MAX
};
[BSS_TR_NEIGHBORS] = { "neighbors", BLOBMSG_TYPE_ARRAY },
[BSS_TR_ABRIDGED] = { "abridged", BLOBMSG_TYPE_BOOL },
[BSS_TR_DIALOG_TOKEN] = { "dialog_token", BLOBMSG_TYPE_INT32 },
+#ifdef CONFIG_MBO
+ [BSS_TR_MBO_REASON] = { "mbo_reason", BLOBMSG_TYPE_INT32 },
+ [BSS_TR_CELL_PREF] = { "cell_pref", BLOBMSG_TYPE_INT32 },
+ [BSS_TR_REASSOC_DELAY] = { "reassoc_delay", BLOBMSG_TYPE_INT32 },
+#endif
};
static int
u32 dialog_token = 1;
bool abridged;
bool da_imminent;
+ u8 mbo_reason;
+ u8 cell_pref;
+ u8 reassoc_delay;
blobmsg_parse(bss_tr_policy, __BSS_TR_DISASSOC_MAX, tb, blob_data(msg), blob_len(msg));
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]));
+#ifdef CONFIG_MBO
+ if (tb[BSS_TR_MBO_REASON])
+ mbo_reason = blobmsg_get_u32(tb[BSS_TR_MBO_REASON]);
+
+ if (tb[BSS_TR_CELL_PREF])
+ cell_pref = blobmsg_get_u32(tb[BSS_TR_CELL_PREF]);
+
+ if (tb[BSS_TR_REASSOC_DELAY])
+ reassoc_delay = blobmsg_get_u32(tb[BSS_TR_REASSOC_DELAY]);
+#endif
+
return hostapd_bss_tr_send(hapd, addr, da_imminent, abridged, da_timer, valid_period,
- dialog_token, tb[BSS_TR_NEIGHBORS]);
+ dialog_token, tb[BSS_TR_NEIGHBORS], mbo_reason, cell_pref, reassoc_delay);
}
#endif
ubus_notify(ctx, &hapd->ubus.obj, type, b.head, -1);
}
+void hostapd_ubus_notify_authorized(struct hostapd_data *hapd, struct sta_info *sta,
+ const char *auth_alg)
+{
+ if (!hapd->ubus.obj.has_subscribers)
+ return;
+
+ blob_buf_init(&b, 0);
+ blobmsg_add_macaddr(&b, "address", sta->addr);
+ if (auth_alg)
+ blobmsg_add_string(&b, "auth-alg", auth_alg);
+
+ ubus_notify(ctx, &hapd->ubus.obj, "sta-authorized", b.head, -1);
+}
+
void hostapd_ubus_notify_beacon_report(
struct hostapd_data *hapd, const u8 *addr, u8 token, u8 rep_mode,
struct rrm_measurement_beacon_report *rep, size_t len)
blobmsg_add_macaddr(&b, "bssid", rep->bssid);
blobmsg_add_u16(&b, "antenna-id", rep->antenna_id);
blobmsg_add_u16(&b, "parent-tsf", rep->parent_tsf);
+ blobmsg_add_u16(&b, "rep-mode", rep_mode);
ubus_notify(ctx, &hapd->ubus.obj, "beacon-report", b.head, -1);
}