wifi: mac80211: simplify adding supported rates
authorJohannes Berg <johannes.berg@intel.com>
Mon, 29 Jan 2024 19:19:32 +0000 (20:19 +0100)
committerJohannes Berg <johannes.berg@intel.com>
Thu, 8 Feb 2024 14:00:43 +0000 (15:00 +0100)
Make this a new-style "put" function, and change the
parameters to pass more information directly, this
makes it usable also for the MLME code.

Link: https://msgid.link/20240129202041.f604a03bd728.I8c798ea45b8479ac9982e77d0378af11a09ccdaf@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/ieee80211_i.h
net/mac80211/mesh.c
net/mac80211/mesh_plink.c
net/mac80211/mlme.c
net/mac80211/tdls.c
net/mac80211/util.c

index f7b2381878a96fedb884b7951308718b26f6d16f..b69f081e1c1fbb5873259a6f672b853cd6b3cdba 100644 (file)
@@ -2511,12 +2511,6 @@ u8 *ieee80211_ie_build_eht_oper(u8 *pos, struct cfg80211_chan_def *chandef,
 int ieee80211_parse_bitrates(enum nl80211_chan_width width,
                             const struct ieee80211_supported_band *sband,
                             const u8 *srates, int srates_len, u32 *rates);
-int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata,
-                           struct sk_buff *skb, bool need_basic,
-                           enum nl80211_band band);
-int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata,
-                               struct sk_buff *skb, bool need_basic,
-                               enum nl80211_band band);
 u8 *ieee80211_add_wmm_info_ie(u8 *buf, u8 qosinfo);
 void ieee80211_add_s1g_capab_ie(struct ieee80211_sub_if_data *sdata,
                                struct ieee80211_sta_s1g_cap *caps,
@@ -2526,6 +2520,10 @@ void ieee80211_add_aid_request_ie(struct ieee80211_sub_if_data *sdata,
 u8 *ieee80211_ie_build_s1g_cap(u8 *pos, struct ieee80211_sta_s1g_cap *s1g_cap);
 
 /* element building in SKBs */
+int ieee80211_put_srates_elem(struct sk_buff *skb,
+                             const struct ieee80211_supported_band *sband,
+                             u32 basic_rates, u32 rate_flags, u32 masked_rates,
+                             u8 element_id);
 void ieee80211_put_he_6ghz_cap(struct sk_buff *skb,
                               struct ieee80211_sub_if_data *sdata,
                               enum ieee80211_smps_mode smps_mode);
index 10c7d7714ffed28cdd063fb2bcb5ded01f3fb1fb..7e860486c6bc5d07a654727a86f33aa7ea5706e7 100644 (file)
@@ -968,19 +968,19 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
        int head_len, tail_len;
        struct sk_buff *skb;
        struct ieee80211_mgmt *mgmt;
-       struct ieee80211_chanctx_conf *chanctx_conf;
        struct mesh_csa_settings *csa;
-       enum nl80211_band band;
+       const struct ieee80211_supported_band *sband;
        u8 ie_len_he_cap, ie_len_eht_cap;
        u8 *pos;
        struct ieee80211_sub_if_data *sdata;
        int hdr_len = offsetofend(struct ieee80211_mgmt, u.beacon);
+       u32 rate_flags;
 
        sdata = container_of(ifmsh, struct ieee80211_sub_if_data, u.mesh);
-       rcu_read_lock();
-       chanctx_conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
-       band = chanctx_conf->def.chan->band;
-       rcu_read_unlock();
+
+       sband = ieee80211_get_sband(sdata);
+       rate_flags =
+               ieee80211_chandef_rate_flags(&sdata->vif.bss_conf.chanreq.oper);
 
        ie_len_he_cap = ieee80211_ie_len_he_cap(sdata);
        ie_len_eht_cap = ieee80211_ie_len_eht_cap(sdata);
@@ -1107,7 +1107,9 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
        }
        rcu_read_unlock();
 
-       if (ieee80211_add_srates_ie(sdata, skb, true, band) ||
+       if (ieee80211_put_srates_elem(skb, sband,
+                                     sdata->vif.bss_conf.basic_rates,
+                                     rate_flags, 0, WLAN_EID_SUPP_RATES) ||
            mesh_add_ds_params_ie(sdata, skb))
                goto out_free;
 
@@ -1118,7 +1120,9 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
        skb_trim(skb, 0);
        bcn->tail = bcn->head + bcn->head_len;
 
-       if (ieee80211_add_ext_srates_ie(sdata, skb, true, band) ||
+       if (ieee80211_put_srates_elem(skb, sband,
+                                     sdata->vif.bss_conf.basic_rates,
+                                     rate_flags, 0, WLAN_EID_EXT_SUPP_RATES) ||
            mesh_add_rsn_ie(sdata, skb) ||
            mesh_add_ht_cap_ie(sdata, skb) ||
            mesh_add_ht_oper_ie(sdata, skb) ||
index 7ba0f01805a4ab6165dbdd4b32d30de492b71e97..8f2b492a9fe9822f4cee34f6579f1122e81ff02d 100644 (file)
@@ -264,14 +264,13 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
 
        if (action != WLAN_SP_MESH_PEERING_CLOSE) {
                struct ieee80211_supported_band *sband;
-               enum nl80211_band band;
+               u32 rate_flags, basic_rates;
 
                sband = ieee80211_get_sband(sdata);
                if (!sband) {
                        err = -EINVAL;
                        goto free;
                }
-               band = sband->band;
 
                /* capability info */
                pos = skb_put_zero(skb, 2);
@@ -280,8 +279,17 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
                        pos = skb_put(skb, 2);
                        put_unaligned_le16(sta->sta.aid, pos);
                }
-               if (ieee80211_add_srates_ie(sdata, skb, true, band) ||
-                   ieee80211_add_ext_srates_ie(sdata, skb, true, band) ||
+
+               rate_flags =
+                       ieee80211_chandef_rate_flags(&sdata->vif.bss_conf.chanreq.oper);
+               basic_rates = sdata->vif.bss_conf.basic_rates;
+
+               if (ieee80211_put_srates_elem(skb, sband, basic_rates,
+                                             rate_flags, 0,
+                                             WLAN_EID_SUPP_RATES) ||
+                   ieee80211_put_srates_elem(skb, sband, basic_rates,
+                                             rate_flags, 0,
+                                             WLAN_EID_EXT_SUPP_RATES) ||
                    mesh_add_rsn_ie(sdata, skb) ||
                    mesh_add_meshid_ie(sdata, skb) ||
                    mesh_add_meshconf_ie(sdata, skb))
index 74a6c67a94da5a364224fc92a3f7d68f1b1b302a..d807a904419c8e52c1d6dee6eeb42ab7144582a3 100644 (file)
@@ -1110,10 +1110,7 @@ static void ieee80211_assoc_add_rates(struct sk_buff *skb,
                                      struct ieee80211_supported_band *sband,
                                      struct ieee80211_mgd_assoc_data *assoc_data)
 {
-       unsigned int rates_len, supp_rates_len;
-       u32 rates = 0;
-       int i, count;
-       u8 *pos;
+       u32 rates;
 
        if (assoc_data->supp_rates_len) {
                /*
@@ -1122,53 +1119,23 @@ static void ieee80211_assoc_add_rates(struct sk_buff *skb,
                 * in the association request (e.g. D-Link DAP 1353 in
                 * b-only mode)...
                 */
-               rates_len = ieee80211_parse_bitrates(width, sband,
-                                                    assoc_data->supp_rates,
-                                                    assoc_data->supp_rates_len,
-                                                    &rates);
+               ieee80211_parse_bitrates(width, sband,
+                                        assoc_data->supp_rates,
+                                        assoc_data->supp_rates_len,
+                                        &rates);
        } else {
                /*
                 * In case AP not provide any supported rates information
                 * before association, we send information element(s) with
                 * all rates that we support.
                 */
-               rates_len = sband->n_bitrates;
-               for (i = 0; i < sband->n_bitrates; i++)
-                       rates |= BIT(i);
-       }
-
-       supp_rates_len = rates_len;
-       if (supp_rates_len > 8)
-               supp_rates_len = 8;
-
-       pos = skb_put(skb, supp_rates_len + 2);
-       *pos++ = WLAN_EID_SUPP_RATES;
-       *pos++ = supp_rates_len;
-
-       count = 0;
-       for (i = 0; i < sband->n_bitrates; i++) {
-               if (BIT(i) & rates) {
-                       int rate = DIV_ROUND_UP(sband->bitrates[i].bitrate, 5);
-                       *pos++ = (u8)rate;
-                       if (++count == 8)
-                               break;
-               }
+               rates = ~0;
        }
 
-       if (rates_len > count) {
-               pos = skb_put(skb, rates_len - count + 2);
-               *pos++ = WLAN_EID_EXT_SUPP_RATES;
-               *pos++ = rates_len - count;
-
-               for (i++; i < sband->n_bitrates; i++) {
-                       if (BIT(i) & rates) {
-                               int rate;
-
-                               rate = DIV_ROUND_UP(sband->bitrates[i].bitrate, 5);
-                               *pos++ = (u8)rate;
-                       }
-               }
-       }
+       ieee80211_put_srates_elem(skb, sband, 0, 0, ~rates,
+                                 WLAN_EID_SUPP_RATES);
+       ieee80211_put_srates_elem(skb, sband, 0, 0, ~rates,
+                                 WLAN_EID_EXT_SUPP_RATES);
 }
 
 static size_t ieee80211_add_before_ht_elems(struct sk_buff *skb,
index e6808b7660ff5fcc262c1215b51fedfb817e3a2b..edbd3fd8a7374ce4ee1e71c975bfa3e8c5e50cab 100644 (file)
@@ -382,8 +382,8 @@ ieee80211_tdls_add_setup_start_ies(struct ieee80211_link_data *link,
        if (WARN_ON_ONCE(!sband))
                return;
 
-       ieee80211_add_srates_ie(sdata, skb, false, sband->band);
-       ieee80211_add_ext_srates_ie(sdata, skb, false, sband->band);
+       ieee80211_put_srates_elem(skb, sband, 0, 0, 0, WLAN_EID_SUPP_RATES);
+       ieee80211_put_srates_elem(skb, sband, 0, 0, 0, WLAN_EID_EXT_SUPP_RATES);
        ieee80211_tdls_add_supp_channels(sdata, skb);
 
        /* add any custom IEs that go before Extended Capabilities */
index c90f338b229c840557c82538361c5ba3939541a8..3888ad3b052f3287ee239fb71c52b893cfa601b4 100644 (file)
@@ -4091,93 +4091,62 @@ int ieee80211_parse_bitrates(enum nl80211_chan_width width,
        return count;
 }
 
-int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata,
-                           struct sk_buff *skb, bool need_basic,
-                           enum nl80211_band band)
+int ieee80211_put_srates_elem(struct sk_buff *skb,
+                             const struct ieee80211_supported_band *sband,
+                             u32 basic_rates, u32 rate_flags, u32 masked_rates,
+                             u8 element_id)
 {
-       struct ieee80211_local *local = sdata->local;
-       struct ieee80211_supported_band *sband;
-       int rate;
-       u8 i, rates, *pos;
-       u32 basic_rates = sdata->vif.bss_conf.basic_rates;
-       u32 rate_flags;
+       u8 i, rates, skip;
 
-       rate_flags =
-               ieee80211_chandef_rate_flags(&sdata->vif.bss_conf.chanreq.oper);
-       sband = local->hw.wiphy->bands[band];
        rates = 0;
        for (i = 0; i < sband->n_bitrates; i++) {
                if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
                        continue;
+               if (masked_rates & BIT(i))
+                       continue;
                rates++;
        }
-       if (rates > 8)
-               rates = 8;
 
-       if (skb_tailroom(skb) < rates + 2)
-               return -ENOMEM;
-
-       pos = skb_put(skb, rates + 2);
-       *pos++ = WLAN_EID_SUPP_RATES;
-       *pos++ = rates;
-       for (i = 0; i < rates; i++) {
-               u8 basic = 0;
-               if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
-                       continue;
-
-               if (need_basic && basic_rates & BIT(i))
-                       basic = 0x80;
-               rate = DIV_ROUND_UP(sband->bitrates[i].bitrate, 5);
-               *pos++ = basic | (u8) rate;
+       if (element_id == WLAN_EID_SUPP_RATES) {
+               rates = min_t(u8, rates, 8);
+               skip = 0;
+       } else {
+               skip = 8;
+               if (rates <= skip)
+                       return 0;
+               rates -= skip;
        }
 
-       return 0;
-}
+       if (skb_tailroom(skb) < rates + 2)
+               return -ENOBUFS;
 
-int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata,
-                               struct sk_buff *skb, bool need_basic,
-                               enum nl80211_band band)
-{
-       struct ieee80211_local *local = sdata->local;
-       struct ieee80211_supported_band *sband;
-       int rate;
-       u8 i, exrates, *pos;
-       u32 basic_rates = sdata->vif.bss_conf.basic_rates;
-       u32 rate_flags;
+       skb_put_u8(skb, element_id);
+       skb_put_u8(skb, rates);
+
+       for (i = 0; i < sband->n_bitrates && rates; i++) {
+               int rate;
+               u8 basic;
 
-       rate_flags =
-               ieee80211_chandef_rate_flags(&sdata->vif.bss_conf.chanreq.oper);
-       sband = local->hw.wiphy->bands[band];
-       exrates = 0;
-       for (i = 0; i < sband->n_bitrates; i++) {
                if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
                        continue;
-               exrates++;
-       }
+               if (masked_rates & BIT(i))
+                       continue;
 
-       if (exrates > 8)
-               exrates -= 8;
-       else
-               exrates = 0;
+               if (skip > 0) {
+                       skip--;
+                       continue;
+               }
 
-       if (skb_tailroom(skb) < exrates + 2)
-               return -ENOMEM;
+               basic = basic_rates & BIT(i) ? 0x80 : 0;
 
-       if (exrates) {
-               pos = skb_put(skb, exrates + 2);
-               *pos++ = WLAN_EID_EXT_SUPP_RATES;
-               *pos++ = exrates;
-               for (i = 8; i < sband->n_bitrates; i++) {
-                       u8 basic = 0;
-                       if ((rate_flags & sband->bitrates[i].flags)
-                           != rate_flags)
-                               continue;
-                       if (need_basic && basic_rates & BIT(i))
-                               basic = 0x80;
-                       rate = DIV_ROUND_UP(sband->bitrates[i].bitrate, 5);
-                       *pos++ = basic | (u8) rate;
-               }
+               rate = DIV_ROUND_UP(sband->bitrates[i].bitrate, 5);
+               skb_put_u8(skb, basic | (u8)rate);
+               rates--;
        }
+
+       WARN(rates > 0, "rates confused: rates:%d, element:%d\n",
+            rates, element_id);
+
        return 0;
 }