1 /*
2 * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 #include "qdf_types.h"
18 #include <net/cfg80211.h>
19 #include "wlan_cfg80211.h"
20 #include "wlan_objmgr_psoc_obj.h"
21 #include "wlan_objmgr_pdev_obj.h"
22 #include "wlan_objmgr_vdev_obj.h"
23 #include "os_if_dp_local_pkt_capture.h"
24 #include "wlan_dp_ucfg_api.h"
25 #include "wlan_dp_main.h"
26 #include "cdp_txrx_mon.h"
27 #include "wlan_policy_mgr_api.h"
28 #include <ol_defines.h>
29 #include "wlan_osif_priv.h"
30
31 /* Short name for QCA_NL80211_VENDOR_SUBCMD_SET_MONITOR_MODE command */
32 #define SET_MONITOR_MODE_CONFIG_MAX \
33 QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MAX
34 #define SET_MONITOR_MODE_INVALID \
35 QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_INVALID
36 #define SET_MONITOR_MODE_DATA_TX_FRAME_TYPE \
37 QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_TX_FRAME_TYPE
38 #define SET_MONITOR_MODE_DATA_RX_FRAME_TYPE \
39 QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_RX_FRAME_TYPE
40 #define SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE \
41 QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE
42 #define SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE \
43 QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE
44 #define SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE \
45 QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE
46 #define SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE \
47 QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE
48
49 /* Short name for QCA_NL80211_VENDOR_SUBCMD_GET_MONITOR_MODE command */
50 #define GET_MONITOR_MODE_CONFIG_MAX \
51 QCA_WLAN_VENDOR_ATTR_GET_MONITOR_MODE_MAX
52 #define GET_MONITOR_MODE_INVALID \
53 QCA_WLAN_VENDOR_ATTR_GET_MONITOR_MODE_INVALID
54 #define GET_MONITOR_MODE_STATUS \
55 QCA_WLAN_VENDOR_ATTR_GET_MONITOR_MODE_STATUS
56
57 #define MGMT_FRAME_TYPE 0
58 #define DATA_FRAME_TYPE 1
59 #define CTRL_FRAME_TYPE 2
60
61 const struct nla_policy
62 set_monitor_mode_policy[SET_MONITOR_MODE_CONFIG_MAX + 1] = {
63 [SET_MONITOR_MODE_DATA_TX_FRAME_TYPE] = { .type = NLA_U32 },
64 [SET_MONITOR_MODE_DATA_RX_FRAME_TYPE] = { .type = NLA_U32 },
65 [SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE] = { .type = NLA_U32 },
66 [SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE] = { .type = NLA_U32 },
67 [SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE] = { .type = NLA_U32 },
68 [SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE] = { .type = NLA_U32 },
69 };
70
71 static
os_if_local_pkt_capture_concurrency_allowed(struct wlan_objmgr_psoc * psoc)72 bool os_if_local_pkt_capture_concurrency_allowed(struct wlan_objmgr_psoc *psoc)
73 {
74 uint32_t num_connections, sta_count;
75
76 num_connections = policy_mgr_get_connection_count(psoc);
77 osif_debug("Total connections %d", num_connections);
78
79 /*
80 * No connections, local packet capture is allowed
81 * Only 1 connection and its STA, then local packet capture is allowed
82 * 2+ port concurrency, local packet capture is not allowed
83 */
84 if (!num_connections)
85 return true;
86
87 if (num_connections > 1)
88 return false;
89
90 sta_count = policy_mgr_mode_specific_connection_count(psoc,
91 PM_STA_MODE,
92 NULL);
93 osif_debug("sta_count %d", sta_count);
94 if (sta_count == 1)
95 return true;
96
97 return false;
98 }
99
os_if_lpc_mon_intf_creation_allowed(struct wlan_objmgr_psoc * psoc)100 bool os_if_lpc_mon_intf_creation_allowed(struct wlan_objmgr_psoc *psoc)
101 {
102 if (ucfg_dp_is_local_pkt_capture_enabled(psoc)) {
103 if (policy_mgr_is_mlo_sta_present(psoc)) {
104 osif_err("MLO STA present, lpc interface creation not allowed");
105 return false;
106 }
107
108 if (!os_if_local_pkt_capture_concurrency_allowed(psoc)) {
109 osif_err("Concurrency check failed, lpc interface creation not allowed");
110 return false;
111 }
112 }
113
114 return true;
115 }
116
os_if_start_capture_allowed(struct wlan_objmgr_vdev * vdev)117 static QDF_STATUS os_if_start_capture_allowed(struct wlan_objmgr_vdev *vdev)
118 {
119 enum QDF_OPMODE mode = wlan_vdev_mlme_get_opmode(vdev);
120 struct wlan_objmgr_psoc *psoc;
121
122 psoc = wlan_vdev_get_psoc(vdev);
123 if (!psoc) {
124 osif_err("NULL psoc");
125 return QDF_STATUS_E_INVAL;
126 }
127
128 if (!ucfg_dp_is_local_pkt_capture_enabled(psoc)) {
129 osif_warn("local pkt capture feature not enabled");
130 return QDF_STATUS_E_NOSUPPORT;
131 }
132
133 if (mode != QDF_MONITOR_MODE) {
134 osif_err("Operation not permitted in mode: %d", mode);
135 return QDF_STATUS_E_PERM;
136 }
137
138 /*
139 * Whether STA interface is present or not, is already checked
140 * while creating monitor interface
141 */
142
143 if (policy_mgr_is_mlo_sta_present(psoc)) {
144 osif_err("MLO STA present, start capture is not permitted");
145 return QDF_STATUS_E_PERM;
146 }
147
148 if (!os_if_local_pkt_capture_concurrency_allowed(psoc)) {
149 osif_err("Concurrency check failed, start capture not allowed");
150 return QDF_STATUS_E_PERM;
151 }
152
153 return QDF_STATUS_SUCCESS;
154 }
155
os_if_stop_capture_allowed(struct wlan_objmgr_vdev * vdev)156 static QDF_STATUS os_if_stop_capture_allowed(struct wlan_objmgr_vdev *vdev)
157 {
158 enum QDF_OPMODE mode;
159 struct wlan_objmgr_psoc *psoc;
160 void *soc;
161
162 soc = cds_get_context(QDF_MODULE_ID_SOC);
163 if (!soc)
164 return QDF_STATUS_E_INVAL;
165
166 psoc = wlan_vdev_get_psoc(vdev);
167 if (!psoc) {
168 osif_err("NULL psoc");
169 return QDF_STATUS_E_INVAL;
170 }
171
172 mode = wlan_vdev_mlme_get_opmode(vdev);
173 if (mode != QDF_MONITOR_MODE) {
174 osif_warn("Operation not permitted in mode: %d", mode);
175 return QDF_STATUS_E_PERM;
176 }
177
178 if (!ucfg_dp_is_local_pkt_capture_enabled(psoc)) {
179 osif_err("local pkt capture feature not enabled");
180 return QDF_STATUS_E_NOSUPPORT;
181 }
182
183 if (!cdp_is_local_pkt_capture_running(soc, OL_TXRX_PDEV_ID)) {
184 osif_debug("local pkt capture not running, no need to stop");
185 return QDF_STATUS_E_PERM;
186 }
187
188 return QDF_STATUS_SUCCESS;
189 }
190
191 static
os_if_dp_local_pkt_capture_start(struct wlan_objmgr_vdev * vdev,struct nlattr ** tb)192 QDF_STATUS os_if_dp_local_pkt_capture_start(struct wlan_objmgr_vdev *vdev,
193 struct nlattr **tb)
194 {
195 QDF_STATUS status;
196 struct cdp_monitor_filter filter = {0};
197 uint32_t pkt_type = 0, val;
198 void *soc;
199
200 status = os_if_start_capture_allowed(vdev);
201 if (QDF_IS_STATUS_ERROR(status))
202 goto error;
203
204 soc = cds_get_context(QDF_MODULE_ID_SOC);
205 if (!soc)
206 return QDF_STATUS_E_INVAL;
207
208 if (tb[SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE]) {
209 val = nla_get_u32(tb[SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE]);
210
211 if (val != QCA_WLAN_VENDOR_MONITOR_MGMT_FRAME_TYPE_ALL) {
212 osif_err("Invalid value: %d Expected: %d",
213 val,
214 QCA_WLAN_VENDOR_MONITOR_MGMT_FRAME_TYPE_ALL);
215 status = QDF_STATUS_E_INVAL;
216 goto error;
217 }
218 pkt_type |= BIT(MGMT_FRAME_TYPE);
219 }
220
221 if (tb[SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE]) {
222 val = nla_get_u32(tb[SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE]);
223
224 if (val != QCA_WLAN_VENDOR_MONITOR_MGMT_FRAME_TYPE_ALL) {
225 osif_err("Invalid value: %d Expected: %d",
226 val,
227 QCA_WLAN_VENDOR_MONITOR_MGMT_FRAME_TYPE_ALL);
228 status = QDF_STATUS_E_INVAL;
229 goto error;
230 }
231 pkt_type |= BIT(MGMT_FRAME_TYPE);
232 }
233
234 if (tb[SET_MONITOR_MODE_DATA_TX_FRAME_TYPE]) {
235 val = nla_get_u32(tb[SET_MONITOR_MODE_DATA_TX_FRAME_TYPE]);
236
237 if (val != QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ALL) {
238 osif_err("Invalid value: %d Expected: %d",
239 val,
240 QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ALL);
241 status = QDF_STATUS_E_INVAL;
242 goto error;
243 }
244 pkt_type |= BIT(DATA_FRAME_TYPE);
245 }
246
247 if (tb[SET_MONITOR_MODE_DATA_RX_FRAME_TYPE]) {
248 val = nla_get_u32(tb[SET_MONITOR_MODE_DATA_RX_FRAME_TYPE]);
249
250 if (val != QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ALL) {
251 osif_err("Invalid value: %d Expected: %d",
252 val,
253 QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ALL);
254 status = QDF_STATUS_E_INVAL;
255 goto error;
256 }
257 pkt_type |= BIT(DATA_FRAME_TYPE);
258 }
259
260 if (tb[SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE]) {
261 val = nla_get_u32(tb[SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE]);
262
263 if (val != QCA_WLAN_VENDOR_MONITOR_CTRL_FRAME_TYPE_ALL) {
264 osif_err("Invalid value: %d Expected: %d",
265 val,
266 QCA_WLAN_VENDOR_MONITOR_CTRL_FRAME_TYPE_ALL);
267 status = QDF_STATUS_E_INVAL;
268 goto error;
269 }
270 pkt_type |= BIT(CTRL_FRAME_TYPE);
271 }
272
273 if (tb[SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE]) {
274 val = nla_get_u32(tb[SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE]);
275
276 if (val != QCA_WLAN_VENDOR_MONITOR_CTRL_FRAME_TYPE_ALL) {
277 osif_err("Invalid value: %d Expected: %d",
278 val,
279 QCA_WLAN_VENDOR_MONITOR_CTRL_FRAME_TYPE_ALL);
280 status = QDF_STATUS_E_INVAL;
281 goto error;
282 }
283 pkt_type |= BIT(CTRL_FRAME_TYPE);
284 }
285
286 if (pkt_type == 0) {
287 osif_err("Invalid config, pkt_type: %d", pkt_type);
288 status = QDF_STATUS_E_INVAL;
289 goto error;
290 }
291 osif_debug("start capture config pkt_type:0x%x", pkt_type);
292
293 filter.mode = MON_FILTER_PASS;
294 filter.fp_mgmt = pkt_type & BIT(MGMT_FRAME_TYPE) ? FILTER_MGMT_ALL : 0;
295 filter.fp_data = pkt_type & BIT(DATA_FRAME_TYPE) ? FILTER_DATA_ALL : 0;
296 filter.fp_ctrl = pkt_type & BIT(CTRL_FRAME_TYPE) ? FILTER_CTRL_ALL : 0;
297
298 status = cdp_start_local_pkt_capture(soc, OL_TXRX_PDEV_ID, &filter);
299
300 error:
301 return status;
302 }
303
os_if_dp_set_lpc_configure(struct wlan_objmgr_vdev * vdev,const void * data,int data_len)304 QDF_STATUS os_if_dp_set_lpc_configure(struct wlan_objmgr_vdev *vdev,
305 const void *data, int data_len)
306 {
307 struct nlattr *tb[SET_MONITOR_MODE_CONFIG_MAX + 1];
308 QDF_STATUS status = QDF_STATUS_SUCCESS;
309
310 if (wlan_cfg80211_nla_parse(tb, SET_MONITOR_MODE_CONFIG_MAX,
311 data, data_len, set_monitor_mode_policy)) {
312 osif_err("Invalid monitor attr");
313 status = QDF_STATUS_E_INVAL;
314 goto error;
315 }
316
317 status = os_if_dp_local_pkt_capture_start(vdev, tb);
318
319 error:
320 return status;
321 }
322
os_if_dp_local_pkt_capture_stop(struct wlan_objmgr_vdev * vdev)323 QDF_STATUS os_if_dp_local_pkt_capture_stop(struct wlan_objmgr_vdev *vdev)
324 {
325 QDF_STATUS status;
326 void *soc;
327
328 soc = cds_get_context(QDF_MODULE_ID_SOC);
329 if (!soc || !vdev)
330 return QDF_STATUS_E_INVAL;
331
332 status = os_if_stop_capture_allowed(vdev);
333 if (QDF_IS_STATUS_ERROR(status))
334 return status;
335
336 return cdp_stop_local_pkt_capture(soc, OL_TXRX_PDEV_ID);
337 }
338
os_if_dp_get_lpc_state(struct wlan_objmgr_vdev * vdev,const void * data,int data_len)339 QDF_STATUS os_if_dp_get_lpc_state(struct wlan_objmgr_vdev *vdev,
340 const void *data, int data_len)
341 {
342 struct wlan_objmgr_psoc *psoc;
343 struct vdev_osif_priv *osif_priv;
344 struct sk_buff *reply_skb;
345 uint32_t skb_len = NLMSG_HDRLEN, val;
346 QDF_STATUS status = QDF_STATUS_SUCCESS;
347 struct wireless_dev *wdev;
348 bool running;
349 void *soc;
350
351 psoc = wlan_vdev_get_psoc(vdev);
352 if (!psoc)
353 return QDF_STATUS_E_INVAL;
354
355 osif_priv = wlan_vdev_get_ospriv(vdev);
356 if (!osif_priv) {
357 osif_err("osif_priv is null");
358 return QDF_STATUS_E_INVAL;
359 }
360
361 wdev = osif_priv->wdev;
362 if (!wdev) {
363 osif_err("wireless dev is null");
364 return QDF_STATUS_E_INVAL;
365 }
366
367 soc = cds_get_context(QDF_MODULE_ID_SOC);
368 if (!soc)
369 return QDF_STATUS_E_INVAL;
370
371 /* Length of attribute QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_STATUS */
372 skb_len += nla_total_size(sizeof(u32));
373
374 reply_skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wdev->wiphy,
375 skb_len);
376 if (!reply_skb) {
377 osif_err("alloc reply skb failed");
378 return QDF_STATUS_E_NOMEM;
379 }
380
381 running = cdp_is_local_pkt_capture_running(soc, OL_TXRX_PDEV_ID);
382 val = running ? QCA_WLAN_VENDOR_MONITOR_MODE_CAPTURE_RUNNING :
383 QCA_WLAN_VENDOR_MONITOR_MODE_NO_CAPTURE_RUNNING;
384
385 if (nla_put_u32(reply_skb, GET_MONITOR_MODE_STATUS, val)) {
386 osif_err("nla put failed");
387 status = QDF_STATUS_E_INVAL;
388 goto fail;
389 }
390
391 if (wlan_cfg80211_vendor_cmd_reply(reply_skb))
392 status = QDF_STATUS_E_INVAL;
393
394 return status;
395 fail:
396 wlan_cfg80211_vendor_free_skb(reply_skb);
397 return status;
398 }
399
400