diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index 889902efcb0a..47273b4f9ff2 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -469,16 +469,6 @@ static bool bgp_attr_aigp_get_tlv_metric(uint8_t *pnt, int length, return false; } -static uint64_t bgp_aigp_metric_total(struct bgp_path_info *bpi) -{ - uint64_t aigp = bgp_attr_get_aigp_metric(bpi->attr); - - if (bpi->nexthop) - return aigp + bpi->nexthop->metric; - else - return aigp; -} - static void stream_put_bgp_aigp_tlv_metric(struct stream *s, struct bgp_path_info *bpi) { diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index c3e661a8c87e..b5ea45971f5c 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -595,6 +595,16 @@ static inline void bgp_attr_set_aigp_metric(struct attr *attr, uint64_t aigp) attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AIGP); } +static inline uint64_t bgp_aigp_metric_total(struct bgp_path_info *bpi) +{ + uint64_t aigp = bgp_attr_get_aigp_metric(bpi->attr); + + if (bpi->nexthop) + return aigp + bpi->nexthop->metric; + else + return aigp; +} + static inline struct cluster_list *bgp_attr_get_cluster(const struct attr *attr) { return attr->cluster1; diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 39009146f74e..6c71c87580f0 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -927,8 +927,8 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, if (CHECK_FLAG(newattr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP)) && CHECK_FLAG(existattr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP)) && CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_AIGP)) { - uint64_t new_aigp = bgp_attr_get_aigp_metric(newattr); - uint64_t exist_aigp = bgp_attr_get_aigp_metric(existattr); + uint64_t new_aigp = bgp_aigp_metric_total(new); + uint64_t exist_aigp = bgp_aigp_metric_total(exist); if (new_aigp < exist_aigp) { *reason = bgp_path_selection_aigp; diff --git a/tests/topotests/bgp_aigp/r1/ospfd.conf b/tests/topotests/bgp_aigp/r1/ospfd.conf index 38aa11d0362a..098bf57b0365 100644 --- a/tests/topotests/bgp_aigp/r1/ospfd.conf +++ b/tests/topotests/bgp_aigp/r1/ospfd.conf @@ -1,6 +1,6 @@ ! interface lo - ip ospf cost 10 + ip ospf passive ! interface r1-eth0 ip ospf dead-interval 4 diff --git a/tests/topotests/bgp_aigp/r2/bgpd.conf b/tests/topotests/bgp_aigp/r2/bgpd.conf index 4db468753642..4539016f916b 100644 --- a/tests/topotests/bgp_aigp/r2/bgpd.conf +++ b/tests/topotests/bgp_aigp/r2/bgpd.conf @@ -1,6 +1,7 @@ router bgp 65001 no bgp ebgp-requires-policy no bgp network import-check + bgp route-reflector allow-outbound-policy neighbor 10.0.0.1 remote-as internal neighbor 10.0.0.1 timers 1 3 neighbor 10.0.0.1 timers connect 1 @@ -11,5 +12,6 @@ router bgp 65001 neighbor 192.168.24.4 aigp address-family ipv4 redistribute connected + neighbor 10.0.0.1 next-hop-self force exit-address-family ! diff --git a/tests/topotests/bgp_aigp/r2/ospfd.conf b/tests/topotests/bgp_aigp/r2/ospfd.conf index ed31941f65c0..106a46251d2e 100644 --- a/tests/topotests/bgp_aigp/r2/ospfd.conf +++ b/tests/topotests/bgp_aigp/r2/ospfd.conf @@ -1,6 +1,6 @@ ! interface lo - ip ospf cost 10 + ip ospf passive ! interface r2-eth0 ip ospf dead-interval 4 diff --git a/tests/topotests/bgp_aigp/r3/bgpd.conf b/tests/topotests/bgp_aigp/r3/bgpd.conf index 5ab712eaba65..bdaa5cf55d1e 100644 --- a/tests/topotests/bgp_aigp/r3/bgpd.conf +++ b/tests/topotests/bgp_aigp/r3/bgpd.conf @@ -1,6 +1,7 @@ router bgp 65001 no bgp ebgp-requires-policy no bgp network import-check + bgp route-reflector allow-outbound-policy neighbor 10.0.0.1 remote-as internal neighbor 10.0.0.1 timers 1 3 neighbor 10.0.0.1 timers connect 1 @@ -11,5 +12,6 @@ router bgp 65001 neighbor 192.168.35.5 aigp address-family ipv4 redistribute connected + neighbor 10.0.0.1 next-hop-self force exit-address-family ! diff --git a/tests/topotests/bgp_aigp/r3/ospfd.conf b/tests/topotests/bgp_aigp/r3/ospfd.conf index f971ad6f8975..9ede3a1fab64 100644 --- a/tests/topotests/bgp_aigp/r3/ospfd.conf +++ b/tests/topotests/bgp_aigp/r3/ospfd.conf @@ -1,6 +1,6 @@ ! interface lo - ip ospf cost 10 + ip ospf passive ! interface r3-eth0 ip ospf dead-interval 4 diff --git a/tests/topotests/bgp_aigp/r4/bgpd.conf b/tests/topotests/bgp_aigp/r4/bgpd.conf index aa88bac91385..e12c45e0bb06 100644 --- a/tests/topotests/bgp_aigp/r4/bgpd.conf +++ b/tests/topotests/bgp_aigp/r4/bgpd.conf @@ -1,6 +1,7 @@ router bgp 65001 no bgp ebgp-requires-policy no bgp network import-check + bgp route-reflector allow-outbound-policy neighbor 192.168.24.2 remote-as internal neighbor 192.168.24.2 timers 1 3 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 update-source lo address-family ipv4 - redistribute connected - redistribute ospf + redistribute connected route-map connected-to-bgp + neighbor 192.168.24.2 route-map set-nexthop out 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 +! diff --git a/tests/topotests/bgp_aigp/r4/ospfd.conf b/tests/topotests/bgp_aigp/r4/ospfd.conf index c9e6796f6e74..237b5e18abe0 100644 --- a/tests/topotests/bgp_aigp/r4/ospfd.conf +++ b/tests/topotests/bgp_aigp/r4/ospfd.conf @@ -1,6 +1,6 @@ ! interface lo - ip ospf cost 10 + ip ospf passive ! interface r4-eth1 ip ospf dead-interval 4 diff --git a/tests/topotests/bgp_aigp/r5/bgpd.conf b/tests/topotests/bgp_aigp/r5/bgpd.conf index 4fde262053ce..3d1f5e85722b 100644 --- a/tests/topotests/bgp_aigp/r5/bgpd.conf +++ b/tests/topotests/bgp_aigp/r5/bgpd.conf @@ -1,6 +1,7 @@ router bgp 65001 no bgp ebgp-requires-policy no bgp network import-check + bgp route-reflector allow-outbound-policy neighbor 192.168.35.3 remote-as internal neighbor 192.168.35.3 timers 1 3 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 update-source lo address-family ipv4 - redistribute connected - redistribute ospf + redistribute connected route-map connected-to-bgp + neighbor 192.168.35.3 route-map set-nexthop out 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 +! diff --git a/tests/topotests/bgp_aigp/r5/ospfd.conf b/tests/topotests/bgp_aigp/r5/ospfd.conf index b853c74102a2..65a213df1721 100644 --- a/tests/topotests/bgp_aigp/r5/ospfd.conf +++ b/tests/topotests/bgp_aigp/r5/ospfd.conf @@ -1,6 +1,6 @@ ! interface lo - ip ospf cost 10 + ip ospf passive ! interface r5-eth1 ip ospf dead-interval 4 diff --git a/tests/topotests/bgp_aigp/r6/bgpd.conf b/tests/topotests/bgp_aigp/r6/bgpd.conf index 2faae7720c90..2d5f7a89baf4 100644 --- a/tests/topotests/bgp_aigp/r6/bgpd.conf +++ b/tests/topotests/bgp_aigp/r6/bgpd.conf @@ -1,6 +1,7 @@ router bgp 65001 no bgp ebgp-requires-policy no bgp network import-check + bgp route-reflector allow-outbound-policy neighbor 10.0.0.4 remote-as internal neighbor 10.0.0.4 timers 1 3 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 connect 1 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 ! +route-map set-nexthop permit 10 + set ip next-hop peer-address +exit +! diff --git a/tests/topotests/bgp_aigp/r6/ospfd.conf b/tests/topotests/bgp_aigp/r6/ospfd.conf index 46b293317866..89cbefa89522 100644 --- a/tests/topotests/bgp_aigp/r6/ospfd.conf +++ b/tests/topotests/bgp_aigp/r6/ospfd.conf @@ -1,6 +1,6 @@ ! interface lo - ip ospf cost 10 + ip ospf passive ! interface r6-eth0 ip ospf dead-interval 4 diff --git a/tests/topotests/bgp_aigp/test_bgp_aigp.py b/tests/topotests/bgp_aigp/test_bgp_aigp.py index 655e9ad18485..108b19c4a5c4 100644 --- a/tests/topotests/bgp_aigp/test_bgp_aigp.py +++ b/tests/topotests/bgp_aigp/test_bgp_aigp.py @@ -12,9 +12,9 @@ r6 receives those routes with aigp-metric TLV. 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 @@ -109,15 +109,29 @@ def _bgp_converge(): expected = { "paths": [ { - "aigpMetric": 111, + "aigpMetric": 81, "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, - "bestpath": {"selectionReason": "Neighbor IP"}, - "nexthops": [{"hostname": "r2", "accessible": True}], + "bestpath": {"selectionReason": "IGP Metric"}, + "nexthops": [ + { + "ip": "10.0.0.2", + "hostname": "r2", + "metric": 10, + "accessible": True, + } + ], }, ] } @@ -141,30 +155,58 @@ def _bgp_check_aigp_metric_bestpath(): "10.0.0.71/32": { "paths": [ { - "aigpMetric": 111, - "bestpath": {"selectionReason": "AIGP"}, + "aigpMetric": 81, "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, - "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": { "paths": [ { - "aigpMetric": 112, - "bestpath": {"selectionReason": "AIGP"}, + "aigpMetric": 82, "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, - "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 _bgp_check_aigp_metric_bestpath(): _, 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" - # r2, 10.0.0.71/32 with aigp-metric 101 (71 + 30) - test_func = functools.partial(_bgp_check_aigp_metric, r2, "10.0.0.71/32", 101) + # 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", 91) _, 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) - test_func = functools.partial(_bgp_check_aigp_metric, r3, "10.0.0.72/32", 92) + # 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", 82) _, 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) _, 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"