blob: 6e13b024ef4a2209ed67ef8e43960ec48b445ddc [file] [log] [blame]
developer05f3b2b2024-08-19 19:17:34 +08001From b74aa64e3cbacf537ac3e7a96f3295ebe0979c0c Mon Sep 17 00:00:00 2001
developer66e89bc2024-04-23 14:50:01 +08002From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
3Date: Mon, 20 Feb 2023 14:56:55 +0800
developer05f3b2b2024-08-19 19:17:34 +08004Subject: [PATCH 022/126] mtk: hostapd: Add DFS offchan channel switch
developer66e89bc2024-04-23 14:50:01 +08005
6Add DFS background chain channel switch command for testing purpose.
7This feature is implemented via hostapd_cli command.
8Command format:
9hostapd_cli -i <interface> raw SET_OFFCHAN_CTRL chan=<dfs_channel>
10
11Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
12---
13 hostapd/ctrl_iface.c | 72 ++++++++++++++++++++++++++++++++++++++++++++
14 src/ap/dfs.c | 25 ++++++---------
15 src/ap/dfs.h | 15 +++++++++
16 3 files changed, 96 insertions(+), 16 deletions(-)
17
18diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
developer05f3b2b2024-08-19 19:17:34 +080019index ef0ade6c9..32d4997b2 100644
developer66e89bc2024-04-23 14:50:01 +080020--- a/hostapd/ctrl_iface.c
21+++ b/hostapd/ctrl_iface.c
developer05f3b2b2024-08-19 19:17:34 +080022@@ -4284,6 +4284,76 @@ hostapd_ctrl_iface_set_dfs_detect_mode(struct hostapd_data *hapd, char *value,
developer66e89bc2024-04-23 14:50:01 +080023 }
24
25
26+static int
27+hostapd_ctrl_iface_set_offchan_ctrl(struct hostapd_data *hapd, char *cmd,
28+ char *buf, size_t buflen)
29+{
30+ struct hostapd_iface *iface = hapd->iface;
31+ char *pos, *param;
32+ enum hostapd_hw_mode hw_mode;
33+ bool chan_found = false;
34+ int i, num_available_chandefs, channel, chan_width, sec = 0;
35+ int sec_chan_idx_80p80 = -1;
36+ u8 oper_centr_freq_seg0_idx, oper_centr_freq_seg1_idx;
37+ struct hostapd_channel_data *chan;
38+ enum dfs_channel_type type = DFS_NO_CAC_YET;
39+
40+ param = os_strchr(cmd, ' ');
41+ if (!param)
42+ return -1;
43+ *param++ = '\0';
44+
45+ pos = os_strstr(param, "chan=");
46+ if (pos)
47+ channel = strtol(pos + 5, NULL, 10);
48+ else
49+ return -1;
50+
developer05f3b2b2024-08-19 19:17:34 +080051+ num_available_chandefs = dfs_find_channel(iface, NULL, 0, 0, type);
developer66e89bc2024-04-23 14:50:01 +080052+ for (i = 0; i < num_available_chandefs; i++) {
developer05f3b2b2024-08-19 19:17:34 +080053+ dfs_find_channel(iface, &chan, 0, i, type);
developer66e89bc2024-04-23 14:50:01 +080054+ if (chan->chan == channel) {
55+ chan_found = true;
56+ break;
57+ }
58+ }
59+
60+ if (!chan_found)
61+ return -1;
62+
63+ if (iface->conf->secondary_channel)
64+ sec = 1;
65+
66+ dfs_adjust_center_freq(iface, chan,
67+ sec,
68+ sec_chan_idx_80p80,
69+ &oper_centr_freq_seg0_idx,
70+ &oper_centr_freq_seg1_idx);
71+
72+ if (hostapd_start_dfs_cac(iface, iface->conf->hw_mode,
73+ chan->freq, chan->chan,
74+ iface->conf->ieee80211n,
75+ iface->conf->ieee80211ac,
76+ iface->conf->ieee80211ax,
77+ iface->conf->ieee80211be,
78+ sec, hostapd_get_oper_chwidth(iface->conf),
79+ oper_centr_freq_seg0_idx,
80+ oper_centr_freq_seg1_idx, true)) {
81+ wpa_printf(MSG_ERROR, "DFS failed to start CAC offchannel");
82+ iface->radar_background.channel = -1;
83+ return -1;
84+ }
85+
86+ iface->radar_background.channel = chan->chan;
87+ iface->radar_background.freq = chan->freq;
88+ iface->radar_background.secondary_channel = sec;
89+ iface->radar_background.centr_freq_seg0_idx = oper_centr_freq_seg0_idx;
90+ iface->radar_background.centr_freq_seg1_idx = oper_centr_freq_seg1_idx;
91+
92+ return os_snprintf(buf, buflen, "OK\n");
93+}
94+
95+
96 static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
97 char *buf, char *reply,
98 int reply_size,
developer05f3b2b2024-08-19 19:17:34 +080099@@ -4908,6 +4978,8 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
developer66e89bc2024-04-23 14:50:01 +0800100 } else if (os_strncmp(buf, "DFS_DETECT_MODE ", 16) == 0) {
101 reply_len = hostapd_ctrl_iface_set_dfs_detect_mode(hapd, buf + 16,
102 reply, reply_size);
103+ } else if (os_strncmp(buf, "SET_OFFCHAN_CTRL", 16) == 0) {
104+ reply_len = hostapd_ctrl_iface_set_offchan_ctrl(hapd, buf + 16, reply, reply_size);
105 } else {
106 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
107 reply_len = 16;
108diff --git a/src/ap/dfs.c b/src/ap/dfs.c
developer05f3b2b2024-08-19 19:17:34 +0800109index 49dc4d424..42cce2dce 100644
developer66e89bc2024-04-23 14:50:01 +0800110--- a/src/ap/dfs.c
111+++ b/src/ap/dfs.c
developer05f3b2b2024-08-19 19:17:34 +0800112@@ -20,13 +20,6 @@
developer66e89bc2024-04-23 14:50:01 +0800113 #include "dfs.h"
114 #include "crypto/crypto.h"
115
116-
117-enum dfs_channel_type {
118- DFS_ANY_CHANNEL,
119- DFS_AVAILABLE, /* non-radar or radar-available */
120- DFS_NO_CAC_YET, /* radar-not-yet-available */
121-};
122-
123 static struct hostapd_channel_data *
124 dfs_downgrade_bandwidth(struct hostapd_iface *iface, int *secondary_channel,
125 u8 *oper_centr_freq_seg0_idx,
developer05f3b2b2024-08-19 19:17:34 +0800126@@ -239,9 +232,9 @@ static int is_in_chanlist(struct hostapd_iface *iface,
developer66e89bc2024-04-23 14:50:01 +0800127 * - hapd->vht/he_oper_centr_freq_seg0_idx
128 * - hapd->vht/he_oper_centr_freq_seg1_idx
129 */
130-static int dfs_find_channel(struct hostapd_iface *iface,
131- struct hostapd_channel_data **ret_chan,
132- int idx, enum dfs_channel_type type)
133+int dfs_find_channel(struct hostapd_iface *iface,
134+ struct hostapd_channel_data **ret_chan,
135+ int idx, enum dfs_channel_type type)
136 {
137 struct hostapd_hw_modes *mode;
138 struct hostapd_channel_data *chan;
developer05f3b2b2024-08-19 19:17:34 +0800139@@ -301,12 +294,12 @@ static int dfs_find_channel(struct hostapd_iface *iface,
developer66e89bc2024-04-23 14:50:01 +0800140 }
141
142
143-static void dfs_adjust_center_freq(struct hostapd_iface *iface,
144- struct hostapd_channel_data *chan,
145- int secondary_channel,
146- int sec_chan_idx_80p80,
147- u8 *oper_centr_freq_seg0_idx,
148- u8 *oper_centr_freq_seg1_idx)
149+void dfs_adjust_center_freq(struct hostapd_iface *iface,
150+ struct hostapd_channel_data *chan,
151+ int secondary_channel,
152+ int sec_chan_idx_80p80,
153+ u8 *oper_centr_freq_seg0_idx,
154+ u8 *oper_centr_freq_seg1_idx)
155 {
156 if (!iface->conf->ieee80211ac && !iface->conf->ieee80211ax)
157 return;
158diff --git a/src/ap/dfs.h b/src/ap/dfs.h
159index 606c1b393..c2556d2d9 100644
160--- a/src/ap/dfs.h
161+++ b/src/ap/dfs.h
162@@ -9,6 +9,12 @@
163 #ifndef DFS_H
164 #define DFS_H
165
166+enum dfs_channel_type {
167+ DFS_ANY_CHANNEL,
168+ DFS_AVAILABLE, /* non-radar or radar-available */
169+ DFS_NO_CAC_YET, /* radar-not-yet-available */
170+};
171+
172 int hostapd_handle_dfs(struct hostapd_iface *iface);
173
174 int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq,
175@@ -32,5 +38,14 @@ int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq,
176 int hostapd_handle_dfs_offload(struct hostapd_iface *iface);
177 int hostapd_is_dfs_overlap(struct hostapd_iface *iface, enum chan_width width,
178 int center_freq);
179+int dfs_find_channel(struct hostapd_iface *iface,
180+ struct hostapd_channel_data **ret_chan,
181+ int idx, enum dfs_channel_type type);
182+void dfs_adjust_center_freq(struct hostapd_iface *iface,
183+ struct hostapd_channel_data *chan,
184+ int secondary_channel,
185+ int sec_chan_idx_80p80,
186+ u8 *oper_centr_freq_seg0_idx,
187+ u8 *oper_centr_freq_seg1_idx);
188
189 #endif /* DFS_H */
190--
developer05f3b2b2024-08-19 19:17:34 +08001912.18.0
developer66e89bc2024-04-23 14:50:01 +0800192