Эх сурвалжийг харах

qcacld-3.0: Implement ACL API for EasyMesh

Add API to set/get ACL policy. Add API to add/delete ACL MAC.
Add API to kickout sta according to MAC.

Change-Id: I329501d4f0c929b6e7933a8e484b5d8493dbbabe
CRs-Fixed: 3042927
bings 3 жил өмнө
parent
commit
9aad58a07d

+ 4 - 10
core/hdd/src/wlan_hdd_cfg80211.c

@@ -20230,17 +20230,11 @@ fn_end:
 }
 
 #if defined(USE_CFG80211_DEL_STA_V2)
-/**
- * wlan_hdd_del_station() - delete station wrapper
- * @adapter: pointer to the hdd adapter
- *
- * Return: Errno
- */
-int wlan_hdd_del_station(struct hdd_adapter *adapter)
+int wlan_hdd_del_station(struct hdd_adapter *adapter, const uint8_t *mac)
 {
 	struct station_del_parameters del_sta;
 
-	del_sta.mac = NULL;
+	del_sta.mac = mac;
 	del_sta.subtype = IEEE80211_STYPE_DEAUTH >> 4;
 	del_sta.reason_code = WLAN_REASON_DEAUTH_LEAVING;
 
@@ -20248,10 +20242,10 @@ int wlan_hdd_del_station(struct hdd_adapter *adapter)
 					     adapter->dev, &del_sta);
 }
 #else
-int wlan_hdd_del_station(struct hdd_adapter *adapter)
+int wlan_hdd_del_station(struct hdd_adapter *adapter, const uint8_t *mac)
 {
 	return wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy,
-					     adapter->dev, NULL);
+					     adapter->dev, mac);
 }
 #endif
 

+ 9 - 1
core/hdd/src/wlan_hdd_cfg80211.h

