Skip to content

Commit

Permalink
drivers: wifi: DMS support
Browse files Browse the repository at this point in the history
Support for Directed multicast service(DMS).

Signed-off-by: Ajay Parida <[email protected]>
  • Loading branch information
ajayparida committed Jun 11, 2024
1 parent 058452a commit decfa9e
Show file tree
Hide file tree
Showing 4 changed files with 197 additions and 4 deletions.
2 changes: 2 additions & 0 deletions drivers/wifi/nrf700x/inc/fmac_main.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ struct nrf_wifi_vif_ctx_zep {
#endif /* CONFIG_NRF700X_DATA_TX */
unsigned long rssi_record_timestamp_us;
signed short rssi;
unsigned char dms_id_map;
unsigned char dms_id_in_progress_map;
#endif /* CONFIG_NRF700X_STA_MODE */
};

Expand Down
6 changes: 6 additions & 0 deletions drivers/wifi/nrf700x/inc/wifi_mgmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,10 @@ int nrf_wifi_filter(const struct device *dev,
struct wifi_filter_info *filter);
#endif /* CONFIG_NRF700X_RAW_DATA_RX || CONFIG_NRF700X_PROMISC_DATA_RX */

int nrf_wifi_req_dms(const struct device *dev,
struct wifi_dms_params *dms_params);

void nrf_wifi_event_proc_dms_zep(void *vif_ctx,
struct nrf_wifi_umac_dms_op *dms_accept_info,
unsigned int event_len);
#endif /* __ZEPHYR_WIFI_MGMT_H__ */
2 changes: 2 additions & 0 deletions drivers/wifi/nrf700x/src/fmac_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,7 @@ static int nrf_wifi_drv_main_zep(const struct device *dev)
callbk_fns.event_get_wiphy = nrf_wifi_wpa_supp_event_get_wiphy;
callbk_fns.mgmt_rx_callbk_fn = nrf_wifi_wpa_supp_event_mgmt_rx_callbk_fn;
callbk_fns.get_conn_info_callbk_fn = nrf_wifi_supp_event_proc_get_conn_info;
callbk_fns.dms_callbk_fn = nrf_wifi_event_proc_dms_zep;
#endif /* CONFIG_NRF700X_STA_MODE */

