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 */