@@ -440,7 +440,15 @@ void hdd_select_cbmode(struct hdd_adapter *adapter, qdf_freq_t oper_freq,
  * Return: true or false based on findings
  */
 bool wlan_hdd_is_ap_supports_immediate_power_save(uint8_t *ies, int length);
-int wlan_hdd_del_station(struct hdd_adapter *adapter);
+
+/**
+ * wlan_hdd_del_station() - delete station wrapper
+ * @adapter: pointer to the hdd adapter
+ * @mac: pointer to mac addr
+ *
+ * Return: Errno
+ */
+int wlan_hdd_del_station(struct hdd_adapter *adapter, const uint8_t *mac);
 
 #if defined(USE_CFG80211_DEL_STA_V2)
 int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,

+ 1 - 1
core/hdd/src/wlan_hdd_hostapd.c

@@ -6211,7 +6211,7 @@ static int __wlan_hdd_cfg80211_stop_ap(struct wiphy *wiphy,
 	hdd_abort_ongoing_sta_connection(hdd_ctx);
 
 	if (adapter->device_mode == QDF_SAP_MODE) {
-		wlan_hdd_del_station(adapter);
+		wlan_hdd_del_station(adapter, NULL);
 		mac_handle = hdd_ctx->mac_handle;
 		status = wlan_hdd_flush_pmksa_cache(adapter);
 		if (QDF_IS_STATUS_ERROR(status))

+ 3 - 3
core/hdd/src/wlan_hdd_main.c

@@ -7719,7 +7719,7 @@ QDF_STATUS hdd_stop_adapter_ext(struct hdd_context *hdd_ctx,
 		hdd_abort_ongoing_sta_connection(hdd_ctx);
 		/* Diassociate with all the peers before stop ap post */
 		if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) {
-			if (wlan_hdd_del_station(adapter))
+			if (wlan_hdd_del_station(adapter, NULL))
 				hdd_sap_indicate_disconnect_for_sta(adapter);
 		}
 		status = wlan_hdd_flush_pmksa_cache(adapter);
@@ -16051,7 +16051,7 @@ void wlan_hdd_stop_sap(struct hdd_adapter *ap_adapter)
 
 	mutex_lock(&hdd_ctx->sap_lock);
 	if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
-		wlan_hdd_del_station(ap_adapter);
+		wlan_hdd_del_station(ap_adapter, NULL);
 		hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
 		hdd_debug("Now doing SAP STOPBSS");
 		qdf_event_reset(&hostapd_state->qdf_stop_bss_event);
@@ -18511,7 +18511,7 @@ void hdd_restart_sap(struct hdd_adapter *ap_adapter)
 
 	mutex_lock(&hdd_ctx->sap_lock);
 	if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
-		wlan_hdd_del_station(ap_adapter);
+		wlan_hdd_del_station(ap_adapter, NULL);
 		hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
 		qdf_event_reset(&hostapd_state->qdf_stop_bss_event);
 		if (QDF_STATUS_SUCCESS == wlansap_stop_bss(sap_ctx)) {

+ 246 - 0
core/hdd/src/wlan_hdd_son.c

@@ -862,11 +862,252 @@ static enum ieee80211_phymode hdd_son_get_phymode(struct wlan_objmgr_vdev *vdev)
 		hdd_err("null hdd ctx");
 		return IEEE80211_MODE_AUTO;
 	}
+
 	phymode = sme_get_phy_mode(hdd_ctx->mac_handle);
 
 	return hdd_phymode_chwidth_freq_to_son_phymode(phymode, chwidth, freq);
 }
 
+/**
+ * hdd_son_set_acl_policy() - set son acl policy
+ * @vdev: vdev
+ * @son_acl_policy: enum ieee80211_acl_cmd
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS hdd_son_set_acl_policy(struct wlan_objmgr_vdev *vdev,
+					 ieee80211_acl_cmd son_acl_policy)
+{
+	struct hdd_adapter *adapter;
+	QDF_STATUS status = QDF_STATUS_E_INVAL;
+
+	if (!vdev) {
+		hdd_err("null vdev");
+		return status;
+	}
+	adapter = wlan_hdd_get_adapter_from_objmgr(vdev);
+	if (!adapter) {
+		hdd_err("null adapter");
+		return status;
+	}
+
+	switch (son_acl_policy) {
+	case IEEE80211_MACCMD_POLICY_OPEN:
+		status = wlansap_set_acl_mode(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
+					      eSAP_ALLOW_ALL);
+		break;
+	case IEEE80211_MACCMD_POLICY_ALLOW:
+		status = wlansap_set_acl_mode(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
+					      eSAP_DENY_UNLESS_ACCEPTED);
+		break;
+	case IEEE80211_MACCMD_POLICY_DENY:
+		status = wlansap_set_acl_mode(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
+					      eSAP_ACCEPT_UNLESS_DENIED);
+		break;
+	case IEEE80211_MACCMD_FLUSH:
+	case IEEE80211_MACCMD_DETACH:
+		status = wlansap_clear_acl(WLAN_HDD_GET_SAP_CTX_PTR(adapter));
+		break;
+	default:
+		hdd_err("invalid son acl policy %d", son_acl_policy);
+		break;
+	}
+
+	return status;
+}
+
+/**
+ * hdd_acl_policy_to_son_acl_policy() - convert acl policy to son acl policy
+ * @acl_policy: acl policy
+ *
+ * Return: son acl policy. enum ieee80211_acl_cmd
+ */
+static ieee80211_acl_cmd hdd_acl_policy_to_son_acl_policy(
+						eSapMacAddrACL acl_policy)
+{
+	ieee80211_acl_cmd son_acl_policy = IEEE80211_MACCMD_DETACH;
+
+	switch (acl_policy) {
+	case eSAP_ACCEPT_UNLESS_DENIED:
+		son_acl_policy = IEEE80211_MACCMD_POLICY_DENY;
+		break;
+	case eSAP_DENY_UNLESS_ACCEPTED:
+		son_acl_policy = IEEE80211_MACCMD_POLICY_ALLOW;
+		break;
+	case eSAP_ALLOW_ALL:
+		son_acl_policy = IEEE80211_MACCMD_POLICY_OPEN;
+		break;
+	default:
+		hdd_err("invalid acl policy %d", acl_policy);
+		break;
+	}
+
+	return son_acl_policy;
+}
+
+/**
+ * hdd_son_get_acl_policy() - get son acl policy
+ * @vdev: vdev
+ *
+ * Return: son acl policy. enum ieee80211_acl_cmd
+ */
+static ieee80211_acl_cmd hdd_son_get_acl_policy(struct wlan_objmgr_vdev *vdev)
+{
+	eSapMacAddrACL acl_policy;
+	struct hdd_adapter *adapter;
+	ieee80211_acl_cmd son_acl_policy = IEEE80211_MACCMD_DETACH;
+
+	if (!vdev) {
+		hdd_err("null vdev");
+		return son_acl_policy;
+	}
+	adapter = wlan_hdd_get_adapter_from_objmgr(vdev);
+	if (!adapter) {
+		hdd_err("null adapter");
+		return son_acl_policy;
+	}
+
+	wlansap_get_acl_mode(WLAN_HDD_GET_SAP_CTX_PTR(adapter), &acl_policy);
+
+	son_acl_policy = hdd_acl_policy_to_son_acl_policy(acl_policy);
+
+	return son_acl_policy;
+}
+
+/**
+ * hdd_son_add_acl_mac() - add mac to access control list(ACL)
+ * @vdev: vdev
+ * @acl_mac: mac address to add
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+static int hdd_son_add_acl_mac(struct wlan_objmgr_vdev *vdev,
+			       struct qdf_mac_addr *acl_mac)
+{
+	eSapACLType list_type;
+	QDF_STATUS qdf_status;
+	eSapMacAddrACL acl_policy;
+	struct hdd_adapter *adapter;
+
+	if (!vdev) {
+		hdd_err("null vdev");
+		return -EINVAL;
+	}
+	if (!acl_mac) {
+		hdd_err("null acl_mac");
+		return -EINVAL;
+	}
+	adapter = wlan_hdd_get_adapter_from_objmgr(vdev);
+	if (!adapter) {
+		hdd_err("null adapter");
+		return -EINVAL;
+	}
+
+	wlansap_get_acl_mode(WLAN_HDD_GET_SAP_CTX_PTR(adapter), &acl_policy);
+
+	if (acl_policy == eSAP_ACCEPT_UNLESS_DENIED) {
+		list_type = eSAP_BLACK_LIST;
+	} else if (acl_policy == eSAP_DENY_UNLESS_ACCEPTED) {
+		list_type = eSAP_WHITE_LIST;
+	} else {
+		hdd_err("Invalid ACL policy %d.", acl_policy);
+		return -EINVAL;
+	}
+	qdf_status = wlansap_modify_acl(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
+					acl_mac->bytes, list_type,
+					ADD_STA_TO_ACL);
+	if (QDF_IS_STATUS_ERROR(qdf_status)) {
+		hdd_err("Modify ACL failed");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+/**
+ * hdd_son_del_acl_mac() - delete mac from acl
+ * @vdev: vdev
+ * @acl_mac: mac to remove
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+static int hdd_son_del_acl_mac(struct wlan_objmgr_vdev *vdev,
+			       struct qdf_mac_addr *acl_mac)
+{
+	eSapACLType list_type;
+	QDF_STATUS qdf_status;
+	eSapMacAddrACL acl_policy;
+	struct hdd_adapter *adapter;
+	struct sap_context *sap_ctx;
+
+	if (!vdev) {
+		hdd_err("null vdev");
+		return -EINVAL;
+	}
+	if (!acl_mac) {
+		hdd_err("null acl_mac");
+		return -EINVAL;
+	}
+	adapter = wlan_hdd_get_adapter_from_objmgr(vdev);
+	if (!adapter) {
+		hdd_err("null adapter");
+		return -EINVAL;
+	}
+
+	sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(adapter);
+	if (!sap_ctx) {
+		hdd_err("null sap ctx");
+		return -EINVAL;
+	}
+
+	wlansap_get_acl_mode(sap_ctx, &acl_policy);
+
+	if (acl_policy == eSAP_ACCEPT_UNLESS_DENIED) {
+		list_type = eSAP_BLACK_LIST;
+	} else if (acl_policy == eSAP_DENY_UNLESS_ACCEPTED) {
+		list_type = eSAP_WHITE_LIST;
+	} else {
+		hdd_err("Invalid ACL policy %d.", acl_policy);
+		return -EINVAL;
+	}
+	qdf_status = wlansap_modify_acl(sap_ctx, acl_mac->bytes, list_type,
+					DELETE_STA_FROM_ACL);
+	if (QDF_IS_STATUS_ERROR(qdf_status)) {
+		hdd_err("Modify ACL failed");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+/**
+ * hdd_son_kickout_mac() - kickout sta with given mac
+ * @vdev: vdev
+ * @acl_mac: sta mac to kickout
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+static int hdd_son_kickout_mac(struct wlan_objmgr_vdev *vdev,
+			       struct qdf_mac_addr *mac)
+{
+	struct hdd_adapter *adapter;
+
+	if (!vdev) {
+		hdd_err("null vdev");
+		return -EINVAL;
+	}
+	adapter = wlan_hdd_get_adapter_from_objmgr(vdev);
+	if (!adapter) {
+		hdd_err("null adapter");
+		return -EINVAL;
+	}
+
+	if (mac)
+		return wlan_hdd_del_station(adapter, mac->bytes);
+	else
+		return wlan_hdd_del_station(adapter, NULL);
+}
+
 static uint8_t hdd_son_get_rx_nss(struct wlan_objmgr_vdev *vdev)
 {
 	struct hdd_adapter *adapter = wlan_hdd_get_adapter_from_objmgr(vdev);
@@ -891,6 +1132,11 @@ void hdd_son_register_callbacks(struct hdd_context *hdd_ctx)
 	cb_obj.os_if_set_bandwidth = hdd_son_set_bandwidth;
 	cb_obj.os_if_get_bandwidth = hdd_son_get_bandwidth;
 	cb_obj.os_if_set_chan = hdd_son_set_chan;
+	cb_obj.os_if_set_acl_policy = hdd_son_set_acl_policy;
+	cb_obj.os_if_get_acl_policy = hdd_son_get_acl_policy;
+	cb_obj.os_if_add_acl_mac = hdd_son_add_acl_mac;
+	cb_obj.os_if_del_acl_mac = hdd_son_del_acl_mac;
+	cb_obj.os_if_kickout_mac = hdd_son_kickout_mac;
 	cb_obj.os_if_set_country_code = hdd_son_set_country;
 	cb_obj.os_if_set_candidate_freq = hdd_son_set_candidate_freq;
 	cb_obj.os_if_get_candidate_freq = hdd_son_get_candidate_freq;

+ 63 - 0
os_if/son/inc/os_if_son.h

@@ -46,6 +46,11 @@
  * @os_if_set_phymode: set phy mode
  * @os_if_get_phymode: get phy mode
  * @os_if_get_rx_nss: Gets number of RX spatial streams
+ * @os_if_set_acl_policy: set acl policy
+ * @os_if_get_acl_policy: get acl policy
+ * @os_if_add_acl_mac: add mac to acl
+ * @os_if_del_acl_mac: del mac from acl
+ * @os_if_kickout_mac: kickout sta with given mac
  */
 struct son_callbacks {
 	uint32_t (*os_if_is_acs_in_progress)(struct wlan_objmgr_vdev *vdev);
@@ -70,6 +75,16 @@ struct son_callbacks {
 	enum ieee80211_phymode (*os_if_get_phymode)(
 					struct wlan_objmgr_vdev *vdev);
 	uint8_t (*os_if_get_rx_nss)(struct wlan_objmgr_vdev *vdev);
+	QDF_STATUS (*os_if_set_acl_policy)(struct wlan_objmgr_vdev *vdev,
+					   ieee80211_acl_cmd son_acl_policy);
+	ieee80211_acl_cmd (*os_if_get_acl_policy)(
+						struct wlan_objmgr_vdev *vdev);
+	int (*os_if_add_acl_mac)(struct wlan_objmgr_vdev *vdev,
+				 struct qdf_mac_addr *acl_mac);
+	int (*os_if_del_acl_mac)(struct wlan_objmgr_vdev *vdev,
+				 struct qdf_mac_addr *acl_mac);
+	int (*os_if_kickout_mac)(struct wlan_objmgr_vdev *vdev,
+				 struct qdf_mac_addr *acl_mac);
 };
 
 /**
@@ -370,4 +385,52 @@ QDF_STATUS os_if_son_cfg80211_reply(qdf_nbuf_t sk_buf);
  */
 bool os_if_son_vdev_is_wds(struct wlan_objmgr_vdev *vdev);
 
+/*
+ * os_if_son_set_acl_policy() - set acl policy
+ * @vdev: vdev
+ * @son_acl_policy: son acl policy. enum ieee80211_acl_cmd
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS os_if_son_set_acl_policy(struct wlan_objmgr_vdev *vdev,
+				    ieee80211_acl_cmd son_acl_policy);
+
+/**
+ * os_if_son_get_acl_policy() - get acl policy
+ * @vdev: vdev
+ *
+ * Return: acl policy. enum ieee80211_acl_cmd
+ */
+ieee80211_acl_cmd os_if_son_get_acl_policy(struct wlan_objmgr_vdev *vdev);
+
+/**
+ * os_if_son_add_acl_mac() - add mac to acl
+ * @vdev: vdev
+ * @acl_mac: mac to add
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+int os_if_son_add_acl_mac(struct wlan_objmgr_vdev *vdev,
+			  struct qdf_mac_addr *acl_mac);
+
+/**
+ * os_if_son_del_acl_mac() - del mac from acl
+ * @vdev: vdev
+ * @acl_mac: mac to del
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+int os_if_son_del_acl_mac(struct wlan_objmgr_vdev *vdev,
+			  struct qdf_mac_addr *acl_mac);
+
+/**
+ * os_if_son_kickout_mac() - kickout sta with given mac
+ * @vdev: vdev
+ * @acl_mac: sta mac to kickout
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+int os_if_son_kickout_mac(struct wlan_objmgr_vdev *vdev,
+			  struct qdf_mac_addr *mac);
+
 #endif

+ 83 - 0
os_if/son/src/os_if_son.c

@@ -625,6 +625,89 @@ qdf_freq_t os_if_son_get_candidate_freq(struct wlan_objmgr_vdev *vdev)
 }
 qdf_export_symbol(os_if_son_get_candidate_freq);
 
+QDF_STATUS os_if_son_set_acl_policy(struct wlan_objmgr_vdev *vdev,
+				    ieee80211_acl_cmd son_acl_policy)
+{
+	QDF_STATUS ret;
+
+	if (!vdev) {
+		osif_err("null vdev");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	ret = g_son_os_if_cb.os_if_set_acl_policy(vdev, son_acl_policy);
+	osif_debug("set acl policy %d status %d", son_acl_policy, ret);
+
+	return ret;
+}
+qdf_export_symbol(os_if_son_set_acl_policy);
+
+ieee80211_acl_cmd os_if_son_get_acl_policy(struct wlan_objmgr_vdev *vdev)
+{
+	ieee80211_acl_cmd son_acl_policy;
+
+	if (!vdev) {
+		osif_err("null vdev");
+		return IEEE80211_MACCMD_DETACH;
+	}
+	son_acl_policy = g_son_os_if_cb.os_if_get_acl_policy(vdev);
+	osif_debug("get acl policy %d", son_acl_policy);
+
+	return son_acl_policy;
+}
+qdf_export_symbol(os_if_son_get_acl_policy);
+
+int os_if_son_add_acl_mac(struct wlan_objmgr_vdev *vdev,
+			  struct qdf_mac_addr *acl_mac)
+{
+	int ret;
+
+	if (!vdev) {
+		osif_err("null vdev");
+		return -EINVAL;
+	}
+	ret = g_son_os_if_cb.os_if_add_acl_mac(vdev, acl_mac);
+	osif_debug("add_acl_mac " QDF_MAC_ADDR_FMT " ret %d",
+		   QDF_MAC_ADDR_REF(acl_mac->bytes), ret);
+
+	return ret;
+}
+qdf_export_symbol(os_if_son_add_acl_mac);
+
+int os_if_son_del_acl_mac(struct wlan_objmgr_vdev *vdev,
+			  struct qdf_mac_addr *acl_mac)
+{
+	int ret;
+
+	if (!vdev) {
+		osif_err("null vdev");
+		return -EINVAL;
+	}
+	ret = g_son_os_if_cb.os_if_del_acl_mac(vdev, acl_mac);
+	osif_debug("del_acl_mac " QDF_MAC_ADDR_FMT " ret %d",
+		   QDF_MAC_ADDR_REF(acl_mac->bytes), ret);
+
+	return ret;
+}
+qdf_export_symbol(os_if_son_del_acl_mac);
+
+int os_if_son_kickout_mac(struct wlan_objmgr_vdev *vdev,
+			  struct qdf_mac_addr *mac)
+{
+	int ret;
+
+	if (!vdev) {
+		osif_err("null vdev");
+		return -EINVAL;
+	}
+	ret = g_son_os_if_cb.os_if_kickout_mac(vdev, mac);
+	osif_debug("kickout mac " QDF_MAC_ADDR_FMT " ret %d",
+		   QDF_MAC_ADDR_REF(mac->bytes), ret);
+
+	return ret;
+}
+qdf_export_symbol(os_if_son_kickout_mac);
+
 int os_if_son_set_phymode(struct wlan_objmgr_vdev *vdev,
 			  enum ieee80211_phymode mode)
 {