wireless/bluetooth: add interrupt_context hander for netsnoop

Signed-off-by: chengkai <chengkai@xiaomi.com>
This commit is contained in:
chengkai
2022-09-04 18:26:59 +08:00
committed by Xiang Xiao
parent eb240e014c
commit f864e5f657
4 changed files with 267 additions and 78 deletions
+2 -5
View File
@@ -424,17 +424,14 @@ static int bt_bridge_send(FAR struct bt_driver_s *drv,
flags = enter_critical_section(); flags = enter_critical_section();
if (bt_filter_can_send(&device->filter, type, data, len)) if (bt_filter_can_send(&device->filter, type, data, len))
{ {
int ret;
leave_critical_section(flags); leave_critical_section(flags);
ret = driver->send(driver, type, data, len);
#ifdef CONFIG_BLUETOOTH_BRIDGE_BTSNOOP #ifdef CONFIG_BLUETOOTH_BRIDGE_BTSNOOP
snoop_dump(bridge->snoop, data - drv->head_reserve, snoop_dump(bridge->snoop, data - drv->head_reserve,
len + drv->head_reserve, 0, len + drv->head_reserve, 0,
SNOOP_DIRECTION_FLAG_SENT); SNOOP_DIRECTION_FLAG_SENT);
#endif /* CONFIG_BLUETOOTH_BRIDGE_BTSNOOP */ #endif /* CONFIG_BLUETOOTH_BRIDGE_BTSNOOP */
return ret;
return driver->send(driver, type, data, len);
} }
leave_critical_section(flags); leave_critical_section(flags);
+52 -3
View File
@@ -27,6 +27,9 @@
#include <stdint.h> #include <stdint.h>
#include <nuttx/mutex.h>
#include <nuttx/wqueue.h>
/**************************************************************************** /****************************************************************************
* Pre-processor Definitions * Pre-processor Definitions
****************************************************************************/ ****************************************************************************/
@@ -81,11 +84,18 @@
#define SNOOP_DIRECTION_FLAG_SENT 0 /* Direction flag 0 = Sent */ #define SNOOP_DIRECTION_FLAG_SENT 0 /* Direction flag 0 = Sent */
#define SNOOP_DIRECTION_FLAG_RECV 1 /* Direction flag 1 = Received */ #define SNOOP_DIRECTION_FLAG_RECV 1 /* Direction flag 1 = Received */
#ifndef CONFIG_NET_SNOOP_BUFSIZE
# define CONFIG_NET_SNOOP_BUFSIZE 4096
#endif
struct snoop_s struct snoop_s
{ {
bool autosync; bool autosync;
uint32_t datalink; uint32_t datalink;
struct file filep; struct file filep;
mutex_t mutex;
struct work_s work;
uint8_t buf[CONFIG_NET_SNOOP_BUFSIZE];
size_t next;
}; };
/**************************************************************************** /****************************************************************************
@@ -106,6 +116,17 @@ extern "C"
* Description: * Description:
* This function open snoop file by datalink. * This function open snoop file by datalink.
* *
* Input Parameters:
* snoop The snoop driver struct
* filename Snoop file name
* datalink Snoop datalink type, such as SNOOP_DATALINK_TYPE_XX
* autosync whether do file_sync when snoop_dump
*
* Returned Value:
* OK on success; Negated errno on failure.
*
* Assumptions:
*
****************************************************************************/ ****************************************************************************/
int snoop_open(FAR struct snoop_s *snoop, FAR const char *filename, int snoop_open(FAR struct snoop_s *snoop, FAR const char *filename,
@@ -117,6 +138,18 @@ int snoop_open(FAR struct snoop_s *snoop, FAR const char *filename,
* Description: * Description:
* This function dump nbytes buf data into snoop file. * This function dump nbytes buf data into snoop file.
* *
* Input Parameters:
* snoop The snoop driver struct
* buf Snoop buffer
* nbytes Snoop buffer size
* drops cumulative number of dropped packets
* flags Packet Flags: 1 hci cmd , eg: btsnoop
*
* Returned Value:
* OK on success; Negated errno on failure.
*
* Assumptions:
*
****************************************************************************/ ****************************************************************************/
int snoop_dump(FAR struct snoop_s *snoop, FAR const void *buf, int snoop_dump(FAR struct snoop_s *snoop, FAR const void *buf,
@@ -128,6 +161,14 @@ int snoop_dump(FAR struct snoop_s *snoop, FAR const void *buf,
* Description: * Description:
* This function sync snoop buffer. * This function sync snoop buffer.
* *
* Input Parameters:
* snoop The snoop driver struct
*
* Returned Value:
* OK on success; Negated errno on failure.
*
* Assumptions:
*
****************************************************************************/ ****************************************************************************/
int snoop_sync(FAR struct snoop_s *snoop); int snoop_sync(FAR struct snoop_s *snoop);
@@ -138,6 +179,14 @@ int snoop_sync(FAR struct snoop_s *snoop);
* Description: * Description:
* This function close snoop file. * This function close snoop file.
* *
* Input Parameters:
* snoop The snoop driver struct
*
* Returned Value:
* OK on success; Negated errno on failure.
*
* Assumptions:
*
****************************************************************************/ ****************************************************************************/
int snoop_close(FAR struct snoop_s *snoop); int snoop_close(FAR struct snoop_s *snoop);
+4
View File
@@ -24,3 +24,7 @@ config NET_ARCH_CHKSUM
uint16_t ipv4_chksum(FAR struct ipv4_hdr_s *ipv4) uint16_t ipv4_chksum(FAR struct ipv4_hdr_s *ipv4)
uint16_t ipv4_upperlayer_chksum(FAR struct net_driver_s *dev, uint8_t proto) uint16_t ipv4_upperlayer_chksum(FAR struct net_driver_s *dev, uint8_t proto)
uint16_t ipv6_upperlayer_chksum(FAR struct net_driver_s *dev, uint8_t proto, unsigned int iplen) uint16_t ipv6_upperlayer_chksum(FAR struct net_driver_s *dev, uint8_t proto, unsigned int iplen)
config NET_SNOOP_BUFSIZE
int "Snoop buffer size for interrupt"
default 4096
+209 -70
View File
@@ -161,76 +161,128 @@ begin_packed_struct struct snoop_packet_header_s
****************************************************************************/ ****************************************************************************/
/**************************************************************************** /****************************************************************************
* Name: snoop_dump_packet_header * Name: snoop_fill_packet_header
* *
* Description: * Description:
* This function fill snoop headr info. * This function fill snoop packet header info.
* *
****************************************************************************/ ****************************************************************************/
static int snoop_dump_packet_header(FAR struct snoop_s *snoop, static void snoop_fill_packet_header(FAR struct snoop_s *snoop,
uint32_t bytes, uint32_t drops, uint32_t bytes, uint32_t drops,
uint32_t flags) uint32_t flags, FAR struct
snoop_packet_header_s *header)
{ {
struct snoop_packet_header_s header; struct timeval tv;
int ret;
if (!snoop)
{
return -EINVAL;
}
switch (snoop->datalink) switch (snoop->datalink)
{ {
case SNOOP_DATALINK_HCI_UNENCAP: case SNOOP_DATALINK_HCI_UNENCAP:
case SNOOP_DATALINK_HCI_UART: case SNOOP_DATALINK_HCI_UART:
case SNOOP_DATALINK_HCI_BSCP: case SNOOP_DATALINK_HCI_BSCP:
case SNOOP_DATALINK_HCI_SERIAL: case SNOOP_DATALINK_HCI_SERIAL:
{
struct timeval tv;
gettimeofday(&tv, NULL); gettimeofday(&tv, NULL);
header.ts_usec = htobe64(SNOOP_EPOCH_USEC(tv)); header->ts_usec = htobe64(SNOOP_EPOCH_USEC(tv));
header.flags = htobe32(flags); header->flags = htobe32(flags);
break; break;
}
case SNOOP_DATALINK_TYPE_TOKENBUS:
case SNOOP_DATALINK_TYPE_TOKERING:
case SNOOP_DATALINK_TYPE_METRONET:
case SNOOP_DATALINK_TYPE_ETHERNET:
case SNOOP_DATALINK_TYPE_HDLC:
case SNOOP_DATALINK_TYPE_CHARSYNC:
case SNOOP_DATALINK_TYPE_IBMC2C:
case SNOOP_DATALINK_TYPE_FDDI:
case SNOOP_DATALINK_TYPE_OTHER:
{
struct timeval tv;
case SNOOP_DATALINK_TYPE_TOKENBUS:
case SNOOP_DATALINK_TYPE_TOKERING:
case SNOOP_DATALINK_TYPE_METRONET:
case SNOOP_DATALINK_TYPE_ETHERNET:
case SNOOP_DATALINK_TYPE_HDLC:
case SNOOP_DATALINK_TYPE_CHARSYNC:
case SNOOP_DATALINK_TYPE_IBMC2C:
case SNOOP_DATALINK_TYPE_FDDI:
case SNOOP_DATALINK_TYPE_OTHER:
gettimeofday(&tv, NULL); gettimeofday(&tv, NULL);
header.ts.ts_sec = htobe32(tv.tv_sec); header->ts.ts_sec = htobe32(tv.tv_sec);
header.ts.ts_usec = htobe32(tv.tv_usec); header->ts.ts_usec = htobe32(tv.tv_usec);
header.rec_len = htobe32(flags); header->rec_len = htobe32(flags);
break; break;
}
default: default:
{ DEBUGASSERT(false);
return -EINVAL;
}
} }
header.orig_len = htobe32(bytes); header->orig_len = htobe32(bytes);
header.incl_len = htobe32(bytes); header->incl_len = htobe32(bytes);
header.cum_drops = htobe32(drops); header->cum_drops = htobe32(drops);
}
ret = file_write(&snoop->filep, &header, sizeof(header)); /****************************************************************************
if (ret != sizeof(header)) * Name: snoop_flush
*
* Description:
* This function could flush snoop buf into file.
*
****************************************************************************/
static int snoop_flush(FAR struct snoop_s *snoop)
{
ssize_t ret;
if (snoop->next == 0)
{ {
return ret < 0 ? ret : -EINVAL; return 0;
} }
return OK; do
{
ret = file_write(&snoop->filep, snoop->buf, snoop->next);
if (ret < 0)
{
break;
}
snoop->next -= ret;
memmove(snoop->buf, snoop->buf + ret, snoop->next);
}
while (snoop->next > 0);
#ifndef CONFIG_DISABLE_MOUNTPOINT
if (snoop->autosync)
{
ret = file_fsync(&snoop->filep);
}
#endif
return ret;
}
/****************************************************************************
* Name: snoop_flush_lock
*
* Description:
* Snoop flush atomic
*
****************************************************************************/
static int snoop_flush_lock(FAR struct snoop_s *snoop)
{
irqstate_t flags;
int ret;
flags = enter_critical_section();
nxmutex_lock(&snoop->mutex);
ret = snoop_flush(snoop);
nxmutex_unlock(&snoop->mutex);
leave_critical_section(flags);
return ret;
}
/****************************************************************************
* Name: snoop_flush_work
*
* Description:
* Do snoop flush work.
*
****************************************************************************/
static void snoop_flush_work(FAR void *arg)
{
snoop_flush_lock((FAR struct snoop_s *)arg);
} }
/**************************************************************************** /****************************************************************************
@@ -243,6 +295,17 @@ static int snoop_dump_packet_header(FAR struct snoop_s *snoop,
* Description: * Description:
* This function open snoop file by datalink. * This function open snoop file by datalink.
* *
* Input Parameters:
* snoop The snoop driver struct
* filename Snoop file name
* datalink Snoop datalink type, such as SNOOP_DATALINK_TYPE_XX
* autosync whether do file_sync when snoop_dump
*
* Returned Value:
* OK on success; Negated errno on failure.
*
* Assumptions:
*
****************************************************************************/ ****************************************************************************/
int snoop_open(FAR struct snoop_s *snoop, FAR const char *filename, int snoop_open(FAR struct snoop_s *snoop, FAR const char *filename,
@@ -268,7 +331,7 @@ int snoop_open(FAR struct snoop_s *snoop, FAR const char *filename,
case SNOOP_DATALINK_TYPE_FDDI: case SNOOP_DATALINK_TYPE_FDDI:
case SNOOP_DATALINK_TYPE_OTHER: case SNOOP_DATALINK_TYPE_OTHER:
{ {
uint8_t snoop_magic[] = static const uint8_t snoop_magic[] =
{ {
's', 'n', 'o', 'o', 'p', '\0', '\0', '\0' 's', 'n', 'o', 'o', 'p', '\0', '\0', '\0'
}; };
@@ -283,7 +346,7 @@ int snoop_open(FAR struct snoop_s *snoop, FAR const char *filename,
case SNOOP_DATALINK_HCI_BSCP: case SNOOP_DATALINK_HCI_BSCP:
case SNOOP_DATALINK_HCI_SERIAL: case SNOOP_DATALINK_HCI_SERIAL:
{ {
uint8_t btsnoop_magic[] = static const uint8_t btsnoop_magic[] =
{ {
'b', 't', 's', 'n', 'o', 'o', 'p', '\0' 'b', 't', 's', 'n', 'o', 'o', 'p', '\0'
}; };
@@ -307,8 +370,9 @@ int snoop_open(FAR struct snoop_s *snoop, FAR const char *filename,
snoop->datalink = datalink; snoop->datalink = datalink;
snoop->autosync = autosync; snoop->autosync = autosync;
header.datalink = htobe32(datalink); snoop->next = 0;
header.datalink = htobe32(datalink);
ret = file_write(&snoop->filep, &header, sizeof(header)); ret = file_write(&snoop->filep, &header, sizeof(header));
if (ret != sizeof(header)) if (ret != sizeof(header))
{ {
@@ -316,10 +380,11 @@ int snoop_open(FAR struct snoop_s *snoop, FAR const char *filename,
goto error; goto error;
} }
nxmutex_init(&snoop->mutex);
return OK; return OK;
error: error:
file_close(&snoop->filep); snoop_close(snoop);
return ret; return ret;
} }
@@ -329,31 +394,93 @@ error:
* Description: * Description:
* This function dump nbytes buf data into snoop file. * This function dump nbytes buf data into snoop file.
* *
* Input Parameters:
* snoop The snoop driver struct
* buf Snoop buffer
* nbytes Snoop buffer size
* drops cumulative number of dropped packets
* flags Packet Flags: 1 hci cmd , eg: btsnoop
*
* Returned Value:
* OK on success; Negated errno on failure.
*
* Assumptions:
*
****************************************************************************/ ****************************************************************************/
int snoop_dump(FAR struct snoop_s *snoop, FAR const void *buf, int snoop_dump(FAR struct snoop_s *snoop, FAR const void *buf,
uint32_t nbytes, uint32_t drops, uint32_t flags) uint32_t nbytes, uint32_t drops, uint32_t flags)
{ {
int ret; struct snoop_packet_header_s header;
irqstate_t irqflags;
int ret = 0;
if (!snoop) if (!snoop)
{ {
return -EINVAL; return -EINVAL;
} }
ret = snoop_dump_packet_header(snoop, nbytes, drops, flags); snoop_fill_packet_header(snoop, nbytes, drops, flags, &header);
if (ret != OK)
irqflags = enter_critical_section();
if (up_interrupt_context())
{ {
return ret; if (sizeof(snoop->buf) - snoop->next <
nbytes + sizeof(struct snoop_packet_header_s))
{
ret = -ENOMEM;
goto out_leave;
}
memcpy(snoop->buf + snoop->next, &header, sizeof(header));
snoop->next += sizeof(header);
memcpy(snoop->buf + snoop->next, buf, nbytes);
snoop->next += nbytes;
if (work_available(&snoop->work))
{
work_queue(HPWORK, &snoop->work, snoop_flush_work, snoop, 0);
}
goto out_leave;
}
else
{
nxmutex_lock(&snoop->mutex);
ret = snoop_flush(snoop);
if (ret < 0)
{
goto out_unlock;
}
ret = file_write(&snoop->filep, &header, sizeof(header));
if (ret < 0)
{
goto out_unlock;
}
else if (ret != sizeof(header))
{
ret = -EINVAL;
goto out_unlock;
}
ret = file_write(&snoop->filep, buf, nbytes);
if (ret < 0)
{
goto out_unlock;
}
else if (ret != nbytes)
{
ret = -EINVAL;
goto out_unlock;
}
} }
ret = file_write(&snoop->filep, buf, nbytes); out_unlock:
if (ret != nbytes) nxmutex_unlock(&snoop->mutex);
{ out_leave:
return ret < 0 ? ret : -EINVAL; leave_critical_section(irqflags);
} return ret;
return snoop->autosync ? snoop_sync(snoop) : OK;
} }
/**************************************************************************** /****************************************************************************
@@ -362,21 +489,24 @@ int snoop_dump(FAR struct snoop_s *snoop, FAR const void *buf,
* Description: * Description:
* This function sync snoop buffer. * This function sync snoop buffer.
* *
* Input Parameters:
* snoop The snoop driver struct
*
* Returned Value:
* OK on success; Negated errno on failure.
*
* Assumptions:
*
****************************************************************************/ ****************************************************************************/
int snoop_sync(FAR struct snoop_s *snoop) int snoop_sync(FAR struct snoop_s *snoop)
{ {
int ret = OK;
if (!snoop) if (!snoop)
{ {
return -EINVAL; return -EINVAL;
} }
#ifndef CONFIG_DISABLE_MOUNTPOINT return snoop_flush_lock(snoop);
ret = file_fsync(&snoop->filep);
#endif
return ret;
} }
/**************************************************************************** /****************************************************************************
@@ -385,6 +515,14 @@ int snoop_sync(FAR struct snoop_s *snoop)
* Description: * Description:
* This function close snoop file. * This function close snoop file.
* *
* Input Parameters:
* snoop The snoop driver struct
*
* Returned Value:
* OK on success; Negated errno on failure.
*
* Assumptions:
*
****************************************************************************/ ****************************************************************************/
int snoop_close(FAR struct snoop_s *snoop) int snoop_close(FAR struct snoop_s *snoop)
@@ -394,5 +532,6 @@ int snoop_close(FAR struct snoop_s *snoop)
return -EINVAL; return -EINVAL;
} }
nxmutex_destroy(&snoop->mutex);
return file_close(&snoop->filep); return file_close(&snoop->filep);
} }