0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2025-01-03 07:31:54 +00:00

MPLS: FEC Map moved from protocol to MPLS channel

This commit is contained in:
Maria Matejka 2023-11-24 00:05:51 +01:00
parent 34d040a034
commit e711a991d4
8 changed files with 46 additions and 104 deletions

View File

@ -565,6 +565,7 @@ mpls_channel_init(struct channel *C, struct channel_config *CC)
c->domain = cc->domain->domain; c->domain = cc->domain->domain;
c->range = cc->range->range; c->range = cc->range->range;
c->label_policy = cc->label_policy; c->label_policy = cc->label_policy;
c->rts = cc->rts;
} }
static int static int
@ -575,6 +576,9 @@ mpls_channel_start(struct channel *C)
mpls_lock_domain(c->domain); mpls_lock_domain(c->domain);
mpls_lock_range(c->range); mpls_lock_range(c->range);
ASSERT_DIE(c->rts);
c->mpls_map = mpls_fec_map_new(C->proto->pool, C, c->rts);
return 0; return 0;
} }
@ -592,6 +596,9 @@ mpls_channel_cleanup(struct channel *C)
{ {
struct mpls_channel *c = (void *) 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_range(c->range);
mpls_unlock_domain(c->domain); mpls_unlock_domain(c->domain);
} }
@ -623,6 +630,8 @@ mpls_channel_reconfigure(struct channel *C, struct channel_config *CC, int *impo
*import_changed = 1; *import_changed = 1;
} }
mpls_fec_map_reconfigure(c->mpls_map, C);
return 1; return 1;
} }
@ -1141,8 +1150,10 @@ mpls_apply_fec(rte *r, struct mpls_fec *fec)
int 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; struct mpls_fec *fec = NULL;
/* Select FEC for route */ /* 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 static inline struct mpls_fec_tmp_lock
mpls_rte_get_fec_lock(const rte *r) mpls_rte_get_fec_lock(const rte *r)
{ {
struct mpls_fec_tmp_lock mt = { struct mpls_fec_tmp_lock mt = {};
.m = SKIP_BACK(struct proto, sources, r->src->owner)->mpls_map,
};
if (!mt.m) struct channel *c = SKIP_BACK(struct proto, sources, r->src->owner)->mpls_channel;
if (!c)
return mt; 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); uint label = ea_get_int(r->attrs, &ea_gen_mpls_label, 0);
if (label < 16) if (label < 16)
return mt; return mt;

View File

@ -70,6 +70,7 @@ struct mpls_channel_config {
struct mpls_range_config *range; struct mpls_range_config *range;
uint label_policy; uint label_policy;
uint rts;
}; };
struct mpls_channel { struct mpls_channel {
@ -79,12 +80,25 @@ struct mpls_channel {
struct mpls_range *range; struct mpls_range *range;
uint label_policy; 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); void mpls_channel_postconfig(struct channel_config *CF);
extern struct channel_class channel_mpls; 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 { struct mpls_fec {
u32 label; /* Label for 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_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); 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); 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); void mpls_rte_preimport(rte *new, const rte *old);

View File

@ -1512,70 +1512,6 @@ proto_configure_channel(struct proto *p, struct channel **pc, struct channel_con
return 1; 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 static void
proto_cleanup(struct proto *p) proto_cleanup(struct proto *p)

View File

@ -34,7 +34,6 @@ struct channel;
struct ea_list; struct ea_list;
struct eattr; struct eattr;
struct symbol; struct symbol;
struct mpls_fec_map;
/* /*
@ -160,7 +159,6 @@ struct proto {
TLIST_LIST(proto_neigh) neighbors; /* List of neighbor structures */ TLIST_LIST(proto_neigh) neighbors; /* List of neighbor structures */
struct iface_subscription iface_sub; /* Interface notification subscription */ struct iface_subscription iface_sub; /* Interface notification subscription */
struct channel *mpls_channel; /* MPLS channel, when used */ 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) */ const char *name; /* Name of this instance (== cf->name) */
u32 debug; /* Debugging flags */ 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); struct channel *proto_add_channel(struct proto *p, struct channel_config *cf);
void proto_remove_channel(struct proto *p, struct channel *c); void proto_remove_channel(struct proto *p, struct channel *c);
int proto_configure_channel(struct proto *p, struct channel **c, struct channel_config *cf); 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_set_state(struct channel *c, uint state);
void channel_schedule_reload(struct channel *c, struct channel_import_request *cir); void channel_schedule_reload(struct channel *c, struct channel_import_request *cir);

View File

