@@ -351,6 +351,11 @@ CFLAGS += -DCONFIG_IEEE80211AX
OBJS += ../src/ap/ieee802_11_he.o
endif
+ifdef CONFIG_IEEE80211AH
+CFLAGS += -DCONFIG_IEEE80211AH
+OBJS += ../src/ap/ieee802_11_s1g.o
+endif
+
ifdef CONFIG_MBO
CFLAGS += -DCONFIG_MBO
OBJS += ../src/ap/mbo_ap.o
@@ -571,18 +571,22 @@ int hostapd_flush(struct hostapd_data *hapd)
int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode,
- int freq, int channel, int edmg, u8 edmg_channel,
+ int freq, int freq_khz, int channel,
+ int edmg, u8 edmg_channel,
int ht_enabled, int vht_enabled,
int he_enabled, bool eht_enabled,
+ int s1g_enabled,
int sec_channel_offset, int oper_chwidth,
int center_segment0, int center_segment1)
{
struct hostapd_freq_params data;
struct hostapd_hw_modes *cmode = hapd->iface->current_mode;
- if (hostapd_set_freq_params(&data, mode, freq, channel, edmg,
+ if (hostapd_set_freq_params(&data, mode, freq, freq_khz,
+ channel, edmg,
edmg_channel, ht_enabled,
- vht_enabled, he_enabled, eht_enabled,
+ vht_enabled, he_enabled,
+ eht_enabled, s1g_enabled,
sec_channel_offset, oper_chwidth,
center_segment0, center_segment1,
cmode ? cmode->vht_capab : 0,
@@ -879,8 +883,9 @@ int hostapd_drv_send_action_addr3_ap(struct hostapd_data *hapd,
int hostapd_start_dfs_cac(struct hostapd_iface *iface,
enum hostapd_hw_mode mode, int freq,
- int channel, int ht_enabled, int vht_enabled,
- int he_enabled, bool eht_enabled,
+ int channel, int ht_enabled,
+ int vht_enabled, int he_enabled,
+ bool eht_enabled, int s1g_enabled,
int sec_channel_offset, int oper_chwidth,
int center_segment0, int center_segment1,
bool radar_background)
@@ -899,9 +904,10 @@ int hostapd_start_dfs_cac(struct hostapd_iface *iface,
return -1;
}
- if (hostapd_set_freq_params(&data, mode, freq, channel, 0, 0,
+ if (hostapd_set_freq_params(&data, mode, freq, 0, channel, 0, 0,
ht_enabled,
- vht_enabled, he_enabled, eht_enabled,
+ vht_enabled, he_enabled,
+ eht_enabled, s1g_enabled,
sec_channel_offset,
oper_chwidth, center_segment0,
center_segment1,
@@ -65,9 +65,11 @@ int hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd,
const u8 *addr, int idx, int link_id, u8 *seq);
int hostapd_flush(struct hostapd_data *hapd);
int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode,
- int freq, int channel, int edmg, u8 edmg_channel,
+ int freq, int freq_khz,
+ int channel, int edmg, u8 edmg_channel,
int ht_enabled, int vht_enabled, int he_enabled,
- bool eht_enabled, int sec_channel_offset, int oper_chwidth,
+ bool eht_enabled, int s1g_enabled,
+ int sec_channel_offset, int oper_chwidth,
int center_segment0, int center_segment1);
int hostapd_set_rts(struct hostapd_data *hapd, int rts);
int hostapd_set_frag(struct hostapd_data *hapd, int frag);
@@ -129,8 +131,9 @@ int hostapd_add_tspec(struct hostapd_data *hapd, const u8 *addr,
u8 *tspec_ie, size_t tspec_ielen);
int hostapd_start_dfs_cac(struct hostapd_iface *iface,
enum hostapd_hw_mode mode, int freq,
- int channel, int ht_enabled, int vht_enabled,
- int he_enabled, bool eht_enabled,
+ int channel, int ht_enabled,
+ int vht_enabled, int he_enabled,
+ bool eht_enabled, int s1g_enabled,
int sec_channel_offset, int oper_chwidth,
int center_segment0, int center_segment1,
bool radar_background);
@@ -2213,10 +2213,11 @@ static int __ieee802_11_set_beacon(struct hostapd_data *hapd)
if (cmode &&
hostapd_set_freq_params(&freq, iconf->hw_mode, iface->freq,
+ iface->freq_khz,
iconf->channel, iconf->enable_edmg,
iconf->edmg_channel, iconf->ieee80211n,
iconf->ieee80211ac, iconf->ieee80211ax,
- iconf->ieee80211be,
+ iconf->ieee80211be, iconf->ieee80211ah,
iconf->secondary_channel,
hostapd_get_oper_chwidth(iconf),
hostapd_get_oper_centr_freq_seg0_idx(iconf),
@@ -831,6 +831,9 @@ int hostapd_handle_dfs(struct hostapd_iface *iface)
if (is_6ghz_freq(iface->freq))
return 1;
+ if (is_s1g_freq(iface->freq_khz))
+ return 1;
+
if (!iface->current_mode) {
/*
* This can happen with drivers that do not provide mode
@@ -903,7 +906,7 @@ int hostapd_handle_dfs(struct hostapd_iface *iface)
iface, iface->conf->hw_mode, iface->freq, iface->conf->channel,
iface->conf->ieee80211n, iface->conf->ieee80211ac,
iface->conf->ieee80211ax, iface->conf->ieee80211be,
- iface->conf->secondary_channel,
+ iface->conf->ieee80211ah, iface->conf->secondary_channel,
hostapd_get_oper_chwidth(iface->conf),
hostapd_get_oper_centr_freq_seg0_idx(iface->conf),
hostapd_get_oper_centr_freq_seg1_idx(iface->conf),
@@ -960,6 +963,7 @@ int hostapd_is_dfs_chan_available(struct hostapd_iface *iface)
static int hostapd_dfs_request_channel_switch(struct hostapd_iface *iface,
int channel, int freq,
+ int freq_khz,
int secondary_channel,
u8 current_vht_oper_chwidth,
u8 oper_centr_freq_seg0_idx,
@@ -989,13 +993,14 @@ static int hostapd_dfs_request_channel_switch(struct hostapd_iface *iface,
#endif /* CONFIG_MESH */
err = hostapd_set_freq_params(&csa_settings.freq_params,
iface->conf->hw_mode,
- freq, channel,
+ freq, freq_khz, channel,
iface->conf->enable_edmg,
iface->conf->edmg_channel,
iface->conf->ieee80211n,
iface->conf->ieee80211ac,
iface->conf->ieee80211ax,
iface->conf->ieee80211be,
+ iface->conf->ieee80211ah,
secondary_channel,
new_vht_oper_chwidth,
oper_centr_freq_seg0_idx,
@@ -1076,6 +1081,7 @@ static void hostpad_dfs_update_background_chain(struct hostapd_iface *iface)
iface->conf->ieee80211ac,
iface->conf->ieee80211ax,
iface->conf->ieee80211be,
+ iface->conf->ieee80211ah,
sec, hostapd_get_oper_chwidth(iface->conf),
oper_centr_freq_seg0_idx,
oper_centr_freq_seg1_idx, true)) {
@@ -1122,7 +1128,7 @@ hostapd_dfs_start_channel_switch_background(struct hostapd_iface *iface)
hostpad_dfs_update_background_chain(iface);
return hostapd_dfs_request_channel_switch(
- iface, iface->conf->channel, iface->freq,
+ iface, iface->conf->channel, iface->freq, 0,
iface->conf->secondary_channel, current_vht_oper_chwidth,
hostapd_get_oper_centr_freq_seg0_idx(iface->conf),
hostapd_get_oper_centr_freq_seg1_idx(iface->conf));
@@ -1414,6 +1420,7 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
return hostapd_dfs_request_channel_switch(iface, channel->chan,
channel->freq,
+ channel->freq_khz,
secondary_channel,
current_vht_oper_chwidth,
oper_centr_freq_seg0_idx,
@@ -1025,8 +1025,8 @@ void hostapd_event_sta_opmode_changed(struct hostapd_data *hapd, const u8 *addr,
}
-void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
- int offset, int width, int cf1, int cf2,
+void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int freq_khz,
+ int ht, int offset, int width, int cf1, int cf2,
u16 punct_bitmap, int finished)
{
#ifdef NEED_AP_MLME
@@ -1056,7 +1056,7 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
is_dfs0 = hostapd_is_dfs_required(hapd->iface);
hapd->iface->freq = freq;
- channel = hostapd_hw_get_channel(hapd, freq);
+ channel = hostapd_hw_get_channel(hapd, freq, freq_khz);
if (!channel) {
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_WARNING,
@@ -1285,6 +1285,7 @@ void hostapd_acs_channel_selected(struct hostapd_data *hapd,
if (hapd->iface->freq > 0 &&
!hw_get_chan(mode->mode,
hapd->iface->freq,
+ hapd->iface->freq_khz,
hapd->iface->hw_features,
hapd->iface->num_hw_features))
continue;
@@ -1309,7 +1310,7 @@ void hostapd_acs_channel_selected(struct hostapd_data *hapd,
goto out;
}
pri_chan = hw_get_channel_freq(hapd->iface->current_mode->mode,
- acs_res->pri_freq, NULL,
+ acs_res->pri_freq, 0, NULL,
hapd->iface->hw_features,
hapd->iface->num_hw_features);
if (!pri_chan) {
@@ -2350,6 +2351,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
if (!data)
break;
hostapd_event_ch_switch(hapd, data->ch_switch.freq,
+ data->ch_switch.freq_khz,
data->ch_switch.ht_enabled,
data->ch_switch.ch_offset,
data->ch_switch.ch_width,
@@ -1671,8 +1671,8 @@ static int hostapd_no_ir_channel_list_updated(struct hostapd_iface *iface,
mode = &iface->hw_features[i];
if (mode->mode == iface->conf->hw_mode) {
- if (iface->freq > 0 &&
- !hw_mode_get_channel(mode, iface->freq, NULL)) {
+ if ((iface->freq > 0 || iface->freq_khz > 0) &&
+ !hw_mode_get_channel(mode, iface->freq, iface->freq_khz, NULL)) {
mode = NULL;
continue;
}
@@ -1698,7 +1698,8 @@ static int hostapd_no_ir_channel_list_updated(struct hostapd_iface *iface,
struct hostapd_channel_data *chan;
chan = hw_get_channel_freq(iface->current_mode->mode,
- iface->freq, NULL,
+ iface->freq,
+ iface->freq_khz, NULL,
iface->hw_features,
iface->num_hw_features);
@@ -1733,7 +1734,8 @@ static int hostapd_no_ir_channel_list_updated(struct hostapd_iface *iface,
struct hostapd_channel_data *chan;
chan = hw_get_channel_freq(iface->current_mode->mode,
- iface->freq, NULL,
+ iface->freq,
+ iface->freq_khz, NULL,
iface->hw_features,
iface->num_hw_features);
if (!chan) {
@@ -1874,6 +1876,10 @@ static int configured_fixed_chan_to_freq(struct hostapd_iface *iface)
{
int freq, i, j;
+ if (iface->conf->ieee80211ah) {
+ return 0;
+ }
+
if (!iface->conf->channel)
return 0;
if (iface->conf->op_class) {
@@ -2333,7 +2339,8 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
#endif /* CONFIG_MESH */
if (!delay_apply_cfg &&
- hostapd_set_freq(hapd, hapd->iconf->hw_mode, iface->freq,
+ hostapd_set_freq(hapd, hapd->iconf->hw_mode,
+ iface->freq, iface->freq_khz,
hapd->iconf->channel,
hapd->iconf->enable_edmg,
hapd->iconf->edmg_channel,
@@ -2341,6 +2348,7 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
hapd->iconf->ieee80211ac,
hapd->iconf->ieee80211ax,
hapd->iconf->ieee80211be,
+ hapd->iconf->ieee80211ah,
hapd->iconf->secondary_channel,
hostapd_get_oper_chwidth(hapd->iconf),
hostapd_get_oper_centr_freq_seg0_idx(
@@ -3776,7 +3784,7 @@ static int hostapd_change_config_freq(struct hostapd_data *hapd,
if (!params->channel) {
/* check if the new channel is supported by hw */
- params->channel = hostapd_hw_get_channel(hapd, params->freq);
+ params->channel = hostapd_hw_get_channel(hapd, params->freq, 0);
}
channel = params->channel;
@@ -3790,10 +3798,12 @@ static int hostapd_change_config_freq(struct hostapd_data *hapd,
if (old_params &&
hostapd_set_freq_params(old_params, conf->hw_mode,
hostapd_hw_get_freq(hapd, conf->channel),
+ 0,
conf->channel, conf->enable_edmg,
conf->edmg_channel, conf->ieee80211n,
conf->ieee80211ac, conf->ieee80211ax,
- conf->ieee80211be, conf->secondary_channel,
+ conf->ieee80211be, conf->ieee80211ah,
+ conf->secondary_channel,
hostapd_get_oper_chwidth(conf),
hostapd_get_oper_centr_freq_seg0_idx(conf),
hostapd_get_oper_centr_freq_seg1_idx(conf),
@@ -561,6 +561,7 @@ struct hostapd_iface {
struct hostapd_rate_data *current_rates;
int *basic_rates;
int freq;
+ int freq_khz;
/* Background radar configuration */
struct {
@@ -739,8 +740,8 @@ void hostapd_event_connect_failed_reason(struct hostapd_data *hapd,
int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da,
const u8 *bssid, const u8 *ie, size_t ie_len,
int ssi_signal);
-void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
- int offset, int width, int cf1, int cf2,
+void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int freq_khz,
+ int ht, int offset, int width, int cf1, int cf2,
u16 punct_bitmap, int finished);
struct survey_results;
void hostapd_event_get_survey(struct hostapd_iface *iface,
@@ -264,11 +264,11 @@ static int ieee80211n_allowed_ht40_channel_pair(struct hostapd_iface *iface)
if (!iface->current_mode)
return 0;
- p_chan = hw_get_channel_freq(iface->current_mode->mode, pri_freq, NULL,
+ p_chan = hw_get_channel_freq(iface->current_mode->mode, pri_freq, 0, NULL,
iface->hw_features,
iface->num_hw_features);
- s_chan = hw_get_channel_freq(iface->current_mode->mode, sec_freq, NULL,
+ s_chan = hw_get_channel_freq(iface->current_mode->mode, sec_freq, 0, NULL,
iface->hw_features,
iface->num_hw_features);
@@ -303,10 +303,10 @@ static int ieee80211n_check_40mhz_5g(struct hostapd_iface *iface,
if (!iface->current_mode)
return 0;
- pri_chan = hw_get_channel_freq(iface->current_mode->mode, pri_freq,
+ pri_chan = hw_get_channel_freq(iface->current_mode->mode, pri_freq, 0,
NULL, iface->hw_features,
iface->num_hw_features);
- sec_chan = hw_get_channel_freq(iface->current_mode->mode, sec_freq,
+ sec_chan = hw_get_channel_freq(iface->current_mode->mode, sec_freq, 0,
NULL, iface->hw_features,
iface->num_hw_features);
@@ -829,15 +829,16 @@ int hostapd_check_he_6ghz_capab(struct hostapd_iface *iface)
* -1 = not currently usable due to 6 GHz NO-IR
*/
static int hostapd_is_usable_chan(struct hostapd_iface *iface,
- int frequency, int primary)
+ int frequency, int frequency_khz, int primary)
{
struct hostapd_channel_data *chan;
if (!iface->current_mode)
return 0;
- chan = hw_get_channel_freq(iface->current_mode->mode, frequency, NULL,
- iface->hw_features, iface->num_hw_features);
+ chan = hw_get_channel_freq(iface->current_mode->mode, frequency,
+ frequency_khz, NULL, iface->hw_features,
+ iface->num_hw_features);
if (!chan)
return 0;
@@ -847,7 +848,8 @@ static int hostapd_is_usable_chan(struct hostapd_iface *iface,
wpa_printf(MSG_INFO,
"Frequency %d (%s) not allowed for AP mode, flags: 0x%x%s%s",
- frequency, primary ? "primary" : "secondary",
+ frequency_khz ? frequency_khz : frequency,
+ primary ? "primary" : "secondary",
chan->flag,
chan->flag & HOSTAPD_CHAN_NO_IR ? " NO-IR" : "",
chan->flag & HOSTAPD_CHAN_RADAR ? " RADAR" : "");
@@ -874,7 +876,8 @@ static int hostapd_is_usable_edmg(struct hostapd_iface *iface)
if (!iface->current_mode)
return 0;
pri_chan = hw_get_channel_freq(iface->current_mode->mode,
- iface->freq, NULL,
+ iface->freq,
+ iface->freq_khz, NULL,
iface->hw_features,
iface->num_hw_features);
if (!pri_chan)
@@ -904,7 +907,7 @@ static int hostapd_is_usable_edmg(struct hostapd_iface *iface)
if (num_of_enabled > 4)
return 0;
- err = hostapd_is_usable_chan(iface, freq, 1);
+ err = hostapd_is_usable_chan(iface, freq, 0, 1);
if (err <= 0)
return err;
@@ -1005,8 +1008,10 @@ static int hostapd_is_usable_chans(struct hostapd_iface *iface)
if (!iface->current_mode)
return 0;
+
pri_chan = hw_get_channel_freq(iface->current_mode->mode,
- iface->freq, NULL,
+ iface->freq,
+ iface->freq_khz, NULL,
iface->hw_features,
iface->num_hw_features);
if (!pri_chan) {
@@ -1014,11 +1019,17 @@ static int hostapd_is_usable_chans(struct hostapd_iface *iface)
return 0;
}
- err = hostapd_is_usable_chan(iface, pri_chan->freq, 1);
+ err = hostapd_is_usable_chan(iface, pri_chan->freq,
+ pri_chan->freq_khz,
+ pri_chan->freq_khz ? 0 : 1);
if (err <= 0) {
wpa_printf(MSG_ERROR, "Primary frequency not allowed");
return err;
}
+
+ if (iface->conf->ieee80211ah)
+ return 1;
+
err = hostapd_is_usable_edmg(iface);
if (err <= 0)
return err;
@@ -1030,7 +1041,7 @@ static int hostapd_is_usable_chans(struct hostapd_iface *iface)
return 1;
err = hostapd_is_usable_chan(iface, iface->freq +
- iface->conf->secondary_channel * 20, 0);
+ iface->conf->secondary_channel * 20, 0, 0);
if (err > 0) {
if (iface->conf->secondary_channel == 1 &&
(pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40P))
@@ -1044,14 +1055,14 @@ static int hostapd_is_usable_chans(struct hostapd_iface *iface)
/* Both HT40+ and HT40- are set, pick a valid secondary channel */
secondary_freq = iface->freq + 20;
- err = hostapd_is_usable_chan(iface, secondary_freq, 0);
+ err = hostapd_is_usable_chan(iface, secondary_freq, 0, 0);
if (err > 0 && (pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40P)) {
iface->conf->secondary_channel = 1;
return 1;
}
secondary_freq = iface->freq - 20;
- err = hostapd_is_usable_chan(iface, secondary_freq, 0);
+ err = hostapd_is_usable_chan(iface, secondary_freq, 0, 0);
if (err > 0 && (pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40M)) {
iface->conf->secondary_channel = -1;
return 1;
@@ -1066,7 +1077,8 @@ static bool skip_mode(struct hostapd_iface *iface,
{
int chan;
- if (iface->freq > 0 && !hw_mode_get_channel(mode, iface->freq, &chan))
+ if ((iface->freq > 0 || iface->freq_khz > 0) &&
+ !hw_mode_get_channel(mode, iface->freq, iface->freq_khz, &chan))
return true;
if (is_6ghz_op_class(iface->conf->op_class) && iface->freq == 0 &&
@@ -1120,7 +1132,7 @@ int hostapd_determine_mode(struct hostapd_iface *iface)
static enum hostapd_chan_status
hostapd_check_chans(struct hostapd_iface *iface)
{
- if (iface->freq) {
+ if (iface->freq || iface->freq_khz) {
int err;
hostapd_determine_mode(iface);
@@ -1338,13 +1350,14 @@ int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan)
}
-int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq)
+int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq, int freq_khz)
{
int i, channel;
struct hostapd_hw_modes *mode;
if (hapd->iface->current_mode) {
channel = hw_get_chan(hapd->iface->current_mode->mode, freq,
+ freq_khz,
hapd->iface->hw_features,
hapd->iface->num_hw_features);
if (channel)
@@ -1357,7 +1370,7 @@ int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq)
return 0;
for (i = 0; i < hapd->iface->num_hw_features; i++) {
mode = &hapd->iface->hw_features[i];
- channel = hw_get_chan(mode->mode, freq,
+ channel = hw_get_chan(mode->mode, freq, freq_khz,
hapd->iface->hw_features,
hapd->iface->num_hw_features);
if (channel)
@@ -20,7 +20,7 @@ int hostapd_acs_completed(struct hostapd_iface *iface, int err);
int hostapd_select_hw_mode(struct hostapd_iface *iface);
const char * hostapd_hw_mode_txt(int mode);
int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan);
-int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq);
+int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq, int freq_khz);
int hostapd_check_ht_capab(struct hostapd_iface *iface);
int hostapd_check_edmg_capab(struct hostapd_iface *iface);
int hostapd_check_he_6ghz_capab(struct hostapd_iface *iface);
@@ -519,6 +519,12 @@ enum frame_encryption {
FRAME_ENCRYPTED = 1
};
+#define MHZ_TO_KHZ(x) ((x) * 1000)
+#define KHZ_TO_MHZ(x) ((x) / 1000)
+#define KHZ_TO_S1G_OFFSET(x) ((x) % 1000)
+/* If x (freq_khz) is 0 then print "MHz" else print "kHz" */
+#define KHZ_PRINT_FREQ_UNITS(x) (x) == 0 ? "MHz" : "kHz"
+
#define MAX_NUM_MLD_LINKS 15
enum sae_pwe {
@@ -41,14 +41,17 @@ struct hostapd_channel_data * hw_get_channel_chan(struct hostapd_hw_modes *mode,
struct hostapd_channel_data *
-hw_mode_get_channel(struct hostapd_hw_modes *mode, int freq, int *chan)
+hw_mode_get_channel(struct hostapd_hw_modes *mode, int freq,
+ int freq_khz, int *chan)
{
int i;
for (i = 0; i < mode->num_channels; i++) {
struct hostapd_channel_data *ch = &mode->channels[i];
-
- if (ch->freq == freq) {
+ if (freq_khz && (ch->freq_khz == freq_khz)) {
+ return ch;
+ }
+ if (freq && (ch->freq == freq)) {
if (chan)
*chan = ch->chan;
return ch;
@@ -60,8 +63,9 @@ hw_mode_get_channel(struct hostapd_hw_modes *mode, int freq, int *chan)
struct hostapd_channel_data *
-hw_get_channel_freq(enum hostapd_hw_mode mode, int freq, int *chan,
- struct hostapd_hw_modes *hw_features, int num_hw_features)
+hw_get_channel_freq(enum hostapd_hw_mode mode, int freq, int freq_khz,
+ int *chan, struct hostapd_hw_modes *hw_features,
+ int num_hw_features)
{
struct hostapd_channel_data *chan_data;
int i;
@@ -78,7 +82,8 @@ hw_get_channel_freq(enum hostapd_hw_mode mode, int freq, int *chan,
if (curr_mode->mode != mode)
continue;
- chan_data = hw_mode_get_channel(curr_mode, freq, chan);
+ chan_data = hw_mode_get_channel(curr_mode, freq,
+ freq_khz, chan);
if (chan_data)
return chan_data;
}
@@ -97,12 +102,13 @@ int hw_get_freq(struct hostapd_hw_modes *mode, int chan)
}
-int hw_get_chan(enum hostapd_hw_mode mode, int freq,
+int hw_get_chan(enum hostapd_hw_mode mode, int freq, int freq_khz,
struct hostapd_hw_modes *hw_features, int num_hw_features)
{
int chan;
- hw_get_channel_freq(mode, freq, &chan, hw_features, num_hw_features);
+ hw_get_channel_freq(mode, freq, freq_khz, &chan, hw_features,
+ num_hw_features);
return chan;
}
@@ -383,10 +389,12 @@ int check_40mhz_2g4(struct hostapd_hw_modes *mode,
int hostapd_set_freq_params(struct hostapd_freq_params *data,
enum hostapd_hw_mode mode,
- int freq, int channel, int enable_edmg,
+ int freq, int freq_khz,
+ int channel, int enable_edmg,
u8 edmg_channel, int ht_enabled,
int vht_enabled, int he_enabled,
- bool eht_enabled, int sec_channel_offset,
+ bool eht_enabled, int s1g_enabled,
+ int sec_channel_offset,
enum oper_chan_width oper_chwidth,
int center_segment0,
int center_segment1, u32 vht_caps,
@@ -400,11 +408,13 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
os_memset(data, 0, sizeof(*data));
data->mode = mode;
data->freq = freq;
+ data->freq_khz = freq_khz;
data->channel = channel;
data->ht_enabled = ht_enabled;
data->vht_enabled = vht_enabled;
data->he_enabled = he_enabled;
data->eht_enabled = eht_enabled;
+ data->s1g_enabled = s1g_enabled;
data->sec_channel_offset = sec_channel_offset;
data->center_freq1 = freq + sec_channel_offset * 10;
data->center_freq2 = 0;
@@ -15,14 +15,16 @@
struct hostapd_channel_data * hw_get_channel_chan(struct hostapd_hw_modes *mode,
int chan, int *freq);
struct hostapd_channel_data *
-hw_mode_get_channel(struct hostapd_hw_modes *mode, int freq, int *chan);
+hw_mode_get_channel(struct hostapd_hw_modes *mode, int freq,
+ int freq_khz, int *chan);
struct hostapd_channel_data *
-hw_get_channel_freq(enum hostapd_hw_mode mode, int freq, int *chan,
- struct hostapd_hw_modes *hw_features, int num_hw_features);
+hw_get_channel_freq(enum hostapd_hw_mode mode, int freq, int freq_khz,
+ int *chan, struct hostapd_hw_modes *hw_features,
+ int num_hw_features);
int hw_get_freq(struct hostapd_hw_modes *mode, int chan);
-int hw_get_chan(enum hostapd_hw_mode mode, int freq,
+int hw_get_chan(enum hostapd_hw_mode mode, int freq, int freq_khz,
struct hostapd_hw_modes *hw_features, int num_hw_features);
int allowed_ht40_channel_pair(enum hostapd_hw_mode mode,
@@ -37,10 +39,12 @@ int check_40mhz_2g4(struct hostapd_hw_modes *mode,
int sec_chan);
int hostapd_set_freq_params(struct hostapd_freq_params *data,
enum hostapd_hw_mode mode,
- int freq, int channel, int edmg, u8 edmg_channel,
+ int freq, int freq_khz,
+ int channel, int edmg, u8 edmg_channel,
int ht_enabled,
int vht_enabled, int he_enabled,
- bool eht_enabled, int sec_channel_offset,
+ bool eht_enabled, int s1g_enabled,
+ int sec_channel_offset,
enum oper_chan_width oper_chwidth,
int center_segment0,
int center_segment1, u32 vht_caps,
@@ -1381,6 +1381,10 @@ ieee80211_freq_to_channel_ext(unsigned int freq, int sec_channel,
/* TODO: more operating classes */
+ if (is_s1g_freq(MHZ_TO_KHZ(freq))) {
+ return HOSTAPD_MODE_IEEE80211A;
+ }
+
if (sec_channel > 1 || sec_channel < -1)
return NUM_HOSTAPD_MODES;
@@ -2834,6 +2838,15 @@ int get_6ghz_sec_channel(int channel)
}
+bool is_s1g_freq(int freq_khz)
+{
+ if (freq_khz < 1000000 && freq_khz > 0)
+ return true;
+
+ return false;
+}
+
+
int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep,
size_t nei_rep_len)
{
@@ -283,6 +283,8 @@ bool is_6ghz_op_class(u8 op_class);
bool is_6ghz_psc_frequency(int freq);
int get_6ghz_sec_channel(int channel);
+bool is_s1g_freq(int freq_khz);
+
int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep,
size_t nei_rep_len);
@@ -119,6 +119,11 @@ struct hostapd_channel_data {
*/
int freq;
+ /**
+ * freq_khz - Frequency in kHz
+ */
+ int freq_khz;
+
/**
* flag - Channel flags (HOSTAPD_CHAN_*)
*/
@@ -778,6 +783,11 @@ struct hostapd_freq_params {
*/
int freq;
+ /**
+ * freq_khz - Primary channel center frequency in kHz
+ */
+ int freq_khz;
+
/**
* channel - Channel number
*/
@@ -807,6 +817,11 @@ struct hostapd_freq_params {
*/
int he_enabled;
+ /**
+ * s1g_enabled - Whether S1G is enabled
+ */
+ int s1g_enabled;
+
/**
* center_freq1 - Segment 0 center frequency in MHz
*
@@ -6446,6 +6461,7 @@ union wpa_event_data {
*/
struct ch_switch {
int freq;
+ int freq_khz;
int ht_enabled;
int ch_offset;
enum chan_width ch_width;
@@ -6548,6 +6564,7 @@ union wpa_event_data {
*/
struct acs_selected_channels {
unsigned int pri_freq;
+ unsigned int pri_freq_khz;
unsigned int sec_freq;
u8 edmg_channel;
u8 vht_seg0_center_ch;
@@ -4862,7 +4862,20 @@ static int nl80211_put_freq_params(struct nl_msg *msg,
u8 channel;
wpa_printf(MSG_DEBUG, " * freq=%d", freq->freq);
- if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq->freq))
+ if (is_s1g_freq(freq->freq_khz)) {
+ if (nla_put_u32(msg,
+ NL80211_ATTR_WIPHY_FREQ,
+ KHZ_TO_MHZ(freq->freq_khz)))
+ return -ENOBUFS;
+ } else {
+ if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq->freq))
+ return -ENOBUFS;
+ }
+
+ wpa_printf(MSG_DEBUG, " * freq_offset=%d",
+ KHZ_TO_S1G_OFFSET(freq->freq_khz));
+ if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET,
+ KHZ_TO_S1G_OFFSET(freq->freq_khz)))
return -ENOBUFS;
wpa_printf(MSG_DEBUG, " * eht_enabled=%d", freq->eht_enabled);
@@ -5027,6 +5040,14 @@ static int wpa_driver_nl80211_set_ap(void *priv,
nla_put(msg, NL80211_ATTR_SSID, params->ssid_len, params->ssid))
goto fail;
+ if (is_s1g_freq(params->freq->freq_khz)) {
+ if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
+ KHZ_TO_MHZ(params->freq->freq_khz)) ||
+ nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET,
+ KHZ_TO_S1G_OFFSET(params->freq->freq_khz)))
+ goto fail;
+ }
+
if (params->mld_ap) {
wpa_printf(MSG_DEBUG, "nl80211: link_id=%u",
params->mld_link_id);
@@ -1652,6 +1652,8 @@ static void phy_info_freq(struct hostapd_hw_modes *mode,
os_memset(chan, 0, sizeof(*chan));
chan->freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]);
+ chan->freq_khz = MHZ_TO_KHZ(chan->freq) +
+ nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_OFFSET]);
chan->flag = 0;
chan->allowed_bw = ~0;
chan->dfs_cac_ms = 0;
@@ -2134,7 +2136,10 @@ wpa_driver_nl80211_postprocess_modes(struct hostapd_hw_modes *modes,
for (m = 0; m < *num_modes; m++) {
if (!modes[m].num_channels)
continue;
- if (modes[m].channels[0].freq < 2000) {
+ if (modes[m].channels[0].freq_khz < 1000000 &&
+ modes[m].channels[0].freq_khz > 0){
+ modes[m].mode = HOSTAPD_MODE_IEEE80211A;
+ } else if (modes[m].channels[0].freq < 2000) {
modes[m].num_channels = 0;
continue;
} else if (modes[m].channels[0].freq < 4000) {
@@ -1198,7 +1198,8 @@ static int calculate_chan_offset(int width, int freq, int cf1, int cf2)
static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv,
struct nlattr *ifindex, struct nlattr *link,
- struct nlattr *freq, struct nlattr *type,
+ struct nlattr *freq, struct nlattr *freq_off,
+ struct nlattr *type,
struct nlattr *bw, struct nlattr *cf1,
struct nlattr *cf2,
struct nlattr *punct_bitmap,
@@ -1255,6 +1256,8 @@ static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv,
os_memset(&data, 0, sizeof(data));
data.ch_switch.freq = nla_get_u32(freq);
+ data.ch_switch.freq_khz = MHZ_TO_KHZ(data.ch_switch.freq) +
+ nla_get_u32(freq_off);
data.ch_switch.ht_enabled = ht_enabled;
data.ch_switch.ch_offset = chan_offset;
if (punct_bitmap)
@@ -1631,7 +1634,8 @@ nl80211_get_mld_link_by_freq(struct i802_bss *bss, unsigned int freq)
static void mlme_event(struct i802_bss *bss,
enum nl80211_commands cmd, struct nlattr *frame,
struct nlattr *addr, struct nlattr *timed_out,
- struct nlattr *freq, struct nlattr *ack,
+ struct nlattr *freq, struct nlattr *freq_offset,
+ struct nlattr *ack,
struct nlattr *cookie, struct nlattr *sig,
struct nlattr *wmm, struct nlattr *req_ie,
struct nlattr *link)
@@ -3878,7 +3882,9 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
case NL80211_CMD_UNPROT_DISASSOCIATE:
mlme_event(bss, cmd, tb[NL80211_ATTR_FRAME],
tb[NL80211_ATTR_MAC], tb[NL80211_ATTR_TIMED_OUT],
- tb[NL80211_ATTR_WIPHY_FREQ], tb[NL80211_ATTR_ACK],
+ tb[NL80211_ATTR_WIPHY_FREQ],
+ tb[NL80211_ATTR_WIPHY_FREQ_OFFSET],
+ tb[NL80211_ATTR_ACK],
tb[NL80211_ATTR_COOKIE],
tb[NL80211_ATTR_RX_SIGNAL_DBM],
tb[NL80211_ATTR_STA_WME],
@@ -3907,6 +3913,7 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
tb[NL80211_ATTR_IFINDEX],
tb[NL80211_ATTR_MLO_LINK_ID],
tb[NL80211_ATTR_WIPHY_FREQ],
+ tb[NL80211_ATTR_WIPHY_FREQ_OFFSET],
tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE],
tb[NL80211_ATTR_CHANNEL_WIDTH],
tb[NL80211_ATTR_CENTER_FREQ1],
@@ -3919,6 +3926,7 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
tb[NL80211_ATTR_IFINDEX],
tb[NL80211_ATTR_MLO_LINK_ID],
tb[NL80211_ATTR_WIPHY_FREQ],
+ tb[NL80211_ATTR_WIPHY_FREQ_OFFSET],
tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE],
tb[NL80211_ATTR_CHANNEL_WIDTH],
tb[NL80211_ATTR_CENTER_FREQ1],
@@ -4108,7 +4116,9 @@ int process_bss_event(struct nl_msg *msg, void *arg)
case NL80211_CMD_FRAME_TX_STATUS:
mlme_event(bss, gnlh->cmd, tb[NL80211_ATTR_FRAME],
tb[NL80211_ATTR_MAC], tb[NL80211_ATTR_TIMED_OUT],
- tb[NL80211_ATTR_WIPHY_FREQ], tb[NL80211_ATTR_ACK],
+ tb[NL80211_ATTR_WIPHY_FREQ],
+ tb[NL80211_ATTR_WIPHY_FREQ_OFFSET],
+ tb[NL80211_ATTR_ACK],
tb[NL80211_ATTR_COOKIE],
tb[NL80211_ATTR_RX_SIGNAL_DBM],
tb[NL80211_ATTR_STA_WME], NULL,
@@ -1838,8 +1838,8 @@ int ap_ctrl_iface_chanswitch(struct wpa_supplicant *wpa_s, const char *pos)
#endif /* CONFIG_CTRL_IFACE */
-void wpas_ap_ch_switch(struct wpa_supplicant *wpa_s, int freq, int ht,
- int offset, int width, int cf1, int cf2,
+void wpas_ap_ch_switch(struct wpa_supplicant *wpa_s, int freq, int freq_khz,
+ int ht, int offset, int width, int cf1, int cf2,
u16 punct_bitmap, int finished)
{
struct hostapd_iface *iface = wpa_s->ap_iface;
@@ -1849,9 +1849,12 @@ void wpas_ap_ch_switch(struct wpa_supplicant *wpa_s, int freq, int ht,
if (!iface)
return;
wpa_s->assoc_freq = freq;
- if (wpa_s->current_ssid)
+ wpa_s->assoc_freq_khz = freq_khz;
+ if (wpa_s->current_ssid) {
wpa_s->current_ssid->frequency = freq;
- hostapd_event_ch_switch(iface->bss[0], freq, ht,
+ wpa_s->current_ssid->frequency_khz = freq_khz;
+ }
+ hostapd_event_ch_switch(iface->bss[0], freq, freq_khz, ht,
offset, width, cf1, cf2, punct_bitmap,
finished);
}
@@ -524,6 +524,11 @@ struct wpa_ssid {
*/
int frequency;
+ /**
+ * frequency_khz - Channel frequency in kilohertz (kHz)
+ */
+ int frequency_khz;
+
/**
* enable_edmg - Enable EDMG feature in STA/AP mode
*
@@ -5739,6 +5739,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
wpa_s->current_ssid->mode ==
WPAS_MODE_P2P_GROUP_FORMATION) {
wpas_ap_ch_switch(wpa_s, data->ch_switch.freq,
+ data->ch_switch.freq_khz,
data->ch_switch.ht_enabled,
data->ch_switch.ch_offset,
data->ch_switch.ch_width,
@@ -219,13 +219,14 @@ static int wpas_mesh_update_freq_params(struct wpa_supplicant *wpa_s)
¶ms->freq,
ifmsh->conf->hw_mode,
ifmsh->freq,
+ ifmsh->freq_khz,
ifmsh->conf->channel,
ifmsh->conf->enable_edmg,
ifmsh->conf->edmg_channel,
ifmsh->conf->ieee80211n,
ifmsh->conf->ieee80211ac,
ifmsh->conf->ieee80211ax,
- ifmsh->conf->ieee80211be,
+ ifmsh->conf->ieee80211ah,
ifmsh->conf->secondary_channel,
hostapd_get_oper_chwidth(ifmsh->conf),
hostapd_get_oper_centr_freq_seg0_idx(ifmsh->conf),
@@ -2997,10 +2997,11 @@ static bool ibss_mesh_select_80_160mhz(struct wpa_supplicant *wpa_s,
skip_80mhz:
if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
+ freq->freq_khz,
freq->channel, ssid->enable_edmg,
ssid->edmg_channel, freq->ht_enabled,
freq->vht_enabled, freq->he_enabled,
- freq->eht_enabled,
+ freq->eht_enabled, freq->s1g_enabled,
freq->sec_channel_offset,
chwidth, seg0, seg1, vht_caps,
&mode->he_capab[ieee80211_mode],
@@ -3027,6 +3028,7 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
bool is_6ghz;
freq->freq = ssid->frequency;
+ freq->freq_khz = ssid->frequency_khz;
if (ssid->mode == WPAS_MODE_IBSS && !ssid->fixed_freq) {
struct wpa_bss *bss = ibss_find_existing_bss(wpa_s, ssid);
@@ -3043,7 +3045,7 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
if (wpa_s->hw.modes[i].mode == hw_mode &&
- hw_mode_get_channel(&wpa_s->hw.modes[i], freq->freq,
+ hw_mode_get_channel(&wpa_s->hw.modes[i], freq->freq, freq->freq_khz,
NULL) != NULL) {
mode = &wpa_s->hw.modes[i];
break;