Page 1 of 1

The problem of packet capture ability of esp32 promiscuous mode.

Posted: Tue Mar 20, 2018 11:25 am
by jason2
I did a experiment.Send packets from esp32,using esp_wifi_80211_tx.Another esp32 capture data in promiscuous mode.Data size per packet is 961 bytes. Counting how many packets been captured by esp32's promiscuous mode per 120 packets.It is showed that, esp32's promiscous mode lost a lot of packets.Is it because of esp32's low capturing ability?Or another reason ?
Sender code:

Code: Select all

#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "esp_wifi.h"
#include "esp_wifi_types.h"
#include "esp_system.h"
#include "esp_event.h"
#include "esp_event_loop.h"
#include "nvs_flash.h"
#include "driver/gpio.h"
#include "lwip/err.h"
#include "esp_log.h"

#define USERDATASTZE 961

#define PACK_NUM_PER_FRAME 120

#define MAX_DELAY 4

#define DATAOFFSET 32
//rates:
/*
0 - B 1Mb CCK
1 - B 2Mb CCK
2 - B 5.5Mb CCK
3 - B 11Mb CCK
4 - XXX Not working. Should be B 1Mb CCK SP
5 - B 2Mb CCK SP
6 - B 5.5Mb CCK SP
7 - B 11Mb CCK SP

8 - G 48Mb ODFM
9 - G 24Mb ODFM
10 - G 12Mb ODFM
11 - G 6Mb ODFM
12 - G 54Mb ODFM
13 - G 36Mb ODFM
14 - G 18Mb ODFM
15 - G 9Mb ODFM

16 - N 6.5Mb MCS0
17 - N 13Mb MCS1
18 - N 19.5Mb MCS2
19 - N 26Mb MCS3
20 - N 39Mb MCS4
21 - N 52Mb MCS5
22 - N 58Mb MCS6
23 - N 65Mb MCS7

24 - N 7.2Mb MCS0 SP
25 - N 14.4Mb MCS1 SP
26 - N 21.7Mb MCS2 SP
27 - N 28.9Mb MCS3 SP
28 - N 43.3Mb MCS4 SP
29 - N 57.8Mb MCS5 SP
30 - N 65Mb MCS6 SP
31 - N 72Mb MCS7 SP
*/
#define RATE_MCS7 31
typedef union {
     uint8_t fix_rate;
     uint8_t b5;
     uint8_t b4;
 
     struct {
         uint8_t b3;
         uint8_t b2;
     } b1;
 
     struct {
         uint32_t a1;
         uint8_t  a2;
         uint8_t  a3;
         uint8_t  a4;
         uint8_t  a5;
         struct {
             uint8_t a6;
             uint8_t a7;
         } a8[4];
         uint8_t a9;
         uint8_t a10;
         uint8_t a11;
         uint8_t a12;
     } a13;
 
 } wifi_internal_rate_t;



uint8_t packetH[DATAOFFSET+USERDATASTZE]={
0x80, 0x00, //Frame Control subtype is beacon
0x00, 0x00, //Duration
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, //Receiver Address= Destination Address 
0x30, 0xAE, 0xA4, 0x05, 0x17, 0x64, //Transmitter Address= Source Address
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, //BSSID
0x00, 0x00,                         //Sequence control
0x01, 0x02, 0x02, 0x03,0x03,0x03,0x04,0x04, //Body
//0x05, 0x03, 0x02, 0x01 //FCS
};

extern	esp_err_t esp_wifi_80211_tx(wifi_interface_t ifx, const void *buffer, int len, bool en_sys_seq);  
extern	esp_err_t esp_wifi_internal_set_rate(int a, int b, int c, wifi_internal_rate_t *d);


static esp_err_t event_handler(void *ctx, system_event_t *event);




static void wifi_init(void)
{
	nvs_flash_init();
    tcpip_adapter_init();
    ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) );
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
	ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
	//ESP_ERROR_CHECK( esp_wifi_set_country(&wifi_country) ); /* set country for channel range [1, 13] */
	ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
    ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_NULL) );
    ESP_ERROR_CHECK( esp_wifi_start() );
	wifi_internal_rate_t rate;  
	rate.fix_rate = RATE_MCS7;
	esp_wifi_internal_set_rate(100, 1, 4, &rate);
}


