0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-11-08 12:18:42 +00:00

BGP: Add MPLS support

When MPLS is active, received routes on MPLS-aware SAFIs (ipvX-mpls,
vpnX-mpls) are automatically labeled according to active label policy and
corresponding MPLS routes are automatically generated. Also routes sent
on MPLS-aware SAFIs announce local labels when it should be done.
This commit is contained in:
Ondrej Zajicek 2022-09-15 02:30:15 +02:00
parent 15c86ed061
commit 9d456d5366
4 changed files with 27 additions and 5 deletions

View File

@ -17,6 +17,7 @@
#include "nest/protocol.h" #include "nest/protocol.h"
#include "nest/route.h" #include "nest/route.h"
#include "nest/attrs.h" #include "nest/attrs.h"
#include "nest/mpls.h"
#include "conf/conf.h" #include "conf/conf.h"
#include "lib/resource.h" #include "lib/resource.h"
#include "lib/string.h" #include "lib/string.h"
@ -1501,6 +1502,13 @@ bgp_finish_attrs(struct bgp_parse_state *s, rta *a)
p->cf->local_role == BGP_ROLE_RS_CLIENT)) p->cf->local_role == BGP_ROLE_RS_CLIENT))
bgp_set_attr_u32(&a->eattrs, s->pool, BA_ONLY_TO_CUSTOMER, 0, p->cf->remote_as); bgp_set_attr_u32(&a->eattrs, s->pool, 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(&a->eattrs, s->pool, EA_MPLS_POLICY, 0, EAF_TYPE_INT, mc->label_policy);
}
} }

View File

@ -522,6 +522,8 @@ 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, 1);
proto_notify_state(&p->p, PS_STOP); proto_notify_state(&p->p, PS_STOP);
bgp_graceful_close_conn(&p->outgoing_conn, subcode, data, len); bgp_graceful_close_conn(&p->outgoing_conn, subcode, data, len);
bgp_graceful_close_conn(&p->incoming_conn, subcode, data, len); bgp_graceful_close_conn(&p->incoming_conn, subcode, data, len);
@ -1573,6 +1575,8 @@ 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, 1);
/* 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)
{ {
@ -1729,11 +1733,14 @@ bgp_init(struct proto_config *CF)
if (cf->c.parent) if (cf->c.parent)
cf->remote_ip = IPA_NONE; cf->remote_ip = IPA_NONE;
/* Add all channels */ /* Add all BGP channels */
struct bgp_channel_config *cc; struct bgp_channel_config *cc;
BGP_CF_WALK_CHANNELS(cf, cc) BGP_CF_WALK_CHANNELS(cf, cc)
proto_add_channel(P, &cc->c); proto_add_channel(P, &cc->c);
/* Add MPLS channel */
proto_configure_channel(P, &P->mpls_channel, proto_cf_mpls_channel(CF));
return P; return P;
} }
@ -2153,16 +2160,23 @@ bgp_reconfigure(struct proto *P, struct proto_config *CF)
WALK_LIST(C, p->p.channels) WALK_LIST(C, p->p.channels)
C->stale = 1; C->stale = 1;
/* Reconfigure BGP channels */
BGP_CF_WALK_CHANNELS(new, cc) BGP_CF_WALK_CHANNELS(new, cc)
{ {
C = (struct channel *) bgp_find_channel(p, cc->afi); C = (struct channel *) bgp_find_channel(p, cc->afi);
same = proto_configure_channel(P, &C, &cc->c) && same; 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) 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, 1);
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);
@ -2653,7 +2667,7 @@ struct protocol proto_bgp = {
.template = "bgp%d", .template = "bgp%d",
.class = PROTOCOL_BGP, .class = PROTOCOL_BGP,
.preference = DEF_PREF_BGP, .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), .proto_size = sizeof(struct bgp_proto),
.config_size = sizeof(struct bgp_config), .config_size = sizeof(struct bgp_config),
.postconfig = bgp_postconfig, .postconfig = bgp_postconfig,

View File

@ -129,6 +129,7 @@ bgp_proto:
bgp_proto_start proto_name '{' bgp_proto_start proto_name '{'
| bgp_proto proto_item ';' | bgp_proto proto_item ';'
| bgp_proto bgp_proto_channel ';' | bgp_proto bgp_proto_channel ';'
| bgp_proto mpls_channel ';'
| bgp_proto LOCAL bgp_loc_opts ';' | bgp_proto LOCAL bgp_loc_opts ';'
| bgp_proto LOCAL ipa ipa_scope bgp_loc_opts ';' { | bgp_proto LOCAL ipa ipa_scope bgp_loc_opts ';' {
BGP_CFG->local_ip = $3; BGP_CFG->local_ip = $3;

View File

@ -1217,11 +1217,10 @@ bgp_update_next_hop_ip(struct bgp_export_state *s, eattr *a, ea_list **to)
bgp_set_attr_data(to, s->pool, BA_NEXT_HOP, 0, nh, ipa_nonzero(nh[1]) ? 32 : 16); bgp_set_attr_data(to, s->pool, BA_NEXT_HOP, 0, nh, ipa_nonzero(nh[1]) ? 32 : 16);
s->local_next_hop = 1; s->local_next_hop = 1;
/* TODO: Use local MPLS assigned label */
if (s->mpls) if (s->mpls)
{ {
u32 implicit_null = BGP_MPLS_NULL; u32 label = ea_get_int(s->route->attrs->eattrs, EA_MPLS_LABEL, BGP_MPLS_NULL);
bgp_set_attr_data(to, s->pool, BA_MPLS_LABEL_STACK, 0, &implicit_null, 4); bgp_set_attr_data(to, s->pool, BA_MPLS_LABEL_STACK, 0, &label, 4);
} }
else else
bgp_unset_attr(to, s->pool, BA_MPLS_LABEL_STACK); bgp_unset_attr(to, s->pool, BA_MPLS_LABEL_STACK);