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: fix do not skip paths with same nexthop #16153

Merged
merged 3 commits into from
Jun 18, 2024

Conversation

pguibert6WIND
Copy link
Member

Under a setup where two BGP prefixes are available from multiple sources, if one of the two prefixes is recursive over the other BGP prefix, then it will not be considered as multipath. The below output shows the two prefixes 192.0.2.24/32 and 192.0.2.21/32. The 192.0.2.[5,6,8] are the known IP addresses visible from the IGP.

show bgp ipv4 192.0.2.24/32

*>i 192.0.2.24/32 192.0.2.21 0 100 0 i

  • i 192.0.2.21 0 100 0 i
  • i 192.0.2.21 0 100 0 i

show bgp ipv4 192.0.2.21/32

*>i 192.0.2.21/32 192.0.2.5 0 100 0 i
*=i 192.0.2.6 0 100 0 i
*=i 192.0.2.8 0 100 0 i

The bgp best selection algorithm refuses to consider the paths to '192.0.2.24/32' as multipath, whereas the BGP paths which use the BGP peer as nexthop are considered multipath.

... has the same nexthop as the bestpath, skip it ...

Previously, this condition has been added to prevent ZEBRA from installing routes with same nexthop:

Here you can see the two paths with nexthop 210.2.2.2
superm-redxp-05# show ip route 2.23.24.192/28
Routing entry for 2.23.24.192/28
  Known via "bgp", distance 20, metric 0, best
  Last update 00:32:12 ago
  * 210.2.2.2, via swp3
  * 210.2.0.2, via swp1
  * 210.2.1.2, via swp2
  * 210.2.2.2, via swp3

[..]

But today, ZEBRA knows how to handle it. When receiving incoming routes, nexthop groups are used. At creation, duplicated nexthops are identified, and will not be installed. The below output illustrate the duplicate paths to 172.16.0.200 received by an other peer.

r1# show ip route 172.18.1.100 nexthop-group
Routing entry for 172.18.1.100/32
Known via "bgp", distance 200, metric 0, best
Last update 00:03:03 ago
Nexthop Group ID: 75757580
172.16.0.200 (recursive), weight 1

  • 172.31.0.3, via r1-eth1, label 16055, weight 1
  • 172.31.2.4, via r1-eth2, label 16055, weight 1
  • 172.31.0.3, via r1-eth1, label 16006, weight 1
  • 172.31.2.4, via r1-eth2, label 16006, weight 1
  • 172.31.8.7, via r1-eth4, label 16008, weight 1
    172.16.0.200 (duplicate nexthop removed) (recursive), weight 1
    172.31.0.3, via r1-eth1 (duplicate nexthop removed), label 16055, weight 1
    172.31.2.4, via r1-eth2 (duplicate nexthop removed), label 16055, weight 1
    172.31.0.3, via r1-eth1 (duplicate nexthop removed), label 16006, weight 1
    172.31.2.4, via r1-eth2 (duplicate nexthop removed), label 16006, weight 1
    172.31.8.7, via r1-eth4 (duplicate nexthop removed), label 16008, weight 1

Fix this by proposing to let ZEBRA handle this duplicate decision.

Fixes: 7dc9d4e ("bgp may add multiple path entries with the same nexthop")

@pguibert6WIND pguibert6WIND marked this pull request as draft June 4, 2024 09:21
Copy link
Member

@ton31337 ton31337 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A topotest?

@pguibert6WIND
Copy link
Member Author

A topotest?

I am surprised that it passes, I was thinking there was already something that was covering this.
sure I will do it.

I would like a feedback if you think it is worth configuring this behaviour ?

@pguibert6WIND pguibert6WIND force-pushed the bgp_recursive_duplicate branch from 2a4692b to a2701c7 Compare June 4, 2024 20:04
@github-actions github-actions bot added size/XL and removed size/M labels Jun 4, 2024
@pguibert6WIND pguibert6WIND force-pushed the bgp_recursive_duplicate branch 4 times, most recently from e635ddb to 079cde9 Compare June 6, 2024 12:07
@pguibert6WIND pguibert6WIND marked this pull request as ready for review June 6, 2024 15:05
bgpd/bgp_mpath.c Show resolved Hide resolved
@@ -0,0 +1,14 @@
debug bgp bestpath 192.0.2.8/32
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please comment this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -602,6 +602,30 @@ def is_linux():
return False


def iproute2_is_json_capable():
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we put this into a separate commit?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -0,0 +1,43 @@
# SPDX-License-Identifier: ISC
#
# Copyright (c) 2019 by VMware, Inc. ("VMware")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VMWare?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

replaced with 6w..

else:
output = json.loads(router.run(f"ip -json route show {ipaddr_str}"))
if output is None:
return "problem. iproute2 returns nothing"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return {} then...

Copy link
Member Author

