]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Merge commit '5121101136cb80151a9361c63dc4822afeb44eef' into thread-next
authorMaria Matejka <mq@ucw.cz>
Thu, 12 Oct 2023 12:12:33 +0000 (14:12 +0200)
committerMaria Matejka <mq@ucw.cz>
Thu, 12 Oct 2023 12:12:33 +0000 (14:12 +0200)
28 files changed:
1  2 
.gitlab-ci.yml
NEWS
conf/cf-lex.l
conf/confbase.Y
doc/bird.sgml
filter/decl.m4
filter/f-inst.c
filter/test.conf
filter/trie_test.c
lib/birdlib.h
lib/ip.h
lib/timer.h
nest/Makefile
nest/rt-fib_test.c
proto/babel/babel.c
proto/babel/babel.h
proto/babel/config.Y
proto/babel/packets.c
proto/bgp/bgp.c
proto/bgp/bgp.h
proto/bgp/packets.c
proto/radv/config.Y
proto/radv/packets.c
proto/radv/radv.h
sysdep/linux/netlink.c
sysdep/unix/io.c
test/bt-utils.c
test/bt-utils.h

diff --cc .gitlab-ci.yml
index 1c8aa8692671774b36f70c49ec743e315b0b6d7f,c913d0f81065bee0caae32f0bc340f8249f9f8ca..dc3960a760982c0354570d9f539aea8e0a4ef906
@@@ -284,8 -258,15 +254,8 @@@ pkg-fedora-33-amd64
  pkg-fedora-34-amd64:
    <<: *pkg-rpm
    needs: [build-fedora-34-amd64]
-   image: registry.labs.nic.cz/labs/bird:fedora-34-amd64
+   image: registry.nic.cz/labs/bird:fedora-34-amd64
  
 -#pkg-centos-7-amd64:
 -#  <<: *pkg-rpm-wa
 -#  variables:
 -#    LC_ALL: en_US.UTF-8
 -#  needs: [build-centos-7-amd64]
 -#  image: registry.nic.cz/labs/bird:centos-7-amd64
 -
  pkg-centos-8-amd64:
    <<: *pkg-rpm-wa
    needs: [build-centos-8-amd64]
diff --cc NEWS
index c0ccaa8e752284d08303d0432b187f4adc5c86ae,30f3b932611d78064f61faf9cb7fc744ef10685f..5e51a2bdc1bd256a6965c412934be8c21061a41e
--- 1/NEWS
--- 2/NEWS
+++ b/NEWS
@@@ -1,34 -1,9 +1,40 @@@
 +Version 3.0alpha2 (2023-05-11)
 +  o Fixed memory leaks and use-after free bugs
 +  o Simple thread work balancing
 +  o MRT switched off
 +  o Slow kernel route synchronization to be fixed later
 +
 +Version 3.0alpha1 (2023-04-18)
 +  o Worker threads for BGP, Pipe, RPKI and BFD
 +  o Configurable number of threads
 +  o Asynchronous route export
 +  o Flat attribute structure
 +  o Inline import tables
 +  o Export tables merged with BGP prefix / attribute buckets
 +  o Fixed ROA check locking inversion in route table dumps
 +  o MRT switched off
 +
 +Version 3.0-alpha0 (2022-02-07)
 +  o Removal of fixed protocol-specific route attributes
 +  o Asynchronous route export
 +  o Explicit table import / export hooks
 +  o Partially lockless route attribute cache
 +  o Thread-safe resource management
 +  o Thread-safe interface notifications
 +  o Thread-safe protocol API
 +  o Adoption of BFD IO loop for general use
 +  o Parallel Pipe protocol
 +  o Parallel RPKI protocol
 +  o Parallel BGP protocol
 +  o Lots of refactoring
 +  o Bugfixes and improvements as they came along
 +
+ Version 2.13.1 (2023-06-23)
+   o BGP: Fix role check when no capability option is present
+   o Filter: Fixed segfault when a case option had an empty block
+   This is a bugfix version.
  Version 2.13 (2023-04-21)
    o Babel: IPv4 via IPv6 extension (RFC 9229)
    o Babel: Improve authentication on lossy networks
