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(&params);
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