]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
io-loop.h: Fixup sk_dump all
authorKaterina Kubecova <katerina.kubecova@nic.cz>
Thu, 3 Apr 2025 14:54:16 +0000 (16:54 +0200)
committerKaterina Kubecova <katerina.kubecova@nic.cz>
Mon, 14 Apr 2025 13:27:39 +0000 (15:27 +0200)
Only sockets in main birdloop were dumped. Now, all sockets are dumped.
Because of serilization problems, socket dump is cached for each birdloop
and it is couninuously updated.

sysdep/unix/io-loop.c
sysdep/unix/io-loop.h
sysdep/unix/io.c

index 3be4a4ef6372fd16da6a929a47ba48a48f8dc817..8f3053fb4e66317d5601f1cb19a2278b18ef5fc4 100644 (file)
@@ -392,7 +392,7 @@ sockets_init(struct birdloop *loop)
 }
 
 void
-socket_changed(sock *s)
+socket_changed(struct birdsock *s, bool recalculate_sk_info)
 {
   struct birdloop *loop = s->loop;
   ASSERT_DIE(birdloop_inside(loop));
@@ -400,6 +400,38 @@ socket_changed(sock *s)
   LOOP_TRACE(loop, DL_SOCKETS, "socket %p changed", s);
   loop->sock_changed = 1;
   birdloop_ping(loop);
+
+  if (loop != &main_birdloop && recalculate_sk_info)
+  {
+    int size = loop->sock_num * sk_max_dump_len() + 17;
+    char *new_info = mb_alloc(loop->pool, size);
+
+    node *n;
+    buffer buf = {
+      .start = new_info,
+      .pos = new_info,
+      .end = new_info + size,
+    };
+
+    buffer_print(&buf, "%p ", s);
+
+    WALK_LIST(n, loop->sock_list)
+    {
+      SKIP_BACK_DECLARE(sock, s, n, n);
+      sk_dump_to_buffer(&buf, s);
+    }
+    buf.pos[0] = '\0';
+
+    char *old_info = NULL;
+    if (loop->sockets_info)
+      old_info = atomic_load_explicit(&loop->sockets_info, memory_order_relaxed);
+    atomic_store_explicit(&loop->sockets_info, new_info, memory_order_relaxed);
+
+    synchronize_rcu();
+
+    if (old_info)
+      mb_free(old_info);
+  }
 }
 
 void
@@ -415,7 +447,7 @@ birdloop_add_socket(struct birdloop *loop, sock *s)
   s->loop = loop;
   s->index = -1;
 
-  socket_changed(s);
+  socket_changed(s, true);
 }
 
 extern sock *stored_sock; /* mainloop hack */
@@ -443,7 +475,7 @@ birdloop_remove_socket(struct birdloop *loop, sock *s)
   rem_node(&s->n);
   loop->sock_num--;
 
-  socket_changed(s);
+  socket_changed(s, true);
 
   s->loop = NULL;
   s->index = -1;
@@ -467,7 +499,7 @@ sk_pause_rx(struct birdloop *loop, sock *s)
 {
   ASSERT_DIE(birdloop_inside(loop));
   s->rx_hook = NULL;
-  socket_changed(s);
+  socket_changed(s, false);
 }
 
 void
@@ -476,7 +508,7 @@ sk_resume_rx(struct birdloop *loop, sock *s, int (*hook)(sock *, uint))
   ASSERT_DIE(birdloop_inside(loop));
   ASSERT_DIE(hook);
   s->rx_hook = hook;
-  socket_changed(s);
+  socket_changed(s, false);
 }
 
 static inline uint sk_want_events(sock *s)
@@ -1511,7 +1543,6 @@ bird_thread_sync_all(struct bird_thread_syncer *sync,
   UNLOCK_DOMAIN(control, sync->lock);
 }
 
-
 struct bird_thread_show_data {
   struct bird_thread_syncer sync;
   cli *cli;
@@ -1671,6 +1702,111 @@ cmd_show_threads(int show_loops)
   bird_thread_sync_all(&tsd->sync, bird_thread_show, cmd_show_threads_done, "Show Threads");
 }
 
