Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bfdd: disable echo socket when not using it #16987

Merged
merged 1 commit into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
151 changes: 103 additions & 48 deletions bfdd/bfd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1172,6 +1172,9 @@ void bfd_set_echo(struct bfd_session *bs, bool echo)
if (bs->bdc == NULL)
ptm_bfd_echo_stop(bs);
}

if (bs->vrf && bs->vrf->info)
bfd_vrf_toggle_echo(bs->vrf->info);
}

void bfd_set_shutdown(struct bfd_session *bs, bool shutdown)
Expand Down Expand Up @@ -1800,6 +1803,69 @@ void bfd_profiles_remove(void)
bfd_profile_free(bp);
}

struct __bfd_session_echo {
/* VRF peers must match */
struct vrf *vrf;
/* Echo enabled or not */
bool enabled;
};

static int __bfd_session_has_echo(struct hash_bucket *hb, void *arg)
{
const struct bfd_session *session = hb->data;
struct __bfd_session_echo *has_echo = arg;

if (session->vrf != has_echo->vrf)
return HASHWALK_CONTINUE;
if (!CHECK_FLAG(session->flags, BFD_SESS_FLAG_ECHO))
return HASHWALK_CONTINUE;

has_echo->enabled = true;
return HASHWALK_ABORT;
}

void bfd_vrf_toggle_echo(struct bfd_vrf_global *bfd_vrf)
{
struct __bfd_session_echo has_echo = {
.enabled = false,
.vrf = bfd_vrf->vrf,
};

/* Check for peers using echo */
hash_walk(bfd_id_hash, __bfd_session_has_echo, &has_echo);

/*
* No peers using echo, close all echo sockets.
*/
if (!has_echo.enabled) {
if (bfd_vrf->bg_echo != -1) {
event_cancel(&bfd_vrf->bg_ev[4]);
rzalamena marked this conversation as resolved.
Show resolved Hide resolved
close(bfd_vrf->bg_echo);
bfd_vrf->bg_echo = -1;
}

if (bfd_vrf->bg_echov6 != -1) {
event_cancel(&bfd_vrf->bg_ev[5]);
close(bfd_vrf->bg_echov6);
bfd_vrf->bg_echov6 = -1;
}
return;
}

/*
* At least one peer using echo, open echo sockets.
*/
if (bfd_vrf->bg_echo == -1)
bfd_vrf->bg_echo = bp_echo_socket(bfd_vrf->vrf);
if (bfd_vrf->bg_echov6 == -1)
bfd_vrf->bg_echov6 = bp_echov6_socket(bfd_vrf->vrf);

if (bfd_vrf->bg_ev[4] == NULL && bfd_vrf->bg_echo != -1)
event_add_read(master, bfd_recv_cb, bfd_vrf, bfd_vrf->bg_echo, &bfd_vrf->bg_ev[4]);
if (bfd_vrf->bg_ev[5] == NULL && bfd_vrf->bg_echov6 != -1)
event_add_read(master, bfd_recv_cb, bfd_vrf, bfd_vrf->bg_echov6, &bfd_vrf->bg_ev[5]);
}

/*
* Profile related hash functions.
*/
Expand Down Expand Up @@ -1842,9 +1908,23 @@ static void bfd_profile_detach(struct bfd_profile *bp)
*/
static int bfd_vrf_new(struct vrf *vrf)
{
struct bfd_vrf_global *bvrf;

if (bglobal.debug_zebra)
zlog_debug("VRF Created: %s(%u)", vrf->name, vrf->vrf_id);

bvrf = XCALLOC(MTYPE_BFDD_VRF, sizeof(struct bfd_vrf_global));
bvrf->vrf = vrf;
vrf->info = bvrf;

/* Invalidate all sockets */
bvrf->bg_shop = -1;
bvrf->bg_mhop = -1;
bvrf->bg_shop6 = -1;
bvrf->bg_mhop6 = -1;
bvrf->bg_echo = -1;
bvrf->bg_echov6 = -1;

return 0;
}

Expand All @@ -1853,70 +1933,53 @@ static int bfd_vrf_delete(struct vrf *vrf)
if (bglobal.debug_zebra)
zlog_debug("VRF Deletion: %s(%u)", vrf->name, vrf->vrf_id);

XFREE(MTYPE_BFDD_VRF, vrf->info);

return 0;
}

