You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2023/01/10 10:08:28 UTC

[nuttx] branch master updated: wireless/bluetooth: add interrupt_context hander for netsnoop

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 <ch...@xiaomi.com>
AuthorDate: Sun Sep 4 18:26:59 2022 +0800

    wireless/bluetooth: add interrupt_context hander for netsnoop
    
    Signed-off-by: chengkai <ch...@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);
 }