diff --git a/drivers/wifi/nrf700x/Kconfig b/drivers/wifi/nrf700x/Kconfig index c7fdacf48e33..abcc5d95b43f 100644 --- a/drivers/wifi/nrf700x/Kconfig +++ b/drivers/wifi/nrf700x/Kconfig @@ -80,6 +80,10 @@ config NRF700X_RAW_DATA_TX bool "Enable RAW TX data path in the driver" depends on NRF700X_SYSTEM_MODE +config NRF700X_RAW_DATA_RX + bool "Enable RAW RX sniffer operation in the driver" + depends on NRF700X_SYSTEM_MODE + config NRF_WIFI_IF_AUTO_START bool "Enable Wi-Fi interface auto start on boot" default y diff --git a/drivers/wifi/nrf700x/inc/net_if.h b/drivers/wifi/nrf700x/inc/net_if.h index 5375a7dec70b..9f78fd615a81 100644 --- a/drivers/wifi/nrf700x/inc/net_if.h +++ b/drivers/wifi/nrf700x/inc/net_if.h @@ -28,6 +28,10 @@ int nrf_wifi_if_set_config_zep(const struct device *dev, enum ethernet_config_type type, const struct ethernet_config *config); +int nrf_wifi_if_get_config_zep(const struct device *dev, + enum ethernet_config_type type, + struct ethernet_config *config); + enum ethernet_hw_caps nrf_wifi_if_caps_get(const struct device *dev); int nrf_wifi_if_send(const struct device *dev, @@ -36,6 +40,12 @@ int nrf_wifi_if_send(const struct device *dev, void nrf_wifi_if_rx_frm(void *os_vif_ctx, void *frm); +#ifdef CONFIG_NRF700X_RAW_DATA_RX +void nrf_wifi_if_sniffer_rx_frm(void *os_vif_ctx, + void *frm, + struct raw_rx_pkt_header *raw_rx_hdr); +#endif /* CONFIG_NRF700X_RAW_DATA_RX */ + enum nrf_wifi_status nrf_wifi_if_carr_state_chg(void *os_vif_ctx, enum nrf_wifi_fmac_if_carr_state carr_state); diff --git a/drivers/wifi/nrf700x/inc/wifi_mgmt.h b/drivers/wifi/nrf700x/inc/wifi_mgmt.h index 6c83b39cbddd..092854d57611 100644 --- a/drivers/wifi/nrf700x/inc/wifi_mgmt.h +++ b/drivers/wifi/nrf700x/inc/wifi_mgmt.h @@ -18,6 +18,10 @@ #include "osal_api.h" +/** Filter setting defines for sniffer mode. */ +#define WIFI_MGMT_DATA_CTRL_FILTER_SETTING 0xE +#define WIFI_ALL_FILTER_SETTING 0xF + struct twt_interval_float { unsigned short mantissa; unsigned char exponent; @@ -56,8 +60,14 @@ int nrf_wifi_mode(const struct device *dev, struct wifi_mode_info *mode); #endif -#ifdef CONFIG_NRF700X_RAW_DATA_TX +#if defined(CONFIG_NRF700X_RAW_DATA_TX) || defined(CONFIG_NRF700X_RAW_DATA_RX) int nrf_wifi_channel(const struct device *dev, struct wifi_channel_info *channel); -#endif /* CONFIG_NRF700X_RAW_DATA_TX */ +#endif /* CONFIG_NRF700X_RAW_DATA_TX || CONFIG_NRF700X_RAW_DATA_RX */ + +#ifdef CONFIG_NRF700X_RAW_DATA_RX +int nrf_wifi_filter(const struct device *dev, + struct wifi_filter_info *filter); +#endif /* CONFIG_NRF700X_RAW_DATA_RX */ + #endif /* __ZEPHYR_WIFI_MGMT_H__ */ diff --git a/drivers/wifi/nrf700x/src/fmac_main.c b/drivers/wifi/nrf700x/src/fmac_main.c index 3245a7f5c88e..bf055115ea50 100644 --- a/drivers/wifi/nrf700x/src/fmac_main.c +++ b/drivers/wifi/nrf700x/src/fmac_main.c @@ -657,6 +657,9 @@ static int nrf_wifi_drv_main_zep(const struct device *dev) data_config.rate_protection_type = rate_protection_type; callbk_fns.if_carr_state_chg_callbk_fn = nrf_wifi_if_carr_state_chg; callbk_fns.rx_frm_callbk_fn = nrf_wifi_if_rx_frm; +#ifdef CONFIG_NRF700X_RAW_DATA_RX + callbk_fns.rx_sniffer_frm_callbk_fn = nrf_wifi_if_sniffer_rx_frm; +#endif #endif rx_buf_pools[0].num_bufs = rx1_num_bufs; rx_buf_pools[1].num_bufs = rx2_num_bufs; @@ -765,9 +768,12 @@ static struct wifi_mgmt_ops nrf_wifi_mgmt_ops = { #ifdef CONFIG_NRF700X_SYSTEM_MODE .mode = nrf_wifi_mode, #endif -#ifdef CONFIG_NRF700X_RAW_DATA_TX +#if defined(CONFIG_NRF700X_RAW_DATA_TX) || defined(CONFIG_NRF700X_RAW_DATA_RX) .channel = nrf_wifi_channel, -#endif /* CONFIG_NRF700X_RAW_DATA_TX */ +#endif /* CONFIG_NRF700X_RAW_DATA_TX || CONFIG_NRF700X_RAW_DATA_RX */ +#ifdef CONFIG_NRF700X_RAW_DATA_RX + .filter = nrf_wifi_filter, +#endif /* CONFIG_NRF700X_RAW_DATA_RX */ }; #endif /* CONFIG_NET_L2_WIFI_MGMT */ @@ -778,6 +784,7 @@ static const struct net_wifi_mgmt_offload wifi_offload_ops = { .wifi_iface.start = nrf_wifi_if_start_zep, .wifi_iface.stop = nrf_wifi_if_stop_zep, .wifi_iface.set_config = nrf_wifi_if_set_config_zep, + .wifi_iface.get_config = nrf_wifi_if_get_config_zep, .wifi_iface.get_capabilities = nrf_wifi_if_caps_get, .wifi_iface.send = nrf_wifi_if_send, #ifdef CONFIG_NET_STATISTICS_ETHERNET diff --git a/drivers/wifi/nrf700x/src/net_if.c b/drivers/wifi/nrf700x/src/net_if.c index 744236e8df9f..7b9fa88f1a29 100644 --- a/drivers/wifi/nrf700x/src/net_if.c +++ b/drivers/wifi/nrf700x/src/net_if.c @@ -91,6 +91,34 @@ static void nrf_wifi_net_iface_work_handler(struct k_work *work) } } +#ifdef CONFIG_NRF700X_RAW_DATA_RX +void nrf_wifi_if_sniffer_rx_frm(void *os_vif_ctx, void *frm, struct raw_rx_pkt_header *raw_rx_hdr) +{ + struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = os_vif_ctx; + struct net_if *iface = vif_ctx_zep->zep_net_if_ctx; + struct net_pkt *pkt; + int status; + struct nrf_wifi_ctx_zep *rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep; + struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = rpu_ctx_zep->rpu_ctx; + struct nrf_wifi_fmac_dev_ctx_def *def_dev_ctx = NULL; + + def_dev_ctx = wifi_dev_priv(fmac_dev_ctx); + + pkt = net_raw_pkt_from_nbuf(iface, frm, sizeof(struct raw_rx_pkt_header), raw_rx_hdr); + if (!pkt) { + LOG_DBG("Failed to allocate net_pkt"); + return; + } + + status = net_recv_data(iface, pkt); + + if (status < 0) { + LOG_DBG("Raw packet dropped by NET stack: %d", status); + net_pkt_unref(pkt); + } +} +#endif /* CONFIG_NRF700X_RAW_DATA_RX */ + void nrf_wifi_if_rx_frm(void *os_vif_ctx, void *frm) { struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = os_vif_ctx; @@ -169,6 +197,10 @@ enum ethernet_hw_caps nrf_wifi_if_caps_get(const struct device *dev) caps |= ETHERNET_HW_TX_CHKSUM_OFFLOAD | ETHERNET_HW_RX_CHKSUM_OFFLOAD; #endif /* CONFIG_NRF700X_TCP_IP_CHECKSUM_OFFLOAD */ + +#ifdef CONFIG_NRF700X_RAW_DATA_TX + caps |= ETHERNET_TXINJECTION_MODE; +#endif return caps; } @@ -719,12 +751,58 @@ int nrf_wifi_if_stop_zep(const struct device *dev) return ret; } +int nrf_wifi_if_get_config_zep(const struct device *dev, + enum ethernet_config_type type, + struct ethernet_config *config) +{ + int ret = -1; +#ifdef CONFIG_NRF700X_RAW_DATA_TX + struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL; + struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL; + struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = NULL; + struct nrf_wifi_fmac_dev_ctx_def *def_dev_ctx = NULL; + + if (!dev || !config) { + LOG_ERR("%s: Invalid parameters", + __func__); + goto out; + } + + vif_ctx_zep = dev->data; + + if (!vif_ctx_zep) { + LOG_ERR("%s: vif_ctx_zep is NULL", + __func__); + goto out; + } + + /** + * If vif_ctx_zep exists, rpu_ctx_zep and subsequent priv structures + * should exist and cannot be NULL. Derive the pointers for further + * structures + */ + rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep; + fmac_dev_ctx = rpu_ctx_zep->rpu_ctx; + def_dev_ctx = wifi_dev_priv(fmac_dev_ctx); + + if (type == ETHERNET_CONFIG_TYPE_TXINJECTION_MODE) { + config->txinjection_mode = + def_dev_ctx->vif_ctx[vif_ctx_zep->vif_idx]->txinjection_mode; + } + ret = 0; +out: +#endif + return ret; +} int nrf_wifi_if_set_config_zep(const struct device *dev, enum ethernet_config_type type, const struct ethernet_config *config) { struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL; + struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL; + struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = NULL; + struct nrf_wifi_fmac_dev_ctx_def *def_dev_ctx = NULL; int ret = -1; if (!dev) { @@ -741,6 +819,15 @@ int nrf_wifi_if_set_config_zep(const struct device *dev, goto out; } + /** + * If vif_ctx_zep exists, rpu_ctx_zep and subsequent priv structures + * should exist and cannot be NULL. Derive the pointers for further + * structures + */ + rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep; + fmac_dev_ctx = rpu_ctx_zep->rpu_ctx; + def_dev_ctx = wifi_dev_priv(fmac_dev_ctx); + if (type == ETHERNET_CONFIG_TYPE_MAC_ADDRESS) { if (!net_eth_is_addr_valid((struct net_eth_addr *)&config->mac_address)) { LOG_ERR("%s: Invalid MAC address", @@ -756,6 +843,39 @@ int nrf_wifi_if_set_config_zep(const struct device *dev, sizeof(vif_ctx_zep->mac_addr.addr), NET_LINK_ETHERNET); } +#ifdef CONFIG_NRF700X_RAW_DATA_TX + else if (type == ETHERNET_CONFIG_TYPE_TXINJECTION_MODE) { + unsigned char mode; + + if (def_dev_ctx->vif_ctx[vif_ctx_zep->vif_idx]->txinjection_mode == + config->txinjection_mode) { + LOG_INF("%s: Driver TX injection setting is same as configured setting", + __func__); + goto out; + } + /** + * Since UMAC wishes to use the same mode command as previously + * used for mode, `OR` the primary mode with TX-Injection mode and + * send it to the UMAC. That way UMAC can still maintain code + * as is + */ + if (config->txinjection_mode) { + mode = (def_dev_ctx->vif_ctx[vif_ctx_zep->vif_idx]->mode) | + (NRF_WIFI_TX_INJECTION_MODE); + } else { + mode = (def_dev_ctx->vif_ctx[vif_ctx_zep->vif_idx]->mode) ^ + (NRF_WIFI_TX_INJECTION_MODE); + } + + ret = nrf_wifi_fmac_set_mode(rpu_ctx_zep->rpu_ctx, + vif_ctx_zep->vif_idx, mode); + + if (ret != NRF_WIFI_STATUS_SUCCESS) { + LOG_ERR("%s: Mode set operation failed", __func__); + goto out; + } + } +#endif ret = 0; out: diff --git a/drivers/wifi/nrf700x/src/shim.c b/drivers/wifi/nrf700x/src/shim.c index 2387d66621a2..c9b2b396d535 100644 --- a/drivers/wifi/nrf700x/src/shim.c +++ b/drivers/wifi/nrf700x/src/shim.c @@ -370,6 +370,55 @@ void *net_pkt_from_nbuf(void *iface, void *frm) return pkt; } +#ifdef CONFIG_NRF700X_RAW_DATA_RX +void *net_raw_pkt_from_nbuf(void *iface, void *frm, unsigned short raw_hdr_len, void *raw_rx_hdr) +{ + struct net_pkt *pkt = NULL; + unsigned char *nwb_data; + unsigned char *data = NULL; + unsigned int nwb_len; + unsigned int total_len; + struct nwb *nwb = frm; + + if (!nwb) { + LOG_ERR("%s: Received network buffer is NULL", __func__); + return NULL; + } + + nwb_len = zep_shim_nbuf_data_size(nwb); + nwb_data = zep_shim_nbuf_data_get(nwb); + + total_len = raw_hdr_len + nwb_len; + + data = (unsigned char *)k_malloc(total_len); + if (!data) { + LOG_ERR("%s: Unable to allocate memory for sniffer data packet", __func__); + goto out; + } + + pkt = net_pkt_rx_alloc_with_buffer(iface, total_len, AF_PACKET, ETH_P_ALL, K_MSEC(100)); + if (!pkt) { + LOG_ERR("%s: Unable to allocate net packet buffer", __func__); + goto out; + } + + memcpy(data, raw_rx_hdr, raw_hdr_len); + memcpy((data+raw_hdr_len), nwb_data, nwb_len); + + if (net_pkt_write(pkt, data, total_len)) { + net_pkt_unref(pkt); + pkt = NULL; + goto out; + } +out: + if (data != NULL) { + k_free(data); + } + zep_shim_nbuf_free(nwb); + return pkt; +} +#endif /* CONFIG_NRF700X_RAW_DATA_RX */ + static void *zep_shim_llist_node_alloc(void) { struct zep_shim_llist_node *llist_node = NULL; diff --git a/drivers/wifi/nrf700x/src/shim.h b/drivers/wifi/nrf700x/src/shim.h index b9122bc6fc05..a92e7764a804 100644 --- a/drivers/wifi/nrf700x/src/shim.h +++ b/drivers/wifi/nrf700x/src/shim.h @@ -57,5 +57,11 @@ struct zep_shim_llist { void *net_pkt_to_nbuf(struct net_pkt *pkt); void *net_pkt_from_nbuf(void *iface, void *frm); +#ifdef CONFIG_NRF700X_RAW_DATA_RX +void *net_raw_pkt_from_nbuf(void *iface, + void *frm, + unsigned short raw_hdr_len, + void *raw_rx_hdr); +#endif /* CONFIG_NRF700X_RAW_DATA_RX */ #endif /* __SHIM_H__ */ diff --git a/drivers/wifi/nrf700x/src/wifi_mgmt.c b/drivers/wifi/nrf700x/src/wifi_mgmt.c index 0ec4d9b80af8..a95358d2dc14 100644 --- a/drivers/wifi/nrf700x/src/wifi_mgmt.c +++ b/drivers/wifi/nrf700x/src/wifi_mgmt.c @@ -791,6 +791,12 @@ int nrf_wifi_mode(const struct device *dev, } else { mode->mode = def_dev_ctx->vif_ctx[vif_ctx_zep->vif_idx]->mode; + +#if defined(CONFIG_NRF700X_RAW_DATA_TX) || defined(CONFIG_NRF700X_RAW_DATA_RX) + if (def_dev_ctx->vif_ctx[vif_ctx_zep->vif_idx]->txinjection_mode == true) { + mode->mode ^= NRF_WIFI_TX_INJECTION_MODE; + } +#endif } ret = 0; out: @@ -799,7 +805,7 @@ int nrf_wifi_mode(const struct device *dev, } #endif -#ifdef CONFIG_NRF700X_RAW_DATA_TX +#if defined(CONFIG_NRF700X_RAW_DATA_TX) || defined(CONFIG_NRF700X_RAW_DATA_RX) int nrf_wifi_channel(const struct device *dev, struct wifi_channel_info *channel) { @@ -863,4 +869,62 @@ int nrf_wifi_channel(const struct device *dev, k_mutex_unlock(&vif_ctx_zep->vif_lock); return ret; } -#endif /* CONFIG_NRF700X_RAW_DATA_TX */ +#endif /* CONFIG_NRF700X_RAW_DATA_TX || CONFIG_NRF700X_RAW_DATA_RX */ + +#ifdef CONFIG_NRF700X_RAW_DATA_RX +int nrf_wifi_filter(const struct device *dev, + struct wifi_filter_info *filter) +{ + 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_fmac_dev_ctx *fmac_dev_ctx = NULL; + struct nrf_wifi_fmac_dev_ctx_def *def_dev_ctx = NULL; + int ret = -1; + + if (!dev || !filter) { + LOG_ERR("%s: Illegal input parameters", __func__); + goto out; + } + + vif_ctx_zep = dev->data; + if (!vif_ctx_zep) { + LOG_ERR("%s: vif_ctx_zep is NULL\n", __func__); + goto out; + } + + rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep; + fmac_dev_ctx = rpu_ctx_zep->rpu_ctx; + def_dev_ctx = wifi_dev_priv(fmac_dev_ctx); + + if (filter->oper == WIFI_MGMT_SET) { + /** + * In case a user sets data + management + ctrl bits + * or all the filter bits. Map it to bit 0 set to + * enable "all" packet filter bit setting + */ + if (filter->filter == WIFI_MGMT_DATA_CTRL_FILTER_SETTING + || filter->filter == WIFI_ALL_FILTER_SETTING) { + filter->filter = 1; + } + + /** + * Send the driver vif_idx instead of upper layer sent if_index. + * we map network if_index 1 to vif_idx of 0 and so on. The vif_ctx_zep + * context maps the correct network interface index to current driver + * interface index + */ + status = nrf_wifi_fmac_set_packet_filter(rpu_ctx_zep->rpu_ctx, filter->filter, + vif_ctx_zep->vif_idx, filter->buffer_size); + if (status != NRF_WIFI_STATUS_SUCCESS) { + LOG_ERR("%s: Set filter operation failed\n", __func__); + goto out; + } + } else { + filter->filter = def_dev_ctx->vif_ctx[vif_ctx_zep->vif_idx]->packet_filter; + } + ret = 0; +out: + return ret; +} +#endif /* CONFIG_NRF700X_RAW_DATA_RX */ diff --git a/drivers/wifi/nrf700x/src/wpa_supp_if.c b/drivers/wifi/nrf700x/src/wpa_supp_if.c index 379d9bc7de84..e7a1f11ac53f 100644 --- a/drivers/wifi/nrf700x/src/wpa_supp_if.c +++ b/drivers/wifi/nrf700x/src/wpa_supp_if.c @@ -769,6 +769,13 @@ int nrf_wifi_wpa_supp_authenticate(void *if_priv, struct wpa_driver_auth_params goto out; } +#ifdef CONFIG_NRF700X_RAW_DATA_RX + if (vif_ctx_zep->if_type == NRF_WIFI_IFTYPE_MONITOR) { + LOG_ERR("%s: Interface is in Monitor mode - cannot connect to a BSS", __func__); + goto out; + } +#endif /* CONFIG_NRF700X_RAW_DATA_RX */ + memset(&auth_info, 0, sizeof(auth_info)); diff --git a/west.yml b/west.yml index 987fbd66ed5c..98f6505df23b 100644 --- a/west.yml +++ b/west.yml @@ -142,7 +142,7 @@ manifest: - name: nrfxlib repo-path: sdk-nrfxlib path: nrfxlib - revision: 97c3a3b499233985d0cf0959b77476b3f98a9e0a + revision: 4443194eab6763c81a1fd0d8c653817cdaf59233 - name: trusted-firmware-m repo-path: sdk-trusted-firmware-m path: modules/tee/tf-m/trusted-firmware-m