@pguibert6WIND pguibert6WIND Jun 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added some more checks. this said, if you have a correct json, then json_cmp will do the job.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My point was to return always a valid JSON (for json_cmp() to compare properly) rather than (None, string, JSON-string)...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I handled the exception, it should be betteR.

)
if rname in ("r1", "r3", "r5", "r6"):
router.load_config(
TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I encourage using "frr.conf" (single file) for upcoming tests...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for encouragement. I will do it at next test I start from scratch.

ip_check_path_selection, tgen.gears["r1"], prefix, expected
)
_, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
assert result is None, f"Failed to check that {prefix} uses the IGP label 16055"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But it can be the label 16006 also, correct?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right. fixed comment


def test_bgp_ipv4_convergence():
"""
Check that R1 has received the 192.0.2.9/32 prefix from R5, and R8
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r6 maybe?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

replaced r8 with r6


tgen.gears["r1"].vtysh_cmd(
"""
configure terminal\n
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

\n not needed

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed \n

""",
isjson=False,
)
tgen.gears["r1"].vtysh_cmd("clear bgp ipv4 *\n")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

\n not needed

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed \n

@pguibert6WIND pguibert6WIND force-pushed the bgp_recursive_duplicate branch 2 times, most recently from e47fdda to c912d61 Compare June 10, 2024 15:38
Under a setup where two BGP prefixes are available from multiple sources,
if one of the two prefixes is recursive over the other BGP prefix, then
it will not be considered as multipath. The below output shows the two
prefixes 192.0.2.24/32 and 192.0.2.21/32. The 192.0.2.[5,6,8] are the
known IP addresses visible from the IGP.

> # show bgp ipv4 192.0.2.24/32
> *>i 192.0.2.24/32    192.0.2.21               0    100      0 i
> * i                  192.0.2.21               0    100      0 i
> * i                  192.0.2.21               0    100      0 i
> # show bgp ipv4 192.0.2.21/32
>  *>i 192.0.2.21/32    192.0.2.5                0    100      0 i
>  *=i                  192.0.2.6                0    100      0 i
>  *=i                  192.0.2.8                0    100      0 i

The bgp best selection algorithm refuses to consider the paths to
'192.0.2.24/32' as multipath, whereas the BGP paths which use the
BGP peer as nexthop are considered multipath.

> ... has the same nexthop as the bestpath, skip it ...

Previously, this condition has been added to prevent ZEBRA from
installing routes with same nexthop:

>     Here you can see the two paths with nexthop 210.2.2.2
>     superm-redxp-05# show ip route 2.23.24.192/28
>     Routing entry for 2.23.24.192/28
>       Known via "bgp", distance 20, metric 0, best
>       Last update 00:32:12 ago
>       * 210.2.2.2, via swp3
>       * 210.2.0.2, via swp1
>       * 210.2.1.2, via swp2
>       * 210.2.2.2, via swp3
> [..]

But today, ZEBRA knows how to handle it. When receiving incoming routes,
nexthop groups are used. At creation, duplicated nexthops are
identified, and will not be installed. The below output illustrate the
duplicate paths to 172.16.0.200 received by an other peer.

> r1# show ip route 172.18.1.100 nexthop-group
> Routing entry for 172.18.1.100/32
>   Known via "bgp", distance 200, metric 0, best
>   Last update 00:03:03 ago
>   Nexthop Group ID: 75757580
>     172.16.0.200 (recursive), weight 1
>   *   172.31.0.3, via r1-eth1, label 16055, weight 1
>   *   172.31.2.4, via r1-eth2, label 16055, weight 1
>   *   172.31.0.3, via r1-eth1, label 16006, weight 1
>   *   172.31.2.4, via r1-eth2, label 16006, weight 1
>   *   172.31.8.7, via r1-eth4, label 16008, weight 1
>     172.16.0.200 (duplicate nexthop removed) (recursive), weight 1
>       172.31.0.3, via r1-eth1 (duplicate nexthop removed), label 16055, weight 1
>       172.31.2.4, via r1-eth2 (duplicate nexthop removed), label 16055, weight 1
>       172.31.0.3, via r1-eth1 (duplicate nexthop removed), label 16006, weight 1
>       172.31.2.4, via r1-eth2 (duplicate nexthop removed), label 16006, weight 1
>       172.31.8.7, via r1-eth4 (duplicate nexthop removed), label 16008, weight 1

Fix this by proposing to let ZEBRA handle this duplicate decision.

Fixes: 7dc9d4e ("bgp may add multiple path entries with the same nexthop")

Signed-off-by: Philippe Guibert <[email protected]>
Some tests may want to use the json facility of iproute2 to
dump some results.
Add an internal API in lib/topotest.py that tells whether iproute2
is json capable or not.

Signed-off-by: Philippe Guibert <[email protected]>
Add a topotest that ensures that when addpath is enabled and two
paths with same nexthop are received, they are sent to ZEBRA which
detects 'duplicate nexthop'.

Signed-off-by: Philippe Guibert <[email protected]>
@pguibert6WIND pguibert6WIND force-pushed the bgp_recursive_duplicate branch from c912d61 to d0bac27 Compare June 11, 2024 08:07
Copy link
Member

@riw777 riw777 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good

@riw777 riw777 added the bugfix label Jun 11, 2024
@riw777 riw777 merged commit 627a8ac into FRRouting:master Jun 18, 2024
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants