forked from Mirror/frr
bfdd: disable echo socket when not using it
Lets avoid a performance penalty in forwarding when not using the BFD echo feature. The echo socket uses raw packet capturing along with a BPF filter which causes performance issues. While here change code to use `-1` for closed sockets instead of valid FD number `0`. Signed-off-by: Rafael Zalamena <rzalamena@opensourcerouting.org>
This commit is contained in:
parent
ac6314d380
commit
20c3756f30
153
bfdd/bfd.c
153
bfdd/bfd.c
|
@ -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)
|
||||
|
@ -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]);
|
||||
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.
|
||||
*/
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
bvrf->bg_shop = bp_udp_shop(vrf);
|
||||
if (!bvrf->bg_mhop)
|
||||
bvrf->bg_mhop = bp_udp_mhop(vrf);
|
||||
if (!bvrf->bg_shop6)
|
||||
bvrf->bg_shop6 = bp_udp6_shop(vrf);
|
||||
if (!bvrf->bg_mhop6)
|
||||
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);
|
||||
/* Don't open sockets when using data plane */
|
||||
if (bglobal.bg_use_dplane)
|
||||
goto skip_sockets;
|
||||
|
||||
if (!bvrf->bg_ev[0] && bvrf->bg_shop != -1)
|
||||
if (bvrf->bg_shop == -1)
|
||||
bvrf->bg_shop = bp_udp_shop(vrf);
|
||||
if (bvrf->bg_mhop == -1)
|
||||
bvrf->bg_mhop = bp_udp_mhop(vrf);
|
||||
if (bvrf->bg_shop6 == -1)
|
||||
bvrf->bg_shop6 = bp_udp6_shop(vrf);
|
||||
if (bvrf->bg_mhop6 == -1)
|
||||
bvrf->bg_mhop6 = bp_udp6_mhop(vrf);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1948,18 +2011,10 @@ 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;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
Loading…
Reference in a new issue