summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_evpn.c29
-rw-r--r--bgpd/bgp_evpn_mh.c58
-rw-r--r--bgpd/bgp_evpn_mh.h6
-rw-r--r--bgpd/bgp_main.c10
-rw-r--r--bgpd/bgp_nb_config.c102
-rw-r--r--bgpd/bgp_vty.c4
-rw-r--r--bgpd/bgp_zebra.c19
-rw-r--r--bgpd/bgpd.c48
-rw-r--r--bgpd/bgpd.h2
-rw-r--r--tests/lib/test_assert.c2
-rw-r--r--zebra/redistribute.c17
11 files changed, 192 insertions, 105 deletions
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index fae3f1000f..d8e57419ee 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -3562,8 +3562,12 @@ static int update_advertise_vni_routes(struct bgp *bgp, struct bgpevpn *vpn)
const struct prefix_evpn *evp =
(const struct prefix_evpn *)bgp_dest_get_prefix(dest);
- /* Identify MAC-IP local routes. */
- if (evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE)
+ /*
+ * We have already processed type-3 routes.
+ * Process only type-1 and type-2 routes here.
+ */
+ if (evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE
+ && evp->prefix.route_type != BGP_EVPN_AD_ROUTE)
continue;
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
@@ -3581,10 +3585,23 @@ static int update_advertise_vni_routes(struct bgp *bgp, struct bgpevpn *vpn)
global_dest = bgp_global_evpn_node_get(bgp->rib[afi][safi], afi, safi,
evp, &vpn->prd);
assert(global_dest);
- update_evpn_route_entry(bgp, vpn, afi, safi, global_dest, attr, 1,
- &global_pi, 0,
- mac_mobility_seqnum(attr),
+
+ if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
+ /* Type-2 route */
+ update_evpn_route_entry(
+ bgp, vpn, afi, safi, global_dest, attr, 1,
+ &global_pi, 0, mac_mobility_seqnum(attr),
false /* setup_sync */, NULL /* old_is_sync */);
+ } else {
+ /* Type-1 route */
+ struct bgp_evpn_es *es;
+ int route_changed = 0;
+
+ es = bgp_evpn_es_find(&evp->prefix.ead_addr.esi);
+ bgp_evpn_mh_route_update(bgp, es, vpn, afi, safi,
+ global_dest, attr, 1,
+ &global_pi, &route_changed);
+ }
/* Schedule for processing and unlock node. */
bgp_process(bgp, global_dest, afi, safi);
@@ -3630,6 +3647,8 @@ static int delete_withdraw_vni_routes(struct bgp *bgp, struct bgpevpn *vpn)
bgp_dest_unlock_node(global_dest);
}
+
+ delete_global_ead_evi_routes(bgp, vpn);
return 0;
}
diff --git a/bgpd/bgp_evpn_mh.c b/bgpd/bgp_evpn_mh.c
index 6467ff8a28..59bced6f93 100644
--- a/bgpd/bgp_evpn_mh.c
+++ b/bgpd/bgp_evpn_mh.c
@@ -347,11 +347,10 @@ static void bgp_evpn_es_route_del_all(struct bgp *bgp, struct bgp_evpn_es *es)
* Note: vpn is applicable only to EAD-EVI routes (NULL for EAD-ES and
* ESR).
*/
-static int bgp_evpn_mh_route_update(struct bgp *bgp, struct bgp_evpn_es *es,
- struct bgpevpn *vpn, afi_t afi, safi_t safi,
- struct bgp_dest *dest, struct attr *attr,
- int add, struct bgp_path_info **ri,
- int *route_changed)
+int bgp_evpn_mh_route_update(struct bgp *bgp, struct bgp_evpn_es *es,
+ struct bgpevpn *vpn, afi_t afi, safi_t safi,
+ struct bgp_dest *dest, struct attr *attr, int add,
+ struct bgp_path_info **ri, int *route_changed)
{
struct bgp_path_info *tmp_pi = NULL;
struct bgp_path_info *local_pi = NULL; /* local route entry if any */
@@ -384,7 +383,8 @@ static int bgp_evpn_mh_route_update(struct bgp *bgp, struct bgp_evpn_es *es,
flog_err(
EC_BGP_ES_INVALID,
"%u ERROR: local es route for ESI: %s Vtep %pI4 also learnt from remote",
- bgp->vrf_id, es->esi_str, &es->originator_ip);
+ bgp->vrf_id, es ? es->esi_str : "Null",
+ &es->originator_ip);
return -1;
}
@@ -441,7 +441,7 @@ static int bgp_evpn_mh_route_update(struct bgp *bgp, struct bgp_evpn_es *es,
if (BGP_DEBUG(evpn_mh, EVPN_MH_RT))
zlog_debug(
"local ES %s vni %u route-type %s nexthop %pI4 updated",
- es->esi_str, vpn ? vpn->vni : 0,
+ es ? es->esi_str : "Null", vpn ? vpn->vni : 0,
evp->prefix.route_type == BGP_EVPN_ES_ROUTE
? "esr"
: (vpn ? "ead-evi" : "ead-es"),
@@ -524,6 +524,50 @@ static int bgp_evpn_mh_route_delete(struct bgp *bgp, struct bgp_evpn_es *es,
return 0;
}
+/*
+ * This function is called when the VNI RD changes.
+ * Delete all EAD/EVI local routes for this VNI from the global routing table.
+ * These routes are scheduled for withdraw from peers.
+ */
+int delete_global_ead_evi_routes(struct bgp *bgp, struct bgpevpn *vpn)
+{
+ afi_t afi;
+ safi_t safi;
+ struct bgp_dest *rdrn, *rn;
+ struct bgp_table *table;
+ struct bgp_path_info *pi;
+
+ afi = AFI_L2VPN;
+ safi = SAFI_EVPN;
+
+ /* Find the RD node for the VNI in the global table */
+ rdrn = bgp_node_lookup(bgp->rib[afi][safi], (struct prefix *)&vpn->prd);
+ if (rdrn && bgp_dest_has_bgp_path_info_data(rdrn)) {
+ table = bgp_dest_get_bgp_table_info(rdrn);
+
+ /*
+ * Iterate over all the routes in this table and delete EAD/EVI
+ * routes
+ */
+ for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
+ struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p;
+
+ if (evp->prefix.route_type != BGP_EVPN_AD_ROUTE)
+ continue;
+
+ delete_evpn_route_entry(bgp, afi, safi, rn, &pi);
+ if (pi)
+ bgp_process(bgp, rn, afi, safi);
+ }
+ }
+
+ /* Unlock RD node. */
+ if (rdrn)
+ bgp_dest_unlock_node(rdrn);
+
+ return 0;
+}
+
/*****************************************************************************
* Ethernet Segment (Type-4) Routes
* ESRs are used for DF election. Currently service-carving described in
diff --git a/bgpd/bgp_evpn_mh.h b/bgpd/bgp_evpn_mh.h
index c96de86871..22a4215664 100644
--- a/bgpd/bgp_evpn_mh.h
+++ b/bgpd/bgp_evpn_mh.h
@@ -377,6 +377,12 @@ extern int bgp_evpn_es_route_install_uninstall(struct bgp *bgp,
struct prefix_evpn *evp, struct bgp_path_info *pi,
int install);
extern void update_type1_routes_for_evi(struct bgp *bgp, struct bgpevpn *vpn);
+extern int delete_global_ead_evi_routes(struct bgp *bgp, struct bgpevpn *vpn);
+extern int bgp_evpn_mh_route_update(struct bgp *bgp, struct bgp_evpn_es *es,
+ struct bgpevpn *vpn, afi_t afi, safi_t safi,
+ struct bgp_dest *dest, struct attr *attr,
+ int add, struct bgp_path_info **ri,
+ int *route_changed);
int bgp_evpn_type1_route_process(struct peer *peer, afi_t afi, safi_t safi,
struct attr *attr, uint8_t *pfx, int psize,
uint32_t addpath_id);
diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c
index ddc5c61ee7..d545becded 100644
--- a/bgpd/bgp_main.c
+++ b/bgpd/bgp_main.c
@@ -314,9 +314,6 @@ static int bgp_vrf_enable(struct vrf *vrf)
bgp_vrf_link(bgp, vrf);
bgp_handle_socket(bgp, vrf, old_vrf_id, true);
- /* Update any redistribution if vrf_id changed */
- if (old_vrf_id != bgp->vrf_id)
- bgp_redistribute_redo(bgp);
bgp_instance_up(bgp);
vpn_leak_zebra_vrf_label_update(bgp, AFI_IP);
vpn_leak_zebra_vrf_label_update(bgp, AFI_IP6);
@@ -336,7 +333,6 @@ static int bgp_vrf_enable(struct vrf *vrf)
static int bgp_vrf_disable(struct vrf *vrf)
{
struct bgp *bgp;
- vrf_id_t old_vrf_id;
if (vrf->vrf_id == VRF_DEFAULT)
return 0;
@@ -358,15 +354,11 @@ static int bgp_vrf_disable(struct vrf *vrf)
vpn_leak_prechange(BGP_VPN_POLICY_DIR_FROMVPN, AFI_IP6,
bgp_get_default(), bgp);
- old_vrf_id = bgp->vrf_id;
bgp_handle_socket(bgp, vrf, VRF_UNKNOWN, false);
/* We have instance configured, unlink from VRF and make it
* "down". */
- bgp_vrf_unlink(bgp, vrf);
- /* Delete any redistribute vrf bitmaps if the vrf_id changed */
- if (old_vrf_id != bgp->vrf_id)
- bgp_unset_redist_vrf_bitmaps(bgp, old_vrf_id);
bgp_instance_down(bgp);
+ bgp_vrf_unlink(bgp, vrf);
}
/* Note: This is a callback, the VRF will be deleted by the caller. */
diff --git a/bgpd/bgp_nb_config.c b/bgpd/bgp_nb_config.c
index ff2c8ce93e..8ca7836a99 100644
--- a/bgpd/bgp_nb_config.c
+++ b/bgpd/bgp_nb_config.c
@@ -111,15 +111,24 @@ int bgp_router_create(struct nb_cb_create_args *args)
is_new_bgp = (bgp_lookup_by_name(name) == NULL);
ret = bgp_get_vty(&bgp, &as, name, inst_type);
- switch (ret) {
- case BGP_ERR_AS_MISMATCH:
- snprintf(args->errmsg, args->errmsg_len,
- "BGP instance is already running; AS is %u",
- as);
- return NB_ERR_INCONSISTENCY;
- case BGP_ERR_INSTANCE_MISMATCH:
- snprintf(args->errmsg, args->errmsg_len,
- "BGP instance type mismatch");
+ if (ret) {
+ switch (ret) {
+ case BGP_ERR_AS_MISMATCH:
+ snprintf(
+ args->errmsg, args->errmsg_len,
+ "BGP instance is already running; AS is %u",
+ as);
+ break;
+ case BGP_ERR_INSTANCE_MISMATCH:
+ snprintf(args->errmsg, args->errmsg_len,
+ "BGP instance type mismatch");
+ break;
+ }
+
+ UNSET_FLAG(bgp->vrf_flags, BGP_VRF_AUTO);
+
+ nb_running_set_entry(args->dnode, bgp);
+
return NB_ERR_INCONSISTENCY;
}
@@ -221,64 +230,26 @@ int bgp_router_destroy(struct nb_cb_destroy_args *args)
int bgp_global_local_as_modify(struct nb_cb_modify_args *args)
{
struct bgp *bgp;
- as_t as;
- const struct lyd_node *vrf_dnode;
- const char *vrf_name;
- const char *name = NULL;
- enum bgp_instance_type inst_type;
- int ret;
- bool is_view_inst = false;
switch (args->event) {
case NB_EV_VALIDATE:
- as = yang_dnode_get_uint32(args->dnode, NULL);
-
- inst_type = BGP_INSTANCE_TYPE_DEFAULT;
-
- vrf_dnode = yang_dnode_get_parent(args->dnode,
- "control-plane-protocol");
- vrf_name = yang_dnode_get_string(vrf_dnode, "./vrf");
-
- if (strmatch(vrf_name, VRF_DEFAULT_NAME)) {
- name = NULL;
- } else {
- name = vrf_name;
- inst_type = BGP_INSTANCE_TYPE_VRF;
- }
-
- is_view_inst = yang_dnode_get_bool(args->dnode,
- "../instance-type-view");
- if (is_view_inst)
- inst_type = BGP_INSTANCE_TYPE_VIEW;
-
- ret = bgp_lookup_by_as_name_type(&bgp, &as, name, inst_type);
- switch (ret) {
- case BGP_ERR_AS_MISMATCH:
- snprintf(args->errmsg, args->errmsg_len,
- "BGP instance is already running; AS is %u",
- as);
- return NB_ERR_VALIDATION;
- case BGP_ERR_INSTANCE_MISMATCH:
+ /*
+ * Changing AS number is not allowed, but we must allow it
+ * once, when the BGP instance is created the first time.
+ * If the instance already exists - return the validation
+ * error.
+ */
+ bgp = nb_running_get_entry_non_rec(args->dnode->parent->parent,
+ NULL, false);
+ if (bgp) {
snprintf(args->errmsg, args->errmsg_len,
- "BGP instance type mismatch");
+ "Changing AS number is not allowed");
return NB_ERR_VALIDATION;
}
break;
case NB_EV_PREPARE:
case NB_EV_ABORT:
- return NB_OK;
case NB_EV_APPLY:
- /* NOTE: handled in bgp_global_create callback, the as change
- * will be rejected in validate phase.
- */
- as = yang_dnode_get_uint32(args->dnode, NULL);
- bgp = nb_running_get_entry(args->dnode, NULL, true);
- if (bgp->as != as) {
- snprintf(args->errmsg, args->errmsg_len,
- "BGP instance is already running; AS is %u",
- bgp->as);
- return NB_ERR_INCONSISTENCY;
- }
break;
}
@@ -1514,12 +1485,27 @@ int bgp_global_global_config_timers_keepalive_modify(
*/
int bgp_global_instance_type_view_modify(struct nb_cb_modify_args *args)
{
+ struct bgp *bgp;
+
switch (args->event) {
case NB_EV_VALIDATE:
+ /*
+ * Changing instance type is not allowed, but we must allow it
+ * once, when the BGP instance is created the first time.
+ * If the instance already exists - return the validation
+ * error.
+ */
+ bgp = nb_running_get_entry_non_rec(args->dnode->parent->parent,
+ NULL, false);
+ if (bgp) {
+ snprintf(args->errmsg, args->errmsg_len,
+ "Changing instance type is not allowed");
+ return NB_ERR_VALIDATION;
+ }
+ break;
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
- /* TODO: implement me. */
break;
}
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 36aa3e1a3e..5b5f166e4b 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -1380,6 +1380,10 @@ DEFUN_YANG_NOSH(router_bgp,
nb_cli_enqueue_change(vty,
"./global/instance-type-view",
NB_OP_MODIFY, "true");
+ } else {
+ nb_cli_enqueue_change(vty,
+ "./global/instance-type-view",
+ NB_OP_MODIFY, "false");
}
ret = nb_cli_apply_changes(vty, base_xpath);
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 288c2851b3..45b60b4903 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -1700,6 +1700,9 @@ int bgp_redistribute_set(struct bgp *bgp, afi_t afi, int type,
redist_add_instance(&zclient->mi_redist[afi][type], instance);
} else {
+ if (vrf_bitmap_check(zclient->redist[afi][type], bgp->vrf_id))
+ return CMD_WARNING;
+
#ifdef ENABLE_BGP_VNC
if (EVPN_ENABLED(bgp) && type == ZEBRA_ROUTE_VNC_DIRECT) {
vnc_export_bgp_enable(
@@ -1909,22 +1912,6 @@ void bgp_redistribute_redo(struct bgp *bgp)
}
}
-/* Unset redistribute vrf bitmap during triggers like
- restart networking or delete VRFs */
-void bgp_unset_redist_vrf_bitmaps(struct bgp *bgp, vrf_id_t old_vrf_id)
-{
- int i;
- afi_t afi;
-
- for (afi = AFI_IP; afi < AFI_MAX; afi++)
- for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
- if (vrf_bitmap_check(zclient->redist[afi][i],
- old_vrf_id))
- vrf_bitmap_unset(zclient->redist[afi][i],
- old_vrf_id);
- return;
-}
-
void bgp_zclient_reset(void)
{
zclient_reset(zclient);
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 21abfeb001..9d2ff9c00e 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -3378,13 +3378,13 @@ int bgp_lookup_by_as_name_type(struct bgp **bgp_val, as_t *as, const char *name,
bgp = bgp_get_default();
if (bgp) {
+ *bgp_val = bgp;
if (bgp->as != *as) {
*as = bgp->as;
return BGP_ERR_AS_MISMATCH;
}
if (bgp->inst_type != inst_type)
return BGP_ERR_INSTANCE_MISMATCH;
- *bgp_val = bgp;
return BGP_SUCCESS;
}
*bgp_val = NULL;
@@ -3438,6 +3438,46 @@ int bgp_get(struct bgp **bgp_val, as_t *as, const char *name,
return BGP_CREATED;
}
+static void bgp_zclient_set_redist(afi_t afi, int type, unsigned short instance,
+ vrf_id_t vrf_id, bool set)
+{
+ if (instance) {
+ if (set)
+ redist_add_instance(&zclient->mi_redist[afi][type],
+ instance);
+ else
+ redist_del_instance(&zclient->mi_redist[afi][type],
+ instance);
+ } else {
+ if (set)
+ vrf_bitmap_set(zclient->redist[afi][type], vrf_id);
+ else
+ vrf_bitmap_unset(zclient->redist[afi][type], vrf_id);
+ }
+}
+
+static void bgp_set_redist_vrf_bitmaps(struct bgp *bgp, bool set)
+{
+ afi_t afi;
+ int i;
+ struct list *red_list;
+ struct listnode *node;
+ struct bgp_redist *red;
+
+ for (afi = AFI_IP; afi < AFI_MAX; afi++) {
+ for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
+
+ red_list = bgp->redist[afi][i];
+ if (!red_list)
+ continue;
+
+ for (ALL_LIST_ELEMENTS_RO(red_list, node, red))
+ bgp_zclient_set_redist(afi, i, red->instance,
+ bgp->vrf_id, set);
+ }
+ }
+}
+
/*
* Make BGP instance "up". Applies only to VRFs (non-default) and
* implies the VRF has been learnt from Zebra.
@@ -3447,6 +3487,8 @@ void bgp_instance_up(struct bgp *bgp)
struct peer *peer;
struct listnode *node, *next;
+ bgp_set_redist_vrf_bitmaps(bgp, true);
+
/* Register with zebra. */
bgp_zebra_instance_register(bgp);
@@ -3491,6 +3533,10 @@ void bgp_instance_down(struct bgp *bgp)
/* Cleanup registered nexthops (flags) */
bgp_cleanup_nexthops(bgp);
+
+ bgp_zebra_instance_deregister(bgp);
+
+ bgp_set_redist_vrf_bitmaps(bgp, false);
}
/* Delete BGP instance. */
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 38c6a70b8b..4a17b72b7f 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -2386,8 +2386,6 @@ static inline bool bgp_in_graceful_shutdown(struct bgp *bgp)
!!CHECK_FLAG(bm->flags, BM_FLAG_GRACEFUL_SHUTDOWN));
}
-extern void bgp_unset_redist_vrf_bitmaps(struct bgp *, vrf_id_t);
-
/* For benefit of rfapi */
extern struct peer *peer_new(struct bgp *bgp);
diff --git a/tests/lib/test_assert.c b/tests/lib/test_assert.c
index 8f1f4f2bad..a4535651d4 100644
--- a/tests/lib/test_assert.c
+++ b/tests/lib/test_assert.c
@@ -27,7 +27,7 @@
#include <assert.h>
__attribute__((noinline))
-void func_for_bt(int number)
+static void func_for_bt(int number)
{
assert(number > 2);
assertf(number > 3, "(A) the number was %d", number);
diff --git a/zebra/redistribute.c b/zebra/redistribute.c
index 7cb426359d..89f46f9c97 100644
--- a/zebra/redistribute.c
+++ b/zebra/redistribute.c
@@ -337,12 +337,17 @@ void zebra_redistribute_add(ZAPI_HANDLER_ARGS)
zvrf_id(zvrf), afi);
}
} else {
- if (IS_ZEBRA_DEBUG_EVENT)
- zlog_debug("%s: setting vrf %s(%u) redist bitmap",
- __func__, VRF_LOGNAME(zvrf->vrf),
- zvrf_id(zvrf));
- vrf_bitmap_set(client->redist[afi][type], zvrf_id(zvrf));
- zebra_redistribute(client, type, 0, zvrf_id(zvrf), afi);
+ if (!vrf_bitmap_check(client->redist[afi][type],
+ zvrf_id(zvrf))) {
+ if (IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug(
+ "%s: setting vrf %s(%u) redist bitmap",
+ __func__, VRF_LOGNAME(zvrf->vrf),
+ zvrf_id(zvrf));
+ vrf_bitmap_set(client->redist[afi][type],
+ zvrf_id(zvrf));
+ zebra_redistribute(client, type, 0, zvrf_id(zvrf), afi);
+ }
}
stream_failure: