From e711a991d4cfc8b796043c728d1da86a4acd2e6e Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Fri, 24 Nov 2023 00:05:51 +0100 Subject: [PATCH] MPLS: FEC Map moved from protocol to MPLS channel --- nest/mpls.c | 21 ++++++++++---- nest/mpls.h | 16 ++++++++++- nest/proto.c | 64 ------------------------------------------- nest/protocol.h | 4 --- nest/rt-table.c | 4 +-- proto/bgp/bgp.c | 12 ++------ proto/l3vpn/l3vpn.c | 19 ++++++------- proto/static/static.c | 10 ++----- 8 files changed, 46 insertions(+), 104 deletions(-) diff --git a/nest/mpls.c b/nest/mpls.c index 8c1c4517..2cc3e04e 100644 --- a/nest/mpls.c +++ b/nest/mpls.c @@ -565,6 +565,7 @@ mpls_channel_init(struct channel *C, struct channel_config *CC) c->domain = cc->domain->domain; c->range = cc->range->range; c->label_policy = cc->label_policy; + c->rts = cc->rts; } static int @@ -575,6 +576,9 @@ mpls_channel_start(struct channel *C) mpls_lock_domain(c->domain); mpls_lock_range(c->range); + ASSERT_DIE(c->rts); + c->mpls_map = mpls_fec_map_new(C->proto->pool, C, c->rts); + return 0; } @@ -592,6 +596,9 @@ mpls_channel_cleanup(struct channel *C) { struct mpls_channel *c = (void *) C; + mpls_fec_map_free(c->mpls_map); + c->mpls_map = NULL; + mpls_unlock_range(c->range); mpls_unlock_domain(c->domain); } @@ -623,6 +630,8 @@ mpls_channel_reconfigure(struct channel *C, struct channel_config *CC, int *impo *import_changed = 1; } + mpls_fec_map_reconfigure(c->mpls_map, C); + return 1; } @@ -1141,8 +1150,10 @@ mpls_apply_fec(rte *r, struct mpls_fec *fec) int -mpls_handle_rte(struct mpls_fec_map *m, const net_addr *n, rte *r) +mpls_handle_rte(struct channel *c, const net_addr *n, rte *r) { + struct mpls_channel *mc = SKIP_BACK(struct mpls_channel, c, c->proto->mpls_channel); + struct mpls_fec_map *m = mc->mpls_map; struct mpls_fec *fec = NULL; /* Select FEC for route */ @@ -1214,13 +1225,13 @@ mpls_handle_rte(struct mpls_fec_map *m, const net_addr *n, rte *r) static inline struct mpls_fec_tmp_lock mpls_rte_get_fec_lock(const rte *r) { - struct mpls_fec_tmp_lock mt = { - .m = SKIP_BACK(struct proto, sources, r->src->owner)->mpls_map, - }; + struct mpls_fec_tmp_lock mt = {}; - if (!mt.m) + struct channel *c = SKIP_BACK(struct proto, sources, r->src->owner)->mpls_channel; + if (!c) return mt; + mt.m = SKIP_BACK(struct mpls_channel, c, c)->mpls_map; uint label = ea_get_int(r->attrs, &ea_gen_mpls_label, 0); if (label < 16) return mt; diff --git a/nest/mpls.h b/nest/mpls.h index 60c38295..f6734001 100644 --- a/nest/mpls.h +++ b/nest/mpls.h @@ -70,6 +70,7 @@ struct mpls_channel_config { struct mpls_range_config *range; uint label_policy; + uint rts; }; struct mpls_channel { @@ -79,12 +80,25 @@ struct mpls_channel { struct mpls_range *range; uint label_policy; + uint rts; + + struct mpls_fec_map *mpls_map; /* Maps protocol routes to FECs / labels */ }; void mpls_channel_postconfig(struct channel_config *CF); extern struct channel_class channel_mpls; +static inline int +proto_configure_mpls_channel(struct proto *p, struct proto_config *pc, uint rts) +{ + struct channel_config *cf = proto_cf_mpls_channel(pc); + if (cf) + SKIP_BACK(struct mpls_channel_config, c, cf)->rts = rts; + + return proto_configure_channel(p, &p->mpls_channel, cf); +} + struct mpls_fec { u32 label; /* Label for FEC */ @@ -134,7 +148,7 @@ struct mpls_fec *mpls_get_fec_by_label(struct mpls_fec_map *m, u32 label); struct mpls_fec *mpls_get_fec_by_net(struct mpls_fec_map *m, const net_addr *net, u32 path_id); struct mpls_fec *mpls_get_fec_by_destination(struct mpls_fec_map *m, ea_list *dest); void mpls_free_fec(struct mpls_fec_map *x, struct mpls_fec *fec); -int mpls_handle_rte(struct mpls_fec_map *m, const net_addr *n, rte *r); +int mpls_handle_rte(struct channel *c, const net_addr *n, rte *r); void mpls_rte_preimport(rte *new, const rte *old); diff --git a/nest/proto.c b/nest/proto.c index 6427afcd..c67a5a3a 100644 --- a/nest/proto.c +++ b/nest/proto.c @@ -1512,70 +1512,6 @@ proto_configure_channel(struct proto *p, struct channel **pc, struct channel_con return 1; } -/** - * proto_setup_mpls_map - automatically setup FEC map for protocol - * @p: affected protocol - * @rts: RTS_* value for generated MPLS routes - * @hooks: whether to update rte_insert / rte_remove hooks - * - * Add, remove or reconfigure MPLS FEC map of the protocol @p, depends on - * whether MPLS channel exists, and setup rte_insert / rte_remove hooks with - * default MPLS handlers. It is a convenience function supposed to be called - * from the protocol start and configure hooks, after reconfiguration of - * channels. For shutdown, use proto_shutdown_mpls_map(). If caller uses its own - * rte_insert / rte_remove hooks, it is possible to disable updating hooks and - * doing that manually. - */ -void -proto_setup_mpls_map(struct proto *p, uint rts) -{ - struct mpls_fec_map *m = p->mpls_map; - struct channel *c = p->mpls_channel; - - if (!m && c) - { - /* - * Note that when called from a protocol start hook, it is called before - * mpls_channel_start(). But FEC map locks MPLS domain internally so it does - * not depend on lock from MPLS channel. - */ - p->mpls_map = mpls_fec_map_new(p->pool, c, rts); - } - else if (m && !c) - { - /* - * Note that for reconfiguration, it is called after the MPLS channel has - * been already removed. But removal of active MPLS channel would trigger - * protocol restart anyways. - */ - mpls_fec_map_free(m); - p->mpls_map = NULL; - } - else if (m && c) - { - mpls_fec_map_reconfigure(m, c); - } -} - - -/** - * proto_shutdown_mpls_map - automatically shutdown FEC map for protocol - * @p: affected protocol - * @hooks: whether to update rte_insert / rte_remove hooks - * - * Remove MPLS FEC map of the protocol @p during protocol shutdown. - */ -void -proto_shutdown_mpls_map(struct proto *p) -{ - struct mpls_fec_map *m = p->mpls_map; - - if (!m) - return; - - mpls_fec_map_free(m); - p->mpls_map = NULL; -} static void proto_cleanup(struct proto *p) diff --git a/nest/protocol.h b/nest/protocol.h index 4c983ffc..aee2c08e 100644 --- a/nest/protocol.h +++ b/nest/protocol.h @@ -34,7 +34,6 @@ struct channel; struct ea_list; struct eattr; struct symbol; -struct mpls_fec_map; /* @@ -160,7 +159,6 @@ struct proto { TLIST_LIST(proto_neigh) neighbors; /* List of neighbor structures */ struct iface_subscription iface_sub; /* Interface notification subscription */ struct channel *mpls_channel; /* MPLS channel, when used */ - struct mpls_fec_map *mpls_map; /* Maps protocol routes to FECs / labels */ const char *name; /* Name of this instance (== cf->name) */ u32 debug; /* Debugging flags */ @@ -687,8 +685,6 @@ struct channel *proto_find_channel_by_name(struct proto *p, const char *n); struct channel *proto_add_channel(struct proto *p, struct channel_config *cf); void proto_remove_channel(struct proto *p, struct channel *c); int proto_configure_channel(struct proto *p, struct channel **c, struct channel_config *cf); -void proto_setup_mpls_map(struct proto *p, uint rts); -void proto_shutdown_mpls_map(struct proto *p); void channel_set_state(struct channel *c, uint state); void channel_schedule_reload(struct channel *c, struct channel_import_request *cir); diff --git a/nest/rt-table.c b/nest/rt-table.c index e1f6683a..29ee8bd3 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -1789,8 +1789,8 @@ rte_update(struct channel *c, const net_addr *n, rte *new, struct rte_src *src) new = NULL; } - if (new && c->proto->mpls_map) - if (mpls_handle_rte(c->proto->mpls_map, n, new) < 0) + if (new && c->proto->mpls_channel) + if (mpls_handle_rte(c->proto->mpls_channel, n, new) < 0) { channel_rte_trace_in(D_FILTERS, c, new, "invalid"); stats->updates_invalid++; diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index 24b952d9..c888460a 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -116,6 +116,7 @@ #include "nest/iface.h" #include "nest/protocol.h" #include "nest/route.h" +#include "nest/mpls.h" #include "nest/cli.h" #include "nest/locks.h" #include "conf/conf.h" @@ -621,8 +622,6 @@ bgp_spawn(struct bgp_proto *pp, ip_addr remote_ip) void bgp_stop(struct bgp_proto *p, int subcode, byte *data, uint len) { - proto_shutdown_mpls_map(&p->p); - proto_notify_state(&p->p, PS_STOP); p->uncork_ev->data = NULL; bgp_graceful_close_conn(&p->outgoing_conn, subcode, data, len); @@ -1794,8 +1793,6 @@ bgp_start(struct proto *P) p->remote_id = 0; p->link_addr = IPA_NONE; - proto_setup_mpls_map(P, RTS_BGP); - /* Lock all channels when in GR recovery mode */ if (p->p.gr_recovery && p->cf->gr_mode) { @@ -1966,7 +1963,7 @@ bgp_init(struct proto_config *CF) proto_add_channel(P, &cc->c); /* Add MPLS channel */ - proto_configure_channel(P, &P->mpls_channel, proto_cf_mpls_channel(CF)); + proto_configure_mpls_channel(P, CF, RTS_BGP); return P; } @@ -2392,15 +2389,12 @@ bgp_reconfigure(struct proto *P, struct proto_config *CF) } /* Reconfigure MPLS channel */ - same = proto_configure_channel(P, &P->mpls_channel, proto_cf_mpls_channel(CF)) && same; + same = proto_configure_mpls_channel(P, CF, RTS_BGP) && same; WALK_LIST_DELSAFE(C, C2, p->p.channels) if (C->stale) same = proto_configure_channel(P, &C, NULL) && same; - if (same) - proto_setup_mpls_map(P, RTS_BGP); - if (same && (p->start_state > BSS_PREPARE)) bgp_update_bfd(p, new->bfd); diff --git a/proto/l3vpn/l3vpn.c b/proto/l3vpn/l3vpn.c index a3c5de9c..c899d202 100644 --- a/proto/l3vpn/l3vpn.c +++ b/proto/l3vpn/l3vpn.c @@ -391,7 +391,8 @@ l3vpn_init(struct proto_config *CF) proto_configure_channel(P, &p->ip6_channel, proto_cf_find_channel(CF, NET_IP6)); proto_configure_channel(P, &p->vpn4_channel, proto_cf_find_channel(CF, NET_VPN4)); proto_configure_channel(P, &p->vpn6_channel, proto_cf_find_channel(CF, NET_VPN6)); - proto_configure_channel(P, &P->mpls_channel, proto_cf_find_channel(CF, NET_MPLS)); + + proto_configure_mpls_channel(P, CF, RTS_L3VPN); P->rt_notify = l3vpn_rt_notify; P->preexport = l3vpn_preexport; @@ -414,22 +415,20 @@ l3vpn_start(struct proto *P) l3vpn_prepare_import_targets(p); l3vpn_prepare_export_targets(p); - proto_setup_mpls_map(P, RTS_L3VPN); - - P->mpls_map->vrf_iface = P->vrf; + SKIP_BACK(struct mpls_channel, c, P->mpls_channel)->mpls_map->vrf_iface = P->vrf; return PS_UP; } +#if 0 static int -l3vpn_shutdown(struct proto *P) +l3vpn_shutdown(struct proto *P UNUSED) { // struct l3vpn_proto *p = (void *) P; - proto_shutdown_mpls_map(P); - return PS_DOWN; } +#endif static int l3vpn_reconfigure(struct proto *P, struct proto_config *CF) @@ -441,7 +440,7 @@ l3vpn_reconfigure(struct proto *P, struct proto_config *CF) !proto_configure_channel(P, &p->ip6_channel, proto_cf_find_channel(CF, NET_IP6)) || !proto_configure_channel(P, &p->vpn4_channel, proto_cf_find_channel(CF, NET_VPN4)) || !proto_configure_channel(P, &p->vpn6_channel, proto_cf_find_channel(CF, NET_VPN6)) || - !proto_configure_channel(P, &P->mpls_channel, proto_cf_find_channel(CF, NET_MPLS))) + !proto_configure_mpls_channel(P, CF, RTS_L3VPN)) return 0; if (p->rd != cf->rd) @@ -454,8 +453,6 @@ l3vpn_reconfigure(struct proto *P, struct proto_config *CF) p->import_target = cf->import_target; p->export_target = cf->export_target; - proto_setup_mpls_map(P, RTS_L3VPN); - if (import_changed) { TRACE(D_EVENTS, "Import target changed"); @@ -518,7 +515,7 @@ struct protocol proto_l3vpn = { .postconfig = l3vpn_postconfig, .init = l3vpn_init, .start = l3vpn_start, - .shutdown = l3vpn_shutdown, +// .shutdown = l3vpn_shutdown, .reconfigure = l3vpn_reconfigure, .copy_config = l3vpn_copy_config, }; diff --git a/proto/static/static.c b/proto/static/static.c index 2024514f..bdccabaf 100644 --- a/proto/static/static.c +++ b/proto/static/static.c @@ -507,7 +507,7 @@ static_init(struct proto_config *CF) P->main_channel = proto_add_channel(P, proto_cf_main_channel(CF)); - proto_configure_channel(P, &P->mpls_channel, proto_cf_mpls_channel(CF)); + proto_configure_mpls_channel(P, CF, RTS_STATIC); P->iface_sub.neigh_notify = static_neigh_notify; P->reload_routes = static_reload_routes; @@ -539,8 +539,6 @@ static_start(struct proto *P) BUFFER_INIT(p->marked, p->p.pool, 4); - proto_setup_mpls_map(P, RTS_STATIC); - /* We have to go UP before routes could be installed */ proto_notify_state(P, PS_UP); @@ -558,8 +556,6 @@ static_shutdown(struct proto *P) struct static_config *cf = (void *) P->cf; struct static_route *r; - proto_shutdown_mpls_map(P); - /* Just reset the flag, the routes will be flushed by the nest */ WALK_LIST(r, cf->routes) static_reset_rte(p, r); @@ -657,11 +653,9 @@ static_reconfigure(struct proto *P, struct proto_config *CF) return 0; if (!proto_configure_channel(P, &P->main_channel, proto_cf_main_channel(CF)) || - !proto_configure_channel(P, &P->mpls_channel, proto_cf_mpls_channel(CF))) + !proto_configure_mpls_channel(P, CF, RTS_STATIC)) return 0; - proto_setup_mpls_map(P, RTS_STATIC); - p->p.cf = CF; /* Reset route lists in neighbor entries */