diff --git a/conf/confbase.Y b/conf/confbase.Y index 63308290..2c37bd4d 100644 --- a/conf/confbase.Y +++ b/conf/confbase.Y @@ -88,6 +88,7 @@ CF_DECLS struct sym_show_data *sd; struct lsadb_show_data *ld; struct mrt_dump_data *md; + struct mpls_show_ranges_cmd *msrc; struct iface *iface; void *g; btime time; diff --git a/doc/reply_codes b/doc/reply_codes index 02f4e656..71cdf341 100644 --- a/doc/reply_codes +++ b/doc/reply_codes @@ -61,6 +61,7 @@ Reply codes of BIRD command-line interface 1023 Show Babel interfaces 1024 Show Babel neighbors 1025 Show Babel entries +1026 Show MPLS ranges 8000 Reply too long 8001 Route not found diff --git a/nest/mpls.Y b/nest/mpls.Y index 5c46392c..0e755fec 100644 --- a/nest/mpls.Y +++ b/nest/mpls.Y @@ -24,6 +24,7 @@ CF_KEYWORDS(MPLS, DOMAIN, LABEL, RANGE, STATIC, DYNAMIC, START, LENGTH, POLICY, %type mpls_label_policy %type mpls_channel_start mpls_channel +%type show_mpls_ranges_args CF_GRAMMAR @@ -137,6 +138,59 @@ mpls_channel_opt_list: mpls_channel_end: { mpls_channel_postconfig(this_channel); } channel_end; +show_mpls_ranges_args: + /* empty */ + { + if (EMPTY_LIST(config->mpls_domains)) + cf_error("No MPLS domain defined"); + + $$ = cfg_allocz(sizeof(struct mpls_show_ranges_cmd)); + } + | show_mpls_ranges_args symbol_known + { + if ($2->class == SYM_MPLS_DOMAIN) + { + if ($$->domain) + cf_error("Only one MPLS domain expected"); + + $$->domain = $2->mpls_domain; + } + else if ($2->class == SYM_MPLS_RANGE) + { + if ($$->range) + cf_error("Only one MPLS label range expected"); + + if ($$->domain != $2->mpls_range->domain) + cf_error("MPLS label range from different MPLS domain"); + + $$->domain = $2->mpls_range->domain; + $$->range = $2->mpls_range; + } + else + cf_error("MPLS domain or label range expected"); + } + | show_mpls_ranges_args STATIC + { + if ($$->range) + cf_error("Only one MPLS label range expected"); + + $$->domain = $$->domain ?: cf_default_mpls_domain(config); + $$->range = $$->domain->static_range; + } + | show_mpls_ranges_args DYNAMIC + { + if ($$->range) + cf_error("Only one MPLS label range expected"); + + $$->domain = $$->domain ?: cf_default_mpls_domain(config); + $$->range = $$->domain->dynamic_range; + } + ; + +CF_CLI(SHOW MPLS RANGES, show_mpls_ranges_args, [ | ], [[Show MPLS ranges]]) +{ mpls_show_ranges($4); } ; + + CF_CODE CF_END diff --git a/nest/mpls.c b/nest/mpls.c index df03a86b..788de7c1 100644 --- a/nest/mpls.c +++ b/nest/mpls.c @@ -76,7 +76,6 @@ * and withdrawal of MPLS routes. * * TODO: - * - show mpls labels CLI command * - label range non-intersection check * - better range reconfigurations (allow reduce ranges over unused labels) * - protocols should do route refresh instead of resetart when reconfiguration @@ -89,6 +88,7 @@ #include "nest/bird.h" #include "nest/route.h" #include "nest/mpls.h" +#include "nest/cli.h" static struct mpls_range *mpls_new_range(struct mpls_domain *m, struct mpls_range_config *cf); static struct mpls_range *mpls_find_range_(list *l, const char *name); @@ -1038,3 +1038,50 @@ mpls_rte_remove(net *n UNUSED, rte *r) mpls_unlock_fec(m, fec); } + +static void +mpls_show_ranges_rng(struct mpls_show_ranges_cmd *cmd, struct mpls_range *r) +{ + uint last = lmap_last_one_in_range(&cmd->dom->labels, r->lo, r->hi); + if (last == r->hi) last = 0; + + cli_msg(-1026, "%-11s %7u %7u %7u %7u %7u", + r->name, r->lo, r->hi - r->lo, r->hi, r->label_count, last); +} + +void +mpls_show_ranges_dom(struct mpls_show_ranges_cmd *cmd, struct mpls_domain *m) +{ + if (cmd->dom) + cli_msg(-1026, ""); + + cmd->dom = m; + cli_msg(-1026, "MPLS domain %s:", m->name); + cli_msg(-1026, "%-11s %7s %7s %7s %7s %7s", + "Range", "Start", "Length", "End", "Labels", "Last"); + + if (cmd->range) + mpls_show_ranges_rng(cmd, cmd->range->range); + else + { + struct mpls_range *r; + WALK_LIST(r, m->ranges) + if (!r->removed) + mpls_show_ranges_rng(cmd, r); + } +} + +void +mpls_show_ranges(struct mpls_show_ranges_cmd *cmd) +{ + if (cmd->domain) + mpls_show_ranges_dom(cmd, cmd->domain->domain); + else + { + struct mpls_domain *m; + WALK_LIST(m, mpls_domains) + mpls_show_ranges_dom(cmd, m); + } + + cli_msg(0, ""); +} diff --git a/nest/mpls.h b/nest/mpls.h index 4b071ad8..bac5c69d 100644 --- a/nest/mpls.h +++ b/nest/mpls.h @@ -171,4 +171,15 @@ void mpls_handle_rte_cleanup(struct mpls_fec_map *m, struct mpls_fec **locked_fe void mpls_rte_insert(net *n UNUSED, rte *r); void mpls_rte_remove(net *n UNUSED, rte *r); + +struct mpls_show_ranges_cmd { + struct mpls_domain_config *domain; + struct mpls_range_config *range; + + /* Runtime */ + struct mpls_domain *dom; +}; + +void mpls_show_ranges(struct mpls_show_ranges_cmd *cmd); + #endif