summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--conf/confbase.Y1
-rw-r--r--doc/reply_codes1
-rw-r--r--nest/mpls.Y54
-rw-r--r--nest/mpls.c49
-rw-r--r--nest/mpls.h11
5 files changed, 115 insertions, 1 deletions
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 <i> mpls_label_policy
%type <cc> mpls_channel_start mpls_channel
+%type <msrc> 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, [<MPLS domain> | <MPLS range>], [[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