Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bgpd: fix prefix same as nexthop in label per nexthop #16990

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions bgpd/bgp_mplsvpn.c
Original file line number Diff line number Diff line change
Expand Up @@ -1598,6 +1598,16 @@ vpn_leak_from_vrf_get_per_nexthop_label(afi_t afi, struct bgp_path_info *pi,
return bgp_mplsvpn_get_vpn_label(&from_bgp->vpn_policy[afi]);
}

if (is_bgp_static_route &&
pi->nexthop->nexthop->type == NEXTHOP_TYPE_IFINDEX) {
ton31337 marked this conversation as resolved.
Show resolved Hide resolved
/* "network" imported prefixes from vrf
* fallback to per-vrf label.
*/

bgp_mplsvpn_path_nh_label_unlink(pi);
return bgp_mplsvpn_get_vpn_label(&from_bgp->vpn_policy[afi]);
}

return _vpn_leak_from_vrf_get_per_nexthop_label(pi, to_bgp, from_bgp,
afi);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ def bgp_vpnv4_table_check(
test_func = functools.partial(
check_bgp_vpnv4_prefix_presence, router, prefix, table_version
)
success, _ = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
success, _ = topotest.run_and_expect(test_func, None, count=10, wait=3)
assert success, "{}, prefix ipv4 vpn {} is not installed yet".format(
router.name, prefix
)
Expand Down Expand Up @@ -321,7 +321,7 @@ def mpls_table_check(router, blacklist=None, label_list=None, whitelist=None):
test_func = functools.partial(
check_show_mpls_table, router, blacklist, label_list, whitelist
)
success, result = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
success, result = topotest.run_and_expect(test_func, None, count=10, wait=3)
assert success, "{}, MPLS labels check fail: {}".format(router.name, result)


Expand All @@ -346,11 +346,32 @@ def check_show_bgp_vpn_prefix_found(router, ipversion, prefix, rd):
expected = {rd: {"prefix": prefix}}
return topotest.json_cmp(output, expected)

def check_show_mpls_table_entry_label_found_nexthop(expected_router, get_router,
network, nexthop):
label = get_mpls_label(get_router, network)
if label < 0:
return False

def check_show_mpls_table_entry_label_found(router, inlabel, interface):
output = json.loads(router.vtysh_cmd("show mpls table {} json".format(inlabel)))
output = json.loads(expected_router.vtysh_cmd("show mpls table {} json".format(label)))
expected = {
"inLabel": inlabel,
"inLabel": label,
"installed": True,
"nexthops": [{"nexthop": nexthop}],
}
return topotest.json_cmp(output, expected)

def check_show_mpls_table_entry_label_found(expected_router, get_router,
interface, network=None, label=None):
if not label:
label = get_mpls_label(get_router, network)
if label < 0:
return False

output = json.loads(expected_router.vtysh_cmd(
"show mpls table {} json".format(label)
))
expected = {
"inLabel": label,
"installed": True,
"nexthops": [{"interface": interface}],
}
Expand Down Expand Up @@ -395,6 +416,17 @@ def mpls_entry_get_interface(router, label):
return outgoing_interface


def get_mpls_label(router, network):
label = router.vtysh_cmd(
"show ip route vrf vrf1 %s json" % network,
isjson=True,
)
label = label.get(f"{network}", [{}])[0].get("nexthops", [{}])[0]
label = int(label.get("labels", [-1])[0])

return label


def test_protocols_convergence():
"""
Assert that all protocols have converged
Expand All @@ -415,7 +447,7 @@ def test_protocols_convergence():
"show bgp vrf vrf1 ipv4 json",
expected,
)
_, result = topotest.run_and_expect(test_func, None, count=20, wait=0.5)
_, result = topotest.run_and_expect(test_func, None, count=10, wait=3)
assertmsg = '"{}" JSON output mismatches'.format(router.name)
assert result is None, assertmsg

Expand All @@ -429,7 +461,7 @@ def test_protocols_convergence():
"show bgp ipv4 vpn json",
expected,
)
_, result = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
_, result = topotest.run_and_expect(test_func, None, count=10, wait=3)
assertmsg = '"{}" JSON output mismatches'.format(router.name)
assert result is None, assertmsg

Expand Down Expand Up @@ -471,7 +503,7 @@ def _bgp_prefix_not_found(router, vrf, ipversion, prefix):
test_func = functools.partial(
_bgp_prefix_not_found, tgen.gears["r1"], "vrf1", "ipv4", "172.31.0.11/32"
)
success, _ = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
success, _ = topotest.run_and_expect(test_func, None, count=10, wait=3)
assert (
success
), "r1, prefix 172.31.0.11/32 from r11 did not disappear. r11 still connected to rr ?"
Expand Down Expand Up @@ -509,7 +541,7 @@ def test_flapping_bgp_vrf_up():
"172.31.0.11/32",
"444:1",
)
success, _ = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
success, _ = topotest.run_and_expect(test_func, None, count=10, wait=3)
assert (
success
), "r2, prefix 172.31.0.11/32 from r11 not present. r11 still disconnected from rr ?"
Expand Down Expand Up @@ -539,7 +571,7 @@ def test_recursive_route():
"172.31.0.30/32",
"444:1",
)
success, _ = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
success, _ = topotest.run_and_expect(test_func, None, count=10, wait=3)
assert success, "r2, vpnv4 update 172.31.0.30 not found"

bgp_vpnv4_table_check(tgen.gears["r2"], group=PREFIXES_R11 + ["172.31.0.30/32"])
Expand All @@ -565,7 +597,7 @@ def test_recursive_route():
"172.31.0.30/32",
"444:1",
)
success, _ = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
success, _ = topotest.run_and_expect(test_func, None, count=10, wait=3)
assert success, "r2, vpnv4 update 172.31.0.30 still present"


Expand All @@ -591,7 +623,7 @@ def test_prefix_changes_interface():
"172.31.0.50/32",
"444:1",
)
success, _ = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
success, _ = topotest.run_and_expect(test_func, None, count=10, wait=3)
assert success, "r2, vpnv4 update 172.31.0.50 not found"

# diagnostic
Expand Down Expand Up @@ -637,7 +669,7 @@ def test_prefix_changes_interface():
"444:1",
label=oldlabel,
)
success, _ = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
success, _ = topotest.run_and_expect(test_func, None, count=10, wait=3)
assert (
success
), "r2, vpnv4 update 172.31.0.50 with old label {0} still present".format(oldlabel)
Expand All @@ -654,7 +686,7 @@ def test_prefix_changes_interface():
"172.31.0.50/32",
"444:1",
)
success, _ = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
success, _ = topotest.run_and_expect(test_func, None, count=10, wait=3)
assert success, "r2, vpnv4 update 172.31.0.50 not found"

label_list = set()
Expand Down Expand Up @@ -719,9 +751,10 @@ def test_changing_default_label_value():
"r1, mpls table, check that MPLS entry with inLabel set to 222 has vrf1 interface"
)
test_func = functools.partial(
check_show_mpls_table_entry_label_found, router, 222, "vrf1"
check_show_mpls_table_entry_label_found, tgen.gears["r1"], router,
"vrf1", label=222
)
success, _ = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
success, _ = topotest.run_and_expect(test_func, None, count=10, wait=3)
assert success, "r1, mpls entry with label 222 not found"

# check label repartition is ok
Expand Down Expand Up @@ -769,7 +802,7 @@ def test_unconfigure_allocation_mode_nexthop():
test_func = functools.partial(
check_show_mpls_table_entry_label_not_found, router, 17
)
success, _ = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
success, _ = topotest.run_and_expect(test_func, None, count=10, wait=3)
assert success, "r1, mpls entry with label 17 still present"

# Check vpnv4 routes from r1
Expand Down Expand Up @@ -821,7 +854,7 @@ def test_reconfigure_allocation_mode_nexthop():
test_func = functools.partial(
check_show_mpls_table_entry_label_not_found, router, 17
)
success, _ = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
success, _ = topotest.run_and_expect(test_func, None, count=10, wait=3)
assert success, "r1, mpls entry with label 17 still present"

# Check vpnv4 routes from r1
Expand All @@ -836,6 +869,114 @@ def test_reconfigure_allocation_mode_nexthop():
logger.info("Checking MPLS values on show mpls table of r1")
mpls_table_check(router, label_list=label_list)

def test_network_command():
"""
Test with network declaration
"""
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info("Disabling redistribute static")
tgen.gears["r1"].vtysh_cmd(
"configure terminal\nrouter bgp 65500 vrf vrf1\naddress-family ipv4 unicast\nno redistribute static\n",
isjson=False,
)
logger.info("Checking BGP VPNv4 labels on r2")
for p in ["172.31.0.24/32", "172.31.0.15/32"]:
test_func = functools.partial(
check_show_bgp_vpn_prefix_not_found, tgen.gears["r2"], "ipv4", p,
"444:1"
)
success, _ = topotest.run_and_expect(test_func, None, count=10, wait=3)
assert success, "network %s should not present on r2" % p

logger.info("Use network command for host networks declared in static instead")
tgen.gears["r1"].vtysh_cmd(
"configure terminal\nrouter bgp 65500 vrf vrf1\naddress-family ipv4 unicast\nnetwork 172.31.0.14/32\n",
isjson=False,
)
tgen.gears["r1"].vtysh_cmd(
"configure terminal\nrouter bgp 65500 vrf vrf1\naddress-family ipv4 unicast\nnetwork 172.31.0.15/32\n",
isjson=False,
)
logger.info("Checking BGP VPNv4 labels on r2")
bgp_vpnv4_table_check(tgen.gears["r2"], group=["172.31.0.12/32", "172.31.0.15/32"])
bgp_vpnv4_table_check(tgen.gears["r2"], group=["172.31.0.14/32"])
mpls_table_check(tgen.gears["r1"], whitelist=["192.0.2.14"])

logger.info(" Remove network to 172.31.0.14/32")
tgen.gears["r1"].vtysh_cmd(
"configure terminal\nrouter bgp 65500 vrf vrf1\naddress-family ipv4 unicast\nno network 172.31.0.14/32\n",
isjson=False,
)
test_func = functools.partial(
check_show_bgp_vpn_prefix_not_found, tgen.gears["r2"], "ipv4",
"172.31.0.14/32", "444:1"
)
success, _ = topotest.run_and_expect(test_func, None, count=10, wait=3)
assert success, "network 172.31.0.14/32 should not present on r2"
mpls_table_check(tgen.gears["r1"], blacklist=["192.0.2.14"])

logger.info("Disabling redistribute connected and enabling redistribute static")
tgen.gears["r1"].vtysh_cmd(
"configure terminal\nrouter bgp 65500 vrf vrf1\naddress-family ipv4 unicast\n"
"redistribute static\n no redistribute connected",
isjson=False,
)
logger.info("Use network command for connect network 192.168.255.0/24 in vrf")
tgen.gears["r1"].vtysh_cmd(
"configure terminal\nrouter bgp 65500 vrf vrf1\naddress-family ipv4 unicast\n"
"network 192.168.255.0/24\n",
isjson=False,
)
logger.info("Checking BGP VPNv4 labels on r2")
bgp_vpnv4_table_check(tgen.gears["r2"], group=["192.168.255.0/24"])
logger.info("Checking no mpls entry associated to 192.168.255.0/24")
mpls_table_check(tgen.gears["r1"], blacklist=["192.168.255.0"])
logger.info("Checking 192.168.255.0/24 fallback to vrf")
test_func = functools.partial(
check_show_mpls_table_entry_label_found,
tgen.gears["r1"], tgen.gears["r2"], "vrf1", network="192.168.255.0/24",
)
success, _ = topotest.run_and_expect(test_func, None, count=10, wait=3)
assert success, "192.168.255.0/24 does not fallback to vrf"

logger.info("Use network command for statically routed network 192.168.3.0/24 in vrf")
tgen.gears["r1"].vtysh_cmd("configure terminal\nvrf vrf1\n"
"ip route 192.168.3.0/24 192.0.2.11\n")
tgen.gears["r1"].vtysh_cmd(
"configure terminal\nrouter bgp 65500 vrf vrf1\naddress-family ipv4 unicast\n"
"network 192.168.3.0/24\n",
isjson=False,
)
logger.info("Checking 192.168.3.0/24 route on r2")
test_func = functools.partial(
check_show_mpls_table_entry_label_found_nexthop,
tgen.gears["r1"], tgen.gears["r2"], "192.168.3.0/24", "192.0.2.11"
)
success, _ = topotest.run_and_expect(test_func, None, count=10, wait=3)
assert success, "label from r2 is not present on r1 for 192.168.3.0/24"

# diagnostic
logger.info("Dumping label nexthop table")
tgen.gears["r1"].vtysh_cmd("show bgp vrf vrf1 label-nexthop detail", isjson=False)
logger.info("Dumping bgp network import-check-table")
tgen.gears["r1"].vtysh_cmd(
"show bgp vrf vrf1 import-check-table detail", isjson=False
)

logger.info("Restoring 172.31.0.14 prefix on r1")
tgen.gears["r1"].vtysh_cmd(
"configure terminal\nrouter bgp 65500 vrf vrf1\naddress-family ipv4 unicast\nnetwork 172.31.0.14/32\n",
isjson=False,
)
logger.info("Restoring redistribute connected")
tgen.gears["r1"].vtysh_cmd(
"configure terminal\nrouter bgp 65500 vrf vrf1\naddress-family ipv4 unicast\n"
"no redistribute static\n redistribute connected",
isjson=False,
)


def test_memory_leak():
"Run the memory leak test and report results."
Expand Down
Loading
Loading