]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
nl80211: Process 6 GHz regulatory rules to accurate channel flags
authorAiny Kumari <quic_ainykuma@quicinc.com>
Thu, 22 Feb 2024 04:02:04 +0000 (09:32 +0530)
committerJouni Malinen <j@w1.fi>
Mon, 4 Mar 2024 17:20:03 +0000 (19:20 +0200)
This is needed to be able to indicate all supported operating classes.

Signed-off-by: Ainy Kumari <quic_ainykuma@quicinc.com>
src/drivers/driver.h
src/drivers/driver_nl80211_capa.c

index bbaf8eafa95200a664ef098ceb6fa9e6bb6902b1..eedc3f647dd9206f21c4b4ea743e75c83f9c835d 100644 (file)
@@ -43,6 +43,7 @@
 
 #define HOSTAPD_CHAN_VHT_80MHZ_SUBCHANNEL 0x00000800
 #define HOSTAPD_CHAN_VHT_160MHZ_SUBCHANNEL 0x00001000
+#define HOSTAPD_CHAN_EHT_320MHZ_SUBCHANNEL 0x00002000
 
 #define HOSTAPD_CHAN_INDOOR_ONLY 0x00010000
 #define HOSTAPD_CHAN_GO_CONCURRENT 0x00020000
index cef23b1836883d3d72ca1049d6a47cfb06324740..3bcd66c24533a020af50fa72067a08708a69d15c 100644 (file)
@@ -2405,6 +2405,57 @@ static void nl80211_reg_rule_vht(struct nlattr *tb[],
 }
 
 
+static void nl80211_set_6ghz_mode(struct hostapd_hw_modes *mode, int start,
+                                 int end, int max_bw)
+{
+       int c;
+
+       for (c = 0; c < mode->num_channels; c++) {
+               struct hostapd_channel_data *chan = &mode->channels[c];
+
+               if (chan->freq - 10 < start || chan->freq + 10 > end)
+                       continue;
+
+               if (max_bw >= 80)
+                       chan->flag |= HOSTAPD_CHAN_VHT_80MHZ_SUBCHANNEL;
+
+               if (max_bw >= 160)
+                       chan->flag |= HOSTAPD_CHAN_VHT_160MHZ_SUBCHANNEL;
+
+               if (max_bw >= 320)
+                       chan->flag |= HOSTAPD_CHAN_EHT_320MHZ_SUBCHANNEL;
+       }
+}
+
+
+static void nl80211_reg_rule_6ghz(struct nlattr *tb[],
+                                struct phy_info_arg *results)
+{
+       u32 start, end, max_bw;
+       u16 m;
+
+       if (!tb[NL80211_ATTR_FREQ_RANGE_START] ||
+           !tb[NL80211_ATTR_FREQ_RANGE_END] ||
+           !tb[NL80211_ATTR_FREQ_RANGE_MAX_BW])
+               return;
+
+       start = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]) / 1000;
+       end = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]) / 1000;
+       max_bw = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]) / 1000;
+
+       if (max_bw < 80)
+               return;
+
+       for (m = 0; m < *results->num_modes; m++) {
+               if (results->modes[m].num_channels == 0 ||
+                   !is_6ghz_freq(results->modes[m].channels[0].freq))
+                       continue;
+
+               nl80211_set_6ghz_mode(&results->modes[m], start, end, max_bw);
+       }
+}
+
+
 static void nl80211_set_dfs_domain(enum nl80211_dfs_regions region,
                                   u8 *dfs_domain)
 {
@@ -2523,6 +2574,13 @@ static int nl80211_get_reg(struct nl_msg *msg, void *arg)
                nl80211_reg_rule_vht(tb_rule, results);
        }
 
+       nla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule)
+       {
+               nla_parse(tb_rule, NL80211_FREQUENCY_ATTR_MAX,
+                         nla_data(nl_rule), nla_len(nl_rule), reg_policy);
+               nl80211_reg_rule_6ghz(tb_rule, results);
+       }
+
        return NL_SKIP;
 }