+struct bird_thread_show_socket {
+  struct bird_thread_syncer sync;
+  struct dump_request *dreq;
+};
+
+void
+sk_dump_all(struct dump_request *dreq)
+{
+  RDUMP("Open sockets:\n");
+  dreq->indent += 3;
+
+  node *n;
+  sock *s;
+
+  /* Dump sockets in main_birdloop */
+  WALK_LIST(n, main_birdloop.sock_list)
+  {
+    s = SKIP_BACK(sock, n, n);
+    RDUMP("%p ", s);
+    sk_dump(dreq, &s->r);
+  }
+
+  /* The rest of birdloops have the socket info cached */
+  WALK_TLIST(thread_group, gpub, &global_thread_group_list)
+    TG_LOCKED(gpub, group)
+      WALK_TLIST(thread, thr, &group->threads)
+        WALK_TLIST(birdloop, loop, &thr->loops)
+        {
+          rcu_read_lock();
+            char *info = atomic_load_explicit(&loop->sockets_info, memory_order_relaxed);
+          rcu_read_unlock();
+          if (info)
+            RDUMP(info);
+        }
+
+  WALK_TLIST_DELSAFE(thread_group, gpub, &global_thread_group_list)
+  TG_LOCKED(gpub, group)
+  {
+    WALK_TLIST_DELSAFE(birdloop, loop, &group->loops){
+      rcu_read_lock();
+        char *info = atomic_load_explicit(&loop->sockets_info, memory_order_relaxed);
+      rcu_read_unlock();
+      if (info)
+        RDUMP(info);
+    }
+  }
+  dreq->indent -= 3;
+  RDUMP("\n");
+}
+
+static void
+_sk_dump_ao_for_thread(struct dump_request *dreq, list sock_list)
+{
+  WALK_LIST_(node, n, sock_list)
+  {
+    sock *s = SKIP_BACK(sock, n, n);
+
+    /* Skip non TCP-AO sockets / not supported */
+    if (sk_get_ao_info(s, &(struct ao_info){}) < 0)
+      continue;
+
+    RDUMP("\n%p", s);
+    sk_dump(dreq, &s->r);
+    sk_dump_ao_info(s, dreq);
+    sk_dump_ao_keys(s, dreq);
+  }
+}
+
+static void
+sk_dump_ao_for_thread(struct bird_thread_syncer *sync)
+{
+  SKIP_BACK_DECLARE(struct bird_thread_show_socket, tss, sync, sync);
+  struct dump_request *dreq = tss->dreq;
+
+  WALK_TLIST(birdloop, loop, &this_thread->loops)
+  {
+    birdloop_enter(loop);
+    _sk_dump_ao_for_thread(dreq, loop->sock_list);
+    birdloop_leave(loop);
+  }
+}
+
+void
+sk_dump_ao_all(struct dump_request *dreq)
+{
+  struct bird_thread_show_socket *tss = mb_allocz(&root_pool, sizeof(struct bird_thread_show_socket));
+  tss->dreq = dreq;
+
+  RDUMP("TCP-AO listening sockets:\n");
+  _sk_dump_ao_for_thread(dreq, main_birdloop.sock_list);
+
+  WALK_TLIST(thread_group, gpub, &global_thread_group_list)
+  TG_LOCKED(gpub, group)
+  {
+    WALK_TLIST(birdloop, loop, &group->loops)
+    {
+      birdloop_enter(loop);
+      _sk_dump_ao_for_thread(dreq, loop->sock_list);
+      birdloop_leave(loop);
+    }
+  }
+  bird_thread_sync_all(&tss->sync, sk_dump_ao_for_thread, NULL, "Show ao sockets");
+}
+
+
 bool task_still_in_limit(void)
 {
   static u64 main_counter = 0;
index 6681f4d6d591370a3606a3a3020887222dbf9dc7..7123456671437a7d2ddbf0f2a25677c45740c5a2 100644 (file)
@@ -21,13 +21,16 @@ struct pfd {
   BUFFER(struct birdloop *) loop;
 };
 
+uint sk_max_dump_len(void);
+void sk_dump_to_buffer(buffer *buf, sock *s);
 void sockets_prepare(struct birdloop *, struct pfd *);
-void socket_changed(struct birdsock *);
+void socket_changed(struct birdsock *, bool recalculate_sk_info);
 
 void pipe_new(struct pipe *);
 void pipe_pollin(struct pipe *, struct pfd *);
 void pipe_drain(struct pipe *);
 void pipe_kick(struct pipe *);
+void sk_dump(struct dump_request *dreq, resource *r);
 
 #define TIME_BY_SEC_SIZE       16
 
@@ -58,6 +61,7 @@ struct birdloop
   struct birdsock *sock_active;
   int sock_num;
   uint sock_changed:1;
+  char *_Atomic sockets_info;
 
   uint ping_pending;
 
index 5b9c2e0e636d8dcbbba93f00887f288cffb99b38..aa43256625eeb3546be9c9a6b369072f76410246 100644 (file)
@@ -348,6 +348,9 @@ dump_to_file_write(struct dump_request *dr, const char *fmt, ...)
       dump_to_file_flush(req);
   }
 
