mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-06 02:16:53 +00:00
bfdd: don't enable sessions without local-address
When the local-address configured by the peer doesn't exist, then we must observe the session until the mentioned address comes up. Signed-off-by: Rafael Zalamena <rzalamena@opensourcerouting.org>
This commit is contained in:
parent
79b4a6fceb
commit
261e0ba94d
27
bfdd/bfd.c
27
bfdd/bfd.c
@ -162,6 +162,13 @@ int bfd_session_enable(struct bfd_session *bs)
|
||||
&& BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH) == 0)
|
||||
bs->ifp = ifp;
|
||||
|
||||
/* Sanity check: don't leak open sockets. */
|
||||
if (bs->sock != -1) {
|
||||
zlog_debug("session-enable: previous socket open");
|
||||
close(bs->sock);
|
||||
bs->sock = -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get socket for transmitting control packets. Note that if we
|
||||
* could use the destination port (3784) for the source
|
||||
@ -170,11 +177,11 @@ int bfd_session_enable(struct bfd_session *bs)
|
||||
if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_IPV6) == 0) {
|
||||
psock = bp_peer_socket(bs);
|
||||
if (psock == -1)
|
||||
return -1;
|
||||
return 0;
|
||||
} else {
|
||||
psock = bp_peer_socketv6(bs);
|
||||
if (psock == -1)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -662,10 +669,6 @@ struct bfd_session *ptm_bfd_sess_new(struct bfd_peer_cfg *bpc)
|
||||
strlcpy(bfd->key.vrfname, bpc->bpc_vrfname,
|
||||
sizeof(bfd->key.vrfname));
|
||||
|
||||
/* Add observer if we have moving parts. */
|
||||
if (bfd->key.ifname[0] || bfd->key.vrfname[0])
|
||||
bs_observer_add(bfd);
|
||||
|
||||
/* Copy remaining data. */
|
||||
if (bpc->bpc_ipv4 == false)
|
||||
BFD_SET_FLAG(bfd->flags, BFD_SESS_FLAG_IPV6);
|
||||
@ -708,6 +711,10 @@ struct bfd_session *ptm_bfd_sess_new(struct bfd_peer_cfg *bpc)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Add observer if we have moving parts. */
|
||||
if (bfd->key.ifname[0] || bfd->key.vrfname[0] || bfd->sock == -1)
|
||||
bs_observer_add(bfd);
|
||||
|
||||
/* Apply other configurations. */
|
||||
_bfd_session_update(bfd, bpc);
|
||||
|
||||
@ -1190,6 +1197,14 @@ int bs_observer_add(struct bfd_session *bs)
|
||||
strlcpy(bso->bso_entryname, bs->key.vrfname,
|
||||
sizeof(bso->bso_entryname));
|
||||
|
||||
/* Handle socket binding failures caused by missing local addresses. */
|
||||
if (bs->sock == -1) {
|
||||
bso->bso_isaddress = true;
|
||||
bso->bso_addr.family = bs->key.family;
|
||||
memcpy(&bso->bso_addr.u.prefix, &bs->key.local,
|
||||
sizeof(bs->key.local));
|
||||
}
|
||||
|
||||
TAILQ_INSERT_TAIL(&bglobal.bg_obslist, bso, bso_entry);
|
||||
|
||||
return 0;
|
||||
|
@ -274,7 +274,11 @@ struct bfd_state_str_list {
|
||||
struct bfd_session_observer {
|
||||
struct bfd_session *bso_bs;
|
||||
bool bso_isinterface;
|
||||
char bso_entryname[MAXNAMELEN];
|
||||
bool bso_isaddress;
|
||||
union {
|
||||
char bso_entryname[MAXNAMELEN];
|
||||
struct prefix bso_addr;
|
||||
};
|
||||
|
||||
TAILQ_ENTRY(bfd_session_observer) bso_entry;
|
||||
};
|
||||
|
@ -942,7 +942,8 @@ static void _bfdd_peer_write_config(struct vty *vty, struct bfd_session *bs)
|
||||
vty_out(vty, "\n");
|
||||
|
||||
if (bs->sock == -1)
|
||||
vty_out(vty, " ! vrf or interface doesn't exist\n");
|
||||
vty_out(vty,
|
||||
" ! vrf, interface or local-address doesn't exist\n");
|
||||
|
||||
if (bs->detect_mult != BPC_DEF_DETECTMULTIPLIER)
|
||||
vty_out(vty, " detect-multiplier %d\n", bs->detect_mult);
|
||||
|
@ -634,6 +634,48 @@ static int bfdd_interface_vrf_update(int command __attribute__((__unused__)),
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bfdd_sessions_enable_address(struct connected *ifc)
|
||||
{
|
||||
struct bfd_session_observer *bso;
|
||||
struct bfd_session *bs;
|
||||
struct prefix prefix;
|
||||
|
||||
TAILQ_FOREACH(bso, &bglobal.bg_obslist, bso_entry) {
|
||||
if (bso->bso_isaddress == false)
|
||||
continue;
|
||||
|
||||
/* Skip enabled sessions. */
|
||||
bs = bso->bso_bs;
|
||||
if (bs->sock != -1)
|
||||
continue;
|
||||
|
||||
/* Check address. */
|
||||
prefix = bso->bso_addr;
|
||||
prefix.prefixlen = ifc->address->prefixlen;
|
||||
if (prefix_cmp(&prefix, ifc->address))
|
||||
continue;
|
||||
|
||||
/* Try to enable it. */
|
||||
bfd_session_enable(bs);
|
||||
}
|
||||
}
|
||||
|
||||
static int bfdd_interface_address_update(int cmd, struct zclient *zc,
|
||||
zebra_size_t len
|
||||
__attribute__((__unused__)),
|
||||
vrf_id_t vrfid)
|
||||
{
|
||||
struct connected *ifc;
|
||||
|
||||
ifc = zebra_interface_address_read(cmd, zc->ibuf, vrfid);
|
||||
if (ifc == NULL)
|
||||
return 0;
|
||||
|
||||
bfdd_sessions_enable_address(ifc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bfdd_zclient_init(struct zebra_privs_t *bfdd_priv)
|
||||
{
|
||||
zclient = zclient_new(master, &zclient_options_default);
|
||||
@ -656,6 +698,10 @@ void bfdd_zclient_init(struct zebra_privs_t *bfdd_priv)
|
||||
|
||||
/* Learn about interface VRF. */
|
||||
zclient->interface_vrf_update = bfdd_interface_vrf_update;
|
||||
|
||||
/* Learn about new addresses being registered. */
|
||||
zclient->interface_address_add = bfdd_interface_address_update;
|
||||
zclient->interface_address_delete = bfdd_interface_address_update;
|
||||
}
|
||||
|
||||
void bfdd_zclient_stop(void)
|
||||
|
Loading…
Reference in New Issue
Block a user