Browse Source

qcacmn: Allow rx UDP packets during roaming before peer map is received

In VoIP cases, no or minimal packet drop is expected during
roaming. Currently, data packets are dropped in host if they
are received after roam sync indication from firmware and before
peer map indication is received due to invalid peer.
This change allows rx UDP data packets during roaming before
peer map indication is received from FW if peer's auth_status
received in roam_sync_indication from FW is authorised.

Change-Id: Ic518b7cd0aef48a2b0f8c923a2e20838b07f3d1f
CRs-Fixed: 3168603
Surabhi Vishnoi 3 năm trước cách đây
mục cha
commit
ecaa0f1f6c
7 tập tin đã thay đổi với 157 bổ sung1 xóa
  1. 26 0
      dp/inc/cdp_txrx_cmn.h
  2. 7 0
      dp/inc/cdp_txrx_ops.h
  3. 23 0
      dp/wifi3.0/dp_main.c
  4. 22 0
      dp/wifi3.0/dp_peer.c
  5. 21 0
      dp/wifi3.0/dp_peer.h
  6. 45 1
      dp/wifi3.0/dp_rx.c
  7. 13 0
      dp/wifi3.0/dp_types.h

+ 26 - 0
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

+ 7 - 0
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);

+ 23 - 0
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,

+ 22 - 0
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;
 }
 

+ 21 - 0
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

+ 45 - 1
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))

+ 13 - 0
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 {