@ -1789,8 +1789,8 @@ rte_update(struct channel *c, const net_addr *n, rte *new, struct rte_src *src)
new = NULL; new = NULL;
} }
if (new && c->proto->mpls_map) if (new && c->proto->mpls_channel)
if (mpls_handle_rte(c->proto->mpls_map, n, new) < 0) if (mpls_handle_rte(c->proto->mpls_channel, n, new) < 0)
{ {
channel_rte_trace_in(D_FILTERS, c, new, "invalid"); channel_rte_trace_in(D_FILTERS, c, new, "invalid");
stats->updates_invalid++; stats->updates_invalid++;

View File

@ -116,6 +116,7 @@
#include "nest/iface.h" #include "nest/iface.h"
#include "nest/protocol.h" #include "nest/protocol.h"
#include "nest/route.h" #include "nest/route.h"
#include "nest/mpls.h"
#include "nest/cli.h" #include "nest/cli.h"
#include "nest/locks.h" #include "nest/locks.h"
#include "conf/conf.h" #include "conf/conf.h"
@ -621,8 +622,6 @@ bgp_spawn(struct bgp_proto *pp, ip_addr remote_ip)
void void
bgp_stop(struct bgp_proto *p, int subcode, byte *data, uint len) 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); proto_notify_state(&p->p, PS_STOP);
p->uncork_ev->data = NULL; p->uncork_ev->data = NULL;
bgp_graceful_close_conn(&p->outgoing_conn, subcode, data, len); bgp_graceful_close_conn(&p->outgoing_conn, subcode, data, len);
@ -1794,8 +1793,6 @@ bgp_start(struct proto *P)
p->remote_id = 0; p->remote_id = 0;
p->link_addr = IPA_NONE; p->link_addr = IPA_NONE;
proto_setup_mpls_map(P, RTS_BGP);
/* Lock all channels when in GR recovery mode */ /* Lock all channels when in GR recovery mode */
if (p->p.gr_recovery && p->cf->gr_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); proto_add_channel(P, &cc->c);
/* Add MPLS channel */ /* 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; return P;
} }
@ -2392,15 +2389,12 @@ bgp_reconfigure(struct proto *P, struct proto_config *CF)
} }
/* Reconfigure MPLS channel */ /* 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) WALK_LIST_DELSAFE(C, C2, p->p.channels)
if (C->stale) if (C->stale)
same = proto_configure_channel(P, &C, NULL) && same; same = proto_configure_channel(P, &C, NULL) && same;
if (same)
proto_setup_mpls_map(P, RTS_BGP);
if (same && (p->start_state > BSS_PREPARE)) if (same && (p->start_state > BSS_PREPARE))
bgp_update_bfd(p, new->bfd); bgp_update_bfd(p, new->bfd);

View File

@ -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->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->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->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->rt_notify = l3vpn_rt_notify;
P->preexport = l3vpn_preexport; P->preexport = l3vpn_preexport;
@ -414,22 +415,20 @@ l3vpn_start(struct proto *P)
l3vpn_prepare_import_targets(p); l3vpn_prepare_import_targets(p);
l3vpn_prepare_export_targets(p); l3vpn_prepare_export_targets(p);
proto_setup_mpls_map(P, RTS_L3VPN); SKIP_BACK(struct mpls_channel, c, P->mpls_channel)->mpls_map->vrf_iface = P->vrf;
P->mpls_map->vrf_iface = P->vrf;
return PS_UP; return PS_UP;
} }
#if 0
static int static int
l3vpn_shutdown(struct proto *P) l3vpn_shutdown(struct proto *P UNUSED)
{ {
// struct l3vpn_proto *p = (void *) P; // struct l3vpn_proto *p = (void *) P;
proto_shutdown_mpls_map(P);
return PS_DOWN; return PS_DOWN;
} }
#endif
static int static int
l3vpn_reconfigure(struct proto *P, struct proto_config *CF) 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->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->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->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; return 0;
if (p->rd != cf->rd) 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->import_target = cf->import_target;
p->export_target = cf->export_target; p->export_target = cf->export_target;
proto_setup_mpls_map(P, RTS_L3VPN);
if (import_changed) if (import_changed)
{ {
TRACE(D_EVENTS, "Import target changed"); TRACE(D_EVENTS, "Import target changed");
@ -518,7 +515,7 @@ struct protocol proto_l3vpn = {
.postconfig = l3vpn_postconfig, .postconfig = l3vpn_postconfig,
.init = l3vpn_init, .init = l3vpn_init,
.start = l3vpn_start, .start = l3vpn_start,
.shutdown = l3vpn_shutdown, // .shutdown = l3vpn_shutdown,
.reconfigure = l3vpn_reconfigure, .reconfigure = l3vpn_reconfigure,
.copy_config = l3vpn_copy_config, .copy_config = l3vpn_copy_config,
}; };

View File

@ -507,7 +507,7 @@ static_init(struct proto_config *CF)
P->main_channel = proto_add_channel(P, proto_cf_main_channel(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->iface_sub.neigh_notify = static_neigh_notify;
P->reload_routes = static_reload_routes; P->reload_routes = static_reload_routes;
@ -539,8 +539,6 @@ static_start(struct proto *P)
BUFFER_INIT(p->marked, p->p.pool, 4); 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 */ /* We have to go UP before routes could be installed */
proto_notify_state(P, PS_UP); proto_notify_state(P, PS_UP);
@ -558,8 +556,6 @@ static_shutdown(struct proto *P)
struct static_config *cf = (void *) P->cf; struct static_config *cf = (void *) P->cf;
struct static_route *r; struct static_route *r;
proto_shutdown_mpls_map(P);
/* Just reset the flag, the routes will be flushed by the nest */ /* Just reset the flag, the routes will be flushed by the nest */
WALK_LIST(r, cf->routes) WALK_LIST(r, cf->routes)
static_reset_rte(p, r); static_reset_rte(p, r);
@ -657,11 +653,9 @@ static_reconfigure(struct proto *P, struct proto_config *CF)
return 0; return 0;
if (!proto_configure_channel(P, &P->main_channel, proto_cf_main_channel(CF)) || 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; return 0;
proto_setup_mpls_map(P, RTS_STATIC);
p->p.cf = CF; p->p.cf = CF;
/* Reset route lists in neighbor entries */ /* Reset route lists in neighbor entries */