1 /*
2 * Copyright (c) 2020, 2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for
6 * any purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
8 * copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 /**
21 * DOC: Implement mgmt txrx APIs which shall be used internally only
22 * in pkt_capture component.
23 * Note: These APIs should be never accessed out of pkt_capture component.
24 */
25
26 #include "wlan_pkt_capture_main.h"
27 #include "wlan_pkt_capture_priv.h"
28 #include "wlan_pkt_capture_mgmt_txrx.h"
29 #include "wlan_mlme_main.h"
30 #include "wlan_lmac_if_api.h"
31 #include "wlan_mgmt_txrx_utils_api.h"
32 #include "wlan_utility.h"
33 #include "cds_ieee80211_common.h"
34 #include "cdp_txrx_ctrl.h"
35
36 enum pkt_capture_tx_status
pkt_capture_mgmt_status_map(uint8_t status)37 pkt_capture_mgmt_status_map(uint8_t status)
38 {
39 enum pkt_capture_tx_status tx_status;
40
41 switch (status) {
42 case WMI_MGMT_TX_COMP_TYPE_COMPLETE_OK:
43 tx_status = pkt_capture_tx_status_ok;
44 break;
45 case WMI_MGMT_TX_COMP_TYPE_COMPLETE_NO_ACK:
46 tx_status = pkt_capture_tx_status_no_ack;
47 break;
48 default:
49 tx_status = pkt_capture_tx_status_discard;
50 break;
51 }
52
53 return tx_status;
54 }
55
56 /**
57 * pkt_capture_mgmtpkt_cb() - callback to process management packets
58 * for pkt capture mode
59 * @context: vdev handler
60 * @ppdev: unused param
61 * @nbuf_list: netbuf list
62 * @vdev_id: vdev id for which packet is captured
63 * @tid: tid number
64 * @ch_freq: channel frequency
65 * @pkt_format: Frame format
66 * @bssid:
67 * @tx_retry_cnt: tx retry count
68 *
69 * Return: none
70 */
71 static void
pkt_capture_mgmtpkt_cb(void * context,void * ppdev,void * nbuf_list,uint8_t vdev_id,uint8_t tid,uint16_t ch_freq,bool pkt_format,uint8_t * bssid,uint8_t tx_retry_cnt)72 pkt_capture_mgmtpkt_cb(void *context, void *ppdev, void *nbuf_list,
73 uint8_t vdev_id, uint8_t tid, uint16_t ch_freq,
74 bool pkt_format, uint8_t *bssid, uint8_t tx_retry_cnt)
75 {
76 struct pkt_capture_vdev_priv *vdev_priv;
77 struct wlan_objmgr_psoc *psoc = context;
78 struct pkt_capture_cb_context *cb_ctx;
79 struct wlan_objmgr_vdev *vdev;
80 qdf_nbuf_t msdu, next_buf;
81 uint32_t drop_count;
82
83 vdev = wlan_objmgr_get_vdev_by_opmode_from_psoc(psoc,
84 QDF_STA_MODE,
85 WLAN_PKT_CAPTURE_ID);
86 if (!vdev) {
87 pkt_capture_err("vdev is NULL");
88 goto free_buf;
89 }
90
91 vdev_priv = pkt_capture_vdev_get_priv(vdev);
92 if (!vdev_priv) {
93 pkt_capture_err("packet capture vdev priv is NULL");
94 goto release_vdev_ref;
95 }
96
97 cb_ctx = vdev_priv->cb_ctx;
98 if (!cb_ctx || !cb_ctx->mon_cb || !cb_ctx->mon_ctx) {
99 pkt_capture_err("mon cb params are NULL");
100 goto release_vdev_ref;
101 }
102
103 msdu = nbuf_list;
104 while (msdu) {
105 next_buf = qdf_nbuf_queue_next(msdu);
106 qdf_nbuf_set_next(msdu, NULL); /* Add NULL terminator */
107 pkt_capture_mon(cb_ctx, msdu, vdev, ch_freq);
108 msdu = next_buf;
109 }
110
111 wlan_objmgr_vdev_release_ref(vdev, WLAN_PKT_CAPTURE_ID);
112 return;
113
114 release_vdev_ref:
115 wlan_objmgr_vdev_release_ref(vdev, WLAN_PKT_CAPTURE_ID);
116 free_buf:
117 drop_count = pkt_capture_drop_nbuf_list(nbuf_list);
118 pkt_capture_debug("Dropped frames %u", drop_count);
119 }
120
121 /**
122 * pkt_capture_mgmtpkt_process() - process management packets
123 * for pkt capture mode
124 * @psoc: pointer to psoc object
125 * @txrx_status: mon_rx_status to update radiotap header
126 * @nbuf: netbuf
127 * @status: Tx status
128 *
129 * Return: QDF_STATUS Enumeration
130 */
131 static QDF_STATUS
pkt_capture_mgmtpkt_process(struct wlan_objmgr_psoc * psoc,struct mon_rx_status * txrx_status,qdf_nbuf_t nbuf,uint8_t status)132 pkt_capture_mgmtpkt_process(struct wlan_objmgr_psoc *psoc,
133 struct mon_rx_status *txrx_status,
134 qdf_nbuf_t nbuf, uint8_t status)
135 {
136 struct wlan_objmgr_vdev *vdev;
137 struct pkt_capture_mon_pkt *pkt;
138 uint32_t headroom;
139 uint8_t type, sub_type;
140 struct ieee80211_frame *wh;
141 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
142 struct wlan_objmgr_pdev *pdev;
143 cdp_config_param_type val;
144 tSirMacAuthFrameBody *auth;
145 struct pkt_capture_vdev_priv *vdev_priv;
146
147 vdev = wlan_objmgr_get_vdev_by_opmode_from_psoc(psoc,
148 QDF_STA_MODE,
149 WLAN_PKT_CAPTURE_ID);
150
151 if (!vdev) {
152 pkt_capture_err("vdev is NULL");
153 return QDF_STATUS_E_FAILURE;
154 }
155
156 vdev_priv = pkt_capture_vdev_get_priv(vdev);
157 if (!vdev_priv) {
158 pkt_capture_err("packet capture vdev priv is NULL");
159 return QDF_STATUS_E_FAILURE;
160 }
161
162 pdev = wlan_vdev_get_pdev(vdev);
163 if (!pdev) {
164 pkt_capture_err("pdev is NULL");
165 return QDF_STATUS_E_FAILURE;
166 }
167
168 wh = (struct ieee80211_frame *)(qdf_nbuf_data(nbuf));
169 type = (wh)->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
170 sub_type = (wh)->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
171
172 /*
173 * Update channel only if successful AUTH Resp is received.
174 * This is done so that EAPOL M1 data frame have correct
175 * channel
176 */
177 if ((type == IEEE80211_FC0_TYPE_MGT) &&
178 (sub_type == MGMT_SUBTYPE_AUTH)) {
179 uint8_t chan = wlan_freq_to_chan(txrx_status->chan_freq);
180
181 auth = (tSirMacAuthFrameBody *)(qdf_nbuf_data(nbuf) +
182 sizeof(tSirMacMgmtHdr));
183
184 if (auth->authTransactionSeqNumber == SIR_MAC_AUTH_FRAME_2 ||
185 auth->authTransactionSeqNumber == SIR_MAC_AUTH_FRAME_4) {
186 if (auth->authStatusCode == STATUS_SUCCESS) {
187 val.cdp_pdev_param_monitor_chan = chan;
188 cdp_txrx_set_pdev_param(
189 soc, wlan_objmgr_pdev_get_pdev_id(pdev),
190 CDP_MONITOR_CHANNEL, val);
191
192 val.cdp_pdev_param_mon_freq =
193 txrx_status->chan_freq;
194 cdp_txrx_set_pdev_param(
195 soc, wlan_objmgr_pdev_get_pdev_id(pdev),
196 CDP_MONITOR_FREQUENCY, val);
197 }
198 }
199 }
200
201 /*
202 * Update channel to last connected channel in case of assoc/reassoc
203 * response failure and save current chan in case of success
204 */
205 if ((type == IEEE80211_FC0_TYPE_MGT) &&
206 ((sub_type == MGMT_SUBTYPE_ASSOC_RESP) ||
207 (sub_type == MGMT_SUBTYPE_REASSOC_RESP))) {
208 if (qdf_nbuf_len(nbuf) < (sizeof(tSirMacMgmtHdr) +
209 SIR_MAC_ASSOC_RSP_STATUS_CODE_OFFSET)) {
210 pkt_capture_err("Packet length is less than expected");
211 qdf_nbuf_free(nbuf);
212 return QDF_STATUS_E_FAILURE;
213 }
214
215 status = (uint16_t)(*(qdf_nbuf_data(nbuf) +
216 sizeof(tSirMacMgmtHdr) +
217 SIR_MAC_ASSOC_RSP_STATUS_CODE_OFFSET));
218
219 if (status == STATUS_SUCCESS) {
220 vdev_priv->last_freq = vdev_priv->curr_freq;
221 vdev_priv->curr_freq = txrx_status->chan_freq;
222 } else {
223 uint8_t chan_num;
224
225 chan_num = wlan_reg_freq_to_chan(pdev,
226 vdev_priv->last_freq);
227
228 val.cdp_pdev_param_monitor_chan = chan_num;
229 cdp_txrx_set_pdev_param(
230 soc, wlan_objmgr_pdev_get_pdev_id(pdev),
231 CDP_MONITOR_CHANNEL, val);
232
233 val.cdp_pdev_param_mon_freq = vdev_priv->last_freq;
234 cdp_txrx_set_pdev_param(
235 soc, wlan_objmgr_pdev_get_pdev_id(pdev),
236 CDP_MONITOR_FREQUENCY, val);
237
238 vdev_priv->curr_freq = vdev_priv->last_freq;
239 }
240 }
241
242 /*
243 * Calculate the headroom and adjust head to prepare radiotap header
244 */
245 headroom = qdf_nbuf_headroom(nbuf);
246 qdf_nbuf_update_radiotap(txrx_status, nbuf, headroom);
247
248 pkt = pkt_capture_alloc_mon_pkt(vdev);
249 if (!pkt) {
250 wlan_objmgr_vdev_release_ref(vdev, WLAN_PKT_CAPTURE_ID);
251 return QDF_STATUS_E_FAILURE;
252 }
253
254 pkt->callback = pkt_capture_mgmtpkt_cb;
255 pkt->context = psoc;
256 pkt->monpkt = nbuf;
257 pkt->vdev_id = WLAN_INVALID_VDEV_ID;
258 pkt->tid = WLAN_INVALID_TID;
259 pkt->status = txrx_status->chan_freq;
260 pkt->pkt_format = PKTCAPTURE_PKT_FORMAT_80211;
261 pkt_capture_indicate_monpkt(vdev, pkt);
262
263 wlan_objmgr_vdev_release_ref(vdev, WLAN_PKT_CAPTURE_ID);
264 return QDF_STATUS_SUCCESS;
265 }
266
267 /**
268 * pkt_capture_is_rmf_enabled - API to check if rmf is enabled or not
269 * @pdev: pointer to pdev object
270 * @psoc: pointer to psoc object
271 * @addr: mac address
272 */
273 static bool
pkt_capture_is_rmf_enabled(struct wlan_objmgr_pdev * pdev,struct wlan_objmgr_psoc * psoc,uint8_t * addr)274 pkt_capture_is_rmf_enabled(struct wlan_objmgr_pdev *pdev,
275 struct wlan_objmgr_psoc *psoc,
276 uint8_t *addr)
277 {
278 struct pkt_psoc_priv *psoc_priv;
279 struct wlan_objmgr_vdev *vdev;
280 uint8_t vdev_id;
281 int rmf_enabled;
282
283 psoc_priv = pkt_capture_psoc_get_priv(psoc);
284 if (!psoc_priv) {
285 pkt_capture_err("psoc priv is NULL");
286 return false;
287 }
288
289 vdev = wlan_objmgr_get_vdev_by_macaddr_from_pdev(pdev,
290 addr,
291 WLAN_PKT_CAPTURE_ID);
292 if (!vdev) {
293 pkt_capture_err("vdev is NULL");
294 return false;
295 }
296
297 vdev_id = wlan_vdev_get_id(vdev);
298 wlan_objmgr_vdev_release_ref(vdev, WLAN_PKT_CAPTURE_ID);
299
300 rmf_enabled = psoc_priv->cb_obj.get_rmf_status(vdev_id);
301 if (rmf_enabled < 0) {
302 pkt_capture_err("unable to get rmf status");
303 return false;
304 }
305
306 return true;
307 }
308
309 /**
310 * pkt_capture_process_rmf_frame - process rmf frame
311 * @pdev: pointer to pdev object
312 * @psoc: pointer to psoc object
313 * @nbuf: netbuf
314 */
315 static QDF_STATUS
pkt_capture_process_rmf_frame(struct wlan_objmgr_pdev * pdev,struct wlan_objmgr_psoc * psoc,qdf_nbuf_t nbuf)316 pkt_capture_process_rmf_frame(struct wlan_objmgr_pdev *pdev,
317 struct wlan_objmgr_psoc *psoc,
318 qdf_nbuf_t nbuf)
319 {
320 tpSirMacFrameCtl pfc = (tpSirMacFrameCtl)(qdf_nbuf_data(nbuf));
321 uint8_t mic_len, hdr_len, pdev_id;
322 struct ieee80211_frame *wh;
323 uint8_t *orig_hdr;
324
325 wh = (struct ieee80211_frame *)qdf_nbuf_data(nbuf);
326
327 if (!QDF_IS_ADDR_BROADCAST(wh->i_addr1) &&
328 !IEEE80211_IS_MULTICAST(wh->i_addr1)) {
329 if (pfc->wep) {
330 QDF_STATUS status;
331
332 orig_hdr = (uint8_t *)qdf_nbuf_data(nbuf);
333 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
334 status = mlme_get_peer_mic_len(psoc, pdev_id,
335 wh->i_addr1,
336 &mic_len,
337 &hdr_len);
338 if (QDF_IS_STATUS_ERROR(status)) {
339 pkt_capture_err("Failed to get mic hdr");
340 return QDF_STATUS_E_FAILURE;
341 }
342
343 /* Strip privacy headers (and trailer)
344 * for a received frame
345 */
346 qdf_mem_move(orig_hdr + hdr_len, wh, sizeof(*wh));
347 qdf_nbuf_pull_head(nbuf, hdr_len);
348 qdf_nbuf_trim_tail(nbuf, mic_len);
349 }
350 } else {
351 qdf_nbuf_trim_tail(nbuf, IEEE80211_MMIE_LEN);
352 }
353
354 return QDF_STATUS_SUCCESS;
355 }
356
357 QDF_STATUS
pkt_capture_process_mgmt_tx_data(struct wlan_objmgr_pdev * pdev,struct mgmt_offload_event_params * params,qdf_nbuf_t nbuf,uint8_t status)358 pkt_capture_process_mgmt_tx_data(struct wlan_objmgr_pdev *pdev,
359 struct mgmt_offload_event_params *params,
360 qdf_nbuf_t nbuf,
361 uint8_t status)
362 {
363 struct mon_rx_status txrx_status = {0};
364 struct wlan_objmgr_psoc *psoc;
365 tpSirMacFrameCtl pfc = (tpSirMacFrameCtl)(qdf_nbuf_data(nbuf));
366 struct ieee80211_frame *wh;
367 uint16_t rate;
368
369 psoc = wlan_pdev_get_psoc(pdev);
370 if (!psoc) {
371 pkt_capture_err("psoc is NULL");
372 return QDF_STATUS_E_FAILURE;
373 }
374
375 wh = (struct ieee80211_frame *)qdf_nbuf_data(nbuf);
376
377 if ((pfc->type == IEEE80211_FC0_TYPE_MGT) &&
378 (pfc->subType == SIR_MAC_MGMT_DISASSOC ||
379 pfc->subType == SIR_MAC_MGMT_DEAUTH ||
380 pfc->subType == SIR_MAC_MGMT_ACTION)) {
381 if (pkt_capture_is_rmf_enabled(pdev, psoc, wh->i_addr2)) {
382 QDF_STATUS status;
383
384 status = pkt_capture_process_rmf_frame(pdev, psoc,
385 nbuf);
386 if (QDF_IS_STATUS_ERROR(status))
387 return status;
388 }
389 }
390
391 txrx_status.tsft = (u_int64_t)params->tsf_l32;
392 txrx_status.chan_num = wlan_reg_freq_to_chan(pdev, params->chan_freq);
393 txrx_status.chan_freq = params->chan_freq;
394 if (params->rssi == INVALID_RSSI_FOR_TX)
395 /* RSSI -128 is invalid rssi for TX, make it 0 here,
396 * will be normalized during radiotap updation
397 */
398 txrx_status.ant_signal_db = 0;
399 else
400 txrx_status.ant_signal_db = params->rssi;
401
402 txrx_status.rssi_comb = txrx_status.ant_signal_db;
403 txrx_status.nr_ant = 1;
404 rate = params->rate_kbps * 2;
405 /* params->rate is in Kbps, convert into Mbps */
406 txrx_status.rate = (uint8_t)(rate / 1000);
407
408 txrx_status.rtap_flags |=
409 ((txrx_status.rate == 12 /* Mbps */) ? BIT(1) : 0);
410
411 if (txrx_status.rate == 12)
412 txrx_status.ofdm_flag = 1;
413 else
414 txrx_status.cck_flag = 1;
415
416 txrx_status.tx_status = status;
417 txrx_status.tx_retry_cnt = params->tx_retry_cnt;
418 txrx_status.add_rtap_ext = true;
419
420 wh = (struct ieee80211_frame *)qdf_nbuf_data(nbuf);
421 wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
422
423 return pkt_capture_mgmtpkt_process(psoc, &txrx_status,
424 nbuf, status);
425 }
426
pkt_capture_mgmt_tx(struct wlan_objmgr_pdev * pdev,qdf_nbuf_t nbuf,uint16_t chan_freq,uint8_t preamble_type)427 void pkt_capture_mgmt_tx(struct wlan_objmgr_pdev *pdev,
428 qdf_nbuf_t nbuf,
429 uint16_t chan_freq,
430 uint8_t preamble_type)
431 {
432 struct mgmt_offload_event_params params = {0};
433 tpSirMacFrameCtl pfc = (tpSirMacFrameCtl)(qdf_nbuf_data(nbuf));
434 struct pkt_capture_vdev_priv *vdev_priv;
435 struct wlan_objmgr_vdev *vdev;
436 qdf_nbuf_t wbuf;
437 int nbuf_len;
438 QDF_STATUS status = QDF_STATUS_SUCCESS;
439
440 if (!pdev) {
441 pkt_capture_err("pdev is NULL");
442 return;
443 }
444
445 vdev = pkt_capture_get_vdev();
446 status = pkt_capture_vdev_get_ref(vdev);
447 if (QDF_IS_STATUS_ERROR(status)) {
448 pkt_capture_err("failed to get vdev ref");
449 return;
450 }
451
452 vdev_priv = pkt_capture_vdev_get_priv(vdev);
453 if (!vdev_priv) {
454 pkt_capture_err("packet capture vdev priv is NULL");
455 pkt_capture_vdev_put_ref(vdev);
456 return;
457 }
458
459 if (pfc->type == IEEE80211_FC0_TYPE_MGT &&
460 !(vdev_priv->frame_filter.mgmt_tx_frame_filter &
461 PKT_CAPTURE_MGMT_FRAME_TYPE_ALL))
462 goto exit;
463
464 if (pfc->type == IEEE80211_FC0_TYPE_CTL &&
465 !vdev_priv->frame_filter.ctrl_tx_frame_filter)
466 goto exit;
467
468 nbuf_len = qdf_nbuf_len(nbuf);
469 wbuf = qdf_nbuf_alloc(NULL, roundup(nbuf_len + RESERVE_BYTES, 4),
470 RESERVE_BYTES, 4, false);
471 if (!wbuf) {
472 pkt_capture_err("Failed to allocate wbuf for mgmt len(%u)",
473 nbuf_len);
474 goto exit;
475 }
476
477 qdf_nbuf_put_tail(wbuf, nbuf_len);
478 qdf_mem_copy(qdf_nbuf_data(wbuf), qdf_nbuf_data(nbuf), nbuf_len);
479
480 params.chan_freq = chan_freq;
481 /*
482 * Filling Tpc in rssi field.
483 * As Tpc is not available, filling with default value of tpc
484 */
485 params.rssi = 0;
486 /* Assigning the local timestamp as TSF timestamp is not available*/
487 params.tsf_l32 = (uint32_t)jiffies;
488
489 if (preamble_type == (1 << WMI_RATE_PREAMBLE_CCK))
490 params.rate_kbps = 1000; /* Rate is 1 Mbps for CCK */
491 else
492 params.rate_kbps = 6000; /* Rate is 6 Mbps for OFDM */
493
494 /*
495 * The mgmt tx packet is send to mon interface before tx completion.
496 * we do not have status for this packet, using magic number(0xFF)
497 * as status for mgmt tx packet
498 */
499 if (QDF_STATUS_SUCCESS !=
500 pkt_capture_process_mgmt_tx_data(pdev, ¶ms, wbuf, 0xFF))
501 qdf_nbuf_free(wbuf);
502 exit:
503 pkt_capture_vdev_put_ref(vdev);
504 }
505
506 void
pkt_capture_mgmt_tx_completion(struct wlan_objmgr_pdev * pdev,uint32_t desc_id,uint32_t status,struct mgmt_offload_event_params * params)507 pkt_capture_mgmt_tx_completion(struct wlan_objmgr_pdev *pdev,
508 uint32_t desc_id,
509 uint32_t status,
510 struct mgmt_offload_event_params *params)
511 {
512 struct pkt_capture_vdev_priv *vdev_priv;
513 struct wlan_objmgr_vdev *vdev;
514 tpSirMacFrameCtl pfc;
515 qdf_nbuf_t wbuf, nbuf;
516 int nbuf_len;
517 QDF_STATUS ret = QDF_STATUS_SUCCESS;
518
519 if (!pdev) {
520 pkt_capture_err("pdev is NULL");
521 return;
522 }
523
524 vdev = pkt_capture_get_vdev();
525 ret = pkt_capture_vdev_get_ref(vdev);
526 if (QDF_IS_STATUS_ERROR(ret)) {
527 pkt_capture_err("failed to get vdev ref");
528 return;
529 }
530
531 vdev_priv = pkt_capture_vdev_get_priv(vdev);
532 if (!vdev_priv) {
533 pkt_capture_err("packet capture vdev priv is NULL");
534 pkt_capture_vdev_put_ref(vdev);
535 return;
536 }
537
538 nbuf = mgmt_txrx_get_nbuf(pdev, desc_id);
539 if (!nbuf)
540 goto exit;
541
542 pfc = (tpSirMacFrameCtl)(qdf_nbuf_data(nbuf));
543 if (pfc->type == IEEE80211_FC0_TYPE_MGT &&
544 !(vdev_priv->frame_filter.mgmt_tx_frame_filter &
545 PKT_CAPTURE_MGMT_FRAME_TYPE_ALL))
546 goto exit;
547
548 if (pfc->type == IEEE80211_FC0_TYPE_CTL &&
549 !vdev_priv->frame_filter.ctrl_tx_frame_filter)
550 goto exit;
551
552 nbuf_len = qdf_nbuf_len(nbuf);
553 wbuf = qdf_nbuf_alloc(NULL, roundup(nbuf_len + RESERVE_BYTES, 4),
554 RESERVE_BYTES, 4, false);
555 if (!wbuf) {
556 pkt_capture_err("Failed to allocate wbuf for mgmt len(%u)",
557 nbuf_len);
558 goto exit;
559 }
560
561 qdf_nbuf_put_tail(wbuf, nbuf_len);
562 qdf_mem_copy(qdf_nbuf_data(wbuf), qdf_nbuf_data(nbuf), nbuf_len);
563
564 if (QDF_STATUS_SUCCESS !=
565 pkt_capture_process_mgmt_tx_data(
566 pdev, params, wbuf,
567 pkt_capture_mgmt_status_map(status)))
568 qdf_nbuf_free(wbuf);
569
570 exit:
571 pkt_capture_vdev_put_ref(vdev);
572 }
573
574 /**
575 * pkt_capture_is_beacon_forward_enable() - API to check whether particular
576 * beacon needs to be forwarded on mon interface based on vendor command
577 * @vdev: vdev object
578 * @wbuf: netbuf
579 *
580 * Return: bool
581 */
582 static bool
pkt_capture_is_beacon_forward_enable(struct wlan_objmgr_vdev * vdev,qdf_nbuf_t wbuf)583 pkt_capture_is_beacon_forward_enable(struct wlan_objmgr_vdev *vdev,
584 qdf_nbuf_t wbuf)
585 {
586 struct pkt_capture_vdev_priv *vdev_priv;
587 struct qdf_mac_addr connected_bssid = {0};
588 tpSirMacMgmtHdr mac_hdr;
589 bool my_beacon = false;
590
591 vdev_priv = pkt_capture_vdev_get_priv(vdev);
592 if (!vdev_priv) {
593 pkt_capture_err("packet capture vdev priv is NULL");
594 return false;
595 }
596
597 mac_hdr = (tpSirMacMgmtHdr)(qdf_nbuf_data(wbuf));
598 wlan_vdev_get_bss_peer_mac(vdev, &connected_bssid);
599
600 if (qdf_is_macaddr_equal((struct qdf_mac_addr *)mac_hdr->bssId,
601 &connected_bssid))
602 my_beacon = true;
603
604 if (((vdev_priv->frame_filter.mgmt_rx_frame_filter &
605 PKT_CAPTURE_MGMT_CONNECT_BEACON) ||
606 vdev_priv->frame_filter.connected_beacon_interval) && my_beacon)
607 return true;
608
609 if (vdev_priv->frame_filter.mgmt_rx_frame_filter &
610 PKT_CAPTURE_MGMT_CONNECT_SCAN_BEACON && !my_beacon)
611 return true;
612
613 return false;
614 }
615
616 #ifdef DP_MON_RSSI_IN_DBM
617 #define PKT_CAPTURE_FILL_RSSI(rx_params) \
618 ((rx_params)->snr + NORMALIZED_TO_NOISE_FLOOR)
619 #else
620 #define PKT_CAPTURE_FILL_RSSI(rx_status) \
621 ((rx_params)->snr)
622 #endif
623
624 /**
625 * pkt_capture_mgmt_rx_data_cb() - process management rx packets
626 * @psoc: psoc object
627 * @peer: Peer object
628 * @wbuf: netbuf
629 * @rx_params: mgmt rx event params
630 * @frm_type: frame type
631 *
632 * Return: none
633 */
634 static QDF_STATUS
pkt_capture_mgmt_rx_data_cb(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_peer * peer,qdf_nbuf_t wbuf,struct mgmt_rx_event_params * rx_params,enum mgmt_frame_type frm_type)635 pkt_capture_mgmt_rx_data_cb(struct wlan_objmgr_psoc *psoc,
636 struct wlan_objmgr_peer *peer,
637 qdf_nbuf_t wbuf,
638 struct mgmt_rx_event_params *rx_params,
639 enum mgmt_frame_type frm_type)
640 {
641 struct mon_rx_status txrx_status = {0};
642 struct pkt_capture_vdev_priv *vdev_priv;
643 struct ieee80211_frame *wh;
644 tpSirMacFrameCtl pfc;
645 qdf_nbuf_t nbuf;
646 int buf_len;
647 struct wlan_objmgr_vdev *vdev;
648 struct wlan_objmgr_pdev *pdev;
649 QDF_STATUS status = QDF_STATUS_SUCCESS;
650
651 vdev = pkt_capture_get_vdev();
652 status = pkt_capture_vdev_get_ref(vdev);
653 if (QDF_IS_STATUS_ERROR(status)) {
654 pkt_capture_err("failed to get vdev ref");
655 qdf_nbuf_free(wbuf);
656 return QDF_STATUS_E_FAILURE;
657 }
658
659 vdev_priv = pkt_capture_vdev_get_priv(vdev);
660 if (!vdev_priv) {
661 pkt_capture_err("packet capture vdev priv is NULL");
662 pkt_capture_vdev_put_ref(vdev);
663 qdf_nbuf_free(wbuf);
664 return QDF_STATUS_E_FAILURE;
665 }
666
667 pfc = (tpSirMacFrameCtl)(qdf_nbuf_data(wbuf));
668
669 if (pfc->type == SIR_MAC_CTRL_FRAME &&
670 !vdev_priv->frame_filter.ctrl_rx_frame_filter)
671 goto exit;
672
673 if (pfc->type == SIR_MAC_MGMT_FRAME &&
674 !vdev_priv->frame_filter.mgmt_rx_frame_filter)
675 goto exit;
676
677 if (pfc->type == SIR_MAC_MGMT_FRAME) {
678 if (pfc->subType == SIR_MAC_MGMT_BEACON) {
679 if (!pkt_capture_is_beacon_forward_enable(vdev, wbuf))
680 goto exit;
681 } else {
682 if (!((vdev_priv->frame_filter.mgmt_rx_frame_filter &
683 PKT_CAPTURE_MGMT_FRAME_TYPE_ALL) ||
684 (vdev_priv->frame_filter.mgmt_rx_frame_filter &
685 PKT_CAPTURE_MGMT_CONNECT_NO_BEACON)))
686 goto exit;
687 }
688 }
689
690 buf_len = qdf_nbuf_len(wbuf);
691 nbuf = qdf_nbuf_alloc(NULL, roundup(
692 buf_len + RESERVE_BYTES, 4),
693 RESERVE_BYTES, 4, false);
694 if (!nbuf) {
695 pkt_capture_vdev_put_ref(vdev);
696 qdf_nbuf_free(wbuf);
697 return QDF_STATUS_E_FAILURE;
698 }
699
700 qdf_nbuf_put_tail(nbuf, buf_len);
701 qdf_mem_copy(qdf_nbuf_data(nbuf), qdf_nbuf_data(wbuf), buf_len);
702
703 qdf_nbuf_free(wbuf);
704
705 pfc = (tpSirMacFrameCtl)(qdf_nbuf_data(nbuf));
706 wh = (struct ieee80211_frame *)qdf_nbuf_data(nbuf);
707
708 pdev = wlan_vdev_get_pdev(vdev);
709 pkt_capture_vdev_put_ref(vdev);
710
711 if ((pfc->type == IEEE80211_FC0_TYPE_MGT) &&
712 (pfc->subType == SIR_MAC_MGMT_DISASSOC ||
713 pfc->subType == SIR_MAC_MGMT_DEAUTH ||
714 pfc->subType == SIR_MAC_MGMT_ACTION)) {
715 if (pkt_capture_is_rmf_enabled(pdev, psoc, wh->i_addr1)) {
716 QDF_STATUS status;
717
718 status = pkt_capture_process_rmf_frame(pdev, psoc,
719 nbuf);
720 if (QDF_IS_STATUS_ERROR(status))
721 return status;
722 }
723 }
724
725 txrx_status.tsft = (u_int64_t)rx_params->tsf_l32;
726 txrx_status.chan_num = rx_params->channel;
727 txrx_status.chan_freq = rx_params->chan_freq;
728 /* rx_params->rate is in Kbps, convert into Mbps */
729 txrx_status.rate = (rx_params->rate / 1000);
730 txrx_status.ant_signal_db = rx_params->snr;
731 txrx_status.chan_noise_floor = NORMALIZED_TO_NOISE_FLOOR;
732 txrx_status.rssi_comb = PKT_CAPTURE_FILL_RSSI(rx_params);
733 txrx_status.nr_ant = 1;
734 txrx_status.rtap_flags |=
735 ((txrx_status.rate == 6 /* Mbps */) ? BIT(1) : 0);
736
737 if (rx_params->phy_mode != PKTCAPTURE_RATECODE_CCK)
738 txrx_status.ofdm_flag = 1;
739 else
740 txrx_status.cck_flag = 1;
741
742 /* Convert rate from Mbps to 500 Kbps */
743 txrx_status.rate = txrx_status.rate * 2;
744
745 wh = (struct ieee80211_frame *)qdf_nbuf_data(nbuf);
746 wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
747
748 if (QDF_STATUS_SUCCESS !=
749 pkt_capture_mgmtpkt_process(psoc, &txrx_status, nbuf, 0))
750 qdf_nbuf_free(nbuf);
751
752 return QDF_STATUS_SUCCESS;
753 exit:
754 pkt_capture_vdev_put_ref(vdev);
755 qdf_nbuf_free(wbuf);
756 return QDF_STATUS_SUCCESS;
757 }
758
pkt_capture_mgmt_rx_ops(struct wlan_objmgr_psoc * psoc,bool is_register)759 QDF_STATUS pkt_capture_mgmt_rx_ops(struct wlan_objmgr_psoc *psoc,
760 bool is_register)
761 {
762 struct mgmt_txrx_mgmt_frame_cb_info frm_cb_info[2];
763 QDF_STATUS status;
764 int num_of_entries;
765
766 frm_cb_info[0].frm_type = MGMT_FRAME_TYPE_ALL;
767 frm_cb_info[0].mgmt_rx_cb = pkt_capture_mgmt_rx_data_cb;
768 frm_cb_info[1].frm_type = MGMT_CTRL_FRAME;
769 frm_cb_info[1].mgmt_rx_cb = pkt_capture_mgmt_rx_data_cb;
770 num_of_entries = 2;
771
772 if (is_register)
773 status = wlan_mgmt_txrx_register_rx_cb(
774 psoc, WLAN_UMAC_COMP_PKT_CAPTURE,
775 frm_cb_info, num_of_entries);
776 else
777 status = wlan_mgmt_txrx_deregister_rx_cb(
778 psoc, WLAN_UMAC_COMP_PKT_CAPTURE,
779 frm_cb_info, num_of_entries);
780
781 return status;
782 }
783