c->domain = cc->domain->domain;
c->range = cc->range->range;
c->label_policy = cc->label_policy;
+ c->rts = cc->rts;
}
static int
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;
}
{
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);
}
*import_changed = 1;
}
+ mpls_fec_map_reconfigure(c->mpls_map, C);
+
return 1;
}
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 */
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;
struct mpls_range_config *range;
uint label_policy;
+ uint rts;
};
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 */
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);
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)
struct ea_list;
struct eattr;
struct symbol;
-struct mpls_fec_map;
/*
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 */
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);
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++;
#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"
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);
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)
{
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;
}
}
/* 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);
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;
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)
!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)
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");
.postconfig = l3vpn_postconfig,
.init = l3vpn_init,
.start = l3vpn_start,
- .shutdown = l3vpn_shutdown,
+// .shutdown = l3vpn_shutdown,
.reconfigure = l3vpn_reconfigure,
.copy_config = l3vpn_copy_config,
};
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;
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);
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);
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 */