wifi: add support for new "6GHz" band

Until now the Wi-Fi bands were named after the first 802.11 standard
that introduced them: "a" for 5GHz introduced in 802.11a and "bg" for
2.4GHz introduced in 802.11b/g. With new bands added, this naming
scheme doesn't sound very intuitive to remember for users. Furthermore
we have now 6GHz that is introduced by 802.11ax (Wi-Fi 6), but the
compatible devices can use all three the bands (2.4, 5, 6 GHz).

For the 6 GHz band, simply name it "6GHz".

Co-authored-by: Beniamino Galvani <bgalvani@redhat.com>
This commit is contained in:
Thomas Makin 2025-11-28 15:19:59 +01:00 committed by Beniamino Galvani
parent ef84a54c43
commit 701449358b
25 changed files with 425 additions and 181 deletions

View file

@ -1718,6 +1718,7 @@
<group choice='req'>
<arg choice='plain'>a</arg>
<arg choice='plain'>bg</arg>
<arg choice='plain'>6GHz</arg>
</group>
</arg>
<arg><option>channel</option> <replaceable>channel</replaceable></arg>

View file

@ -3257,8 +3257,10 @@ act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason)
static void
ensure_hotspot_frequency(NMDeviceWifi *self, NMSettingWireless *s_wifi, NMWifiAP *ap)
{
guint32 a_freqs[] = {5180, 5200, 5220, 5745, 5765, 5785, 5805, 0};
guint32 bg_freqs[] = {2412, 2437, 2462, 2472, 0};
guint32 freqs_a[] = {5180, 5200, 5220, 5745, 5765, 5785, 5805, 0};
guint32 freqs_bg[] = {2412, 2437, 2462, 2472, 0};
guint32 freqs_6ghz[] =
{5955, 5975, 5995, 6015, 6035, 6055, 6075, 6095, 6755, 6775, 6795, 6815, 0};
guint32 *rnd_freqs;
guint rnd_freqs_len;
NMDevice *device = NM_DEVICE(self);
@ -3269,7 +3271,7 @@ ensure_hotspot_frequency(NMDeviceWifi *self, NMSettingWireless *s_wifi, NMWifiAP
guint l;
nm_assert(ap);
nm_assert(NM_IN_STRSET(band, NULL, "a", "bg"));
nm_assert(NM_IN_STRSET(band, NULL, "a", "bg", "6GHz"));
if (nm_wifi_ap_get_freq(ap))
return;
@ -3303,11 +3305,14 @@ ensure_hotspot_frequency(NMDeviceWifi *self, NMSettingWireless *s_wifi, NMWifiAP
}
if (nm_streq0(band, "a")) {
rnd_freqs = a_freqs;
rnd_freqs_len = G_N_ELEMENTS(a_freqs) - 1;
rnd_freqs = freqs_a;
rnd_freqs_len = G_N_ELEMENTS(freqs_a) - 1;
} else if (nm_streq0(band, "6GHz")) {
rnd_freqs = freqs_6ghz;
rnd_freqs_len = G_N_ELEMENTS(freqs_6ghz) - 1;
} else {
rnd_freqs = bg_freqs;
rnd_freqs_len = G_N_ELEMENTS(bg_freqs) - 1;
rnd_freqs = freqs_bg;
rnd_freqs_len = G_N_ELEMENTS(freqs_bg) - 1;
}
/* shuffle the frequencies (inplace). The idea is to choose

View file

@ -574,16 +574,6 @@ nm_wifi_ap_to_string(const NMWifiAP *self, char *str_buf, gulong buf_len, gint64
return str_buf;
}
static guint
freq_to_band(guint32 freq)
{
if (freq >= 4915 && freq <= 5825)
return 5;
else if (freq >= 2412 && freq <= 2484)
return 2;
return 0;
}
gboolean
nm_wifi_ap_check_compatible(NMWifiAP *self, NMConnection *connection)
{
@ -631,12 +621,12 @@ nm_wifi_ap_check_compatible(NMWifiAP *self, NMConnection *connection)
band = nm_setting_wireless_get_band(s_wireless);
if (band) {
guint ap_band = freq_to_band(priv->freq);
const char *ap_band = nm_utils_wifi_freq_to_band(priv->freq);
if (!strcmp(band, "a") && ap_band != 5)
return FALSE;
else if (!strcmp(band, "bg") && ap_band != 2)
if (!nm_streq(band, ap_band))
return FALSE;
return TRUE;
}
channel = nm_setting_wireless_get_channel(s_wireless);

View file

@ -4401,7 +4401,7 @@ make_wireless_setting(shvarFile *ifcfg, GError **error)
NMSettingWireless *s_wireless;
const char *cvalue;
char *value = NULL;
gint64 chan = 0;
guint64 chan = 0;
NMSettingMacRandomization mac_randomization;
NMSettingWirelessPowersave powersave = NM_SETTING_WIRELESS_POWERSAVE_DEFAULT;
NMTernary ternary;
@ -4502,7 +4502,7 @@ make_wireless_setting(shvarFile *ifcfg, GError **error)
value = svGetValueStr_cp(ifcfg, "CHANNEL");
if (value) {
chan = _nm_utils_ascii_str_to_int64(value, 10, 1, 196, 0);
chan = _nm_utils_ascii_str_to_int64(value, 10, 1, _NM_WIFI_CHANNEL_MAX, 0);
if (chan == 0) {
g_set_error(error,
NM_SETTINGS_ERROR,
@ -4518,45 +4518,48 @@ make_wireless_setting(shvarFile *ifcfg, GError **error)
value = svGetValueStr_cp(ifcfg, "BAND");
if (value) {
if (!strcmp(value, "a")) {
if (chan && chan <= 14) {
if (!NM_IN_STRSET(value, "a", "bg", "6GHz")) {
g_set_error(error,
NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_INVALID_CONNECTION,
"Band '%s' invalid for channel %u",
value,
(guint32) chan);
g_free(value);
goto error;
}
} else if (!strcmp(value, "bg")) {
if (chan && chan > 14) {
g_set_error(error,
NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_INVALID_CONNECTION,
"Band '%s' invalid for channel %u",
value,
(guint32) chan);
g_free(value);
goto error;
}
} else {
g_set_error(error,
NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_INVALID_CONNECTION,
"Invalid wireless band '%s'",
"Band '%s' invalid",
value);
g_free(value);
goto error;
}
if (chan) {
if (!nm_utils_wifi_is_channel_valid(chan, value)) {
g_set_error(error,
NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_INVALID_CONNECTION,
"Band '%s' invalid for channel %u",
value,
(guint32) chan);
g_free(value);
goto error;
}
}
g_object_set(s_wireless, NM_SETTING_WIRELESS_BAND, value, NULL);
g_free(value);
} else if (chan > 0) {
if (chan > 14)
if (chan > _NM_WIFI_CHANNEL_MAX_5GHZ) {
g_set_error(error,
NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_INVALID_CONNECTION,
"Setting channel without band is ambiguous and deprecated. Not supported "
"for 6GHz.");
g_free(value);
goto error;
} else if (chan > _NM_WIFI_CHANNEL_MAX_2GHZ) {
PARSE_WARNING(
"Setting channel without band is ambiguous and deprecated. Assuming band 'a'.");
g_object_set(s_wireless, NM_SETTING_WIRELESS_BAND, "a", NULL);
else
} else {
g_object_set(s_wireless, NM_SETTING_WIRELESS_BAND, "bg", NULL);
}
}
value = svGetValueStr_cp(ifcfg, "MTU");
if (value) {

View file

@ -849,7 +849,7 @@ write_wireless_setting(NMConnection *connection,
GBytes *ssid;
const guint8 *ssid_data;
gsize ssid_len;
const char *mode, *bssid;
const char *mode, *bssid, *band;
const char *device_mac, *cloned_mac;
guint32 mtu, chan, i;
gboolean adhoc = FALSE, hex_ssid = FALSE;
@ -968,9 +968,11 @@ write_wireless_setting(NMConnection *connection,
chan = nm_setting_wireless_get_channel(s_wireless);
if (chan) {
svSetValueInt64(ifcfg, "CHANNEL", chan);
} else {
/* Band only set if channel is not, since channel implies band */
svSetValueStr(ifcfg, "BAND", nm_setting_wireless_get_band(s_wireless));
}
band = nm_setting_wireless_get_band(s_wireless);
if (band) {
svSetValueStr(ifcfg, "BAND", band);
}
bssid = nm_setting_wireless_get_bssid(s_wireless);

View file

@ -1,6 +1,7 @@
ESSID=MySSID
MODE=Ap
CHANNEL=196
CHANNEL=52
BAND=a
MAC_ADDRESS_RANDOMIZATION=default
AP_ISOLATION=yes
TYPE=Wireless

View file

@ -0,0 +1,18 @@
ESSID="Test SSID"
MODE=Managed
BAND=6GHz
MAC_ADDRESS_RANDOMIZATION=default
TYPE=Wireless
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=dhcp
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=default
NAME="Test Write Wi-Fi Band 6GHz"
UUID=${UUID}
ONBOOT=yes

View file

@ -13,6 +13,6 @@ IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=default
NAME="Test Write Wi-Fi Band A"
NAME="Test Write Wi-Fi Band A - 5GHz"
UUID=${UUID}
ONBOOT=yes

View file

@ -0,0 +1,13 @@
TYPE=Wireless
DEVICE=eth2
HWADDR=00:16:41:11:22:33
NM_CONTROLLED=yes
BOOTPROTO=dhcp
ESSID=blahblah
BAND=6GHz
MODE=Managed
RATE=auto
ONBOOT=yes
USERCTL=yes
PEERDNS=yes
IPV6INIT=no

View file

@ -0,0 +1,9 @@
TYPE=Wireless
DEVICE=eth2
HWADDR=00:16:41:11:22:33
BOOTPROTO=dhcp
ESSID=blahblah
CHANNEL=14
BAND=6GHz
MODE=Managed

View file

@ -3991,7 +3991,7 @@ test_write_wifi_band_a(void)
s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION);
g_object_set(s_con,
NM_SETTING_CONNECTION_ID,
"Test Write Wi-Fi Band A",
"Test Write Wi-Fi Band A - 5GHz",
NM_SETTING_CONNECTION_UUID,
nm_uuid_generate_random_str_a(),
NM_SETTING_CONNECTION_TYPE,
@ -4012,7 +4012,7 @@ test_write_wifi_band_a(void)
_writer_new_connec_exp(connection,
TEST_SCRATCH_DIR,
TEST_IFCFG_DIR "/ifcfg-Test_Write_WiFi_Band_A.cexpected",
TEST_IFCFG_DIR "/ifcfg-Test_Write_WiFi_Band_a.cexpected",
&testfile);
f = _svOpenFile(testfile);
@ -4024,6 +4024,77 @@ test_write_wifi_band_a(void)
nmtst_assert_connection_equals(connection, TRUE, reread, FALSE);
}
static void
test_read_wifi_band_6ghz(void)
{
gs_unref_object NMConnection *connection = NULL;
NMSettingConnection *s_con;
NMSettingWireless *s_wifi;
connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wifi-band-6ghz",
NULL,
TYPE_WIRELESS,
NULL);
s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION);
g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con),
==,
NM_SETTING_WIRELESS_SETTING_NAME);
s_wifi = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS);
g_assert_cmpstr(nm_setting_wireless_get_band(s_wifi), ==, "6GHz");
}
static void
test_write_wifi_band_6ghz(void)
{
nmtst_auto_unlinkfile char *testfile = NULL;
gs_unref_object NMConnection *connection = NULL;
gs_unref_object NMConnection *reread = NULL;
NMSettingConnection *s_con;
NMSettingWireless *s_wifi;
shvarFile *f;
gs_unref_bytes GBytes *ssid =
nmtst_gbytes_from_arr(0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x53, 0x49, 0x44);
connection = nm_simple_connection_new();
s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION);
g_object_set(s_con,
NM_SETTING_CONNECTION_ID,
"Test Write Wi-Fi Band 6GHz",
NM_SETTING_CONNECTION_UUID,
nm_uuid_generate_random_str_a(),
NM_SETTING_CONNECTION_TYPE,
NM_SETTING_WIRELESS_SETTING_NAME,
NULL);
s_wifi = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS);
g_object_set(s_wifi,
NM_SETTING_WIRELESS_SSID,
ssid,
NM_SETTING_WIRELESS_MODE,
"infrastructure",
NM_SETTING_WIRELESS_BAND,
"6GHz",
NULL);
nmtst_assert_connection_verifies(connection);
_writer_new_connec_exp(connection,
TEST_SCRATCH_DIR,
TEST_IFCFG_DIR "/ifcfg-Test_Write_WiFi_Band_6ghz.cexpected",
&testfile);
f = _svOpenFile(testfile);
_svGetValue_check(f, "BAND", "6GHz");
svCloseFile(f);
reread = _connection_from_file(testfile, NULL, TYPE_WIRELESS, NULL);
nmtst_assert_connection_equals(connection, TRUE, reread, FALSE);
}
static void
test_write_wifi_ap_mode(void)
{
@ -4055,7 +4126,7 @@ test_write_wifi_ap_mode(void)
NM_SETTING_WIRELESS_BAND,
"a",
NM_SETTING_WIRELESS_CHANNEL,
(guint) 196,
(guint) 52,
NM_SETTING_WIRELESS_AP_ISOLATION,
NM_TERNARY_TRUE,
NULL);
@ -4072,6 +4143,18 @@ test_write_wifi_ap_mode(void)
nmtst_assert_connection_equals(connection, TRUE, reread, FALSE);
}
static void
test_read_wifi_band_6ghz_channel_mismatch(void)
{
gs_free_error GError *error = NULL;
_connection_from_file_fail(TEST_IFCFG_DIR "/ifcfg-test-wifi-band-6ghz-channel-mismatch",
NULL,
TYPE_WIRELESS,
&error);
g_assert_error(error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION);
}
static void
test_read_wifi_band_a_channel_mismatch(void)
{
@ -10680,6 +10763,9 @@ main(int argc, char **argv)
test_read_wifi_band_a_channel_mismatch);
g_test_add_func(TPATH "wifi/read-band-bg-channel-mismatch",
test_read_wifi_band_bg_channel_mismatch);
g_test_add_func(TPATH "wifi/read-band-6ghz", test_read_wifi_band_6ghz);
g_test_add_func(TPATH "wifi/read-band-6ghz-channel-mismatch",
test_read_wifi_band_6ghz_channel_mismatch);
g_test_add_func(TPATH "wifi/read-hidden", test_read_wifi_hidden);
nmtst_add_test_func(TPATH "wifi/read-mac-random-always",
@ -10852,6 +10938,7 @@ main(int argc, char **argv)
test_write_wifi_wpa_then_wep_with_perms);
g_test_add_func(TPATH "wifi/write-hidden", test_write_wifi_hidden);
g_test_add_func(TPATH "wifi/write-band-a", test_write_wifi_band_a);
g_test_add_func(TPATH "wifi/write-band-6ghz", test_write_wifi_band_6ghz);
g_test_add_func(TPATH "wifi/write-ap-mode", test_write_wifi_ap_mode);
g_test_add_func(TPATH "s390/read-qeth-static", test_read_wired_qeth_static);