static int bfd_vrf_enable(struct vrf *vrf)
{
struct bfd_vrf_global *bvrf;

/* a different name */
if (!vrf->info) {
bvrf = XCALLOC(MTYPE_BFDD_VRF, sizeof(struct bfd_vrf_global));
bvrf->vrf = vrf;
vrf->info = (void *)bvrf;

/* Disable sockets if using data plane. */
if (bglobal.bg_use_dplane) {
bvrf->bg_shop = -1;
bvrf->bg_mhop = -1;
bvrf->bg_shop6 = -1;
bvrf->bg_mhop6 = -1;
bvrf->bg_echo = -1;
bvrf->bg_echov6 = -1;
}
} else
bvrf = vrf->info;
struct bfd_vrf_global *bvrf = vrf->info;

if (bglobal.debug_zebra)
zlog_debug("VRF enable add %s id %u", vrf->name, vrf->vrf_id);

if (!bvrf->bg_shop)
/* Don't open sockets when using data plane */
if (bglobal.bg_use_dplane)
goto skip_sockets;

if (bvrf->bg_shop == -1)
bvrf->bg_shop = bp_udp_shop(vrf);
if (!bvrf->bg_mhop)
if (bvrf->bg_mhop == -1)
bvrf->bg_mhop = bp_udp_mhop(vrf);
if (!bvrf->bg_shop6)
if (bvrf->bg_shop6 == -1)
bvrf->bg_shop6 = bp_udp6_shop(vrf);
if (!bvrf->bg_mhop6)
if (bvrf->bg_mhop6 == -1)
bvrf->bg_mhop6 = bp_udp6_mhop(vrf);
if (!bvrf->bg_echo)
bvrf->bg_echo = bp_echo_socket(vrf);
if (!bvrf->bg_echov6)
bvrf->bg_echov6 = bp_echov6_socket(vrf);

if (!bvrf->bg_ev[0] && bvrf->bg_shop != -1)
if (bvrf->bg_ev[0] == NULL && bvrf->bg_shop != -1)
event_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_shop,
&bvrf->bg_ev[0]);
if (!bvrf->bg_ev[1] && bvrf->bg_mhop != -1)
if (bvrf->bg_ev[1] == NULL && bvrf->bg_mhop != -1)
event_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_mhop,
&bvrf->bg_ev[1]);
if (!bvrf->bg_ev[2] && bvrf->bg_shop6 != -1)
if (bvrf->bg_ev[2] == NULL && bvrf->bg_shop6 != -1)
event_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_shop6,
&bvrf->bg_ev[2]);
if (!bvrf->bg_ev[3] && bvrf->bg_mhop6 != -1)
if (bvrf->bg_ev[3] == NULL && bvrf->bg_mhop6 != -1)
event_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_mhop6,
&bvrf->bg_ev[3]);
if (!bvrf->bg_ev[4] && bvrf->bg_echo != -1)
event_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_echo,
&bvrf->bg_ev[4]);
if (!bvrf->bg_ev[5] && bvrf->bg_echov6 != -1)
event_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_echov6,
&bvrf->bg_ev[5]);

/* Toggle echo if VRF was disabled. */
bfd_vrf_toggle_echo(bvrf);

skip_sockets:
if (vrf->vrf_id != VRF_DEFAULT) {
bfdd_zclient_register(vrf->vrf_id);
bfdd_sessions_enable_vrf(vrf);
}

return 0;
}

Expand Down Expand Up @@ -1948,17 +2011,9 @@ static int bfd_vrf_disable(struct vrf *vrf)
socket_close(&bvrf->bg_echo);
socket_close(&bvrf->bg_shop);
socket_close(&bvrf->bg_mhop);
if (bvrf->bg_shop6 != -1)
socket_close(&bvrf->bg_shop6);
if (bvrf->bg_mhop6 != -1)
socket_close(&bvrf->bg_mhop6);
socket_close(&bvrf->bg_echo);
if (bvrf->bg_echov6 != -1)
socket_close(&bvrf->bg_echov6);

/* free context */
XFREE(MTYPE_BFDD_VRF, bvrf);
vrf->info = NULL;
socket_close(&bvrf->bg_shop6);
socket_close(&bvrf->bg_mhop6);
socket_close(&bvrf->bg_echov6);

return 0;
}
Expand Down
2 changes: 2 additions & 0 deletions bfdd/bfd.h
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,8 @@ void bfd_sessions_remove_manual(void);
void bfd_profiles_remove(void);
void bfd_rtt_init(struct bfd_session *bfd);

extern void bfd_vrf_toggle_echo(struct bfd_vrf_global *bfd_vrf);

/**
* Set the BFD session echo state.
*
Expand Down
Loading