]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
WNM: Event report handling for BSS color collision and in-use
authorYi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
Tue, 14 Feb 2023 23:07:58 +0000 (15:07 -0800)
committerJouni Malinen <j@w1.fi>
Mon, 20 Feb 2023 20:00:13 +0000 (22:00 +0200)
Add support for WNM event report handling for the BSS color collision
and in use events.

Co-developed-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
src/ap/wnm_ap.c
src/common/ieee802_11_defs.h

index 23a352c9ba54443053752020137f1c4abde263ae..153ee4033468dd142b725811e220bf33af7afb28 100644 (file)
@@ -643,6 +643,133 @@ static void ieee802_11_rx_wnm_coloc_intf_report(struct hostapd_data *hapd,
 }
 
 
+
+static const char * wnm_event_type2str(enum wnm_event_report_type wtype)
+{
+#define W2S(wtype) case WNM_EVENT_TYPE_ ## wtype: return #wtype;
+       switch (wtype) {
+       W2S(TRANSITION)
+       W2S(RSNA)
+       W2S(P2P_LINK)
+       W2S(WNM_LOG)
+       W2S(BSS_COLOR_COLLISION)
+       W2S(BSS_COLOR_IN_USE)
+       }
+       return "UNKNOWN";
+#undef W2S
+}
+
+
+static void ieee802_11_rx_wnm_event_report(struct hostapd_data *hapd,
+                                          const u8 *addr, const u8 *buf,
+                                          size_t len)
+{
+       struct sta_info *sta;
+       u8 dialog_token;
+       struct wnm_event_report_element *report_ie;
+       const u8 *pos = buf, *end = buf + len;
+       const size_t fixed_field_len = 3; /* Event Token/Type/Report Status */
+#ifdef CONFIG_IEEE80211AX
+       const size_t tsf_len = 8;
+       u8 color;
+       u64 bitmap;
+#endif /* CONFIG_IEEE80211AX */
+
+       if (end - pos < 1 + 2) {
+               wpa_printf(MSG_DEBUG,
+                          "WNM: Ignore too short WNM Event Report frame from "
+                          MACSTR, MAC2STR(addr));
+               return;
+       }
+
+       dialog_token = *pos++;
+       report_ie = (struct wnm_event_report_element *) pos;
+
+       if (end - pos < 2 + report_ie->len ||
+           report_ie->len < fixed_field_len) {
+               wpa_printf(MSG_DEBUG,
+                          "WNM: Ignore truncated WNM Event Report frame from "
+                          MACSTR, MAC2STR(addr));
+               return;
+       }
+
+       if (report_ie->eid != WLAN_EID_EVENT_REPORT ||
+           report_ie->status != WNM_STATUS_SUCCESSFUL)
+               return;
+
+       wpa_printf(MSG_DEBUG, "WNM: Received WNM Event Report frame from "
+                  MACSTR " dialog_token=%u event_token=%u type=%d (%s)",
+                  MAC2STR(addr), dialog_token, report_ie->token,
+                  report_ie->type, wnm_event_type2str(report_ie->type));
+
+       pos += 2 + fixed_field_len;
+       wpa_hexdump(MSG_MSGDUMP, "WNM: Event Report", pos, end - pos);
+
+       sta = ap_get_sta(hapd, addr);
+       if (!sta || !(sta->flags & WLAN_STA_ASSOC)) {
+               wpa_printf(MSG_DEBUG, "Station " MACSTR
+                          " not found for received WNM Event Report",
+                          MAC2STR(addr));
+               return;
+       }
+
+       switch (report_ie->type) {
+#ifdef CONFIG_IEEE80211AX
+       case WNM_EVENT_TYPE_BSS_COLOR_COLLISION:
+               if (!hapd->iconf->ieee80211ax || hapd->conf->disable_11ax)
+                       return;
+               if (report_ie->len <
+                   fixed_field_len + tsf_len + 8) {
+                       wpa_printf(MSG_DEBUG,
+                                  "WNM: Too short BSS color collision event report from "
+                                  MACSTR, MAC2STR(addr));
+                       return;
+               }
+               bitmap = WPA_GET_LE64(report_ie->u.bss_color_collision.color_bitmap);
+               wpa_printf(MSG_DEBUG,
+                          "WNM: BSS color collision bitmap 0x%llx reported by "
+                          MACSTR, (unsigned long long) bitmap, MAC2STR(addr));
+               hostapd_switch_color(hapd->iface->bss[0], bitmap);
+               break;
+       case WNM_EVENT_TYPE_BSS_COLOR_IN_USE:
+               if (!hapd->iconf->ieee80211ax || hapd->conf->disable_11ax)
+                       return;
+               if (report_ie->len < fixed_field_len + tsf_len + 1) {
+                       wpa_printf(MSG_DEBUG,
+                                  "WNM: Too short BSS color in use event report from "
+                                  MACSTR, MAC2STR(addr));
+                       return;
+               }
+               color = report_ie->u.bss_color_in_use.color;
+               if (color > 63) {
+                       wpa_printf(MSG_DEBUG,
+                                  "WNM: Invalid BSS color %u report from "
+                                  MACSTR, color, MAC2STR(addr));
+                       return;
+               }
+               if (color == 0) {
+                       wpa_printf(MSG_DEBUG,
+                                  "WNM: BSS color use report canceled by "
+                                  MACSTR, MAC2STR(addr));
+                       /* TODO: Clear stored color from the collision bitmap
+                        * if there are no other users for it. */
+                       return;
+               }
+               wpa_printf(MSG_DEBUG, "WNM: BSS color %u use report by "
+                          MACSTR, color, MAC2STR(addr));
+               hapd->color_collision_bitmap |= 1ULL << color;
+               break;
+#endif /* CONFIG_IEEE80211AX */
+       default:
+               wpa_printf(MSG_DEBUG,
+                          "WNM Event Report type=%d (%s) not supported",
+                          report_ie->type,
+                          wnm_event_type2str(report_ie->type));
+               break;
+       }
+}
+
+
 int ieee802_11_rx_wnm_action_ap(struct hostapd_data *hapd,
                                const struct ieee80211_mgmt *mgmt, size_t len)
 {
@@ -658,6 +785,10 @@ int ieee802_11_rx_wnm_action_ap(struct hostapd_data *hapd,
        plen = len - IEEE80211_HDRLEN - 2;
 
        switch (action) {
+       case WNM_EVENT_REPORT:
+               ieee802_11_rx_wnm_event_report(hapd, mgmt->sa, payload,
+                                              plen);
+               return 0;
        case WNM_BSS_TRANS_MGMT_QUERY:
                ieee802_11_rx_bss_trans_mgmt_query(hapd, mgmt->sa, payload,
                                                   plen);
index 21b48ac523695699e603ad4d2b8132c0d68c48f0..6306ef9a0c86fa015696b009e71cc46144c53702 100644 (file)
@@ -1959,6 +1959,42 @@ enum wnm_notification_Type {
        WNM_NOTIF_TYPE_VENDOR_SPECIFIC = 221,
 };
 
+struct wnm_event_report_element {
+       u8 eid; /* WLAN_EID_EVENT_REPORT */
+       u8 len;
+       u8 token;
+       u8 type;
+       u8 status;
+       /* Followed by conditional fields */
+       union {
+               struct {
+                       u8 tsf[8]; /* Event TSF */
+                       u8 color_bitmap[8]; /* Event Report field */
+               } STRUCT_PACKED bss_color_collision;
+               struct {
+                       u8 tsf[8]; /* Event TSF */
+                       u8 color; /* Event Report field */
+               } STRUCT_PACKED bss_color_in_use;
+       } u;
+} STRUCT_PACKED;
+
+enum wnm_event_report_status {
+       WNM_STATUS_SUCCESSFUL = 0,
+       WNM_STATUS_REQ_FAILED = 1,
+       WNM_STATUS_REQ_REFUSED = 2,
+       WNM_STATUS_REQ_INCAPABLE = 3,
+       WNM_STATUS_FREQUENT_TRANSITION = 4,
+};
+
+enum wnm_event_report_type {
+       WNM_EVENT_TYPE_TRANSITION = 0,
+       WNM_EVENT_TYPE_RSNA = 1,
+       WNM_EVENT_TYPE_P2P_LINK = 2,
+       WNM_EVENT_TYPE_WNM_LOG = 3,
+       WNM_EVENT_TYPE_BSS_COLOR_COLLISION = 4,
+       WNM_EVENT_TYPE_BSS_COLOR_IN_USE = 5,
+};
+
 /* Channel Switch modes (802.11h) */
 #define CHAN_SWITCH_MODE_ALLOW_TX      0
 #define CHAN_SWITCH_MODE_BLOCK_TX      1