Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for random MAC address #19

Merged
merged 5 commits into from
Dec 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions nrf70_bm_lib/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,14 @@ config NRF_WIFI_SCAN_MAX_BSS_CNT
Maximum number of scan results to return. 0 represents unlimited number of BSSes.

config NRF70_FIXED_MAC_ADDRESS
string "WiFi Fixed MAC address in format XX:XX:XX:XX:XX:XX"
string "WiFi Fixed MAC address in format XXXXXXXXXXXX"
help
This overrides the MAC address read from OTP. Strictly for testing purposes only.

choice
prompt "Wi-Fi MAC address type"
default NRF70_OTP_MAC_ADDRESS if NRF70_FIXED_MAC_ADDRESS = ""
default NRF70_FIXED_MAC_ADDRESS_ENABLED if NRF70_FIXED_MAC_ADDRESS != ""
default NRF70_OTP_MAC_ADDRESS
help
Select the type of MAC address to be used by the Wi-Fi driver

Expand All @@ -62,6 +62,13 @@ config NRF70_FIXED_MAC_ADDRESS_ENABLED
bool "Enable fixed MAC address"
help
Enable fixed MAC address

config NRF70_RANDOM_MAC_ADDRESS
bool "Random MAC address generation at runtime"
select TEST_RANDOM_GENERATOR
help
This option enables random MAC address generation at runtime.
The random MAC address is generated using the libc srand() function.
endchoice

config NRF700X_LOG_VERBOSE
Expand Down
28 changes: 23 additions & 5 deletions nrf70_bm_lib/docs/source/nrf70_bm_lib.rst
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,28 @@ The key components of the Zephyr shim reference implementation are:
* ``platform``: Contains the platform specific files, and has an RPU (Radio Processing Unit) abstraction layer that interacts with the nRF70 Series device,
either through QSPI or SPI. The platform also uses Zephyr GPIO APIs to manage GPIO pins of the nRF70 Series.


Design essentials
#################

The nRF70 BM library is designed to be portable to any platform and OS environment.
The following design essentials are important to understand when porting the library to a third-party platform.

MAC address configuration
*************************

The nRF70 Series Wi-Fi driver offers various options for configuring the MAC address used by the Wi-Fi driver.
The MAC address can be configured in the following ways:

* **Use MAC address from OTP**: The MAC address stored in the OTP memory of the nRF70 Series device is used.
This is the default option, controlled by the Kconfig option ``CONFIG_NRF70_OTP_MAC_ADDRESS``.
* **Enable fixed MAC address**: A fixed MAC address can be set in the Kconfig file.
This option is strictly for testing purposes only, and is controlled by the Kconfig option ``CONFIG_NRF70_FIXED_MAC_ADDRESS``.
* **Use Random MAC address**: A random MAC address is generated by the Wi-Fi driver.
Usefull for testing purposes, this option is controlled by the Kconfig option ``CONFIG_NRF70_RANDOM_MAC_ADDRESS``.
This option uses a Zephyr API in the reference implementation to generate a random MAC address.
When porting to a third-party platform, the random MAC address generation can be implemented using a platform-specific pseudo-random number generator (PRNG).


nRF70 BM library threading model
********************************

Expand All @@ -99,20 +117,20 @@ The library driver code execute in the following contexts:"
In the reference implementation for Zephyr tasklet work is offloaded to Zephyr kernel workqueues.

Optimizing scan operation
#########################
*************************

The nRF70 Series BM library provides a single API to perform a Wi-Fi scan operation.
The scan operation is optimized to provide a wide range of scan configuration parameters.

Please see `Optimizing scan operation <https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/protocols/wifi/scan_mode/scan_operation.html>`_ for more information.

nRF70 Series device states
##########################
**************************

The power save state of the nRF70 Series device is described through a combination of the physical power state of the logic or circuits and the logical functional state as observed by 802.11 protocol operations.

Power state
***********
===========

The nRF70 Series device can be in one of the following power states:

Expand All @@ -133,7 +151,7 @@ When the **FMAC** is de-initialized, the nRF Wi-Fi driver puts the nRF70 Series
When the **FMAC** is initialized, the nRF Wi-Fi driver puts the nRF70 Series device in Active state.

Functional state
****************
================

In terms of functionality, the nRF70 Series device can reside in the following states:

Expand Down
5 changes: 5 additions & 0 deletions nrf70_bm_lib/docs/source/nrf70_bm_porting_guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ The reference implementation of the BM Driver for the Zephyr RTOS uses build-tim
- Used to manage the timers for the nRF70 Series driver, esp. for low power mode.
- timer_***
- k_work_delayable_***
* - Pseudo-Random Number Generator (PRNG)
- Used to generate random numbers for the nRF70 Series random MAC address generation,
(if random MAC address generation support is enabled).
- NA
- sys_rand8_get()


.. note ::
Expand Down
4 changes: 2 additions & 2 deletions nrf70_bm_lib/include/nrf70_bm_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ struct nrf70_wifi_drv_priv_bm {

int nrf70_fmac_init(void);
int nrf70_fmac_deinit(void);
int nrf70_fmac_add_vif_sta(void);
int nrf70_fmac_add_vif_sta(uint8_t *mac_addr);
int nrf70_fmac_del_vif_sta(void);

#endif /* NRF70_BM_INIT_H__ */
#endif /* NRF70_BM_INIT_H__ */
4 changes: 3 additions & 1 deletion nrf70_bm_lib/include/nrf70_bm_lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -244,10 +244,12 @@ typedef void (*nrf70_scan_result_cb_t)(struct nrf70_scan_result *entry);
* This also includes powering up the device and setting up the necessary
* configurations including the download of the firmware patch for nRF70 device.
*
* @param[in] mac_addr MAC address of the device.
*
* @retval 0 If the operation was successful.
* @retval -1 If the operation failed.
*/
int nrf70_bm_init(void);
int nrf70_bm_init(uint8_t *mac_addr);

#if !defined(CONFIG_NRF700X_RADIO_TEST) || defined(__DOXYGEN__)
/**@brief Start scanning for WiFi networks.
Expand Down
81 changes: 66 additions & 15 deletions nrf70_bm_lib/source/nrf70_bm_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
/** @file
* @brief nRF70 Bare Metal initialization.
*/
#ifdef CONFIG_NRF70_RANDOM_MAC_ADDRESS
#include <zephyr/random/random.h>
#endif /* CONFIG_NRF70_RANDOM_MAC_ADDRESS */

#include "nrf70_bm_core.h"
#include "nrf70_bm_lib.h"

Expand Down Expand Up @@ -451,29 +455,64 @@ int nrf70_fmac_init(void)
return -1;
}

#ifdef CONFIG_NRF70_RANDOM_MAC_ADDRESS
static void generate_random_mac_address(uint8_t *mac_addr)
{
// For simplicty use Zephyr API to generate random number
for (int i = 0; i < 6; i++) {
mac_addr[i] = sys_rand8_get();
}

enum nrf_wifi_status nrf_wifi_get_mac_addr(struct nrf70_wifi_vif_bm *vif)
// Set the locally administered bit (bit 1 of the first byte)
mac_addr[0] |= 0x02;

// Clear the multicast bit (bit 0 of the first byte)
mac_addr[0] &= 0xFE;
}
#endif /* CONFIG_WIFI_RANDOM_MAC_ADDRESS */

enum nrf_wifi_status nrf_wifi_get_mac_addr(struct nrf70_wifi_vif_bm *vif,
uint8_t *mac_addr)
{
enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
#ifdef CONFIG_NRF70_OTP_MAC_ADDRESS
void *rpu_ctx = nrf70_bm_priv.rpu_ctx_bm.rpu_ctx;
#endif /* CONFIG_NRF70_RANDOM_MAC_ADDRESS */
struct nrf_wifi_fmac_priv *fmac_priv = nrf70_bm_priv.fmac_priv;
unsigned char mac_addr_str[18];
unsigned char mac_addr_str[13];
#ifdef CONFIG_NRF70_FIXED_MAC_ADDRESS_ENABLED
int ret;
char fixed_mac_addr[NR70_MAC_ADDR_LEN];
#endif /* CONFIG_NRF70_FIXED_MAC_ADDRESS_ENABLED */

/* Runtime takes precedence over any other method */
if (mac_addr) {
memcpy(vif->mac_addr, mac_addr, NR70_MAC_ADDR_LEN);
goto mac_addr_check;
}

#ifdef CONFIG_NRF70_FIXED_MAC_ADDRESS_ENABLED
if (strlen(CONFIG_NRF70_FIXED_MAC_ADDRESS) != 2 * NR70_MAC_ADDR_LEN) {
NRF70_LOG_ERR("Invalid fixed MAC address format: len = %d",
strlen(CONFIG_NRF70_FIXED_MAC_ADDRESS));
return NRF_WIFI_STATUS_FAIL;
}


ret = nrf_wifi_utils_hex_str_to_val(nrf70_bm_priv.fmac_priv->opriv,
CONFIG_WIFI_FIXED_MAC_ADDRESS,
fixed_mac_addr,
NR70_MAC_ADDR_LEN);
NR70_MAC_ADDR_LEN,
CONFIG_NRF70_FIXED_MAC_ADDRESS);
if (ret < 0) {
NR70_LOG_ERR("%s: Failed to parse MAC address: %s",
NRF70_LOG_ERR("%s: Failed to parse MAC address: %s",
__func__,
CONFIG_WIFI_FIXED_MAC_ADDRESS);
CONFIG_NRF70_FIXED_MAC_ADDRESS);
goto err;
}

memcpy(vif->mac_addr, fixed_mac_addr, NR70_MAC_ADDR_LEN);
#elif CONFIG_NRF70_RANDOM_MAC_ADDRESS
generate_random_mac_address(vif->mac_addr);
#elif CONFIG_NRF70_OTP_MAC_ADDRESS
status = nrf_wifi_fmac_otp_mac_addr_get(rpu_ctx,
vif->vif_idx,
Expand All @@ -484,7 +523,7 @@ enum nrf_wifi_status nrf_wifi_get_mac_addr(struct nrf70_wifi_vif_bm *vif)
goto err;
}
#endif

