diff --git a/dp/inc/cdp_txrx_cmn.h b/dp/inc/cdp_txrx_cmn.h index 35be83ac92..55439d5a42 100644 --- a/dp/inc/cdp_txrx_cmn.h +++ b/dp/inc/cdp_txrx_cmn.h @@ -708,6 +708,32 @@ cdp_peer_delete(ol_txrx_soc_handle soc, uint8_t vdev_id, soc->ops->cmn_drv_ops->txrx_peer_delete(soc, vdev_id, peer_mac, bitmap); } +#ifdef DP_RX_UDP_OVER_PEER_ROAM +static inline void +cdp_update_roaming_peer_in_vdev(ol_txrx_soc_handle soc, uint8_t vdev_id, + uint8_t *peer_mac, uint32_t auth_status) +{ + if (!soc || !soc->ops) { + QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, + "%s: Invalid Instance:", __func__); + QDF_BUG(0); + return; + } + + if (!soc->ops->cmn_drv_ops || + !soc->ops->cmn_drv_ops->txrx_update_roaming_peer) + return; + + soc->ops->cmn_drv_ops->txrx_update_roaming_peer(soc, vdev_id, + peer_mac, auth_status); +} +#else +static inline void +cdp_update_roaming_peer_in_vdev(ol_txrx_soc_handle soc, uint8_t vdev_id, + uint8_t *peer_mac, uint32_t auth_status) +{ +} +#endif /** * cdp_peer_detach_sync() - peer detach sync callback * @soc: datapath soc handle diff --git a/dp/inc/cdp_txrx_ops.h b/dp/inc/cdp_txrx_ops.h index f0d7644eb0..b9038c8791 100644 --- a/dp/inc/cdp_txrx_ops.h +++ b/dp/inc/cdp_txrx_ops.h @@ -582,6 +582,13 @@ struct cdp_cmn_ops { QDF_STATUS (*set_vdev_pcp_tid_map)(struct cdp_soc_t *soc, uint8_t vdev_id, uint8_t pcp, uint8_t tid); +#ifdef DP_RX_UDP_OVER_PEER_ROAM + QDF_STATUS (*txrx_update_roaming_peer)(struct cdp_soc_t *soc, + uint8_t vdev_id, + uint8_t *peer_mac, + uint32_t auth_status); +#endif + #ifdef QCA_MULTIPASS_SUPPORT QDF_STATUS (*set_vlan_groupkey)(struct cdp_soc_t *soc, uint8_t vdev_id, uint16_t vlan_id, uint16_t group_key); diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 5e011c3eeb..6b577caa7a 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -8407,6 +8407,26 @@ static QDF_STATUS dp_peer_delete_wifi3(struct cdp_soc_t *soc_hdl, return QDF_STATUS_SUCCESS; } +#ifdef DP_RX_UDP_OVER_PEER_ROAM +static QDF_STATUS dp_update_roaming_peer_wifi3(struct cdp_soc_t *soc_hdl, + uint8_t vdev_id, + uint8_t *peer_mac, + uint32_t auth_status) +{ + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id, + DP_MOD_ID_CDP); + if (!vdev) + return QDF_STATUS_E_FAILURE; + + vdev->roaming_peer_status = auth_status; + qdf_mem_copy(vdev->roaming_peer_mac.raw, peer_mac, + QDF_MAC_ADDR_SIZE); + dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_CDP); + + return QDF_STATUS_SUCCESS; +} +#endif /* * dp_get_vdev_mac_addr_wifi3() – Detach txrx peer * @soc_hdl: Datapath soc handle @@ -12455,6 +12475,9 @@ static struct cdp_cmn_ops dp_ops_cmn = { .txrx_peer_ast_delete_by_pdev = dp_peer_ast_entry_del_by_pdev, .txrx_peer_delete = dp_peer_delete_wifi3, +#ifdef DP_RX_UDP_OVER_PEER_ROAM + .txrx_update_roaming_peer = dp_update_roaming_peer_wifi3, +#endif .txrx_vdev_register = dp_vdev_register_wifi3, .txrx_soc_detach = dp_soc_detach_wifi3, .txrx_soc_deinit = dp_soc_deinit_wifi3, diff --git a/dp/wifi3.0/dp_peer.c b/dp/wifi3.0/dp_peer.c index 1819cf123a..51be7772ad 100644 --- a/dp/wifi3.0/dp_peer.c +++ b/dp/wifi3.0/dp_peer.c @@ -2805,6 +2805,26 @@ dp_rx_mlo_peer_map_handler(struct dp_soc *soc, uint16_t peer_id, } #endif +#ifdef DP_RX_UDP_OVER_PEER_ROAM +void dp_rx_reset_roaming_peer(struct dp_soc *soc, uint8_t vdev_id, + uint8_t *peer_mac_addr) +{ + struct dp_vdev *vdev = NULL; + + vdev = dp_vdev_get_ref_by_id(soc, vdev_id, DP_MOD_ID_HTT); + if (vdev) { + if (qdf_mem_cmp(vdev->roaming_peer_mac.raw, peer_mac_addr, + QDF_MAC_ADDR_SIZE) == 0) { + vdev->roaming_peer_status = + WLAN_ROAM_PEER_AUTH_STATUS_NONE; + qdf_mem_zero(vdev->roaming_peer_mac.raw, + QDF_MAC_ADDR_SIZE); + } + dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_HTT); + } +} +#endif + /** * dp_rx_peer_map_handler() - handle peer map event from firmware * @soc_handle - genereic soc handle @@ -2929,6 +2949,8 @@ dp_rx_peer_map_handler(struct dp_soc *soc, uint16_t peer_id, vdev_id, ast_hash, is_wds); } + dp_rx_reset_roaming_peer(soc, vdev_id, peer_mac_addr); + return err; } diff --git a/dp/wifi3.0/dp_peer.h b/dp/wifi3.0/dp_peer.h index a50c31da18..e612a3e519 100644 --- a/dp/wifi3.0/dp_peer.h +++ b/dp/wifi3.0/dp_peer.h @@ -611,6 +611,27 @@ void dp_rx_peer_unmap_handler(struct dp_soc *soc, uint16_t peer_id, uint8_t vdev_id, uint8_t *peer_mac_addr, uint8_t is_wds, uint32_t free_wds_count); +#ifdef DP_RX_UDP_OVER_PEER_ROAM +/** + * dp_rx_reset_roaming_peer() - Reset the roamed peer in vdev + * @soc - dp soc pointer + * @vdev_id - vdev id + * @peer_mac_addr - mac address of the peer + * + * This function resets the roamed peer auth status and mac address + * after peer map indication of same peer is received from firmware. + * + * Return: None + */ +void dp_rx_reset_roaming_peer(struct dp_soc *soc, uint8_t vdev_id, + uint8_t *peer_mac_addr); +#else +static inline void dp_rx_reset_roaming_peer(struct dp_soc *soc, uint8_t vdev_id, + uint8_t *peer_mac_addr) +{ +} +#endif + #ifdef WLAN_FEATURE_11BE_MLO /** * dp_rx_mlo_peer_map_handler() - handle MLO peer map event from firmware diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index 65492114f3..61d0ee1c75 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/dp/wifi3.0/dp_rx.c @@ -2269,6 +2269,49 @@ dp_rx_desc_nbuf_len_sanity_check(struct dp_soc *soc, uint32_t pkt_len) { } #endif #ifdef DP_RX_PKT_NO_PEER_DELIVER +#ifdef DP_RX_UDP_OVER_PEER_ROAM +/** + * dp_rx_is_udp_allowed_over_roam_peer() - check if udp data received + * during roaming + * @vdev: dp_vdev pointer + * @rx_tlv_hdr: rx tlv header + * @nbuf: pkt skb pointer + * + * This function will check if rx udp data is received from authorised + * roamed peer before peer map indication is received from FW after + * roaming. This is needed for VoIP scenarios in which packet loss + * expected during roaming is minimal. + * + * Return: bool + */ +static bool dp_rx_is_udp_allowed_over_roam_peer(struct dp_vdev *vdev, + uint8_t *rx_tlv_hdr, + qdf_nbuf_t nbuf) +{ + char *hdr_desc; + struct ieee80211_frame *wh = NULL; + + hdr_desc = hal_rx_desc_get_80211_hdr(vdev->pdev->soc->hal_soc, + rx_tlv_hdr); + wh = (struct ieee80211_frame *)hdr_desc; + + if (vdev->roaming_peer_status == + WLAN_ROAM_PEER_AUTH_STATUS_AUTHENTICATED && + !qdf_mem_cmp(vdev->roaming_peer_mac.raw, wh->i_addr2, + QDF_MAC_ADDR_SIZE) && (qdf_nbuf_is_ipv4_udp_pkt(nbuf) || + qdf_nbuf_is_ipv6_udp_pkt(nbuf))) + return true; + + return false; +} +#else +static bool dp_rx_is_udp_allowed_over_roam_peer(struct dp_vdev *vdev, + uint8_t *rx_tlv_hdr, + qdf_nbuf_t nbuf) +{ + return false; +} +#endif /** * dp_rx_deliver_to_stack_no_peer() - try deliver rx data even if * no corresbonding peer found @@ -2316,7 +2359,8 @@ void dp_rx_deliver_to_stack_no_peer(struct dp_soc *soc, qdf_nbuf_t nbuf) qdf_nbuf_set_pktlen(nbuf, pkt_len); qdf_nbuf_pull_head(nbuf, soc->rx_pkt_tlv_size + l2_hdr_offset); - if (dp_rx_is_special_frame(nbuf, frame_mask)) { + if (dp_rx_is_special_frame(nbuf, frame_mask) || + dp_rx_is_udp_allowed_over_roam_peer(vdev, rx_tlv_hdr, nbuf)) { qdf_nbuf_set_exc_frame(nbuf, 1); if (QDF_STATUS_SUCCESS != vdev->osif_rx(vdev->osif_vdev, nbuf)) diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index c713e79f50..dee3b0ef13 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -2918,6 +2918,15 @@ struct dp_pdev { struct dp_peer; +#ifdef DP_RX_UDP_OVER_PEER_ROAM +#define WLAN_ROAM_PEER_AUTH_STATUS_NONE 0x0 +/** + * This macro is equivalent to macro ROAM_AUTH_STATUS_AUTHENTICATED used + * in connection mgr + */ +#define WLAN_ROAM_PEER_AUTH_STATUS_AUTHENTICATED 0x2 +#endif + /* VDEV structure for data path state */ struct dp_vdev { /* OS device abstraction */ @@ -3215,6 +3224,10 @@ struct dp_vdev { /* hw tx delay stats enable */ uint8_t hw_tx_delay_stats_enabled; #endif +#ifdef DP_RX_UDP_OVER_PEER_ROAM + uint32_t roaming_peer_status; + union dp_align_mac_addr roaming_peer_mac; +#endif }; enum {