summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTuetuopay <tuetuopay@me.com>2019-03-06 19:09:25 +0100
committerTuetuopay <tuetuopay@me.com>2019-03-19 11:56:14 +0100
commite2f3a930c54c13c3174d6641fe4e6ee159966bd1 (patch)
treebdfc8e5bff81c5ba50c6b83cf37a6e434553bf65
parent0ff3b1118b3fe59859c2f6c9286f1756ba5f775d (diff)
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 <tuetuopay@me.com> Sponsored-by: Scaleway
-rw-r--r--bgpd/bgp_evpn.h2
-rw-r--r--bgpd/bgp_evpn_vty.c11
-rw-r--r--bgpd/bgp_main.c7
-rw-r--r--bgpd/bgp_zebra.c14
-rw-r--r--bgpd/bgpd.c37
-rw-r--r--bgpd/bgpd.h5
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 *);