Skip to content

Commit

Permalink
Merge pull request #16194 from opensourcerouting/fix/bfd_profile_shut…
Browse files Browse the repository at this point in the history
…down

bgpd: Do not start BGP session if BFD profile is in shutdown state
  • Loading branch information
riw777 authored Jun 18, 2024
2 parents b94fc2d + 1fb48f5 commit e9e8a4b
Show file tree
Hide file tree
Showing 8 changed files with 145 additions and 1 deletion.
1 change: 1 addition & 0 deletions bgpd/bgp_packet.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
6 changes: 6 additions & 0 deletions bgpd/bgpd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
6 changes: 6 additions & 0 deletions lib/bfd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
2 changes: 2 additions & 0 deletions lib/bfd.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions tests/topotests/bgp_bfd_down_cease_notification/r1/bfdd.conf
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
bfd
profile r1
exit
!
peer 192.168.255.2 interface r1-eth0
profile r1
exit
!
exit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ def _bgp_bfd_down_notification():
"192.168.255.1": {
"lastNotificationReason": "Cease/BFD Down",
"lastNotificationHardReset": True,
"peerBfdInfo": {
"status": "Up",
},
}
}
return topotest.json_cmp(output, expected)
Expand Down
Original file line number Diff line number Diff line change
@@ -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 <[email protected]>
#

"""
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))

0 comments on commit e9e8a4b

Please sign in to comment.