esp-idf/components/wpa_supplicant/test/test_offchannel.c
Nachiket Kukade 76b2cb28d2 Add DPP Enrollee example
1. Add Example for DPP Enrollee
2. Use DPP Supplicant API's to setup connection
3. Add support for multiple channels in Bootstrapping
4. Add Unity testcase for testing Offchannel operations

Closes https://github.com/espressif/esp-idf/issues/5654
2021-01-25 13:26:33 +05:30

246 lines
7.7 KiB
C

// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "string.h"
#include "esp_system.h"
#include "unity.h"
#include "esp_system.h"
#include "esp_event.h"
#include "esp_wifi_types.h"
#include "utils/common.h"
#include "common/ieee802_11_defs.h"
#include "../src/esp_supplicant/esp_wifi_driver.h"
#include "esp_log.h"
#include "test_utils.h"
#include "freertos/event_groups.h"
#define WIFI_START_EVENT 0x00000001
#define WIFI_ROC_DONE_EVENT 0x00000002
#define WIFI_ACTION_RX_EVENT 0x00000003
#define WIFI_SCAN_DONE_EVENT 0x00000004
#define TEST_LISTEN_CHANNEL 6
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32C3)
static const char *TAG = "test_offchan";
esp_netif_t *wifi_netif;
static EventGroupHandle_t wifi_event;
static void wifi_event_handler(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
switch (event_id) {
case WIFI_EVENT_STA_START:
ESP_LOGI(TAG, "WIFI Started");
xEventGroupSetBits(wifi_event, WIFI_START_EVENT);
break;
case WIFI_EVENT_ACTION_TX_STATUS: {
wifi_event_action_tx_status_t *evt =
(wifi_event_action_tx_status_t *)event_data;
if (evt->status == 0) {
ESP_LOGI(TAG, "Action Tx Successful");
}
}
break;
case WIFI_EVENT_ROC_DONE:
ESP_LOGI(TAG, "ROC Done");
xEventGroupSetBits(wifi_event, WIFI_ROC_DONE_EVENT);
break;
case WIFI_EVENT_SCAN_DONE:
ESP_LOGI(TAG, "Scan Done");
xEventGroupSetBits(wifi_event, WIFI_SCAN_DONE_EVENT);
break;
default:
break;
}
return;
}
static esp_err_t event_init(void)
{
ESP_ERROR_CHECK(esp_event_loop_create_default());
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL));
wifi_netif = esp_netif_create_default_wifi_sta();
return ESP_OK;
}
static void start_wifi_as_sta(void)
{
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
cfg.nvs_enable = false;
event_init();
// can't deinit event loop, need to reset leak check
unity_reset_leak_checks();
if (wifi_event == NULL) {
wifi_event = xEventGroupCreate();
} else {
xEventGroupClearBits(wifi_event, 0x00ffffff);
}
TEST_ESP_OK(esp_wifi_init(&cfg));
TEST_ESP_OK(esp_wifi_set_mode(WIFI_MODE_STA));
TEST_ESP_OK(esp_wifi_start());
}
static void stop_wifi(void)
{
esp_event_loop_delete_default();
ESP_LOGI(TAG, "Stop wifi\n");
TEST_ESP_OK(esp_wifi_stop());
TEST_ESP_OK(esp_wifi_deinit());
esp_wifi_clear_default_wifi_driver_and_handlers(wifi_netif);
esp_netif_destroy(wifi_netif);
if (wifi_event) {
vEventGroupDelete(wifi_event);
wifi_event = NULL;
}
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
int dummy_rx_action(uint8_t *hdr, uint8_t *payload, size_t len, uint8_t channel)
{
return ESP_OK;
}
static const char *frame_data = "This is a test data";
void esp_send_action_frame(uint8_t *dest_mac, const uint8_t *buf, uint32_t len,
uint8_t channel, uint32_t wait_time_ms)
{
wifi_action_tx_req_t *req = os_zalloc(sizeof(*req) + len);;
TEST_ASSERT( req != NULL);
req->ifx = ESP_IF_WIFI_STA;
memcpy(req->dest_mac, dest_mac, ETH_ALEN);
req->no_ack = false;
req->data_len = len;
req->rx_cb = dummy_rx_action;
memcpy(req->data, buf, req->data_len);
ESP_LOGI(TAG, "Action Tx - MAC:" MACSTR ", Channel-%d, WaitT-%d",
MAC2STR(dest_mac), channel, wait_time_ms);
TEST_ESP_OK(esp_wifi_action_tx_req(WIFI_OFFCHAN_TX_REQ, channel, wait_time_ms, req));
os_free(req);
}
/* Test that foreground Scan doesn't pre-empt ROC & vice versa */
TEST_CASE("Test scan and ROC simultaneously", "[Offchan]")
{
wifi_action_rx_cb_t rx_cb = dummy_rx_action;
EventBits_t bits;
test_case_uses_tcpip();
start_wifi_as_sta();
xEventGroupWaitBits(wifi_event, WIFI_START_EVENT, 1, 0, 5000 / portTICK_RATE_MS);
TEST_ESP_OK(esp_wifi_remain_on_channel(ESP_IF_WIFI_STA, WIFI_ROC_REQ, TEST_LISTEN_CHANNEL,
100, rx_cb));
ESP_ERROR_CHECK(esp_wifi_scan_start(NULL, false));
bits = xEventGroupWaitBits(wifi_event, WIFI_ROC_DONE_EVENT | WIFI_SCAN_DONE_EVENT,
pdTRUE, pdFALSE, 5000 / portTICK_RATE_MS);
TEST_ASSERT_TRUE(bits == WIFI_ROC_DONE_EVENT);
vTaskDelay(1000 / portTICK_PERIOD_MS);
ESP_ERROR_CHECK(esp_wifi_scan_start(NULL, false));
TEST_ESP_OK(esp_wifi_remain_on_channel(ESP_IF_WIFI_STA, WIFI_ROC_REQ, TEST_LISTEN_CHANNEL,
100, rx_cb));
bits = xEventGroupWaitBits(wifi_event, WIFI_ROC_DONE_EVENT | WIFI_SCAN_DONE_EVENT,
pdTRUE, pdFALSE, 5000 / portTICK_RATE_MS);
TEST_ASSERT_TRUE(bits == WIFI_SCAN_DONE_EVENT);
stop_wifi();
}
static void test_wifi_offchan_tx(void)
{
int i;
char mac_str[19];
uint8_t mac[6];
test_case_uses_tcpip();
start_wifi_as_sta();
xEventGroupWaitBits(wifi_event, WIFI_START_EVENT, 1, 0, 5000 / portTICK_RATE_MS);
unity_wait_for_signal_param("Listener mac", mac_str, 19);
TEST_ASSERT_TRUE(unity_util_convert_mac_from_string(mac_str, mac));
for (i = 0; i < 3; i++) {
esp_send_action_frame(mac, (const uint8_t *)frame_data, strlen(frame_data),
TEST_LISTEN_CHANNEL, 500);
vTaskDelay(500 / portTICK_PERIOD_MS);
}
stop_wifi();
}
static int test_rx_action(uint8_t *hdr, uint8_t *payload, size_t len, uint8_t channel)
{
struct ieee80211_hdr *rx_hdr = (struct ieee80211_hdr *)hdr;
ESP_LOGI(TAG, "Rxd Action Frame from " MACSTR " (Seq-%lu)", MAC2STR(rx_hdr->addr2),
WLAN_GET_SEQ_SEQ(rx_hdr->seq_ctrl));
if (!os_memcmp(payload, frame_data, strlen(frame_data))) {
xEventGroupSetBits(wifi_event, WIFI_ACTION_RX_EVENT);
}
return ESP_OK;
}
static void test_wifi_roc(void)
{
wifi_action_rx_cb_t rx_cb = test_rx_action;
char mac_str[19] = {0};
EventBits_t bits;
uint8_t mac[6];
test_case_uses_tcpip();
start_wifi_as_sta();
xEventGroupWaitBits(wifi_event, WIFI_START_EVENT, 1, 0, 5000 / portTICK_RATE_MS);
TEST_ESP_OK(esp_wifi_get_mac(ESP_IF_WIFI_STA, mac));
sprintf(mac_str, MACSTR, MAC2STR(mac));
unity_send_signal_param("Listener mac", mac_str);
TEST_ESP_OK(esp_wifi_remain_on_channel(ESP_IF_WIFI_STA, WIFI_ROC_REQ, TEST_LISTEN_CHANNEL,
10000, rx_cb));
bits = xEventGroupWaitBits(wifi_event, WIFI_ROC_DONE_EVENT | WIFI_ACTION_RX_EVENT,
pdTRUE, pdFALSE, portMAX_DELAY);
/* Confirm that Frame has been received successfully */
if (bits == WIFI_ACTION_RX_EVENT) {
TEST_ESP_OK(esp_wifi_remain_on_channel(ESP_IF_WIFI_STA, WIFI_ROC_CANCEL, 0, 0, NULL));
vTaskDelay(1000 / portTICK_PERIOD_MS);
stop_wifi();
} else {
stop_wifi();
TEST_FAIL();
}
}
TEST_CASE_MULTIPLE_DEVICES("test ROC and Offchannel Action Frame Tx", "[Offchan][test_env=UT_T2_1][timeout=90]", test_wifi_roc, test_wifi_offchan_tx);
#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32C3)