Skip to content

Commit da0eee2

Browse files
authored
Merge pull request FRRouting#13137 from FRRouting/mergify/bp/stable/8.5/pr-13124
bgpd: Do not announce routes immediatelly on prefix/distribute/filter changes (backport FRRouting#13124)
2 parents a4bb60f + 8b33a5c commit da0eee2

File tree

7 files changed

+170
-18
lines changed

7 files changed

+170
-18
lines changed

bgpd/bgpd.c

+14-18
Original file line numberDiff line numberDiff line change
@@ -5603,20 +5603,9 @@ void peer_on_policy_change(struct peer *peer, afi_t afi, safi_t safi,
56035603
return;
56045604

56055605
if (CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_OLD_RCV) ||
5606-
CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_NEW_RCV)) {
5607-
if (CHECK_FLAG(peer->af_cap[afi][safi],
5608-
PEER_CAP_ORF_PREFIX_SM_ADV) &&
5609-
(CHECK_FLAG(peer->af_cap[afi][safi],
5610-
PEER_CAP_ORF_PREFIX_RM_RCV) ||
5611-
CHECK_FLAG(peer->af_cap[afi][safi],
5612-
PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
5613-
peer_clear_soft(peer, afi, safi,
5614-
BGP_CLEAR_SOFT_IN_ORF_PREFIX);
5615-
else
5616-
bgp_route_refresh_send(
5617-
peer, afi, safi, 0, 0, 0,
5618-
BGP_ROUTE_REFRESH_NORMAL);
5619-
}
5606+
CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_NEW_RCV))
5607+
bgp_route_refresh_send(peer, afi, safi, 0, 0, 0,
5608+
BGP_ROUTE_REFRESH_NORMAL);
56205609
}
56215610
}
56225611

@@ -6846,11 +6835,18 @@ static void peer_prefix_list_update(struct prefix_list *plist)
68466835

