tests: fix and adjust topotest/bgp_aigp

Fix and adjust the topotest post the fix for route selection with
AIGP.

When there are multiple	IGP domains (OSPF in this case), the nexthop
for a BGP route with the AIGP attribute must be resolved in its own
IGP domain.

The changes in r2/bgpd.conf and r3/bgpd.conf are needed as incorrect
IGP metrics are received from NHT for the recursive nexthops. Once
the issue is resolved, the changes can be reverted.

Signed-off-by: Enke Chen <enchen@paloaltonetworks.com>
(cherry picked from commit 1ee7e63a6c)
This commit is contained in:
Enke Chen 2024-10-14 18:47:59 -07:00 committed by Mergify
parent 3394680c23
commit 4fc971a53e
12 changed files with 111 additions and 35 deletions

View File

@ -1,6 +1,6 @@
! !
interface lo interface lo
ip ospf cost 10 ip ospf passive
! !
interface r1-eth0 interface r1-eth0
ip ospf dead-interval 4 ip ospf dead-interval 4

View File

@ -1,6 +1,7 @@
router bgp 65001 router bgp 65001
no bgp ebgp-requires-policy no bgp ebgp-requires-policy
no bgp network import-check no bgp network import-check
bgp route-reflector allow-outbound-policy
neighbor 10.0.0.1 remote-as internal neighbor 10.0.0.1 remote-as internal
neighbor 10.0.0.1 timers 1 3 neighbor 10.0.0.1 timers 1 3
neighbor 10.0.0.1 timers connect 1 neighbor 10.0.0.1 timers connect 1
@ -11,5 +12,6 @@ router bgp 65001
neighbor 192.168.24.4 aigp neighbor 192.168.24.4 aigp
address-family ipv4 address-family ipv4
redistribute connected redistribute connected
neighbor 10.0.0.1 next-hop-self force
exit-address-family exit-address-family
! !

View File

@ -1,6 +1,6 @@
! !
interface lo interface lo
ip ospf cost 10 ip ospf passive
! !
interface r2-eth0 interface r2-eth0
ip ospf dead-interval 4 ip ospf dead-interval 4

View File

@ -1,6 +1,7 @@
router bgp 65001 router bgp 65001
no bgp ebgp-requires-policy no bgp ebgp-requires-policy
no bgp network import-check no bgp network import-check
bgp route-reflector allow-outbound-policy
neighbor 10.0.0.1 remote-as internal neighbor 10.0.0.1 remote-as internal
neighbor 10.0.0.1 timers 1 3 neighbor 10.0.0.1 timers 1 3
neighbor 10.0.0.1 timers connect 1 neighbor 10.0.0.1 timers connect 1
@ -11,5 +12,6 @@ router bgp 65001
neighbor 192.168.35.5 aigp neighbor 192.168.35.5 aigp
address-family ipv4 address-family ipv4
redistribute connected redistribute connected
neighbor 10.0.0.1 next-hop-self force
exit-address-family exit-address-family
! !

View File

@ -1,6 +1,6 @@
! !
interface lo interface lo
ip ospf cost 10 ip ospf passive
! !
interface r3-eth0 interface r3-eth0
ip ospf dead-interval 4 ip ospf dead-interval 4

View File

@ -1,6 +1,7 @@
router bgp 65001 router bgp 65001
no bgp ebgp-requires-policy no bgp ebgp-requires-policy
no bgp network import-check no bgp network import-check
bgp route-reflector allow-outbound-policy
neighbor 192.168.24.2 remote-as internal neighbor 192.168.24.2 remote-as internal
neighbor 192.168.24.2 timers 1 3 neighbor 192.168.24.2 timers 1 3
neighbor 192.168.24.2 timers connect 1 neighbor 192.168.24.2 timers connect 1
@ -11,7 +12,18 @@ router bgp 65001
neighbor 10.0.0.6 timers connect 1 neighbor 10.0.0.6 timers connect 1
neighbor 10.0.0.6 update-source lo neighbor 10.0.0.6 update-source lo
address-family ipv4 address-family ipv4
redistribute connected redistribute connected route-map connected-to-bgp
redistribute ospf neighbor 192.168.24.2 route-map set-nexthop out
exit-address-family exit-address-family
! !
! Two OSPF domains should be isolated - otherwise the connected routes
! on r4 would be advertised to r3 (via r4 -> r6 -> r5 -> r3), and can
! mess up bgp bestpath calculation (igp metrics for the BGP nexthops).
!
route-map connected-to-bgp permit 10
set community no-advertise
!
route-map set-nexthop permit 10
set ip next-hop peer-address
exit
!

