]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
WIP mrtload: loading with tm_start (based on number of updates or given acceleration...
authorKaterina Kubecova <katerina.kubecova@nic.cz>
Thu, 10 Jul 2025 11:45:49 +0000 (13:45 +0200)
committerKaterina Kubecova <katerina.kubecova@nic.cz>
Thu, 10 Jul 2025 11:45:49 +0000 (13:45 +0200)
nest/protocol.h
nest/rt-table.c
proto/bgp/packets.c
proto/mrt/mrt_load.c
proto/mrt/mrt_load.h
proto/mrt/mrtload.Y

index 241e908967bd8e754cae350102a5962dc404e0ca..5e276b5fc285b8636c324984e7de399ae81e6d2c 100644 (file)
@@ -661,7 +661,6 @@ static inline void rte_update(struct proto *p, const net_addr *n, rte *new) { rt
 static inline void
 rte_update3(struct channel *c, const net_addr *n, rte *new, struct rte_src *src)
 {
-  log("rte_update3 src %x", src);
   if (c->in_table && !rte_update_in(c, n, new, src))
     return;
 
index 8e9b7091e3bf2b6137e8afd0fb12480085a10ff8..5d5c88d9126c12947415e5c88681f9c461c8d411 100644 (file)
@@ -2695,8 +2695,8 @@ rt_next_hop_update_net(rtable *tab, net *n)
        /* Call a pre-comparison hook */
        /* Not really an efficient way to compute this */
        const struct rte_context *ctx = rte_get_context(e);
-  log("nexthop update ctx %x, fc ptr %x", ctx, ctx->rte_recalculate);
-       if (ctx && ctx->rte_recalculate)
+
+  if (ctx && ctx->rte_recalculate)
          ctx->rte_recalculate(ctx, tab, n, new, e, NULL);
 
        if (e != old_best)
index 455e925081f3b27dfad85d63ba06145ed6aa417f..03069435c190e710e2f0e724d5a2d6664e330e8e 100644 (file)
@@ -1097,8 +1097,6 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, uint len)
 static void
 bgp_apply_next_hop(struct bgp_parse_state *s, rta *a, ip_addr gw, ip_addr ll)
 {
-  log("bgp_apply_next_hop");
-
   struct bgp_channel *c = SKIP_BACK(struct bgp_channel, c, s->channel);
 
   if (c->cf->gw_mode == GW_DIRECT)
@@ -1138,7 +1136,6 @@ bgp_apply_next_hop(struct bgp_parse_state *s, rta *a, ip_addr gw, ip_addr ll)
 
     /* With MPLS, hostentry is applied later in bgp_apply_mpls_labels() */
   }
-  log("bgp_apply_next_hop  end");
 }
 
 static void
@@ -1753,10 +1750,8 @@ bgp_decode_nlri_ip4(struct bgp_parse_state *s, byte *pos, uint len, rta *a)
     if (s->mpls)
       bgp_decode_mpls_labels(s, &pos, &len, &l, a);
 
-    log("debug the bug l %i, s->mpls %i, len %i pos %i", l, s->mpls, len, pos);
-    if (l > IP4_MAX_PREFIX_LENGTH){
-      bug("parse error");
-      bgp_parse_error(s, 10);}
+    if (l > IP4_MAX_PREFIX_LENGTH)
+      bgp_parse_error(s, 10);
 
     /* Decode prefix body */
     ip4_addr addr = IP4_NONE;
@@ -2787,7 +2782,6 @@ bgp_rx_end_mark(struct bgp_parse_state *s, u32 afi)
 static inline void
 bgp_decode_nlri(struct bgp_parse_state *s, u32 afi, byte *nlri, uint len, ea_list *ea, byte *nh, uint nh_len)
 {
-  log("bgp_decode_nlri");
   if (!s->get_channel(s, afi))
     DISCARD(BAD_AFI, BGP_AFI(afi), BGP_SAFI(afi));
 
@@ -2802,7 +2796,6 @@ bgp_decode_nlri(struct bgp_parse_state *s, u32 afi, byte *nlri, uint len, ea_lis
 
   if (ea)
   {
-    log("ea %x", ea);
     a = allocz(RTA_MAX_SIZE);
 
     a->source = RTS_BGP;
@@ -2819,14 +2812,10 @@ bgp_decode_nlri(struct bgp_parse_state *s, u32 afi, byte *nlri, uint len, ea_lis
       a = NULL;
   }
 
-  log("jump %s %x (desc %x)", s->desc->name, s->desc->decode_nlri, s->desc);
-  log("true desc %x, name %s fce %x", &bgp_af_table[0], bgp_af_table[0].name, bgp_af_table[0].decode_nlri );
   s->desc->decode_nlri(s, nlri, len, a);
-  log("jumped");
 
   rta_free(s->cached_rta);
   s->cached_rta = NULL;
-  log("bgp_decode_nlri end");
 }
 
 void
@@ -3587,7 +3576,6 @@ bgp_rx_packet(struct bgp_conn *conn, byte *pkt, uint len)
   conn->bgp->stats.rx_messages++;
   conn->bgp->stats.rx_bytes += len;
 
-  log("if (conn->bgp->p.mrtdump & MD_MESSAGES) %x %x", conn->bgp->p.mrtdump, MD_MESSAGES);
   if (conn->bgp->p.mrtdump & MD_MESSAGES)
     bgp_dump_message(conn, pkt, len);
 
index 7629abdb534381c056b1a76da96c088d05b8a667..fbe25c4b82cff45e84fb5d99bfdc480bcffb1b83 100644 (file)
@@ -1,6 +1,4 @@
 
-#include <stdio.h>
-
 #include "mrt.h"
 #include "mrt_load.h"
 
@@ -47,7 +45,6 @@ mrtload_ip(FILE *fp, u64 *remains, ip_addr *addr, bool is_ip6)
   }
   else
   {
-    log("is 4");
     addr->addr[0] = addr->addr[1] = addr->addr[2] = 0;
     addr->addr[3] = mrtload_four_octet(fp, remains);
   }
@@ -100,23 +97,21 @@ mrt_parse_bgp_message(FILE *fp, u64 *remains, bool as4, bool insert_hash, struct
     peer_as = mrtload_two_octet(fp, remains);
     local_as = mrtload_two_octet(fp, remains);
   }
-  int is_internal = (peer_as == local_as);
 
+  int is_internal = (peer_as == local_as);
   int interface_id = mrtload_two_octet(fp, remains);
   int addr_fam = mrtload_two_octet(fp, remains);
 
-  log("interface id %i, addr_fam %i", interface_id, addr_fam);
-
   mrtload_ip(fp, remains, &remote_ip, addr_fam == 2);
   mrtload_ip(fp, remains, &local_ip, addr_fam == 2);
 
-  log("remote_ip %I, local_ip %I", remote_ip, local_ip);
-  log("as; %x %x",peer_as, local_as );
+  //log("remote_ip %I, local_ip %I", remote_ip, local_ip);
+  //log("as; %x %x",peer_as, local_as );
   struct mrtload_route_ctx *route_attrs = HASH_FIND(p->ctx_hash, MRTLOAD_CTX, peer_as, local_as, remote_ip, local_ip);
-  log("log found? %x", route_attrs);
+  //log("log found? %x", route_attrs);
+
   if (!route_attrs && insert_hash)
   {
-    log("inserting");
     route_attrs = (struct mrtload_route_ctx *) mb_allocz(p->ctx_pool, sizeof(struct mrtload_route_ctx));
  
     route_attrs->src = rt_get_source(&p->p, p->source_cnt);
@@ -148,33 +143,31 @@ mrt_parse_bgp_message(FILE *fp, u64 *remains, bool as4, bool insert_hash, struct
 }
 
 void
-mrt_parse_bgp4mp_change_state(FILE *fp, u64 *remains, bool as4, struct proto *P)
+mrt_parse_bgp4mp_change_state(FILE *fp, u64 *remains, bool as4, struct mrtload_proto *p)
 {
-  struct mrtload_proto *p = SKIP_BACK(struct mrtload_proto, p, P);
   struct mrtload_route_ctx *ra = mrt_parse_bgp_message(fp, remains, as4, false, p);
   int old_state = mrtload_two_octet(fp, remains);
   int new_state = mrtload_two_octet(fp, remains);
-  log("old state %i new state %i", old_state, new_state);
+  //log("old state %i new state %i", old_state, new_state);
 
-  log("new_state %i == BS_CLOSE && ra->addr_fam == p->channel->afi >> 16  %i", new_state, p->channel->afi >> 16);
   if (new_state == 1 && ra && ra->addr_fam == (int)(p->channel->afi >> 16)) // state 1 - Idle (rfc 1771)
   {
     FIB_WALK(&p->channel->c.table->fib, net, n)
     {
       rte *e = n->routes;
       while(e)
       {
         rte *next = e->next;
-        log("ra src %x e src %x", ra->src, e->src);
+
         if (e->sender == &p->channel->c && e->src == ra->src)
-        {
-          rte_update2(&p->channel->c, e->net->n.addr, NULL, P->main_source);
-          log("removed");
-        }
+          rte_update2(&p->channel->c, e->net->n.addr, NULL, p->p.main_source);
+
         e = next;
       }
     }
     FIB_WALK_END;
+  
     HASH_DO_REMOVE(p->ctx_hash, MRTLOAD_CTX, &ra);
     mb_free(ra);
   }
@@ -197,6 +190,7 @@ mrt_get_channel_to_parse(struct bgp_parse_state *s UNUSED, u32 afi UNUSED)
   s->channel->proto = s->p;
   channel_set_state(s->channel, CS_START);
   channel_set_state(s->channel, CS_UP);
+
   return true;
 }
 
@@ -207,11 +201,9 @@ mrt_apply_mpls_labels(struct bgp_parse_state *s UNUSED, rta *a UNUSED, u32 *labe
 }
 
 static void
-mrt_parse_bgp4mp_message(FILE *fp, u64 *remains, bool as4, struct proto *P)
+mrt_parse_bgp4mp_message(FILE *fp, u64 *remains, bool as4, struct mrtload_proto *p)
 {
-  struct mrtload_proto *p = (void *) P;
   struct mrtload_route_ctx *proto_attrs = mrt_parse_bgp_message(fp, remains, true, as4, p);
-  log("addr fam %x", proto_attrs->addr_fam);
 
   if (*remains < 19)
   {
@@ -224,24 +216,22 @@ mrt_parse_bgp4mp_message(FILE *fp, u64 *remains, bool as4, struct proto *P)
 
   remains[0] = remains[0] - 16;
   u64 length = mrtload_two_octet(fp, remains) - 16 - 2 -1; /* length without header (marker, length, type) */
-  log("length %i", length);
   int type = mrtload_one(fp, remains);
 
-  log("type %i (pkt update %i)", type, PKT_UPDATE);
   /* in case of new peer, the peer has already been added to hash table 
    * (TODO: it was added to hash table without considering the PKT type) */
   if (type != PKT_UPDATE)
     return;
 
   struct bgp_parse_state s = {
-    .proto_name = P->name,
-    .pool = lp_new(P->pool),
+    .proto_name = p->p.name,
+    .pool = lp_new(p->p.pool),
     .parse_error = mrt_parse_error,
     .end_mark = mrt_rx_end_mark,
     .get_channel = mrt_get_channel_to_parse,
     .apply_mpls_labels = mrt_apply_mpls_labels,
     .is_mrt_parse = 1,
-    .p = P,
+    .p = &p->p,
     .as4_session = as4,
     .last_src = proto_attrs->src,
     .desc = p->channel->desc, // desc is set later in bgp, but we need afi to compare
@@ -256,8 +246,8 @@ mrt_parse_bgp4mp_message(FILE *fp, u64 *remains, bool as4, struct proto *P)
   bgp_parse_update(&s, buf, length, &ea);
 }
 
-int
-mrt_parse_general_header(FILE *fp, struct proto *P)
+u64
+mrt_parse_timestamp(FILE *fp)
 {
   char is_eof = fgetc(fp);
   u64 timestamp = is_eof;
@@ -272,7 +262,12 @@ mrt_parse_general_header(FILE *fp, struct proto *P)
       timestamp += fgetc(fp);
     }
   }
+  return timestamp;
+}
 
+int
+mrt_parse_general_header(FILE *fp, struct mrtload_proto *p)
+{
   int type = (fgetc(fp) << 8) + fgetc(fp);
   int subtype = (fgetc(fp) << 8) + fgetc(fp);
   u64 length = 0;
@@ -285,26 +280,26 @@ mrt_parse_general_header(FILE *fp, struct proto *P)
   u64 remains = length;
 
   /* We do not load MRT_TABLE_DUMP_V2 type and MRT_BGP4MP_STATE_CHANGE_AS4. */
-  log("type %i subtype %i, timestamp %li", type, subtype, timestamp);
+  //log("type %i subtype %i, timestamp %li", type, subtype, timestamp);
   if (type == MRT_BGP4MP)
   {
     switch (subtype)
     {
       case (MRT_BGP4MP_MESSAGE):
-        mrt_parse_bgp4mp_change_state(fp, &remains, false, P);
+        mrt_parse_bgp4mp_change_state(fp, &remains, false, p);
         break;
       case (MRT_BGP4MP_MESSAGE_LOCAL):
       case (MRT_BGP4MP_MESSAGE_ADDPATH):
-        mrt_parse_bgp4mp_message(fp, &remains, false, P);
+        mrt_parse_bgp4mp_message(fp, &remains, false, p);
         break;
       case (MRT_BGP4MP_STATE_CHANGE_AS4):
-        mrt_parse_bgp4mp_change_state(fp, &remains, true, P);
+        mrt_parse_bgp4mp_change_state(fp, &remains, true, p);
         break;
       case (MRT_BGP4MP_MESSAGE_AS4):
       case (MRT_BGP4MP_MESSAGE_AS4_LOCAL):
       case (MRT_BGP4MP_MESSAGE_AS4_LOCAL_ADDPATH):
       case (MRT_BGP4MP_MESSAGE_AS4_ADDPATH):
-        mrt_parse_bgp4mp_message(fp, &remains, true,  P);
+        mrt_parse_bgp4mp_message(fp, &remains, true,  p);
         break;
     }
   }
@@ -314,24 +309,81 @@ mrt_parse_general_header(FILE *fp, struct proto *P)
   for (u64 i = 0; i < remains; i++)
     fgetc(fp);
 
-  return 1;
+  return length;
 }
 
 void
-mrtload(struct proto *P)
+mrtload_hook(timer *tm)
 {
-  struct mrtload_config *cf = (void *) (P->cf);
-  FILE *fp = fopen(cf->filename, "r");
+  struct mrtload_proto *p = tm->data;
+  int loaded = 0;
+  btime stamp;
 
-  if (fp == NULL)
+  while (loaded < 1<<14)
+  {
+    loaded += mrt_parse_general_header(p->parsed_file, p);
+    stamp = mrt_parse_timestamp(p->parsed_file);
+    if (stamp == 0)
+      return;
+  }
+
+  tm_start(p->load_timer, 10000);
+}
+
+void
+mrtload_hook_replay(timer *tm)
+{
+  struct mrtload_proto *p = tm->data;
+  int loaded = 0;
+  s64 time = p->next_time;
+
+  while (time == p->next_time && loaded < 1<<14)
+  {
+    loaded += mrt_parse_general_header(p->parsed_file, p);
+    time = mrt_parse_timestamp(p->parsed_file);
+  }
+
+  // mrt time is in seconds, bird count in microseconds
+  s64 shift_from_start = ((time - p->zero_time) * 1000000) / p->time_replay;
+  s64 wait_time = shift_from_start + p->start_time - current_time();
+  p->next_time = time;
+  //log("next time is %li wait %li shift %li", p->next_time, wait_time, shift_from_start);
+
+  tm_start(p->load_timer, wait_time);
+}
+
+void
+mrtload(struct mrtload_proto *p)
+{
+  struct mrtload_config *cf = (void *) (p->p.cf);
+  p->parsed_file = fopen(cf->filename, "r");
+
+  if (p->parsed_file == NULL)
   {
     log(L_WARN "Can not open file %s", cf->filename);
     return;
   }
 
-  /* Parsing mrt headers in loop. MRT_BGP4MP messages are loaded, the rest is skipped. */
-  int temporary = 0; //TODO REMOVE!!! THIS IS FOR TESTING PURPOSES ONLY!
-  while (mrt_parse_general_header(fp, P)){if (temporary++>400) break; log("%i temporary",temporary);}
+  p->load_timer->data = p;
+  if (!cf->time_replay)
+  {
+    p->load_timer->hook = mrtload_hook;
+
+    if (mrt_parse_timestamp(p->parsed_file))
+      tm_start(p->load_timer, 0);
+    return;
+  }
+
+  p->load_timer->hook = mrtload_hook_replay;
+  p->time_replay = cf->time_replay;
+  p->start_time = current_time();
+  p->zero_time = mrt_parse_timestamp(p->parsed_file);
+  p->next_time = p->zero_time;
+
+  if (p->zero_time)
+    tm_start(p->load_timer, 0);
 }
 
 void
@@ -344,8 +396,6 @@ mrtload_check_config(struct proto_config *CF, struct bgp_channel_config *CC)
 
   if (!cf->filename)
     cf_error("File not specified");
-  else
-    log("%s", cf->filename);
 
   if (!CC->desc)
     cf_error("Afi not specified.");
@@ -384,10 +434,12 @@ mrtload_start(struct proto *P)
   p->addr_fam = cf->table_cf->table->addr_type;
   p->ctx_pool = rp_new(P->pool, "Mrtload route ctx");
   p->source_cnt = 0;
+  p->load_timer = tm_new(P->pool);
   HASH_INIT(p->ctx_hash, p->ctx_pool, 10);
 
   ASSERT_DIE(cf->table_cf->table);
   struct rtable_config **def_tables = cf->c.global->def_tables;
+
   if (cf->table_cf->table->addr_type == NET_IP4)
   {
     p->channel->igp_table_ip4 = cf->table_cf->table;
@@ -402,7 +454,7 @@ mrtload_start(struct proto *P)
 
   ASSERT_DIE(p->channel->igp_table_ip6 || p->channel->igp_table_ip4);
 
-  mrtload(P);
+  mrtload(p);
 
   return PS_UP;
 }
@@ -436,7 +488,8 @@ mrtload_reconfigure(struct proto *P, struct proto_config *CF)
 {
   //TODO where do we want reload mrt ?
   P->cf = CF;
-  mrtload(P);
+  struct mrtload_proto *p = (void *) P;
+  mrtload(p);
 
   return 1;
 }
index 53ebabb250c1fccc75c6b7d7ddcbf4d949976ee2..c424992f8a96524e08afbdba8a2bd208e0d18b50 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _BIRD_MRT_LOAD_H_
 #define _BIRD_MRT_LOAD_H_
 
+#include <stdio.h>
+
 #include "nest/bird.h"
 #include "nest/protocol.h"
 #include "lib/lists.h"
@@ -33,6 +35,7 @@ struct mrtload_config {
   const struct filter *filter;
   const char *filename;
   int always_add_path;
+  int time_replay;
   struct bgp_channel_config *channel_cf;
   const struct bgp_af_desc *desc;
 };
@@ -57,6 +60,12 @@ struct mrtload_proto {
   struct bgp_channel *channel;
   pool *ctx_pool;
   HASH(struct mrtload_route_ctx) ctx_hash;   // TODO : maybe it should be stored somewhere else
+  timer *load_timer;
+  int time_replay;
+  btime start_time;
+  s64 zero_time;
+  s64 next_time;
+  FILE *parsed_file;
 };
 
 
index 3bd29fb229b13514c12ef4a0ac3167fd233b2ab3..a7578270e4bbc120adad2db62e1cc9aedc5185e7 100644 (file)
@@ -10,7 +10,7 @@ CF_DEFINES
 
 CF_DECLS
 
-CF_KEYWORDS(TABLE, FILTER, FILENAME, ADD, MRTLOAD,
+CF_KEYWORDS(TABLE, FILTER, FILENAME, ADD, MRTLOAD, TIME, REPLAY,
             IPV4, IPV6, MULTICAST, MPLS, VPN4, VPN6, FLOW4, FLOW6)
 
 
@@ -29,6 +29,7 @@ mrtload_proto_item:
    proto_item
  | TABLE rtable                { MRTLOAD_CFG->table_cf = $2; }
  | FILENAME text       { MRTLOAD_CFG->filename = $2; }
+ | TIME REPLAY expr    { MRTLOAD_CFG->time_replay = $3; }
  ;