From e2f3a930c54c13c3174d6641fe4e6ee159966bd1 Mon Sep 17 00:00:00 2001 From: Tuetuopay Date: Wed, 6 Mar 2019 19:09:25 +0100 Subject: [PATCH] bgpd: Allow non-default instance to be EVPN one This makes the instance bearing the advertise-all-vni config option register to zebra as the EVPN one, forwarding it the option. Signed-off-by: Tuetuopay Sponsored-by: Scaleway --- bgpd/bgp_evpn.h | 2 +- bgpd/bgp_evpn_vty.c | 11 +++++++++++ bgpd/bgp_main.c | 7 +++++-- bgpd/bgp_zebra.c | 14 ++++++-------- bgpd/bgpd.c | 37 +++++++++++++++++++++++++++++++++++++ bgpd/bgpd.h | 5 +++++ 6 files changed, 65 insertions(+), 11 deletions(-) diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h index fbf30083e1..bcc524d5aa 100644 --- a/bgpd/bgp_evpn.h +++ b/bgpd/bgp_evpn.h @@ -31,7 +31,7 @@ static inline int is_evpn_enabled(void) { struct bgp *bgp = NULL; - bgp = bgp_get_default(); + bgp = bgp_get_evpn(); return bgp ? bgp->advertise_all_vni : 0; } diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index 8437c4024e..9ac1af046a 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -2757,6 +2757,7 @@ static void evpn_unset_advertise_subnet(struct bgp *bgp, struct bgpevpn *vpn) static void evpn_set_advertise_all_vni(struct bgp *bgp) { bgp->advertise_all_vni = 1; + bgp_set_evpn(bgp); bgp_zebra_advertise_all_vni(bgp, bgp->advertise_all_vni); } @@ -2767,6 +2768,7 @@ static void evpn_set_advertise_all_vni(struct bgp *bgp) static void evpn_unset_advertise_all_vni(struct bgp *bgp) { bgp->advertise_all_vni = 0; + bgp_set_evpn(bgp_get_default()); bgp_zebra_advertise_all_vni(bgp, bgp->advertise_all_vni); bgp_evpn_cleanup_on_disable(bgp); } @@ -2954,9 +2956,18 @@ DEFUN (bgp_evpn_advertise_all_vni, "Advertise All local VNIs\n") { struct bgp *bgp = VTY_GET_CONTEXT(bgp); + struct bgp *bgp_evpn = NULL; if (!bgp) return CMD_WARNING; + + bgp_evpn = bgp_get_evpn(); + if (bgp_evpn && bgp_evpn != bgp) { + vty_out(vty, "%% Please unconfigure EVPN in VRF %s\n", + bgp_evpn->name); + return CMD_WARNING_CONFIG_FAILED; + } + evpn_set_advertise_all_vni(bgp); return CMD_SUCCESS; } diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c index 47e7c1686f..697889cc6b 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c @@ -171,7 +171,7 @@ void sigusr1(void) */ static __attribute__((__noreturn__)) void bgp_exit(int status) { - struct bgp *bgp, *bgp_default; + struct bgp *bgp, *bgp_default, *bgp_evpn; struct listnode *node, *nnode; /* it only makes sense for this to be called on a clean exit */ @@ -184,13 +184,16 @@ static __attribute__((__noreturn__)) void bgp_exit(int status) bgp_close(); bgp_default = bgp_get_default(); + bgp_evpn = bgp_get_evpn(); /* reverse bgp_master_init */ for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) { - if (bgp_default == bgp) + if (bgp_default == bgp || bgp_evpn == bgp) continue; bgp_delete(bgp); } + if (bgp_evpn && bgp_evpn != bgp_default) + bgp_delete(bgp_evpn); if (bgp_default) bgp_delete(bgp_default); diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 5f0b20e029..398735d7a4 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1632,7 +1632,7 @@ int bgp_redistribute_set(struct bgp *bgp, afi_t afi, int type, return CMD_WARNING; #if ENABLE_BGP_VNC - if (bgp->vrf_id == VRF_DEFAULT + if (bgp->advertise_all_vni && type == ZEBRA_ROUTE_VNC_DIRECT) { vnc_export_bgp_enable( bgp, afi); /* only enables if mode bits cfg'd */ @@ -1794,7 +1794,7 @@ int bgp_redistribute_unset(struct bgp *bgp, afi_t afi, int type, * status. red lookup fails if there is no zebra connection. */ #if ENABLE_BGP_VNC - if (bgp->vrf_id == VRF_DEFAULT && type == ZEBRA_ROUTE_VNC_DIRECT) { + if (bgp->advertise_all_vni && type == ZEBRA_ROUTE_VNC_DIRECT) { vnc_export_bgp_disable(bgp, afi); } #endif @@ -1861,9 +1861,8 @@ void bgp_zebra_instance_register(struct bgp *bgp) /* Register for router-id, interfaces, redistributed routes. */ zclient_send_reg_requests(zclient, bgp->vrf_id); - /* For default instance, register to learn about VNIs, if appropriate. - */ - if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT && is_evpn_enabled()) + /* For EVPN instance, register to learn about VNIs, if appropriate. */ + if (bgp->advertise_all_vni) bgp_zebra_advertise_all_vni(bgp, 1); bgp_nht_register_nexthops(bgp); @@ -1881,9 +1880,8 @@ void bgp_zebra_instance_deregister(struct bgp *bgp) if (BGP_DEBUG(zebra, ZEBRA)) zlog_debug("Deregistering VRF %u", bgp->vrf_id); - /* For default instance, unregister learning about VNIs, if appropriate. - */ - if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT && is_evpn_enabled()) + /* For EVPN instance, unregister learning about VNIs, if appropriate. */ + if (bgp->advertise_all_vni) bgp_zebra_advertise_all_vni(bgp, 0); /* Deregister for router-id, interfaces, redistributed routes. */ diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index d99b402e28..8fcf417b3a 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -2872,6 +2872,12 @@ static struct bgp *bgp_create(as_t *as, const char *name, name, *as); } + /* Default the EVPN VRF to the default one */ + if (inst_type == BGP_INSTANCE_TYPE_DEFAULT && !bgp_master.bgp_evpn) { + bgp_lock(bgp); + bm->bgp_evpn = bgp; + } + bgp_lock(bgp); bgp->heuristic_coalesce = true; bgp->inst_type = inst_type; @@ -3070,6 +3076,29 @@ struct bgp *bgp_lookup_by_vrf_id(vrf_id_t vrf_id) return (vrf->info) ? (struct bgp *)vrf->info : NULL; } +/* Sets the BGP instance where EVPN is enabled */ +void bgp_set_evpn(struct bgp *bgp) +{ + if (bm->bgp_evpn == bgp) + return; + + /* First, release the reference count we hold on the instance */ + if (bm->bgp_evpn) + bgp_unlock(bm->bgp_evpn); + + bm->bgp_evpn = bgp; + + /* Increase the reference count on this new VRF */ + if (bm->bgp_evpn) + bgp_lock(bm->bgp_evpn); +} + +/* Returns the BGP instance where EVPN is enabled, if any */ +struct bgp *bgp_get_evpn(void) +{ + return bm->bgp_evpn; +} + /* handle socket creation or deletion, if necessary * this is called for all new BGP instances */ @@ -3354,6 +3383,14 @@ int bgp_delete(struct bgp *bgp) if (vrf) bgp_vrf_unlink(bgp, vrf); + /* Update EVPN VRF pointer */ + if (bm->bgp_evpn == bgp) { + if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) + bgp_set_evpn(NULL); + else + bgp_set_evpn(bgp_get_default()); + } + thread_master_free_unused(bm->master); bgp_unlock(bgp); /* initial reference */ diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index c7d137c76c..f9c269e3e6 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -150,6 +150,9 @@ struct bgp_master { /* dynamic mpls label allocation pool */ struct labelpool labelpool; + /* BGP-EVPN VRF ID. Defaults to default VRF (if any) */ + struct bgp* bgp_evpn; + bool terminating; /* global flag that sigint terminate seen */ QOBJ_FIELDS }; @@ -1506,6 +1509,8 @@ extern struct bgp *bgp_get_default(void); extern struct bgp *bgp_lookup(as_t, const char *); extern struct bgp *bgp_lookup_by_name(const char *); extern struct bgp *bgp_lookup_by_vrf_id(vrf_id_t); +extern struct bgp *bgp_get_evpn(void); +extern void bgp_set_evpn(struct bgp *bgp); extern struct peer *peer_lookup(struct bgp *, union sockunion *); extern struct peer *peer_lookup_by_conf_if(struct bgp *, const char *); extern struct peer *peer_lookup_by_hostname(struct bgp *, const char *); -- 2.39.5