From: Maria Matejka Date: Thu, 9 Nov 2023 15:53:34 +0000 (+0100) Subject: Merge branch 'mq-aggregator-for-v3' into thread-next X-Git-Tag: v3.0.0~335 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=219dc0fdb5b90b7c6815635c42a4bdd1c62ab2d0;p=thirdparty%2Fbird.git Merge branch 'mq-aggregator-for-v3' into thread-next --- 219dc0fdb5b90b7c6815635c42a4bdd1c62ab2d0 diff --cc nest/proto.c index 50f302a92,88f4813ef..4b8fef03d --- a/nest/proto.c +++ b/nest/proto.c @@@ -46,27 -49,19 +46,26 @@@ static char *c_states[] = { "DOWN", "ST extern struct protocol proto_unix_iface; --static void channel_request_reload(struct channel *c); -static void proto_shutdown_loop(timer *); static void proto_rethink_goal(struct proto *p); static char *proto_state_name(struct proto *p); -static void channel_verify_limits(struct channel *c); -static inline void channel_reset_limit(struct channel_limit *l); - +static void channel_init_limit(struct channel *c, struct limit *l, int dir, struct channel_limit *cf); +static void channel_update_limit(struct channel *c, struct limit *l, int dir, struct channel_limit *cf); +static void channel_reset_limit(struct channel *c, struct limit *l, int dir); +static int channel_refeed_prefilter(const struct rt_prefilter *p, const net_addr *n); +static int channel_import_prefilter(const struct rt_prefilter *p, const net_addr *n); +static void channel_feed_end(struct channel *c); +static void channel_stop_export(struct channel *c); +static void channel_export_stopped(struct rt_export_request *req); +static void channel_refeed_stopped(struct rt_export_request *req); +static void channel_check_stopped(struct channel *c); +static void channel_reload_in_done(struct channel_import_request *cir); +static void channel_request_partial_reload(struct channel *c, struct channel_import_request *cir); static inline int proto_is_done(struct proto *p) -{ return (p->proto_state == PS_DOWN) && (p->active_channels == 0); } +{ return (p->proto_state == PS_DOWN) && proto_is_inactive(p); } static inline int channel_is_active(struct channel *c) -{ return (c->channel_state == CS_START) || (c->channel_state == CS_UP); } +{ return (c->channel_state != CS_DOWN); } static inline int channel_reloadable(struct channel *c) { return c->proto->reload_routes && c->reloadable; } @@@ -1232,15 -732,9 +1231,15 @@@ channel_stop_export(struct channel *c } static void +channel_import_request_done_dynamic(struct channel_import_request *req) +{ + mb_free(req); +} + - static void ++void channel_request_reload(struct channel *c) { - ASSERT(c->channel_state == CS_UP); + ASSERT(c->in_req.hook); ASSERT(channel_reloadable(c)); CD(c, "Reload requested"); diff --cc nest/protocol.h index bcd54bdc2,af2a5d687..f3bf6b465 --- a/nest/protocol.h +++ b/nest/protocol.h @@@ -697,53 -641,25 +697,55 @@@ int channel_import_request_prefilter(st static inline void channel_init(struct channel *c) { channel_set_state(c, CS_START); } static inline void channel_open(struct channel *c) { channel_set_state(c, CS_UP); } -static inline void channel_close(struct channel *c) { channel_set_state(c, CS_FLUSHING); } +static inline void channel_close(struct channel *c) { channel_set_state(c, CS_STOP); } + +struct channel_feeding_request { + struct channel_feeding_request *next; /* Next in request chain */ + void (*done)(struct channel_feeding_request *); /* Called when refeed finishes */ + const struct f_trie *trie; /* Reload only matching nets */ + PACKED enum channel_feeding_request_type { + CFRT_DIRECT = 1, /* Refeed by export restart */ + CFRT_AUXILIARY, /* Refeed by auxiliary request */ + } type; + PACKED enum { + CFRS_INACTIVE = 0, /* Inactive request */ + CFRS_PENDING, /* Request enqueued, do not touch */ + CFRS_RUNNING, /* Request active, do not touch */ + } state; +}; -void channel_request_feeding(struct channel *c); -void *channel_config_new(const struct channel_class *cc, const char *name, uint net_type, struct proto_config *proto); -void *channel_config_get(const struct channel_class *cc, const char *name, uint net_type, struct proto_config *proto); -int channel_reconfigure(struct channel *c, struct channel_config *cf); +struct channel *channel_from_export_request(struct rt_export_request *req); +void channel_request_feeding(struct channel *c, struct channel_feeding_request *); +void channel_request_feeding_dynamic(struct channel *c, enum channel_feeding_request_type); +static inline int channel_net_is_refeeding(struct channel *c, const net_addr *n) +{ + /* Not refeeding if not refeeding at all */ + if (!c->refeeding || !c->refeed_trie) + return 0; -/* Moved from route.h to avoid dependency conflicts */ -static inline void rte_update(struct proto *p, const net_addr *n, rte *new) { rte_update2(p->main_channel, n, new, p->main_source); } + /* Not refeeding if already refed */ + if (trie_match_net(c->refeed_trie, n)) + return 0; -static inline void -rte_update3(struct channel *c, const net_addr *n, rte *new, struct rte_src *src) -{ - if (c->in_table && !rte_update_in(c, n, new, src)) - return; + /* Refeeding if matching any request */ + for (struct channel_feeding_request *cfr = c->refeeding; cfr; cfr = cfr->next) + if (!cfr->trie || trie_match_net(cfr->trie, n)) + return 1; - rte_update2(c, n, new, src); + /* Not matching any request */ + return 0; } +static inline void channel_net_mark_refed(struct channel *c, const net_addr *n) +{ + ASSERT_DIE(c->refeeding && c->refeed_trie); + trie_add_prefix(c->refeed_trie, n, n->pxlen, n->pxlen); +} + ++void channel_request_reload(struct channel *c); + +void *channel_config_new(const struct channel_class *cc, const char *name, uint net_type, struct proto_config *proto); +void *channel_config_get(const struct channel_class *cc, const char *name, uint net_type, struct proto_config *proto); +int channel_reconfigure(struct channel *c, struct channel_config *cf); #endif diff --cc proto/bgp/bgp.c index c93c553ff,f8146bdf7..24b952d9b --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@@ -1592,24 -1414,26 +1592,36 @@@ bgp_reload_routes(struct channel *C, st struct bgp_proto *p = (void *) C->proto; struct bgp_channel *c = (void *) C; + /* For MPLS channel, reload all MPLS-aware channels */ + if (C == p->p.mpls_channel) + { + BGP_WALK_CHANNELS(p, c) - if ((c->desc->mpls) && (p->route_refresh || c->c.in_table)) - bgp_reload_routes(&c->c); ++ if ((c->desc->mpls) && (p->route_refresh || c->cf->import_table)) ++ channel_request_reload(&c->c); + - return; ++ /* Ignoring CIR, reloading always everything */ ++ cir->done(cir); ++ return 1; + } + /* Ignore non-BGP channels */ - if (C->channel != &channel_bgp) - return; + if (C->class != &channel_bgp) + { + cir->done(cir); + return 1; + } - ASSERT(p->conn && (p->route_refresh || c->c.in_table)); + if (cir->trie) + { + cir->done(cir); + return 0; + } + /* We do not need cir anymore and later we will not be able to detect when to free it. */ + cir->done(cir); - if (c->c.in_table) - channel_schedule_reload(C); - else - bgp_schedule_packet(p->conn, c, PKT_ROUTE_REFRESH); + ASSERT(p->conn && p->route_refresh); + bgp_schedule_packet(p->conn, c, PKT_ROUTE_REFRESH); + return 1; } static void diff --cc proto/l3vpn/l3vpn.c index 7b3d86d2a,b7f60504f..eace62d09 --- a/proto/l3vpn/l3vpn.c +++ b/proto/l3vpn/l3vpn.c @@@ -298,31 -296,17 +298,34 @@@ l3vpn_reload_routes(struct channel *C, break; case NET_MPLS: - /* FIXME */ - channel_request_feeding(p->ip4_channel); - channel_request_feeding(p->ip6_channel); - break; ++ /* MPLS doesn't support partial refeed, always do a full one. */ ++ channel_request_feeding_dynamic(p->ip4_channel, CFRT_DIRECT); ++ channel_request_feeding_dynamic(p->ip6_channel, CFRT_DIRECT); ++ cir->done(cir); + return 1; } -} -static inline u32 -l3vpn_metric(rte *e) -{ - u32 metric = ea_get_int(e->attrs->eattrs, EA_GEN_IGP_METRIC, e->attrs->igp_metric); - return MIN(metric, IGP_METRIC_UNKNOWN); + if (cir->trie) + { + struct import_to_export_reload *reload = lp_alloc(cir->trie->lp, sizeof *reload); + *reload = (struct import_to_export_reload) { + .cir = cir, + .cfr = { + .type = CFRT_AUXILIARY, + .done = pipe_import_by_refeed_free, + .trie = cir->trie, + }, + }; + channel_request_feeding(feed, &reload->cfr); + } + else + { + /* Route reload on one channel is just refeed on the other */ + channel_request_feeding_dynamic(feed, CFRT_DIRECT); + cir->done(cir); + } + + return 1; } static int