1 /*
2 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all
7 * copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
17 */
18 /**
19 * DOC: os_if_dp.c
20 *
21 *
22 */
23 #include "os_if_dp.h"
24 #include "wlan_nlink_srv.h"
25 #include <wlan_cfg80211.h>
26 #include <wlan_osif_priv.h>
27 #include <cdp_txrx_cmn.h>
28 #include "qca_vendor.h"
29 #include "wlan_dp_ucfg_api.h"
30 #include "osif_vdev_sync.h"
31 #include "osif_sync.h"
32 #include <net/netevent.h>
33 #include "wlan_osif_request_manager.h"
34 #include <ol_defines.h>
35
36 /*
37 * define short names for the global vendor params
38 * used by wlan_hdd_cfg80211_setarp_stats_cmd()
39 */
40 #define STATS_GET_INVALID \
41 QCA_ATTR_NUD_STATS_SET_INVALID
42 #define COUNT_FROM_NETDEV \
43 QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_FROM_NETDEV
44 #define COUNT_TO_LOWER_MAC \
45 QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TO_LOWER_MAC
46 #define RX_COUNT_BY_LOWER_MAC \
47 QCA_ATTR_NUD_STATS_ARP_REQ_RX_COUNT_BY_LOWER_MAC
48 #define COUNT_TX_SUCCESS \
49 QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TX_SUCCESS
50 #define RSP_RX_COUNT_BY_LOWER_MAC \
51 QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_LOWER_MAC
52 #define RSP_RX_COUNT_BY_UPPER_MAC \
53 QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_UPPER_MAC
54 #define RSP_COUNT_TO_NETDEV \
55 QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_TO_NETDEV
56 #define RSP_COUNT_OUT_OF_ORDER_DROP \
57 QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_OUT_OF_ORDER_DROP
58 #define AP_LINK_ACTIVE \
59 QCA_ATTR_NUD_STATS_AP_LINK_ACTIVE
60 #define AP_LINK_DAD \
61 QCA_ATTR_NUD_STATS_IS_DAD
62 #define DATA_PKT_STATS \
63 QCA_ATTR_NUD_STATS_DATA_PKT_STATS
64 #define STATS_GET_MAX \
65 QCA_ATTR_NUD_STATS_GET_MAX
66
67 #define CHECK_STATS_INVALID \
68 QCA_ATTR_CONNECTIVITY_CHECK_STATS_INVALID
69 #define CHECK_STATS_PKT_TYPE \
70 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_TYPE
71 #define CHECK_STATS_PKT_DNS_DOMAIN_NAME \
72 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DNS_DOMAIN_NAME
73 #define CHECK_STATS_PKT_SRC_PORT \
74 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_SRC_PORT
75 #define CHECK_STATS_PKT_DEST_PORT \
76 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_PORT
77 #define CHECK_STATS_PKT_DEST_IPV4 \
78 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_IPV4
79 #define CHECK_STATS_PKT_DEST_IPV6 \
80 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_IPV6
81 #define CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV \
82 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV
83 #define CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC \
84 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC
85 #define CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC \
86 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC
87 #define CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS \
88 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS
89 #define CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC \
90 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC
91 #define CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC \
92 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC
93 #define CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV \
94 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV
95 #define CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP \
96 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP
97 #define CHECK_DATA_STATS_MAX \
98 QCA_ATTR_CONNECTIVITY_CHECK_DATA_STATS_MAX
99
100 #define STATS_SET_INVALID \
101 QCA_ATTR_NUD_STATS_SET_INVALID
102 #define STATS_SET_START \
103 QCA_ATTR_NUD_STATS_SET_START
104 #define STATS_GW_IPV4 \
105 QCA_ATTR_NUD_STATS_GW_IPV4
106 #define STATS_SET_DATA_PKT_INFO \
107 QCA_ATTR_NUD_STATS_SET_DATA_PKT_INFO
108 #define STATS_SET_MAX \
109 QCA_ATTR_NUD_STATS_SET_MAX
110
111 const struct nla_policy
112 dp_set_nud_stats_policy[STATS_SET_MAX + 1] = {
113 [STATS_SET_START] = {.type = NLA_FLAG },
114 [STATS_GW_IPV4] = {.type = NLA_U32 },
115 [STATS_SET_DATA_PKT_INFO] = {.type = NLA_NESTED },
116 };
117
118 /* define short names for the global vendor params */
119 #define CONNECTIVITY_STATS_SET_INVALID \
120 QCA_ATTR_CONNECTIVITY_CHECK_STATS_SET_INVALID
121 #define STATS_PKT_INFO_TYPE \
122 QCA_ATTR_CONNECTIVITY_CHECK_STATS_STATS_PKT_INFO_TYPE
123 #define STATS_DNS_DOMAIN_NAME \
124 QCA_ATTR_CONNECTIVITY_CHECK_STATS_DNS_DOMAIN_NAME
125 #define STATS_SRC_PORT \
126 QCA_ATTR_CONNECTIVITY_CHECK_STATS_SRC_PORT
127 #define STATS_DEST_PORT \
128 QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_PORT
129 #define STATS_DEST_IPV4 \
130 QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_IPV4
131 #define STATS_DEST_IPV6 \
132 QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_IPV6
133 #define CONNECTIVITY_STATS_SET_MAX \
134 QCA_ATTR_CONNECTIVITY_CHECK_STATS_SET_MAX
135
136 const struct nla_policy
137 dp_set_connectivity_check_stats[CONNECTIVITY_STATS_SET_MAX + 1] = {
138 [STATS_PKT_INFO_TYPE] = {.type = NLA_U32 },
139 [STATS_DNS_DOMAIN_NAME] = {.type = NLA_NUL_STRING,
140 .len = DNS_DOMAIN_NAME_MAX_LEN },
141 [STATS_SRC_PORT] = {.type = NLA_U32 },
142 [STATS_DEST_PORT] = {.type = NLA_U32 },
143 [STATS_DEST_IPV4] = {.type = NLA_U32 },
144 [STATS_DEST_IPV6] = {.type = NLA_BINARY,
145 .len = ICMPV6_ADDR_LEN },
146 };
147
148 #ifdef WLAN_FEATURE_DP_BUS_BANDWIDTH
149 /**
150 * osif_dp_send_tcp_param_update_event() - Send vendor event to update
151 * TCP parameter through Wi-Fi HAL
152 * @psoc: Pointer to psoc context
153 * @data: Parameters to update
154 * @dir: Direction(tx/rx) to update
155 *
156 * Return: None
157 */
158 static
osif_dp_send_tcp_param_update_event(struct wlan_objmgr_psoc * psoc,union wlan_tp_data * data,uint8_t dir)159 void osif_dp_send_tcp_param_update_event(struct wlan_objmgr_psoc *psoc,
160 union wlan_tp_data *data,
161 uint8_t dir)
162 {
163 struct sk_buff *vendor_event;
164 struct wlan_objmgr_pdev *pdev;
165 struct pdev_osif_priv *os_priv;
166 uint32_t event_len;
167 bool tcp_limit_output = false;
168 bool tcp_del_ack_ind_enabled = false;
169 bool tcp_adv_win_scl_enabled = false;
170 enum wlan_tp_level next_tp_level = WLAN_SVC_TP_NONE;
171 enum qca_nl80211_vendor_subcmds_index index =
172 QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT_INDEX;
173
174 event_len = sizeof(uint8_t) + sizeof(uint8_t) + NLMSG_HDRLEN;
175 pdev = wlan_objmgr_get_pdev_by_id(psoc, 0, WLAN_DP_ID);
176 if (!pdev)
177 return;
178
179 os_priv = wlan_pdev_get_ospriv(pdev);
180
181 if (dir == 0) /*TX Flow */ {
182 struct wlan_tx_tp_data *tx_tp_data =
183 (struct wlan_tx_tp_data *)data;
184
185 next_tp_level = tx_tp_data->level;
186
187 if (tx_tp_data->tcp_limit_output) {
188 /* TCP_LIMIT_OUTPUT_BYTES */
189 event_len += sizeof(uint32_t);
190 tcp_limit_output = true;
191 }
192 } else if (dir == 1) /* RX Flow */ {
193 struct wlan_rx_tp_data *rx_tp_data =
194 (struct wlan_rx_tp_data *)data;
195
196 next_tp_level = rx_tp_data->level;
197
198 if (rx_tp_data->rx_tp_flags & TCP_DEL_ACK_IND_MASK) {
199 event_len += sizeof(uint32_t); /* TCP_DELACK_SEG */
200 tcp_del_ack_ind_enabled = true;
201 }
202 if (rx_tp_data->rx_tp_flags & TCP_ADV_WIN_SCL_MASK) {
203 event_len += sizeof(uint32_t); /* TCP_ADV_WIN_SCALE */
204 tcp_adv_win_scl_enabled = true;
205 }
206 } else {
207 dp_err("Invalid Direction [%d]", dir);
208 wlan_objmgr_pdev_release_ref(pdev, WLAN_DP_ID);
209 return;
210 }
211
212 vendor_event = wlan_cfg80211_vendor_event_alloc(os_priv->wiphy,
213 NULL, event_len,
214 index, GFP_KERNEL);
215
216 if (!vendor_event) {
217 dp_err("wlan_cfg80211_vendor_event_alloc failed");
218 wlan_objmgr_pdev_release_ref(pdev, WLAN_DP_ID);
219 return;
220 }
221
222 if (nla_put_u8(
223 vendor_event,
224 QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_DIRECTION,
225 dir))
226 goto tcp_param_change_nla_failed;
227
228 if (nla_put_u8(
229 vendor_event,
230 QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_THROUGHPUT_LEVEL,
231 (next_tp_level == WLAN_SVC_TP_LOW ?
232 QCA_WLAN_THROUGHPUT_LEVEL_LOW :
233 QCA_WLAN_THROUGHPUT_LEVEL_HIGH)))
234 goto tcp_param_change_nla_failed;
235
236 if (tcp_limit_output &&
237 nla_put_u32(
238 vendor_event,
239 QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_TCP_LIMIT_OUTPUT_BYTES,
240 (next_tp_level == WLAN_SVC_TP_LOW ?
241 TCP_LIMIT_OUTPUT_BYTES_LOW :
242 TCP_LIMIT_OUTPUT_BYTES_HI)))
243 goto tcp_param_change_nla_failed;
244
245 if (tcp_del_ack_ind_enabled &&
246 (nla_put_u32(
247 vendor_event,
248 QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_TCP_DELACK_SEG,
249 (next_tp_level == WLAN_SVC_TP_LOW ?
250 TCP_DEL_ACK_LOW : TCP_DEL_ACK_HI))))
251 goto tcp_param_change_nla_failed;
252
253 if (tcp_adv_win_scl_enabled &&
254 (nla_put_u32(
255 vendor_event,
256 QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_TCP_ADV_WIN_SCALE,
257 (next_tp_level == WLAN_SVC_TP_LOW ?
258 WIN_SCALE_LOW : WIN_SCALE_HI))))
259 goto tcp_param_change_nla_failed;
260
261 wlan_cfg80211_vendor_event(vendor_event, GFP_KERNEL);
262 wlan_objmgr_pdev_release_ref(pdev, WLAN_DP_ID);
263 return;
264
265 tcp_param_change_nla_failed:
266 wlan_objmgr_pdev_release_ref(pdev, WLAN_DP_ID);
267 dp_err("nla_put api failed");
268 wlan_cfg80211_vendor_free_skb(vendor_event);
269 }
270 #else
271 static
osif_dp_send_tcp_param_update_event(struct wlan_objmgr_psoc * psoc,union wlan_tp_data * data,uint8_t dir)272 void osif_dp_send_tcp_param_update_event(struct wlan_objmgr_psoc *psoc,
273 union wlan_tp_data *data,
274 uint8_t dir)
275 {
276 }
277 #endif /*WLAN_FEATURE_DP_BUS_BANDWIDTH*/
278
279 /**
280 * osif_dp_get_net_dev_from_vdev() - Get netdev object from vdev
281 * @vdev: Pointer to vdev manager
282 * @out_net_dev: Pointer to output netdev
283 *
284 * Return: 0 on success, error code on failure
285 */
osif_dp_get_net_dev_from_vdev(struct wlan_objmgr_vdev * vdev,struct net_device ** out_net_dev)286 static int osif_dp_get_net_dev_from_vdev(struct wlan_objmgr_vdev *vdev,
287 struct net_device **out_net_dev)
288 {
289 struct vdev_osif_priv *priv;
290
291 if (!vdev)
292 return -EINVAL;
293
294 priv = wlan_vdev_get_ospriv(vdev);
295 if (!priv || !priv->wdev || !priv->wdev->netdev)
296 return -EINVAL;
297
298 *out_net_dev = priv->wdev->netdev;
299
300 return 0;
301 }
302
303 /**
304 * osif_dp_process_mic_error() - Indicate mic error to supplicant
305 * @info: MIC error information
306 * @vdev: vdev handle
307 *
308 * Return: None
309 */
310 static void
osif_dp_process_mic_error(struct dp_mic_error_info * info,struct wlan_objmgr_vdev * vdev)311 osif_dp_process_mic_error(struct dp_mic_error_info *info,
312 struct wlan_objmgr_vdev *vdev)
313 {
314 struct net_device *dev;
315 struct osif_vdev_sync *vdev_sync;
316 int errno;
317
318 errno = osif_dp_get_net_dev_from_vdev(vdev, &dev);
319 if (errno) {
320 dp_err("failed to get netdev");
321 return;
322 }
323 if (osif_vdev_sync_op_start(dev, &vdev_sync))
324 return;
325
326 /* inform mic failure to nl80211 */
327 cfg80211_michael_mic_failure(dev,
328 (uint8_t *)&info->ta_mac_addr,
329 info->multicast ?
330 NL80211_KEYTYPE_GROUP :
331 NL80211_KEYTYPE_PAIRWISE,
332 info->key_id,
333 info->tsc,
334 GFP_KERNEL);
335 osif_vdev_sync_op_stop(vdev_sync);
336 }
337
338
339 /**
340 * osif_dp_get_arp_stats_event_handler() - ARP get stats event handler
341 * @psoc: psoc handle
342 * @rsp: Get ARP stats response
343 *
344 * Return: None
345 */
osif_dp_get_arp_stats_event_handler(struct wlan_objmgr_psoc * psoc,struct dp_rsp_stats * rsp)346 static void osif_dp_get_arp_stats_event_handler(struct wlan_objmgr_psoc *psoc,
347 struct dp_rsp_stats *rsp)
348 {
349 struct osif_request *request = NULL;
350 void *context;
351
352 context = ucfg_dp_get_arp_request_ctx(psoc);
353 if (!context)
354 return;
355
356 request = osif_request_get(context);
357 if (!request)
358 return;
359
360 ucfg_dp_get_arp_stats_event_handler(psoc, rsp);
361
362 osif_request_complete(request);
363 osif_request_put(request);
364 }
365
366 #ifdef WLAN_NUD_TRACKING
367 /**
368 * nud_state_osif_to_dp() - convert os_if to enum
369 * @curr_state: Current NUD state
370 *
371 * Return: DP enum equivalent to NUD state
372 */
nud_state_osif_to_dp(uint8_t curr_state)373 static inline enum dp_nud_state nud_state_osif_to_dp(uint8_t curr_state)
374 {
375 switch (curr_state) {
376 case NUD_NONE:
377 return DP_NUD_NONE;
378 case NUD_INCOMPLETE:
379 return DP_NUD_INCOMPLETE;
380 case NUD_REACHABLE:
381 return DP_NUD_REACHABLE;
382 case NUD_STALE:
383 return DP_NUD_STALE;
384 case NUD_DELAY:
385 return DP_NUD_DELAY;
386 case NUD_PROBE:
387 return DP_NUD_PROBE;
388 case NUD_FAILED:
389 return DP_NUD_FAILED;
390 case NUD_NOARP:
391 return DP_NUD_NOARP;
392 case NUD_PERMANENT:
393 return DP_NUD_PERMANENT;
394 default:
395 return DP_NUD_STATE_INVALID;
396 }
397 }
398
399 /**
400 * os_if_dp_nud_stats_info() - print NUD stats info
401 * @vdev: vdev handle
402 *
403 * Return: None
404 */
os_if_dp_nud_stats_info(struct wlan_objmgr_vdev * vdev)405 static void os_if_dp_nud_stats_info(struct wlan_objmgr_vdev *vdev)
406 {
407 struct netdev_queue *txq;
408 struct net_device *net_dev;
409 int i = 0, errno;
410
411 errno = osif_dp_get_net_dev_from_vdev(vdev, &net_dev);
412 if (errno) {
413 dp_err("failed to get netdev");
414 return;
415 }
416 dp_info("carrier state: %d", netif_carrier_ok(net_dev));
417
418 for (i = 0; i < NUM_TX_QUEUES; i++) {
419 txq = netdev_get_tx_queue(net_dev, i);
420 dp_info("Queue: %d status: %d txq->trans_start: %lu",
421 i, netif_tx_queue_stopped(txq), txq->trans_start);
422 }
423 }
424
425 /**
426 * os_if_dp_nud_netevent_cb() - netevent callback
427 * @nb: Pointer to notifier block
428 * @event: Net Event triggered
429 * @data: Pointer to neighbour struct
430 *
431 * Callback for netevent
432 *
433 * Return: 0 on success
434 */
os_if_dp_nud_netevent_cb(struct notifier_block * nb,unsigned long event,void * data)435 static int os_if_dp_nud_netevent_cb(struct notifier_block *nb,
436 unsigned long event,
437 void *data)
438 {
439 struct neighbour *neighbor = data;
440 struct osif_vdev_sync *vdev_sync;
441 const struct net_device *netdev = neighbor->dev;
442 int errno;
443
444 errno = osif_vdev_sync_op_start(neighbor->dev, &vdev_sync);
445 if (errno)
446 return errno;
447
448 switch (event) {
449 case NETEVENT_NEIGH_UPDATE:
450 ucfg_dp_nud_event((struct qdf_mac_addr *)netdev->dev_addr,
451 (struct qdf_mac_addr *)&neighbor->ha[0],
452 nud_state_osif_to_dp(neighbor->nud_state));
453 break;
454 default:
455 break;
456 }
457
458 osif_vdev_sync_op_stop(vdev_sync);
459
460 return 0;
461 }
462
463 static struct notifier_block wlan_netevent_nb = {
464 .notifier_call = os_if_dp_nud_netevent_cb
465 };
466
osif_dp_nud_register_netevent_notifier(struct wlan_objmgr_psoc * psoc)467 int osif_dp_nud_register_netevent_notifier(struct wlan_objmgr_psoc *psoc)
468 {
469 int ret = 0;
470
471 if (ucfg_dp_nud_tracking_enabled(psoc)) {
472 ret = register_netevent_notifier(&wlan_netevent_nb);
473 if (!ret)
474 dp_info("Registered netevent notifier");
475 }
476 return ret;
477 }
478
osif_dp_nud_unregister_netevent_notifier(struct wlan_objmgr_psoc * psoc)479 void osif_dp_nud_unregister_netevent_notifier(struct wlan_objmgr_psoc *psoc)
480 {
481 int ret = 0;
482
483 if (ucfg_dp_nud_tracking_enabled(psoc)) {
484 ret = unregister_netevent_notifier(&wlan_netevent_nb);
485 if (!ret)
486 dp_info("Unregistered netevent notifier");
487 }
488 }
489 #else
os_if_dp_nud_stats_info(struct wlan_objmgr_vdev * vdev)490 static void os_if_dp_nud_stats_info(struct wlan_objmgr_vdev *vdev)
491 {
492 }
493
osif_dp_nud_register_netevent_notifier(struct wlan_objmgr_psoc * psoc)494 int osif_dp_nud_register_netevent_notifier(struct wlan_objmgr_psoc *psoc)
495 {
496 return 0;
497 }
498
osif_dp_nud_unregister_netevent_notifier(struct wlan_objmgr_psoc * psoc)499 void osif_dp_nud_unregister_netevent_notifier(struct wlan_objmgr_psoc *psoc)
500 {
501 }
502 #endif
503
504 /**
505 * dp_dns_unmake_name_query() - Convert an uncompressed DNS name to a
506 * NUL-terminated string
507 * @name: DNS name
508 *
509 * Return: Produce a printable version of a DNS name.
510 */
dp_dns_unmake_name_query(uint8_t * name)511 static inline uint8_t *dp_dns_unmake_name_query(uint8_t *name)
512 {
513 uint8_t *p;
514 unsigned int len;
515
516 p = name;
517 while ((len = *p)) {
518 *(p++) = '.';
519 p += len;
520 }
521
522 return name + 1;
523 }
524
525 /**
526 * dp_dns_make_name_query() - Convert a standard NUL-terminated string
527 * to DNS name
528 * @string: Name as a NUL-terminated string
529 * @buf: Buffer in which to place DNS name
530 * @len: BUffer length
531 *
532 * DNS names consist of "<length>element" pairs.
533 *
534 * Return: Byte following constructed DNS name
535 */
dp_dns_make_name_query(const uint8_t * string,uint8_t * buf,uint8_t len)536 static uint8_t *dp_dns_make_name_query(const uint8_t *string,
537 uint8_t *buf, uint8_t len)
538 {
539 uint8_t *length_byte = buf++;
540 uint8_t c;
541
542 if (string[len - 1]) {
543 dp_err("DNS name is not null terminated");
544 return NULL;
545 }
546
547 while ((c = *(string++))) {
548 if (c == '.') {
549 *length_byte = buf - length_byte - 1;
550 length_byte = buf;
551 }
552 *(buf++) = c;
553 }
554 *length_byte = buf - length_byte - 1;
555 *(buf++) = '\0';
556 return buf;
557 }
558
559 /**
560 * osif_dp_set_clear_connectivity_check_stats_info() - set/clear stats info
561 * @vdev: vdev context
562 * @arp_stats_params: arp stats structure to be sent to FW
563 * @tb: nl attribute
564 * @is_set_stats: set/clear stats
565 *
566 *
567 * Return: 0 on success, negative errno on failure
568 */
osif_dp_set_clear_connectivity_check_stats_info(struct wlan_objmgr_vdev * vdev,struct dp_set_arp_stats_params * arp_stats_params,struct nlattr ** tb,bool is_set_stats)569 static int osif_dp_set_clear_connectivity_check_stats_info(
570 struct wlan_objmgr_vdev *vdev,
571 struct dp_set_arp_stats_params *arp_stats_params,
572 struct nlattr **tb, bool is_set_stats)
573 {
574 struct nlattr *tb2[CONNECTIVITY_STATS_SET_MAX + 1];
575 struct nlattr *curr_attr = NULL;
576 int err = 0;
577 uint32_t pkt_bitmap;
578 int rem;
579 uint8_t dns_payload[256];
580 uint32_t pkt_type_bitmap = ucfg_dp_get_pkt_type_bitmap_value(vdev);
581
582 /* Set NUD command for start tracking is received. */
583 nla_for_each_nested(curr_attr,
584 tb[STATS_SET_DATA_PKT_INFO],
585 rem) {
586 if (wlan_cfg80211_nla_parse(tb2,
587 CONNECTIVITY_STATS_SET_MAX,
588 nla_data(curr_attr), nla_len(curr_attr),
589 dp_set_connectivity_check_stats)) {
590 dp_err("nla_parse failed");
591 err = -EINVAL;
592 goto end;
593 }
594
595 if (tb2[STATS_PKT_INFO_TYPE]) {
596 pkt_bitmap = nla_get_u32(tb2[STATS_PKT_INFO_TYPE]);
597 if (!pkt_bitmap) {
598 dp_err("pkt tracking bitmap is empty");
599 err = -EINVAL;
600 goto end;
601 }
602
603 if (is_set_stats) {
604 arp_stats_params->pkt_type_bitmap = pkt_bitmap;
605 arp_stats_params->flag = true;
606 pkt_type_bitmap |=
607 arp_stats_params->pkt_type_bitmap;
608 ucfg_dp_set_pkt_type_bitmap_value(vdev,
609 pkt_type_bitmap);
610
611 if (pkt_bitmap & CONNECTIVITY_CHECK_SET_ARP) {
612 if (!tb[STATS_GW_IPV4]) {
613 dp_err("GW ipv4 address is not present");
614 err = -EINVAL;
615 goto end;
616 }
617 arp_stats_params->ip_addr =
618 nla_get_u32(tb[STATS_GW_IPV4]);
619 arp_stats_params->pkt_type =
620 WLAN_NUD_STATS_ARP_PKT_TYPE;
621 ucfg_dp_set_track_arp_ip_value(vdev,
622 arp_stats_params->ip_addr);
623 }
624
625 if (pkt_bitmap & CONNECTIVITY_CHECK_SET_DNS) {
626 uint8_t *domain_name;
627
628 if (!tb2[STATS_DNS_DOMAIN_NAME]) {
629 dp_err("DNS domain id is not present");
630 err = -EINVAL;
631 goto end;
632 }
633 domain_name = nla_data(
634 tb2[STATS_DNS_DOMAIN_NAME]);
635 ucfg_dp_set_track_dns_domain_len_value(vdev,
636 nla_len(tb2[STATS_DNS_DOMAIN_NAME]));
637 ucfg_dp_get_dns_payload_value(vdev, dns_payload);
638 if (!dp_dns_make_name_query(
639 domain_name,
640 dns_payload,
641 ucfg_dp_get_track_dns_domain_len_value(vdev)))
642 ucfg_dp_set_track_dns_domain_len_value(vdev, 0);
643 /* DNStracking isn't supported in FW. */
644 arp_stats_params->pkt_type_bitmap &=
645 ~CONNECTIVITY_CHECK_SET_DNS;
646 }
647
648 if (pkt_bitmap &
649 CONNECTIVITY_CHECK_SET_TCP_HANDSHAKE) {
650 if (!tb2[STATS_SRC_PORT] ||
651 !tb2[STATS_DEST_PORT]) {
652 dp_err("Source/Dest port is not present");
653 err = -EINVAL;
654 goto end;
655 }
656 arp_stats_params->tcp_src_port =
657 nla_get_u32(
658 tb2[STATS_SRC_PORT]);
659 arp_stats_params->tcp_dst_port =
660 nla_get_u32(
661 tb2[STATS_DEST_PORT]);
662 ucfg_dp_set_track_src_port_value(vdev,
663 arp_stats_params->tcp_src_port);
664 ucfg_dp_set_track_dest_port_value(vdev,
665 arp_stats_params->tcp_dst_port);
666 }
667
668 if (pkt_bitmap &
669 CONNECTIVITY_CHECK_SET_ICMPV4) {
670 if (!tb2[STATS_DEST_IPV4]) {
671 dp_err("destination ipv4 address to track ping packets is not present");
672 err = -EINVAL;
673 goto end;
674 }
675 arp_stats_params->icmp_ipv4 =
676 nla_get_u32(
677 tb2[STATS_DEST_IPV4]);
678 ucfg_dp_set_track_dest_ipv4_value(vdev,
679 arp_stats_params->icmp_ipv4);
680 }
681 } else {
682 /* clear stats command received */
683 arp_stats_params->pkt_type_bitmap = pkt_bitmap;
684 arp_stats_params->flag = false;
685 pkt_type_bitmap &=
686 (~arp_stats_params->pkt_type_bitmap);
687 ucfg_dp_set_pkt_type_bitmap_value(vdev, pkt_type_bitmap);
688
689 if (pkt_bitmap & CONNECTIVITY_CHECK_SET_ARP) {
690 arp_stats_params->pkt_type =
691 WLAN_NUD_STATS_ARP_PKT_TYPE;
692 ucfg_dp_clear_arp_stats(vdev);
693 ucfg_dp_set_track_arp_ip_value(vdev, 0);
694 }
695
696 if (pkt_bitmap & CONNECTIVITY_CHECK_SET_DNS) {
697 /* DNStracking isn't supported in FW. */
698 arp_stats_params->pkt_type_bitmap &=
699 ~CONNECTIVITY_CHECK_SET_DNS;
700 ucfg_dp_clear_dns_stats(vdev);
701 ucfg_dp_clear_dns_payload_value(vdev);
702 ucfg_dp_set_track_dns_domain_len_value(vdev, 0);
703 }
704
705 if (pkt_bitmap &
706 CONNECTIVITY_CHECK_SET_TCP_HANDSHAKE) {
707 ucfg_dp_clear_tcp_stats(vdev);
708 ucfg_dp_set_track_src_port_value(vdev,
709 0);
710 ucfg_dp_set_track_dest_port_value(vdev,
711 0);
712 }
713
714 if (pkt_bitmap &
715 CONNECTIVITY_CHECK_SET_ICMPV4) {
716 ucfg_dp_clear_icmpv4_stats(vdev);
717 ucfg_dp_set_track_dest_ipv4_value(vdev,
718 0);
719 }
720 }
721 } else {
722 dp_err("stats list empty");
723 err = -EINVAL;
724 goto end;
725 }
726 }
727
728 end:
729 return err;
730 }
731
732 /**
733 * osif_dp_populate_dns_stats_info() - populate dns stats info
734 * @vdev: vdev context
735 * @skb: pointer to skb
736 *
737 *
738 * Return: An error code or 0 on success.
739 */
osif_dp_populate_dns_stats_info(struct wlan_objmgr_vdev * vdev,struct sk_buff * skb)740 static int osif_dp_populate_dns_stats_info(struct wlan_objmgr_vdev *vdev,
741 struct sk_buff *skb)
742 {
743 uint8_t *dns_query;
744 uint32_t track_dns_domain_len;
745 struct dp_dns_stats *dns_stats = ucfg_dp_get_dns_stats(vdev);
746
747 if (!dns_stats) {
748 dp_err("Unable to get DNS stats");
749 return -EINVAL;
750 }
751
752 track_dns_domain_len = ucfg_dp_get_track_dns_domain_len_value(vdev);
753 dns_query = qdf_mem_malloc(track_dns_domain_len + 1);
754 if (!dns_query)
755 return -EINVAL;
756
757 ucfg_dp_get_dns_payload_value(vdev, dns_query);
758
759 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
760 CONNECTIVITY_CHECK_SET_DNS) ||
761 nla_put(skb, CHECK_STATS_PKT_DNS_DOMAIN_NAME,
762 track_dns_domain_len,
763 dp_dns_unmake_name_query(dns_query)) ||
764 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
765 dns_stats->tx_dns_req_count) ||
766 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
767 dns_stats->tx_host_fw_sent) ||
768 nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
769 dns_stats->tx_host_fw_sent) ||
770 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
771 dns_stats->tx_ack_cnt) ||
772 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC,
773 dns_stats->rx_dns_rsp_count) ||
774 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV,
775 dns_stats->rx_delivered) ||
776 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP,
777 dns_stats->rx_host_drop)) {
778 dp_err("nla put fail");
779 qdf_mem_free(dns_query);
780 kfree_skb(skb);
781 return -EINVAL;
782 }
783 qdf_mem_free(dns_query);
784 return 0;
785 }
786
787 /**
788 * osif_dp_populate_tcp_stats_info() - populate tcp stats info
789 * @vdev: pointer to vdev context
790 * @skb: pointer to skb
791 * @pkt_type: tcp pkt type
792 *
793 * Return: An error code or 0 on success.
794 */
osif_dp_populate_tcp_stats_info(struct wlan_objmgr_vdev * vdev,struct sk_buff * skb,uint8_t pkt_type)795 static int osif_dp_populate_tcp_stats_info(struct wlan_objmgr_vdev *vdev,
796 struct sk_buff *skb,
797 uint8_t pkt_type)
798 {
799 uint32_t track_src_port = ucfg_dp_get_track_src_port_value(vdev);
800 uint32_t track_dest_port = ucfg_dp_get_track_dest_port_value(vdev);
801 struct dp_tcp_stats *tcp_stats = ucfg_dp_get_tcp_stats(vdev);
802
803 if (!tcp_stats) {
804 dp_err("Unable to get TCP stats");
805 return -EINVAL;
806 }
807
808 switch (pkt_type) {
809 case CONNECTIVITY_CHECK_SET_TCP_SYN:
810 /* Fill info for tcp syn packets (tx packet) */
811 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
812 CONNECTIVITY_CHECK_SET_TCP_SYN) ||
813 nla_put_u16(skb, CHECK_STATS_PKT_SRC_PORT,
814 track_src_port) ||
815 nla_put_u16(skb, CHECK_STATS_PKT_DEST_PORT,
816 track_dest_port) ||
817 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
818 tcp_stats->tx_tcp_syn_count) ||
819 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
820 tcp_stats->tx_tcp_syn_host_fw_sent) ||
821 nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
822 tcp_stats->tx_tcp_syn_host_fw_sent) ||
823 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
824 tcp_stats->tx_tcp_syn_ack_cnt)) {
825 dp_err("nla put fail");
826 kfree_skb(skb);
827 return -EINVAL;
828 }
829 break;
830 case CONNECTIVITY_CHECK_SET_TCP_SYN_ACK:
831 /* Fill info for tcp syn-ack packets (rx packet) */
832 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
833 CONNECTIVITY_CHECK_SET_TCP_SYN_ACK) ||
834 nla_put_u16(skb, CHECK_STATS_PKT_SRC_PORT,
835 track_src_port) ||
836 nla_put_u16(skb, CHECK_STATS_PKT_DEST_PORT,
837 track_dest_port) ||
838 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC,
839 tcp_stats->rx_fw_cnt) ||
840 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC,
841 tcp_stats->rx_tcp_syn_ack_count) ||
842 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV,
843 tcp_stats->rx_delivered) ||
844 nla_put_u16(skb,
845 CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP,
846 tcp_stats->rx_host_drop)) {
847 dp_err("nla put fail");
848 kfree_skb(skb);
849 return -EINVAL;
850 }
851 break;
852 case CONNECTIVITY_CHECK_SET_TCP_ACK:
853 /* Fill info for tcp ack packets (tx packet) */
854 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
855 CONNECTIVITY_CHECK_SET_TCP_ACK) ||
856 nla_put_u16(skb, CHECK_STATS_PKT_SRC_PORT,
857 track_src_port) ||
858 nla_put_u16(skb, CHECK_STATS_PKT_DEST_PORT,
859 track_dest_port) ||
860 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
861 tcp_stats->tx_tcp_ack_count) ||
862 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
863 tcp_stats->tx_tcp_ack_host_fw_sent) ||
864 nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
865 tcp_stats->tx_tcp_ack_host_fw_sent) ||
866 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
867 tcp_stats->tx_tcp_ack_ack_cnt)) {
868 dp_err("nla put fail");
869 kfree_skb(skb);
870 return -EINVAL;
871 }
872 break;
873 default:
874 break;
875 }
876 return 0;
877 }
878
879 /**
880 * osif_dp_populate_icmpv4_stats_info() - populate icmpv4 stats
881 * @vdev: pointer to vdev context
882 * @skb: pointer to skb
883 *
884 *
885 * Return: An error code or 0 on success.
886 */
osif_dp_populate_icmpv4_stats_info(struct wlan_objmgr_vdev * vdev,struct sk_buff * skb)887 static int osif_dp_populate_icmpv4_stats_info(struct wlan_objmgr_vdev *vdev,
888 struct sk_buff *skb)
889 {
890 struct dp_icmpv4_stats *icmpv4_stats = ucfg_dp_get_icmpv4_stats(vdev);
891 uint32_t track_dest_ipv4 = ucfg_dp_get_track_dest_ipv4_value(vdev);
892
893 if (!icmpv4_stats) {
894 dp_err("Unable to get ICMP stats");
895 return -EINVAL;
896 }
897
898 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
899 CONNECTIVITY_CHECK_SET_ICMPV4) ||
900 nla_put_u32(skb, CHECK_STATS_PKT_DEST_IPV4,
901 track_dest_ipv4) ||
902 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
903 icmpv4_stats->tx_icmpv4_req_count) ||
904 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
905 icmpv4_stats->tx_host_fw_sent) ||
906 nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
907 icmpv4_stats->tx_host_fw_sent) ||
908 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
909 icmpv4_stats->tx_ack_cnt) ||
910 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC,
911 icmpv4_stats->rx_fw_cnt) ||
912 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC,
913 icmpv4_stats->rx_icmpv4_rsp_count) ||
914 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV,
915 icmpv4_stats->rx_delivered) ||
916 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP,
917 icmpv4_stats->rx_host_drop)) {
918 dp_err("nla put fail");
919 kfree_skb(skb);
920 return -EINVAL;
921 }
922 return 0;
923 }
924
925 /**
926 * osif_dp_populate_connectivity_check_stats_info() - Poplulate connectivity
927 * stats info
928 * @vdev: pointer to vdev context
929 * @skb: pointer to skb
930 *
931 *
932 * Return: An error code or 0 on success.
933 */
934 static int
osif_dp_populate_connectivity_check_stats_info(struct wlan_objmgr_vdev * vdev,struct sk_buff * skb)935 osif_dp_populate_connectivity_check_stats_info(struct wlan_objmgr_vdev *vdev,
936 struct sk_buff *skb)
937 {
938 struct nlattr *connect_stats, *connect_info;
939 uint32_t count = 0;
940 uint32_t pkt_type_bitmap = ucfg_dp_get_pkt_type_bitmap_value(vdev);
941
942 connect_stats = nla_nest_start(skb, DATA_PKT_STATS);
943 if (!connect_stats) {
944 dp_err("nla_nest_start failed");
945 return -EINVAL;
946 }
947
948 if (pkt_type_bitmap & CONNECTIVITY_CHECK_SET_DNS) {
949 connect_info = nla_nest_start(skb, count);
950 if (!connect_info) {
951 dp_err("nla_nest_start failed count %u", count);
952 return -EINVAL;
953 }
954
955 if (osif_dp_populate_dns_stats_info(vdev, skb))
956 goto put_attr_fail;
957 nla_nest_end(skb, connect_info);
958 count++;
959 }
960
961 if (pkt_type_bitmap & CONNECTIVITY_CHECK_SET_TCP_HANDSHAKE) {
962 connect_info = nla_nest_start(skb, count);
963 if (!connect_info) {
964 dp_err("nla_nest_start failed count %u", count);
965 return -EINVAL;
966 }
967 if (osif_dp_populate_tcp_stats_info(vdev, skb,
968 CONNECTIVITY_CHECK_SET_TCP_SYN))
969 goto put_attr_fail;
970 nla_nest_end(skb, connect_info);
971 count++;
972
973 connect_info = nla_nest_start(skb, count);
974 if (!connect_info) {
975 dp_err("nla_nest_start failed count %u", count);
976 return -EINVAL;
977 }
978 if (osif_dp_populate_tcp_stats_info(vdev, skb,
979 CONNECTIVITY_CHECK_SET_TCP_SYN_ACK))
980 goto put_attr_fail;
981 nla_nest_end(skb, connect_info);
982 count++;
983
984 connect_info = nla_nest_start(skb, count);
985 if (!connect_info) {
986 dp_err("nla_nest_start failed count %u", count);
987 return -EINVAL;
988 }
989 if (osif_dp_populate_tcp_stats_info(vdev, skb,
990 CONNECTIVITY_CHECK_SET_TCP_ACK))
991 goto put_attr_fail;
992 nla_nest_end(skb, connect_info);
993 count++;
994 }
995
996 if (pkt_type_bitmap & CONNECTIVITY_CHECK_SET_ICMPV4) {
997 connect_info = nla_nest_start(skb, count);
998 if (!connect_info) {
999 dp_err("nla_nest_start failed count %u", count);
1000 return -EINVAL;
1001 }
1002
1003 if (osif_dp_populate_icmpv4_stats_info(vdev, skb))
1004 goto put_attr_fail;
1005 nla_nest_end(skb, connect_info);
1006 count++;
1007 }
1008
1009 nla_nest_end(skb, connect_stats);
1010 return 0;
1011
1012 put_attr_fail:
1013 dp_err("QCA_WLAN_VENDOR_ATTR put fail. count %u", count);
1014 return -EINVAL;
1015 }
1016
osif_dp_get_nud_stats(struct wiphy * wiphy,struct wlan_objmgr_vdev * vdev,const void * data,int data_len)1017 int osif_dp_get_nud_stats(struct wiphy *wiphy,
1018 struct wlan_objmgr_vdev *vdev,
1019 const void *data, int data_len)
1020 {
1021 int err = 0;
1022 struct dp_get_arp_stats_params arp_stats_params;
1023 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
1024 uint32_t pkt_type_bitmap = ucfg_dp_get_pkt_type_bitmap_value(vdev);
1025 struct sk_buff *skb;
1026 struct osif_request *request = NULL;
1027 struct dp_arp_stats *arp_stats;
1028 struct wlan_objmgr_psoc *psoc = wlan_vdev_get_psoc(vdev);
1029 static const struct osif_request_params params = {
1030 .priv_size = 0,
1031 .timeout_ms = WLAN_WAIT_TIME_NUD_STATS,
1032 };
1033
1034 request = osif_request_alloc(¶ms);
1035 if (!request) {
1036 dp_err("Request allocation failure");
1037 return -ENOMEM;
1038 }
1039
1040 ucfg_dp_set_nud_stats_cb(psoc, osif_request_cookie(request));
1041
1042 arp_stats_params.pkt_type = WLAN_NUD_STATS_ARP_PKT_TYPE;
1043 arp_stats_params.vdev_id = ucfg_dp_get_link_id(vdev);
1044
1045 /* send NUD failure event only when ARP tracking is enabled. */
1046 if (ucfg_dp_nud_fail_data_stall_evt_enabled() &&
1047 !ucfg_dp_nud_tracking_enabled(psoc) &&
1048 (pkt_type_bitmap & CONNECTIVITY_CHECK_SET_ARP)) {
1049 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_ERROR,
1050 "Data stall due to NUD failure");
1051 cdp_post_data_stall_event(soc,
1052 DATA_STALL_LOG_INDICATOR_FRAMEWORK,
1053 DATA_STALL_LOG_NUD_FAILURE,
1054 OL_TXRX_PDEV_ID, 0XFF,
1055 DATA_STALL_LOG_RECOVERY_TRIGGER_PDR);
1056 }
1057
1058 if (QDF_STATUS_SUCCESS !=
1059 ucfg_dp_req_get_arp_stats(psoc, &arp_stats_params)) {
1060 dp_err("Unable to sent ARP stats request");
1061 err = -EINVAL;
1062 goto exit;
1063 }
1064
1065 err = osif_request_wait_for_response(request);
1066 if (err) {
1067 dp_err("timedout while retrieving NUD stats");
1068 err = -ETIMEDOUT;
1069 goto exit;
1070 }
1071
1072 arp_stats = ucfg_dp_get_arp_stats(vdev);
1073 if (!arp_stats) {
1074 dp_err("Unable to get ARP stats");
1075 err = -EINVAL;
1076 goto exit;
1077 }
1078
1079 skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
1080 WLAN_NUD_STATS_LEN);
1081 if (!skb) {
1082 dp_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
1083 err = -ENOMEM;
1084 goto exit;
1085 }
1086
1087 if (nla_put_u16(skb, COUNT_FROM_NETDEV,
1088 arp_stats->tx_arp_req_count) ||
1089 nla_put_u16(skb, COUNT_TO_LOWER_MAC,
1090 arp_stats->tx_host_fw_sent) ||
1091 nla_put_u16(skb, RX_COUNT_BY_LOWER_MAC,
1092 arp_stats->tx_host_fw_sent) ||
1093 nla_put_u16(skb, COUNT_TX_SUCCESS,
1094 arp_stats->tx_ack_cnt) ||
1095 nla_put_u16(skb, RSP_RX_COUNT_BY_LOWER_MAC,
1096 arp_stats->rx_fw_cnt) ||
1097 nla_put_u16(skb, RSP_RX_COUNT_BY_UPPER_MAC,
1098 arp_stats->rx_arp_rsp_count) ||
1099 nla_put_u16(skb, RSP_COUNT_TO_NETDEV,
1100 arp_stats->rx_delivered) ||
1101 nla_put_u16(skb, RSP_COUNT_OUT_OF_ORDER_DROP,
1102 arp_stats->rx_host_drop_reorder)) {
1103 dp_err("nla put fail");
1104 wlan_cfg80211_vendor_free_skb(skb);
1105 err = -EINVAL;
1106 goto exit;
1107 }
1108 if (ucfg_dp_get_con_status_value(vdev))
1109 nla_put_flag(skb, AP_LINK_ACTIVE);
1110 if (ucfg_dp_get_dad_value(vdev))
1111 nla_put_flag(skb, AP_LINK_DAD);
1112
1113 /* ARP tracking is done above. */
1114 pkt_type_bitmap &= ~CONNECTIVITY_CHECK_SET_ARP;
1115
1116 if (pkt_type_bitmap) {
1117 if (osif_dp_populate_connectivity_check_stats_info(vdev, skb)) {
1118 err = -EINVAL;
1119 goto exit;
1120 }
1121 }
1122
1123 wlan_cfg80211_vendor_cmd_reply(skb);
1124 exit:
1125 ucfg_dp_clear_nud_stats_cb(psoc);
1126 osif_request_put(request);
1127 return err;
1128 }
1129
osif_dp_set_nud_stats(struct wiphy * wiphy,struct wlan_objmgr_vdev * vdev,const void * data,int data_len)1130 int osif_dp_set_nud_stats(struct wiphy *wiphy,
1131 struct wlan_objmgr_vdev *vdev,
1132 const void *data, int data_len)
1133 {
1134 struct nlattr *tb[STATS_SET_MAX + 1];
1135 struct wlan_objmgr_psoc *psoc = wlan_vdev_get_psoc(vdev);
1136 struct dp_set_arp_stats_params arp_stats_params = {0};
1137 uint32_t pkt_type_bitmap = ucfg_dp_get_pkt_type_bitmap_value(vdev);
1138 int err = 0;
1139
1140 err = wlan_cfg80211_nla_parse(tb, STATS_SET_MAX, data, data_len,
1141 dp_set_nud_stats_policy);
1142 if (err) {
1143 dp_err("STATS_SET_START ATTR");
1144 return err;
1145 }
1146
1147 if (tb[STATS_SET_START]) {
1148 /* tracking is enabled for stats other than arp. */
1149 if (tb[STATS_SET_DATA_PKT_INFO]) {
1150 err = osif_dp_set_clear_connectivity_check_stats_info(
1151 vdev,
1152 &arp_stats_params, tb, true);
1153 if (err)
1154 return -EINVAL;
1155
1156 /*
1157 * if only tracking dns, then don't send
1158 * wmi command to FW.
1159 */
1160 if (!arp_stats_params.pkt_type_bitmap)
1161 return err;
1162 } else {
1163 if (!tb[STATS_GW_IPV4]) {
1164 dp_err("STATS_SET_START CMD");
1165 return -EINVAL;
1166 }
1167
1168 arp_stats_params.pkt_type_bitmap =
1169 CONNECTIVITY_CHECK_SET_ARP;
1170 pkt_type_bitmap |=
1171 arp_stats_params.pkt_type_bitmap;
1172 ucfg_dp_set_pkt_type_bitmap_value(vdev,
1173 pkt_type_bitmap);
1174 arp_stats_params.flag = true;
1175 arp_stats_params.ip_addr =
1176 nla_get_u32(tb[STATS_GW_IPV4]);
1177 ucfg_dp_set_track_arp_ip_value(vdev,
1178 arp_stats_params.ip_addr);
1179 arp_stats_params.pkt_type = WLAN_NUD_STATS_ARP_PKT_TYPE;
1180 }
1181 } else {
1182 /* clear stats command received. */
1183 if (tb[STATS_SET_DATA_PKT_INFO]) {
1184 err = osif_dp_set_clear_connectivity_check_stats_info(
1185 vdev,
1186 &arp_stats_params, tb, false);
1187 if (err)
1188 return -EINVAL;
1189
1190 /*
1191 * if only tracking dns, then don't send
1192 * wmi command to FW.
1193 */
1194 if (!arp_stats_params.pkt_type_bitmap)
1195 return err;
1196 } else {
1197 arp_stats_params.pkt_type_bitmap =
1198 CONNECTIVITY_CHECK_SET_ARP;
1199 pkt_type_bitmap &= (~arp_stats_params.pkt_type_bitmap);
1200 ucfg_dp_set_pkt_type_bitmap_value(vdev,
1201 pkt_type_bitmap);
1202 arp_stats_params.flag = false;
1203 ucfg_dp_clear_arp_stats(vdev);
1204 arp_stats_params.pkt_type = WLAN_NUD_STATS_ARP_PKT_TYPE;
1205 }
1206 }
1207
1208 dp_info("STATS_SET_START Received flag %d!", arp_stats_params.flag);
1209
1210 arp_stats_params.vdev_id = ucfg_dp_get_link_id(vdev);
1211
1212 if (QDF_STATUS_SUCCESS !=
1213 ucfg_dp_req_set_arp_stats(psoc, &arp_stats_params)) {
1214 dp_err("Unable to set ARP stats!");
1215 return -EINVAL;
1216 }
1217 return err;
1218 }
1219
1220 /*
1221 * os_if_dp_register_event_handler() - Register osif event handler
1222 * @psoc: psoc handle
1223 *
1224 * Return: None
1225 */
os_if_dp_register_event_handler(struct wlan_objmgr_psoc * psoc)1226 static void os_if_dp_register_event_handler(struct wlan_objmgr_psoc *psoc)
1227 {
1228 struct wlan_dp_psoc_nb_ops cb_obj = {0};
1229
1230 cb_obj.osif_dp_get_arp_stats_evt =
1231 osif_dp_get_arp_stats_event_handler;
1232
1233 ucfg_dp_register_event_handler(psoc, &cb_obj);
1234 }
1235
os_if_dp_register_hdd_callbacks(struct wlan_objmgr_psoc * psoc,struct wlan_dp_psoc_callbacks * cb_obj)1236 void os_if_dp_register_hdd_callbacks(struct wlan_objmgr_psoc *psoc,
1237 struct wlan_dp_psoc_callbacks *cb_obj)
1238 {
1239 cb_obj->osif_dp_send_tcp_param_update_event =
1240 osif_dp_send_tcp_param_update_event;
1241 cb_obj->os_if_dp_nud_stats_info = os_if_dp_nud_stats_info;
1242 cb_obj->osif_dp_process_mic_error = osif_dp_process_mic_error;
1243 os_if_dp_register_txrx_callbacks(cb_obj);
1244
1245 ucfg_dp_register_hdd_callbacks(psoc, cb_obj);
1246 os_if_dp_register_event_handler(psoc);
1247 }
1248