mirror of
https://github.com/FRRouting/frr.git
synced 2025-04-30 13:37:17 +02:00
Merge pull request #18677 from chdxD1/fix-rmac-nhlist
zebra: add vtep_ip to rmac nh_list in all cases
This commit is contained in:
commit
f7ae2c17ea
|
@ -180,34 +180,35 @@ def teardown_module(_mod):
|
||||||
tgen.stop_topology()
|
tgen.stop_topology()
|
||||||
|
|
||||||
|
|
||||||
def _test_evpn_ping_router(pingrouter, ipv4_only=False):
|
def _test_evpn_ping_router(pingrouter, ipv4_only=False, ipv6_only=False):
|
||||||
"""
|
"""
|
||||||
internal function to check ping between r1 and r2
|
internal function to check ping between r1 and r2
|
||||||
"""
|
"""
|
||||||
# Check IPv4 and IPv6 connectivity between r1 and r2 ( routing vxlan evpn)
|
# Check IPv4 and IPv6 connectivity between r1 and r2 ( routing vxlan evpn)
|
||||||
logger.info(
|
if not ipv6_only:
|
||||||
"Check Ping IPv4 from R1(r1-vrf-101) to R2(r2-vrf-101 = 192.168.101.41)"
|
logger.info(
|
||||||
)
|
"Check Ping IPv4 from R1(r1-vrf-101) to R2(r2-vrf-101 = 192.168.101.41)"
|
||||||
output = pingrouter.run("ip netns exec r1-vrf-101 ping 192.168.101.41 -f -c 1000")
|
|
||||||
logger.info(output)
|
|
||||||
if "1000 packets transmitted, 1000 received" not in output:
|
|
||||||
assertmsg = (
|
|
||||||
"expected ping IPv4 from R1(r1-vrf-101) to R2(192.168.101.41) should be ok"
|
|
||||||
)
|
)
|
||||||
assert 0, assertmsg
|
output = pingrouter.run(
|
||||||
else:
|
"ip netns exec r1-vrf-101 ping 192.168.101.41 -f -c 1000"
|
||||||
logger.info("Check Ping IPv4 from R1(r1-vrf-101) to R2(192.168.101.41) OK")
|
)
|
||||||
|
logger.info(output)
|
||||||
|
if "1000 packets transmitted, 1000 received" not in output:
|
||||||
|
assertmsg = "expected ping IPv4 from R1(r1-vrf-101) to R2(192.168.101.41) should be ok"
|
||||||
|
assert 0, assertmsg
|
||||||
|
else:
|
||||||
|
logger.info("Check Ping IPv4 from R1(r1-vrf-101) to R2(192.168.101.41) OK")
|
||||||
|
|
||||||
if ipv4_only:
|
if not ipv4_only:
|
||||||
return
|
logger.info("Check Ping IPv6 from R1(r1-vrf-101) to R2(r2-vrf-101 = fd00::2)")
|
||||||
|
output = pingrouter.run("ip netns exec r1-vrf-101 ping fd00::2 -f -c 1000")
|
||||||
logger.info("Check Ping IPv6 from R1(r1-vrf-101) to R2(r2-vrf-101 = fd00::2)")
|
logger.info(output)
|
||||||
output = pingrouter.run("ip netns exec r1-vrf-101 ping fd00::2 -f -c 1000")
|
if "1000 packets transmitted, 1000 received" not in output:
|
||||||
logger.info(output)
|
assert (
|
||||||
if "1000 packets transmitted, 1000 received" not in output:
|
0
|
||||||
assert 0, "expected ping IPv6 from R1(r1-vrf-101) to R2(fd00::2) should be ok"
|
), "expected ping IPv6 from R1(r1-vrf-101) to R2(fd00::2) should be ok"
|
||||||
else:
|
else:
|
||||||
logger.info("Check Ping IPv6 from R1(r1-vrf-101) to R2(fd00::2) OK")
|
logger.info("Check Ping IPv6 from R1(r1-vrf-101) to R2(fd00::2) OK")
|
||||||
|
|
||||||
|
|
||||||
def test_protocols_convergence():
|
def test_protocols_convergence():
|
||||||
|
@ -239,6 +240,16 @@ def test_protocols_convergence():
|
||||||
assert result is None, assertmsg
|
assert result is None, assertmsg
|
||||||
|
|
||||||
|
|
||||||
|
def _print_evpn_nexthop_rmac(router):
|
||||||
|
tgen = get_topogen()
|
||||||
|
output = tgen.gears[router].vtysh_cmd("show evpn next-hops vni all", isjson=False)
|
||||||
|
logger.info("==== result from {} show evpn next-hops vni all".format(router))
|
||||||
|
logger.info(output)
|
||||||
|
output = tgen.gears[router].vtysh_cmd("show evpn rmac vni all", isjson=False)
|
||||||
|
logger.info("==== result from {}: show evpn rmac vni all".format(router))
|
||||||
|
logger.info(output)
|
||||||
|
|
||||||
|
|
||||||
def test_protocols_dump_info():
|
def test_protocols_dump_info():
|
||||||
"""
|
"""
|
||||||
Dump EVPN information
|
Dump EVPN information
|
||||||
|
@ -273,12 +284,7 @@ def test_protocols_dump_info():
|
||||||
output = tgen.gears["r1"].vtysh_cmd("show evpn vni detail", isjson=False)
|
output = tgen.gears["r1"].vtysh_cmd("show evpn vni detail", isjson=False)
|
||||||
logger.info("==== result from show evpn vni detail")
|
logger.info("==== result from show evpn vni detail")
|
||||||
logger.info(output)
|
logger.info(output)
|
||||||
output = tgen.gears["r1"].vtysh_cmd("show evpn next-hops vni all", isjson=False)
|
_print_evpn_nexthop_rmac("r1")
|
||||||
logger.info("==== result from show evpn next-hops vni all")
|
|
||||||
logger.info(output)
|
|
||||||
output = tgen.gears["r1"].vtysh_cmd("show evpn rmac vni all", isjson=False)
|
|
||||||
logger.info("==== result from show evpn rmac vni all")
|
|
||||||
logger.info(output)
|
|
||||||
|
|
||||||
|
|
||||||
def test_bgp_vrf_routes():
|
def test_bgp_vrf_routes():
|
||||||
|
@ -373,7 +379,7 @@ def _test_router_check_evpn_next_hop(expected_paths=1):
|
||||||
assert result is None, "evpn ipv6 next-hops check failed"
|
assert result is None, "evpn ipv6 next-hops check failed"
|
||||||
|
|
||||||
|
|
||||||
def _test_router_check_evpn_contexts(router, ipv4_only=False):
|
def _test_router_check_evpn_contexts(router, ipv4_only=False, ipv6_only=False):
|
||||||
"""
|
"""
|
||||||
Check EVPN nexthops and RMAC number are correctly configured
|
Check EVPN nexthops and RMAC number are correctly configured
|
||||||
"""
|
"""
|
||||||
|
@ -386,6 +392,15 @@ def _test_router_check_evpn_contexts(router, ipv4_only=False):
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
elif ipv6_only:
|
||||||
|
expected = {
|
||||||
|
"101": {
|
||||||
|
"numNextHops": 1,
|
||||||
|
"::ffff:192.168.100.41": {
|
||||||
|
"nexthopIp": "::ffff:192.168.100.41",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
else:
|
else:
|
||||||
expected = {
|
expected = {
|
||||||
"101": {
|
"101": {
|
||||||
|
@ -465,6 +480,26 @@ def test_evpn_disable_routemap():
|
||||||
assert result is None, assertmsg
|
assert result is None, assertmsg
|
||||||
|
|
||||||
|
|
||||||
|
def _check_evpn_routes(router, family, vrf, routes, expected=True):
|
||||||
|
tgen = get_topogen()
|
||||||
|
rib_routes = {
|
||||||
|
"r1": {
|
||||||
|
"static_routes": [
|
||||||
|
{
|
||||||
|
"vrf": vrf,
|
||||||
|
"network": routes,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = verify_bgp_rib(tgen, family, router, rib_routes, expected=expected)
|
||||||
|
|
||||||
|
if expected:
|
||||||
|
assert result is True, "expect routes {} present".format(routes)
|
||||||
|
else:
|
||||||
|
assert result is not True, "expect routes {} not present".format(routes)
|
||||||
|
|
||||||
|
|
||||||
def test_evpn_remove_ip():
|
def test_evpn_remove_ip():
|
||||||
"""
|
"""
|
||||||
Check the removal of an EVPN route is correctly handled
|
Check the removal of an EVPN route is correctly handled
|
||||||
|
@ -489,25 +524,8 @@ def test_evpn_remove_ip():
|
||||||
assert result is True, "Failed to remove IPv6 network on R2, Error: {} ".format(
|
assert result is True, "Failed to remove IPv6 network on R2, Error: {} ".format(
|
||||||
result
|
result
|
||||||
)
|
)
|
||||||
ipv6_routes = {
|
_check_evpn_routes("r1", "ipv6", "r1-vrf-101", ["fd00::2/128"], expected=False)
|
||||||
"r1": {
|
_print_evpn_nexthop_rmac("r1")
|
||||||
"static_routes": [
|
|
||||||
{
|
|
||||||
"vrf": "r1-vrf-101",
|
|
||||||
"network": ["fd00::2/128"],
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result = verify_bgp_rib(tgen, "ipv6", "r1", ipv6_routes, expected=False)
|
|
||||||
assert result is not True, "expect IPv6 route fd00::2/128 withdrawn"
|
|
||||||
|
|
||||||
output = tgen.gears["r1"].vtysh_cmd("show evpn next-hops vni all", isjson=False)
|
|
||||||
logger.info("==== result from show evpn next-hops vni all")
|
|
||||||
logger.info(output)
|
|
||||||
output = tgen.gears["r1"].vtysh_cmd("show evpn rmac vni all", isjson=False)
|
|
||||||
logger.info("==== result from show evpn next-hops vni all")
|
|
||||||
logger.info(output)
|
|
||||||
|
|
||||||
|
|
||||||
def test_router_check_evpn_contexts_again():
|
def test_router_check_evpn_contexts_again():
|
||||||
|
@ -533,6 +551,75 @@ def test_evpn_ping_again():
|
||||||
_test_evpn_ping_router(tgen.gears["r1"], ipv4_only=True)
|
_test_evpn_ping_router(tgen.gears["r1"], ipv4_only=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_evpn_other_address_family():
|
||||||
|
"""
|
||||||
|
Check the removal of an EVPN route is correctly handled
|
||||||
|
"""
|
||||||
|
tgen = get_topogen()
|
||||||
|
if tgen.routers_have_failure():
|
||||||
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
|
config_add_ipv6 = {
|
||||||
|
"r2": {
|
||||||
|
"raw_config": [
|
||||||
|
"router bgp 65000 vrf r2-vrf-101",
|
||||||
|
"address-family ipv6 unicast",
|
||||||
|
"network fd00::3/128",
|
||||||
|
"network fd00::2/128",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("==== Add IPv6 again network on R2")
|
||||||
|
result = apply_raw_config(tgen, config_add_ipv6)
|
||||||
|
assert result is True, "Failed to add IPv6 network on R2, Error: {} ".format(result)
|
||||||
|
_check_evpn_routes("r1", "ipv6", "r1-vrf-101", ["fd00::2/128"], expected=True)
|
||||||
|
|
||||||
|
config_no_ipv4 = {
|
||||||
|
"r2": {
|
||||||
|
"raw_config": [
|
||||||
|
"router bgp 65000 vrf r2-vrf-101",
|
||||||
|
"address-family ipv4 unicast",
|
||||||
|
"no network 192.168.101.41/32",
|
||||||
|
"no network 192.168.102.41/32",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("==== Remove IPv4 network on R2")
|
||||||
|
result = apply_raw_config(tgen, config_no_ipv4)
|
||||||
|
assert result is True, "Failed to remove IPv4 network on R2, Error: {} ".format(
|
||||||
|
result
|
||||||
|
)
|
||||||
|
|
||||||
|
_check_evpn_routes(
|
||||||
|
"r1", "ipv4", "r1-vrf-101", ["192.168.101.41/32"], expected=False
|
||||||
|
)
|
||||||
|
_print_evpn_nexthop_rmac("r1")
|
||||||
|
|
||||||
|
|
||||||
|
def test_router_check_evpn_contexts_again_other_address_family():
|
||||||
|
"""
|
||||||
|
Check EVPN nexthops and RMAC number are correctly configured
|
||||||
|
"""
|
||||||
|
tgen = get_topogen()
|
||||||
|
if tgen.routers_have_failure():
|
||||||
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
|
_test_router_check_evpn_contexts(tgen.gears["r1"], ipv6_only=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_evpn_ping_again_other_address_family():
|
||||||
|
"""
|
||||||
|
Check ping between R1 and R2 is ok
|
||||||
|
"""
|
||||||
|
tgen = get_topogen()
|
||||||
|
if tgen.routers_have_failure():
|
||||||
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
|
_test_evpn_ping_router(tgen.gears["r1"], ipv6_only=True)
|
||||||
|
|
||||||
|
|
||||||
def _get_established_epoch(router, peer):
|
def _get_established_epoch(router, peer):
|
||||||
"""
|
"""
|
||||||
Get the established epoch for a peer
|
Get the established epoch for a peer
|
||||||
|
|
|
@ -1390,23 +1390,22 @@ static int zl3vni_remote_rmac_add(struct zebra_l3vni *zl3vni,
|
||||||
|
|
||||||
/* install rmac in kernel */
|
/* install rmac in kernel */
|
||||||
zl3vni_rmac_install(zl3vni, zrmac);
|
zl3vni_rmac_install(zl3vni, zrmac);
|
||||||
} else if (!IPV4_ADDR_SAME(&zrmac->fwd_info.r_vtep_ip,
|
} else {
|
||||||
&(ipv4_vtep.ipaddr_v4))) {
|
if (!IPV4_ADDR_SAME(&zrmac->fwd_info.r_vtep_ip, &(ipv4_vtep.ipaddr_v4))) {
|
||||||
if (IS_ZEBRA_DEBUG_VXLAN)
|
if (IS_ZEBRA_DEBUG_VXLAN)
|
||||||
zlog_debug(
|
zlog_debug("L3VNI %u Remote VTEP change(%pI4 -> %pIA) for RMAC %pEA",
|
||||||
"L3VNI %u Remote VTEP change(%pI4 -> %pIA) for RMAC %pEA",
|
zl3vni->vni, &zrmac->fwd_info.r_vtep_ip, vtep_ip, rmac);
|
||||||
zl3vni->vni, &zrmac->fwd_info.r_vtep_ip,
|
|
||||||
vtep_ip, rmac);
|
|
||||||
|
|
||||||
zrmac->fwd_info.r_vtep_ip = ipv4_vtep.ipaddr_v4;
|
zrmac->fwd_info.r_vtep_ip = ipv4_vtep.ipaddr_v4;
|
||||||
|
|
||||||
|
/* install rmac in kernel */
|
||||||
|
zl3vni_rmac_install(zl3vni, zrmac);
|
||||||
|
}
|
||||||
|
|
||||||
vtep = XCALLOC(MTYPE_EVPN_VTEP, sizeof(struct ipaddr));
|
vtep = XCALLOC(MTYPE_EVPN_VTEP, sizeof(struct ipaddr));
|
||||||
memcpy(vtep, vtep_ip, sizeof(struct ipaddr));
|
memcpy(vtep, vtep_ip, sizeof(struct ipaddr));
|
||||||
if (!listnode_add_sort_nodup(zrmac->nh_list, (void *)vtep))
|
if (!listnode_add_sort_nodup(zrmac->nh_list, (void *)vtep))
|
||||||
XFREE(MTYPE_EVPN_VTEP, vtep);
|
XFREE(MTYPE_EVPN_VTEP, vtep);
|
||||||
|
|
||||||
/* install rmac in kernel */
|
|
||||||
zl3vni_rmac_install(zl3vni, zrmac);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in a new issue