This is an automated email from the ASF dual-hosted git repository. xiaoxiang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push: new f864e5f657 wireless/bluetooth: add interrupt_context hander for netsnoop f864e5f657 is described below commit f864e5f6577b349396eb586a80d35e2c87a2c7ae Author: chengkai <cheng...@xiaomi.com> AuthorDate: Sun Sep 4 18:26:59 2022 +0800 wireless/bluetooth: add interrupt_context hander for netsnoop Signed-off-by: chengkai <cheng...@xiaomi.com> --- drivers/wireless/bluetooth/bt_bridge.c | 7 +- include/nuttx/net/snoop.h | 55 ++++++- net/utils/Kconfig | 4 + net/utils/net_snoop.c | 275 +++++++++++++++++++++++++-------- 4 files changed, 265 insertions(+), 76 deletions(-) diff --git a/drivers/wireless/bluetooth/bt_bridge.c b/drivers/wireless/bluetooth/bt_bridge.c index 9ef41c06b4..b28138ecde 100644 --- a/drivers/wireless/bluetooth/bt_bridge.c +++ b/drivers/wireless/bluetooth/bt_bridge.c @@ -424,17 +424,14 @@ static int bt_bridge_send(FAR struct bt_driver_s *drv, flags = enter_critical_section(); if (bt_filter_can_send(&device->filter, type, data, len)) { - int ret; - leave_critical_section(flags); - ret = driver->send(driver, type, data, len); - #ifdef CONFIG_BLUETOOTH_BRIDGE_BTSNOOP snoop_dump(bridge->snoop, data - drv->head_reserve, len + drv->head_reserve, 0, SNOOP_DIRECTION_FLAG_SENT); #endif /* CONFIG_BLUETOOTH_BRIDGE_BTSNOOP */ - return ret; + + return driver->send(driver, type, data, len); } leave_critical_section(flags); diff --git a/include/nuttx/net/snoop.h b/include/nuttx/net/snoop.h index b234032ffb..a8aa0165d0 100644 --- a/include/nuttx/net/snoop.h +++ b/include/nuttx/net/snoop.h @@ -27,6 +27,9 @@ #include <stdint.h> +#include <nuttx/mutex.h> +#include <nuttx/wqueue.h> + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -81,11 +84,18 @@ #define SNOOP_DIRECTION_FLAG_SENT 0 /* Direction flag 0 = Sent */ #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 { - bool autosync; - uint32_t datalink; - struct file filep; + bool autosync; + uint32_t datalink; + 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: * 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, @@ -117,6 +138,18 @@ int snoop_open(FAR struct snoop_s *snoop, FAR const char *filename, * Description: * 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, @@ -128,6 +161,14 @@ int snoop_dump(FAR struct snoop_s *snoop, FAR const void *buf, * Description: * 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); @@ -138,6 +179,14 @@ int snoop_sync(FAR struct snoop_s *snoop); * Description: * 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); diff --git a/net/utils/Kconfig b/net/utils/Kconfig index b8d1a0484c..6e55134dd9 100644 --- a/net/utils/Kconfig +++ b/net/utils/Kconfig @@ -24,3 +24,7 @@ config NET_ARCH_CHKSUM 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 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 diff --git a/net/utils/net_snoop.c b/net/utils/net_snoop.c index 75caa9c1d0..6e1541c0a4 100644 --- a/net/utils/net_snoop.c +++ b/net/utils/net_snoop.c @@ -161,76 +161,128 @@ begin_packed_struct struct snoop_packet_header_s ****************************************************************************/ /**************************************************************************** - * Name: snoop_dump_packet_header + * Name: snoop_fill_packet_header * * 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, - uint32_t bytes, uint32_t drops, - uint32_t flags) +static void snoop_fill_packet_header(FAR struct snoop_s *snoop, + uint32_t bytes, uint32_t drops, + uint32_t flags, FAR struct + snoop_packet_header_s *header) { - struct snoop_packet_header_s header; - int ret; - - if (!snoop) - { - return -EINVAL; - } + struct timeval tv; switch (snoop->datalink) { - case SNOOP_DATALINK_HCI_UNENCAP: - case SNOOP_DATALINK_HCI_UART: - case SNOOP_DATALINK_HCI_BSCP: - case SNOOP_DATALINK_HCI_SERIAL: - { - struct timeval tv; - + case SNOOP_DATALINK_HCI_UNENCAP: + case SNOOP_DATALINK_HCI_UART: + case SNOOP_DATALINK_HCI_BSCP: + case SNOOP_DATALINK_HCI_SERIAL: gettimeofday(&tv, NULL); - header.ts_usec = htobe64(SNOOP_EPOCH_USEC(tv)); - header.flags = htobe32(flags); + header->ts_usec = htobe64(SNOOP_EPOCH_USEC(tv)); + header->flags = htobe32(flags); 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); - header.ts.ts_sec = htobe32(tv.tv_sec); - header.ts.ts_usec = htobe32(tv.tv_usec); - header.rec_len = htobe32(flags); + header->ts.ts_sec = htobe32(tv.tv_sec); + header->ts.ts_usec = htobe32(tv.tv_usec); + header->rec_len = htobe32(flags); break; - } - default: - { - return -EINVAL; - } + default: + DEBUGASSERT(false); } - header.orig_len = htobe32(bytes); - header.incl_len = htobe32(bytes); - header.cum_drops = htobe32(drops); + header->orig_len = htobe32(bytes); + header->incl_len = htobe32(bytes); + 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: * 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, @@ -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_OTHER: { - uint8_t snoop_magic[] = + static const uint8_t snoop_magic[] = { '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_SERIAL: { - uint8_t btsnoop_magic[] = + static const uint8_t btsnoop_magic[] = { '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->autosync = autosync; - header.datalink = htobe32(datalink); + snoop->next = 0; + header.datalink = htobe32(datalink); ret = file_write(&snoop->filep, &header, sizeof(header)); if (ret != sizeof(header)) { @@ -316,10 +380,11 @@ int snoop_open(FAR struct snoop_s *snoop, FAR const char *filename, goto error; } + nxmutex_init(&snoop->mutex); return OK; error: - file_close(&snoop->filep); + snoop_close(snoop); return ret; } @@ -329,31 +394,93 @@ error: * Description: * 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, 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) { return -EINVAL; } - ret = snoop_dump_packet_header(snoop, nbytes, drops, flags); - if (ret != OK) + snoop_fill_packet_header(snoop, nbytes, drops, flags, &header); + + 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; + } - ret = file_write(&snoop->filep, buf, nbytes); - if (ret != nbytes) + 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 { - return ret < 0 ? ret : -EINVAL; + 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; + } } - return snoop->autosync ? snoop_sync(snoop) : OK; +out_unlock: + nxmutex_unlock(&snoop->mutex); +out_leave: + leave_critical_section(irqflags); + return ret; } /**************************************************************************** @@ -362,21 +489,24 @@ int snoop_dump(FAR struct snoop_s *snoop, FAR const void *buf, * Description: * 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 ret = OK; - if (!snoop) { return -EINVAL; } -#ifndef CONFIG_DISABLE_MOUNTPOINT - ret = file_fsync(&snoop->filep); -#endif - return ret; + return snoop_flush_lock(snoop); } /**************************************************************************** @@ -385,6 +515,14 @@ int snoop_sync(FAR struct snoop_s *snoop) * Description: * 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) @@ -394,5 +532,6 @@ int snoop_close(FAR struct snoop_s *snoop) return -EINVAL; } + nxmutex_destroy(&snoop->mutex); return file_close(&snoop->filep); }