}
void
-socket_changed(sock *s)
+socket_changed(struct birdsock *s, bool recalculate_sk_info)
{
struct birdloop *loop = s->loop;
ASSERT_DIE(birdloop_inside(loop));
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
s->loop = loop;
s->index = -1;
- socket_changed(s);
+ socket_changed(s, true);
}
extern sock *stored_sock; /* mainloop hack */
rem_node(&s->n);
loop->sock_num--;
- socket_changed(s);
+ socket_changed(s, true);
s->loop = NULL;
s->index = -1;
{
ASSERT_DIE(birdloop_inside(loop));
s->rx_hook = NULL;
- socket_changed(s);
+ socket_changed(s, false);
}
void
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)
UNLOCK_DOMAIN(control, sync->lock);
}
-
struct bird_thread_show_data {
struct bird_thread_syncer sync;
cli *cli;
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;
dump_to_file_flush(req);
}
+ if (req->fd < 0)
+ return;
+
bug("Too long dump call");
}
sk_alloc_bufs(s);
}
-static void
+void
sk_dump(struct dump_request *dreq, resource *r)
{
sock *s = (sock *) 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),
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;
}
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
*/