From 26c6cd139774c1420ed4abc75bcb816671d0e45e Mon Sep 17 00:00:00 2001 From: Pavankumar Nandeshwar Date: Mon, 23 Aug 2021 11:39:47 -0700 Subject: [PATCH] qcacmn: Enable intra-bss in Waikiki In Beryllium the HW does the ast lookup and match and sets the intra-bss bit in the msdu_desc_info structure of reo_destination ring and WBM Rx release ring. So, change the Beryllium code to make use of this hardware assistance for intra-bss. Change-Id: Ic7c89efc741fefe35603082309204fbe3c9a97c7 --- dp/wifi3.0/be/dp_be_rx.c | 128 ++++++++++++++++++++++++++++++++++++- dp/wifi3.0/be/dp_be_rx.h | 21 ++++++ dp/wifi3.0/dp_rx.c | 50 +++++---------- dp/wifi3.0/dp_rx.h | 48 ++++++++++---- dp/wifi3.0/li/dp_li_rx.c | 2 +- hal/wifi3.0/be/hal_be_rx.h | 8 +++ hal/wifi3.0/hal_rx.h | 4 +- 7 files changed, 210 insertions(+), 51 deletions(-) diff --git a/dp/wifi3.0/be/dp_be_rx.c b/dp/wifi3.0/be/dp_be_rx.c index a3af5e40c6..16ddedb4d3 100644 --- a/dp/wifi3.0/be/dp_be_rx.c +++ b/dp/wifi3.0/be/dp_be_rx.c @@ -20,6 +20,7 @@ #include "hal_hw_headers.h" #include "dp_types.h" #include "dp_rx.h" +#include "dp_tx.h" #include "dp_be_rx.h" #include "dp_peer.h" #include "hal_rx.h" @@ -339,6 +340,9 @@ more_data: if (msdu_desc_info.msdu_flags & HAL_MSDU_F_SA_IS_VALID) qdf_nbuf_set_sa_valid(rx_desc->nbuf, 1); + if (msdu_desc_info.msdu_flags & HAL_MSDU_F_INTRA_BSS) + qdf_nbuf_set_intra_bss(rx_desc->nbuf, 1); + qdf_nbuf_set_tid_val(rx_desc->nbuf, HAL_RX_REO_QUEUE_NUMBER_GET(ring_desc)); #ifdef CONFIG_LITHIUM @@ -685,8 +689,9 @@ done: /* Intrabss-fwd */ if (dp_rx_check_ap_bridge(vdev)) - if (DP_RX_INTRABSS_FWD(soc, peer, rx_tlv_hdr, - nbuf, msdu_metadata)) { + if (dp_rx_intrabss_fwd_be(soc, peer, rx_tlv_hdr, + nbuf, + msdu_metadata)) { nbuf = next; tid_stats->intrabss_cnt++; continue; /* Get next desc */ @@ -1025,3 +1030,122 @@ uint32_t dp_rx_nf_process(struct dp_intr *int_ctx, return work_done; } #endif + +#ifndef QCA_HOST_MODE_WIFI_DISABLED +#if defined(QCA_WIFI_WCN7850) || !defined(INTRA_BSS_FW_OFFLOAD) +bool dp_rx_intrabss_fwd_be(struct dp_soc *soc, struct dp_peer *ta_peer, + uint8_t *rx_tlv_hdr, qdf_nbuf_t nbuf, + struct hal_rx_msdu_metadata msdu_metadata) +{ + /* Hamilton V1 uses Lithium path */ + return dp_rx_intrabss_fwd(soc, ta_peer, rx_tlv_hdr, nbuf, + msdu_metadata); +} +#else +/* + * dp_rx_intrabss_fwd_be() - API for intrabss fwd. For EAPOL + * pkt with DA not equal to vdev mac addr, fwd is not allowed. + * @soc: core txrx main context + * @ta_peer: source peer entry + * @rx_tlv_hdr: start address of rx tlvs + * @nbuf: nbuf that has to be intrabss forwarded + * @msdu_metadata: msdu metadata + * + * Return: true if it is forwarded else false + */ +bool dp_rx_intrabss_fwd_be(struct dp_soc *soc, struct dp_peer *ta_peer, + uint8_t *rx_tlv_hdr, qdf_nbuf_t nbuf, + struct hal_rx_msdu_metadata msdu_metadata) +{ + uint16_t len; + qdf_nbuf_t nbuf_copy; + uint8_t tid = qdf_nbuf_get_tid_val(nbuf); + uint8_t ring_id = QDF_NBUF_CB_RX_CTX_ID(nbuf); + struct cdp_tid_rx_stats *tid_stats = &ta_peer->vdev->pdev->stats. + tid_stats.tid_rx_stats[ring_id][tid]; + + /* if it is a broadcast pkt (eg: ARP) and it is not its own + * source, then clone the pkt and send the cloned pkt for + * intra BSS forwarding and original pkt up the network stack + * Note: how do we handle multicast pkts. do we forward + * all multicast pkts as is or let a higher layer module + * like igmpsnoop decide whether to forward or not with + * Mcast enhancement. + */ + if (qdf_nbuf_is_da_mcbc(nbuf) && !ta_peer->bss_peer) { + if (dp_rx_intrabss_eapol_drop_check(soc, ta_peer, rx_tlv_hdr, + nbuf)) + return true; + + if (!dp_rx_check_ndi_mdns_fwding(ta_peer, nbuf)) + return false; + + /* If the source peer in the isolation list + * then dont forward instead push to bridge stack + */ + if (dp_get_peer_isolation(ta_peer)) + return false; + + nbuf_copy = qdf_nbuf_copy(nbuf); + if (!nbuf_copy) + return false; + + len = QDF_NBUF_CB_RX_PKT_LEN(nbuf); + if (dp_tx_send((struct cdp_soc_t *)soc, + ta_peer->vdev->vdev_id, nbuf_copy)) { + DP_STATS_INC_PKT(ta_peer, rx.intra_bss.fail, 1, len); + tid_stats->fail_cnt[INTRABSS_DROP]++; + qdf_nbuf_free(nbuf_copy); + } else { + DP_STATS_INC_PKT(ta_peer, rx.intra_bss.pkts, 1, len); + tid_stats->intrabss_cnt++; + } + return false; + } + + if (qdf_nbuf_is_intra_bss(nbuf)) { + if (dp_rx_intrabss_eapol_drop_check(soc, ta_peer, rx_tlv_hdr, + nbuf)) + return true; + + len = QDF_NBUF_CB_RX_PKT_LEN(nbuf); + + /* linearize the nbuf just before we send to + * dp_tx_send() + */ + if (qdf_unlikely(qdf_nbuf_is_frag(nbuf))) { + if (qdf_nbuf_linearize(nbuf) == -ENOMEM) + return false; + + nbuf = qdf_nbuf_unshare(nbuf); + if (!nbuf) { + DP_STATS_INC_PKT(ta_peer, + rx.intra_bss.fail, 1, len); + /* return true even though the pkt is + * not forwarded. Basically skb_unshare + * failed and we want to continue with + * next nbuf. + */ + tid_stats->fail_cnt[INTRABSS_DROP]++; + return true; + } + } + + if (!dp_tx_send((struct cdp_soc_t *)soc, + ta_peer->vdev->vdev_id, nbuf)) { + DP_STATS_INC_PKT(ta_peer, rx.intra_bss.pkts, 1, + len); + } else { + DP_STATS_INC_PKT(ta_peer, rx.intra_bss.fail, 1, + len); + tid_stats->fail_cnt[INTRABSS_DROP]++; + return false; + } + + return true; + } + return false; +} +#endif +#endif + diff --git a/dp/wifi3.0/be/dp_be_rx.h b/dp/wifi3.0/be/dp_be_rx.h index 35b1a9db7e..6996d21614 100644 --- a/dp/wifi3.0/be/dp_be_rx.h +++ b/dp/wifi3.0/be/dp_be_rx.h @@ -22,6 +22,27 @@ #include #include "dp_be.h" +#ifndef QCA_HOST_MODE_WIFI_DISABLED + +/* + * dp_rx_intrabss_fwd_be() - API for intrabss fwd. For EAPOL + * pkt with DA not equal to vdev mac addr, fwd is not allowed. + * @soc: core txrx main context + * @ta_peer: source peer entry + * @rx_tlv_hdr: start address of rx tlvs + * @nbuf: nbuf that has to be intrabss forwarded + * @msdu_metadata: msdu metadata + * + * Return: true if it is forwarded else false + */ + +bool dp_rx_intrabss_fwd_be(struct dp_soc *soc, + struct dp_peer *ta_peer, + uint8_t *rx_tlv_hdr, + qdf_nbuf_t nbuf, + struct hal_rx_msdu_metadata msdu_metadata); +#endif + uint32_t dp_rx_process_be(struct dp_intr *int_ctx, hal_ring_handle_t hal_ring_hdl, uint8_t reo_ring_num, uint32_t quota); diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index 5c35482b31..53c0605ec0 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/dp/wifi3.0/dp_rx.c @@ -39,28 +39,6 @@ #include "dp_txrx_wds.h" #endif -#ifndef QCA_HOST_MODE_WIFI_DISABLED - -#ifdef DP_RX_DISABLE_NDI_MDNS_FORWARDING -static inline -bool dp_rx_check_ndi_mdns_fwding(struct dp_peer *ta_peer, qdf_nbuf_t nbuf) -{ - if (ta_peer->vdev->opmode == wlan_op_mode_ndi && - qdf_nbuf_is_ipv6_mdns_pkt(nbuf)) { - DP_STATS_INC(ta_peer, rx.intra_bss.mdns_no_fwd, 1); - return false; - } - return true; -} -#else -static inline -bool dp_rx_check_ndi_mdns_fwding(struct dp_peer *ta_peer, qdf_nbuf_t nbuf) -{ - return true; -} -#endif -#endif /* QCA_HOST_MODE_WIFI_DISABLED */ - #ifdef DUP_RX_DESC_WAR void dp_rx_dump_info_and_assert(struct dp_soc *soc, hal_ring_handle_t hal_ring, @@ -566,6 +544,9 @@ dp_rx_intrabss_fwd(struct dp_soc *soc, */ if ((qdf_nbuf_is_da_valid(nbuf) && !qdf_nbuf_is_da_mcbc(nbuf))) { + if (dp_rx_intrabss_eapol_drop_check(soc, ta_peer, rx_tlv_hdr, + nbuf)) + return true; ast_entry = soc->ast_table[msdu_metadata.da_idx]; if (!ast_entry) @@ -594,6 +575,16 @@ dp_rx_intrabss_fwd(struct dp_soc *soc, DP_MOD_ID_RX); if (!da_peer) return false; + + /* If the source or destination peer in the isolation + * list then dont forward instead push to bridge stack. + */ + if (dp_get_peer_isolation(ta_peer) || + dp_get_peer_isolation(da_peer)) { + dp_peer_unref_delete(da_peer, DP_MOD_ID_RX); + return false; + } + is_da_bss_peer = da_peer->bss_peer; dp_peer_unref_delete(da_peer, DP_MOD_ID_RX); @@ -602,13 +593,6 @@ dp_rx_intrabss_fwd(struct dp_soc *soc, is_frag = qdf_nbuf_is_frag(nbuf); memset(nbuf->cb, 0x0, sizeof(nbuf->cb)); - /* If the source or destination peer in the isolation - * list then dont forward instead push to bridge stack. - */ - if (dp_get_peer_isolation(ta_peer) || - dp_get_peer_isolation(da_peer)) - return false; - /* linearize the nbuf just before we send to * dp_tx_send() */ @@ -655,6 +639,10 @@ dp_rx_intrabss_fwd(struct dp_soc *soc, */ else if (qdf_unlikely((qdf_nbuf_is_da_mcbc(nbuf) && !ta_peer->bss_peer))) { + if (dp_rx_intrabss_eapol_drop_check(soc, ta_peer, rx_tlv_hdr, + nbuf)) + return true; + if (!dp_rx_check_ndi_mdns_fwding(ta_peer, nbuf)) goto end; @@ -669,10 +657,6 @@ dp_rx_intrabss_fwd(struct dp_soc *soc, goto end; len = QDF_NBUF_CB_RX_PKT_LEN(nbuf); - memset(nbuf_copy->cb, 0x0, sizeof(nbuf_copy->cb)); - - /* Set cb->ftype to intrabss FWD */ - qdf_nbuf_set_tx_ftype(nbuf_copy, CB_FTYPE_INTRABSS_FWD); if (dp_tx_send((struct cdp_soc_t *)soc, ta_peer->vdev->vdev_id, nbuf_copy)) { DP_STATS_INC_PKT(ta_peer, rx.intra_bss.fail, 1, len); diff --git a/dp/wifi3.0/dp_rx.h b/dp/wifi3.0/dp_rx.h index 0288da43fa..b76c1b37f2 100644 --- a/dp/wifi3.0/dp_rx.h +++ b/dp/wifi3.0/dp_rx.h @@ -272,6 +272,27 @@ bool dp_rx_deliver_special_frame(struct dp_soc *soc, struct dp_peer *peer, } #endif +#ifndef QCA_HOST_MODE_WIFI_DISABLED +#ifdef DP_RX_DISABLE_NDI_MDNS_FORWARDING +static inline +bool dp_rx_check_ndi_mdns_fwding(struct dp_peer *ta_peer, qdf_nbuf_t nbuf) +{ + if (ta_peer->vdev->opmode == wlan_op_mode_ndi && + qdf_nbuf_is_ipv6_mdns_pkt(nbuf)) { + DP_STATS_INC(ta_peer, rx.intra_bss.mdns_no_fwd, 1); + return false; + } + return true; +} +#else +static inline +bool dp_rx_check_ndi_mdns_fwding(struct dp_peer *ta_peer, qdf_nbuf_t nbuf) +{ + return true; +} +#endif +#endif /* QCA_HOST_MODE_WIFI_DISABLED */ + /* DOC: Offset to obtain LLC hdr * * In the case of Wifi parse error @@ -1101,20 +1122,19 @@ bool dp_rx_intrabss_fwd(struct dp_soc *soc, #ifdef DISABLE_EAPOL_INTRABSS_FWD /* - * dp_rx_intrabss_fwd_wrapper() - Wrapper API for intrabss fwd. For EAPOL + * dp_rx_intrabss_eapol_drop_check() - API For EAPOL * pkt with DA not equal to vdev mac addr, fwd is not allowed. * @soc: core txrx main context * @ta_peer: source peer entry * @rx_tlv_hdr: start address of rx tlvs * @nbuf: nbuf that has to be intrabss forwarded - * @msdu_metadata: msdu metadata * * Return: true if it is forwarded else false */ static inline -bool dp_rx_intrabss_fwd_wrapper(struct dp_soc *soc, struct dp_peer *ta_peer, - uint8_t *rx_tlv_hdr, qdf_nbuf_t nbuf, - struct hal_rx_msdu_metadata msdu_metadata) +bool dp_rx_intrabss_eapol_drop_check(struct dp_soc *soc, + struct dp_peer *ta_peer, + uint8_t *rx_tlv_hdr, qdf_nbuf_t nbuf) { if (qdf_unlikely(qdf_nbuf_is_ipv4_eapol_pkt(nbuf) && qdf_mem_cmp(qdf_nbuf_data(nbuf) + @@ -1126,18 +1146,18 @@ bool dp_rx_intrabss_fwd_wrapper(struct dp_soc *soc, struct dp_peer *ta_peer, return true; } - return dp_rx_intrabss_fwd(soc, ta_peer, rx_tlv_hdr, nbuf, - msdu_metadata); + return false; } - -#define DP_RX_INTRABSS_FWD(soc, peer, rx_tlv_hdr, nbuf, msdu_metadata) \ - dp_rx_intrabss_fwd_wrapper(soc, peer, rx_tlv_hdr, nbuf, \ - msdu_metadata) #else /* DISABLE_EAPOL_INTRABSS_FWD */ -#define DP_RX_INTRABSS_FWD(soc, peer, rx_tlv_hdr, nbuf, msdu_metadata) \ - dp_rx_intrabss_fwd(soc, peer, rx_tlv_hdr, nbuf, msdu_metadata) -#endif /* DISABLE_EAPOL_INTRABSS_FWD */ +static inline +bool dp_rx_intrabss_eapol_drop_check(struct dp_soc *soc, + struct dp_peer *ta_peer, + uint8_t *rx_tlv_hdr, qdf_nbuf_t nbuf) +{ + return false; +} +#endif /* DISABLE_EAPOL_INTRABSS_FWD */ /** * dp_rx_defrag_concat() - Concatenate the fragments * diff --git a/dp/wifi3.0/li/dp_li_rx.c b/dp/wifi3.0/li/dp_li_rx.c index 1d2ac4f5e7..32cf1b34cd 100644 --- a/dp/wifi3.0/li/dp_li_rx.c +++ b/dp/wifi3.0/li/dp_li_rx.c @@ -752,7 +752,7 @@ done: /* Intrabss-fwd */ if (dp_rx_check_ap_bridge(vdev)) - if (DP_RX_INTRABSS_FWD(soc, peer, rx_tlv_hdr, + if (dp_rx_intrabss_fwd(soc, peer, rx_tlv_hdr, nbuf, msdu_metadata)) { nbuf = next; tid_stats->intrabss_cnt++; diff --git a/hal/wifi3.0/be/hal_be_rx.h b/hal/wifi3.0/be/hal_be_rx.h index 8a94b5cbfe..acfed6b8dc 100644 --- a/hal/wifi3.0/be/hal_be_rx.h +++ b/hal/wifi3.0/be/hal_be_rx.h @@ -166,6 +166,11 @@ RX_MSDU_DESC_INFO_DA_IS_MCBC_OFFSET)) & \ RX_MSDU_DESC_INFO_DA_IS_MCBC_MASK) +#define HAL_RX_MSDU_INTRA_BSS_FLAG_GET(msdu_info_ptr) \ + ((*_OFFSET_TO_WORD_PTR(msdu_info_ptr, \ + RX_MSDU_DESC_INFO_INTRA_BSS_OFFSET)) & \ + RX_MSDU_DESC_INFO_INTRA_BSS_MASK) + #define HAL_RX_MPDU_ENCRYPT_TYPE_GET(_rx_mpdu_info) \ (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ RX_MPDU_INFO_ENCRYPT_TYPE_OFFSET)), \ @@ -367,6 +372,9 @@ uint32_t hal_rx_msdu_flags_get_be(rx_msdu_desc_info_t msdu_desc_info_hdl) if (HAL_RX_MSDU_DA_IS_MCBC_FLAG_GET(msdu_desc_info)) flags |= HAL_MSDU_F_DA_IS_MCBC; + if (HAL_RX_MSDU_INTRA_BSS_FLAG_GET(msdu_desc_info)) + flags |= HAL_MSDU_F_INTRA_BSS; + return flags; } diff --git a/hal/wifi3.0/hal_rx.h b/hal/wifi3.0/hal_rx.h index cc44e569f4..a58b24a7e0 100644 --- a/hal/wifi3.0/hal_rx.h +++ b/hal/wifi3.0/hal_rx.h @@ -193,6 +193,7 @@ struct hal_rx_msdu_desc_info { * @ HAL_MSDU_F_DA_IS_VALID: Found match for DA in AST * @ HAL_MSDU_F_DA_IS_MCBC: DA is MC/BC address * @ HAL_MSDU_F_DA_IDX_TIMEOUT: AST search for DA timed out + * @ HAL_MSDU_F_INTRA_BSS: This is an intrabss packet */ enum hal_rx_msdu_desc_flags { HAL_MSDU_F_FIRST_MSDU_IN_MPDU = (0x1 << 0), @@ -202,7 +203,8 @@ enum hal_rx_msdu_desc_flags { HAL_MSDU_F_SA_IDX_TIMEOUT = (0x1 << 24), HAL_MSDU_F_DA_IS_VALID = (0x1 << 25), HAL_MSDU_F_DA_IS_MCBC = (0x1 << 26), - HAL_MSDU_F_DA_IDX_TIMEOUT = (0x1 << 27) + HAL_MSDU_F_DA_IDX_TIMEOUT = (0x1 << 27), + HAL_MSDU_F_INTRA_BSS = (0x1 << 28), }; /*