]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
WIP: mrtload not failing, but does it actually do something?
authorKaterina Kubecova <katerina.kubecova@nic.cz>
Wed, 25 Jun 2025 15:02:40 +0000 (17:02 +0200)
committerKaterina Kubecova <katerina.kubecova@nic.cz>
Thu, 26 Jun 2025 15:34:33 +0000 (17:34 +0200)
nest/proto.c
nest/rt-table.c
proto/bgp/attrs.c
proto/bgp/bgp.c
proto/bgp/bgp.h
proto/bgp/packets.c
proto/mrt/mrt.c
proto/mrt/mrt_load.c
proto/mrt/mrt_load.h

index 14260d633d50079b233647169775049490bf8a3a..c38dfffcbc5637155afbc6a52a1f41725c75d2eb 100644 (file)
@@ -1085,6 +1085,7 @@ proto_new(struct proto_config *cf)
 
   p->cf = cf;
   p->debug = cf->debug;
+  log("cf->mrtdump %x cf->name %s", cf->mrtdump, cf->name);
   p->mrtdump = cf->mrtdump;
   p->name = cf->name;
   p->proto = cf->protocol;
index 73f1b60a6be4a2fba7e42bf464b43aa66d6f2eb0..8e9b7091e3bf2b6137e8afd0fb12480085a10ff8 100644 (file)
@@ -2695,6 +2695,7 @@ 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)
          ctx->rte_recalculate(ctx, tab, n, new, e, NULL);
 
