Merge pull request #15255 from louis-6wind/bgp-leak-interface

bgpd: fix interface of routes leaked from another VRF
This commit is contained in:
Donald Sharp 2024-02-08 11:18:58 -05:00 committed by GitHub
commit afa07a7f3a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 354 additions and 16 deletions

View File

@ -2209,12 +2209,22 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
/* If the path has accept-own community and the source VRF
* is valid, reset next-hop to self, to allow importing own
* routes between different VRFs on the same node.
* Set the nh ifindex to VRF's interface, not the real interface.
*/
if (src_bgp)
subgroup_announce_reset_nhop(nhfamily, &static_attr);
bpi_ultimate = bgp_get_imported_bpi_ultimate(path_vpn);
/* The nh ifindex may not be defined (when the route is
* imported from the network statement => BGP_ROUTE_STATIC)
* or to the real interface.
* Rewrite the nh ifindex to VRF's interface.
* Let the kernel to decide with double lookup the real next-hop
* interface when installing the route.
*/
if (src_bgp) {
subgroup_announce_reset_nhop(nhfamily, &static_attr);
if (src_bgp || bpi_ultimate->sub_type == BGP_ROUTE_STATIC ||
bpi_ultimate->sub_type == BGP_ROUTE_REDISTRIBUTE) {
ifp = if_get_vrf_loopback(src_vrf->vrf_id);
if (ifp)
static_attr.nh_ifindex = ifp->ifindex;
@ -2300,9 +2310,6 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
*/
if (!CHECK_FLAG(to_bgp->af_flags[afi][safi],
BGP_CONFIG_VRF_TO_VRF_IMPORT)) {
/* work back to original route */
bpi_ultimate = bgp_get_imported_bpi_ultimate(path_vpn);
/*
* if original route was unicast,
* then it did not arrive over vpn

View File

@ -12,7 +12,7 @@
{
"fib": true,
"directlyConnected": true,
"interfaceName": "eth0",
"interfaceName": "vrf10",
"vrf": "vrf10",
"active": true
}

View File

@ -1,10 +1,19 @@
hostname r1
router bgp 99
no bgp ebgp-requires-policy
address-family ipv4 unicast
redistribute connected
import vrf DONNA
!
!
router bgp 99 vrf DONNA
no bgp ebgp-requires-policy
address-family ipv4 unicast
redistribute connected
import vrf EVA
import vrf NOTEXISTING
import vrf default
!
!
router bgp 99 vrf EVA
@ -12,5 +21,13 @@ router bgp 99 vrf EVA
address-family ipv4 unicast
redistribute connected
import vrf DONNA
import vrf NOTEXISTING
!
!
router bgp 99 vrf NOTEXISTING
no bgp ebgp-requires-policy
no bgp network import-check
address-family ipv4 unicast
network 172.16.101.0/24
!
!

View File

@ -1,5 +1,9 @@
hostname r1
int dummy0
ip address 10.0.4.1/24
no shut
!
int dummy1
ip address 10.0.0.1/24
no shut
@ -16,3 +20,9 @@ int dummy4
ip address 10.0.3.1/24
no shut
!
int EVA
no shut
!
int DONNA
no shut
!

View File

@ -3,6 +3,7 @@
ip link add DONNA type vrf table 1001
ip link add EVA type vrf table 1002
ip link add dummy0 type dummy # vrf default
ip link add dummy1 type dummy
ip link add dummy2 type dummy
ip link add dummy3 type dummy

View File

@ -64,7 +64,7 @@ def teardown_module(mod):
tgen.stop_topology()
def test_vrf_route_leak():
def test_vrf_route_leak_donna():
logger.info("Ensure that routes are leaked back and forth")
tgen = get_topogen()
# Don't run this test if we have any failure.
@ -81,11 +81,59 @@ def test_vrf_route_leak():
}
],
"10.0.1.0/24": [
{"protocol": "bgp", "selected": True, "nexthops": [{"fib": True}]}
{
"protocol": "bgp",
"selected": True,
"nexthops": [
{
"fib": True,
"interfaceName": "EVA",
"vrf": "EVA",
"active": True,
},
],
},
],
"10.0.2.0/24": [{"protocol": "connected"}],
"10.0.3.0/24": [
{"protocol": "bgp", "selected": True, "nexthops": [{"fib": True}]}
{
"protocol": "bgp",
"selected": True,
"nexthops": [
{
"fib": True,
"interfaceName": "EVA",
"vrf": "EVA",
"active": True,
},
],
},
],
"10.0.4.0/24": [
{
"protocol": "bgp",
"selected": True,
"nexthops": [
{
"fib": True,
"interfaceName": "lo",
"vrf": "default",
"active": True,
},
],
},
],
"172.16.101.0/24": [
{
"protocol": "bgp",
"nexthops": [
{
"interfaceIndex": 0,
"interfaceName": "unknown",
"vrf": "Unknown",
},
],
},
],
}
@ -95,10 +143,31 @@ def test_vrf_route_leak():
result, diff = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
assert result, "BGP VRF DONNA check failed:\n{}".format(diff)
def test_vrf_route_leak_eva():
logger.info("Ensure that routes are leaked back and forth")
tgen = get_topogen()
# Don't run this test if we have any failure.
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
r1 = tgen.gears["r1"]
# Test EVA VRF.
expect = {
"10.0.0.0/24": [
{"protocol": "bgp", "selected": True, "nexthops": [{"fib": True}]}
{
"protocol": "bgp",
"selected": True,
"nexthops": [
{
"fib": True,
"interfaceName": "DONNA",
"vrf": "DONNA",
"active": True,
},
],
},
],
"10.0.1.0/24": [
{
@ -106,13 +175,36 @@ def test_vrf_route_leak():
}
],
"10.0.2.0/24": [
{"protocol": "bgp", "selected": True, "nexthops": [{"fib": True}]}
{
"protocol": "bgp",
"selected": True,
"nexthops": [
{
"fib": True,
"interfaceName": "DONNA",
"vrf": "DONNA",
"active": True,
},
],
},
],
"10.0.3.0/24": [
{
"protocol": "connected",
}
],
"172.16.101.0/24": [
{
"protocol": "bgp",
"nexthops": [
{
"interfaceIndex": 0,
"interfaceName": "unknown",
"vrf": "Unknown",
},
],
},
],
}
test_func = partial(
@ -122,6 +214,217 @@ def test_vrf_route_leak():
assert result, "BGP VRF EVA check failed:\n{}".format(diff)
def test_vrf_route_leak_donna():
logger.info("Ensure that routes are leaked back and forth")
tgen = get_topogen()
# Don't run this test if we have any failure.
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
r1 = tgen.gears["r1"]
# Test DONNA VRF.
expect = {
"10.0.0.0/24": [
{
"protocol": "connected",
}
],
"10.0.1.0/24": [
{
"protocol": "bgp",
"selected": True,
"nexthops": [
{
"fib": True,
"interfaceName": "EVA",
"vrf": "EVA",
"active": True,
},
],
},
],
"10.0.2.0/24": [{"protocol": "connected"}],
"10.0.3.0/24": [
{
"protocol": "bgp",
"selected": True,
"nexthops": [
{
"fib": True,
"interfaceName": "EVA",
"vrf": "EVA",
"active": True,
},
],
},
],
"10.0.4.0/24": [
{
"protocol": "bgp",
"selected": True,
"nexthops": [
{
"fib": True,
"interfaceName": "lo",
"vrf": "default",
"active": True,
},
],
},
],
"172.16.101.0/24": [
{
"protocol": "bgp",
"nexthops": [
{
"interfaceIndex": 0,
"interfaceName": "unknown",
"vrf": "Unknown",
},
],
},
],
}
test_func = partial(
topotest.router_json_cmp, r1, "show ip route vrf DONNA json", expect
)
result, diff = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
assert result, "BGP VRF DONNA check failed:\n{}".format(diff)
def test_vrf_route_leak_eva():
logger.info("Ensure that routes are leaked back and forth")
tgen = get_topogen()
# Don't run this test if we have any failure.
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
r1 = tgen.gears["r1"]
# Test EVA VRF.
expect = {
"10.0.0.0/24": [
{
"protocol": "bgp",
"selected": True,
"nexthops": [
{
"fib": True,
"interfaceName": "DONNA",
"vrf": "DONNA",
"active": True,
},
],
},
],
"10.0.1.0/24": [
{
"protocol": "connected",
}
],
"10.0.2.0/24": [
{
"protocol": "bgp",
"selected": True,
"nexthops": [
{
"fib": True,
"interfaceName": "DONNA",
"vrf": "DONNA",
"active": True,
},
],
},
],
"10.0.3.0/24": [
{
"protocol": "connected",
}
],
"172.16.101.0/24": [
{
"protocol": "bgp",
"nexthops": [
{
"interfaceIndex": 0,
"interfaceName": "unknown",
"vrf": "Unknown",
},
],
},
],
}
def test_vrf_route_leak_default():
logger.info("Ensure that routes are leaked back and forth")
tgen = get_topogen()
# Don't run this test if we have any failure.
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
r1 = tgen.gears["r1"]
# Test default VRF.
expect = {
"10.0.0.0/24": [
{
"protocol": "bgp",
"selected": True,
"nexthops": [
{
"fib": True,
"interfaceName": "DONNA",
"vrf": "DONNA",
"active": True,
},
],
},
],
"10.0.2.0/24": [
{
"protocol": "bgp",
"selected": True,
"nexthops": [
{
"fib": True,
"interfaceName": "DONNA",
"vrf": "DONNA",
"active": True,
},
],
},
],
"10.0.4.0/24": [
{
"protocol": "connected",
}
],
}
test_func = partial(topotest.router_json_cmp, r1, "show ip route json", expect)
result, diff = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
assert result, "BGP VRF default check failed:\n{}".format(diff)
def test_ping():
"Simple ping tests"
tgen = get_topogen()
# Don't run this test if we have any failure.
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
r1 = tgen.gears["r1"]
logger.info("Ping from default to DONNA")
output = r1.run("ping -c 4 -w 4 -I 10.0.4.1 10.0.0.1")
assert " 0% packet loss" in output, "Ping default->DONNA FAILED"
def test_memory_leak():
"Run the memory leak test and report results."
tgen = get_topogen()

View File

@ -7,5 +7,5 @@ O>* 10.0.4.0/24 [110/20] via 10.0.20.2, r1-eth1, weight 1, XX:XX:XX
O 10.0.20.0/24 [110/10] is directly connected, r1-eth1, weight 1, XX:XX:XX
C>* 10.0.20.0/24 is directly connected, r1-eth1, XX:XX:XX
L>* 10.0.20.1/32 is directly connected, r1-eth1, XX:XX:XX
B>* 10.0.30.0/24 [20/0] is directly connected, r1-eth2 (vrf neno), weight 1, XX:XX:XX
B>* 10.0.30.0/24 [20/0] is directly connected, neno (vrf neno), weight 1, XX:XX:XX
O>* 10.0.40.0/24 [110/20] via 10.0.20.2, r1-eth1, weight 1, XX:XX:XX

View File

@ -9,4 +9,4 @@ O 10.0.20.0/24 [110/10] is directly connected, r2-eth1, weight 1, XX:XX:XX
C>* 10.0.20.0/24 is directly connected, r2-eth1, XX:XX:XX
L>* 10.0.20.2/32 is directly connected, r2-eth1, XX:XX:XX
O>* 10.0.30.0/24 [110/20] via 10.0.20.1, r2-eth1, weight 1, XX:XX:XX
B>* 10.0.40.0/24 [20/0] is directly connected, r2-eth2 (vrf ray), weight 1, XX:XX:XX
B>* 10.0.40.0/24 [20/0] is directly connected, ray (vrf ray), weight 1, XX:XX:XX

View File

@ -1,9 +1,9 @@
VRF ray:
B 10.0.1.0/24 [20/20] via 10.0.20.1, r2-eth1 (vrf default) inactive, weight 1, XX:XX:XX
B 10.0.2.0/24 [20/0] is directly connected, r2-eth0 (vrf default) inactive, weight 1, XX:XX:XX
B 10.0.2.0/24 [20/0] is directly connected, lo (vrf default) inactive, weight 1, XX:XX:XX
B>* 10.0.3.0/24 [20/20] via 10.0.20.1, r2-eth1 (vrf default), weight 1, XX:XX:XX
O>* 10.0.4.0/24 [110/20] via 10.0.40.4, r2-eth2, weight 1, XX:XX:XX
B 10.0.20.0/24 [20/0] is directly connected, r2-eth1 (vrf default) inactive, weight 1, XX:XX:XX
B 10.0.20.0/24 [20/0] is directly connected, lo (vrf default) inactive, weight 1, XX:XX:XX
B>* 10.0.30.0/24 [20/20] via 10.0.20.1, r2-eth1 (vrf default), weight 1, XX:XX:XX
O 10.0.40.0/24 [110/10] is directly connected, r2-eth2, weight 1, XX:XX:XX
C>* 10.0.40.0/24 is directly connected, r2-eth2, XX:XX:XX