os_if_dp.c 34 KB

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