void app_main(void)
{
	esp_log_level_set("*", ESP_LOG_NONE);
	static unsigned int fail_count=0;
	struct timeval time_start;
	struct timeval time_end;
	struct timeval result_time;
	static uint8_t data[USERDATASTZE];
	uint32_t delay=1;
	esp_wifi_set_channel(1, WIFI_SECOND_CHAN_NONE);
	/* setup */
	wifi_init();
	while(true)
	{
		gettimeofday(&time_start,NULL);
		for(uint8_t i=1;i<=PACK_NUM_PER_FRAME;i++)
		{
			data[0]=i; //pack num
			memcpy(packetH+DATAOFFSET,data,sizeof(data));
			int result = esp_wifi_80211_tx(WIFI_MODE_STA, packetH, sizeof(packetH), true);
			switch (result) 
			{
			/*
				case ERR_OK:
					//Serial.println("ERR_OK"); 
					printf("ESPOK\n");
					break;
			*/
				case ESP_ERR_WIFI_NO_MEM:
					fail_count++;
					vTaskDelay(delay);
					if(delay<MAX_DELAY)
					{
						delay<<=1;
					}
					break;
				case ERR_IF:
					printf("ERR_IF\n");
					break;
				
				case ERR_ARG: 
					printf("ERR_ARG\n");
					break;
				//default:
			//	printf("result=%d",result);
			}
		}

		gettimeofday(&time_end,NULL);
		//caculat the time of sending 115200 bytes(921kbits)
		timersub(&time_end, &time_start, &result_time);
		printf("result_time usec is %ld\n",result_time.tv_usec);

		
		printf("fail_count=%d\n",fail_count);
		fail_count=0;
		vTaskDelay(10000);
		}
}

esp_err_t
event_handler(void *ctx, system_event_t *event)
{
	return ESP_OK;
}





promiscuous mode code:

Code: Select all

#include "freertos/FreeRTOS.h"
#include "esp_wifi.h"
#include "esp_wifi_types.h"
#include "esp_system.h"
#include "esp_event.h"
#include "esp_event_loop.h"
#include "nvs_flash.h"
#include "driver/gpio.h"
#include "string.h"

#define	LED_GPIO_PIN			GPIO_NUM_4
#define	WIFI_CHANNEL_MAX		(13)
#define	WIFI_CHANNEL_SWITCH_INTERVAL	(500)
#define PACKSIZE (960+1)
#define FRAMESIZE 115200UL
#define PACKNUM 120
#define	LED_GPIO_PIN			GPIO_NUM_4
#define	WIFI_CHANNEL_MAX		(13)
#define	WIFI_CHANNEL_SWITCH_INTERVAL	(500)
#define PAYLOADOFFSET 32



static uint8_t frame[FRAMESIZE+PACKNUM];
static uint8_t pack_count=0;
static uint8_t pre_pack_num=0;
static wifi_country_t wifi_country = {.cc="CN", .schan=1, .nchan=13, .policy=WIFI_COUNTRY_POLICY_AUTO};

typedef struct {
	unsigned frame_ctrl:16;
	unsigned duration_id:16;
	uint8_t addr1[6]; /* receiver address */
	uint8_t addr2[6]; /* sender address */
	uint8_t addr3[6]; /* filtering address */
	unsigned sequence_ctrl:16;
	uint8_t addr4[6]; /* optional */
} wifi_ieee80211_mac_hdr_t;

typedef struct {
	wifi_ieee80211_mac_hdr_t hdr;
	uint8_t payload[0]; /* network data ended with 4 bytes csum (CRC32) */
} wifi_ieee80211_packet_t;

