WiFi: Add support for setting channel width

This commit is contained in:
Mattias Walström
2026-05-18 09:27:03 +02:00
parent 2885112da8
commit 64819075d5
3 changed files with 136 additions and 1 deletions
+85 -1
View File
@@ -359,14 +359,55 @@ static void wifi_gen_ssid_config(FILE *hostapd, struct lyd_node *cif, struct lyd
free(secret);
}
/*
* Center channel for 80MHz VHT/HE operation.
* 5GHz 80MHz groups: 36-48(42), 52-64(58), 100-112(106),
* 116-128(122), 132-144(138), 149-161(155)
*/
static int wifi_center_chan_80(int ch)
{
static const int grp[][2] = {
{36, 42}, {52, 58}, {100, 106}, {116, 122}, {132, 138}, {149, 155}
};
int i;
for (i = 0; i < 6; i++)
if (ch >= grp[i][0] && ch < grp[i][0] + 16)
return grp[i][1];
return 0;
}
/*
* Center channel for 160MHz VHT/HE operation.
* 5GHz 160MHz groups: 36-64(50), 100-128(114)
*/
static int wifi_center_chan_160(int ch)
{
if (ch >= 36 && ch <= 64)
return 50;
if (ch >= 100 && ch <= 128)
return 114;
return 0;
}
/* HT40 secondary channel direction: lower channel in pair uses +, upper uses - */
static const char *wifi_ht40_dir(int ch)
{
return ((ch / 4) % 2) ? "[HT40+]" : "[HT40-]";
}
/* Helper: Write radio-specific configuration */
static void wifi_gen_radio_config(FILE *hostapd, struct lyd_node *radio_node)
{
const char *country, *channel, *band;
const char *country, *channel, *band, *width;
int ch = 0;
country = lydx_get_cattr(radio_node, "country-code");
band = lydx_get_cattr(radio_node, "band");
channel = lydx_get_cattr(radio_node, "channel");
width = lydx_get_cattr(radio_node, "channel-width");
if (channel && strcmp(channel, "auto"))
ch = atoi(channel);
if (country)
fprintf(hostapd, "country_code=%s\n", country);
@@ -460,6 +501,49 @@ static void wifi_gen_radio_config(FILE *hostapd, struct lyd_node *radio_node)
/* 802.11ax (WiFi 6) always enabled for better performance */
fprintf(hostapd, "ieee80211ax=1\n");
/*
* Channel width configuration.
* - HT (802.11n): ht_capab [HT40+] or [HT40-]
* - VHT (802.11ac): vht_oper_chwidth 0=20/40, 1=80, 2=160
* - HE (802.11ax): he_oper_chwidth follows VHT values
* Without explicit width, hostapd uses driver defaults.
*/
if (width && strcmp(width, "auto")) {
if (!strcmp(width, "20MHz")) {
fprintf(hostapd, "ht_capab=\n");
if (strcmp(band, "2.4GHz")) {
fprintf(hostapd, "vht_oper_chwidth=0\n");
fprintf(hostapd, "he_oper_chwidth=0\n");
}
} else if (!strcmp(width, "40MHz")) {
fprintf(hostapd, "ht_capab=%s\n", ch ? wifi_ht40_dir(ch) : "[HT40+]");
if (strcmp(band, "2.4GHz")) {
fprintf(hostapd, "vht_oper_chwidth=0\n");
fprintf(hostapd, "he_oper_chwidth=0\n");
}
} else if (!strcmp(width, "80MHz") && ch) {
int center = wifi_center_chan_80(ch);
fprintf(hostapd, "ht_capab=%s\n", wifi_ht40_dir(ch));
fprintf(hostapd, "vht_oper_chwidth=1\n");
fprintf(hostapd, "he_oper_chwidth=1\n");
if (center) {
fprintf(hostapd, "vht_oper_centr_freq_seg0_idx=%d\n", center);
fprintf(hostapd, "he_oper_centr_freq_seg0_idx=%d\n", center);
}
} else if (!strcmp(width, "160MHz") && ch) {
int center = wifi_center_chan_160(ch);
fprintf(hostapd, "ht_capab=%s\n", wifi_ht40_dir(ch));
fprintf(hostapd, "vht_oper_chwidth=2\n");
fprintf(hostapd, "he_oper_chwidth=2\n");
if (center) {
fprintf(hostapd, "vht_oper_centr_freq_seg0_idx=%d\n", center);
fprintf(hostapd, "he_oper_centr_freq_seg0_idx=%d\n", center);
}
}
}
/* Beamforming improves signal quality and range */
fprintf(hostapd, "he_su_beamformer=1\n");
fprintf(hostapd, "he_su_beamformee=1\n");
+51
View File
@@ -21,6 +21,11 @@ module infix-hardware {
contact "kernelkit@googlegroups.com";
description "Vital Product Data augmentation of ieee-hardware and deviations.";
revision 2026-03-01 {
description "Add channel-width leaf for WiFi radio container.";
reference "internal";
}
revision 2026-02-08 {
description "Add GPS/GNSS receiver hardware class and container for time sync.";
reference "internal";
@@ -98,6 +103,36 @@ module infix-hardware {
description "WiFi frequency band selection.";
}
typedef wifi-channel-width {
type enumeration {
enum "auto" {
description "Automatic selection based on hardware and regulatory capabilities.";
}
enum "20MHz" {
description "20 MHz channel width.";
}
enum "40MHz" {
description "40 MHz channel width (HT40).";
}
enum "80MHz" {
description "80 MHz channel width (VHT/HE, 5/6 GHz only).";
}
enum "160MHz" {
description "160 MHz channel width (VHT/HE, 5/6 GHz only).";
}
}
description
"WiFi channel bandwidth selection.
Wider channels provide higher throughput but increase
interference and reduce the number of non-overlapping channels.
Constraints:
- 40 MHz: Requires HT capable hardware
- 80 MHz: Requires VHT capable hardware (5/6 GHz only)
- 160 MHz: Requires VHT capable hardware (5/6 GHz only)";
}
/*
* Hardware class identities
*/
@@ -294,6 +329,22 @@ module infix-hardware {
congestion in most environments.";
}
leaf channel-width {
type wifi-channel-width;
default "auto";
must "../band != '2.4GHz' or . = 'auto' or . = '20MHz' or . = '40MHz'" {
error-message "80/160 MHz channel width requires 5 GHz or 6 GHz band.";
}
description
"Channel bandwidth.
Wider channels increase throughput but are more susceptible
to interference. Default 'auto' lets the driver select the
widest width supported by hardware and regulatory domain.
Only applicable in Access Point mode.";
}
leaf probe-timeout {
type uint8;
description