diff --git a/nest/config.Y b/nest/config.Y index a0a10daf..6b9f6e94 100644 --- a/nest/config.Y +++ b/nest/config.Y @@ -692,10 +692,10 @@ CF_CLI(SHOW MEMORY,,, [[Show memory usage]]) { cmd_show_memory(); } ; CF_CLI(SHOW PROTOCOLS, proto_patt2, [ | \"\"], [[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, [ | \"\"], [[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; } diff --git a/nest/proto.c b/nest/proto.c index 6f9923f0..0856ec70 100644 --- a/nest/proto.c +++ b/nest/proto.c @@ -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) { @@ -2090,6 +2103,7 @@ extern void bfd_init_all(void); void protos_build_gen(void); + /** * protos_build - build a protocol list * @@ -2489,6 +2503,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) { @@ -2582,7 +2609,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]; @@ -2591,23 +2618,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) @@ -2627,6 +2668,7 @@ proto_cmd_show(struct proto *p, uintptr_t verbose, int cnt) } cli_msg(-1006, ""); + } } } @@ -2829,6 +2871,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) { diff --git a/nest/protocol.h b/nest/protocol.h index a77c28db..75a942d9 100644 --- a/nest/protocol.h +++ b/nest/protocol.h @@ -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); @@ -713,6 +720,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); diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c index 7c649214..0077ff48 100644 --- a/proto/ospf/ospf.c +++ b/proto/ospf/ospf.c @@ -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; diff --git a/proto/radv/radv.c b/proto/radv/radv.c index ea0b8d38..5ee4ca03 100644 --- a/proto/radv/radv.c +++ b/proto/radv/radv.c @@ -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; diff --git a/proto/rip/rip.c b/proto/rip/rip.c index 1d4e6cf5..a4727018 100644 --- a/proto/rip/rip.c +++ b/proto/rip/rip.c @@ -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; diff --git a/proto/static/static.c b/proto/static/static.c index c8fdcc37..366cc2b2 100644 --- a/proto/static/static.c +++ b/proto/static/static.c @@ -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); diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c index cb1093ef..bc5b4e98 100644 --- a/sysdep/unix/krt.c +++ b/sysdep/unix/krt.c @@ -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;