diff options
author | Maria Matejka <mq@ucw.cz> | 2022-08-02 22:08:59 +0200 |
---|---|---|
committer | Maria Matejka <mq@ucw.cz> | 2022-08-02 22:08:59 +0200 |
commit | 71b434a987067475b517792360f58dbe03bfee9e (patch) | |
tree | a6bad599a80fd6dd16b0117f16e95a5c213cfe8d /proto | |
parent | 0072d11f3431165240656edf6ade473554b8747e (diff) | |
parent | f0507f05ce57398e135651896dace4cb68eeed54 (diff) |
Merge commit 'f0507f05ce57398e135651896dace4cb68eeed54' into thread-next
Diffstat (limited to 'proto')
-rw-r--r-- | proto/babel/babel.c | 15 | ||||
-rw-r--r-- | proto/bgp/attrs.c | 32 | ||||
-rw-r--r-- | proto/bgp/bgp.c | 15 | ||||
-rw-r--r-- | proto/bgp/bgp.h | 7 | ||||
-rw-r--r-- | proto/bgp/packets.c | 5 | ||||
-rw-r--r-- | proto/mrt/mrt.c | 4 | ||||
-rw-r--r-- | proto/ospf/ospf.c | 13 | ||||
-rw-r--r-- | proto/ospf/ospf.h | 2 | ||||
-rw-r--r-- | proto/pipe/pipe.c | 2 | ||||
-rw-r--r-- | proto/rip/rip.c | 25 | ||||
-rw-r--r-- | proto/static/static.c | 27 |
11 files changed, 104 insertions, 43 deletions
diff --git a/proto/babel/babel.c b/proto/babel/babel.c index 00b9aa79..4d024e3a 100644 --- a/proto/babel/babel.c +++ b/proto/babel/babel.c @@ -2259,7 +2259,7 @@ babel_kick_timer(struct babel_proto *p) static int babel_preexport(struct channel *C, struct rte *new) { - if (new->src->proto != C->proto) + if (new->src->owner != &C->proto->sources) return 0; /* Reject our own unreachable routes */ @@ -2289,7 +2289,7 @@ babel_rt_notify(struct proto *P, struct channel *c UNUSED, const net_addr *net, uint rt_metric = ea_get_int(new->attrs, &ea_babel_metric, 0); u64 rt_router_id = 0; - if (new->src->proto == P) + if (new->src->owner == &P->sources) { rt_seqno = ea_get_int(new->attrs, &ea_babel_seqno, 0); eattr *e = ea_find(new->attrs, &ea_babel_router_id); @@ -2373,6 +2373,12 @@ babel_postconfig(struct proto_config *CF) cf->ip6_channel = ip6 ?: ip6_sadr; } +static struct rte_owner_class babel_rte_owner_class = { + .get_route_info = babel_get_route_info, + .rte_better = babel_rte_better, + .rte_igp_metric = babel_rte_igp_metric, +}; + static struct proto * babel_init(struct proto_config *CF) { @@ -2386,8 +2392,8 @@ babel_init(struct proto_config *CF) P->if_notify = babel_if_notify; P->rt_notify = babel_rt_notify; P->preexport = babel_preexport; - P->rte_better = babel_rte_better; - P->rte_igp_metric = babel_rte_igp_metric; + + P->sources.class = &babel_rte_owner_class; return P; } @@ -2498,7 +2504,6 @@ struct protocol proto_babel = { .start = babel_start, .shutdown = babel_shutdown, .reconfigure = babel_reconfigure, - .get_route_info = babel_get_route_info, }; void diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c index a7b1a7ed..e96b175d 100644 --- a/proto/bgp/attrs.c +++ b/proto/bgp/attrs.c @@ -1671,8 +1671,9 @@ bgp_free_prefix_table(struct bgp_channel *c) } static struct bgp_prefix * -bgp_get_prefix(struct bgp_channel *c, const net_addr *net, u32 path_id) +bgp_get_prefix(struct bgp_channel *c, const net_addr *net, struct rte_src *src) { + u32 path_id = src->global_id; u32 path_id_hash = c->add_path_tx ? path_id : 0; /* We must use a different hash function than the rtable */ u32 hash = u32_hash(net_hash(net) ^ u32_hash(path_id_hash)); @@ -1690,6 +1691,7 @@ bgp_get_prefix(struct bgp_channel *c, const net_addr *net, u32 path_id) px->hash = hash; px->path_id = path_id; net_copy(px->net, net); + rt_lock_source(src); HASH_INSERT2(c->prefix_hash, PXH, c->pool, px); @@ -1756,6 +1758,8 @@ bgp_free_prefix(struct bgp_channel *c, struct bgp_prefix *px) { HASH_REMOVE2(c->prefix_hash, PXH, c->pool, px); + rt_unlock_source(rt_find_source_global(px->path_id)); + if (c->prefix_slab) sl_free(px); else @@ -1931,9 +1935,8 @@ bgp_setup_out_table(struct bgp_channel *c) int bgp_preexport(struct channel *C, rte *e) { - struct proto *SRC = e->src->proto; struct bgp_proto *p = (struct bgp_proto *) C->proto; - struct bgp_proto *src = (SRC->proto == &proto_bgp) ? (struct bgp_proto *) SRC : NULL; + struct bgp_proto *src = bgp_rte_proto(e); /* Reject our routes */ if (src == p) @@ -2002,8 +2005,7 @@ bgp_preexport(struct channel *C, rte *e) static ea_list * bgp_update_attrs(struct bgp_proto *p, struct bgp_channel *c, rte *e, ea_list *attrs0, struct linpool *pool) { - struct proto *SRC = e->src->proto; - struct bgp_proto *src = (SRC->proto == &proto_bgp) ? (void *) SRC : NULL; + struct bgp_proto *src = bgp_rte_proto(e); struct bgp_export_state s = { .proto = p, .channel = c, .pool = pool, .src = src, .route = e, .mpls = c->desc->mpls }; ea_list *attrs = attrs0; eattr *a; @@ -2121,7 +2123,7 @@ bgp_rt_notify(struct proto *P, struct channel *C, const net_addr *n, rte *new, c struct bgp_proto *p = (void *) P; struct bgp_channel *c = (void *) C; struct bgp_bucket *buck; - u32 path; + struct rte_src *path; if (new) { @@ -2133,12 +2135,12 @@ bgp_rt_notify(struct proto *P, struct channel *C, const net_addr *n, rte *new, c /* If attributes are invalid, we fail back to withdraw */ buck = attrs ? bgp_get_bucket(c, attrs) : bgp_get_withdraw_bucket(c); - path = new->src->global_id; + path = new->src; } else { buck = bgp_get_withdraw_bucket(c); - path = old->src->global_id; + path = old->src; } if (bgp_update_prefix(c, bgp_get_prefix(c, n, path), buck)) @@ -2156,7 +2158,7 @@ bgp_get_neighbor(rte *r) return as; /* If AS_PATH is not defined, we treat rte as locally originated */ - struct bgp_proto *p = (void *) r->src->proto; + struct bgp_proto *p = bgp_rte_proto(r); return p->cf->confederation ?: p->local_as; } @@ -2186,8 +2188,8 @@ rte_stale(rte *r) int bgp_rte_better(rte *new, rte *old) { - struct bgp_proto *new_bgp = (struct bgp_proto *) new->src->proto; - struct bgp_proto *old_bgp = (struct bgp_proto *) old->src->proto; + struct bgp_proto *new_bgp = bgp_rte_proto(new); + struct bgp_proto *old_bgp = bgp_rte_proto(old); eattr *x, *y; u32 n, o; @@ -2331,8 +2333,8 @@ bgp_rte_better(rte *new, rte *old) int bgp_rte_mergable(rte *pri, rte *sec) { - struct bgp_proto *pri_bgp = (struct bgp_proto *) pri->src->proto; - struct bgp_proto *sec_bgp = (struct bgp_proto *) sec->src->proto; + struct bgp_proto *pri_bgp = bgp_rte_proto(pri); + struct bgp_proto *sec_bgp = bgp_rte_proto(sec); eattr *x, *y; u32 p, s; @@ -2416,8 +2418,8 @@ same_group(rte *r, u32 lpref, u32 lasn) static inline int use_deterministic_med(struct rte_storage *r) { - struct proto *P = r->rte.src->proto; - return (P->proto == &proto_bgp) && ((struct bgp_proto *) P)->cf->deterministic_med; + struct bgp_proto *p = bgp_rte_proto(&r->rte); + return p && p->cf->deterministic_med; } int diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index 33849b0b..d240112c 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -1710,6 +1710,13 @@ done: return p->p.proto_state; } +struct rte_owner_class bgp_rte_owner_class = { + .get_route_info = bgp_get_route_info, + .rte_better = bgp_rte_better, + .rte_mergable = bgp_rte_mergable, + .rte_igp_metric = bgp_rte_igp_metric, +}; + static struct proto * bgp_init(struct proto_config *CF) { @@ -1723,10 +1730,9 @@ bgp_init(struct proto_config *CF) P->reload_routes = bgp_reload_routes; P->feed_begin = bgp_feed_begin; P->feed_end = bgp_feed_end; - P->rte_better = bgp_rte_better; - P->rte_mergable = bgp_rte_mergable; - P->rte_recalculate = cf->deterministic_med ? bgp_rte_recalculate : NULL; - P->rte_igp_metric = bgp_rte_igp_metric; + + P->sources.class = &bgp_rte_owner_class; + P->sources.rte_recalculate = cf->deterministic_med ? bgp_rte_recalculate : NULL; p->cf = cf; p->is_internal = (cf->local_as == cf->remote_as); @@ -2638,7 +2644,6 @@ struct protocol proto_bgp = { .reconfigure = bgp_reconfigure, .copy_config = bgp_copy_config, .get_status = bgp_get_status, - .get_route_info = bgp_get_route_info, .show_proto_info = bgp_show_proto_info }; diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index 469f0cb9..81382099 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -535,6 +535,7 @@ rte_resolvable(const rte *rt) return NEXTHOP_IS_REACHABLE(nhad) || (nhad->dest != RTD_UNREACHABLE); } +extern struct rte_owner_class bgp_rte_owner_class; #ifdef LOCAL_DEBUG #define BGP_FORCE_DEBUG 1 @@ -585,6 +586,12 @@ int bgp_preexport(struct channel *, struct rte *); void bgp_get_route_info(struct rte *, byte *); int bgp_total_aigp_metric_(const rte *e, u64 *metric, const struct adata **ad); +static inline struct bgp_proto *bgp_rte_proto(struct rte *rte) +{ + return (rte->src->owner->class == &bgp_rte_owner_class) ? + SKIP_BACK(struct bgp_proto, p.sources, rte->src->owner) : NULL; +} + #define BGP_AIGP_METRIC 1 #define BGP_AIGP_MAX U64(0xffffffffffffffff) diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index de976588..867be75f 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -1372,6 +1372,8 @@ bgp_rte_update(struct bgp_parse_state *s, const net_addr *n, u32 path_id, ea_lis { if (path_id != s->last_id) { + rt_unlock_source(s->last_src); + s->last_src = rt_get_source(&s->proto->p, path_id); s->last_id = path_id; @@ -2449,6 +2451,7 @@ bgp_decode_nlri(struct bgp_parse_state *s, u32 afi, byte *nlri, uint len, ea_lis s->last_id = 0; s->last_src = s->proto->p.main_source; + rt_lock_source(s->last_src); /* * IPv4 BGP and MP-BGP may be used together in one update, therefore we do not @@ -2475,6 +2478,8 @@ bgp_decode_nlri(struct bgp_parse_state *s, u32 afi, byte *nlri, uint len, ea_lis rta_free(s->cached_ea); s->cached_ea = NULL; + + rt_unlock_source(s->last_src); } static void diff --git a/proto/mrt/mrt.c b/proto/mrt/mrt.c index 5ef4cd44..f4c09ab1 100644 --- a/proto/mrt/mrt.c +++ b/proto/mrt/mrt.c @@ -472,9 +472,9 @@ mrt_rib_table_entry(struct mrt_table_dump_state *s, rte *r) #ifdef CONFIG_BGP /* Find peer index */ - if (r->src->proto->proto == &proto_bgp) + struct bgp_proto *p = bgp_rte_proto(r); + if (p) { - struct bgp_proto *p = (void *) r->src->proto; struct mrt_peer_entry *n = HASH_FIND(s->peer_hash, PEER, p->remote_id, p->remote_as, p->remote_ip); diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c index 9c25f0f0..4e29f960 100644 --- a/proto/ospf/ospf.c +++ b/proto/ospf/ospf.c @@ -377,8 +377,8 @@ ospf_init(struct proto_config *CF) P->reload_routes = ospf_reload_routes; P->feed_begin = ospf_feed_begin; P->feed_end = ospf_feed_end; - P->rte_better = ospf_rte_better; - P->rte_igp_metric = ospf_rte_igp_metric; + + P->sources.class = &ospf_rte_owner_class; return P; } @@ -492,7 +492,7 @@ ospf_preexport(struct channel *C, rte *e) struct ospf_area *oa = ospf_main_area(p); /* Reject our own routes */ - if (e->src->proto == &p->p) + if (e->sender == C->in_req.hook) return -1; /* Do not export routes to stub areas */ @@ -1506,6 +1506,12 @@ ospf_sh_lsadb(struct lsadb_show_data *ld) } +struct rte_owner_class ospf_rte_owner_class = { + .get_route_info = ospf_get_route_info, + .rte_better = ospf_rte_better, + .rte_igp_metric = ospf_rte_igp_metric, +}; + struct protocol proto_ospf = { .name = "OSPF", .template = "ospf%d", @@ -1519,7 +1525,6 @@ struct protocol proto_ospf = { .shutdown = ospf_shutdown, .reconfigure = ospf_reconfigure, .get_status = ospf_get_status, - .get_route_info = ospf_get_route_info }; struct ea_class ea_ospf_metric1 = { diff --git a/proto/ospf/ospf.h b/proto/ospf/ospf.h index 7bed5c85..3477ba5a 100644 --- a/proto/ospf/ospf.h +++ b/proto/ospf/ospf.h @@ -1002,6 +1002,8 @@ void ospf_sh_state(struct proto *P, int verbose, int reachable); void ospf_sh_lsadb(struct lsadb_show_data *ld); +extern struct rte_owner_class ospf_rte_owner_class; + /* iface.c */ void ospf_iface_chstate(struct ospf_iface *ifa, u8 state); void ospf_iface_sm(struct ospf_iface *ifa, int event); diff --git a/proto/pipe/pipe.c b/proto/pipe/pipe.c index 8af6de81..b3b50a0d 100644 --- a/proto/pipe/pipe.c +++ b/proto/pipe/pipe.c @@ -87,7 +87,7 @@ pipe_preexport(struct channel *C, rte *e) { log_rl(&p->rl_gen, L_ERR "Route overpiped (%u hops of %u configured in %s) in table %s: %N %s/%u:%u", e->generation, max_generation, C->proto->name, - C->table->name, e->net, e->src->proto->name, e->src->private_id, e->src->global_id); + C->table->name, e->net, e->src->owner->name, e->src->private_id, e->src->global_id); return -1; } diff --git a/proto/rip/rip.c b/proto/rip/rip.c index f5c01380..ab0e3f4b 100644 --- a/proto/rip/rip.c +++ b/proto/rip/rip.c @@ -377,7 +377,7 @@ rip_rt_notify(struct proto *P, struct channel *ch UNUSED, const net_addr *net, s en->valid = RIP_ENTRY_VALID; en->metric = rt_metric; en->tag = rt_tag; - en->from = (new->src->proto == P) ? rt_from : NULL; + en->from = (new->src->owner == &P->sources) ? rt_from : NULL; eattr *nhea = ea_find(new->attrs, &ea_gen_nexthop); if (nhea) @@ -1112,11 +1112,20 @@ rip_reload_routes(struct channel *C) rip_kick_timer(p); } +static struct rte_owner_class rip_rte_owner_class; + +static inline struct rip_proto * +rip_rte_proto(struct rte *rte) +{ + return (rte->src->owner->class == &rip_rte_owner_class) ? + SKIP_BACK(struct rip_proto, p.sources, rte->src->owner) : NULL; +} + static int rip_rte_better(struct rte *new, struct rte *old) { ASSERT_DIE(new->src == old->src); - struct rip_proto *p = (struct rip_proto *) new->src->proto; + struct rip_proto *p = rip_rte_proto(new); u32 new_metric = ea_get_int(new->attrs, &ea_rip_metric, p->infinity); u32 old_metric = ea_get_int(old->attrs, &ea_rip_metric, p->infinity); @@ -1151,8 +1160,7 @@ rip_init(struct proto_config *CF) P->rt_notify = rip_rt_notify; P->neigh_notify = rip_neigh_notify; P->reload_routes = rip_reload_routes; - P->rte_better = rip_rte_better; - P->rte_igp_metric = rip_rte_igp_metric; + P->sources.class = &rip_rte_owner_class; return P; } @@ -1227,7 +1235,7 @@ rip_reconfigure(struct proto *P, struct proto_config *CF) static void rip_get_route_info(rte *rte, byte *buf) { - struct rip_proto *p = (struct rip_proto *) rte->src->proto; + struct rip_proto *p = rip_rte_proto(rte); u32 rt_metric = ea_get_int(rte->attrs, &ea_rip_metric, p->infinity); u32 rt_tag = ea_get_int(rte->attrs, &ea_rip_tag, 0); @@ -1359,6 +1367,12 @@ rip_dump(struct proto *P) } +static struct rte_owner_class rip_rte_owner_class = { + .get_route_info = rip_get_route_info, + .rte_better = rip_rte_better, + .rte_igp_metric = rip_rte_igp_metric, +}; + struct protocol proto_rip = { .name = "RIP", .template = "rip%d", @@ -1372,7 +1386,6 @@ struct protocol proto_rip = { .start = rip_start, .shutdown = rip_shutdown, .reconfigure = rip_reconfigure, - .get_route_info = rip_get_route_info, }; void diff --git a/proto/static/static.c b/proto/static/static.c index f0a514f7..65f3eccc 100644 --- a/proto/static/static.c +++ b/proto/static/static.c @@ -50,11 +50,14 @@ static inline struct rte_src * static_get_source(struct static_proto *p, uint i) { return i ? rt_get_source(&p->p, i) : p->p.main_source; } +static inline void static_free_source(struct rte_src *src, uint i) +{ if (i) rt_unlock_source(src); } + static void static_announce_rte(struct static_proto *p, struct static_route *r) { + struct rte_src *src; ea_list *ea = NULL; - struct rte_src *src = static_get_source(p, r->index); ea_set_attr_u32(&ea, &ea_gen_preference, 0, p->p.main_channel->preference); ea_set_attr_u32(&ea, &ea_gen_source, 0, RTS_STATIC); @@ -114,6 +117,7 @@ static_announce_rte(struct static_proto *p, struct static_route *r) return; /* We skip rta_lookup() here */ + src = static_get_source(p, r->index); rte e0 = { .attrs = ea, .src = src, .net = r->net, }, *e = &e0; /* Evaluate the filter */ @@ -121,6 +125,8 @@ static_announce_rte(struct static_proto *p, struct static_route *r) f_eval_rte(r->cmds, e); rte_update(p->p.main_channel, r->net, e, src); + static_free_source(src, r->index); + r->state = SRS_CLEAN; return; @@ -128,7 +134,9 @@ withdraw: if (r->state == SRS_DOWN) return; + src = static_get_source(p, r->index); rte_update(p->p.main_channel, r->net, NULL, src); + static_free_source(src, r->index); r->state = SRS_DOWN; } @@ -294,7 +302,11 @@ static void static_remove_rte(struct static_proto *p, struct static_route *r) { if (r->state) - rte_update(p->p.main_channel, r->net, NULL, static_get_source(p, r->index)); + { + struct rte_src *src = static_get_source(p, r->index); + rte_update(p->p.main_channel, r->net, NULL, src); + static_free_source(src, r->index); + } static_reset_rte(p, r); } @@ -437,6 +449,8 @@ static_postconfig(struct proto_config *CF) static_index_routes(cf); } +static struct rte_owner_class static_rte_owner_class; + static struct proto * static_init(struct proto_config *CF) { @@ -448,8 +462,7 @@ static_init(struct proto_config *CF) P->neigh_notify = static_neigh_notify; P->reload_routes = static_reload_routes; - P->rte_better = static_rte_better; - P->rte_mergable = static_rte_mergable; + P->sources.class = &static_rte_owner_class; if (cf->igp_table_ip4) p->igp_table_ip4 = cf->igp_table_ip4->table; @@ -748,6 +761,11 @@ static_show(struct proto *P) static_show_rt(r); } +static struct rte_owner_class static_rte_owner_class = { + .get_route_info = static_get_route_info, + .rte_better = static_rte_better, + .rte_mergable = static_rte_mergable, +}; struct protocol proto_static = { .name = "Static", @@ -763,7 +781,6 @@ struct protocol proto_static = { .shutdown = static_shutdown, .reconfigure = static_reconfigure, .copy_config = static_copy_config, - .get_route_info = static_get_route_info, }; void |