View File

@ -1,6 +1,6 @@
! !
interface lo interface lo
ip ospf cost 10 ip ospf passive
! !
interface r4-eth1 interface r4-eth1
ip ospf dead-interval 4 ip ospf dead-interval 4

View File

@ -1,6 +1,7 @@
router bgp 65001 router bgp 65001
no bgp ebgp-requires-policy no bgp ebgp-requires-policy
no bgp network import-check no bgp network import-check
bgp route-reflector allow-outbound-policy
neighbor 192.168.35.3 remote-as internal neighbor 192.168.35.3 remote-as internal
neighbor 192.168.35.3 timers 1 3 neighbor 192.168.35.3 timers 1 3
neighbor 192.168.35.3 timers connect 1 neighbor 192.168.35.3 timers connect 1
@ -11,7 +12,18 @@ router bgp 65001
neighbor 10.0.0.6 timers connect 1 neighbor 10.0.0.6 timers connect 1
neighbor 10.0.0.6 update-source lo neighbor 10.0.0.6 update-source lo
address-family ipv4 address-family ipv4
redistribute connected redistribute connected route-map connected-to-bgp
redistribute ospf neighbor 192.168.35.3 route-map set-nexthop out
exit-address-family exit-address-family
! !
! Two OSPF domains should be isolated - otherwise the connected routes
! on r5 would be advertised to r2 (via r5 -> r6 -> r4 -> r2), and can
! mess up bgp bestpath calculation (igp metrics for the BGP nexthops).
!
route-map connected-to-bgp permit 10
set community no-advertise
!
route-map set-nexthop permit 10
set ip next-hop peer-address
exit
!

View File

@ -1,6 +1,6 @@
! !
interface lo interface lo
ip ospf cost 10 ip ospf passive
! !
interface r5-eth1 interface r5-eth1
ip ospf dead-interval 4 ip ospf dead-interval 4

View File

@ -1,6 +1,7 @@
router bgp 65001 router bgp 65001
no bgp ebgp-requires-policy no bgp ebgp-requires-policy
no bgp network import-check no bgp network import-check
bgp route-reflector allow-outbound-policy
neighbor 10.0.0.4 remote-as internal neighbor 10.0.0.4 remote-as internal
neighbor 10.0.0.4 timers 1 3 neighbor 10.0.0.4 timers 1 3
neighbor 10.0.0.4 timers connect 1 neighbor 10.0.0.4 timers connect 1
@ -15,6 +16,11 @@ router bgp 65001
neighbor 192.168.67.7 timers 1 3 neighbor 192.168.67.7 timers 1 3
neighbor 192.168.67.7 timers connect 1 neighbor 192.168.67.7 timers connect 1
address-family ipv4 address-family ipv4
redistribute ospf neighbor 10.0.0.4 route-map set-nexthop out
neighbor 10.0.0.5 route-map set-nexthop out
exit-address-family exit-address-family
! !
route-map set-nexthop permit 10
set ip next-hop peer-address
exit
!

View File

@ -1,6 +1,6 @@
! !
interface lo interface lo
ip ospf cost 10 ip ospf passive
! !
interface r6-eth0 interface r6-eth0
ip ospf dead-interval 4 ip ospf dead-interval 4

View File

