[ESP32S3 Undocumented] ESP32 WIFI: кое-какая статистика

Недавно наткнулся на неприметную струтуру в драйвере WiFi, на которую раньше не обращал внимания. Но сегодня у меня был выходной и я сел с утра и вот к пяти часам расколупал.

Это счетчик. Статисика WiFi, которую просто и легко можно использовать у себя в скетче. На ESP32 не проверял, но уверен, что заработает: там тот-же драйвер. Счетчик принятых и отправленных фреймов, счетчики по типам фреймов, кое-какие индикаторы ошибок, то-сё.

Удобно использовать для отладки WiFi, когда соединение не устанавливается или сбрасывается.

Кот:

// Этот код демонстрирует доступ к счётчикам драйвера WiFi на ESP32 / ESP32-S3
// в среде Arduino Framework.
//

#include <Arduino.h>


// Счётчики увеличиваются драйвером WiFi. Я не нашёл в коде Espressif места,
// где эти счётчики очищаются, поэтому при необходимости пользователь должен
// сбрасывать их самостоятельно.
// Счётчики обнуляются при запуске системы, но не сбрасываются при
// включении или выключении интерфейса. Наверно стоит использовать __attribute__((packed)), 
// но вроде работает и так.
// Если расползутся значения при очередном апдейте компилятора - допишите packed.
typedef struct {

  // Статистика RX для STA
  uint32_t sta_total_rx;         // Общее количество WiFi-фреймов, принятых STA
  uint32_t sta_data;             // Общее количество data-фреймов, принятых STA
  uint16_t sta_ctl;              // Control-фреймы
  uint16_t sta_mgmt;             // Management-фреймы
  uint16_t sta_bcn_probe;        // Beacon / Probe фреймы

  // Не совсем понятно, почему следующие счётчики 8-битные.
  // Возможно, Espressif экономит память, предполагая, что такие события
  // происходят относительно редко. В любом случае все счётчики в этой
  // структуре могут (и будут) переполняться и начинать отсчёт заново.
  uint8_t  sta_assoc;            // Количество ASSOC-запросов?
  uint8_t  sta_auth;             // Количество успешных попыток аутентификации?
  uint8_t  sta_deauth;           // Количество deauth-фреймов?
  uint8_t  sta_action;           // Количество action-фреймов?

  uint16_t sta_amsdu;            // AMSDU-фреймы

  // Статистика RX для AP
  uint32_t ap_total_rx;          // То же самое, но для интерфейса AP
  uint32_t ap_data;           
  uint16_t ap_ctl;            
  uint16_t ap_mgmt;           
  uint16_t ap_bcn_probe;      
  uint8_t  ap_assoc;          
  uint8_t  ap_auth;          
  uint8_t  ap_deauth;         
  uint8_t  ap_action;         
  uint16_t ap_amsdu;          

  // Статистика TX
  uint32_t ap_total_tx;          // AP: общее количество переданных фреймов
  uint32_t sta_total_tx;         // STA: общее количество переданных фреймов

  // Очередь Power Save? Точное назначение этого блока неизвестно.
  // Названия полей структуры взяты из кода Espressif.
  //
  uint16_t psq_tx;               // Фреймы в очереди?
  uint16_t psq_mc;               // Multicast-фреймы в очереди?
  uint16_t psq_uc;               // Unicast-фреймы в очереди?

  uint16_t reorder;              // События AMPDU reorder?   <-- увеличивается при некоторых ошибках
  uint16_t oos;                  // Out-of-sequence события? <-- увеличивается при некоторых ошибках

  uint16_t ps_uc1;               // Назначение неизвестно

  uint16_t tx_amsdu;             // TX AMSDU

} hmac_cnt_t;


// Объявляем переменную со счётчиками. Остальное сделает линкер.
//
#ifdef __cplusplus
extern "C" {
#endif

extern hmac_cnt_t g_hmac_cnt;

#ifdef __cplusplus
};
#endif


void setup() {
  Serial.begin(115200);
}


void loop() {

  delay(1000);

  Serial.printf("STA total frames received=%lu, data frames=%lu, ctrl=%u, mgmt=%u\r\n"
                "STA total frames sent %lu\r\n",
                g_hmac_cnt.sta_total_rx,
                g_hmac_cnt.sta_data,
                g_hmac_cnt.sta_ctl,
                g_hmac_cnt.sta_mgmt,
                g_hmac_cnt.sta_total_tx
                );

}
2 лайка

вот эта фраза непонятна

Уточню: Я проверил это на ESP32-S3. На ESP32 не проверял.

Драйвер WiFi на ESP32 и прочих версиях процессора имеет части аппаратно-зависимые и не зависимые.

Одна из таких независимых частей - счетчик статистики. Еще общие независимые части - это packet processing, LMAC, MAC. Части связанные с железом - где как: где-то совпадает код, где-то нет. Но что касается глобальных переменных драйвера, торчащих наружу - они есть у всех чипов.

Аппаратно-зависимые части - разные, в зависимости от чипа. Остальной код - тот же самый, на 99.9%. Их код - это переделка libnet80211 из FreeBSD версии 13+. Сильно переделанное, но все же из FreeBSD. Что помогает в реверсе :slight_smile: