Skip to content

Commit

Permalink
bgpd: fix duplicate BGP instance created with unified config
Browse files Browse the repository at this point in the history
When running the bgp_evpn_rt5 setup with unified config, memory leak
about a non deleted BGP instance happens.

> root@ubuntu2204hwe:~/frr/tests/topotests/bgp_evpn_rt5# cat /tmp/topotests/bgp_evpn_rt5.test_bgp_evpn/r1.asan.bgpd.1164105
>
> =================================================================
> ==1164105==ERROR: LeakSanitizer: detected memory leaks
>
> Indirect leak of 12496 byte(s) in 1 object(s) allocated from:
>     #0 0x7f358eeb4a57 in __interceptor_calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:154
>     FRRouting#1 0x7f358e877233 in qcalloc lib/memory.c:106
>     FRRouting#2 0x55d06c95680a in bgp_create bgpd/bgpd.c:3405
>     FRRouting#3 0x55d06c95a7b3 in bgp_get bgpd/bgpd.c:3805
>     FRRouting#4 0x55d06c87a9b5 in bgp_get_vty bgpd/bgp_vty.c:603
>     FRRouting#5 0x55d06c68dc71 in bgp_evpn_local_l3vni_add bgpd/bgp_evpn.c:7032
>     FRRouting#6 0x55d06c92989b in bgp_zebra_process_local_l3vni bgpd/bgp_zebra.c:3204
>     FRRouting#7 0x7f358e9e3feb in zclient_read lib/zclient.c:4626
>     FRRouting#8 0x7f358e98082d in event_call lib/event.c:1996
>     FRRouting#9 0x7f358e848931 in frr_run lib/libfrr.c:1232
>     FRRouting#10 0x55d06c60eae1 in main bgpd/bgp_main.c:557
>     FRRouting#11 0x7f358e229d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58

Actually, a BGP VRF Instance is created in auto mode when creating the
global BGP instance for the L3 VNI. And again, an other BGP VRF instance
is created. Fix this by ensuring that a non existing BGP instance is not
present. If it is present, and with auto mode or in hidden mode, then
override the AS value.

Fixes: f153b9a ("bgpd: Ignore auto created VRF BGP instances")

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>

fixup bgpd: fix duplicate BGP instance created with unified config
  • Loading branch information
