]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
TMP/CLI: show proto rework to not lock all protocols wip-show-proto-no-lock
authorMaria Matejka <mq@ucw.cz>
Tue, 15 Oct 2024 09:32:48 +0000 (11:32 +0200)
committerKaterina Kubecova <katerina.kubecova@nic.cz>
Wed, 23 Oct 2024 13:00:43 +0000 (15:00 +0200)
nest/config.Y
nest/proto.c
nest/protocol.h
proto/ospf/ospf.c
proto/radv/radv.c
proto/rip/rip.c
proto/static/static.c
sysdep/unix/krt.c

index a0a10daf43c54d2bc012f5bfe97976568a826faf..6b9f6e947ebbee66eade0e48dcf69cdebd27f7c1 100644 (file)
@@ -692,10 +692,10 @@ CF_CLI(SHOW MEMORY,,, [[Show memory usage]])
 { cmd_show_memory(); } ;
 
 CF_CLI(SHOW PROTOCOLS, proto_patt2, [<protocol> | \"<pattern>\"], [[Show routing protocols]])
-{ proto_apply_cmd($3, proto_cmd_show, 0, 0); } ;
+{ proto_apply_cmd_no_lock($3, proto_cmd_show, 0, (union cmd_arg){.verbose  = 0}); } ;
 
 CF_CLI(SHOW PROTOCOLS ALL, proto_patt2, [<protocol> | \"<pattern>\"], [[Show routing protocol details]])
-{ proto_apply_cmd($4, proto_cmd_show, 0, 1); } ;
+{ proto_apply_cmd_no_lock($4, proto_cmd_show, 0, (union cmd_arg){.verbose  = 1}); } ;
 
 optproto:
    CF_SYM_KNOWN { cf_assert_symbol($1, SYM_PROTO); $$ = $1; }
index ed365a56bdefd03bf672a7b3138f7cb8c4c1afba..f79a626c2da7405e743e23a2d8effa910298a133 100644 (file)
@@ -293,6 +293,19 @@ proto_add_channel(struct proto *p, struct channel_config *cf)
   return c;
 }
 
+struct channel *
+proto_add_main_channel(struct proto *p, struct channel_config *cf)
+{
+  p->main_channel = proto_add_channel(p, cf);
+  ea_list *eal;
+
+  eal = p->ea_state;
+  ea_set_attr(&eal, EA_LITERAL_EMBEDDED(&ea_main_table_id, 0, p->main_channel->table->id));
+  proto_announce_state(p, eal);
+
+  return p->main_channel;
+}
+
 void
 proto_remove_channel(struct proto *p UNUSED, struct channel *c)
 {
@@ -2089,6 +2102,7 @@ extern void bfd_init_all(void);
 
 void protos_build_gen(void);
 
+
 /**
  * protos_build - build a protocol list
  *
@@ -2488,6 +2502,19 @@ proto_state_name(struct proto *p)
   }
 }
 
+static char *
+proto_state_name_from_int(int state)
+{
+  switch (state)
+  {
+  case PS_DOWN:                return "flush or down";
+  case PS_START:       return "start";
+  case PS_UP:          return "up";
+  case PS_STOP:                return "stop";
+  default:             return "???";
+  }
+}
+
 static void
 channel_show_stats(struct channel *c)
 {
@@ -2581,7 +2608,7 @@ channel_cmd_debug(struct channel *c, uint mask)
 }
 
 void
-proto_cmd_show(struct proto *p, uintptr_t verbose, int cnt)
+proto_cmd_show(struct proto *p, union cmd_arg verbose, int cnt)
 {
   byte buf[256], tbuf[TM_DATETIME_BUFFER_SIZE];
 
@@ -2590,23 +2617,37 @@ proto_cmd_show(struct proto *p, uintptr_t verbose, int cnt)
     cli_msg(-2002, "%-10s %-10s %-10s %-6s %-12s  %s",
            "Name", "Proto", "Table", "State", "Since", "Info");
 
-  buf[0] = 0;
-  if (p->proto->get_status)
-    p->proto->get_status(p, buf);
-
-  rcu_read_lock();
-  tm_format_time(tbuf, &atomic_load_explicit(&global_runtime, memory_order_acquire)->tf_proto, p->last_state_change);
-  rcu_read_unlock();
-  cli_msg(-1002, "%-10s %-10s %-10s %-6s %-12s  %s",
-         p->name,
-         p->proto->name,
-         p->main_channel ? p->main_channel->table->name : "---",
-         proto_state_name(p),
-         tbuf,
-         buf);
-
-  if (verbose)
+  PST_LOCKED(ts)
   {
+    ea_list *eal = ts->states[p->id];
+
+    const char *name = ea_get_adata(eal, &ea_name)->data;
+    struct protocol *proto = (struct protocol *) ea_get_ptr(eal, &ea_protocol_type, 0);
+    const int state  = ea_get_int(eal, &ea_state, 0);
+    ea_list *chan_ea = ts->channels[ea_get_int(eal, &ea_main_table_id, 0)];
+    const char *table = ea_get_adata(chan_ea, &ea_name)->data;
+    buf[0] = 0;
+    if (p->proto->get_status)
+    {
+      PROTO_LOCKED_FROM_MAIN(p)
+        p->proto->get_status(p, buf);
+    }
+    const btime *time = (btime *)ea_get_adata(eal, &ea_last_modified)->data;
+    tm_format_time(tbuf, &atomic_load_explicit(&global_runtime, memory_order_acquire)->tf_proto, *time);
+
+    cli_msg(-1002, "%-10s %-10s %-10s %-6s %-12s  %s",
+           name,
+           proto->name,
+           table ? table : "---",
+           proto_state_name_from_int(state),
+           tbuf,
+           buf);
+       }
+
+  if (verbose.verbose)
+  {
+    PROTO_LOCKED_FROM_MAIN(p)
+    {
     if (p->cf->dsc)
       cli_msg(-1006, "  Description:    %s", p->cf->dsc);
     if (p->message)
@@ -2626,6 +2667,7 @@ proto_cmd_show(struct proto *p, uintptr_t verbose, int cnt)
     }
 
     cli_msg(-1006, "");
+    }
   }
 }
 
@@ -2828,6 +2870,46 @@ proto_apply_cmd(struct proto_spec ps, void (* cmd)(struct proto *, uintptr_t, in
     proto_apply_cmd_symbol(ps.ptr, cmd, arg);
 }
 
+void
+proto_apply_cmd_no_lock(struct proto_spec ps, void (* cmd)(struct proto *, union cmd_arg, int),
+               int restricted, union cmd_arg arg)
+{
+  if (restricted && cli_access_restricted())
+    return;
+
+  if (ps.patt)
+  {
+    int cnt = 0;
+    const char *patt = ps.ptr;
+
+    WALK_TLIST(proto, p, &global_proto_list)
+    if (!patt || patmatch(patt, p->name))
+         cmd(p, arg, cnt++);
+
+    if (!cnt)
+      cli_msg(8003, "No protocols match");
+    else
+    cli_msg(0, "");
+  }
+  else
+  {
+    const struct symbol *s = ps.ptr;
+    if (s->class != SYM_PROTO)
+    {
+      cli_msg(9002, "%s is not a protocol", s->name);
+      return;
+    }
+    if (s->proto->proto)
+    {
+      struct proto *p = s->proto->proto;
+      cmd(p, arg, 0);
+      cli_msg(0, "");
+    }
+    else
+      cli_msg(9002, "%s does not exist", s->name);
+  }
+}
+
 struct proto *
 proto_get_named(struct symbol *sym, struct protocol *pr)
 {
index b6ba200fdb3caa57ac62deec851fa92b27be724c..8f9723d90fdaecde2eed1d1cb547f94b51dfdbdf 100644 (file)
@@ -262,7 +262,13 @@ void channel_show_limit(struct limit *l, const char *dsc, int active, int action
 void channel_show_info(struct channel *c);
 void channel_cmd_debug(struct channel *c, uint mask);
 
-void proto_cmd_show(struct proto *, uintptr_t, int);
+union cmd_arg {
+  int verbose;
+  struct proto_reload_request *prr;
+  char *msg;
+};
+
+void proto_cmd_show(struct proto *, union cmd_arg verbose, int);
 void proto_cmd_disable(struct proto *, uintptr_t, int);
 void proto_cmd_enable(struct proto *, uintptr_t, int);
 void proto_cmd_restart(struct proto *, uintptr_t, int);
@@ -271,6 +277,7 @@ void proto_cmd_debug(struct proto *, uintptr_t, int);
 void proto_cmd_mrtdump(struct proto *, uintptr_t, int);
 
 void proto_apply_cmd(struct proto_spec ps, void (* cmd)(struct proto *, uintptr_t, int), int restricted, uintptr_t arg);
+void proto_apply_cmd_no_lock(struct proto_spec ps, void (* cmd)(struct proto *, union cmd_arg, int), int restricted, union cmd_arg arg);
 struct proto *proto_get_named(struct symbol *, struct protocol *);
 struct proto *proto_iterate_named(struct symbol *sym, struct protocol *proto, struct proto *old);
 
@@ -714,6 +721,7 @@ static inline struct channel_config *proto_cf_mpls_channel(struct proto_config *
 struct channel *proto_find_channel_by_table(struct proto *p, rtable *t);
 struct channel *proto_find_channel_by_name(struct proto *p, const char *n);
 struct channel *proto_add_channel(struct proto *p, struct channel_config *cf);
+struct channel *proto_add_main_channel(struct proto *p, struct channel_config *cf);
 void proto_remove_channel(struct proto *p, struct channel *c);
 int proto_configure_channel(struct proto *p, struct channel **c, struct channel_config *cf);
 
index 7c6492145c867fae37a436b51d9f9364d902445b..0077ff4845e02f65b333dcdae18741e211aed6f4 100644 (file)
@@ -368,7 +368,7 @@ ospf_init(struct proto_config *CF)
   struct ospf_config *cf = (struct ospf_config *) CF;
   struct proto *P = proto_new(CF);
 
-  P->main_channel = proto_add_channel(P, proto_cf_main_channel(CF));
+  proto_add_main_channel(P, proto_cf_main_channel(CF));
 
   P->rt_notify = ospf_rt_notify;
   P->iface_sub.if_notify = ospf_if_notify;
index ea0b8d383a5b6e94e75b3599c6205af97fbc41af..5ee4ca0389cda9e5520d2a6c9f159d677a99928b 100644 (file)
@@ -579,7 +579,7 @@ radv_init(struct proto_config *CF)
 {
   struct proto *P = proto_new(CF);
 
-  P->main_channel = proto_add_channel(P, proto_cf_main_channel(CF));
+  proto_add_main_channel(P, proto_cf_main_channel(CF));
 
   P->preexport = radv_preexport;
   P->rt_notify = radv_rt_notify;
index 1d4e6cf5c59f153d409c492fcd63d7d9e02f24a8..a4727018216788970424a26df4c2abb37ae5556b 100644 (file)
@@ -1162,7 +1162,7 @@ rip_init(struct proto_config *CF)
 {
   struct proto *P = proto_new(CF);
 
-  P->main_channel = proto_add_channel(P, proto_cf_main_channel(CF));
+  proto_add_main_channel(P, proto_cf_main_channel(CF));
 
   P->iface_sub.if_notify = rip_if_notify;
   P->rt_notify = rip_rt_notify;
index c8fdcc37b3ac8fc58ba2f71dadb6b4ecd59f1ed9..366cc2b2d0912db2cd830eeb3b2c95cd08b31f54 100644 (file)
@@ -507,7 +507,7 @@ static_init(struct proto_config *CF)
   struct static_proto *p = (void *) P;
   struct static_config *cf = (void *) CF;
 
-  P->main_channel = proto_add_channel(P, proto_cf_main_channel(CF));
+  proto_add_main_channel(P, proto_cf_main_channel(CF));
 
   proto_configure_mpls_channel(P, CF, RTS_STATIC);
 
index cb1093efcd1ea070797da0dc0b9786122ee2d105..bc5b4e9807119370efd8130b1db029451770e82b 100644 (file)
@@ -820,7 +820,7 @@ krt_init(struct proto_config *CF)
   struct krt_proto *p = proto_new(CF);
   // struct krt_config *cf = (void *) CF;
 
-  p->p.main_channel = proto_add_channel(&p->p, proto_cf_main_channel(CF));
+  proto_add_main_channel(&p->p, proto_cf_main_channel(CF));
 
   p->p.preexport = krt_preexport;
   p->p.rt_notify = krt_rt_notify;