index e9851cc62f779aa0ba97ce6d585d4fb2ca1fa5e0..39f43018bd70a6f9025081611a56225a665c430f 100644 (file)
@@ -450,7 +450,7 @@ bgp_decode_as_path(struct bgp_parse_state *s, uint code UNUSED, uint flags, byte
 {
   int as_length = s->as4_session ? 4 : 2;
   int as_sets = s->allow_as_sets;
-  struct bgp_proto_attributes *proto_attrs = s->proto_attrs;
+  struct bgp_route_ctx *proto_attrs = s->proto_attrs;
   if (!proto_attrs)
     return;
 
@@ -1438,6 +1438,8 @@ bgp_decode_attrs(struct bgp_parse_state *s, byte *data, uint len)
   if (!s->as4_session)
     bgp_process_as4_attrs(&attrs, s->pool);
 
+  if (!s->proto_attrs)
+    return attrs;
 #define IS_LOOP(msg, args...)  { RTRACE("update is loop (" msg "), treating as withdraw", ##args); goto loop; }
 
   /* Reject routes with our ASN in AS_PATH attribute */
@@ -1991,7 +1993,7 @@ bgp_get_neighbor(rte *r)
     return as;
 
   /* If AS_PATH is not defined, we treat rte as locally originated */
-  struct bgp_proto_attributes *p = (struct bgp_proto_attributes *) ea_find(r->attrs->eattrs, EA_ROUTE_CONTEXT)->u.ptr;
+  struct bgp_route_ctx *p = (struct bgp_route_ctx *) ea_find(r->attrs->eattrs, EA_ROUTE_CONTEXT)->u.ptr;
   return p->confederation ?: p->local_as;
 }
 
@@ -2021,8 +2023,8 @@ rte_stale(rte *r)
 int
 bgp_rte_better(const struct rte_context *ctx, rte *new, rte *old)
 {
-  const struct bgp_proto_attributes *new_bgp = SKIP_BACK(const struct bgp_proto_attributes, bgp_rte_ctx, ctx);
-  const struct bgp_proto_attributes *old_bgp = bgp_get_route_context(old);
+  const struct bgp_route_ctx *new_bgp = SKIP_BACK(const struct bgp_route_ctx, bgp_rte_ctx, ctx);
+  const struct bgp_route_ctx *old_bgp = bgp_get_route_context(old);
 
   ASSERT_DIE(old_bgp); /* This means that old is actually really a bgp route */
 
@@ -2169,8 +2171,8 @@ bgp_rte_better(const struct rte_context *ctx, rte *new, rte *old)
 int
 bgp_rte_mergable(rte *pri, rte *sec)
 {
-  struct bgp_proto_attributes *pri_bgp = (struct bgp_proto_attributes *) ea_find(pri->attrs->eattrs, EA_ROUTE_CONTEXT)->u.ptr;
-  struct bgp_proto_attributes *sec_bgp = (struct bgp_proto_attributes *) ea_find(sec->attrs->eattrs, EA_ROUTE_CONTEXT)->u.ptr;
+  struct bgp_route_ctx *pri_bgp = (struct bgp_route_ctx *) ea_find(pri->attrs->eattrs, EA_ROUTE_CONTEXT)->u.ptr;
+  struct bgp_route_ctx *sec_bgp = (struct bgp_route_ctx *) ea_find(sec->attrs->eattrs, EA_ROUTE_CONTEXT)->u.ptr;
   eattr *x, *y;
   u32 p, s;
 
@@ -2254,7 +2256,7 @@ same_group(rte *r, u32 lpref, u32 lasn)
 static inline int
 use_deterministic_med(const rte *r)
 {
-  const struct bgp_proto_attributes *pa = bgp_get_route_context(r);
+  const struct bgp_route_ctx *pa = bgp_get_route_context(r);
   return pa && pa->deterministic_med;
 }
 
index 6b836cf5f884c2ebbe9e401bfaa3d7e7d0cc46b4..d09e158782f5cd0306e6bc7b58d8caf5afb6aa24 100644 (file)
@@ -2239,10 +2239,10 @@ done:
   return p->p.proto_state;
 }
 
-static uint
+uint
 bgp_format_rte_ctx(const struct rte_context *ctx, byte *buf)
 {
-  struct bgp_proto_attributes *pa = SKIP_BACK(struct bgp_proto_attributes, bgp_rte_ctx, ctx);
+  struct bgp_route_ctx *pa = SKIP_BACK(struct bgp_route_ctx, bgp_rte_ctx, ctx);
   uint buf_shift;
   buf_shift = bsprintf(buf, "loc=%I %u; ", pa->local_ip, pa->local_as);
   buf_shift += bsprintf(buf + buf_shift, "loc ID %R; ", pa->local_id);
index e33f2dd2d4002d07ea1eca94cacf5318184b129f..ee12f5080409af8d235ae8c5b4390939871716ba 100644 (file)
@@ -374,14 +374,14 @@ struct bgp_conn {
   /* from conf */ \
   BGP_ROUTE_ATTRIBUTES\
 
-struct bgp_proto_attributes { BGP_ROUTE_CONTEXT };
+struct bgp_route_ctx { BGP_ROUTE_CONTEXT };
 
 struct bgp_proto {
   struct proto p;
   const struct bgp_config *cf;         /* Shortcut to BGP configuration */
   const char *hostname;      /* Hostname for this BGP protocol */
   union {
-    struct bgp_proto_attributes proto_attrs;
+    struct bgp_route_ctx proto_attrs;
     struct { BGP_ROUTE_CONTEXT; };
   };
   u32 public_as;                       /* Externally visible ASN (local_as or confederation id) */
@@ -514,7 +514,7 @@ struct bgp_write_state {
 
 struct bgp_parse_state {
   // instead of struct bgp_proto *proto;
-  struct bgp_proto_attributes *proto_attrs;
+  struct bgp_route_ctx *proto_attrs;
   struct proto *p;
   u32 public_as;
   u8 is_mrt_parse;
@@ -678,12 +678,12 @@ rte_resolvable(rte *rt)
 
 /* attrs.c */
 
-static inline const struct bgp_proto_attributes *
+static inline const struct bgp_route_ctx *
 bgp_get_route_context(const rte *r)
 {
   const struct rte_context *ctx = rte_get_context(r);
   return (ctx && (ctx->proto_class == PROTOCOL_BGP)) ?
-    SKIP_BACK(struct bgp_proto_attributes, bgp_rte_ctx, ctx) : NULL;
+    SKIP_BACK(struct bgp_route_ctx, bgp_rte_ctx, ctx) : NULL;
 }
 
 static inline eattr *
@@ -776,6 +776,7 @@ void bgp_log_error(struct bgp_proto *p, u8 class, char *msg, unsigned code, unsi
 
 void bgp_update_next_hop(struct bgp_export_state *s, eattr *a, ea_list **to);
 byte *bgp_create_end_mark_(struct bgp_channel *c, byte *buf);
+uint bgp_format_rte_ctx(const struct rte_context *ctx, byte *buf);
 
 
 /* Packet types */
index 35a79bc32d49e0ce6196e796c1b163942559b7d7..63ea57c24d48033938f4cf74cbd69e23e3c2848d 100644 (file)
@@ -1097,8 +1097,8 @@ 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)
 {
-  ASSERT_DIE(s->p);
-  struct bgp_proto *p = (struct bgp_proto *) s->p;
+  log("bgp_apply_next_hop");
+
   struct bgp_channel *c = SKIP_BACK(struct bgp_channel, c, s->channel);
 
   if (c->cf->gw_mode == GW_DIRECT)
@@ -1107,16 +1107,16 @@ bgp_apply_next_hop(struct bgp_parse_state *s, rta *a, ip_addr gw, ip_addr ll)
 
     /* GW_DIRECT -> single_hop -> p->neigh != NULL */
     if (ipa_nonzero2(gw))
-      nbr = neigh_find(&p->p, gw, NULL, 0);
-    else if (ipa_nonzero(ll))
-      nbr = neigh_find(&p->p, ll, p->neigh->iface, 0);
+      nbr = neigh_find(s->p, gw, NULL, 0);
+    //else if (ipa_nonzero(ll)) //TODO
+    //  nbr = neigh_find(&s->p, ll, p->neigh->iface, 0);
     else
-      WITHDRAW(BAD_NEXT_HOP " - zero address");
+      WITHDRAW(BAD_NEXT_HOP " - zero address FIX ME LINK LOCAL NEXTHOP ONLY");
 
     if (!nbr)
       WITHDRAW(BAD_NEXT_HOP " - address %I not directly reachable", ipa_nonzero(gw) ? gw : ll);
 
-    if (nbr->scope == SCOPE_HOST)
+    if (nbr && nbr->scope == SCOPE_HOST)
       WITHDRAW(BAD_NEXT_HOP " - address %I is local", nbr->addr);
 
     a->dest = RTD_UNICAST;
@@ -1138,6 +1138,7 @@ 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
@@ -1752,8 +1753,9 @@ 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);
 
-    if (l > IP4_MAX_PREFIX_LENGTH)
-      bgp_parse_error(s, 10);
+    if (l > IP4_MAX_PREFIX_LENGTH){
+      bug("parse error");
+      bgp_parse_error(s, 10);}
 
     /* Decode prefix body */
     ip4_addr addr = IP4_NONE;
@@ -2784,6 +2786,7 @@ 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));
 
@@ -2798,6 +2801,7 @@ 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;
@@ -2814,10 +2818,14 @@ 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
@@ -2864,6 +2872,8 @@ bgp_parse_update(struct bgp_parse_state *s, byte *pkt, uint len, ea_list **ea)
   struct rte_ctx_adata *rcad = lp_allocz(s->pool, sizeof *rcad);
   rcad->ad.length = sizeof *rcad - sizeof rcad->ad;
   rcad->ctx = &s->proto_attrs->bgp_rte_ctx;
+  log("ctx %x, fc ptr %x (%s)", rcad->ctx, rcad->ctx->rte_recalculate, s->proto_name);
+  ASSERT_DIE(s->proto_name);
   ea_set_attr_ptr(ea, s->pool, EA_ROUTE_CONTEXT, 0, EAF_TYPE_OPAQUE, &rcad->ad);
 
   /* Check for End-of-RIB marker */
@@ -3559,6 +3569,7 @@ 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 c460e691346b0ce9e9ee0073d25b14c6fa7cbcc9..a874900b8b63a968ee7b31cb32f1dfbb27527267 100644 (file)
@@ -372,6 +372,7 @@ mrt_peer_table_dump(struct mrt_table_dump_state *s)
   put_u16(s->buf.start + s->peer_count_offset, s->peer_count);
 
   mrt_dump_message(&s->buf, s->fd);
+  log("mrt_peer_table_dump ok");
 }
 
 static void
index 908eacadb9cf949f74a6dc7306a8556f91c1fc27..0dd51d38a6123a38c9953e8e43fcdbad63acf73a 100644 (file)
@@ -80,10 +80,9 @@ mrt_parse_error(struct bgp_parse_state * ps UNUSED, uint e UNUSED)
 
                      Figure 12: BGP4MP_MESSAGE Subtype
 */
-void
-mrt_parse_bgp_message(FILE *fp, u64 *remains, bool as4)
+int
+mrt_parse_bgp_message(FILE *fp, u64 *remains, bool as4, struct bgp_route_ctx *proto_attrs)
 {
-  log("mrt_parse_bgp_message");
   u64 peer_as, local_as;
   if (as4)
   {
@@ -94,16 +93,18 @@ mrt_parse_bgp_message(FILE *fp, u64 *remains, bool as4)
     peer_as = mrtload_two_octet(fp, remains);
     local_as = mrtload_two_octet(fp, remains);
   }
+  proto_attrs->is_internal = peer_as == local_as;
 
   int interface_id = mrtload_two_octet(fp, remains);
   int addr_fam = mrtload_two_octet(fp, remains);
 
   log("peer as %i", peer_as);
-  ip_addr peer_addr, local_addr;
-  mrtload_ip(fp, remains, &peer_addr, addr_fam == 2);
-  mrtload_ip(fp, remains, &local_addr, addr_fam == 2);
 
-  log("peer as %lx local as %lx interface %x add fam %i peer %I loc %I", peer_as, local_as, interface_id, addr_fam, peer_addr, local_addr);
+  mrtload_ip(fp, remains, &proto_attrs->remote_ip, addr_fam == 2);
+  mrtload_ip(fp, remains, &proto_attrs->local_ip, addr_fam == 2);
+
+  log("peer as %lx local as %lx interface %x add fam %i peer %I loc %I", peer_as, local_as, interface_id, addr_fam, proto_attrs->remote_ip, proto_attrs->local_ip);
+  return addr_fam;
 }
 
 static void
@@ -135,8 +136,13 @@ 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)
 {
-  log("here");
-  mrt_parse_bgp_message(fp, remains, as4);
+  struct mrtload_proto *p = (void *) P;
+  struct mrtload_route_ctx *proto_attrs = (struct mrtload_route_ctx *) mb_alloc(p->ctx_pool, sizeof(struct mrtload_route_ctx));
+  int addr_fam = mrt_parse_bgp_message(fp, remains, as4, &proto_attrs->ctx);
+  log("addr fam %x", addr_fam);
+  if (addr_fam != p->addr_fam)
+    return;
+  log("continue");
 
   if (*remains < 19)
   {
@@ -149,8 +155,10 @@ 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);
   if (type != PKT_UPDATE)
     return;
 
@@ -159,6 +167,7 @@ mrt_parse_bgp4mp_message(FILE *fp, u64 *remains, bool as4, struct proto *P)
   rt_lock_source(P->main_source);
 
   struct bgp_parse_state s = {
+    .proto_name = P->name,
     .pool = lp_new(P->pool),
     .parse_error = mrt_parse_error,
     .end_mark = mrt_rx_end_mark,
@@ -168,6 +177,22 @@ mrt_parse_bgp4mp_message(FILE *fp, u64 *remains, bool as4, struct proto *P)
     .p = P,
   };
 
+  proto_attrs->ctx.bgp_rte_ctx.proto_class = PROTOCOL_BGP;
+  proto_attrs->ctx.bgp_rte_ctx.rte_better = bgp_rte_better;
+  proto_attrs->ctx.bgp_rte_ctx.rte_recalculate = NULL; //cf->deterministic_med ? bgp_rte_recalculate
+  proto_attrs->ctx.bgp_rte_ctx.format = bgp_format_rte_ctx;
+
+  // TODO: this is not the correct setting
+  proto_attrs->ctx.local_id = proto_get_router_id(P->cf);
+  proto_attrs->ctx.remote_id = 0;
+  proto_attrs->ctx.rr_client = 0;
+  proto_attrs->ctx.rs_client = 0;
+  proto_attrs->ctx.is_interior = proto_attrs->ctx.is_internal;
+
+  HASH_INSERT(p->ctx_hash, MRTLOAD_CTX, proto_attrs);
+
+  s.proto_attrs = &proto_attrs->ctx;
+
   byte buf[length];
   ASSERT_DIE(length <= remains[0]);
   mrtload_n_octet(fp, remains, buf, length);
@@ -207,7 +232,6 @@ mrt_parse_general_header(FILE *fp, struct proto *P)
   log("type %i subtype %i", type, subtype);
   if (type == MRT_BGP4MP)
   {
-    log("yeah?");
     switch (subtype)
     {
       case (MRT_BGP4MP_MESSAGE):
@@ -297,12 +321,25 @@ mrtload_start(struct proto *P)
   p->channel->desc = cf->channel_cf->desc;
   p->channel->c.channel = &channel_mrtload;
   p->channel->c.table = cf->table_cf->table;
+  p->addr_fam = cf->table_cf->table->addr_type;
+  p->ctx_pool = rp_new(P->pool, "Mrtload route ctx");
+  HASH_INIT(p->ctx_hash, p->ctx_pool, 10);
 
-  if (cf->channel_cf->igp_table_ip4)
-    p->channel->igp_table_ip4 = cf->channel_cf->igp_table_ip4->table;
+  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;
+    p->channel->igp_table_ip6 = def_tables[NET_IP6]->table;
+  }
 
-  if (cf->channel_cf->igp_table_ip6)
-    p->channel->igp_table_ip6 = cf->channel_cf->igp_table_ip6->table;
+  if (cf->table_cf->table->addr_type == NET_IP6)
+  {
+    p->channel->igp_table_ip6 = cf->table_cf->table;
+    p->channel->igp_table_ip4 = def_tables[NET_IP4]->table;
+  }
+
+  ASSERT_DIE(p->channel->igp_table_ip6 || p->channel->igp_table_ip4);
 
   mrtload(P);
 
@@ -348,6 +385,7 @@ void
 mrtload_postconfig(struct proto_config *CF)
 {
   struct mrtload_config *cf = (void *) CF;
+
   if (cf->channel_cf->c.in_filter != FILTER_ACCEPT)
     cf_error("MRT load channel in filter must be set to accept");
   if (cf->channel_cf->c.out_filter != FILTER_REJECT)
index 0bddb526b127cc37af6e3a42f4843f554db8e5f7..479fb825b01264edfcf863452d2cdc13342594c3 100644 (file)
@@ -9,6 +9,16 @@
 #include "filter/filter.h"
 #include "proto/mrt/mrt.h"
 
+#define MRTLOAD_CTX_KEY(n)             n->ctx.remote_as, n->ctx.local_as, \
+  n->ctx.is_internal
+#define MRTLOAD_CTX_NEXT(n)            n->next
+#define MRTLOAD_CTX_EQ(p1,n1,p2,n2)    p1 == p2 && n1 == n2
+#define MRTLOAD_CTX_FN(pas, las, iin)   u64_hash(pas) + u64_hash(las) + iin
+#define MRTLOAD_CTX_REHASH             mrtload_ctx_rehash
+#define MRTLOAD_CTX_PARAMS             /2, *2, 1, 1, 8, 20
+#define MRTLOAD_CTX_INIT_ORDER         6
+
+
 extern const struct channel_class channel_mrtload;
 
 struct mrtload_config {
@@ -27,6 +37,11 @@ struct mrtload_config {
   const struct bgp_af_desc *desc;
 };
 
+struct mrtload_route_ctx {
+  struct bgp_route_ctx ctx;
+  struct mrtload_route_ctx *next;
+};
+
 struct mrtload_proto {
   struct proto p;
     union {
@@ -34,8 +49,11 @@ struct mrtload_proto {
     struct { BGP_ROUTE_CONTEXT };
   };
 
+  int addr_fam;
   struct mrt_table_dump_state *table_dump;
   struct bgp_channel *channel;
+  pool *ctx_pool;
+  HASH(struct mrtload_route_ctx) ctx_hash;   // TODO : maybe it should be stored somewhere else
 };