@ -12,9 +12,9 @@ r7 sets aigp-metric for 10.0.0.71/32 to 71, and 72 for 10.0.0.72/32.
r6 receives those routes with aigp-metric TLV. r6 receives those routes with aigp-metric TLV.
r2 and r3 receives those routes with aigp-metric TLV increased by 20, r2 and r3 receives those routes with aigp-metric TLV increased by 20,
and 30 appropriately. and 10 appropriately.
r1 receives routes with aigp-metric TLV 111,131 and 112,132 appropriately. r1 receives routes with aigp-metric TLV 81, 91 and 82, 92 respectively.
""" """
import os import os
@ -109,15 +109,29 @@ def test_bgp_aigp():
expected = { expected = {
"paths": [ "paths": [
{ {
"aigpMetric": 111, "aigpMetric": 81,
"valid": True, "valid": True,
"nexthops": [{"hostname": "r3", "accessible": True}], "nexthops": [
{
"ip": "10.0.0.3",
"hostname": "r3",
"metric": 30,
"accessible": True,
}
],
}, },
{ {
"aigpMetric": 131, "aigpMetric": 91,
"valid": True, "valid": True,
"bestpath": {"selectionReason": "Neighbor IP"}, "bestpath": {"selectionReason": "IGP Metric"},
"nexthops": [{"hostname": "r2", "accessible": True}], "nexthops": [
{
"ip": "10.0.0.2",
"hostname": "r2",
"metric": 10,
"accessible": True,
}
],
}, },
] ]
} }
@ -141,30 +155,58 @@ def test_bgp_aigp():
"10.0.0.71/32": { "10.0.0.71/32": {
"paths": [ "paths": [
{ {
"aigpMetric": 111, "aigpMetric": 81,
"bestpath": {"selectionReason": "AIGP"},
"valid": True, "valid": True,
"nexthops": [{"hostname": "r3", "accessible": True}], "nexthops": [
{
"ip": "10.0.0.3",
"hostname": "r3",
"metric": 30,
"accessible": True,
}
],
}, },
{ {
"aigpMetric": 131, "aigpMetric": 91,
"valid": True, "valid": True,
"nexthops": [{"hostname": "r2", "accessible": True}], "bestpath": {"selectionReason": "AIGP"},
"nexthops": [
{
"ip": "10.0.0.2",
"hostname": "r2",
"metric": 10,
"accessible": True,
}
],
}, },
], ],
}, },
"10.0.0.72/32": { "10.0.0.72/32": {
"paths": [ "paths": [
{ {
"aigpMetric": 112, "aigpMetric": 82,
"bestpath": {"selectionReason": "AIGP"},
"valid": True, "valid": True,
"nexthops": [{"hostname": "r3", "accessible": True}], "nexthops": [
{
"ip": "10.0.0.3",
"hostname": "r3",
"metric": 30,
"accessible": True,
}
],
}, },
{ {
"aigpMetric": 132, "aigpMetric": 92,
"valid": True, "valid": True,
"nexthops": [{"hostname": "r2", "accessible": True}], "bestpath": {"selectionReason": "AIGP"},
"nexthops": [
{
"ip": "10.0.0.2",
"hostname": "r2",
"metric": 10,
"accessible": True,
}
],
}, },
], ],
}, },
@ -196,17 +238,17 @@ def test_bgp_aigp():
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1) _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
assert result is None, "aigp-metric for 10.0.0.72/32 is not 72" assert result is None, "aigp-metric for 10.0.0.72/32 is not 72"
# r2, 10.0.0.71/32 with aigp-metric 101 (71 + 30) # r2, 10.0.0.71/32 with aigp-metric 101 (71 + 20)
test_func = functools.partial(_bgp_check_aigp_metric, r2, "10.0.0.71/32", 101) test_func = functools.partial(_bgp_check_aigp_metric, r2, "10.0.0.71/32", 91)
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1) _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
assert result is None, "aigp-metric for 10.0.0.71/32 is not 101" assert result is None, "aigp-metric for 10.0.0.71/32 is not 91"
# r3, 10.0.0.72/32 with aigp-metric 92 (72 + 20) # r3, 10.0.0.72/32 with aigp-metric 92 (72 + 10)
test_func = functools.partial(_bgp_check_aigp_metric, r3, "10.0.0.72/32", 92) test_func = functools.partial(_bgp_check_aigp_metric, r3, "10.0.0.72/32", 82)
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1) _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
assert result is None, "aigp-metric for 10.0.0.72/32 is not 92" assert result is None, "aigp-metric for 10.0.0.72/32 is not 82"
# r1, check if AIGP is considered in best-path selection (lowest wins) # r1, check if AIGP is considered in best-path selection (lowest wins: aigp + nexthop-metric)
test_func = functools.partial(_bgp_check_aigp_metric_bestpath) test_func = functools.partial(_bgp_check_aigp_metric_bestpath)
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1) _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
assert result is None, "AIGP attribute is not considered in best-path selection" assert result is None, "AIGP attribute is not considered in best-path selection"