Merge pull request #16194 from opensourcerouting/fix/bfd_profile_shutdown

bgpd: Do not start BGP session if BFD profile is in shutdown state
This commit is contained in:
Russ White 2024-06-18 09:57:00 -04:00 committed by GitHub
commit e9e8a4baa4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 145 additions and 1 deletions

View File

@ -982,6 +982,7 @@ static void bgp_notify_send_internal(struct peer_connection *connection,
peer->notify.code = bgp_notify.code;
peer->notify.subcode = bgp_notify.subcode;
peer->notify.length = bgp_notify.length;
peer->notify.hard_reset = hard_reset;
if (bgp_notify.length && data) {
bgp_notify.data = XMALLOC(MTYPE_BGP_NOTIFICATION,

View File

@ -4507,6 +4507,12 @@ bool peer_active(struct peer *peer)
{
if (BGP_CONNECTION_SU_UNSPEC(peer->connection))
return false;
if (peer->bfd_config) {
if (bfd_session_is_down(peer->bfd_config->session))
return false;
}
if (peer->afc[AFI_IP][SAFI_UNICAST] || peer->afc[AFI_IP][SAFI_MULTICAST]
|| peer->afc[AFI_IP][SAFI_LABELED_UNICAST]
|| peer->afc[AFI_IP][SAFI_MPLS_VPN] || peer->afc[AFI_IP][SAFI_ENCAP]

View File

@ -1334,3 +1334,9 @@ int bfd_nht_update(const struct prefix *match, const struct zapi_route *route)
return 0;
}
bool bfd_session_is_down(const struct bfd_session_params *session)
{
return session->bss.state == BSS_DOWN ||
session->bss.state == BSS_ADMIN_DOWN;
}

View File

@ -464,6 +464,8 @@ extern bool bfd_protocol_integration_shutting_down(void);
extern int bfd_nht_update(const struct prefix *match,
const struct zapi_route *route);
extern bool bfd_session_is_down(const struct bfd_session_params *session);
#ifdef __cplusplus
}
#endif

View File

@ -1,5 +1,9 @@
bfd
profile r1
exit
!
peer 192.168.255.2 interface r1-eth0
profile r1
exit
!
exit

View File

@ -3,7 +3,7 @@ router bgp 65001
neighbor 192.168.255.2 remote-as external
neighbor 192.168.255.2 timers 3 10
neighbor 192.168.255.2 timers connect 1
neighbor 192.168.255.2 bfd
neighbor 192.168.255.2 bfd profile r1
neighbor 192.168.255.2 passive
address-family ipv4
redistribute connected

View File

@ -89,6 +89,9 @@ def test_bgp_bfd_down_notification():
"192.168.255.1": {
"lastNotificationReason": "Cease/BFD Down",
"lastNotificationHardReset": True,
"peerBfdInfo": {
"status": "Up",
},
}
}
return topotest.json_cmp(output, expected)

View File

@ -0,0 +1,122 @@
#!/usr/bin/env python
# SPDX-License-Identifier: ISC
#
# bgp_bfd_down_cease_notification_shutdown.py
#
# Copyright (c) 2024 by
# Donatas Abraitis <donatas@opensourcerouting.org>
#
"""
Check if Cease/BFD Down notification message is sent/received
when the BFD is down (administratively).
"""
import os
import sys
import json
import pytest
import functools
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
# pylint: disable=C0413
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.common_config import kill_router_daemons, step
pytestmark = [pytest.mark.bfdd, pytest.mark.bgpd]
def build_topo(tgen):
for routern in range(1, 3):
tgen.add_router("r{}".format(routern))
switch = tgen.add_switch("s1")
switch.add_link(tgen.gears["r1"])
switch.add_link(tgen.gears["r2"])
def setup_module(mod):
tgen = Topogen(build_topo, mod.__name__)
tgen.start_topology()
router_list = tgen.routers()
for i, (rname, router) in enumerate(router_list.items(), 1):
router.load_config(
TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
)
router.load_config(
TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
)
router.load_config(
TopoRouter.RD_BFD, os.path.join(CWD, "{}/bfdd.conf".format(rname))
)
tgen.start_router()
def teardown_module(mod):
tgen = get_topogen()
tgen.stop_topology()
def test_bgp_bfd_down_notification_shutdown():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
r1 = tgen.gears["r1"]
r2 = tgen.gears["r2"]
def _bgp_converge():
output = json.loads(r2.vtysh_cmd("show ip bgp neighbor 192.168.255.1 json"))
expected = {
"192.168.255.1": {
"bgpState": "Established",
"addressFamilyInfo": {"ipv4Unicast": {"acceptedPrefixCounter": 2}},
"peerBfdInfo": {"status": "Up"},
}
}
return topotest.json_cmp(output, expected)
def _bgp_bfd_down_notification():
output = json.loads(r2.vtysh_cmd("show ip bgp neighbor 192.168.255.1 json"))
expected = {
"192.168.255.1": {
"lastNotificationReason": "Cease/BFD Down",
"lastNotificationHardReset": True,
"peerBfdInfo": {
"status": "Down",
},
}
}
return topotest.json_cmp(output, expected)
step("Initial BGP converge")
test_func = functools.partial(_bgp_converge)
_, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
assert result is None, "Failed to see BGP convergence on R2"
r1.vtysh_cmd(
"""
configure
bfd
profile r1
shutdown
"""
)
step("Check if we received Cease/BFD Down notification message")
test_func = functools.partial(_bgp_bfd_down_notification)
_, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
assert result is None, "Failed to see BGP Cease/BFD Down notification message on R2"
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))