mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-05-26 00:10:24 +00:00
Merge pull request #15351 from louis-6wind/fix-leak-vrf-interface
bgpd: update route leak after vrf interface changes
This commit is contained in:
commit
ab40199f00
@ -2347,6 +2347,12 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
|
|||||||
return BGP_ATTR_PARSE_WITHDRAW;
|
return BGP_ATTR_PARSE_WITHDRAW;
|
||||||
}
|
}
|
||||||
attr->nh_ifindex = peer->nexthop.ifp->ifindex;
|
attr->nh_ifindex = peer->nexthop.ifp->ifindex;
|
||||||
|
if (if_is_operative(peer->nexthop.ifp))
|
||||||
|
SET_FLAG(attr->nh_flags,
|
||||||
|
BGP_ATTR_NH_IF_OPERSTATE);
|
||||||
|
else
|
||||||
|
UNSET_FLAG(attr->nh_flags,
|
||||||
|
BGP_ATTR_NH_IF_OPERSTATE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
|
case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
|
||||||
@ -2364,6 +2370,12 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
|
|||||||
return BGP_ATTR_PARSE_WITHDRAW;
|
return BGP_ATTR_PARSE_WITHDRAW;
|
||||||
}
|
}
|
||||||
attr->nh_ifindex = peer->nexthop.ifp->ifindex;
|
attr->nh_ifindex = peer->nexthop.ifp->ifindex;
|
||||||
|
if (if_is_operative(peer->nexthop.ifp))
|
||||||
|
SET_FLAG(attr->nh_flags,
|
||||||
|
BGP_ATTR_NH_IF_OPERSTATE);
|
||||||
|
else
|
||||||
|
UNSET_FLAG(attr->nh_flags,
|
||||||
|
BGP_ATTR_NH_IF_OPERSTATE);
|
||||||
}
|
}
|
||||||
if (attr->mp_nexthop_len
|
if (attr->mp_nexthop_len
|
||||||
== BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) {
|
== BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) {
|
||||||
|
@ -158,6 +158,7 @@ struct attr {
|
|||||||
uint8_t nh_flags;
|
uint8_t nh_flags;
|
||||||
|
|
||||||
#define BGP_ATTR_NH_VALID 0x01
|
#define BGP_ATTR_NH_VALID 0x01
|
||||||
|
#define BGP_ATTR_NH_IF_OPERSTATE 0x02
|
||||||
|
|
||||||
/* Path origin attribute */
|
/* Path origin attribute */
|
||||||
uint8_t origin;
|
uint8_t origin;
|
||||||
|
@ -2093,8 +2093,9 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
|
|||||||
struct bgp_path_info *bpi;
|
struct bgp_path_info *bpi;
|
||||||
int origin_local = 0;
|
int origin_local = 0;
|
||||||
struct bgp *src_vrf;
|
struct bgp *src_vrf;
|
||||||
struct interface *ifp;
|
struct interface *ifp = NULL;
|
||||||
char rd_buf[RD_ADDRSTRLEN];
|
char rd_buf[RD_ADDRSTRLEN];
|
||||||
|
|
||||||
int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF);
|
int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF);
|
||||||
|
|
||||||
if (!vpn_leak_from_vpn_active(to_bgp, afi, &debugmsg)) {
|
if (!vpn_leak_from_vpn_active(to_bgp, afi, &debugmsg)) {
|
||||||
@ -2260,6 +2261,15 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!ifp && static_attr.nh_ifindex)
|
||||||
|
ifp = if_lookup_by_index(static_attr.nh_ifindex,
|
||||||
|
src_vrf->vrf_id);
|
||||||
|
|
||||||
|
if (ifp && if_is_operative(ifp))
|
||||||
|
SET_FLAG(static_attr.nh_flags, BGP_ATTR_NH_IF_OPERSTATE);
|
||||||
|
else
|
||||||
|
UNSET_FLAG(static_attr.nh_flags, BGP_ATTR_NH_IF_OPERSTATE);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* route map handling
|
* route map handling
|
||||||
*/
|
*/
|
||||||
|
@ -8569,6 +8569,7 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
|
|||||||
afi_t afi;
|
afi_t afi;
|
||||||
route_map_result_t ret;
|
route_map_result_t ret;
|
||||||
struct bgp_redist *red;
|
struct bgp_redist *red;
|
||||||
|
struct interface *ifp;
|
||||||
|
|
||||||
if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS) ||
|
if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS) ||
|
||||||
bgp->peer_self == NULL)
|
bgp->peer_self == NULL)
|
||||||
@ -8628,6 +8629,11 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
|
|||||||
}
|
}
|
||||||
attr.nh_type = nhtype;
|
attr.nh_type = nhtype;
|
||||||
attr.nh_ifindex = ifindex;
|
attr.nh_ifindex = ifindex;
|
||||||
|
ifp = if_lookup_by_index(ifindex, bgp->vrf_id);
|
||||||
|
if (ifp && if_is_operative(ifp))
|
||||||
|
SET_FLAG(attr.nh_flags, BGP_ATTR_NH_IF_OPERSTATE);
|
||||||
|
else
|
||||||
|
UNSET_FLAG(attr.nh_flags, BGP_ATTR_NH_IF_OPERSTATE);
|
||||||
|
|
||||||
attr.med = metric;
|
attr.med = metric;
|
||||||
attr.distance = distance;
|
attr.distance = distance;
|
||||||
|
@ -235,6 +235,14 @@ static int bgp_ifp_up(struct interface *ifp)
|
|||||||
hook_call(bgp_vrf_status_changed, bgp, ifp);
|
hook_call(bgp_vrf_status_changed, bgp, ifp);
|
||||||
bgp_nht_ifp_up(ifp);
|
bgp_nht_ifp_up(ifp);
|
||||||
|
|
||||||
|
if (bgp_get_default() && if_is_loopback(ifp)) {
|
||||||
|
vpn_leak_zebra_vrf_label_update(bgp, AFI_IP);
|
||||||
|
vpn_leak_zebra_vrf_label_update(bgp, AFI_IP6);
|
||||||
|
vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP);
|
||||||
|
vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP6);
|
||||||
|
vpn_leak_postchange_all();
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,6 +290,14 @@ static int bgp_ifp_down(struct interface *ifp)
|
|||||||
hook_call(bgp_vrf_status_changed, bgp, ifp);
|
hook_call(bgp_vrf_status_changed, bgp, ifp);
|
||||||
bgp_nht_ifp_down(ifp);
|
bgp_nht_ifp_down(ifp);
|
||||||
|
|
||||||
|
if (bgp_get_default() && if_is_loopback(ifp)) {
|
||||||
|
vpn_leak_zebra_vrf_label_withdraw(bgp, AFI_IP);
|
||||||
|
vpn_leak_zebra_vrf_label_withdraw(bgp, AFI_IP6);
|
||||||
|
vpn_leak_zebra_vrf_sid_withdraw(bgp, AFI_IP);
|
||||||
|
vpn_leak_zebra_vrf_sid_withdraw(bgp, AFI_IP6);
|
||||||
|
vpn_leak_postchange_all();
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3144,6 +3160,15 @@ static int bgp_ifp_create(struct interface *ifp)
|
|||||||
|
|
||||||
bgp_update_interface_nbrs(bgp, ifp, ifp);
|
bgp_update_interface_nbrs(bgp, ifp, ifp);
|
||||||
hook_call(bgp_vrf_status_changed, bgp, ifp);
|
hook_call(bgp_vrf_status_changed, bgp, ifp);
|
||||||
|
|
||||||
|
if (bgp_get_default() && if_is_loopback(ifp)) {
|
||||||
|
vpn_leak_zebra_vrf_label_update(bgp, AFI_IP);
|
||||||
|
vpn_leak_zebra_vrf_label_update(bgp, AFI_IP6);
|
||||||
|
vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP);
|
||||||
|
vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP6);
|
||||||
|
vpn_leak_postchange_all();
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ router bgp 99 vrf DONNA
|
|||||||
address-family ipv4 unicast
|
address-family ipv4 unicast
|
||||||
redistribute connected
|
redistribute connected
|
||||||
import vrf EVA
|
import vrf EVA
|
||||||
import vrf NOTEXISTING
|
import vrf ZITA
|
||||||
import vrf default
|
import vrf default
|
||||||
!
|
!
|
||||||
!
|
!
|
||||||
@ -21,10 +21,10 @@ router bgp 99 vrf EVA
|
|||||||
address-family ipv4 unicast
|
address-family ipv4 unicast
|
||||||
redistribute connected
|
redistribute connected
|
||||||
import vrf DONNA
|
import vrf DONNA
|
||||||
import vrf NOTEXISTING
|
import vrf ZITA
|
||||||
!
|
!
|
||||||
!
|
!
|
||||||
router bgp 99 vrf NOTEXISTING
|
router bgp 99 vrf ZITA
|
||||||
no bgp ebgp-requires-policy
|
no bgp ebgp-requires-policy
|
||||||
no bgp network import-check
|
no bgp network import-check
|
||||||
address-family ipv4 unicast
|
address-family ipv4 unicast
|
||||||
|
@ -24,7 +24,7 @@ sys.path.append(os.path.join(CWD, "../"))
|
|||||||
from lib import topotest
|
from lib import topotest
|
||||||
from lib.topogen import Topogen, TopoRouter, get_topogen
|
from lib.topogen import Topogen, TopoRouter, get_topogen
|
||||||
from lib.topolog import logger
|
from lib.topolog import logger
|
||||||
|
from lib.checkping import check_ping
|
||||||
|
|
||||||
pytestmark = [pytest.mark.bgpd]
|
pytestmark = [pytest.mark.bgpd]
|
||||||
|
|
||||||
@ -126,11 +126,13 @@ def test_vrf_route_leak_donna():
|
|||||||
"172.16.101.0/24": [
|
"172.16.101.0/24": [
|
||||||
{
|
{
|
||||||
"protocol": "bgp",
|
"protocol": "bgp",
|
||||||
|
"selected": None,
|
||||||
"nexthops": [
|
"nexthops": [
|
||||||
{
|
{
|
||||||
"interfaceIndex": 0,
|
"fib": None,
|
||||||
"interfaceName": "unknown",
|
"interfaceName": "unknown",
|
||||||
"vrf": "Unknown",
|
"vrf": "Unknown",
|
||||||
|
"active": None,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -196,11 +198,13 @@ def test_vrf_route_leak_eva():
|
|||||||
"172.16.101.0/24": [
|
"172.16.101.0/24": [
|
||||||
{
|
{
|
||||||
"protocol": "bgp",
|
"protocol": "bgp",
|
||||||
|
"selected": None,
|
||||||
"nexthops": [
|
"nexthops": [
|
||||||
{
|
{
|
||||||
"interfaceIndex": 0,
|
"fib": None,
|
||||||
"interfaceName": "unknown",
|
"interfaceName": "unknown",
|
||||||
"vrf": "Unknown",
|
"vrf": "Unknown",
|
||||||
|
"active": None,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -214,150 +218,6 @@ def test_vrf_route_leak_eva():
|
|||||||
assert result, "BGP VRF EVA check failed:\n{}".format(diff)
|
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():
|
def test_vrf_route_leak_default():
|
||||||
logger.info("Ensure that routes are leaked back and forth")
|
logger.info("Ensure that routes are leaked back and forth")
|
||||||
tgen = get_topogen()
|
tgen = get_topogen()
|
||||||
@ -421,8 +281,215 @@ def test_ping():
|
|||||||
r1 = tgen.gears["r1"]
|
r1 = tgen.gears["r1"]
|
||||||
|
|
||||||
logger.info("Ping from default to DONNA")
|
logger.info("Ping from default to DONNA")
|
||||||
output = r1.run("ping -c 4 -w 4 -I 10.0.4.1 10.0.0.1")
|
check_ping("r1", "10.0.0.1", True, 10, 0.5, source_addr="10.0.4.1")
|
||||||
assert " 0% packet loss" in output, "Ping default->DONNA FAILED"
|
|
||||||
|
|
||||||
|
def test_vrf_route_leak_donna_after_eva_down():
|
||||||
|
logger.info("Ensure that route states change after EVA interface goes down")
|
||||||
|
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"]
|
||||||
|
r1.vtysh_cmd(
|
||||||
|
"""
|
||||||
|
configure
|
||||||
|
interface EVA
|
||||||
|
shutdown
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
# Test DONNA VRF.
|
||||||
|
expect = {
|
||||||
|
"10.0.1.0/24": [
|
||||||
|
{
|
||||||
|
"protocol": "bgp",
|
||||||
|
"selected": None,
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"fib": None,
|
||||||
|
"interfaceName": "EVA",
|
||||||
|
"vrf": "EVA",
|
||||||
|
"active": None,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"10.0.3.0/24": [
|
||||||
|
{
|
||||||
|
"protocol": "bgp",
|
||||||
|
"selected": None,
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"fib": None,
|
||||||
|
"interfaceName": "EVA",
|
||||||
|
"vrf": "EVA",
|
||||||
|
"active": None,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
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_donna_after_eva_up():
|
||||||
|
logger.info("Ensure that route states change after EVA interface goes up")
|
||||||
|
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"]
|
||||||
|
r1.vtysh_cmd(
|
||||||
|
"""
|
||||||
|
configure
|
||||||
|
interface EVA
|
||||||
|
no shutdown
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
# Test DONNA VRF.
|
||||||
|
expect = {
|
||||||
|
"10.0.1.0/24": [
|
||||||
|
{
|
||||||
|
"protocol": "bgp",
|
||||||
|
"selected": True,
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"fib": True,
|
||||||
|
"interfaceName": "EVA",
|
||||||
|
"vrf": "EVA",
|
||||||
|
"active": True,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"10.0.3.0/24": [
|
||||||
|
{
|
||||||
|
"protocol": "bgp",
|
||||||
|
"selected": True,
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"fib": True,
|
||||||
|
"interfaceName": "EVA",
|
||||||
|
"vrf": "EVA",
|
||||||
|
"active": True,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
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_donna_add_vrf_zita():
|
||||||
|
logger.info("Add VRF ZITA and ensure that the route from VRF ZITA is updated")
|
||||||
|
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"]
|
||||||
|
r1.cmd("ip link add ZITA type vrf table 1003")
|
||||||
|
|
||||||
|
# Test DONNA VRF.
|
||||||
|
expect = {
|
||||||
|
"172.16.101.0/24": [
|
||||||
|
{
|
||||||
|
"protocol": "bgp",
|
||||||
|
"selected": None,
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"fib": None,
|
||||||
|
"interfaceName": "ZITA",
|
||||||
|
"vrf": "ZITA",
|
||||||
|
"active": None,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
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_donna_set_zita_up():
|
||||||
|
logger.info("Set VRF ZITA up and ensure that the route from VRF ZITA is updated")
|
||||||
|
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"]
|
||||||
|
r1.vtysh_cmd(
|
||||||
|
"""
|
||||||
|
configure
|
||||||
|
interface ZITA
|
||||||
|
no shutdown
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
# Test DONNA VRF.
|
||||||
|
expect = {
|
||||||
|
"172.16.101.0/24": [
|
||||||
|
{
|
||||||
|
"protocol": "bgp",
|
||||||
|
"selected": True,
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"fib": True,
|
||||||
|
"interfaceName": "ZITA",
|
||||||
|
"vrf": "ZITA",
|
||||||
|
"active": True,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
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_donna_delete_vrf_zita():
|
||||||
|
logger.info("Delete VRF ZITA and ensure that the route from VRF ZITA is deleted")
|
||||||
|
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"]
|
||||||
|
r1.cmd("ip link delete ZITA")
|
||||||
|
|
||||||
|
# Test DONNA VRF.
|
||||||
|
expect = {
|
||||||
|
"172.16.101.0/24": None,
|
||||||
|
}
|
||||||
|
|
||||||
|
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_memory_leak():
|
def test_memory_leak():
|
||||||
|
@ -8,7 +8,7 @@ from lib.topolog import logger
|
|||||||
from lib import topotest
|
from lib import topotest
|
||||||
|
|
||||||
|
|
||||||
def check_ping(name, dest_addr, expect_connected, count, wait):
|
def check_ping(name, dest_addr, expect_connected, count, wait, source_addr=None):
|
||||||
"""
|
"""
|
||||||
Assert that ping to dest_addr is expected
|
Assert that ping to dest_addr is expected
|
||||||
* 'name': the router to set the ping from
|
* 'name': the router to set the ping from
|
||||||
@ -18,9 +18,13 @@ def check_ping(name, dest_addr, expect_connected, count, wait):
|
|||||||
* 'wait': how long ping should wait to receive all replies
|
* 'wait': how long ping should wait to receive all replies
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def _check(name, dest_addr, match):
|
def _check(name, dest_addr, source_addr, match):
|
||||||
tgen = get_topogen()
|
tgen = get_topogen()
|
||||||
output = tgen.gears[name].run("ping {} -c 1 -w 1".format(dest_addr))
|
cmd = "ping {}".format(dest_addr)
|
||||||
|
if source_addr:
|
||||||
|
cmd += " -I {}".format(source_addr)
|
||||||
|
cmd += " -c 1 -w 1"
|
||||||
|
output = tgen.gears[name].run(cmd)
|
||||||
logger.info(output)
|
logger.info(output)
|
||||||
if match not in output:
|
if match not in output:
|
||||||
return "ping fail"
|
return "ping fail"
|
||||||
@ -28,6 +32,6 @@ def check_ping(name, dest_addr, expect_connected, count, wait):
|
|||||||
match = ", {} packet loss".format("0%" if expect_connected else "100%")
|
match = ", {} packet loss".format("0%" if expect_connected else "100%")
|
||||||
logger.info("[+] check {} {} {}".format(name, dest_addr, match))
|
logger.info("[+] check {} {} {}".format(name, dest_addr, match))
|
||||||
tgen = get_topogen()
|
tgen = get_topogen()
|
||||||
func = functools.partial(_check, name, dest_addr, match)
|
func = functools.partial(_check, name, dest_addr, source_addr, match)
|
||||||
success, result = topotest.run_and_expect(func, None, count=count, wait=wait)
|
success, result = topotest.run_and_expect(func, None, count=count, wait=wait)
|
||||||
assert result is None, "Failed"
|
assert result is None, "Failed"
|
||||||
|
Loading…
Reference in New Issue
Block a user