xref: /wlan-driver/qcacld-3.0/os_if/dp/src/os_if_dp_local_pkt_capture.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
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