static esp_err_t event_handler(void *ctx, system_event_t *event);
static void wifi_sniffer_init(void);
static void wifi_sniffer_set_channel(uint8_t channel);
//static const char *wifi_sniffer_packet_type2str(wifi_promiscuous_pkt_type_t type);
static void wifi_sniffer_packet_handler(void *buff, wifi_promiscuous_pkt_type_t type);

void
app_main(void)
{
	uint8_t  channel = 1;

	/* setup */
	wifi_sniffer_init();
	gpio_set_direction(LED_GPIO_PIN, GPIO_MODE_OUTPUT);
	wifi_sniffer_set_channel(channel);
}

esp_err_t
event_handler(void *ctx, system_event_t *event)
{
	
	return ESP_OK;
}

void
wifi_sniffer_init(void)
{

	nvs_flash_init();
    	tcpip_adapter_init();
    	ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) );
    	wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
	ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
	ESP_ERROR_CHECK( esp_wifi_set_country(&wifi_country) ); /* set country for channel range [1, 13] */
	ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
    	ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_NULL) );
    	ESP_ERROR_CHECK( esp_wifi_start() );
	esp_wifi_set_promiscuous(true);
	esp_wifi_set_promiscuous_rx_cb(&wifi_sniffer_packet_handler);
}

void
wifi_sniffer_set_channel(uint8_t channel)
{
	
	esp_wifi_set_channel(channel, WIFI_SECOND_CHAN_NONE);
}


int pack_seq[120];
void
wifi_sniffer_packet_handler(void* buff, wifi_promiscuous_pkt_type_t type)
{

	if (type != WIFI_PKT_MGMT)
		return;

	const wifi_promiscuous_pkt_t *ppkt = (wifi_promiscuous_pkt_t *)buff;
	const wifi_ieee80211_packet_t *ipkt = (wifi_ieee80211_packet_t *)ppkt->payload;
	const wifi_ieee80211_mac_hdr_t *hdr = &ipkt->hdr;

	if((hdr->addr2[4]==0x17)&&(hdr->addr2[5]==0x64))
	{
		pack_seq[pack_count]=ppkt->payload[PAYLOADOFFSET];
		//indicate that begin receive next frame,so count the numbers of packets received in last frame
		if(ppkt->payload[PAYLOADOFFSET]<pre_pack_num)
		{
				printf("recive pack num:");
				//The numbers that are not printed in 1~120 represent packets that are not caught 
				for(int i=0;i<pre_pack_num;i++)
				{
					printf("%d,",pack_seq[i]);
				}
				printf("\n");
				printf("\n");
			memset(pack_seq,0,sizeof(pack_seq));
			memset(frame,0,sizeof(frame));
			pack_count=0;
			pack_seq[pack_count]=ppkt->payload[PAYLOADOFFSET];
				
		}
	}

	pack_count++;
	pre_pack_num=ppkt->payload[PAYLOADOFFSET];
}



sender log :
result_time usec is 28163
fail_count=0
result_time usec is 31111
fail_count=0
result_time usec is 30351
fail_count=0
result_time usec is 30077
fail_count=0
result_time usec is 30189
fail_count=0
result_time usec is 31657
fail_count=0
result_time usec is 30228
fail_count=0
result_time usec is 29752
fail_count=0
result_time usec is 27911
fail_count=0

promiscuous mode log:
recive pack num:26,27,28,29,30,85,86,87,89,90,0,95,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,

recive pack num:95,96,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,

recive pack num:1,2,3,4,5,6,7,8,9,10,11,12,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,0,88,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,

recive pack num:88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,

recive pack num:1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,29,30,31,32,33,34,35,36,1,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,

And the attachements are the sdkconfig files of these little two projects.

Re: The problem of packet capture ability of esp32 promiscuous mode.

Posted: Fri Mar 23, 2018 7:02 pm
by jeanleflambeur
To improve the capture speed try this:

1. Remove your printf calls from the sniffer callback. The callback has to finish as soon as possible.
2. Mark the function as IRAM_ATTR. This resulted in a 10x rate improvement for me:

Code: Select all

IRAM_ATTR void packet_received_cb(void* buf, wifi_promiscuous_pkt_type_t type)
{
...
}