diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c index 9c85ab79..6c4d9dcd 100644 --- a/proto/bgp/attrs.c +++ b/proto/bgp/attrs.c @@ -17,6 +17,7 @@ #include "nest/protocol.h" #include "nest/route.h" #include "lib/attrs.h" +#include "nest/mpls.h" #include "conf/conf.h" #include "lib/resource.h" #include "lib/string.h" @@ -1559,6 +1560,13 @@ bgp_finish_attrs(struct bgp_parse_state *s, ea_list **to) p->cf->local_role == BGP_ROLE_RS_CLIENT)) bgp_set_attr_u32(to, BA_ONLY_TO_CUSTOMER, 0, p->cf->remote_as); } + + /* Apply MPLS policy for labeled SAFIs */ + if (s->mpls && s->proto->p.mpls_channel) + { + struct mpls_channel *mc = (void *) s->proto->p.mpls_channel; + ea_set_attr_u32(to, &ea_gen_mpls_policy, 0, mc->label_policy); + } } diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index ea89b3b9..c93c553f 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -621,6 +621,8 @@ 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); @@ -1780,6 +1782,8 @@ 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) { @@ -1944,11 +1948,14 @@ bgp_init(struct proto_config *CF) if (cf->c.parent) cf->remote_ip = IPA_NONE; - /* Add all channels */ + /* Add all BGP channels */ struct bgp_channel_config *cc; BGP_CF_WALK_CHANNELS(cf, cc) proto_add_channel(P, &cc->c); + /* Add MPLS channel */ + proto_configure_channel(P, &P->mpls_channel, proto_cf_mpls_channel(CF)); + return P; } @@ -2365,16 +2372,23 @@ bgp_reconfigure(struct proto *P, struct proto_config *CF) WALK_LIST(C, p->p.channels) C->stale = 1; + /* Reconfigure BGP channels */ BGP_CF_WALK_CHANNELS(new, cc) { C = (struct channel *) bgp_find_channel(p, cc->afi); same = proto_configure_channel(P, &C, &cc->c) && same; } + /* Reconfigure MPLS channel */ + same = proto_configure_channel(P, &P->mpls_channel, proto_cf_mpls_channel(CF)) && 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); @@ -2884,7 +2898,7 @@ struct protocol proto_bgp = { .name = "BGP", .template = "bgp%d", .preference = DEF_PREF_BGP, - .channel_mask = NB_IP | NB_VPN | NB_FLOW, + .channel_mask = NB_IP | NB_VPN | NB_FLOW | NB_MPLS, .proto_size = sizeof(struct bgp_proto), .config_size = sizeof(struct bgp_config), .postconfig = bgp_postconfig, diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y index cdfb3cf0..07b3af7c 100644 --- a/proto/bgp/config.Y +++ b/proto/bgp/config.Y @@ -129,6 +129,7 @@ bgp_proto: bgp_proto_start proto_name '{' | bgp_proto proto_item ';' | bgp_proto bgp_proto_channel ';' + | bgp_proto mpls_channel ';' | bgp_proto LOCAL bgp_loc_opts ';' | bgp_proto LOCAL ipa ipa_scope bgp_loc_opts ';' { BGP_CFG->local_ip = $3; diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index 542ec707..b2228db7 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -1230,11 +1230,10 @@ bgp_update_next_hop_ip(struct bgp_export_state *s, eattr *a, ea_list **to) bgp_set_attr_data(to, BA_NEXT_HOP, 0, nh, ipa_nonzero(nh[1]) ? 32 : 16); s->local_next_hop = 1; - /* TODO: Use local MPLS assigned label */ if (s->mpls) { - u32 implicit_null = BGP_MPLS_NULL; - bgp_set_attr_data(to, BA_MPLS_LABEL_STACK, 0, &implicit_null, 4); + u32 label = ea_get_int(s->route->attrs, &ea_gen_mpls_label, BGP_MPLS_NULL); + bgp_set_attr_data(to, BA_MPLS_LABEL_STACK, 0, &label, 4); } else bgp_unset_attr(to, BA_MPLS_LABEL_STACK);