From 35726051517aaf1869458caed03c7ee1c516721c Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Fri, 22 Sep 2023 15:47:48 +0200 Subject: [PATCH] MPLS: Label range non-intersection check --- nest/mpls.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++-- nest/mpls.h | 1 + 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/nest/mpls.c b/nest/mpls.c index bab6d128..ff76c05d 100644 --- a/nest/mpls.c +++ b/nest/mpls.c @@ -76,7 +76,6 @@ * and withdrawal of MPLS routes. * * TODO: - * - label range non-intersection check * - protocols should do route refresh instead of restart when reconfiguration * requires changing labels (e.g. different label range) * - registering static allocations @@ -84,6 +83,8 @@ * - special handling of reserved labels */ +#include + #include "nest/bird.h" #include "nest/route.h" #include "nest/mpls.h" @@ -122,6 +123,7 @@ mpls_domain_config_new(struct symbol *s) rc->name = "static"; rc->start = 16; rc->length = 984; + rc->implicit = 1; mc->static_range = rc; /* Predefined dynamic range */ @@ -129,6 +131,7 @@ mpls_domain_config_new(struct symbol *s) rc->name = "dynamic"; rc->start = 1000; rc->length = 9000; + rc->implicit = 1; mc->dynamic_range = rc; add_tail(&new_config->mpls_domains, &mc->n); @@ -136,10 +139,52 @@ mpls_domain_config_new(struct symbol *s) return mc; } +static int +mpls_compare_range_configs(const void *r1_, const void *r2_) +{ + const struct mpls_range_config * const *r1 = r1_; + const struct mpls_range_config * const *r2 = r2_; + + return uint_cmp((*r1)->start, (*r2)->start); +} + void mpls_domain_postconfig(struct mpls_domain_config *cf UNUSED) { - /* Add label range non-intersection check */ + /* Label range non-intersection check */ + + int num_ranges = list_length(&cf->ranges); + struct mpls_range_config **ranges = tmp_alloc(num_ranges * sizeof(struct mpls_range_config *)); + + { + int i = 0; + struct mpls_range_config *r; + WALK_LIST(r, cf->ranges) + ranges[i++] = r; + } + + qsort(ranges, num_ranges, sizeof(struct mpls_range_config *), mpls_compare_range_configs); + + struct mpls_range_config *max_range = NULL; + uint max_hi = 0; + + for (int i = 0; i < num_ranges; i++) + { + struct mpls_range_config *r = ranges[i]; + uint hi = r->start + r->length; + + if (r->implicit) + continue; + + if (r->start < max_hi) + cf_warn("MPLS label ranges %s and %s intersect", max_range->name, r->name); + + if (hi > max_hi) + { + max_range = r; + max_hi = hi; + } + } } static struct mpls_domain * diff --git a/nest/mpls.h b/nest/mpls.h index bac5c69d..6452220a 100644 --- a/nest/mpls.h +++ b/nest/mpls.h @@ -63,6 +63,7 @@ struct mpls_range_config { uint start; /* Label range start, (uint) -1 for undefined */ uint length; /* Label range length, (uint) -1 for undefined */ + u8 implicit; /* Implicitly defined range */ }; struct mpls_range {