Procházet zdrojové kódy

qcacld-3.0: Add support for multicast traffic over NDI

Add support for passing multicast traffic over nan data interface.

Integration from qcacld-2.0 to qcacld-3.0.

CRs-Fixed: 1046519
Change-Id: Iaf012c08e6b5a7a6327b84b12c06ab27963a704c
Ravi Joshi před 8 roky
rodič
revize
24477b7c2b
2 změnil soubory, kde provedl 90 přidání a 71 odebrání
  1. 26 20
      core/hdd/src/wlan_hdd_power.c
  2. 64 51
      core/hdd/src/wlan_hdd_tx_rx.c

+ 26 - 20
core/hdd/src/wlan_hdd_power.c

@@ -924,11 +924,12 @@ void wlan_hdd_set_mc_addr_list(hdd_adapter_t *pAdapter, uint8_t set)
 	tpSirRcvFltMcAddrList pMulticastAddrs = NULL;
 	tHalHandle hHal = NULL;
 	hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
+	hdd_station_ctx_t *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
 
-	if (NULL == pHddCtx) {
-		hdd_err("HDD CTX is NULL");
+	ENTER();
+
+	if (wlan_hdd_validate_context(pHddCtx))
 		return;
-	}
 
 	hHal = pHddCtx->hHal;
 
@@ -937,8 +938,12 @@ void wlan_hdd_set_mc_addr_list(hdd_adapter_t *pAdapter, uint8_t set)
 		return;
 	}
 
