]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Lib: Extend MPLS label allocator bitmap
authorOndrej Zajicek <santiago@crfreenet.org>
Mon, 18 Sep 2023 12:12:22 +0000 (14:12 +0200)
committerOndrej Zajicek <santiago@crfreenet.org>
Wed, 4 Oct 2023 11:07:33 +0000 (13:07 +0200)
Add function lmap_last_one_in_range() for finding the last active label
in a label range.

lib/bitmap.c
lib/bitmap.h
lib/bitmap_test.c

index 60883cf281d2fda3901877fa8b0c4ae3dba2050b..c036f80deba81e0b6dc3950e9a2de289df20b4b3 100644 (file)
@@ -398,6 +398,81 @@ lmap_first_zero_in_range(struct lmap *b, uint lo, uint hi)
   return hi;
 }
 
+static inline int
+b1024_last_one(u32 *p)
+{
+  for (int i = 31; i >= 0; i--)
+    if (p[i])
+      return 32*i + (31 - u32_clz(p[i]));
+
+  return 1024;
+}
+
+static uint
+b1024_last_one_in_range(u32 *p, uint lo, uint hi)
+{
+  uint lo0 = lo >> 5;
+  uint lo1 = lo & 0x1f;
+  uint hi0 = hi >> 5;
+  uint hi1 = hi & 0x1f;
+  u32 mask = (1u << hi1) - 1;
+  u32 val;
+
+  for (int i = hi0; i > (int) lo0; i--)
+  {
+    val = p[i] & mask;
+    mask = ~0;
+
+    if (val)
+      return 32*i + (31 - u32_clz(val));
+  }
+
+  {
+    mask &= ~((1u << lo1) - 1);
+    val = p[lo0] & mask;
+
+    if (val)
+      return 32*lo0 + (31 - u32_clz(val));
+  }
+
+  return hi;
+}
+
+uint
+lmap_last_one_in_range(struct lmap *b, uint lo, uint hi)
+{
+  uint lo0 = lo >> 10;
+  uint lo1 = lo & 0x3ff;
+  uint hi0 = hi >> 10;
+  uint hi1 = hi & 0x3ff;
+
+  if (hi1 && (hi0 < b->size) && b->data[hi0])
+  {
+    uint min = (lo0 == hi0) ? lo1 : 0;
+    uint n0 = hi0;
+    uint n1 = b1024_last_one_in_range(b->data[n0], min, hi1);
+
+    if (n1 < hi1)
+      return (n0 << 10) + n1;
+  }
+
+  for (int i = (int)MIN(hi0, b->size) - 1; i >= (int) lo0; i--)
+  {
+    if (! b->data[i])
+      continue;
+
+    uint n0 = i;
+    uint n1 = b1024_last_one(b->data[n0]);
+
+    if ((n0 == lo0) && (n1 < lo1))
+      return hi;
+
+    return (n0 << 10) + n1;
+  }
+
+  return hi;
+}
+
 void
 lmap_check(struct lmap *b)
 {
index 4d2dc2a862720eb6a58bf9f3530c7d39aeb56a2e..e3351ab193d9ad35eb0538ef6c7dad0e8a501a28 100644 (file)
@@ -79,6 +79,7 @@ void lmap_set(struct lmap *b, uint n);
 void lmap_clear(struct lmap *b, uint n);
 uint lmap_first_zero(struct lmap *b);
 uint lmap_first_zero_in_range(struct lmap *b, uint lo, uint hi);
+uint lmap_last_one_in_range(struct lmap *b, uint lo, uint hi);
 void lmap_check(struct lmap *b);
 
 #endif
index 3aeeaef5e779d747eb8b0ab4dcca4085823705e6..39fbd0ed4e361f22a1d1a5e05cf4f6d45eab8e48 100644 (file)
@@ -216,6 +216,18 @@ t_lmap_set_clear_fill(void)
       lmap_clear(&b, n);
       expected[n] = 0;
     }
+
+    {
+      n = lmap_last_one_in_range(&b, lo, hi);
+      bt_assert(n >= lo);
+      bt_assert(n <= hi);
+
+      for (last = n + 1; last < hi; last++)
+       bt_assert(!expected[last]);
+
+      if (n < hi)
+       bt_assert(expected[n]);
+    }
   }
 
   uint cnt = 0;