+  if (req->fd < 0)
+    return;
+
   bug("Too long dump call");
 }
 
@@ -1212,7 +1215,7 @@ sk_reallocate(sock *s)
   sk_alloc_bufs(s);
 }
 
-static void
+void
 sk_dump(struct dump_request *dreq, resource *r)
 {
   sock *s = (sock *) r;
@@ -1230,6 +1233,36 @@ sk_dump(struct dump_request *dreq, resource *r)
        s->iface ? s->iface->name : "none");
 }
 
+uint
+sk_max_dump_len(void)
+{
+  uint ret = strlen("(%s, ud=%p, sa=%I, sp=%d, da=%I, dp=%d, tos=%d, ttl=%d, if=%s)\n");
+  ret += 3; // max sk_type_name = 5
+  ret += 14; // looks like %p size is 16
+  ret += (IP6_MAX_TEXT_LENGTH -2) * 2;
+  ret += 14 * 4; // %d
+  ret += IFNAMSIZ - 2;
+  ret++; // terminating zero
+  return ret;
+}
+
+void
+sk_dump_to_buffer(buffer *buf, sock *s)
+{
+  static char *sk_type_names[] = { "TCP<", "TCP>", "TCP", "UDP", NULL, "IP", NULL, "MAGIC", "UNIX<", "UNIX", "SSH>", "SSH", "DEL!" };
+
+  buffer_print(buf, "(%s, ud=%p, sa=%I, sp=%d, da=%I, dp=%d, tos=%d, ttl=%d, if=%s)\n",
+       sk_type_names[s->type],
+       s->data,
+       s->saddr,
+       s->sport,
+       s->daddr,
+       s->dport,
+       s->tos,
+       s->ttl,
+       s->iface ? s->iface->name : "none");
+}
+
 static struct resclass sk_class = {
   "Socket",
   sizeof(sock),
@@ -2158,7 +2191,7 @@ sk_send(sock *s, unsigned len)
 
   int e = sk_maybe_write(s);
   if (e == 0) /* Trigger thread poll reload to poll this socket's write. */
-    socket_changed(s);
+    socket_changed(s, false);
 
   return e;
 }
@@ -2407,48 +2440,6 @@ sk_err(sock *s, int revents)
   tmp_flush();
 }
 
-
-/* FIXME: these two functions should actually call bird_thread_sync_all()
- * to get threads from all loops. Now they dump just mainloop. */
-
-void
-sk_dump_all(struct dump_request *dreq)
-{
-  node *n;
-  sock *s;
-
-  RDUMP("Open sockets:\n");
-  dreq->indent += 3;
-  WALK_LIST(n, main_birdloop.sock_list)
-  {
-    s = SKIP_BACK(sock, n, n);
-    RDUMP("%p ", s);
-    sk_dump(dreq, &s->r);
-  }
-  dreq->indent -= 3;
-  RDUMP("\n");
-}
-
-void
-sk_dump_ao_all(struct dump_request *dreq)
-{
-  RDUMP("TCP-AO listening sockets:\n");
-  WALK_LIST_(node, n, main_birdloop.sock_list)
-  {
-    sock *s = SKIP_BACK(sock, n, n);
-
-    /* Skip non TCP-AO sockets / not supported */
-    if (sk_get_ao_info(s, &(struct ao_info){}) < 0)
-      continue;
-
-    RDUMP("\n%p", s);
-    sk_dump(dreq, &s->r);
-    sk_dump_ao_info(s, dreq);
-    sk_dump_ao_keys(s, dreq);
-  }
-}
-
-
 /*
  *     Internal event log and watchdog
  */