summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss White <russ@riw.us>2024-09-24 10:01:10 -0400
committerGitHub <noreply@github.com>2024-09-24 10:01:10 -0400
commit1a2eaba14cf2fdd74c9e607b23c0911f44b88060 (patch)
tree0fa696feb1e8a4bd25f89ef978311add55204c9d
parent3c89cb638f005213107a00a3b76eba54c9942ca6 (diff)
parentbb977d13b865243c20e1792f43e6653562bcbce2 (diff)
Merge pull request #16838 from opensourcerouting/fix/refresh_pr_9079
Refreshement of BGP multi ASNs
-rw-r--r--bgpd/bgp_damp.c3
-rw-r--r--bgpd/bgp_evpn.c17
-rw-r--r--bgpd/bgp_mplsvpn.c46
-rw-r--r--bgpd/bgp_route.c46
-rw-r--r--bgpd/bgp_vty.c61
-rw-r--r--bgpd/bgpd.c154
-rw-r--r--bgpd/bgpd.h17
7 files changed, 279 insertions, 65 deletions
diff --git a/bgpd/bgp_damp.c b/bgpd/bgp_damp.c
index 339bfae56d..93f5a19902 100644
--- a/bgpd/bgp_damp.c
+++ b/bgpd/bgp_damp.c
@@ -779,7 +779,8 @@ int bgp_show_dampening_parameters(struct vty *vty, afi_t afi, safi_t safi,
bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
bgp = bgp_get_default();
- if (bgp == NULL) {
+
+ if (bgp == NULL || IS_BGP_INSTANCE_HIDDEN(bgp)) {
vty_out(vty, "No BGP process is configured\n");
return CMD_WARNING;
}
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index 4317eb9bab..fb7d2f47fb 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -1610,12 +1610,16 @@ static int update_evpn_type5_route_entry(struct bgp *bgp_evpn,
struct bgp_labels bgp_labels = {};
struct bgp_path_info *local_pi = NULL;
struct bgp_path_info *tmp_pi = NULL;
+ struct aspath *new_aspath;
+ struct attr static_attr = { 0 };
*route_changed = 0;
/* See if this is an update of an existing route, or a new add. */
local_pi = bgp_evpn_route_get_local_path(bgp_evpn, dest);
+ static_attr = *attr;
+
/*
* create a new route entry if one doesn't exist.
* Otherwise see if route attr has changed
@@ -1625,8 +1629,19 @@ static int update_evpn_type5_route_entry(struct bgp *bgp_evpn,
/* route has changed as this is the first entry */
*route_changed = 1;
+ /*
+ * if the asn values are different, copy the as of
+ * source vrf to the target entry
+ */
+ if (bgp_vrf->as != bgp_evpn->as) {
+ new_aspath = aspath_dup(static_attr.aspath);
+ new_aspath = aspath_add_seq(new_aspath, bgp_vrf->as);
+ static_attr.aspath = new_aspath;
+ }
+
/* Add (or update) attribute to hash. */
- attr_new = bgp_attr_intern(attr);
+ attr_new = bgp_attr_intern(&static_attr);
+ bgp_attr_flush(&static_attr);
/* create the route info from attribute */
pi = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0,
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index f5dbb4aa58..13da55ffb7 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -34,6 +34,7 @@
#include "bgpd/bgp_nht.h"
#include "bgpd/bgp_evpn.h"
#include "bgpd/bgp_memory.h"
+#include "bgpd/bgp_aspath.h"
#ifdef ENABLE_BGP_VNC
#include "bgpd/rfapi/rfapi_backend.h"
@@ -2156,6 +2157,7 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
struct bgp *src_vrf;
struct interface *ifp = NULL;
char rd_buf[RD_ADDRSTRLEN];
+ struct aspath *new_aspath;
int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF);
@@ -2213,6 +2215,32 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
return;
}
+ bn = bgp_afi_node_get(to_bgp->rib[afi][safi], afi, safi, p, NULL);
+
+ /* Check if leaked route has our asn. If so, don't import it. */
+ if (aspath_loop_check(path_vpn->attr->aspath, to_bgp->as)) {
+ for (bpi = bgp_dest_get_bgp_path_info(bn); bpi;
+ bpi = bpi->next) {
+ if (bpi->extra && bpi->extra->vrfleak &&
+ (struct bgp_path_info *)bpi->extra->vrfleak->parent ==
+ path_vpn) {
+ break;
+ }
+ }
+
+ if (bpi) {
+ if (debug)
+ zlog_debug("%s: blocking import of %p, as-path match",
+ __func__, bpi);
+ bgp_aggregate_decrement(to_bgp, p, bpi, afi, safi);
+ bgp_path_info_delete(bn, bpi);
+ bgp_process(to_bgp, bn, bpi, afi, safi);
+ }
+ bgp_dest_unlock_node(bn);
+
+ return;
+ }
+
if (debug)
zlog_debug("%s: updating RD %s, %pFX to %s", __func__, rd_buf,
p, to_bgp->name_pretty);
@@ -2365,6 +2393,21 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
nexthop_self_flag = 0;
}
+ /*
+ * if the asn values are different, copy the asn of the source vrf
+ * into the entry before importing. This helps with as-path loop
+ * detection
+ */
+ if (path_vpn->extra && path_vpn->extra->vrfleak &&
+ path_vpn->extra->vrfleak->bgp_orig &&
+ (to_bgp->as != path_vpn->extra->vrfleak->bgp_orig->as)) {
+ new_aspath = aspath_dup(static_attr.aspath);
+ new_aspath =
+ aspath_add_seq(new_aspath,
+ path_vpn->extra->vrfleak->bgp_orig->as);
+ static_attr.aspath = new_aspath;
+ }
+
new_attr = bgp_attr_intern(&static_attr);
bgp_attr_flush(&static_attr);
@@ -3866,7 +3909,8 @@ void bgp_vpn_leak_unimport(struct bgp *from_bgp)
bool is_vrf_leak_bind;
int debug;
- if (from_bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
+ if (from_bgp->inst_type != BGP_INSTANCE_TYPE_VRF &&
+ from_bgp->inst_type != BGP_INSTANCE_TYPE_DEFAULT)
return;
debug = (BGP_DEBUG(vpn, VPN_LEAK_TO_VRF) |
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index f4118952fd..f28c9adda2 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -3621,7 +3621,16 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
struct bgp_path_info_pair old_and_new;
int debug = 0;
- if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
+ /*
+ * For default bgp instance, which is deleted i.e. marked hidden
+ * we are skipping SAFI_MPLS_VPN route table deletion
+ * in bgp_cleanup_routes.
+ * So, we need to delete routes from VPNV4 table.
+ * Here for !IS_BGP_INSTANCE_HIDDEN,
+ * !(SAFI_MPLS_VPN && AF_IP/AF_IP6),
+ * we ignore the event for the prefix.
+ */
+ if (BGP_INSTANCE_HIDDEN_DELETE_IN_PROGRESS(bgp, afi, safi)) {
if (dest)
debug = bgp_debug_bestpath(dest);
if (debug)
@@ -6447,16 +6456,21 @@ void bgp_cleanup_routes(struct bgp *bgp)
if (afi != AFI_L2VPN) {
safi_t safi;
safi = SAFI_MPLS_VPN;
- for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
- dest = bgp_route_next(dest)) {
- table = bgp_dest_get_bgp_table_info(dest);
- if (table != NULL) {
- bgp_cleanup_table(bgp, table, afi, safi);
- bgp_table_finish(&table);
- bgp_dest_set_bgp_table_info(dest, NULL);
- dest = bgp_dest_unlock_node(dest);
-
- assert(dest);
+ if (!IS_BGP_INSTANCE_HIDDEN(bgp)) {
+ for (dest = bgp_table_top(bgp->rib[afi][safi]);
+ dest; dest = bgp_route_next(dest)) {
+ table = bgp_dest_get_bgp_table_info(
+ dest);
+ if (table != NULL) {
+ bgp_cleanup_table(bgp, table,
+ afi, safi);
+ bgp_table_finish(&table);
+ bgp_dest_set_bgp_table_info(dest,
+ NULL);
+ dest = bgp_dest_unlock_node(
+ dest);
+ assert(dest);
+ }
}
}
safi = SAFI_ENCAP;
@@ -12160,7 +12174,7 @@ static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
bgp = bgp_get_default();
}
- if (bgp == NULL) {
+ if (bgp == NULL || IS_BGP_INSTANCE_HIDDEN(bgp)) {
if (!use_json)
vty_out(vty, "No BGP process is configured\n");
else
@@ -12206,6 +12220,8 @@ static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
vty_out(vty, "{\n");
for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
+ if (IS_BGP_INSTANCE_HIDDEN(bgp))
+ continue;
route_output = true;
if (use_json) {
if (!is_first)
@@ -12724,7 +12740,7 @@ static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
{
if (!bgp) {
bgp = bgp_get_default();
- if (!bgp) {
+ if (!bgp || IS_BGP_INSTANCE_HIDDEN(bgp)) {
if (!use_json)
vty_out(vty, "No BGP process is configured\n");
else
@@ -14382,7 +14398,7 @@ DEFUN (show_ip_bgp_vpn_all_route_prefix,
int idx = 0;
char *network = NULL;
struct bgp *bgp = bgp_get_default();
- if (!bgp) {
+ if (!bgp || IS_BGP_INSTANCE_HIDDEN(bgp)) {
vty_out(vty, "Can't find default instance\n");
return CMD_WARNING;
}
@@ -15884,7 +15900,7 @@ static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
/* BGP structure lookup. */
if (view_name) {
bgp = bgp_lookup_by_name(view_name);
- if (bgp == NULL) {
+ if (bgp == NULL || IS_BGP_INSTANCE_HIDDEN(bgp)) {
vty_out(vty, "%% Can't find BGP instance %s\n",
view_name);
return CMD_WARNING;
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index a3b23fb2d5..cf74a6566c 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -879,6 +879,7 @@ int bgp_vty_return(struct vty *vty, enum bgp_create_error_code ret)
switch (ret) {
case BGP_SUCCESS:
case BGP_CREATED:
+ case BGP_INSTANCE_EXISTS:
case BGP_GR_NO_OPERATION:
break;
case BGP_ERR_INVALID_VALUE:
@@ -1418,7 +1419,7 @@ DEFUN_HIDDEN (bgp_local_mac,
seq = strtoul(argv[7]->arg, NULL, 10);
bgp = bgp_get_default();
- if (!bgp) {
+ if (!bgp || IS_BGP_INSTANCE_HIDDEN(bgp)) {
vty_out(vty, "Default BGP instance is not there\n");
return CMD_WARNING;
}
@@ -1458,7 +1459,7 @@ DEFUN_HIDDEN (no_bgp_local_mac,
memset(&ip, 0, sizeof(ip));
bgp = bgp_get_default();
- if (!bgp) {
+ if (!bgp || IS_BGP_INSTANCE_HIDDEN(bgp)) {
vty_out(vty, "Default BGP instance is not there\n");
return CMD_WARNING;
}
@@ -1601,8 +1602,12 @@ DEFUN_NOSH (router_bgp,
if (is_new_bgp && inst_type == BGP_INSTANCE_TYPE_DEFAULT)
vpn_leak_postchange_all();
- if (inst_type == BGP_INSTANCE_TYPE_VRF)
+ if (inst_type == BGP_INSTANCE_TYPE_VRF ||
+ IS_BGP_INSTANCE_HIDDEN(bgp)) {
bgp_vpn_leak_export(bgp);
+ UNSET_FLAG(bgp->flags, BGP_FLAG_INSTANCE_HIDDEN);
+ UNSET_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS);
+ }
/* Pending: handle when user tries to change a view to vrf n vv.
*/
/* for pre-existing bgp instance,
@@ -1674,7 +1679,7 @@ DEFUN (no_router_bgp,
argv[idx_asn]->arg);
return CMD_WARNING_CONFIG_FAILED;
}
- if (argc > 4) {
+ if (argc > 4 && strncmp(argv[4]->arg, "vrf", 3) == 0) {
name = argv[idx_vrf]->arg;
if (strmatch(argv[idx_vrf - 1]->text, "vrf")
&& strmatch(name, VRF_DEFAULT_NAME))
@@ -10446,9 +10451,9 @@ DEFPY(af_import_vrf_route_map, af_import_vrf_route_map_cmd,
bgp_default = bgp_get_default();
if (!bgp_default) {
int32_t ret;
- as_t as = bgp->as;
+ as_t as = AS_UNSPECIFIED;
- /* Auto-create assuming the same AS */
+ /* Auto-create with AS_UNSPECIFIED, to be filled in later */
ret = bgp_get_vty(&bgp_default, &as, NULL,
BGP_INSTANCE_TYPE_DEFAULT, NULL,
ASNOTATION_UNDEFINED);
@@ -10458,6 +10463,8 @@ DEFPY(af_import_vrf_route_map, af_import_vrf_route_map_cmd,
"VRF default is not configured as a bgp instance\n");
return CMD_WARNING;
}
+
+ SET_FLAG(bgp_default->flags, BGP_FLAG_INSTANCE_HIDDEN);
}
vpn_leak_prechange(dir, afi, bgp_get_default(), bgp);
@@ -10561,7 +10568,9 @@ DEFPY(bgp_imexport_vrf, bgp_imexport_vrf_cmd,
bgp_default = bgp_get_default();
if (!bgp_default) {
- /* Auto-create assuming the same AS */
+ as = AS_UNSPECIFIED;
+
+ /* Auto-create with AS_UNSPECIFIED, to be filled in later */
ret = bgp_get_vty(&bgp_default, &as, NULL,
BGP_INSTANCE_TYPE_DEFAULT, NULL,
ASNOTATION_UNDEFINED);
@@ -10571,6 +10580,8 @@ DEFPY(bgp_imexport_vrf, bgp_imexport_vrf_cmd,
"VRF default is not configured as a bgp instance\n");
return CMD_WARNING;
}
+
+ SET_FLAG(bgp_default->flags, BGP_FLAG_INSTANCE_HIDDEN);
}
vrf_bgp = bgp_lookup_by_name(import_name);
@@ -10578,9 +10589,19 @@ DEFPY(bgp_imexport_vrf, bgp_imexport_vrf_cmd,
if (strcmp(import_name, VRF_DEFAULT_NAME) == 0) {
vrf_bgp = bgp_default;
} else {
- /* Auto-create assuming the same AS */
+ as = AS_UNSPECIFIED;
+
+ /* Auto-create with AS_UNSPECIFIED, fill in later */
ret = bgp_get_vty(&vrf_bgp, &as, import_name, bgp_type,
NULL, ASNOTATION_UNDEFINED);
+ if (ret) {
+ vty_out(vty,
+ "VRF %s is not configured as a bgp instance\n",
+ import_name);
+ return CMD_WARNING;
+ }
+
+ SET_FLAG(vrf_bgp->flags, BGP_FLAG_INSTANCE_HIDDEN);
/* Auto created VRF instances should be marked
* properly, otherwise we have a state after bgpd
@@ -11551,7 +11572,7 @@ DEFUN(show_bgp_martian_nexthop_db, show_bgp_martian_nexthop_db_cmd,
else
bgp = bgp_get_default();
- if (!bgp) {
+ if (!bgp || IS_BGP_INSTANCE_HIDDEN(bgp)) {
vty_out(vty, "%% No BGP process is configured\n");
return CMD_WARNING;
}
@@ -12783,6 +12804,9 @@ static void bgp_show_all_instances_summary_vty(struct vty *vty, afi_t afi,
if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_AUTO))
continue;
+ if (IS_BGP_INSTANCE_HIDDEN(bgp))
+ continue;
+
nbr_output = true;
if (use_json) {
if (!is_first)
@@ -16177,6 +16201,9 @@ static void bgp_show_all_instances_neighbors_vty(struct vty *vty,
if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_AUTO))
continue;
+ if (IS_BGP_INSTANCE_HIDDEN(bgp))
+ continue;
+
nbr_output = true;
if (use_json) {
if (!(json = json_object_new_object())) {
@@ -16832,6 +16859,9 @@ static void bgp_show_all_instances_updgrps_vty(struct vty *vty, afi_t afi,
if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_AUTO))
continue;
+ if (IS_BGP_INSTANCE_HIDDEN(bgp))
+ continue;
+
if (!uj)
vty_out(vty, "\nInstance %s:\n",
(bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
@@ -16954,7 +16984,7 @@ DEFUN (show_bgp_updgrps_stats,
struct bgp *bgp;
bgp = bgp_get_default();
- if (bgp)
+ if (bgp && !IS_BGP_INSTANCE_HIDDEN(bgp))
update_group_show_stats(bgp, vty);
return CMD_SUCCESS;
@@ -18951,6 +18981,10 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
char *addr;
bool flag_scomm, flag_secomm, flag_slcomm;
+ /* skip hidden default vrf bgp instance */
+ if (IS_BGP_INSTANCE_HIDDEN(bgp))
+ return;
+
/* Skip dynamic neighbors. */
if (peer_dynamic_neighbor(peer))
return;
@@ -19256,6 +19290,9 @@ static void bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi,
struct peer_group *group;
struct listnode *node, *nnode;
+ /* skip hidden default vrf bgp instance */
+ if (IS_BGP_INSTANCE_HIDDEN(bgp))
+ return;
vty_frame(vty, " !\n address-family ");
if (afi == AFI_IP) {
@@ -19438,6 +19475,10 @@ int bgp_config_write(struct vty *vty)
if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_AUTO))
continue;
+ /* skip hidden default vrf bgp instance */
+ if (IS_BGP_INSTANCE_HIDDEN(bgp))
+ continue;
+
/* Router bgp ASN */
vty_out(vty, "router bgp %s", bgp->as_pretty);
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 8fe8f244da..a3caa5a806 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -3420,12 +3420,18 @@ static void bgp_vrf_string_name_delete(void *data)
static struct bgp *bgp_create(as_t *as, const char *name,
enum bgp_instance_type inst_type,
const char *as_pretty,
- enum asnotation_mode asnotation)
+ enum asnotation_mode asnotation,
+ struct bgp *bgp_old, bool hidden)
{
struct bgp *bgp;
afi_t afi;
safi_t safi;
+ if (hidden) {
+ bgp = bgp_old;
+ goto peer_init;
+ }
+
bgp = XCALLOC(MTYPE_BGP, sizeof(struct bgp));
bgp->as = *as;
if (as_pretty)
@@ -3479,18 +3485,24 @@ static struct bgp *bgp_create(as_t *as, const char *name,
bgp->peer_self->domainname =
XSTRDUP(MTYPE_BGP_PEER_HOST, cmd_domainname_get());
bgp->peer = list_new();
+
+peer_init:
bgp->peer->cmp = (int (*)(void *, void *))peer_cmp;
bgp->peerhash = hash_create(peer_hash_key_make, peer_hash_same,
"BGP Peer Hash");
bgp->peerhash->max_size = BGP_PEER_MAX_HASH_SIZE;
- bgp->group = list_new();
+ if (!hidden)
+ bgp->group = list_new();
bgp->group->cmp = (int (*)(void *, void *))peer_group_cmp;
FOREACH_AFI_SAFI (afi, safi) {
- bgp->route[afi][safi] = bgp_table_init(bgp, afi, safi);
- bgp->aggregate[afi][safi] = bgp_table_init(bgp, afi, safi);
- bgp->rib[afi][safi] = bgp_table_init(bgp, afi, safi);
+ if (!hidden) {
+ bgp->route[afi][safi] = bgp_table_init(bgp, afi, safi);
+ bgp->aggregate[afi][safi] = bgp_table_init(bgp, afi,
+ safi);
+ bgp->rib[afi][safi] = bgp_table_init(bgp, afi, safi);
+ }
/* Enable maximum-paths */
bgp_maximum_paths_set(bgp, afi, safi, BGP_PEER_EBGP,
@@ -3511,7 +3523,8 @@ static struct bgp *bgp_create(as_t *as, const char *name,
bgp->default_subgroup_pkt_queue_max =
BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX;
bgp_tcp_keepalive_unset(bgp);
- bgp_timers_unset(bgp);
+ if (!hidden)
+ bgp_timers_unset(bgp);
bgp->default_min_holdtime = 0;
bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
@@ -3529,7 +3542,7 @@ static struct bgp *bgp_create(as_t *as, const char *name,
bgp->rmap_def_originate_eval_timer = 0;
#ifdef ENABLE_BGP_VNC
- if (inst_type != BGP_INSTANCE_TYPE_VRF) {
+ if (inst_type != BGP_INSTANCE_TYPE_VRF && !hidden) {
bgp->rfapi = bgp_rfapi_new(bgp);
assert(bgp->rfapi);
assert(bgp->rfapi_cfg);
@@ -3546,9 +3559,11 @@ static struct bgp *bgp_create(as_t *as, const char *name,
bgp->vpn_policy[afi].import_vrf = list_new();
bgp->vpn_policy[afi].import_vrf->del =
bgp_vrf_string_name_delete;
- bgp->vpn_policy[afi].export_vrf = list_new();
- bgp->vpn_policy[afi].export_vrf->del =
- bgp_vrf_string_name_delete;
+ if (!hidden) {
+ bgp->vpn_policy[afi].export_vrf = list_new();
+ bgp->vpn_policy[afi].export_vrf->del =
+ bgp_vrf_string_name_delete;
+ }
SET_FLAG(bgp->af_flags[afi][SAFI_MPLS_VPN],
BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL);
}
@@ -3566,7 +3581,7 @@ static struct bgp *bgp_create(as_t *as, const char *name,
bgp->restart_time, &bgp->t_startup);
/* printable name we can use in debug messages */
- if (inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
+ if (inst_type == BGP_INSTANCE_TYPE_DEFAULT && !hidden) {
bgp->name_pretty = XSTRDUP(MTYPE_BGP_NAME, "VRF default");
} else {
const char *n;
@@ -3594,17 +3609,20 @@ static struct bgp *bgp_create(as_t *as, const char *name,
bgp->coalesce_time = BGP_DEFAULT_SUBGROUP_COALESCE_TIME;
bgp->default_af[AFI_IP][SAFI_UNICAST] = true;
- QOBJ_REG(bgp, bgp);
+ if (!hidden)
+ QOBJ_REG(bgp, bgp);
update_bgp_group_init(bgp);
- /* assign a unique rd id for auto derivation of vrf's RD */
- bf_assign_index(bm->rd_idspace, bgp->vrf_rd_id);
+ if (!hidden) {
+ /* assign a unique rd id for auto derivation of vrf's RD */
+ bf_assign_index(bm->rd_idspace, bgp->vrf_rd_id);
- bgp_evpn_init(bgp);
- bgp_evpn_vrf_es_init(bgp);
- bgp_pbr_init(bgp);
- bgp_srv6_init(bgp);
+ bgp_evpn_init(bgp);
+ bgp_evpn_vrf_es_init(bgp);
+ bgp_pbr_init(bgp);
+ bgp_srv6_init(bgp);
+ }
/*initilize global GR FSM */
bgp_global_gr_init(bgp);
@@ -3742,10 +3760,15 @@ int bgp_handle_socket(struct bgp *bgp, struct vrf *vrf, vrf_id_t old_vrf_id,
return bgp_check_main_socket(create, bgp);
}
-int bgp_lookup_by_as_name_type(struct bgp **bgp_val, as_t *as, const char *name,
+int bgp_lookup_by_as_name_type(struct bgp **bgp_val, as_t *as,
+ const char *as_pretty,
+ enum asnotation_mode asnotation, const char *name,
enum bgp_instance_type inst_type)
{
struct bgp *bgp;
+ struct peer *peer = NULL;
+ struct listnode *node, *nnode;
+ bool hidden = false;
/* Multiple instance check. */
if (name)
@@ -3754,14 +3777,41 @@ 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 (IS_BGP_INSTANCE_HIDDEN(bgp) && *as != AS_UNSPECIFIED)
+ hidden = true;
+ /* Handle AS number change */
if (bgp->as != *as) {
+ if (hidden || CHECK_FLAG(bgp->vrf_flags, BGP_VRF_AUTO)) {
+ if (hidden) {
+ bgp_create(as, name, inst_type,
+ as_pretty, asnotation, bgp,
+ hidden);
+ UNSET_FLAG(bgp->flags,
+ BGP_FLAG_INSTANCE_HIDDEN);
+ } else {
+ bgp->as = *as;
+ UNSET_FLAG(bgp->vrf_flags, BGP_VRF_AUTO);
+ }
+
+ /* Set all peer's local AS with this ASN */
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode,
+ peer))
+ peer->local_as = *as;
+ *bgp_val = bgp;
+ return BGP_INSTANCE_EXISTS;
+ }
+
*as = bgp->as;
- return BGP_ERR_AS_MISMATCH;
+ *bgp_val = bgp;
+ return BGP_ERR_INSTANCE_MISMATCH;
}
if (bgp->inst_type != inst_type)
return BGP_ERR_INSTANCE_MISMATCH;
- return BGP_SUCCESS;
+ if (hidden)
+ bgp_create(as, name, inst_type, as_pretty, asnotation,
+ bgp, hidden);
+ *bgp_val = bgp;
+ return BGP_INSTANCE_EXISTS;
}
*bgp_val = NULL;
@@ -3777,11 +3827,13 @@ int bgp_get(struct bgp **bgp_val, as_t *as, const char *name,
struct vrf *vrf = NULL;
int ret = 0;
- ret = bgp_lookup_by_as_name_type(bgp_val, as, name, inst_type);
+ ret = bgp_lookup_by_as_name_type(bgp_val, as, as_pretty, asnotation,
+ name, inst_type);
if (ret || *bgp_val)
return ret;
- bgp = bgp_create(as, name, inst_type, as_pretty, asnotation);
+ bgp = bgp_create(as, name, inst_type, as_pretty, asnotation, NULL,
+ false);
/*
* view instances will never work inside of a vrf
@@ -4021,6 +4073,15 @@ int bgp_delete(struct bgp *bgp)
bgp_damp_disable(bgp, afi, safi);
}
+ if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT &&
+ (bgp_table_top(bgp->rib[AFI_IP][SAFI_MPLS_VPN]) ||
+ bgp_table_top(bgp->rib[AFI_IP6][SAFI_MPLS_VPN]))) {
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug(
+ "Marking the deleting default bgp instance as hidden");
+ SET_FLAG(bgp->flags, BGP_FLAG_INSTANCE_HIDDEN);
+ }
+
if (BGP_DEBUG(zebra, ZEBRA)) {
if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
zlog_debug("Deleting Default VRF");
@@ -4033,7 +4094,8 @@ int bgp_delete(struct bgp *bgp)
}
/* unmap from RT list */
- bgp_evpn_vrf_delete(bgp);
+ if (!IS_BGP_INSTANCE_HIDDEN(bgp))
+ bgp_evpn_vrf_delete(bgp);
/* unmap bgp vrf label */
vpn_leak_zebra_vrf_label_withdraw(bgp, AFI_IP);
@@ -4065,7 +4127,7 @@ int bgp_delete(struct bgp *bgp)
peer_delete(peer);
}
- if (bgp->peer_self) {
+ if (bgp->peer_self && !IS_BGP_INSTANCE_HIDDEN(bgp)) {
peer_delete(bgp->peer_self);
bgp->peer_self = NULL;
}
@@ -4075,7 +4137,8 @@ int bgp_delete(struct bgp *bgp)
/* TODO - Other memory may need to be freed - e.g., NHT */
#ifdef ENABLE_BGP_VNC
- rfapi_delete(bgp);
+ if (!IS_BGP_INSTANCE_HIDDEN(bgp))
+ rfapi_delete(bgp);
#endif
/* Free memory allocated with aggregate address configuration. */
@@ -4117,7 +4180,7 @@ int bgp_delete(struct bgp *bgp)
}
/* Deregister from Zebra, if needed */
- if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) {
+ if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp) && !IS_BGP_INSTANCE_HIDDEN(bgp)) {
if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug(
"%s: deregistering this bgp %s instance from zebra",
@@ -4125,17 +4188,19 @@ int bgp_delete(struct bgp *bgp)
bgp_zebra_instance_deregister(bgp);
}
- /* Remove visibility via the master list - there may however still be
- * routes to be processed still referencing the struct bgp.
- */
- listnode_delete(bm->bgp, bgp);
-
- /* Free interfaces in this instance. */
- bgp_if_finish(bgp);
+ if (!IS_BGP_INSTANCE_HIDDEN(bgp)) {
+ /* Remove visibility via the master list -
+ * there may however still be routes to be processed
+ * still referencing the struct bgp.
+ */
+ listnode_delete(bm->bgp, bgp);
+ /* Free interfaces in this instance. */
+ bgp_if_finish(bgp);
+ }
vrf = bgp_vrf_lookup_by_instance_type(bgp);
bgp_handle_socket(bgp, vrf, VRF_UNKNOWN, false);
- if (vrf)
+ if (vrf && !IS_BGP_INSTANCE_HIDDEN(bgp))
bgp_vrf_unlink(bgp, vrf);
/* Update EVPN VRF pointer */
@@ -4150,7 +4215,22 @@ int bgp_delete(struct bgp *bgp)
work_queue_free_and_null(&bgp->process_queue);
event_master_free_unused(bm->master);
- bgp_unlock(bgp); /* initial reference */
+
+ if (!IS_BGP_INSTANCE_HIDDEN(bgp))
+ bgp_unlock(bgp); /* initial reference */
+ else {
+ for (afi = AFI_IP; afi < AFI_MAX; afi++) {
+ enum vpn_policy_direction dir;
+
+ if (bgp->vpn_policy[afi].import_vrf)
+ list_delete(&bgp->vpn_policy[afi].import_vrf);
+
+ dir = BGP_VPN_POLICY_DIR_FROMVPN;
+ if (bgp->vpn_policy[afi].rtlist[dir])
+ ecommunity_free(
+ &bgp->vpn_policy[afi].rtlist[dir]);
+ }
+ }
return 0;
}
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 795e4fbc58..3c3655f0a5 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -550,6 +550,7 @@ struct bgp {
#define BGP_FLAG_ENFORCE_FIRST_AS (1ULL << 36)
#define BGP_FLAG_DYNAMIC_CAPABILITY (1ULL << 37)
#define BGP_FLAG_VNI_DOWN (1ULL << 38)
+#define BGP_FLAG_INSTANCE_HIDDEN (1ULL << 39)
/* BGP default address-families.
* New peers inherit enabled afi/safis from bgp instance.
@@ -2153,6 +2154,7 @@ enum bgp_clear_type {
enum bgp_create_error_code {
BGP_SUCCESS = 0,
BGP_CREATED = 1,
+ BGP_INSTANCE_EXISTS = 2,
BGP_ERR_INVALID_VALUE = -1,
BGP_ERR_INVALID_FLAG = -2,
BGP_ERR_INVALID_AS = -3,
@@ -2823,6 +2825,8 @@ extern struct peer *peer_new(struct bgp *bgp);
extern struct peer *peer_lookup_in_view(struct vty *vty, struct bgp *bgp,
const char *ip_str, bool use_json);
extern int bgp_lookup_by_as_name_type(struct bgp **bgp_val, as_t *as,
+ const char *as_pretty,
+ enum asnotation_mode asnotation,
const char *name,
enum bgp_instance_type inst_type);
@@ -2864,4 +2868,17 @@ extern void bgp_session_reset_safe(struct peer *peer, struct listnode **nnode);
/* clang-format on */
#endif
+/* Macro to check if default bgp instance is hidden */
+#define IS_BGP_INSTANCE_HIDDEN(_bgp) \
+ (CHECK_FLAG(_bgp->flags, BGP_FLAG_INSTANCE_HIDDEN) && \
+ (_bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT || \
+ _bgp->inst_type == BGP_INSTANCE_TYPE_VRF))
+
+/* Macro to check if bgp instance delete in-progress and !hidden */
+#define BGP_INSTANCE_HIDDEN_DELETE_IN_PROGRESS(_bgp, _afi, _safi) \
+ (CHECK_FLAG(_bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS) && \
+ !IS_BGP_INSTANCE_HIDDEN(_bgp) && \
+ !(_afi == AFI_IP && _safi == SAFI_MPLS_VPN) && \
+ !(_afi == AFI_IP6 && _safi == SAFI_MPLS_VPN))
+
#endif /* _QUAGGA_BGPD_H */