12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247 |
- /*
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
- *
- * Permission to use, copy, modify, and/or distribute this software for
- * any purpose with or without fee is hereby granted, provided that the
- * above copyright notice and this permission notice appear in all
- * copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
- * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
- * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
- /**
- * DOC: os_if_dp.c
- *
- *
- */
- #include "os_if_dp.h"
- #include "wlan_nlink_srv.h"
- #include <wlan_cfg80211.h>
- #include <wlan_osif_priv.h>
- #include <cdp_txrx_cmn.h>
- #include "qca_vendor.h"
- #include "wlan_dp_ucfg_api.h"
- #include "osif_vdev_sync.h"
- #include "osif_sync.h"
- #include <net/netevent.h>
- #include "wlan_osif_request_manager.h"
- #include <ol_defines.h>
- /*
- * define short names for the global vendor params
- * used by wlan_hdd_cfg80211_setarp_stats_cmd()
- */
- #define STATS_GET_INVALID \
- QCA_ATTR_NUD_STATS_SET_INVALID
- #define COUNT_FROM_NETDEV \
- QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_FROM_NETDEV
- #define COUNT_TO_LOWER_MAC \
- QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TO_LOWER_MAC
- #define RX_COUNT_BY_LOWER_MAC \
- QCA_ATTR_NUD_STATS_ARP_REQ_RX_COUNT_BY_LOWER_MAC
- #define COUNT_TX_SUCCESS \
- QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TX_SUCCESS
- #define RSP_RX_COUNT_BY_LOWER_MAC \
- QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_LOWER_MAC
- #define RSP_RX_COUNT_BY_UPPER_MAC \
- QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_UPPER_MAC
- #define RSP_COUNT_TO_NETDEV \
- QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_TO_NETDEV
- #define RSP_COUNT_OUT_OF_ORDER_DROP \
- QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_OUT_OF_ORDER_DROP
- #define AP_LINK_ACTIVE \
- QCA_ATTR_NUD_STATS_AP_LINK_ACTIVE
- #define AP_LINK_DAD \
- QCA_ATTR_NUD_STATS_IS_DAD
- #define DATA_PKT_STATS \
- QCA_ATTR_NUD_STATS_DATA_PKT_STATS
- #define STATS_GET_MAX \
- QCA_ATTR_NUD_STATS_GET_MAX
- #define CHECK_STATS_INVALID \
- QCA_ATTR_CONNECTIVITY_CHECK_STATS_INVALID
- #define CHECK_STATS_PKT_TYPE \
- QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_TYPE
- #define CHECK_STATS_PKT_DNS_DOMAIN_NAME \
- QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DNS_DOMAIN_NAME
- #define CHECK_STATS_PKT_SRC_PORT \
- QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_SRC_PORT
- #define CHECK_STATS_PKT_DEST_PORT \
- QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_PORT
- #define CHECK_STATS_PKT_DEST_IPV4 \
- QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_IPV4
- #define CHECK_STATS_PKT_DEST_IPV6 \
- QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_IPV6
- #define CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV \
- QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV
- #define CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC \
- QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC
- #define CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC \
- QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC
- #define CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS \
- QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS
- #define CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC \
- QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC
- #define CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC \
- QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC
- #define CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV \
- QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV
- #define CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP \
- QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP
- #define CHECK_DATA_STATS_MAX \
- QCA_ATTR_CONNECTIVITY_CHECK_DATA_STATS_MAX
- #define STATS_SET_INVALID \
- QCA_ATTR_NUD_STATS_SET_INVALID
- #define STATS_SET_START \
- QCA_ATTR_NUD_STATS_SET_START
- #define STATS_GW_IPV4 \
- QCA_ATTR_NUD_STATS_GW_IPV4
- #define STATS_SET_DATA_PKT_INFO \
- QCA_ATTR_NUD_STATS_SET_DATA_PKT_INFO
- #define STATS_SET_MAX \
- QCA_ATTR_NUD_STATS_SET_MAX
- const struct nla_policy
- dp_set_nud_stats_policy[STATS_SET_MAX + 1] = {
- [STATS_SET_START] = {.type = NLA_FLAG },
- [STATS_GW_IPV4] = {.type = NLA_U32 },
- [STATS_SET_DATA_PKT_INFO] = {.type = NLA_NESTED },
- };
- /* define short names for the global vendor params */
- #define CONNECTIVITY_STATS_SET_INVALID \
- QCA_ATTR_CONNECTIVITY_CHECK_STATS_SET_INVALID
- #define STATS_PKT_INFO_TYPE \
- QCA_ATTR_CONNECTIVITY_CHECK_STATS_STATS_PKT_INFO_TYPE
- #define STATS_DNS_DOMAIN_NAME \
- QCA_ATTR_CONNECTIVITY_CHECK_STATS_DNS_DOMAIN_NAME
- #define STATS_SRC_PORT \
- QCA_ATTR_CONNECTIVITY_CHECK_STATS_SRC_PORT
- #define STATS_DEST_PORT \
- QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_PORT
- #define STATS_DEST_IPV4 \
- QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_IPV4
- #define STATS_DEST_IPV6 \
- QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_IPV6
- #define CONNECTIVITY_STATS_SET_MAX \
- QCA_ATTR_CONNECTIVITY_CHECK_STATS_SET_MAX
- const struct nla_policy
- dp_set_connectivity_check_stats[CONNECTIVITY_STATS_SET_MAX + 1] = {
- [STATS_PKT_INFO_TYPE] = {.type = NLA_U32 },
- [STATS_DNS_DOMAIN_NAME] = {.type = NLA_NUL_STRING,
- .len = DNS_DOMAIN_NAME_MAX_LEN },
- [STATS_SRC_PORT] = {.type = NLA_U32 },
- [STATS_DEST_PORT] = {.type = NLA_U32 },
- [STATS_DEST_IPV4] = {.type = NLA_U32 },
- [STATS_DEST_IPV6] = {.type = NLA_BINARY,
- .len = ICMPV6_ADDR_LEN },
- };
- #ifdef WLAN_FEATURE_DP_BUS_BANDWIDTH
- /**
- * osif_dp_send_tcp_param_update_event() - Send vendor event to update
- * TCP parameter through Wi-Fi HAL
- * @psoc: Pointer to psoc context
- * @data: Parameters to update
- * @dir: Direction(tx/rx) to update
- *
- * Return: None
- */
- static
- void osif_dp_send_tcp_param_update_event(struct wlan_objmgr_psoc *psoc,
- union wlan_tp_data *data,
- uint8_t dir)
- {
- struct sk_buff *vendor_event;
- struct wlan_objmgr_pdev *pdev;
- struct pdev_osif_priv *os_priv;
- uint32_t event_len;
- bool tcp_limit_output = false;
- bool tcp_del_ack_ind_enabled = false;
- bool tcp_adv_win_scl_enabled = false;
- enum wlan_tp_level next_tp_level = WLAN_SVC_TP_NONE;
- enum qca_nl80211_vendor_subcmds_index index =
- QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT_INDEX;
- event_len = sizeof(uint8_t) + sizeof(uint8_t) + NLMSG_HDRLEN;
- pdev = wlan_objmgr_get_pdev_by_id(psoc, 0, WLAN_DP_ID);
- if (!pdev)
- return;
- os_priv = wlan_pdev_get_ospriv(pdev);
- if (dir == 0) /*TX Flow */ {
- struct wlan_tx_tp_data *tx_tp_data =
- (struct wlan_tx_tp_data *)data;
- next_tp_level = tx_tp_data->level;
- if (tx_tp_data->tcp_limit_output) {
- /* TCP_LIMIT_OUTPUT_BYTES */
- event_len += sizeof(uint32_t);
- tcp_limit_output = true;
- }
- } else if (dir == 1) /* RX Flow */ {
- struct wlan_rx_tp_data *rx_tp_data =
- (struct wlan_rx_tp_data *)data;
- next_tp_level = rx_tp_data->level;
- if (rx_tp_data->rx_tp_flags & TCP_DEL_ACK_IND_MASK) {
- event_len += sizeof(uint32_t); /* TCP_DELACK_SEG */
- tcp_del_ack_ind_enabled = true;
- }
- if (rx_tp_data->rx_tp_flags & TCP_ADV_WIN_SCL_MASK) {
- event_len += sizeof(uint32_t); /* TCP_ADV_WIN_SCALE */
- tcp_adv_win_scl_enabled = true;
- }
- } else {
- dp_err("Invalid Direction [%d]", dir);
- wlan_objmgr_pdev_release_ref(pdev, WLAN_DP_ID);
- return;
- }
- vendor_event = wlan_cfg80211_vendor_event_alloc(os_priv->wiphy,
- NULL, event_len,
- index, GFP_KERNEL);
- if (!vendor_event) {
- dp_err("wlan_cfg80211_vendor_event_alloc failed");
- wlan_objmgr_pdev_release_ref(pdev, WLAN_DP_ID);
- return;
- }
- if (nla_put_u8(
- vendor_event,
- QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_DIRECTION,
- dir))
- goto tcp_param_change_nla_failed;
- if (nla_put_u8(
- vendor_event,
- QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_THROUGHPUT_LEVEL,
- (next_tp_level == WLAN_SVC_TP_LOW ?
- QCA_WLAN_THROUGHPUT_LEVEL_LOW :
- QCA_WLAN_THROUGHPUT_LEVEL_HIGH)))
- goto tcp_param_change_nla_failed;
- if (tcp_limit_output &&
- nla_put_u32(
- vendor_event,
- QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_TCP_LIMIT_OUTPUT_BYTES,
- (next_tp_level == WLAN_SVC_TP_LOW ?
- TCP_LIMIT_OUTPUT_BYTES_LOW :
- TCP_LIMIT_OUTPUT_BYTES_HI)))
- goto tcp_param_change_nla_failed;
- if (tcp_del_ack_ind_enabled &&
- (nla_put_u32(
- vendor_event,
- QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_TCP_DELACK_SEG,
- (next_tp_level == WLAN_SVC_TP_LOW ?
- TCP_DEL_ACK_LOW : TCP_DEL_ACK_HI))))
- goto tcp_param_change_nla_failed;
- if (tcp_adv_win_scl_enabled &&
- (nla_put_u32(
- vendor_event,
- QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_TCP_ADV_WIN_SCALE,
- (next_tp_level == WLAN_SVC_TP_LOW ?
- WIN_SCALE_LOW : WIN_SCALE_HI))))
- goto tcp_param_change_nla_failed;
- wlan_cfg80211_vendor_event(vendor_event, GFP_KERNEL);
- wlan_objmgr_pdev_release_ref(pdev, WLAN_DP_ID);
- return;
- tcp_param_change_nla_failed:
- wlan_objmgr_pdev_release_ref(pdev, WLAN_DP_ID);
- dp_err("nla_put api failed");
- wlan_cfg80211_vendor_free_skb(vendor_event);
- }
- #else
- static
- void osif_dp_send_tcp_param_update_event(struct wlan_objmgr_psoc *psoc,
- union wlan_tp_data *data,
- uint8_t dir)
- {
- }
- #endif /*WLAN_FEATURE_DP_BUS_BANDWIDTH*/
- /**
- * osif_dp_get_net_dev_from_vdev() - Get netdev object from vdev
- * @vdev: Pointer to vdev manager
- * @out_net_dev: Pointer to output netdev
- *
- * Return: 0 on success, error code on failure
- */
- static int osif_dp_get_net_dev_from_vdev(struct wlan_objmgr_vdev *vdev,
- struct net_device **out_net_dev)
- {
- struct vdev_osif_priv *priv;
- if (!vdev)
- return -EINVAL;
- priv = wlan_vdev_get_ospriv(vdev);
- if (!priv || !priv->wdev || !priv->wdev->netdev)
- return -EINVAL;
- *out_net_dev = priv->wdev->netdev;
- return 0;
- }
- /**
- * osif_dp_process_mic_error() - Indicate mic error to supplicant
- * @info: MIC error information
- * @vdev: vdev handle
- *
- * Return: None
- */
- static void
- osif_dp_process_mic_error(struct dp_mic_error_info *info,
- struct wlan_objmgr_vdev *vdev)
- {
- struct net_device *dev;
- struct osif_vdev_sync *vdev_sync;
- int errno;
- errno = osif_dp_get_net_dev_from_vdev(vdev, &dev);
- if (errno) {
- dp_err("failed to get netdev");
- return;
- }
- if (osif_vdev_sync_op_start(dev, &vdev_sync))
- return;
- /* inform mic failure to nl80211 */
- cfg80211_michael_mic_failure(dev,
- (uint8_t *)&info->ta_mac_addr,
- info->multicast ?
- NL80211_KEYTYPE_GROUP :
- NL80211_KEYTYPE_PAIRWISE,
- info->key_id,
- info->tsc,
- GFP_KERNEL);
- osif_vdev_sync_op_stop(vdev_sync);
- }
- /**
- * osif_dp_get_arp_stats_event_handler() - ARP get stats event handler
- * @psoc: psoc handle
- * @rsp: Get ARP stats response
- *
- * Return: None
- */
- static void osif_dp_get_arp_stats_event_handler(struct wlan_objmgr_psoc *psoc,
- struct dp_rsp_stats *rsp)
- {
- struct osif_request *request = NULL;
- void *context;
- context = ucfg_dp_get_arp_request_ctx(psoc);
- if (!context)
- return;
- request = osif_request_get(context);
- if (!request)
- return;
- ucfg_dp_get_arp_stats_event_handler(psoc, rsp);
- osif_request_complete(request);
- osif_request_put(request);
- }
- #ifdef WLAN_NUD_TRACKING
- /**
- * nud_state_osif_to_dp() - convert os_if to enum
- * @curr_state: Current NUD state
- *
- * Return: DP enum equivalent to NUD state
- */
- static inline enum dp_nud_state nud_state_osif_to_dp(uint8_t curr_state)
- {
- switch (curr_state) {
- case NUD_NONE:
- return DP_NUD_NONE;
- case NUD_INCOMPLETE:
- return DP_NUD_INCOMPLETE;
- case NUD_REACHABLE:
- return DP_NUD_REACHABLE;
- case NUD_STALE:
- return DP_NUD_STALE;
- case NUD_DELAY:
- return DP_NUD_DELAY;
- case NUD_PROBE:
- return DP_NUD_PROBE;
- case NUD_FAILED:
- return DP_NUD_FAILED;
- case NUD_NOARP:
- return DP_NUD_NOARP;
- case NUD_PERMANENT:
- return DP_NUD_PERMANENT;
- default:
- return DP_NUD_STATE_INVALID;
- }
- }
- /**
- * os_if_dp_nud_stats_info() - print NUD stats info
- * @vdev: vdev handle
- *
- * Return: None
- */
- static void os_if_dp_nud_stats_info(struct wlan_objmgr_vdev *vdev)
- {
- struct netdev_queue *txq;
- struct net_device *net_dev;
- int i = 0, errno;
- errno = osif_dp_get_net_dev_from_vdev(vdev, &net_dev);
- if (errno) {
- dp_err("failed to get netdev");
- return;
- }
- dp_info("carrier state: %d", netif_carrier_ok(net_dev));
- for (i = 0; i < NUM_TX_QUEUES; i++) {
- txq = netdev_get_tx_queue(net_dev, i);
- dp_info("Queue: %d status: %d txq->trans_start: %lu",
- i, netif_tx_queue_stopped(txq), txq->trans_start);
- }
- }
- /**
- * os_if_dp_nud_netevent_cb() - netevent callback
- * @nb: Pointer to notifier block
- * @event: Net Event triggered
- * @data: Pointer to neighbour struct
- *
- * Callback for netevent
- *
- * Return: 0 on success
- */
- static int os_if_dp_nud_netevent_cb(struct notifier_block *nb,
- unsigned long event,
- void *data)
- {
- struct neighbour *neighbor = data;
- struct osif_vdev_sync *vdev_sync;
- const struct net_device *netdev = neighbor->dev;
- int errno;
- errno = osif_vdev_sync_op_start(neighbor->dev, &vdev_sync);
- if (errno)
- return errno;
- switch (event) {
- case NETEVENT_NEIGH_UPDATE:
- ucfg_dp_nud_event((struct qdf_mac_addr *)netdev->dev_addr,
- (struct qdf_mac_addr *)&neighbor->ha[0],
- nud_state_osif_to_dp(neighbor->nud_state));
- break;
- default:
- break;
- }
- osif_vdev_sync_op_stop(vdev_sync);
- return 0;
- }
- static struct notifier_block wlan_netevent_nb = {
- .notifier_call = os_if_dp_nud_netevent_cb
- };
- int osif_dp_nud_register_netevent_notifier(struct wlan_objmgr_psoc *psoc)
- {
- int ret = 0;
- if (ucfg_dp_nud_tracking_enabled(psoc)) {
- ret = register_netevent_notifier(&wlan_netevent_nb);
- if (!ret)
- dp_info("Registered netevent notifier");
- }
- return ret;
- }
- void osif_dp_nud_unregister_netevent_notifier(struct wlan_objmgr_psoc *psoc)
- {
- int ret = 0;
- if (ucfg_dp_nud_tracking_enabled(psoc)) {
- ret = unregister_netevent_notifier(&wlan_netevent_nb);
- if (!ret)
- dp_info("Unregistered netevent notifier");
- }
- }
- #else
- static void os_if_dp_nud_stats_info(struct wlan_objmgr_vdev *vdev)
- {
- }
- int osif_dp_nud_register_netevent_notifier(struct wlan_objmgr_psoc *psoc)
- {
- return 0;
- }
- void osif_dp_nud_unregister_netevent_notifier(struct wlan_objmgr_psoc *psoc)
- {
- }
- #endif
- /**
- * dp_dns_unmake_name_query() - Convert an uncompressed DNS name to a
- * NUL-terminated string
- * @name: DNS name
- *
- * Return: Produce a printable version of a DNS name.
- */
- static inline uint8_t *dp_dns_unmake_name_query(uint8_t *name)
- {
- uint8_t *p;
- unsigned int len;
- p = name;
- while ((len = *p)) {
- *(p++) = '.';
- p += len;
- }
- return name + 1;
- }
- /**
- * dp_dns_make_name_query() - Convert a standard NUL-terminated string
- * to DNS name
- * @string: Name as a NUL-terminated string
- * @buf: Buffer in which to place DNS name
- * @len: BUffer length
- *
- * DNS names consist of "<length>element" pairs.
- *
- * Return: Byte following constructed DNS name
- */
- static uint8_t *dp_dns_make_name_query(const uint8_t *string,
- uint8_t *buf, uint8_t len)
- {
- uint8_t *length_byte = buf++;
- uint8_t c;
- if (string[len - 1]) {
- dp_err("DNS name is not null terminated");
- return NULL;
- }
- while ((c = *(string++))) {
- if (c == '.') {
- *length_byte = buf - length_byte - 1;
- length_byte = buf;
- }
- *(buf++) = c;
- }
- *length_byte = buf - length_byte - 1;
- *(buf++) = '\0';
- return buf;
- }
- /**
- * osif_dp_set_clear_connectivity_check_stats_info() - set/clear stats info
- * @vdev: vdev context
- * @arp_stats_params: arp stats structure to be sent to FW
- * @tb: nl attribute
- * @is_set_stats: set/clear stats
- *
- *
- * Return: 0 on success, negative errno on failure
- */
- static int 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)
- {
- struct nlattr *tb2[CONNECTIVITY_STATS_SET_MAX + 1];
- struct nlattr *curr_attr = NULL;
- int err = 0;
- uint32_t pkt_bitmap;
- int rem;
- uint8_t dns_payload[256];
- uint32_t pkt_type_bitmap = ucfg_dp_get_pkt_type_bitmap_value(vdev);
- /* Set NUD command for start tracking is received. */
- nla_for_each_nested(curr_attr,
- tb[STATS_SET_DATA_PKT_INFO],
- rem) {
- if (wlan_cfg80211_nla_parse(tb2,
- CONNECTIVITY_STATS_SET_MAX,
- nla_data(curr_attr), nla_len(curr_attr),
- dp_set_connectivity_check_stats)) {
- dp_err("nla_parse failed");
- err = -EINVAL;
- goto end;
- }
- if (tb2[STATS_PKT_INFO_TYPE]) {
- pkt_bitmap = nla_get_u32(tb2[STATS_PKT_INFO_TYPE]);
- if (!pkt_bitmap) {
- dp_err("pkt tracking bitmap is empty");
- err = -EINVAL;
- goto end;
- }
- if (is_set_stats) {
- arp_stats_params->pkt_type_bitmap = pkt_bitmap;
- arp_stats_params->flag = true;
- pkt_type_bitmap |=
- arp_stats_params->pkt_type_bitmap;
- ucfg_dp_set_pkt_type_bitmap_value(vdev,
- pkt_type_bitmap);
- if (pkt_bitmap & CONNECTIVITY_CHECK_SET_ARP) {
- if (!tb[STATS_GW_IPV4]) {
- dp_err("GW ipv4 address is not present");
- err = -EINVAL;
- goto end;
- }
- arp_stats_params->ip_addr =
- nla_get_u32(tb[STATS_GW_IPV4]);
- arp_stats_params->pkt_type =
- WLAN_NUD_STATS_ARP_PKT_TYPE;
- ucfg_dp_set_track_arp_ip_value(vdev,
- arp_stats_params->ip_addr);
- }
- if (pkt_bitmap & CONNECTIVITY_CHECK_SET_DNS) {
- uint8_t *domain_name;
- if (!tb2[STATS_DNS_DOMAIN_NAME]) {
- dp_err("DNS domain id is not present");
- err = -EINVAL;
- goto end;
- }
- domain_name = nla_data(
- tb2[STATS_DNS_DOMAIN_NAME]);
- ucfg_dp_set_track_dns_domain_len_value(vdev,
- nla_len(tb2[STATS_DNS_DOMAIN_NAME]));
- ucfg_dp_get_dns_payload_value(vdev, dns_payload);
- if (!dp_dns_make_name_query(
- domain_name,
- dns_payload,
- ucfg_dp_get_track_dns_domain_len_value(vdev)))
- ucfg_dp_set_track_dns_domain_len_value(vdev, 0);
- /* DNStracking isn't supported in FW. */
- arp_stats_params->pkt_type_bitmap &=
- ~CONNECTIVITY_CHECK_SET_DNS;
- }
- if (pkt_bitmap &
- CONNECTIVITY_CHECK_SET_TCP_HANDSHAKE) {
- if (!tb2[STATS_SRC_PORT] ||
- !tb2[STATS_DEST_PORT]) {
- dp_err("Source/Dest port is not present");
- err = -EINVAL;
- goto end;
- }
- arp_stats_params->tcp_src_port =
- nla_get_u32(
- tb2[STATS_SRC_PORT]);
- arp_stats_params->tcp_dst_port =
- nla_get_u32(
- tb2[STATS_DEST_PORT]);
- ucfg_dp_set_track_src_port_value(vdev,
- arp_stats_params->tcp_src_port);
- ucfg_dp_set_track_dest_port_value(vdev,
- arp_stats_params->tcp_dst_port);
- }
- if (pkt_bitmap &
- CONNECTIVITY_CHECK_SET_ICMPV4) {
- if (!tb2[STATS_DEST_IPV4]) {
- dp_err("destination ipv4 address to track ping packets is not present");
- err = -EINVAL;
- goto end;
- }
- arp_stats_params->icmp_ipv4 =
- nla_get_u32(
- tb2[STATS_DEST_IPV4]);
- ucfg_dp_set_track_dest_ipv4_value(vdev,
- arp_stats_params->icmp_ipv4);
- }
- } else {
- /* clear stats command received */
- arp_stats_params->pkt_type_bitmap = pkt_bitmap;
- arp_stats_params->flag = false;
- pkt_type_bitmap &=
- (~arp_stats_params->pkt_type_bitmap);
- ucfg_dp_set_pkt_type_bitmap_value(vdev, pkt_type_bitmap);
- if (pkt_bitmap & CONNECTIVITY_CHECK_SET_ARP) {
- arp_stats_params->pkt_type =
- WLAN_NUD_STATS_ARP_PKT_TYPE;
- ucfg_dp_clear_arp_stats(vdev);
- ucfg_dp_set_track_arp_ip_value(vdev, 0);
- }
- if (pkt_bitmap & CONNECTIVITY_CHECK_SET_DNS) {
- /* DNStracking isn't supported in FW. */
- arp_stats_params->pkt_type_bitmap &=
- ~CONNECTIVITY_CHECK_SET_DNS;
- ucfg_dp_clear_dns_stats(vdev);
- ucfg_dp_clear_dns_payload_value(vdev);
- ucfg_dp_set_track_dns_domain_len_value(vdev, 0);
- }
- if (pkt_bitmap &
- CONNECTIVITY_CHECK_SET_TCP_HANDSHAKE) {
- ucfg_dp_clear_tcp_stats(vdev);
- ucfg_dp_set_track_src_port_value(vdev,
- 0);
- ucfg_dp_set_track_dest_port_value(vdev,
- 0);
- }
- if (pkt_bitmap &
- CONNECTIVITY_CHECK_SET_ICMPV4) {
- ucfg_dp_clear_icmpv4_stats(vdev);
- ucfg_dp_set_track_dest_ipv4_value(vdev,
- 0);
- }
- }
- } else {
- dp_err("stats list empty");
- err = -EINVAL;
- goto end;
- }
- }
- end:
- return err;
- }
- /**
- * osif_dp_populate_dns_stats_info() - populate dns stats info
- * @vdev: vdev context
- * @skb: pointer to skb
- *
- *
- * Return: An error code or 0 on success.
- */
- static int osif_dp_populate_dns_stats_info(struct wlan_objmgr_vdev *vdev,
- struct sk_buff *skb)
- {
- uint8_t *dns_query;
- uint32_t track_dns_domain_len;
- struct dp_dns_stats *dns_stats = ucfg_dp_get_dns_stats(vdev);
- if (!dns_stats) {
- dp_err("Unable to get DNS stats");
- return -EINVAL;
- }
- track_dns_domain_len = ucfg_dp_get_track_dns_domain_len_value(vdev);
- dns_query = qdf_mem_malloc(track_dns_domain_len + 1);
- if (!dns_query)
- return -EINVAL;
- ucfg_dp_get_dns_payload_value(vdev, dns_query);
- if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
- CONNECTIVITY_CHECK_SET_DNS) ||
- nla_put(skb, CHECK_STATS_PKT_DNS_DOMAIN_NAME,
- track_dns_domain_len,
- dp_dns_unmake_name_query(dns_query)) ||
- nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
- dns_stats->tx_dns_req_count) ||
- nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
- dns_stats->tx_host_fw_sent) ||
- nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
- dns_stats->tx_host_fw_sent) ||
- nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
- dns_stats->tx_ack_cnt) ||
- nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC,
- dns_stats->rx_dns_rsp_count) ||
- nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV,
- dns_stats->rx_delivered) ||
- nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP,
- dns_stats->rx_host_drop)) {
- dp_err("nla put fail");
- qdf_mem_free(dns_query);
- kfree_skb(skb);
- return -EINVAL;
- }
- qdf_mem_free(dns_query);
- return 0;
- }
- /**
- * osif_dp_populate_tcp_stats_info() - populate tcp stats info
- * @vdev: pointer to vdev context
- * @skb: pointer to skb
- * @pkt_type: tcp pkt type
- *
- * Return: An error code or 0 on success.
- */
- static int osif_dp_populate_tcp_stats_info(struct wlan_objmgr_vdev *vdev,
- struct sk_buff *skb,
- uint8_t pkt_type)
- {
- uint32_t track_src_port = ucfg_dp_get_track_src_port_value(vdev);
- uint32_t track_dest_port = ucfg_dp_get_track_dest_port_value(vdev);
- struct dp_tcp_stats *tcp_stats = ucfg_dp_get_tcp_stats(vdev);
- if (!tcp_stats) {
- dp_err("Unable to get TCP stats");
- return -EINVAL;
- }
- switch (pkt_type) {
- case CONNECTIVITY_CHECK_SET_TCP_SYN:
- /* Fill info for tcp syn packets (tx packet) */
- if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
- CONNECTIVITY_CHECK_SET_TCP_SYN) ||
- nla_put_u16(skb, CHECK_STATS_PKT_SRC_PORT,
- track_src_port) ||
- nla_put_u16(skb, CHECK_STATS_PKT_DEST_PORT,
- track_dest_port) ||
- nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
- tcp_stats->tx_tcp_syn_count) ||
- nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
- tcp_stats->tx_tcp_syn_host_fw_sent) ||
- nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
- tcp_stats->tx_tcp_syn_host_fw_sent) ||
- nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
- tcp_stats->tx_tcp_syn_ack_cnt)) {
- dp_err("nla put fail");
- kfree_skb(skb);
- return -EINVAL;
- }
- break;
- case CONNECTIVITY_CHECK_SET_TCP_SYN_ACK:
- /* Fill info for tcp syn-ack packets (rx packet) */
- if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
- CONNECTIVITY_CHECK_SET_TCP_SYN_ACK) ||
- nla_put_u16(skb, CHECK_STATS_PKT_SRC_PORT,
- track_src_port) ||
- nla_put_u16(skb, CHECK_STATS_PKT_DEST_PORT,
- track_dest_port) ||
- nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC,
- tcp_stats->rx_fw_cnt) ||
- nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC,
- tcp_stats->rx_tcp_syn_ack_count) ||
- nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV,
- tcp_stats->rx_delivered) ||
- nla_put_u16(skb,
- CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP,
- tcp_stats->rx_host_drop)) {
- dp_err("nla put fail");
- kfree_skb(skb);
- return -EINVAL;
- }
- break;
- case CONNECTIVITY_CHECK_SET_TCP_ACK:
- /* Fill info for tcp ack packets (tx packet) */
- if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
- CONNECTIVITY_CHECK_SET_TCP_ACK) ||
- nla_put_u16(skb, CHECK_STATS_PKT_SRC_PORT,
- track_src_port) ||
- nla_put_u16(skb, CHECK_STATS_PKT_DEST_PORT,
- track_dest_port) ||
- nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
- tcp_stats->tx_tcp_ack_count) ||
- nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
- tcp_stats->tx_tcp_ack_host_fw_sent) ||
- nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
- tcp_stats->tx_tcp_ack_host_fw_sent) ||
- nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
- tcp_stats->tx_tcp_ack_ack_cnt)) {
- dp_err("nla put fail");
- kfree_skb(skb);
- return -EINVAL;
- }
- break;
- default:
- break;
- }
- return 0;
- }
- /**
- * osif_dp_populate_icmpv4_stats_info() - populate icmpv4 stats
- * @vdev: pointer to vdev context
- * @skb: pointer to skb
- *
- *
- * Return: An error code or 0 on success.
- */
- static int osif_dp_populate_icmpv4_stats_info(struct wlan_objmgr_vdev *vdev,
- struct sk_buff *skb)
- {
- struct dp_icmpv4_stats *icmpv4_stats = ucfg_dp_get_icmpv4_stats(vdev);
- uint32_t track_dest_ipv4 = ucfg_dp_get_track_dest_ipv4_value(vdev);
- if (!icmpv4_stats) {
- dp_err("Unable to get ICMP stats");
- return -EINVAL;
- }
- if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
- CONNECTIVITY_CHECK_SET_ICMPV4) ||
- nla_put_u32(skb, CHECK_STATS_PKT_DEST_IPV4,
- track_dest_ipv4) ||
- nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
- icmpv4_stats->tx_icmpv4_req_count) ||
- nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
- icmpv4_stats->tx_host_fw_sent) ||
- nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
- icmpv4_stats->tx_host_fw_sent) ||
- nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
- icmpv4_stats->tx_ack_cnt) ||
- nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC,
- icmpv4_stats->rx_fw_cnt) ||
- nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC,
- icmpv4_stats->rx_icmpv4_rsp_count) ||
- nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV,
- icmpv4_stats->rx_delivered) ||
- nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP,
- icmpv4_stats->rx_host_drop)) {
- dp_err("nla put fail");
- kfree_skb(skb);
- return -EINVAL;
- }
- return 0;
- }
- /**
- * osif_dp_populate_connectivity_check_stats_info() - Poplulate connectivity
- * stats info
- * @vdev: pointer to vdev context
- * @skb: pointer to skb
- *
- *
- * Return: An error code or 0 on success.
- */
- static int
- osif_dp_populate_connectivity_check_stats_info(struct wlan_objmgr_vdev *vdev,
- struct sk_buff *skb)
- {
- struct nlattr *connect_stats, *connect_info;
- uint32_t count = 0;
- uint32_t pkt_type_bitmap = ucfg_dp_get_pkt_type_bitmap_value(vdev);
- connect_stats = nla_nest_start(skb, DATA_PKT_STATS);
- if (!connect_stats) {
- dp_err("nla_nest_start failed");
- return -EINVAL;
- }
- if (pkt_type_bitmap & CONNECTIVITY_CHECK_SET_DNS) {
- connect_info = nla_nest_start(skb, count);
- if (!connect_info) {
- dp_err("nla_nest_start failed count %u", count);
- return -EINVAL;
- }
- if (osif_dp_populate_dns_stats_info(vdev, skb))
- goto put_attr_fail;
- nla_nest_end(skb, connect_info);
- count++;
- }
- if (pkt_type_bitmap & CONNECTIVITY_CHECK_SET_TCP_HANDSHAKE) {
- connect_info = nla_nest_start(skb, count);
- if (!connect_info) {
- dp_err("nla_nest_start failed count %u", count);
- return -EINVAL;
- }
- if (osif_dp_populate_tcp_stats_info(vdev, skb,
- CONNECTIVITY_CHECK_SET_TCP_SYN))
- goto put_attr_fail;
- nla_nest_end(skb, connect_info);
- count++;
- connect_info = nla_nest_start(skb, count);
- if (!connect_info) {
- dp_err("nla_nest_start failed count %u", count);
- return -EINVAL;
- }
- if (osif_dp_populate_tcp_stats_info(vdev, skb,
- CONNECTIVITY_CHECK_SET_TCP_SYN_ACK))
- goto put_attr_fail;
- nla_nest_end(skb, connect_info);
- count++;
- connect_info = nla_nest_start(skb, count);
- if (!connect_info) {
- dp_err("nla_nest_start failed count %u", count);
- return -EINVAL;
- }
- if (osif_dp_populate_tcp_stats_info(vdev, skb,
- CONNECTIVITY_CHECK_SET_TCP_ACK))
- goto put_attr_fail;
- nla_nest_end(skb, connect_info);
- count++;
- }
- if (pkt_type_bitmap & CONNECTIVITY_CHECK_SET_ICMPV4) {
- connect_info = nla_nest_start(skb, count);
- if (!connect_info) {
- dp_err("nla_nest_start failed count %u", count);
- return -EINVAL;
- }
- if (osif_dp_populate_icmpv4_stats_info(vdev, skb))
- goto put_attr_fail;
- nla_nest_end(skb, connect_info);
- count++;
- }
- nla_nest_end(skb, connect_stats);
- return 0;
- put_attr_fail:
- dp_err("QCA_WLAN_VENDOR_ATTR put fail. count %u", count);
- return -EINVAL;
- }
- int osif_dp_get_nud_stats(struct wiphy *wiphy,
- struct wlan_objmgr_vdev *vdev,
- const void *data, int data_len)
- {
- int err = 0;
- struct dp_get_arp_stats_params arp_stats_params;
- void *soc = cds_get_context(QDF_MODULE_ID_SOC);
- uint32_t pkt_type_bitmap = ucfg_dp_get_pkt_type_bitmap_value(vdev);
- struct sk_buff *skb;
- struct osif_request *request = NULL;
- struct dp_arp_stats *arp_stats;
- struct wlan_objmgr_psoc *psoc = wlan_vdev_get_psoc(vdev);
- static const struct osif_request_params params = {
- .priv_size = 0,
- .timeout_ms = WLAN_WAIT_TIME_NUD_STATS,
- };
- request = osif_request_alloc(¶ms);
- if (!request) {
- dp_err("Request allocation failure");
- return -ENOMEM;
- }
- ucfg_dp_set_nud_stats_cb(psoc, osif_request_cookie(request));
- arp_stats_params.pkt_type = WLAN_NUD_STATS_ARP_PKT_TYPE;
- arp_stats_params.vdev_id = ucfg_dp_get_link_id(vdev);
- /* send NUD failure event only when ARP tracking is enabled. */
- if (ucfg_dp_nud_fail_data_stall_evt_enabled() &&
- !ucfg_dp_nud_tracking_enabled(psoc) &&
- (pkt_type_bitmap & CONNECTIVITY_CHECK_SET_ARP)) {
- QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_ERROR,
- "Data stall due to NUD failure");
- cdp_post_data_stall_event(soc,
- DATA_STALL_LOG_INDICATOR_FRAMEWORK,
- DATA_STALL_LOG_NUD_FAILURE,
- OL_TXRX_PDEV_ID, 0XFF,
- DATA_STALL_LOG_RECOVERY_TRIGGER_PDR);
- }
- if (QDF_STATUS_SUCCESS !=
- ucfg_dp_req_get_arp_stats(psoc, &arp_stats_params)) {
- dp_err("Unable to sent ARP stats request");
- err = -EINVAL;
- goto exit;
- }
- err = osif_request_wait_for_response(request);
- if (err) {
- dp_err("timedout while retrieving NUD stats");
- err = -ETIMEDOUT;
- goto exit;
- }
- arp_stats = ucfg_dp_get_arp_stats(vdev);
- if (!arp_stats) {
- dp_err("Unable to get ARP stats");
- err = -EINVAL;
- goto exit;
- }
- skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
- WLAN_NUD_STATS_LEN);
- if (!skb) {
- dp_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
- err = -ENOMEM;
- goto exit;
- }
- if (nla_put_u16(skb, COUNT_FROM_NETDEV,
- arp_stats->tx_arp_req_count) ||
- nla_put_u16(skb, COUNT_TO_LOWER_MAC,
- arp_stats->tx_host_fw_sent) ||
- nla_put_u16(skb, RX_COUNT_BY_LOWER_MAC,
- arp_stats->tx_host_fw_sent) ||
- nla_put_u16(skb, COUNT_TX_SUCCESS,
- arp_stats->tx_ack_cnt) ||
- nla_put_u16(skb, RSP_RX_COUNT_BY_LOWER_MAC,
- arp_stats->rx_fw_cnt) ||
- nla_put_u16(skb, RSP_RX_COUNT_BY_UPPER_MAC,
- arp_stats->rx_arp_rsp_count) ||
- nla_put_u16(skb, RSP_COUNT_TO_NETDEV,
- arp_stats->rx_delivered) ||
- nla_put_u16(skb, RSP_COUNT_OUT_OF_ORDER_DROP,
- arp_stats->rx_host_drop_reorder)) {
- dp_err("nla put fail");
- wlan_cfg80211_vendor_free_skb(skb);
- err = -EINVAL;
- goto exit;
- }
- if (ucfg_dp_get_con_status_value(vdev))
- nla_put_flag(skb, AP_LINK_ACTIVE);
- if (ucfg_dp_get_dad_value(vdev))
- nla_put_flag(skb, AP_LINK_DAD);
- /* ARP tracking is done above. */
- pkt_type_bitmap &= ~CONNECTIVITY_CHECK_SET_ARP;
- if (pkt_type_bitmap) {
- if (osif_dp_populate_connectivity_check_stats_info(vdev, skb)) {
- err = -EINVAL;
- goto exit;
- }
- }
- wlan_cfg80211_vendor_cmd_reply(skb);
- exit:
- ucfg_dp_clear_nud_stats_cb(psoc);
- osif_request_put(request);
- return err;
- }
- int osif_dp_set_nud_stats(struct wiphy *wiphy,
- struct wlan_objmgr_vdev *vdev,
- const void *data, int data_len)
- {
- struct nlattr *tb[STATS_SET_MAX + 1];
- struct wlan_objmgr_psoc *psoc = wlan_vdev_get_psoc(vdev);
- struct dp_set_arp_stats_params arp_stats_params = {0};
- uint32_t pkt_type_bitmap = ucfg_dp_get_pkt_type_bitmap_value(vdev);
- int err = 0;
- err = wlan_cfg80211_nla_parse(tb, STATS_SET_MAX, data, data_len,
- dp_set_nud_stats_policy);
- if (err) {
- dp_err("STATS_SET_START ATTR");
- return err;
- }
- if (tb[STATS_SET_START]) {
- /* tracking is enabled for stats other than arp. */
- if (tb[STATS_SET_DATA_PKT_INFO]) {
- err = osif_dp_set_clear_connectivity_check_stats_info(
- vdev,
- &arp_stats_params, tb, true);
- if (err)
- return -EINVAL;
- /*
- * if only tracking dns, then don't send
- * wmi command to FW.
- */
- if (!arp_stats_params.pkt_type_bitmap)
- return err;
- } else {
- if (!tb[STATS_GW_IPV4]) {
- dp_err("STATS_SET_START CMD");
- return -EINVAL;
- }
- arp_stats_params.pkt_type_bitmap =
- CONNECTIVITY_CHECK_SET_ARP;
- pkt_type_bitmap |=
- arp_stats_params.pkt_type_bitmap;
- ucfg_dp_set_pkt_type_bitmap_value(vdev,
- pkt_type_bitmap);
- arp_stats_params.flag = true;
- arp_stats_params.ip_addr =
- nla_get_u32(tb[STATS_GW_IPV4]);
- ucfg_dp_set_track_arp_ip_value(vdev,
- arp_stats_params.ip_addr);
- arp_stats_params.pkt_type = WLAN_NUD_STATS_ARP_PKT_TYPE;
- }
- } else {
- /* clear stats command received. */
- if (tb[STATS_SET_DATA_PKT_INFO]) {
- err = osif_dp_set_clear_connectivity_check_stats_info(
- vdev,
- &arp_stats_params, tb, false);
- if (err)
- return -EINVAL;
- /*
- * if only tracking dns, then don't send
- * wmi command to FW.
- */
- if (!arp_stats_params.pkt_type_bitmap)
- return err;
- } else {
- arp_stats_params.pkt_type_bitmap =
- CONNECTIVITY_CHECK_SET_ARP;
- pkt_type_bitmap &= (~arp_stats_params.pkt_type_bitmap);
- ucfg_dp_set_pkt_type_bitmap_value(vdev,
- pkt_type_bitmap);
- arp_stats_params.flag = false;
- ucfg_dp_clear_arp_stats(vdev);
- arp_stats_params.pkt_type = WLAN_NUD_STATS_ARP_PKT_TYPE;
- }
- }
- dp_info("STATS_SET_START Received flag %d!", arp_stats_params.flag);
- arp_stats_params.vdev_id = ucfg_dp_get_link_id(vdev);
- if (QDF_STATUS_SUCCESS !=
- ucfg_dp_req_set_arp_stats(psoc, &arp_stats_params)) {
- dp_err("Unable to set ARP stats!");
- return -EINVAL;
- }
- return err;
- }
- /*
- * os_if_dp_register_event_handler() - Register osif event handler
- * @psoc: psoc handle
- *
- * Return: None
- */
- static void os_if_dp_register_event_handler(struct wlan_objmgr_psoc *psoc)
- {
- struct wlan_dp_psoc_nb_ops cb_obj = {0};
- cb_obj.osif_dp_get_arp_stats_evt =
- osif_dp_get_arp_stats_event_handler;
- ucfg_dp_register_event_handler(psoc, &cb_obj);
- }
- void os_if_dp_register_hdd_callbacks(struct wlan_objmgr_psoc *psoc,
- struct wlan_dp_psoc_callbacks *cb_obj)
- {
- cb_obj->osif_dp_send_tcp_param_update_event =
- osif_dp_send_tcp_param_update_event;
- cb_obj->os_if_dp_nud_stats_info = os_if_dp_nud_stats_info;
- cb_obj->osif_dp_process_mic_error = osif_dp_process_mic_error;
- os_if_dp_register_txrx_callbacks(cb_obj);
- ucfg_dp_register_hdd_callbacks(psoc, cb_obj);
- os_if_dp_register_event_handler(psoc);
- }
|