68476836
/* If we touch prefix-list, we need to process
68486837
* new updates. This is important for ORF to
6849-
* work correctly as well.
6838+
* work correctly.
68506839
*/
6851-
if (peer->afc_nego[afi][safi])
6852-
peer_on_policy_change(peer, afi, safi,
6853-
0);
6840+
if (CHECK_FLAG(peer->af_cap[afi][safi],
6841+
PEER_CAP_ORF_PREFIX_SM_ADV) &&
6842+
(CHECK_FLAG(peer->af_cap[afi][safi],
6843+
PEER_CAP_ORF_PREFIX_RM_RCV) ||
6844+
CHECK_FLAG(
6845+
peer->af_cap[afi][safi],
6846+
PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
6847+
peer_clear_soft(
6848+
peer, afi, safi,
6849+
BGP_CLEAR_SOFT_IN_ORF_PREFIX);
68546850
}
68556851
}
68566852
for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {

tests/topotests/bgp_route_map_delay_timer/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
!
2+
debug bgp updates
3+
debug bgp neighbor
4+
!
5+
bgp route-map delay-timer 5
6+
!
7+
router bgp 65001
8+
no bgp ebgp-requires-policy
9+
no bgp network import-check
10+
neighbor 192.168.1.2 remote-as external
11+
address-family ipv4 unicast
12+
network 10.10.10.1/32
13+
network 10.10.10.2/32
14+
network 10.10.10.3/32
15+
aggregate-address 10.10.10.0/24 summary-only
16+
neighbor 192.168.1.2 unsuppress-map r2
17+
exit-address-family
18+
!
19+
ip prefix-list r1 seq 5 permit 10.10.10.1/32
20+
ip prefix-list r1 seq 10 permit 10.10.10.2/32
21+
!
22+
route-map r2 permit 10
23+
match ip address prefix-list r1
24+
exit
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
!
2+
int r1-eth0
3+
ip address 192.168.1.1/24
4+
!
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
router bgp 65002
2+
no bgp ebgp-requires-policy
3+
neighbor 192.168.1.1 remote-as external
4+
!
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
!
2+
int r2-eth0
3+
ip address 192.168.1.2/24
4+
!
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
#!/usr/bin/env python
2+
# SPDX-License-Identifier: ISC
3+
4+
# Copyright (c) 2023 by
5+
# Donatas Abraitis <[email protected]>
6+
#
7+
8+
"""
9+
10+
"""
11+
12+
import os
13+
import sys
14+
import json
15+
import pytest
16+
import functools
17+
18+
pytestmark = pytest.mark.bgpd
19+
20+
CWD = os.path.dirname(os.path.realpath(__file__))
21+
sys.path.append(os.path.join(CWD, "../"))
22+
23+
# pylint: disable=C0413
24+
from lib import topotest
25+
from lib.topogen import Topogen, TopoRouter, get_topogen
26+
27+
pytestmark = [pytest.mark.bgpd]
28+
29+
30+
def setup_module(mod):
31+
topodef = {"s1": ("r1", "r2")}
32+
tgen = Topogen(topodef, mod.__name__)
33+
tgen.start_topology()
34+
35+
router_list = tgen.routers()
36+
37+
for i, (rname, router) in enumerate(router_list.items(), 1):
38+
router.load_config(
39+
TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
40+
)
41+
router.load_config(
42+
TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
43+
)
44+
45+
tgen.start_router()
46+
47+
48+
def teardown_module(mod):
49+
tgen = get_topogen()
50+
tgen.stop_topology()
51+
52+
53+
def test_bgp_route_map_delay_timer():
54+
tgen = get_topogen()
55+
56+
if tgen.routers_have_failure():
57+
pytest.skip(tgen.errors)
58+
59+
r1 = tgen.gears["r1"]
60+
r2 = tgen.gears["r2"]
61+
62+
def _bgp_converge_1():
63+
output = json.loads(
64+
r1.vtysh_cmd(
65+
"show bgp ipv4 unicast neighbor 192.168.1.2 advertised-routes json"
66+
)
67+
)
68+
expected = {
69+
"advertisedRoutes": {
70+
"10.10.10.0/24": {},
71+
"10.10.10.1/32": {},
72+
"10.10.10.2/32": {},
73+
"10.10.10.3/32": None,
74+
}
75+
}
76+
return topotest.json_cmp(output, expected)
77+
78+
test_func = functools.partial(_bgp_converge_1)
79+
_, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
80+
assert result is None, "10.10.10.3/32 should not be advertised to r2"
81+
82+
# Set route-map delay-timer to max value and remove 10.10.10.2/32.
83+
# After this, r1 MUST do not announce updates immediately, and wait
84+
# 600 seconds before withdrawing 10.10.10.2/32.
85+
r2.vtysh_cmd(
86+
"""
87+
configure terminal
88+
bgp route-map delay-timer 600
89+
no ip prefix-list r1 seq 10 permit 10.10.10.2/32
90+
"""
91+
)
92+
93+
def _bgp_converge_2():
94+
output = json.loads(
95+
r1.vtysh_cmd(
96+
"show bgp ipv4 unicast neighbor 192.168.1.2 advertised-routes json"
97+
)
98+
)
99+
expected = {
100+
"advertisedRoutes": {
101+
"10.10.10.0/24": {},
102+
"10.10.10.1/32": {},
103+
"10.10.10.2/32": None,
104+
"10.10.10.3/32": None,
105+
}
106+
}
107+
return topotest.json_cmp(output, expected)
108+
109+
# We are checking `not None` here to wait count*wait time and if we have different
110+
# results than expected, it means good - 10.10.10.2/32 wasn't withdrawn immediately.
111+
test_func = functools.partial(_bgp_converge_2)
112+
_, result = topotest.run_and_expect(test_func, not None, count=60, wait=0.5)
113+
assert (
114+
result is not None
115+
), "10.10.10.2/32 advertised, but should not be advertised to r2"
116+
117+
118+
if __name__ == "__main__":
119+
args = ["-s"] + sys.argv[1:]
120+
sys.exit(pytest.main(args))

0 commit comments

Comments
 (0)