summaryrefslogtreecommitdiff
path: root/bfdd
diff options
context:
space:
mode:
authorRuss White <russ@riw.us>2024-11-26 08:51:07 -0500
committerGitHub <noreply@github.com>2024-11-26 08:51:07 -0500
commite268fc4665e18cd9c3226fab93158cc30c0eb0e6 (patch)
tree0c39971517e20ab77f44e1508ed7f6bf5534730b /bfdd
parente8fdbbeb7b11963c95ed34e7a88892e50754b16f (diff)
parent20c3756f30f69ae71d9d7acefb925dfb9d526303 (diff)
Merge pull request #16987 from opensourcerouting/bfd-echo-sock
bfdd: disable echo socket when not using it
Diffstat (limited to 'bfdd')
-rw-r--r--bfdd/bfd.c151
-rw-r--r--bfdd/bfd.h2
2 files changed, 105 insertions, 48 deletions
diff --git a/bfdd/bfd.c b/bfdd/bfd.c
index eb9c300313..f32bc2598b 100644
--- a/bfdd/bfd.c
+++ b/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)
+ /* 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;
}
@@ -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;
}
diff --git a/bfdd/bfd.h b/bfdd/bfd.h
index 2f83b245eb..d4d14ffce6 100644
--- a/bfdd/bfd.h
+++ b/bfdd/bfd.h
@@ -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.
*