From: Katerina Kubecova Date: Wed, 25 Jun 2025 15:02:40 +0000 (+0200) Subject: WIP: mrtload not failing, but does it actually do something? X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=27ee583e5912264e7166c58dfc15e1decc4ebb72;p=thirdparty%2Fbird.git WIP: mrtload not failing, but does it actually do something? --- diff --git a/nest/proto.c b/nest/proto.c index 14260d633..c38dfffcb 100644 --- a/nest/proto.c +++ b/nest/proto.c @@ -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; diff --git a/nest/rt-table.c b/nest/rt-table.c index 73f1b60a6..8e9b7091e 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -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); diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c index e9851cc62..39f43018b 100644 --- a/proto/bgp/attrs.c +++ b/proto/bgp/attrs.c @@ -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; } diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index 6b836cf5f..d09e15878 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -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); diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index e33f2dd2d..ee12f5080 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -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 */ diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index 35a79bc32..63ea57c24 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -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); diff --git a/proto/mrt/mrt.c b/proto/mrt/mrt.c index c460e6913..a874900b8 100644 --- a/proto/mrt/mrt.c +++ b/proto/mrt/mrt.c @@ -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 diff --git a/proto/mrt/mrt_load.c b/proto/mrt/mrt_load.c index 908eacadb..0dd51d38a 100644 --- a/proto/mrt/mrt_load.c +++ b/proto/mrt/mrt_load.c @@ -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) diff --git a/proto/mrt/mrt_load.h b/proto/mrt/mrt_load.h index 0bddb526b..479fb825b 100644 --- a/proto/mrt/mrt_load.h +++ b/proto/mrt/mrt_load.h @@ -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 };