diff --cc conf/cf-lex.l
Simple merge
diff --cc conf/confbase.Y
index 8e5da9e3f792e86f5ecea4dbf5ef13808fe5bfdc,3dd5fed7f0f36533e9770ffe2a7ba850fd08c840..4873696ca38aa3ccf9aec5f1d117c6001c9589a5
@@@ -94,9 -93,8 +94,9 @@@ CF_DECL
    struct proto_spec ps;
    struct channel_limit cl;
    struct timeformat *tf;
 -  mpls_label_stack *mls;
 +  struct settle_config settle;
 +  struct adata *ad;
-   struct bytestring *bs;
+   const struct bytestring *bs;
  }
  
  %token END CLI_MARKER INVALID_TOKEN ELSECOL DDOT
diff --cc doc/bird.sgml
Simple merge
diff --cc filter/decl.m4
index 3179a331d0f3cfd3833adbb5a203593d566c28e6,7c863bdc4db38978cdb42d4f7493e95c1e160805..ed7630fc99a0b53dcddca6478aa74733f0070ee6
@@@ -200,8 -200,7 +200,8 @@@ FID_INTERPRET_BODY()'
  #     Executing another filter line. This replaces the recursion
  #     that was needed in the former implementation.
  m4_define(LINEX, `FID_INTERPRET_EXEC()LINEX_($1)FID_INTERPRET_NEW()return $1 FID_INTERPRET_BODY()')
- m4_define(LINEX_, `do {
+ m4_define(LINEX_, `do if ($1) {
 +  if (fstk->ecnt + 1 >= fstk->elen) runtime("Filter execution stack overflow");
    fstk->estk[fstk->ecnt].pos = 0;
    fstk->estk[fstk->ecnt].line = $1;
    fstk->estk[fstk->ecnt].ventry = fstk->vcnt;
diff --cc filter/f-inst.c
Simple merge
Simple merge
Simple merge
diff --cc lib/birdlib.h
Simple merge
diff --cc lib/ip.h
Simple merge
diff --cc lib/timer.h
index 4a3a210834f6729df527b2089749985677e46e19,0f87852bd6d38cb0ff0ee24acfe0eef12828fc09..34b53aa6f158d71d75d48b52c0dd54f5a57a02ba
@@@ -39,22 -31,24 +39,25 @@@ typedef struct time
  struct timeloop
  {
    BUFFER_(timer *) timers;
 -  btime last_time;
 -  btime real_time;
 +  struct domain_generic *domain;
 +  struct birdloop *loop;
  };
  
 +#define TLOCK_TIMER_ASSERT(loop) ASSERT_DIE((loop)->domain && DG_IS_LOCKED((loop)->domain))
 +#define TLOCK_LOCAL_ASSERT(loop) ASSERT_DIE(!(loop)->domain || DG_IS_LOCKED((loop)->domain))
 +
  static inline uint timers_count(struct timeloop *loop)
 -{ return loop->timers.used - 1; }
 +{ TLOCK_TIMER_ASSERT(loop); return loop->timers.used - 1; }
  
  static inline timer *timers_first(struct timeloop *loop)
 -{ return (loop->timers.used > 1) ? loop->timers.data[1] : NULL; }
 -
 -extern struct timeloop main_timeloop;
 +{ TLOCK_TIMER_ASSERT(loop); return (loop->timers.used > 1) ? loop->timers.data[1] : NULL; }
  
 -btime current_time(void);
 -btime current_real_time(void);
 +#define current_time()                atomic_load_explicit(&last_time, memory_order_acquire)
 +#define current_real_time()   atomic_load_explicit(&real_time, memory_order_acquire)
  
+ /* In sysdep code */
+ btime current_time_now(void);
  //#define now (current_time() TO_S)
  //#define now_real (current_real_time() TO_S)
  extern btime boot_time;
diff --cc nest/Makefile
index 1a71c2fbdaa2bd93d60ddaa13458dee3ec5dbb62,5a244c7569e33e4be1b3ec903894f9b9405b46b9..bb141f5c373f25bdf7e8f7c4375c3dcccac244d1
@@@ -13,6 -9,6 +13,6 @@@ $(o)proto-build.c: Makefile $(lastword 
  
  prepare: $(o)proto-build.c
  
- tests_src :=
 -tests_src := a-set_test.c a-path_test.c rt-fib_test.c
++tests_src := rt-fib_test.c
  tests_targets := $(tests_targets) $(tests-target-files)
  tests_objs := $(tests_objs) $(src-o-files)
index 0000000000000000000000000000000000000000,2dd7ce8a38d26a16d4f8e4a035af1c9d8e0bf7ff..b796cc682bffa9fe2dba3cd1859e9cb5db4a79b5
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,246 +1,240 @@@
 -#include "nest/route.h"
+ /*
+  *    BIRD -- Forwarding Information Base -- Tests
+  *
+  *    (c) 2023 CZ.NIC z.s.p.o.
+  *
+  *    Can be freely distributed and used under the terms of the GNU GPL.
+  */
+ #include "test/birdtest.h"
+ #include "test/bt-utils.h"
 -  bt_bird_init();
++#include "nest/rt.h"
+ #define TESTS_NUM             10
+ #define PREFIXES_NUM          400000
+ #define PREFIX_TESTS_NUM      200000
+ #define PREFIX_BENCH_MAX      1000000
+ #define PREFIX_BENCH_NUM      10000000
+ struct test_node
+ {
+   int pos;
+   struct fib_node n;
+ };
+ static inline int net_match(struct test_node *tn, net_addr *query, net_addr *data)
+ { return (tn->pos < PREFIXES_NUM) && net_equal(query, &data[tn->pos]); }
+ static int
+ t_match_random_net(void)
+ {
 -    pool *p = rp_new(&root_pool, "FIB pool");
+   bt_config_parse(BT_CONFIG_SIMPLE);
+   for (int round = 0; round < TESTS_NUM; round++)
+   {
+     int type = !(round & 1) ? NET_IP4 : NET_IP6;
 -  bt_bird_cleanup();
++    pool *p = rp_new(&root_pool, the_bird_domain.the_bird, "FIB pool");
+     net_addr *nets = bt_random_nets(type, PREFIXES_NUM);
+     /* Make FIB structure */
+     struct fib f;
+     fib_init(&f, &root_pool, type, sizeof(struct test_node), OFFSETOF(struct test_node, n), 4, NULL);
+     for (int i = 0; i < PREFIXES_NUM; i++)
+     {
+       struct test_node *tn = fib_get(&f, &nets[i]);
+       bt_assert(!tn->pos || net_match(tn, &nets[i], nets));
+       tn->pos = i;
+     }
+     /* Test (mostly) negative matches */
+     for (int i = 0; i < PREFIX_TESTS_NUM; i++)
+     {
+       net_addr net;
+       bt_random_net(&net, type);
+       struct test_node *tn = fib_find(&f, &net);
+       bt_assert(!tn || net_match(tn, &net, nets));
+     }
+     /* Test positive matches */
+     for (int i = 0; i < PREFIX_TESTS_NUM; i++)
+     {
+       int j = bt_random_n(PREFIXES_NUM);
+       struct test_node *tn = fib_find(&f, &nets[j]);
+       bt_assert(tn && net_match(tn, &nets[j], nets));
+     }
+     rfree(p);
+     tmp_flush();
+   }
 -  bt_bird_init();
+   return 1;
+ }
+ static int
+ t_fib_walk(void)
+ {
 -    pool *p = rp_new(&root_pool, "FIB pool");
+   bt_config_parse(BT_CONFIG_SIMPLE);
+   for (int round = 0; round < TESTS_NUM; round++)
+   {
+     int type = !(round & 1) ? NET_IP4 : NET_IP6;
 -  bt_bird_cleanup();
++    pool *p = rp_new(&root_pool, the_bird_domain.the_bird, "FIB pool");
+     net_addr *nets = bt_random_nets(type, PREFIXES_NUM);
+     byte *marks = tmp_allocz(PREFIXES_NUM);
+     /* Make FIB structure */
+     struct fib f;
+     fib_init(&f, p, type, sizeof(struct test_node), OFFSETOF(struct test_node, n), 4, NULL);
+     for (int i = 1; i < PREFIXES_NUM; i++)
+     {
+       struct test_node *tn = fib_get(&f, &nets[i]);
+       bt_assert(!tn->pos || net_match(tn, &nets[i], nets));
+       if (tn->pos)
+       {
+       /* Mark dupicate nets */
+       bt_assert(!marks[tn->pos]);
+       marks[tn->pos] = 1;
+       }
+       tn->pos = i;
+     }
+     /* Walk FIB and mark nets */
+     FIB_WALK(&f, struct test_node, tn)
+     {
+       bt_assert(!marks[tn->pos]);
+       marks[tn->pos] = 1;
+     }
+     FIB_WALK_END;
+     /* Check in all nets are marked */
+     for (int i = 1; i < PREFIXES_NUM; i++)
+       bt_assert(marks[i]);
+     rfree(p);
+     tmp_flush();
+   }
 -  pool *p = rp_new(&root_pool, "FIB pool");
+   return 1;
+ }
+ static int
+ benchmark_fib_dataset(const char *filename, int type)
+ {
+   net_addr *nets, *test_r, *test_s;
+   uint n = PREFIX_BENCH_MAX;
+   int tn = PREFIX_BENCH_NUM;
+   int match;
+   bt_reset_suite_case_timer();
+   bt_log_suite_case_result(1, "Reading %s", filename, n);
+   nets = bt_read_net_file(filename, type, &n);
+   bt_log_suite_case_result(1, "Read net data, %u nets", n);
+   bt_reset_suite_case_timer();
 -  bt_bird_init();
++  pool *p = rp_new(&root_pool, the_bird_domain.the_bird, "FIB pool");
+   /* Make FIB structure */
+   struct fib f;
+   fib_init(&f, p, type, sizeof(struct test_node), OFFSETOF(struct test_node, n), 0, NULL);
+   for (int i = 0; i < (int) n; i++)
+   {
+     struct test_node *tn = fib_get(&f, &nets[i]);
+     tn->pos = i;
+   }
+   bt_log_suite_case_result(1, "Fill FIB structure, %u nets, order %u", n, f.hash_order);
+   bt_reset_suite_case_timer();
+   /* Compute FIB size */
+   size_t fib_size = rmemsize(p).effective * 1000 / (1024*1024);
+   bt_log_suite_case_result(1, "FIB size: %u.%03u MB", (uint) (fib_size / 1000), (uint) (fib_size % 1000));
+   /* Compute FIB histogram */
+   uint hist[16] = {};
+   uint sum = 0;
+   for (uint i = 0; i < f.hash_size; i++)
+   {
+     int len = 0;
+     for (struct fib_node *fn = f.hash_table[i]; fn; fn = fn->next)
+       len++;
+     sum += len;
+     len = MIN(len, 15);
+     hist[len]++;
+   }
+   bt_log_suite_case_result(1, "FIB histogram:");
+   for (uint i = 0; i < 16; i++)
+     if (hist[i])
+       bt_log_suite_case_result(1, "%02u: %8u", i, hist[i]);
+   uint avg = (sum * 1000) / (f.hash_size - hist[0]);
+   bt_log_suite_case_result(1, "FIB chain length: %u.%03u", (uint) (avg / 1000), (uint) (avg % 1000));
+   bt_reset_suite_case_timer();
+   /* Make test data */
+   test_r = bt_random_nets(type, tn);
+   test_s = bt_random_net_subset(nets, n, tn);
+   bt_log_suite_case_result(1, "Make test data, 2x %u nets", tn);
+   bt_reset_suite_case_timer();
+   /* Test (mostly negative) random matches */
+   match = 0;
+   for (int i = 0; i < tn; i++)
+     if (fib_find(&f, &test_r[i]))
+       match++;
+   bt_log_suite_case_result(1, "Random match, %d / %d matches", match, tn);
+   bt_reset_suite_case_timer();
+   /* Test (positive) subset matches */
+   match = 0;
+   for (int i = 0; i < tn; i++)
+     if (fib_find(&f, &test_s[i]))
+       match++;
+   bt_log_suite_case_result(1, "Subset match, %d / %d matches", match, tn);
+   bt_log_suite_case_result(1, "");
+   bt_reset_suite_case_timer();
+   rfree(p);
+   tmp_flush();
+   return 1;
+ }
+ static int UNUSED
+ t_bench_fib_datasets(void)
+ {
 -  bt_bird_cleanup();
 -
+   bt_config_parse(BT_CONFIG_SIMPLE);
+   /* Specific datasets, not included */
+   benchmark_fib_dataset("fib-data-bgp-v4-1",  NET_IP4);
+   benchmark_fib_dataset("fib-data-bgp-v4-10", NET_IP4);
+   benchmark_fib_dataset("fib-data-bgp-v6-1",  NET_IP6);
+   benchmark_fib_dataset("fib-data-bgp-v6-10", NET_IP6);
+   return 1;
+ }
+ int
+ main(int argc, char *argv[])
+ {
+   bt_init(argc, argv);
++  bt_bird_init();
+   bt_test_suite(t_match_random_net, "Testing random prefix matching");
+   bt_test_suite(t_fib_walk, "Testing FIB_WALK() on random FIB");
+   // bt_test_suite(t_bench_fib_datasets, "Benchmark FIB from datasets by random subset of nets");
+   return bt_exit_value();
+ }
Simple merge
Simple merge
index 6d1ad7d0f39eb9411084236a613a5e4438632e38,b8af02679f0cf5d1709f8386fcab37c2ce5e0211..28bf8027bce147565da9f8ae1bc1b31f7c9a8544
@@@ -24,9 -24,9 +24,9 @@@ CF_DECL
  
  CF_KEYWORDS(BABEL, INTERFACE, METRIC, RXCOST, HELLO, UPDATE, INTERVAL, PORT,
        TYPE, WIRED, WIRELESS, RX, TX, BUFFER, PRIORITY, LENGTH, CHECK, LINK,
 -      NEXT, HOP, IPV4, IPV6, BABEL_METRIC, SHOW, INTERFACES, NEIGHBORS,
 +      NEXT, HOP, IPV4, IPV6, SHOW, INTERFACES, NEIGHBORS,
        ENTRIES, RANDOMIZE, ROUTER, ID, AUTHENTICATION, NONE, MAC, PERMISSIVE,
-       EXTENDED)
+       EXTENDED, TUNNEL, RTT, MIN, MAX, DECAY, SEND, TIMESTAMPS)
  
  CF_GRAMMAR
  
Simple merge
diff --cc proto/bgp/bgp.c
Simple merge
diff --cc proto/bgp/bgp.h
Simple merge
Simple merge
index fb68d2e51cdc7b11e3073ae637931d9a424b1018,eeafe6f454a8ba439217ffc168738a661eaaee15..3c975517031d36ecb1471b6b0e83da99a3a3b88a
@@@ -33,7 -42,7 +42,7 @@@ CF_KEYWORDS(RADV, PREFIX, INTERFACE, MI
        RETRANS, TIMER, CURRENT, HOP, LIMIT, DEFAULT, VALID, PREFERRED, MULT,
        LIFETIME, SKIP, ONLINK, AUTONOMOUS, RDNSS, DNSSL, NS, DOMAIN, LOCAL,
        TRIGGER, SENSITIVE, PREFERENCE, LOW, MEDIUM, HIGH, PROPAGATE, ROUTE,
-       ROUTES)
 -      ROUTES, RA_PREFERENCE, RA_LIFETIME, CUSTOM, OPTION, TYPE, VALUE)
++      ROUTES, CUSTOM, OPTION, TYPE, VALUE)
  
  CF_ENUM(T_ENUM_RA_PREFERENCE, RA_PREF_, LOW, MEDIUM, HIGH)
  
Simple merge
Simple merge
index e8a86ce4f58a35ac5f179fd954900c3cadcfb793,e3298a0f5549c5f677cc5467ddd0ebcba2d45020..3cc3bb9b2d91afdee823673e7df0f31ed12ceec9
@@@ -1760,17 -1655,15 +1758,15 @@@ nl_parse_route(struct nl_parse_state *s
        }
  
        if (a[RTA_GATEWAY])
 -      ra->nh.gw = rta_get_ipa(a[RTA_GATEWAY]);
 +      nhad.nh.gw = rta_get_ipa(a[RTA_GATEWAY]);
  
- #ifdef HAVE_MPLS_KERNEL
        if (a[RTA_VIA])
 -      ra->nh.gw = rta_get_via(a[RTA_VIA]);
 +      nhad.nh.gw = rta_get_via(a[RTA_VIA]);
- #endif
  
        if (i->rtm_flags & RTNH_F_ONLINK)
 -      ra->nh.flags |= RNF_ONLINK;
 +      nhad.nh.flags |= RNF_ONLINK;
  
 -      if (ipa_nonzero(ra->nh.gw))
 +      if (ipa_nonzero(nhad.nh.gw))
        {
          /* Silently skip strange 6to4 routes */
          const net_addr_ip6 sit = NET_ADDR_IP6(IP6_NONE, 96);
index 83149a964071a0cda1210d2ab0d528d3f1547062,6aedcfb669191ae60c198d6b3620a9123afc8e9a..11dfb2e4e042ae0270dc4eadab8757684b1ade7c
@@@ -259,25 -168,23 +259,38 @@@ times_update(void
    if (rv < 0)
      die("clock_gettime: %m");
  
 -  loop->real_time = ts.tv_sec S + ts.tv_nsec NS;
 +  btime new_real_time = ts.tv_sec S + ts.tv_nsec NS;
 +
 +  if (!atomic_compare_exchange_strong_explicit(
 +      &last_time,
 +      &old_time,
 +      new_time,
 +      memory_order_acq_rel,
 +      memory_order_relaxed))
 +    DBG("Time update collision: last_time");
 +
 +  if (!atomic_compare_exchange_strong_explicit(
 +      &real_time,
 +      &old_real_time,
 +      new_real_time,
 +      memory_order_acq_rel,
 +      memory_order_relaxed))
 +    DBG("Time update collision: real_time");
  }
  
 -
+ btime
+ current_time_now(void)
+ {
+   struct timespec ts;
+   int rv;
+   rv = clock_gettime(CLOCK_MONOTONIC, &ts);
+   if (rv < 0)
+     die("clock_gettime: %m");
+   return ts.tv_sec S + ts.tv_nsec NS;
+ }
  /**
   * DOC: Sockets
   *
diff --cc test/bt-utils.c
Simple merge
diff --cc test/bt-utils.h
index 758dbf48ba3848f5279c7fb9115b226df4aae3ca,d29a0b7c8d2015087a640ccbb124f62516723092..031db6e8869938e0972daea6a0b2d3665d1c89c4
  
  uint bt_naive_pow(uint base, uint power);
  void bt_bytes_to_hex(char *buf, const byte *in_data, size_t size);
+ void bt_random_net(net_addr *net, int type);
+ net_addr *bt_random_nets(int type, uint n);
+ net_addr *bt_random_net_subset(net_addr *src, uint sn, uint dn);
+ void bt_read_net(const char *str, net_addr *net, int type);
+ net_addr *bt_read_nets(FILE *f, int type, uint *n);
+ net_addr *bt_read_net_file(const char *filename, int type, uint *n);
  
  void bt_bird_init(void);
 -void bt_bird_cleanup(void);
  struct config *bt_config_parse(const char *cfg);
  struct config *bt_config_file_parse(const char *filepath);