From 565cb46582040b64d5c335160ed3055a27f8950b Mon Sep 17 00:00:00 2001 From: Katerina Kubecova Date: Tue, 10 Sep 2024 09:29:12 +0200 Subject: [PATCH] commit before krt falling --- proto/bmp/bmp.c | 108 +++++++++++++++++++++++++++++++++++++++--------- proto/bmp/bmp.h | 3 +- 2 files changed, 91 insertions(+), 20 deletions(-) diff --git a/proto/bmp/bmp.c b/proto/bmp/bmp.c index 319339a5..be57653c 100644 --- a/proto/bmp/bmp.c +++ b/proto/bmp/bmp.c @@ -561,6 +561,17 @@ bmp_add_table_exp_req(struct bmp_proto *p, rtable *tab) }; rt_export_subscribe(tab, all, &bt->out_req); + /*bt->in_req = (struct rt_export_feeder) { + .name = mb_sprintf(p->p.pool, "%s.imp_request", p->p.name), + .trace_routes = c->debug, + .next_feed_index = channel_reimport_next_feed_index, + }; + bt->reimport_event = (event) { + .hook = bmp_do_pre_policy, + .data = bt, + }; + rt_feeder_subscribe(&c->table->export_all, &bt->in_req);*/ + return bt; } @@ -582,11 +593,14 @@ bmp_remove_table(struct bmp_proto *p, struct bmp_table *bt) } static void -bmp_remove_table_rt(struct bmp_proto *p, struct bmp_table *bt) +bmp_remove_table_rt(struct bmp_proto *p, struct bmp_table *bt) // still falling in krt routes... The thread synchronization was maybe not needed... { log("removing table - bmp table %x chann %x, (subscr %x uc %x)",bt, bt->channel, &bt->channel->roa_subscriptions, &bt->uc); - channel_set_state(bt->channel, CS_STOP); - channel_set_state(bt->channel, CS_DOWN); + if (bt->channel) + { + channel_set_state(bt->channel, CS_STOP); + channel_set_state(bt->channel, CS_DOWN); + } rt_export_unsubscribe(all, &bt->out_req); HASH_REMOVE(p->table_map, HASH_TABLE, bt); @@ -596,16 +610,41 @@ bmp_remove_table_rt(struct bmp_proto *p, struct bmp_table *bt) log("free table %x", bt); mb_free(bt); + //log("free done"); } -static inline struct bmp_table *bmp_get_table(struct bmp_proto *p, rtable *tab) -{ return bmp_find_table(p, tab) ?: bmp_add_table_exp_req(p, tab); } - static inline void bmp_lock_table(struct bmp_proto *p UNUSED, struct bmp_table *bt) { bt->uc++; } +struct bmp_table *bmp_get_table(struct bmp_proto *p, rtable *tab) +{ + struct bmp_table *bt = bmp_find_table(p, tab); + if (bt) + { + while (true) { + atomic_int i = bt->uc; + if (i == 0) + { + struct bmp_table *new = bmp_add_table_exp_req(p, tab); + bmp_lock_table(p, new); + return new; + } + if (atomic_compare_exchange_strong_explicit(&bt->uc, &i, i+1, memory_order_acq_rel, memory_order_relaxed)) + return bt; + } + } + struct bmp_table *new = bmp_add_table_exp_req(p, tab); + bmp_lock_table(p, new); + return new; +} + static inline void bmp_unlock_table(struct bmp_proto *p, struct bmp_table *bt) -{ bt->uc--; if (!bt->uc) bmp_remove_table_rt(p, bt); } // TODO: should it be atomic? +{ atomic_int i = 1; + if (atomic_compare_exchange_strong_explicit(&bt->uc, &i, 0, memory_order_acq_rel, memory_order_relaxed)) + bmp_remove_table_rt(p, bt); + else + bt->uc--; +} /* @@ -640,7 +679,7 @@ bmp_add_stream(struct bmp_proto *p, struct bmp_peer *bp, u32 afi, bool policy, r HASH_INSERT(p->stream_map, HASH_STREAM, bs); bs->table = bmp_get_table(p, tab); - bmp_lock_table(p, bs->table); + //bmp_lock_table(p, bs->table); bs->sender = sender; bs->sync = false; @@ -717,11 +756,9 @@ bmp_add_peer(struct bmp_proto *p, ea_list *bgp_attr) static void bmp_remove_peer(struct bmp_proto *p, struct bmp_peer *bp) { - /* struct bmp_stream *bs, *bs_next; WALK_LIST_DELSAFE(bs, bs_next, bp->streams) - bmp_remove_stream(p, bs); - */ + bmp_remove_stream(p, bs);//TODO//TODO//TODO HASH_REMOVE(p->peer_map, HASH_PEER, bp); @@ -1146,17 +1183,43 @@ bmp_rt_notify(struct proto *P, struct channel *c, const net_addr *net, bmp_route_monitor_notify(p, bgp, bs, net, new, (new ?: old)->src); } + +static void +bmp_do_pre_policy(void *bt_) +{ + struct bmp_table *bt = (struct bmp_table *)bt_; + struct bmp_proto *p = bt->p; + + RT_FEED_WALK(&bt->in_req, f) + { + bool seen = 0; + for (uint i = 0; i < f->count_routes; i++) + { + rte *r = &f->block[i]; + + if (r->flags & REF_OBSOLETE) + break; + + rte new = rte_init_from(r); + + /* Strip the later attribute layers */ + new.attrs = ea_strip_to(new.attrs, BIT32_ALL(EALS_PREIMPORT)); + } + } +} + int -bgp_next_hop_present(rte *n) +bgp_next_hop_present(const rte *n) { for (int i = 0; i < n->attrs->count; i++) { eattr a = n->attrs->attrs[i]; const struct ea_class *class = ea_class_find(a.id); log("ea class %s", class->name); - //if (class == &(get_bgp_attr_table()[BA_NEXT_HOP].class)) //TODO - // return 1; + if (class == bgp_next_hop_ea_class) + return 1; } + log("BAD RTE, BAD."); return 0; } @@ -1166,6 +1229,7 @@ bmp_rt_notify_exp_req(void *bt_) log("ok in notify exp req"); struct bmp_table *bt = (struct bmp_table *)bt_; struct bmp_proto *p = bt->p; + RT_EXPORT_WALK(&bt->out_req, u) //const struct rt_export_union *_u; { switch (u->kind) @@ -1184,7 +1248,7 @@ bmp_rt_notify_exp_req(void *bt_) { rte *new = &u->feed->block[i]; struct proto *rte_proto = (struct proto*) SKIP_BACK(struct proto, sources, new->src->owner); - if (rte_proto->proto != &proto_bgp) + if (rte_proto->proto != &proto_bgp || !bgp_next_hop_present(new)) break; struct bgp_proto *bgp = (struct bgp_proto *) rte_proto; struct bgp_channel *bc = (struct bgp_channel *) SKIP_BACK(struct channel, in_req, new->sender->req); @@ -1197,6 +1261,8 @@ bmp_rt_notify_exp_req(void *bt_) return; } log("bmp stream found feed, policy %i", bs->in_pre_policy); + if (bmp_find_peer(p, proto_state_table->attrs[bgp->p.id]) == NULL) + bug("not implemented"); bmp_route_monitor_notify(p, bgp, bs, new->net, new, new->src); } break; @@ -1204,11 +1270,11 @@ bmp_rt_notify_exp_req(void *bt_) log("export update"); const rte *new = u->update->new; const rte *old = u->update->old; - struct proto *rte_proto = (struct proto*) SKIP_BACK(struct proto, sources, new->src->owner); - if (rte_proto->proto != &proto_bgp) + struct proto *rte_proto = (struct proto*) SKIP_BACK(struct proto, sources, (new ?: old)->src->owner); + if (rte_proto->proto != &proto_bgp || !bgp_next_hop_present(new ?: old)) break; struct bgp_proto *bgp = (struct bgp_proto *) rte_proto; - struct bgp_channel *bc = (struct bgp_channel *) SKIP_BACK(struct channel, in_req, new->sender->req); + struct bgp_channel *bc = (struct bgp_channel *) SKIP_BACK(struct channel, in_req, (new ?: old)->sender->req); struct bgp_channel *src = SKIP_BACK(struct bgp_channel, c.in_req, (new ?: old)->sender->req); bool policy = (bc->c.table == src->c.table); //TODO? struct bmp_stream *bs = bmp_find_stream(p, bgp, src->afi, policy); @@ -1218,7 +1284,9 @@ bmp_rt_notify_exp_req(void *bt_) return; } log("bmp stream found update"); - bmp_route_monitor_notify(p, bgp, bs, new->net, new, (new ?: old)->src); + if (bmp_find_peer(p, proto_state_table->attrs[bgp->p.id]) == NULL) + bug("not implemented"); + bmp_route_monitor_notify(p, bgp, bs, (new ?: old)->net, new, (new ?: old)->src); } } log("end of notify fce"); @@ -1314,6 +1382,7 @@ bmp_down(struct bmp_proto *p) { ASSERT(p->started); p->started = false; + log("_!p->peer_map.count (%i) && !p->stream_map.count (%i)&& !p->table_map.count(%i)", p->peer_map.count, p->stream_map.count, p->table_map.count); TRACE(D_EVENTS, "BMP session closed"); @@ -1326,6 +1395,7 @@ bmp_down(struct bmp_proto *p) HASH_WALK_END; /* Removing peers should also remove all streams and tables */ //TODO + log("!p->peer_map.count (%i) && !p->stream_map.count (%i)&& !p->table_map.count(%i)", p->peer_map.count, p->stream_map.count, p->table_map.count); ASSERT(!p->peer_map.count && !p->stream_map.count && !p->table_map.count); } diff --git a/proto/bmp/bmp.h b/proto/bmp/bmp.h index cc92ece7..cb317748 100644 --- a/proto/bmp/bmp.h +++ b/proto/bmp/bmp.h @@ -100,9 +100,10 @@ struct bmp_table { struct bmp_table *next; struct channel *channel; struct rt_export_request out_req; + struct rt_export_feeder in_req; struct bmp_proto *p; event event; - u32 uc; + atomic_int uc; };