View file

@ -363,14 +363,24 @@ nm_supplicant_config_get_blobs(NMSupplicantConfig *self)
}
static const char *
wifi_freqs_to_string(gboolean bg_band)
wifi_freqs_to_string(const char *band)
{
static const char *str_2ghz = NULL;
static const char *str_5ghz = NULL;
static const char *str_6ghz = NULL;
const char **f_p;
const char *f;
f_p = bg_band ? &str_2ghz : &str_5ghz;
if (nm_streq0(band, "a"))
f_p = &str_5ghz;
else if (nm_streq0(band, "bg"))
f_p = &str_2ghz;
else if (nm_streq0(band, "6GHz"))
f_p = &str_6ghz;
else {
nm_assert_not_reached();
return NULL;
}
again:
f = g_atomic_pointer_get(f_p);
@ -380,7 +390,13 @@ again:
const guint *freqs;
int i;
freqs = bg_band ? nm_utils_wifi_2ghz_freqs() : nm_utils_wifi_5ghz_freqs();
if (f_p == &str_2ghz)
freqs = nm_utils_wifi_2ghz_freqs();
else if (f_p == &str_5ghz)
freqs = nm_utils_wifi_5ghz_freqs();
else
freqs = nm_utils_wifi_6ghz_freqs();
for (i = 0; freqs[i]; i++) {
if (i > 0)
nm_str_buf_append_c(&strbuf, ' ');
@ -523,15 +539,24 @@ get_ap_params(guint freq,
guint channel;
guint center_channel = 0;
/* Determine the center channel according to the table at
* https://en.wikipedia.org/wiki/List_of_WLAN_channels */
if (freq > 5950) {
/* 6 GHz */
channel = (freq - 5950) / 5;
channel = ((channel - 1) / 16) * 16 + 7;
*out_ht40 = 1;
*out_max_oper_chwidth = 1;
*out_center_freq = 5950 + 5 * channel;
} else {
/* 5 GHz */
if (freq < 5000) {
/* the setting is not valid */
nm_assert_not_reached();
return;
}
/* Determine the center channel according to the table at
* https://en.wikipedia.org/wiki/List_of_WLAN_channels */
channel = (freq - 5000) / 5;
if (channel >= 36 && channel <= 48)
@ -554,7 +579,7 @@ get_ap_params(guint freq,
*out_max_oper_chwidth = 1;
*out_center_freq = 5000 + 5 * center_channel;
}
}
return;
}
@ -701,10 +726,7 @@ nm_supplicant_config_add_setting_wireless(NMSupplicantConfig *self,
} else {
const char *freqs = NULL;
if (nm_streq(band, "a"))
freqs = wifi_freqs_to_string(FALSE);
else if (nm_streq(band, "bg"))
freqs = wifi_freqs_to_string(TRUE);
freqs = wifi_freqs_to_string(band);
if (freqs
&& !nm_supplicant_config_add_option(self,

View file

@ -6,6 +6,7 @@
#include "src/core/nm-default-daemon.h"
#include "nm-supplicant-settings-verify.h"
#include "libnm-core-aux-intern/nm-libnm-core-utils.h"
#include <stdio.h>
#include <stdlib.h>
@ -71,7 +72,7 @@ static const struct Opt opt_table[] = {
OPT_BYTES("engine_id", 0),
OPT_INT("fragment_size", 1, 2000),
OPT_KEYWORD("freq_list", NULL),
OPT_INT("frequency", 2412, 5825),
OPT_INT("frequency", _NM_WIFI_FREQ_MIN, _NM_WIFI_FREQ_MAX),
OPT_KEYWORD("group", NM_MAKE_STRV("CCMP", "TKIP", "WEP104", "WEP40", "GCMP-256", )),
OPT_INT("ht40", 0, 1),
OPT_BYTES("identity", 0),

View file

@ -2093,3 +2093,8 @@ global:
nm_utils_copy_cert_as_user;
nm_vpn_plugin_info_supports_safe_private_file_access;
} libnm_1_54_0;
libnm_1_58_0 {
global:
nm_utils_wifi_6ghz_freqs;
} libnm_1_56_0;

View file

@ -18,6 +18,7 @@
#include "nm-dbus-interface.h"
#include "nm-object-private.h"
#include "libnm-core-aux-intern/nm-libnm-core-utils.h"
/*****************************************************************************/
@ -338,11 +339,14 @@ nm_access_point_connection_valid(NMAccessPoint *ap, NMConnection *connection)
ap_freq = nm_access_point_get_frequency(ap);
if (ap_freq) {
setting_band = nm_setting_wireless_get_band(s_wifi);
if (g_strcmp0(setting_band, "a") == 0) {
if (ap_freq < 4915 || ap_freq > 5825)
if (nm_streq0(setting_band, "a")) {
if (ap_freq < _NM_WIFI_FREQ_MIN_5GHZ || ap_freq > _NM_WIFI_FREQ_MAX_5GHZ)
return FALSE;
} else if (g_strcmp0(setting_band, "bg") == 0) {
if (ap_freq < 2412 || ap_freq > 2484)
} else if (nm_streq0(setting_band, "bg")) {
if (ap_freq < _NM_WIFI_FREQ_MIN_2GHZ || ap_freq > _NM_WIFI_FREQ_MAX_2GHZ)
return FALSE;
} else if (nm_streq0(setting_band, "6Ghz")) {
if (ap_freq < _NM_WIFI_FREQ_MIN_6GHZ || ap_freq > _NM_WIFI_FREQ_MAX_6GHZ)
return FALSE;
}

View file

@ -342,4 +342,23 @@ const char *nm_dns_uri_normalize(int addr_family, const char *str, char **out_fr
gboolean nm_setting_ovs_other_config_check_key(const char *key, GError **error);
gboolean nm_setting_ovs_other_config_check_val(const char *val, GError **error);
/*****************************************************************************/
/* Wi-Fi frequencies range for each band */
#define _NM_WIFI_FREQ_MIN_2GHZ 2412
#define _NM_WIFI_FREQ_MAX_2GHZ 2484
#define _NM_WIFI_FREQ_MIN_5GHZ 4915
#define _NM_WIFI_FREQ_MAX_5GHZ 5885
#define _NM_WIFI_FREQ_MIN_6GHZ 5955
#define _NM_WIFI_FREQ_MAX_6GHZ 7115
#define _NM_WIFI_FREQ_MIN _NM_WIFI_FREQ_MIN_2GHZ
#define _NM_WIFI_FREQ_MAX _NM_WIFI_FREQ_MAX_6GHZ
/* Max Wi-Fi channel for each band */
#define _NM_WIFI_CHANNEL_MAX_2GHZ 14
#define _NM_WIFI_CHANNEL_MAX_5GHZ 177
#define _NM_WIFI_CHANNEL_MAX_6GHZ 233
#define _NM_WIFI_CHANNEL_MAX _NM_WIFI_CHANNEL_MAX_6GHZ
#endif /* __NM_LIBNM_SHARED_UTILS_H__ */

View file

@ -1086,7 +1086,7 @@ verify(NMSetting *setting, NMConnection *connection, GError **error)
NM_SETTING_WIRELESS_MODE_AP,
NM_SETTING_WIRELESS_MODE_MESH,
NULL};
const char *valid_bands[] = {"a", "bg", NULL};
const char *valid_bands[] = {"a", "bg", "6GHz", NULL};
guint i;
gsize length;
GError *local = NULL;
@ -1363,11 +1363,11 @@ verify(NMSetting *setting, NMConnection *connection, GError **error)
}
if (priv->channel_width == NM_SETTING_WIRELESS_CHANNEL_WIDTH_80MHZ
&& !nm_streq0(priv->band, "a")) {
&& !NM_IN_STRSET(priv->band, "a", "6GHz")) {
g_set_error_literal(error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
_("80MHz channels are only supported in the 5GHz band"));
_("80MHz channels are only supported in the 'a' and '6GHz' bands"));
g_prefix_error(error,
"%s.%s: ",
NM_SETTING_WIRELESS_SETTING_NAME,
@ -1636,17 +1636,18 @@ nm_setting_wireless_class_init(NMSettingWirelessClass *klass)
/**
* NMSettingWireless:band:
*
* 802.11 frequency band of the network. One of "a" for 5GHz 802.11a or
* "bg" for 2.4GHz 802.11. This will lock associations to the Wi-Fi network
* to the specific band, i.e. if "a" is specified, the device will not
* associate with the same network in the 2.4GHz band even if the network's
* settings are compatible. This setting depends on specific driver
* capability and may not work with all drivers.
* 802.11 frequency band of the network. One of "a" for 5GHz,
* "bg" for 2.4GHz or "6GHz". This will lock associations to the
* Wi-Fi network to the specific band, i.e. if "a" is specified,
* the device will not associate with the same network in the
* 2.4GHz (bg) or 6GHz bands even if the network's settings are
* compatible. This setting depends on specific driver capability
* and may not work with all drivers.
**/
/* ---ifcfg-rh---
* property: band
* variable: BAND(+)
* values: a, bg
* values: a, bg, 6GHz
* description: BAND alone is honored, but CHANNEL overrides BAND since it
* implies a band.
* example: BAND=bg
@ -1673,8 +1674,6 @@ nm_setting_wireless_class_init(NMSettingWirelessClass *klass)
* property: channel
* variable: CHANNEL
* description: Channel used for the Wi-Fi communication.
* Channels greater than 14 mean "a" band, otherwise the
* band is "bg".
* example: CHANNEL=6
* ---end---
*/

View file

@ -25,6 +25,7 @@
#include "libnm-glib-aux/nm-time-utils.h"
#include "libnm-glib-aux/nm-secret-utils.h"
#include "libnm-core-aux-intern/nm-common-macros.h"
#include "libnm-core-aux-intern/nm-libnm-core-utils.h"
#include "nm-utils-private.h"
#include "nm-setting-private.h"
#include "nm-setting-bond.h"
@ -3697,25 +3698,8 @@ struct cf_pair {
guint32 freq;
};
static const struct cf_pair a_table[] = {
/* A band */
{7, 5035}, {8, 5040}, {9, 5045}, {11, 5055}, {12, 5060}, {16, 5080}, {34, 5170},
{36, 5180}, {38, 5190}, {40, 5200}, {42, 5210}, {44, 5220}, {46, 5230}, {48, 5240},
{50, 5250}, {52, 5260}, {56, 5280}, {58, 5290}, {60, 5300}, {64, 5320}, {100, 5500},
{104, 5520}, {108, 5540}, {112, 5560}, {116, 5580}, {120, 5600}, {124, 5620}, {128, 5640},
{132, 5660}, {136, 5680}, {140, 5700}, {149, 5745}, {152, 5760}, {153, 5765}, {157, 5785},
{160, 5800}, {161, 5805}, {165, 5825}, {183, 4915}, {184, 4920}, {185, 4925}, {187, 4935},
{188, 4945}, {192, 4960}, {196, 4980}, {0, 0}};
static const guint a_table_freqs[G_N_ELEMENTS(a_table)] = {
/* A band */
5035, 5040, 5045, 5055, 5060, 5080, 5170, 5180, 5190, 5200, 5210, 5220, 5230, 5240, 5250, 5260,
5280, 5290, 5300, 5320, 5500, 5520, 5540, 5560, 5580, 5600, 5620, 5640, 5660, 5680, 5700, 5745,
5760, 5765, 5785, 5800, 5805, 5825, 4915, 4920, 4925, 4935, 4945, 4960, 4980, 0,
};
static const struct cf_pair bg_table[] = {
/* B/G band */
static const struct cf_pair table_2ghz[] = {
/* 2.4GHz band */
{1, 2412},
{2, 2417},
{3, 2422},
@ -3732,8 +3716,8 @@ static const struct cf_pair bg_table[] = {
{14, 2484},
{0, 0}};
static const guint bg_table_freqs[G_N_ELEMENTS(bg_table)] = {
/* B/G band */
static const guint table_2ghz_freqs[G_N_ELEMENTS(table_2ghz)] = {
/* 2.4GHz band */
2412,
2417,
2422,
@ -3751,6 +3735,44 @@ static const guint bg_table_freqs[G_N_ELEMENTS(bg_table)] = {
0,
};
static const struct cf_pair table_5ghz[] = {
/* 5GHz band */
/* NOTE: 5030-5090 MHz have been reallocated and can no longer be used */
{34, 5170}, {36, 5180}, {38, 5190}, {40, 5200}, {42, 5210}, {44, 5220}, {46, 5230},
{48, 5240}, {50, 5250}, {52, 5260}, {56, 5280}, {58, 5290}, {60, 5300}, {64, 5320},
{100, 5500}, {104, 5520}, {108, 5540}, {112, 5560}, {116, 5580}, {120, 5600}, {124, 5620},
{128, 5640}, {132, 5660}, {136, 5680}, {140, 5700}, {149, 5745}, {152, 5760}, {153, 5765},
{157, 5785}, {160, 5800}, {161, 5805}, {165, 5825}, {169, 5845}, {173, 5865}, {177, 5885},
{183, 4915}, {184, 4920}, {185, 4925}, {187, 4935}, {188, 4940}, {189, 4945}, {192, 4960},
{196, 4980}, {0, 0}};
static const guint table_5ghz_freqs[G_N_ELEMENTS(table_5ghz)] = {
/* 5GHz band */
5170, 5180, 5190, 5200, 5210, 5220, 5230, 5240, 5250, 5260, 5280, 5290, 5300, 5320, 5500,
5520, 5540, 5560, 5580, 5600, 5620, 5640, 5660, 5680, 5700, 5745, 5760, 5765, 5785, 5800,
5805, 5825, 5845, 5865, 5885, 4915, 4920, 4925, 4935, 4940, 4945, 4960, 4980, 0,
};
static const struct cf_pair table_6ghz[] = {
/* 6GHz band */
{1, 5955}, {5, 5975}, {9, 5995}, {13, 6015}, {17, 6035}, {21, 6055}, {25, 6075},
{29, 6095}, {33, 6115}, {37, 6135}, {41, 6155}, {45, 6175}, {49, 6195}, {53, 6215},
{57, 6235}, {61, 6255}, {65, 6275}, {69, 6295}, {73, 6315}, {77, 6335}, {81, 6355},
{85, 6375}, {89, 6395}, {93, 6415}, {97, 6435}, {101, 6455}, {105, 6475}, {109, 6495},
{113, 6515}, {117, 6535}, {121, 6555}, {125, 6575}, {129, 6595}, {133, 6615}, {137, 6635},
{141, 6655}, {145, 6675}, {149, 6695}, {153, 6715}, {157, 6735}, {161, 6755}, {169, 6775},
{173, 6815}, {177, 6835}, {181, 6855}, {185, 6875}, {189, 6895}, {193, 6915}, {197, 6935},
{201, 6955}, {205, 6975}, {209, 6995}, {213, 7015}, {217, 7035}, {221, 7055}, {225, 7075},
{229, 7095}, {233, 7115}, {0, 0}};
static const guint table_6ghz_freqs[G_N_ELEMENTS(table_6ghz)] = {
/* 6GHz band */
5955, 5975, 5995, 6015, 6035, 6055, 6075, 6095, 6115, 6135, 6155, 6175, 6195, 6215, 6235,
6255, 6275, 6295, 6315, 6335, 6355, 6375, 6395, 6415, 6435, 6455, 6475, 6495, 6515, 6535,
6555, 6575, 6595, 6615, 6635, 6655, 6675, 6695, 6715, 6735, 6755, 6775, 6815, 6835, 6855,
6875, 6895, 6915, 6935, 6955, 6975, 6995, 7015, 7035, 7055, 7075, 7095, 7115, 0,
};
/**
* nm_utils_wifi_freq_to_channel:
* @freq: frequency
@ -3764,15 +3786,21 @@ nm_utils_wifi_freq_to_channel(guint32 freq)
{
int i = 0;
if (freq > 4900) {
while (a_table[i].freq && (a_table[i].freq != freq))
if (freq >= _NM_WIFI_FREQ_MIN_6GHZ) {
while (table_6ghz[i].freq && (table_6ghz[i].freq != freq))
i++;
return a_table[i].chan;
return table_6ghz[i].chan;
}
while (bg_table[i].freq && (bg_table[i].freq != freq))
if (freq >= _NM_WIFI_FREQ_MIN_5GHZ) {
while (table_5ghz[i].freq && (table_5ghz[i].freq != freq))
i++;
return bg_table[i].chan;
return table_5ghz[i].chan;
}
while (table_2ghz[i].freq && (table_2ghz[i].freq != freq))
i++;
return table_2ghz[i].chan;
}
/**
@ -3786,10 +3814,12 @@ nm_utils_wifi_freq_to_channel(guint32 freq)
const char *
nm_utils_wifi_freq_to_band(guint32 freq)
{
if (freq >= 4915 && freq <= 5825)
return "a";
else if (freq >= 2412 && freq <= 2484)
if (freq >= _NM_WIFI_FREQ_MIN_2GHZ && freq <= _NM_WIFI_FREQ_MAX_2GHZ)
return "bg";
else if (freq >= _NM_WIFI_FREQ_MIN_5GHZ && freq <= _NM_WIFI_FREQ_MAX_5GHZ)
return "a";
else if (freq >= _NM_WIFI_FREQ_MIN_6GHZ && freq <= _NM_WIFI_FREQ_MAX_6GHZ)
return "6GHz";
return NULL;
}
@ -3797,7 +3827,7 @@ nm_utils_wifi_freq_to_band(guint32 freq)
/**
* nm_utils_wifi_channel_to_freq:
* @channel: channel
* @band: frequency band for wireless ("a" or "bg")
* @band: frequency band for wireless ("a", "bg", "6GHz")
*
* Utility function to translate a Wi-Fi channel to its corresponding frequency.
*
@ -3812,18 +3842,26 @@ nm_utils_wifi_channel_to_freq(guint32 channel, const char *band)
g_return_val_if_fail(band, 0);
if (nm_streq(band, "a")) {
for (i = 0; a_table[i].chan; i++) {
if (a_table[i].chan == channel)
return a_table[i].freq;
if (nm_streq0(band, "a")) {
for (i = 0; table_5ghz[i].chan; i++) {
if (table_5ghz[i].chan == channel)
return table_5ghz[i].freq;
}
return ((guint32) -1);
}
if (nm_streq(band, "bg")) {
for (i = 0; bg_table[i].chan; i++) {
if (bg_table[i].chan == channel)
return bg_table[i].freq;
if (nm_streq0(band, "bg")) {
for (i = 0; table_2ghz[i].chan; i++) {
if (table_2ghz[i].chan == channel)
return table_2ghz[i].freq;
}
return ((guint32) -1);
}
if (nm_streq0(band, "6GHz")) {
for (i = 0; table_6ghz[i].chan; i++) {
if (table_6ghz[i].chan == channel)
return table_6ghz[i].freq;
}
return ((guint32) -1);
}
@ -3835,7 +3873,7 @@ nm_utils_wifi_channel_to_freq(guint32 channel, const char *band)
* nm_utils_wifi_find_next_channel:
* @channel: current channel
* @direction: whether going downward (0 or less) or upward (1 or more)
* @band: frequency band for wireless ("a" or "bg")
* @band: frequency band for wireless ("a", "bg", "6GHz")
*
* Utility function to find out next/previous Wi-Fi channel for a channel.
*
@ -3844,22 +3882,29 @@ nm_utils_wifi_channel_to_freq(guint32 channel, const char *band)
guint32
nm_utils_wifi_find_next_channel(guint32 channel, int direction, char *band)
{
size_t a_size = G_N_ELEMENTS(a_table);
size_t bg_size = G_N_ELEMENTS(bg_table);
size_t size_2ghz = G_N_ELEMENTS(table_2ghz);
size_t size_5ghz = G_N_ELEMENTS(table_5ghz);
size_t size_6ghz = G_N_ELEMENTS(table_6ghz);
const struct cf_pair *pair;
if (nm_streq(band, "a")) {
if (channel < a_table[0].chan)
return a_table[0].chan;
if (channel > a_table[a_size - 2].chan)
return a_table[a_size - 2].chan;
pair = &a_table[0];
} else if (nm_streq(band, "bg")) {
if (channel < bg_table[0].chan)
return bg_table[0].chan;
if (channel > bg_table[bg_size - 2].chan)
return bg_table[bg_size - 2].chan;
pair = &bg_table[0];
if (nm_streq0(band, "a")) {
if (channel < table_5ghz[0].chan)
return table_5ghz[0].chan;
if (channel > table_5ghz[size_5ghz - 2].chan)
return table_5ghz[size_5ghz - 2].chan;
pair = &table_5ghz[0];
} else if (nm_streq0(band, "bg")) {
if (channel < table_2ghz[0].chan)
return table_2ghz[0].chan;
if (channel > table_2ghz[size_2ghz - 2].chan)
return table_2ghz[size_2ghz - 2].chan;
pair = &table_2ghz[0];
} else if (nm_streq0(band, "6GHz")) {
if (channel < table_6ghz[0].chan)
return table_6ghz[0].chan;
if (channel > table_6ghz[size_6ghz - 2].chan)
return table_6ghz[size_6ghz - 2].chan;
pair = &table_6ghz[0];
} else
g_return_val_if_reached(0);
@ -3880,7 +3925,7 @@ nm_utils_wifi_find_next_channel(guint32 channel, int direction, char *band)
/**
* nm_utils_wifi_is_channel_valid:
* @channel: channel
* @band: frequency band for wireless ("a" or "bg")
* @band: frequency band for wireless ("a", "bg", "6GHz")
*
* Utility function to verify Wi-Fi channel validity.
*
@ -3930,8 +3975,8 @@ nm_utils_wifi_is_channel_valid(guint32 channel, const char *band)
const guint *
nm_utils_wifi_2ghz_freqs(void)
{
_nm_assert_wifi_freqs(bg_table, bg_table_freqs);
return bg_table_freqs;
_nm_assert_wifi_freqs(table_2ghz, table_2ghz_freqs);
return table_2ghz_freqs;
}
/**
@ -3946,8 +3991,24 @@ nm_utils_wifi_2ghz_freqs(void)
const guint *
nm_utils_wifi_5ghz_freqs(void)
{
_nm_assert_wifi_freqs(a_table, a_table_freqs);
return a_table_freqs;
_nm_assert_wifi_freqs(table_5ghz, table_5ghz_freqs);
return table_5ghz_freqs;
}
/**
* nm_utils_wifi_6ghz_freqs:
*
* Utility function to return 6 GHz Wi-Fi frequencies (802.11ax/be, Wi-Fi 6E).
*
* Returns: zero-terminated array of frequencies numbers (in MHz)
*
* Since: 1.58
**/
const guint *
nm_utils_wifi_6ghz_freqs(void)
{
_nm_assert_wifi_freqs(table_6ghz, table_6ghz_freqs);
return table_6ghz_freqs;
}
/**

View file

@ -11140,7 +11140,7 @@ _do_wifi_ghz_freqs(const guint *freqs, const char *band)
int j;
int i;
g_assert(NM_IN_STRSET(band, "a", "bg"));
g_assert(NM_IN_STRSET(band, "a", "bg", "6GHz"));
g_assert(freqs);
g_assert(freqs[0] != 0);
@ -11178,6 +11178,7 @@ test_nm_utils_wifi_ghz_freqs(void)
{
_do_wifi_ghz_freqs(nm_utils_wifi_2ghz_freqs(), "bg");
_do_wifi_ghz_freqs(nm_utils_wifi_5ghz_freqs(), "a");
_do_wifi_ghz_freqs(nm_utils_wifi_6ghz_freqs(), "6GHz");
}
/*****************************************************************************/

View file

@ -143,6 +143,8 @@ NM_AVAILABLE_IN_1_2
const guint *nm_utils_wifi_2ghz_freqs(void);
NM_AVAILABLE_IN_1_2
const guint *nm_utils_wifi_5ghz_freqs(void);
NM_AVAILABLE_IN_1_58
const guint *nm_utils_wifi_6ghz_freqs(void);
const char *nm_utils_wifi_strength_bars(guint8 strength);

View file

@ -4292,7 +4292,8 @@ _set_fcn_wireless_channel(ARGS_SET_FCN)
}
if (!nm_utils_wifi_is_channel_valid(chan_int, "a")
&& !nm_utils_wifi_is_channel_valid(chan_int, "bg")) {
&& !nm_utils_wifi_is_channel_valid(chan_int, "bg")
&& !nm_utils_wifi_is_channel_valid(chan_int, "6GHz")) {
nm_utils_error_set(error,
NM_UTILS_ERROR_UNKNOWN,
_("'%ld' is not a valid channel"),
@ -8530,7 +8531,7 @@ static const NMMetaPropertyInfo *const property_infos_WIRELESS[] = {
PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_BAND,
.property_type = &_pt_gobject_string,
.property_typ_data = DEFINE_PROPERTY_TYP_DATA (
.values_static = NM_MAKE_STRV ("a", "bg"),
.values_static = NM_MAKE_STRV ("a", "bg", "6GHz"),
),
),
PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_CHANNEL,

View file

@ -452,7 +452,7 @@
#define DESCRIBE_DOC_NM_SETTING_WIREGUARD_PRIVATE_KEY N_("The 256 bit private-key in base64 encoding.")
#define DESCRIBE_DOC_NM_SETTING_WIREGUARD_PRIVATE_KEY_FLAGS N_("Flags indicating how to handle the \"private-key\" property.")
#define DESCRIBE_DOC_NM_SETTING_WIRELESS_AP_ISOLATION N_("Configures AP isolation, which prevents communication between wireless devices connected to this AP. This property can be set to a value different from \"default\" (-1) only when the interface is configured in AP mode. If set to \"true\" (1), devices are not able to communicate with each other. This increases security because it protects devices against attacks from other clients in the network. At the same time, it prevents devices to access resources on the same wireless networks as file shares, printers, etc. If set to \"false\" (0), devices can talk to each other. When set to \"default\" (-1), the global default is used; in case the global default is unspecified it is assumed to be \"false\" (0).")
#define DESCRIBE_DOC_NM_SETTING_WIRELESS_BAND N_("802.11 frequency band of the network. One of \"a\" for 5GHz 802.11a or \"bg\" for 2.4GHz 802.11. This will lock associations to the Wi-Fi network to the specific band, i.e. if \"a\" is specified, the device will not associate with the same network in the 2.4GHz band even if the network's settings are compatible. This setting depends on specific driver capability and may not work with all drivers.")
#define DESCRIBE_DOC_NM_SETTING_WIRELESS_BAND N_("802.11 frequency band of the network. One of \"a\" for 5GHz, \"bg\" for 2.4GHz or \"6GHz\". This will lock associations to the Wi-Fi network to the specific band, i.e. if \"a\" is specified, the device will not associate with the same network in the 2.4GHz (bg) or 6GHz bands even if the network's settings are compatible. This setting depends on specific driver capability and may not work with all drivers.")
#define DESCRIBE_DOC_NM_SETTING_WIRELESS_BSSID N_("If specified, directs the device to only associate with the given access point. This capability is highly driver dependent and not supported by all devices. Note: this property does not control the BSSID used when creating an Ad-Hoc network and is unlikely to in the future. Locking a client profile to a certain BSSID will prevent roaming and also disable background scanning. That can be useful, if there is only one access point for the SSID.")
#define DESCRIBE_DOC_NM_SETTING_WIRELESS_CHANNEL N_("Wireless channel to use for the Wi-Fi connection. The device will only join (or create for Ad-Hoc networks) a Wi-Fi network on the specified channel. Because channel numbers overlap between bands, this property also requires the \"band\" property to be set.")
#define DESCRIBE_DOC_NM_SETTING_WIRELESS_CHANNEL_WIDTH N_("Specifies width of the wireless channel in Access Point (AP) mode. When set to \"auto\" (0) (the default), the channel width is automatically determined. At the moment, this means that the safest (smallest) width is chosen. If the value is not \"auto\" (0), then the 'channel' property must also be set. When using the 2.4GHz band, the width can be at most 40MHz. This property can be set to a value different from \"auto\" (0) only when the interface is configured in AP mode.")

View file

@ -866,7 +866,7 @@ usage(void)
"<ifname>]\n"
" [bssid <BSSID>] [name <name>] [private yes|no] [hidden "
"yes|no]\n\n"
" wifi hotspot [ifname <ifname>] [con-name <name>] [ssid <SSID>] [band a|bg] "
" wifi hotspot [ifname <ifname>] [con-name <name>] [ssid <SSID>] [band a|bg|6GHz] "
"[channel <channel>] [password <password>]\n\n"
" wifi rescan [ifname <ifname>] [[ssid <SSID to scan>] ...]\n\n"
" wifi show-password [ifname <ifname>]\n\n"
@ -1021,7 +1021,7 @@ usage_device_wifi(void)
"It is also assumed that IP configuration is obtained via DHCP.\n"
"\n"
"ARGUMENTS := hotspot [ifname <ifname>] [con-name <name>] [ssid <SSID>]\n"
" [band a|bg] [channel <channel>] [password <password>]\n"
" [band a|bg|6GHz] [channel <channel>] [password <password>]\n"
"\n"
"Create a Wi-Fi hotspot. Use 'connection down' or 'device disconnect'\n"
"to stop the hotspot.\n"
@ -4443,10 +4443,11 @@ do_device_wifi_hotspot(const NMCCommand *cmd, NmCli *nmc, int argc, const char *
}
band = *argv;
if (argc == 1 && nmc->complete)
nmc_complete_strings(band, "a", "bg");
if (strcmp(band, "a") && strcmp(band, "bg")) {
nmc_complete_strings(band, "a", "bg", "6GHz");
if (!NM_IN_STRSET(band, "a", "bg", "6GHz")) {
g_string_printf(nmc->return_text,
_("Error: band argument value '%s' is invalid; use 'a' or 'bg'."),
_("Error: band argument value '%s' is invalid; use 'a', 'bg' "
"or '6GHz'."),
band);
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
return;
@ -4494,7 +4495,7 @@ do_device_wifi_hotspot(const NMCCommand *cmd, NmCli *nmc, int argc, const char *
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
return;
}
if (!nmc_string_to_uint(channel, TRUE, 1, 5825, &value)
if (!nmc_string_to_uint(channel, TRUE, 1, G_MAXUINT32, &value)
|| !nm_utils_wifi_is_channel_valid(value, band)) {
g_string_printf(nmc->return_text,
_("Error: channel '%s' not valid for band '%s'."),

View file

@ -33,9 +33,9 @@
format="string"
values="infrastructure, adhoc, ap, mesh" />
<property name="band"
nmcli-description="802.11 frequency band of the network. One of &quot;a&quot; for 5GHz 802.11a or &quot;bg&quot; for 2.4GHz 802.11. This will lock associations to the Wi-Fi network to the specific band, i.e. if &quot;a&quot; is specified, the device will not associate with the same network in the 2.4GHz band even if the network&apos;s settings are compatible. This setting depends on specific driver capability and may not work with all drivers."
nmcli-description="802.11 frequency band of the network. One of &quot;a&quot; for 5GHz, &quot;bg&quot; for 2.4GHz or &quot;6GHz&quot;. This will lock associations to the Wi-Fi network to the specific band, i.e. if &quot;a&quot; is specified, the device will not associate with the same network in the 2.4GHz (bg) or 6GHz bands even if the network&apos;s settings are compatible. This setting depends on specific driver capability and may not work with all drivers."
format="string"
values="a, bg" />
values="a, bg, 6GHz" />
<property name="channel"
nmcli-description="Wireless channel to use for the Wi-Fi connection. The device will only join (or create for Ad-Hoc networks) a Wi-Fi network on the specified channel. Because channel numbers overlap between bands, this property also requires the &quot;band&quot; property to be set."
format="integer"

View file

@ -54,10 +54,9 @@ static NmtNewtPopupEntry wifi_mode[] = {{NC_("Wi-Fi", "Client"), NM_SETTING_WIRE
{NULL, NULL}};
static NmtNewtPopupEntry wifi_band[] = {{NC_("Wi-Fi", "Automatic"), NULL},
/* 802.11a Wi-Fi network */
{N_("A (5 GHz)"), "a"},
/* 802.11b / 802.11g Wi-Fi network */
{N_("B/G (2.4 GHz)"), "bg"},
{N_("5 GHz"), "a"},
{N_("2.4 GHz"), "bg"},
{N_("6 GHz"), "6GHz"},
{NULL, NULL}};
static struct {