pguibert6WIND committed Jan 7, 2025
1 parent 12ddfa4 commit 3b351fb
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 22 deletions.
18 changes: 10 additions & 8 deletions bgpd/bgp_vty.c
Original file line number Diff line number Diff line change
Expand Up @@ -1509,13 +1509,12 @@ DEFUN_NOSH (router_bgp,
int idx_asn = 2;
int idx_view_vrf = 3;
int idx_vrf = 4;
int is_new_bgp = 0;
int idx_asnotation = 3;
int idx_asnotation_kind = 4;
enum asnotation_mode asnotation = ASNOTATION_UNDEFINED;
int ret;
as_t as;
struct bgp *bgp;
struct bgp *bgp = NULL;
const char *name = NULL;
enum bgp_instance_type inst_type;

Expand Down Expand Up @@ -1577,11 +1576,14 @@ DEFUN_NOSH (router_bgp,
asnotation = ASNOTATION_PLAIN;
}

if (inst_type == BGP_INSTANCE_TYPE_DEFAULT)
is_new_bgp = (bgp_lookup(as, name) == NULL);

ret = bgp_get_vty(&bgp, &as, name, inst_type,
argv[idx_asn]->arg, asnotation);
ret = bgp_lookup_by_as_name_type(&bgp, &as, argv[idx_asn]->arg, asnotation, name,
inst_type, true);
if (bgp && ret == BGP_INSTANCE_EXISTS)
ret = CMD_SUCCESS;
else if (bgp == NULL && ret == CMD_SUCCESS)
/* SUCCESS and bgp is NULL */
ret = bgp_get_vty(&bgp, &as, name, inst_type, argv[idx_asn]->arg,
asnotation);
switch (ret) {
case BGP_ERR_AS_MISMATCH:
vty_out(vty, "BGP is already running; AS is %s\n",
Expand All @@ -1601,7 +1603,7 @@ DEFUN_NOSH (router_bgp,
* any pending VRF-VPN leaking that was configured via
* earlier "router bgp X vrf FOO" blocks.
*/
if (is_new_bgp && inst_type == BGP_INSTANCE_TYPE_DEFAULT)
if (bgp && inst_type == BGP_INSTANCE_TYPE_DEFAULT)
vpn_leak_postchange_all();

if (inst_type == BGP_INSTANCE_TYPE_VRF ||
Expand Down
29 changes: 20 additions & 9 deletions bgpd/bgpd.c
Original file line number Diff line number Diff line change
Expand Up @@ -3630,13 +3630,13 @@ struct bgp *bgp_lookup(as_t as, const char *name)
}

/* Lookup BGP structure by view name. */
struct bgp *bgp_lookup_by_name(const char *name)
static struct bgp *_bgp_lookup_by_name(const char *name, bool all)
{
struct bgp *bgp;
struct listnode *node, *nnode;

for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_AUTO))
if (all == false && CHECK_FLAG(bgp->vrf_flags, BGP_VRF_AUTO))
continue;
if ((bgp->name == NULL && name == NULL)
|| (bgp->name && name && strcmp(bgp->name, name) == 0))
Expand All @@ -3645,6 +3645,16 @@ struct bgp *bgp_lookup_by_name(const char *name)
return NULL;
}

struct bgp *bgp_lookup_by_name(const char *name)
{
return _bgp_lookup_by_name(name, false);
}

struct bgp *bgp_lookup_by_name_all(const char *name)
{
return _bgp_lookup_by_name(name, true);
}

/* Lookup BGP instance based on VRF id. */
/* Note: Only to be used for incoming messages from Zebra. */
struct bgp *bgp_lookup_by_vrf_id(vrf_id_t vrf_id)
Expand Down Expand Up @@ -3730,18 +3740,19 @@ 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 *as_pretty,
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)
enum bgp_instance_type inst_type, bool force_config)
{
struct bgp *bgp;
struct peer *peer = NULL;
struct listnode *node, *nnode;
bool hidden = false;

/* Multiple instance check. */
if (name)
if (name && force_config)
bgp = bgp_lookup_by_name_all(name);
else if (name)
bgp = bgp_lookup_by_name(name);
else
bgp = bgp_get_default();
Expand All @@ -3752,7 +3763,7 @@ int bgp_lookup_by_as_name_type(struct bgp **bgp_val, as_t *as,
/* Handle AS number change */
if (bgp->as != *as) {
if (hidden || CHECK_FLAG(bgp->vrf_flags, BGP_VRF_AUTO)) {
if (hidden) {
if (force_config == false && hidden) {
bgp_create(as, name, inst_type,
as_pretty, asnotation, bgp,
hidden);
Expand All @@ -3761,6 +3772,7 @@ int bgp_lookup_by_as_name_type(struct bgp **bgp_val, as_t *as,
} else {
bgp->as = *as;
UNSET_FLAG(bgp->vrf_flags, BGP_VRF_AUTO);
UNSET_FLAG(bgp->flags, BGP_FLAG_INSTANCE_HIDDEN);
}

/* Set all peer's local AS with this ASN */
Expand Down Expand Up @@ -3797,8 +3809,7 @@ 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, as_pretty, asnotation,
name, inst_type);
ret = bgp_lookup_by_as_name_type(bgp_val, as, as_pretty, asnotation, name, inst_type, false);
if (ret || *bgp_val)
return ret;

Expand Down
9 changes: 4 additions & 5 deletions bgpd/bgpd.h
Original file line number Diff line number Diff line change
Expand Up @@ -2281,6 +2281,7 @@ extern void bgp_zclient_reset(void);
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_name_all(const char *name);
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);
Expand Down Expand Up @@ -2855,11 +2856,9 @@ 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);
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, bool force_config);

/* Hooks */
DECLARE_HOOK(bgp_vrf_status_changed, (struct bgp *bgp, struct interface *ifp),
Expand Down

0 comments on commit 3b351fb

Please sign in to comment.