-	/* Check if INI is enabled or not, other wise just return
-	 */
+	if (!sta_ctx) {
+		hdd_err("sta_ctx is NULL");
+		return;
+	}
+
+	/* Check if INI is enabled or not, other wise just return */
 	if (!pHddCtx->config->fEnableMCAddrList) {
 		hdd_notice("gMCAddrListEnable is not enabled in INI");
 		return;
@@ -952,23 +957,24 @@ void wlan_hdd_set_mc_addr_list(hdd_adapter_t *pAdapter, uint8_t set)
 	pMulticastAddrs->action = set;
 
 	if (set) {
-		/* Following pre-conditions should be satisfied before we
+		/*
+		 * Following pre-conditions should be satisfied before we
 		 * configure the MC address list.
 		 */
-		if (((pAdapter->device_mode == QDF_STA_MODE)
-		     || (pAdapter->device_mode == QDF_P2P_CLIENT_MODE))
-		    && pAdapter->mc_addr_list.mc_cnt
-		    && (eConnectionState_Associated ==
-			(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->
-			conn_info.connState)) {
+		if (pAdapter->mc_addr_list.mc_cnt &&
+				(((pAdapter->device_mode == QDF_STA_MODE ||
+				pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
+				hdd_conn_is_connected(sta_ctx)) ||
+				(WLAN_HDD_IS_NDI(pAdapter) &&
+				WLAN_HDD_IS_NDI_CONNECTED(pAdapter)))) {
+
 			pMulticastAddrs->ulMulticastAddrCnt =
 				pAdapter->mc_addr_list.mc_cnt;
-			for (i = 0; i < pAdapter->mc_addr_list.mc_cnt;
-			     i++) {
+
+			for (i = 0; i < pAdapter->mc_addr_list.mc_cnt; i++) {
 				memcpy(pMulticastAddrs->multicastAddr[i].bytes,
 				       pAdapter->mc_addr_list.addr[i],
-				       sizeof(pAdapter->mc_addr_list.
-					      addr[i]));
+				       sizeof(pAdapter->mc_addr_list.addr[i]));
 				hdd_info("%s multicast filter: addr ="
 				       MAC_ADDRESS_STR,
 				       set ? "setting" : "clearing",
@@ -984,12 +990,10 @@ void wlan_hdd_set_mc_addr_list(hdd_adapter_t *pAdapter, uint8_t set)
 		if (pAdapter->mc_addr_list.isFilterApplied) {
 			pMulticastAddrs->ulMulticastAddrCnt =
 				pAdapter->mc_addr_list.mc_cnt;
-			for (i = 0; i < pAdapter->mc_addr_list.mc_cnt;
-			     i++) {
+			for (i = 0; i < pAdapter->mc_addr_list.mc_cnt; i++) {
 				memcpy(pMulticastAddrs->multicastAddr[i].bytes,
 				       pAdapter->mc_addr_list.addr[i],
-				       sizeof(pAdapter->mc_addr_list.
-					      addr[i]));
+				       sizeof(pAdapter->mc_addr_list.addr[i]));
 			}
 			sme_8023_multicast_list(hHal, pAdapter->sessionId,
 						pMulticastAddrs);
@@ -1003,6 +1007,8 @@ void wlan_hdd_set_mc_addr_list(hdd_adapter_t *pAdapter, uint8_t set)
 
 	pAdapter->mc_addr_list.isFilterApplied = set ? true : false;
 	qdf_mem_free(pMulticastAddrs);
+
+	EXIT();
 	return;
 }
 #endif

+ 64 - 51
core/hdd/src/wlan_hdd_tx_rx.c

@@ -297,6 +297,55 @@ static bool wlan_hdd_is_eapol_or_wai(struct sk_buff *skb)
 	return false;
 }
 
+/**
+ * hdd_get_transmit_sta_id() - function to retrieve station id to be used for
+ * sending traffic towards a particular destination address. The destination
+ * address can be unicast, multicast or broadcast
+ *
+ * @adapter: Handle to adapter context
+ * @dst_addr: Destination address
+ * @station_id: station id
+ *
+ * Returns: None
+ */
+static void hdd_get_transmit_sta_id(hdd_adapter_t *adapter,
+			struct qdf_mac_addr *dst_addr, uint8_t *station_id)
+{
+	bool mcbc_addr = false;
+	hdd_station_ctx_t *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
+
+	hdd_get_peer_sta_id(sta_ctx, dst_addr, station_id);
+	if (*station_id == HDD_WLAN_INVALID_STA_ID) {
+		if (qdf_is_macaddr_broadcast(dst_addr) ||
+				qdf_is_macaddr_group(dst_addr)) {
+			hdd_info("Received MC/BC packet for transmission");
+			mcbc_addr = true;
+		} else {
+			hdd_err("UC frame with invalid destination address");
+		}
+	}
+
+	if (adapter->device_mode == QDF_IBSS_MODE) {
+		/*
+		 * This check is necessary to make sure station id is not
+		 * overwritten for UC traffic in IBSS mode
+		 */
+		if (mcbc_addr)
+			*station_id = sta_ctx->broadcast_ibss_staid;
+	} else if (adapter->device_mode == QDF_NDI_MODE) {
+		/*
+		 * This check is necessary to make sure station id is not
+		 * overwritten for UC traffic in NAN data mode
+		 */
+		if (mcbc_addr)
+			*station_id = NDP_BROADCAST_STAID;
+	} else {
+		/* For the rest, traffic is directed to AP/P2P GO */
+		if (eConnectionState_Associated == sta_ctx->conn_info.connState)
+			*station_id = sta_ctx->conn_info.staId[0];
+	}
+}
+
 /**
  * hdd_hard_start_xmit() - Transmit a frame
  * @skb: pointer to OS packet (sk_buff)
@@ -317,6 +366,7 @@ int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	bool granted;
 	uint8_t STAId = WLAN_MAX_STA_COUNT;
 	hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
+	struct qdf_mac_addr *pDestMacAddress = NULL;
 #ifdef QCA_PKT_PROTO_TRACE
 	uint8_t proto_type = 0;
 #endif /* QCA_PKT_PROTO_TRACE */
@@ -336,55 +386,15 @@ int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		goto drop_pkt;
 	}
 
-	if (QDF_IBSS_MODE == pAdapter->device_mode) {
-		struct qdf_mac_addr *pDestMacAddress =
-					(struct qdf_mac_addr *) skb->data;
+	pDestMacAddress = (struct qdf_mac_addr *)skb->data;
+	STAId = HDD_WLAN_INVALID_STA_ID;
 
-		if (QDF_STATUS_SUCCESS !=
-			hdd_get_peer_sta_id(&pAdapter->sessionCtx.station,
-				pDestMacAddress, &STAId))
-			STAId = HDD_WLAN_INVALID_STA_ID;
-
-		if ((STAId == HDD_WLAN_INVALID_STA_ID) &&
-		    (qdf_is_macaddr_broadcast(pDestMacAddress) ||
-		     qdf_is_macaddr_group(pDestMacAddress))) {
-			STAId = pHddStaCtx->broadcast_ibss_staid;
-			QDF_TRACE(QDF_MODULE_ID_HDD_DATA,
-				  QDF_TRACE_LEVEL_INFO_LOW, "%s: BC/MC packet",
-				  __func__);
-		} else if (STAId == HDD_WLAN_INVALID_STA_ID) {
-			QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_WARN,
-				  "%s: Received Unicast frame with invalid staID",
-				  __func__);
-			goto drop_pkt;
-		}
-	} else if (QDF_NDI_MODE == pAdapter->device_mode) {
-		struct qdf_mac_addr *dest_mac_addr =
-			(struct qdf_mac_addr *)skb->data;
-		if (hdd_get_peer_sta_id(&pAdapter->sessionCtx.station,
-				dest_mac_addr, &STAId) !=
-				QDF_STATUS_SUCCESS) {
-			QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_WARN,
-				FL("Can't find peer: %pM, dropping packet"),
-				dest_mac_addr);
-			++pAdapter->stats.tx_dropped;
-			++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
-			kfree_skb(skb);
-			return NETDEV_TX_OK;
-		}
-	} else {
-		if (QDF_OCB_MODE != pAdapter->device_mode &&
-			eConnectionState_Associated !=
-				pHddStaCtx->conn_info.connState) {
-			QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_INFO,
-				FL("Tx frame in not associated state in %d context"),
-				pAdapter->device_mode);
-			goto drop_pkt;
-		}
-		STAId = pHddStaCtx->conn_info.staId[0];
+	hdd_get_transmit_sta_id(pAdapter, pDestMacAddress, &STAId);
+	if (STAId == HDD_WLAN_INVALID_STA_ID) {
+		hddLog(LOGE, "Invalid station id, transmit operation suspended");
+		goto drop_pkt;
 	}
 
-
 	hdd_get_tx_resource(pAdapter, STAId,
 				WLAN_HDD_TX_FLOW_CONTROL_OS_Q_BLOCK_TIME);
 
@@ -398,7 +408,8 @@ int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 			goto drop_pkt_accounting;
 	}
 
-	/* user priority from IP header, which is already extracted and set from
+	/*
+	 * user priority from IP header, which is already extracted and set from
 	 * select_queue call back function
 	 */
 	up = skb->priority;
@@ -410,7 +421,8 @@ int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 #endif /* HDD_WMM_DEBUG */
 
 	if (HDD_PSB_CHANGED == pAdapter->psbChanged) {
-		/* Function which will determine acquire admittance for a
+		/*
+		 * Function which will determine acquire admittance for a
 		 * WMM AC is required or not based on psb configuration done
 		 * in the framework
 		 */
@@ -435,7 +447,8 @@ int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	if (!granted) {
 		bool isDefaultAc = false;
-		/* ADDTS request for this AC is sent, for now
+		/*
+		 * ADDTS request for this AC is sent, for now
 		 * send this packet through next avaiable lower
 		 * Access category until ADDTS negotiation completes.
 		 */
@@ -518,8 +531,8 @@ int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	}
 
 	/*
-	* If a transmit function is not registered, drop packet
-	*/
+	 * If a transmit function is not registered, drop packet
+	 */
 	if (!pAdapter->tx_fn) {
 		QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO_HIGH,
 			 "%s: TX function not registered by the data path",