Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bgpd: Do not start BGP session if BFD profile is in shutdown state #16194

Merged
merged 3 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
ton31337 marked this conversation as resolved.
Show resolved Hide resolved

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