rpu_drv_priv_zep.fmac_priv = nrf_wifi_fmac_init(&data_config,
Expand Down Expand Up @@ -786,6 +787,7 @@ static struct wifi_mgmt_ops nrf_wifi_mgmt_ops = {
.set_twt = nrf_wifi_set_twt,
.reg_domain = nrf_wifi_reg_domain,
.get_power_save_config = nrf_wifi_get_power_save_config,
.req_dms = nrf_wifi_req_dms,
#endif /* CONFIG_NRF700X_STA_MODE */
#ifdef CONFIG_NRF700X_SYSTEM_MODE
.mode = nrf_wifi_mode,
Expand Down
191 changes: 187 additions & 4 deletions drivers/wifi/nrf700x/src/wifi_mgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -508,20 +508,20 @@ int nrf_wifi_set_twt(const struct device *dev,
twt_params->flow_id >= WIFI_MAX_TWT_FLOWS) {
LOG_ERR("%s: Invalid flow id: %d",
__func__, twt_params->flow_id);
twt_params->fail_reason = WIFI_TWT_FAIL_INVALID_FLOW_ID;
twt_params->fail_reason = WIFI_FAIL_INVALID_FLOW_ID;
goto out;
}

switch (twt_params->operation) {
case WIFI_TWT_SETUP:
if (vif_ctx_zep->twt_flow_in_progress_map & BIT(twt_params->flow_id)) {
twt_params->fail_reason = WIFI_TWT_FAIL_OPERATION_IN_PROGRESS;
twt_params->fail_reason = WIFI_FAIL_OPERATION_IN_PROGRESS;
goto out;
}

if (twt_params->setup_cmd == WIFI_TWT_SETUP_CMD_REQUEST) {
if (vif_ctx_zep->twt_flows_map & BIT(twt_params->flow_id)) {
twt_params->fail_reason = WIFI_TWT_FAIL_FLOW_ALREADY_EXISTS;
twt_params->fail_reason = WIFI_FAIL_FLOW_ALREADY_EXISTS;
goto out;
}
}
Expand Down Expand Up @@ -559,7 +559,7 @@ int nrf_wifi_set_twt(const struct device *dev,

if (!twt_params->teardown.teardown_all) {
if (!(vif_ctx_zep->twt_flows_map & BIT(twt_params->flow_id))) {
twt_params->fail_reason = WIFI_TWT_FAIL_INVALID_FLOW_ID;
twt_params->fail_reason = WIFI_FAIL_INVALID_FLOW_ID;
goto out;
}
start_flow_id = twt_params->flow_id;
Expand Down Expand Up @@ -948,3 +948,186 @@ int nrf_wifi_filter(const struct device *dev,
return ret;
}
#endif /* CONFIG_NRF700X_RAW_DATA_RX || CONFIG_NRF700X_PROMISC_DATA_RX */

static void nrf_wifi_dms_update_internal_state(struct nrf_wifi_vif_ctx_zep *vif_ctx_zep,
bool add, unsigned char dmsid)
{
if (add) {
vif_ctx_zep->dms_id_map |= BIT(dmsid);
vif_ctx_zep->dms_id_in_progress_map &= ~BIT(dmsid);
} else {
vif_ctx_zep->dms_id_map &= ~BIT(dmsid);
}
}

int nrf_wifi_req_dms(const struct device *dev,
struct wifi_dms_params *dms_params)
{
enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL;
struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
struct nrf_wifi_umac_config_dms_info dms_info = {0};
int ret = -1;

if (!dev || !dms_params) {
LOG_ERR("%s: dev or dms_params is NULL", __func__);
return ret;
}

vif_ctx_zep = dev->data;

if (!vif_ctx_zep) {
LOG_ERR("%s: vif_ctx_zep is NULL", __func__);
return ret;
}

rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep;

if (!rpu_ctx_zep) {
LOG_ERR("%s: rpu_ctx_zep is NULL", __func__);
return ret;
}

k_mutex_lock(&vif_ctx_zep->vif_lock, K_FOREVER);
if (!rpu_ctx_zep->rpu_ctx) {
LOG_DBG("%s: RPU context not initialized", __func__);
goto out;
}

switch (dms_params->operation) {
case WIFI_DMS_REQ_ADD:
if (vif_ctx_zep->dms_id_in_progress_map & BIT(dms_params->dmsid)) {
dms_params->fail_reason = WIFI_FAIL_OPERATION_IN_PROGRESS;
goto out;
}

if (dms_params->operation == WIFI_DMS_REQ_ADD) {
if (vif_ctx_zep->dms_id_map & BIT(dms_params->dmsid)) {
dms_params->fail_reason = WIFI_FAIL_FLOW_ALREADY_EXISTS;
goto out;
}
}

dms_info.dmsid = dms_params->dmsid;
dms_info.dialog_token = dms_params->dialog_token;

dms_info.up = dms_params->tclas_elem.up;
dms_info.tclas_type = dms_params->tclas_elem.classifier_info.type;
dms_info.tclas_mask = dms_params->tclas_elem.classifier_info.mask;
dms_info.version = dms_params->tclas_elem.classifier_info.param_info.version;
dms_info.src_ip_addr = dms_params->tclas_elem.classifier_info.param_info.src_ip_addr;
dms_info.src_port = dms_params->tclas_elem.classifier_info.param_info.src_port;
dms_info.dest_ip_addr = dms_params->tclas_elem.classifier_info.param_info.dest_ip_addr;
dms_info.dest_port = dms_params->tclas_elem.classifier_info.param_info.dest_port;
dms_info.dscp = dms_params->tclas_elem.classifier_info.param_info.dscp;
dms_info.protocol = dms_params->tclas_elem.classifier_info.param_info.protocol;

status = nrf_wifi_fmac_req_add_dms(rpu_ctx_zep->rpu_ctx,
vif_ctx_zep->vif_idx,
&dms_info);
break;
case WIFI_DMS_REQ_REMOVE:
if (!(vif_ctx_zep->dms_id_map & BIT(dms_params->dmsid))) {
dms_params->fail_reason = WIFI_FAIL_INVALID_DMS_ID;
goto out;
}
dms_info.dmsid = dms_params->dmsid;

status = nrf_wifi_fmac_req_remove_dms(vif_ctx_zep,
vif_ctx_zep->vif_idx,
&dms_info);
break;
case WIFI_DMS_REQ_CHANGE:
if (vif_ctx_zep->dms_id_in_progress_map & BIT(dms_params->dmsid)) {
dms_params->fail_reason = WIFI_FAIL_OPERATION_IN_PROGRESS;
goto out;
}

if (!(vif_ctx_zep->dms_id_map & BIT(dms_params->dmsid))) {
dms_params->fail_reason = WIFI_FAIL_INVALID_DMS_ID;
goto out;
}

dms_info.dmsid = dms_params->dmsid;
dms_info.dialog_token = dms_params->dialog_token;

dms_info.up = dms_params->tclas_elem.up;
dms_info.tclas_type = dms_params->tclas_elem.classifier_info.type;
dms_info.tclas_mask = dms_params->tclas_elem.classifier_info.mask;
dms_info.version = dms_params->tclas_elem.classifier_info.param_info.version;
dms_info.src_ip_addr = dms_params->tclas_elem.classifier_info.param_info.src_ip_addr;
dms_info.src_port = dms_params->tclas_elem.classifier_info.param_info.src_port;
dms_info.dest_ip_addr = dms_params->tclas_elem.classifier_info.param_info.dest_ip_addr;
dms_info.dest_port = dms_params->tclas_elem.classifier_info.param_info.dest_port;
dms_info.dscp = dms_params->tclas_elem.classifier_info.param_info.dscp;
dms_info.protocol = dms_params->tclas_elem.classifier_info.param_info.protocol;

status = nrf_wifi_fmac_req_change_dms(rpu_ctx_zep->rpu_ctx,
vif_ctx_zep->vif_idx,
&dms_info);
break;
default:
LOG_ERR("Unknown DMS operation");
status = NRF_WIFI_STATUS_FAIL;
break;
}

if (status != NRF_WIFI_STATUS_SUCCESS) {
LOG_ERR("%s: nrf_wifi_req_dms %s failed",
__func__,
(dms_params->operation == WIFI_DMS_REQ_ADD) ? "add" :
(dms_params->operation == WIFI_DMS_REQ_REMOVE) ? "remove" : "change");
goto out;
}

ret = 0;
out:
k_mutex_unlock(&vif_ctx_zep->vif_lock);
return ret;
}

void nrf_wifi_event_proc_dms_zep(void *vif_ctx,
struct nrf_wifi_umac_dms_op *dms_info,
unsigned int event_len)
{
struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
struct wifi_dms_params dms_params;

if (!vif_ctx || !dms_info) {
return;
}

vif_ctx_zep = vif_ctx;

dms_params.dmsid = dms_info->info.dmsid;
dms_params.dialog_token = dms_info->info.dialog_token;
dms_params.tclas_elem.up = dms_info->info.up;
dms_params.tclas_elem.classifier_info.param_info.version = dms_info->info.version;
dms_params.tclas_elem.classifier_info.param_info.src_ip_addr = dms_info->info.src_ip_addr;
dms_params.tclas_elem.classifier_info.param_info.src_port = dms_info->info.src_port;
dms_params.tclas_elem.classifier_info.param_info.dest_ip_addr = dms_info->info.dest_ip_addr;
dms_params.tclas_elem.classifier_info.param_info.dest_port = dms_info->info.dest_port;
dms_params.tclas_elem.classifier_info.param_info.dscp = dms_info->info.dscp;
dms_params.tclas_elem.classifier_info.param_info.protocol = dms_info->info.protocol;
dms_params.tclas_elem.classifier_info.type = dms_info->info.tclas_type;
dms_params.tclas_elem.classifier_info.mask = dms_info->info.tclas_mask;

switch(dms_info->info.event_type) {
case NRF_WIFI_DMS_EVENT_ACCEPT:
dms_params.operation = WIFI_DMS_REQ_ADD;
if (dms_info->info.dms_resp_status == 0) {
nrf_wifi_dms_update_internal_state(vif_ctx_zep, true, dms_params.dmsid);
}
break;
case NRF_WIFI_DMS_EVENT_REJECT:
break;
case NRF_WIFI_DMS_EVENT_TERMINATE:
nrf_wifi_dms_update_internal_state(vif_ctx_zep, false, dms_params.dmsid);
break;
case NRF_WIFI_DMS_EVENT_INVALID:
LOG_ERR("Unknown DMS event received");
break;
}

wifi_mgmt_raise_dms_event(vif_ctx_zep->zep_net_if_ctx, &dms_params);
}

0 comments on commit decfa9e

Please sign in to comment.