Quellcode durchsuchen

qcacld-3.0: Handle MLO link switch case for FISA flow flush to stack

When FISA aggregated flow is flushed to n/w stack, there
is a vdev_id comparison between the flow and the head skb.
If this vdev_id check fails, the packets are dropped.

In case of MLO link switch during the FISA flow aggregation,
the packets might be received on different vdev (belonging to
the same MLD). Hence the vdev_id comparison will fail when
there is a MLO link switch in between the flow aggregation.

Since both the vdevs belong to the same MLD, add a MLD addr
validation to mitigate the above mentioned issue.

Change-Id: I0328dccff3f08da87f55758b469d773b9ea1169b
CRs-Fixed: 3568987
Rakesh Pillai vor 1 Jahr
Ursprung
Commit
d03053c1c7

+ 2 - 0
components/dp/core/inc/wlan_dp_priv.h

@@ -432,6 +432,7 @@ struct fisa_pkt_hist {
  * @flow_init_ts: FLOW init timestamp
  * @last_accessed_ts: Timestamp when the flow was last accessed
  * @pkt_hist: FISA aggreagtion packets history
+ * @same_mld_vdev_mismatch: Packets flushed after vdev_mismatch on same MLD
  */
 struct dp_fisa_rx_sw_ft {
 	void *hw_fse;
@@ -478,6 +479,7 @@ struct dp_fisa_rx_sw_ft {
 #ifdef WLAN_SUPPORT_RX_FISA_HIST
 	struct fisa_pkt_hist pkt_hist;
 #endif
+	uint64_t same_mld_vdev_mismatch;
 };
 
 #define DP_RX_GET_SW_FT_ENTRY_SIZE sizeof(struct dp_fisa_rx_sw_ft)

+ 84 - 9
components/dp/core/src/wlan_dp_fisa_rx.c

@@ -1425,6 +1425,84 @@ static qdf_nbuf_t dp_fisa_rx_linear_skb(struct dp_vdev *vdev,
 	return NULL;
 }
 
+#ifdef WLAN_FEATURE_11BE
+static inline struct dp_vdev *
+dp_fisa_rx_get_flow_flush_vdev_ref(ol_txrx_soc_handle cdp_soc,
+				   struct dp_fisa_rx_sw_ft *fisa_flow)
+{
+	struct dp_vdev *fisa_flow_head_skb_vdev;
+	uint8_t vdev_id;
+
+	vdev_id = QDF_NBUF_CB_RX_VDEV_ID(fisa_flow->head_skb);
+
+get_new_vdev_ref:
+	fisa_flow_head_skb_vdev = dp_vdev_get_ref_by_id(
+						cdp_soc_t_to_dp_soc(cdp_soc),
+						vdev_id, DP_MOD_ID_RX);
+	if (qdf_unlikely(!fisa_flow_head_skb_vdev)) {
+		qdf_nbuf_free(fisa_flow->head_skb);
+		goto out;
+	}
+
+	if (qdf_unlikely(fisa_flow_head_skb_vdev != fisa_flow->vdev)) {
+		/*
+		 * vdev_id may mismatch in case of MLO link switch.
+		 * Check if the vdevs belong to same MLD,
+		 * if yes, then submit the flow else drop the packets.
+		 */
+		if (qdf_unlikely(qdf_mem_cmp(
+				fisa_flow->vdev->mld_mac_addr.raw,
+				fisa_flow_head_skb_vdev->mld_mac_addr.raw,
+				QDF_MAC_ADDR_SIZE) != 0)) {
+			qdf_nbuf_free(fisa_flow->head_skb);
+			goto out;
+		} else {
+			fisa_flow->same_mld_vdev_mismatch++;
+			/* Continue with aggregation */
+
+			/* Release ref to old vdev */
+			dp_vdev_unref_delete(cdp_soc_t_to_dp_soc(cdp_soc),
+					     fisa_flow_head_skb_vdev,
+					     DP_MOD_ID_RX);
+			/*
+			 * Update vdev_id and let it loop to find this
+			 * vdev by ref.
+			 */
+			vdev_id = fisa_flow->vdev->vdev_id;
+			goto get_new_vdev_ref;
+		}
+	}
+
+out:
+	return fisa_flow_head_skb_vdev;
+}
+#else
+static inline struct dp_vdev *
+dp_fisa_rx_get_flow_flush_vdev_ref(ol_txrx_soc_handle cdp_soc,
+				   struct dp_fisa_rx_sw_ft *fisa_flow)
+{
+	struct dp_vdev *fisa_flow_head_skb_vdev;
+
+	fisa_flow_head_skb_vdev = dp_vdev_get_ref_by_id(
+				cdp_soc_t_to_dp_soc(cdp_soc),
+				QDF_NBUF_CB_RX_VDEV_ID(fisa_flow->head_skb),
+				DP_MOD_ID_RX);
+	if (qdf_unlikely(!fisa_flow_head_skb_vdev ||
+			 (fisa_flow_head_skb_vdev != fisa_flow->vdev))) {
+		qdf_nbuf_free(fisa_flow->head_skb);
+		goto out;
+	}
+
+	return fisa_flow_head_skb_vdev;
+
+out:
+	dp_vdev_unref_delete(cdp_soc_t_to_dp_soc(cdp_soc),
+			     fisa_flow_head_skb_vdev,
+			     DP_MOD_ID_RX);
+	return NULL;
+}
+#endif
+
 /**
  * dp_rx_fisa_flush_udp_flow() - Flush all aggregated nbuf of the udp flow
  * @vdev: handle to dp_vdev
@@ -1519,15 +1597,10 @@ dp_rx_fisa_flush_udp_flow(struct dp_vdev *vdev,
 
 	hex_dump_skb_data(fisa_flow->head_skb, false);
 
-	fisa_flow_vdev = dp_vdev_get_ref_by_id(
-				cdp_soc_t_to_dp_soc(cdp_soc),
-				QDF_NBUF_CB_RX_VDEV_ID(fisa_flow->head_skb),
-				DP_MOD_ID_RX);
-	if (qdf_unlikely(!fisa_flow_vdev ||
-			 (fisa_flow_vdev != fisa_flow->vdev))) {
-		qdf_nbuf_free(fisa_flow->head_skb);
-		goto out;
-	}
+	fisa_flow_vdev = dp_fisa_rx_get_flow_flush_vdev_ref(cdp_soc, fisa_flow);
+	if (!fisa_flow_vdev)
+		goto vdev_ref_get_fail;
+
 	dp_fisa_debug("fisa_flow->curr_aggr %d", fisa_flow->cur_aggr);
 	linear_skb = dp_fisa_rx_linear_skb(vdev, fisa_flow->head_skb, 24000);
 	if (linear_skb) {
@@ -1559,6 +1632,8 @@ out:
 		dp_vdev_unref_delete(cdp_soc_t_to_dp_soc(cdp_soc),
 				     fisa_flow_vdev,
 				     DP_MOD_ID_RX);
+
+vdev_ref_get_fail:
 	fisa_flow->head_skb = NULL;
 	fisa_flow->last_skb = NULL;
 

+ 3 - 2
components/dp/core/src/wlan_dp_rx_fst.c

@@ -145,7 +145,7 @@ static QDF_STATUS dp_rx_dump_fisa_stats(struct wlan_dp_psoc_context *dp_ctx)
 				 tuple_str,
 				 sizeof(tuple_str));
 
-		dp_info("Flow[%d][%s][%s] ring %d msdu-aggr %d flushes %d bytes-agg %llu avg-bytes-aggr %llu",
+		dp_info("Flow[%d][%s][%s] ring %d msdu-aggr %d flushes %d bytes-agg %llu avg-bytes-aggr %llu same_mld_vdev_mismatch %llu",
 			sw_ft_entry->flow_id,
 			sw_ft_entry->is_flow_udp ? "udp" : "tcp",
 			tuple_str,
@@ -154,7 +154,8 @@ static QDF_STATUS dp_rx_dump_fisa_stats(struct wlan_dp_psoc_context *dp_ctx)
 			sw_ft_entry->flush_count,
 			sw_ft_entry->bytes_aggregated,
 			qdf_do_div(sw_ft_entry->bytes_aggregated,
-				   sw_ft_entry->flush_count));
+				   sw_ft_entry->flush_count),
+			sw_ft_entry->same_mld_vdev_mismatch);
 	}
 	return QDF_STATUS_SUCCESS;
 }