From: Katerina Kubecova Date: Thu, 3 Apr 2025 14:54:16 +0000 (+0200) Subject: io-loop.h: Fixup sk_dump all X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e125302653b9640b2739536acf660d082f9ea477;p=thirdparty%2Fbird.git io-loop.h: Fixup sk_dump all 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. --- diff --git a/sysdep/unix/io-loop.c b/sysdep/unix/io-loop.c index 3be4a4ef6..8f3053fb4 100644 --- a/sysdep/unix/io-loop.c +++ b/sysdep/unix/io-loop.c @@ -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; diff --git a/sysdep/unix/io-loop.h b/sysdep/unix/io-loop.h index 6681f4d6d..712345667 100644 --- a/sysdep/unix/io-loop.h +++ b/sysdep/unix/io-loop.h @@ -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; diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c index 5b9c2e0e6..aa4325662 100644 --- a/sysdep/unix/io.c +++ b/sysdep/unix/io.c @@ -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 */