mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-26 18:14:11 +00:00
wpa_supplicant: Add initial roaming support
This commit adds different features from 802.11k and 802.11v specifications to make the device ready for network assisted roaming. It also adds initial framework for device to detect whether it needs to move to a better AP. Followings are added as part of this. 1. Support for sending neighbor report request and provide the report back to the APP. 2. Support for beacon measurement report. 3. Support for link measurement report. 4. Support for sending bss transition management query frame (triggered by the APP). 5. Support for bss transition management request and move to the candidate based on that. 6. Sending the bss transition management response.
This commit is contained in:
89
components/wpa_supplicant/src/utils/bitfield.c
Normal file
89
components/wpa_supplicant/src/utils/bitfield.c
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Bitfield
|
||||
* Copyright (c) 2013, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "bitfield.h"
|
||||
|
||||
|
||||
struct bitfield {
|
||||
u8 *bits;
|
||||
size_t max_bits;
|
||||
};
|
||||
|
||||
|
||||
struct bitfield * bitfield_alloc(size_t max_bits)
|
||||
{
|
||||
struct bitfield *bf;
|
||||
|
||||
bf = os_zalloc(sizeof(*bf) + (max_bits + 7) / 8);
|
||||
if (bf == NULL)
|
||||
return NULL;
|
||||
bf->bits = (u8 *) (bf + 1);
|
||||
bf->max_bits = max_bits;
|
||||
return bf;
|
||||
}
|
||||
|
||||
|
||||
void bitfield_free(struct bitfield *bf)
|
||||
{
|
||||
os_free(bf);
|
||||
}
|
||||
|
||||
|
||||
void bitfield_set(struct bitfield *bf, size_t bit)
|
||||
{
|
||||
if (bit >= bf->max_bits)
|
||||
return;
|
||||
bf->bits[bit / 8] |= BIT(bit % 8);
|
||||
}
|
||||
|
||||
|
||||
void bitfield_clear(struct bitfield *bf, size_t bit)
|
||||
{
|
||||
if (bit >= bf->max_bits)
|
||||
return;
|
||||
bf->bits[bit / 8] &= ~BIT(bit % 8);
|
||||
}
|
||||
|
||||
|
||||
int bitfield_is_set(struct bitfield *bf, size_t bit)
|
||||
{
|
||||
if (bit >= bf->max_bits)
|
||||
return 0;
|
||||
return !!(bf->bits[bit / 8] & BIT(bit % 8));
|
||||
}
|
||||
|
||||
|
||||
static int first_zero(u8 val)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (!(val & 0x01))
|
||||
return i;
|
||||
val >>= 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int bitfield_get_first_zero(struct bitfield *bf)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < (bf->max_bits + 7) / 8; i++) {
|
||||
if (bf->bits[i] != 0xff)
|
||||
break;
|
||||
}
|
||||
if (i == (bf->max_bits + 7) / 8)
|
||||
return -1;
|
||||
i = i * 8 + first_zero(bf->bits[i]);
|
||||
if (i >= bf->max_bits)
|
||||
return -1;
|
||||
return i;
|
||||
}
|
21
components/wpa_supplicant/src/utils/bitfield.h
Normal file
21
components/wpa_supplicant/src/utils/bitfield.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Bitfield
|
||||
* Copyright (c) 2013, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef BITFIELD_H
|
||||
#define BITFIELD_H
|
||||
|
||||
struct bitfield;
|
||||
|
||||
struct bitfield * bitfield_alloc(size_t max_bits);
|
||||
void bitfield_free(struct bitfield *bf);
|
||||
void bitfield_set(struct bitfield *bf, size_t bit);
|
||||
void bitfield_clear(struct bitfield *bf, size_t bit);
|
||||
int bitfield_is_set(struct bitfield *bf, size_t bit);
|
||||
int bitfield_get_first_zero(struct bitfield *bf);
|
||||
|
||||
#endif /* BITFIELD_H */
|
@@ -491,3 +491,59 @@ int hwaddr_aton2(const char *txt, u8 *addr)
|
||||
|
||||
return pos - txt;
|
||||
}
|
||||
|
||||
static inline int os_reltime_expired(struct os_time *now,
|
||||
struct os_time *ts,
|
||||
os_time_t timeout_secs)
|
||||
{
|
||||
struct os_time age;
|
||||
|
||||
os_time_sub(now, ts, &age);
|
||||
return (age.sec > timeout_secs) ||
|
||||
(age.sec == timeout_secs && age.usec > 0);
|
||||
}
|
||||
|
||||
int os_time_expired(struct os_time *now,
|
||||
struct os_time *ts,
|
||||
os_time_t timeout_secs)
|
||||
{
|
||||
return os_reltime_expired(now, ts, timeout_secs);
|
||||
}
|
||||
|
||||
u8 rssi_to_rcpi(int rssi)
|
||||
{
|
||||
if (!rssi)
|
||||
return 255; /* not available */
|
||||
if (rssi < -110)
|
||||
return 0;
|
||||
if (rssi > 0)
|
||||
return 220;
|
||||
return (rssi + 110) * 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* wpa_ssid_txt - Convert SSID to a printable string
|
||||
* @ssid: SSID (32-octet string)
|
||||
* @ssid_len: Length of ssid in octets
|
||||
* Returns: Pointer to a printable string
|
||||
*
|
||||
* This function can be used to convert SSIDs into printable form. In most
|
||||
* cases, SSIDs do not use unprintable characters, but IEEE 802.11 standard
|
||||
* does not limit the used character set, so anything could be used in an SSID.
|
||||
*
|
||||
* This function uses a static buffer, so only one call can be used at the
|
||||
* time, i.e., this is not re-entrant and the returned buffer must be used
|
||||
* before calling this again.
|
||||
*/
|
||||
const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len)
|
||||
{
|
||||
static char ssid_txt[SSID_MAX_LEN * 4 + 1];
|
||||
|
||||
if (ssid == NULL) {
|
||||
ssid_txt[0] = '\0';
|
||||
return ssid_txt;
|
||||
}
|
||||
|
||||
printf_encode(ssid_txt, sizeof(ssid_txt), ssid, ssid_len);
|
||||
return ssid_txt;
|
||||
}
|
||||
|
@@ -13,6 +13,7 @@
|
||||
#endif /* ets */
|
||||
#include "os.h"
|
||||
#include "esp_bit_defs.h"
|
||||
#include "list.h"
|
||||
|
||||
/* Define platform specific variable type macros */
|
||||
#if defined(ESP_PLATFORM)
|
||||
@@ -115,6 +116,12 @@ static inline unsigned int wpa_swap_32(unsigned int v)
|
||||
#define WPA_BYTE_SWAP_DEFINED
|
||||
#endif /* !WPA_BYTE_SWAP_DEFINED */
|
||||
|
||||
#define SSID_MAX_LEN 32
|
||||
|
||||
struct wpa_ssid_value {
|
||||
u8 ssid[SSID_MAX_LEN];
|
||||
size_t ssid_len;
|
||||
};
|
||||
|
||||
/* Macros for handling unaligned memory accesses */
|
||||
|
||||
@@ -379,6 +386,10 @@ int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data,
|
||||
size_t len);
|
||||
|
||||
int hwaddr_mask_txt(char *buf, size_t len, const u8 *addr, const u8 *mask);
|
||||
u8 rssi_to_rcpi(int rssi);
|
||||
int os_time_expired(struct os_time *now,
|
||||
struct os_time *ts,
|
||||
os_time_t timeout_secs);
|
||||
|
||||
#ifdef CONFIG_NATIVE_WINDOWS
|
||||
void wpa_unicode2ascii_inplace(TCHAR *str);
|
||||
|
@@ -12,8 +12,8 @@
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#ifndef LIST_H
|
||||
#define LIST_H
|
||||
#ifndef DL_LIST_H
|
||||
#define DL_LIST_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
@@ -100,4 +100,4 @@ static inline unsigned int dl_list_len(struct dl_list *list)
|
||||
#define DEFINE_DL_LIST(name) \
|
||||
struct dl_list name = { &(name), &(name) }
|
||||
|
||||
#endif /* LIST_H */
|
||||
#endif /* DL_LIST_H */
|
||||
|
@@ -91,22 +91,22 @@ void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len)
|
||||
size_t i;
|
||||
char output[50];
|
||||
|
||||
if (level < MSG_MSGDUMP)
|
||||
if (level < MSG_ERROR)
|
||||
return;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "%s - hexdump(len=%lu):", title, (unsigned long) len);
|
||||
wpa_printf(level, "%s - hexdump(len=%lu):", title, (unsigned long) len);
|
||||
if (buf == NULL) {
|
||||
wpa_printf(MSG_DEBUG, " [NULL]");
|
||||
wpa_printf(level, " [NULL]");
|
||||
} else {
|
||||
for (i = 0; i < len / 16; i++) {
|
||||
_wpa_snprintf_hex(output, 50, buf + i * 16, 16, 0, 1);
|
||||
wpa_printf(MSG_DEBUG, "%s", output);
|
||||
wpa_printf(level, "%s", output);
|
||||
}
|
||||
if (len % 16) {
|
||||
int bytes_printed = (len / 16) * 16;
|
||||
_wpa_snprintf_hex(output, 50, buf + bytes_printed,
|
||||
len - bytes_printed, 0, 1);
|
||||
wpa_printf(MSG_DEBUG, "%s", output);
|
||||
wpa_printf(level, "%s", output);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user