mac_addr_check:
nrf70_bm_mac_txt(vif->mac_addr, mac_addr_str, sizeof(mac_addr_str));
if (!nrf_wifi_utils_is_mac_addr_valid(fmac_priv->opriv,
vif->mac_addr)) {
Expand All @@ -502,7 +541,7 @@ enum nrf_wifi_status nrf_wifi_get_mac_addr(struct nrf70_wifi_vif_bm *vif)

#ifndef CONFIG_NRF70_RADIO_TEST
#define STA_VIF_NAME "wlan0"
int nrf70_fmac_add_vif_sta(void)
int nrf70_fmac_add_vif_sta(uint8_t *mac_addr)
{
enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
struct nrf_wifi_umac_add_vif_info add_vif_info;
Expand All @@ -524,7 +563,7 @@ int nrf70_fmac_add_vif_sta(void)
goto err;
}

status = nrf_wifi_get_mac_addr(vif);
status = nrf_wifi_get_mac_addr(vif, mac_addr);
if (status != NRF_WIFI_STATUS_SUCCESS) {
NRF70_LOG_ERR("%s: Failed to get MAC address", __func__);
goto del_vif;
Expand All @@ -536,6 +575,10 @@ int nrf70_fmac_add_vif_sta(void)
goto del_vif;
}

NRF70_LOG_INF("MAC address set to %02X:%02X:%02X:%02X:%02X:%02X",
vif->mac_addr[0], vif->mac_addr[1], vif->mac_addr[2],
vif->mac_addr[3], vif->mac_addr[4], vif->mac_addr[5]);

memset(&vif_info, 0, sizeof(vif_info));
vif_info.state = NRF_WIFI_FMAC_IF_OP_STATE_UP;
vif_info.if_index = vif->vif_idx;
Expand Down Expand Up @@ -603,13 +646,21 @@ int nrf70_fmac_deinit(void)
NRF70_LOG_DBG("Deinitializing FMAC module");

#ifndef CONFIG_NRF70_RADIO_TEST
nrf_wifi_fmac_dev_deinit(nrf70_bm_priv.rpu_ctx_bm.rpu_ctx);
nrf_wifi_fmac_dev_rem(nrf70_bm_priv.rpu_ctx_bm.rpu_ctx);
nrf_wifi_fmac_deinit(nrf70_bm_priv.fmac_priv);
if (nrf70_bm_priv.rpu_ctx_bm.rpu_ctx) {
nrf_wifi_fmac_dev_deinit(nrf70_bm_priv.rpu_ctx_bm.rpu_ctx);
nrf_wifi_fmac_dev_rem(nrf70_bm_priv.rpu_ctx_bm.rpu_ctx);
}
if (nrf70_bm_priv.fmac_priv) {
nrf_wifi_fmac_deinit(nrf70_bm_priv.fmac_priv);
}
#else
nrf_wifi_fmac_deinit_rt(nrf70_bm_priv.fmac_priv);
nrf_wifi_fmac_dev_rem_rt(nrf70_bm_priv.rpu_ctx_bm.rpu_ctx);
nrf_wifi_fmac_deinit_rt(nrf70_bm_priv.fmac_priv);
if (nrf70_bm_priv.rpu_ctx_bm.rpu_ctx) {
nrf_wifi_fmac_dev_deinit_rt(nrf70_bm_priv.rpu_ctx_bm.rpu_ctx);
nrf_wifi_fmac_dev_rem_rt(nrf70_bm_priv.rpu_ctx_bm.rpu_ctx);
}
if (nrf70_bm_priv.fmac_priv) {
nrf_wifi_fmac_deinit_rt(nrf70_bm_priv.fmac_priv);
}
#endif /* CONFIG_NRF70_RADIO_TEST */

nrf70_bm_priv.fmac_priv = NULL;
Expand Down
4 changes: 2 additions & 2 deletions nrf70_bm_lib/source/nrf70_bm_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ static enum nrf_wifi_band nrf_wifi_map_band_to_rpu(enum nrf70_frequency_bands ba
}
#endif /* CONFIG_NRF700X_RADIO_TEST */

int nrf70_bm_init(void)
int nrf70_bm_init(uint8_t *mac_addr)
{
int ret;

Expand All @@ -99,7 +99,7 @@ int nrf70_bm_init(void)
goto err;
}
#ifndef CONFIG_NRF700X_RADIO_TEST
ret = nrf70_fmac_add_vif_sta();
ret = nrf70_fmac_add_vif_sta(mac_addr);
if (ret) {
NRF70_LOG_ERR("Failed to add STA VIF");
goto deinit;
Expand Down
2 changes: 1 addition & 1 deletion samples/scan_bm/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ int main(void)
printf("WiFi scan sample application using nRF70 Bare Metal library\n");

// Initialize the WiFi module
CHECK_RET(nrf70_bm_init());
CHECK_RET(nrf70_bm_init(NULL));

printf("Scanning for WiFi networks...\n");

Expand Down
Loading