Merge pull request #17219 from zhou-run/202406201119

isisd: When the ISIS types of the routers do not match on a P2P link, the neighbor status remains UP
This commit is contained in:
Russ White 2024-11-26 10:10:33 -05:00 committed by GitHub
commit 0a40e044ac
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 163 additions and 1 deletions

View file

@ -231,7 +231,8 @@ static int process_p2p_hello(struct iih_info *iih)
return ISIS_OK;
}
}
if (!adj || adj->level != iih->calculated_type) {
if (!adj || adj->level != iih->calculated_type ||
!(iih->circuit->is_type & iih->circ_type)) {
if (!adj) {
adj = isis_new_adj(iih->sys_id, NULL,
iih->calculated_type, iih->circuit);

View file

@ -12,6 +12,7 @@
"""
test_isis_topo1.py: Test ISIS topology.
"""
import time
import datetime
import functools
import json
@ -314,6 +315,107 @@ def test_isis_neighbor_json():
), assertmsg
def test_isis_neighbor_state():
"Check that the neighbor states remain normal when the ISIS type is switched."
tgen = get_topogen()
# Don't run this test if we have any failure.
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info("Checking 'show isis neighbor state on a p2p link'")
# Establish a P2P link
# When the IS-IS type of r3 is set to level-1-2 and the IS-IS type of r5 is set to level-1,
# it is expected that all neighbors exist and are in the Up state
r3 = tgen.gears["r3"]
r3.vtysh_cmd(
"""
configure
router isis 1
no redistribute ipv4 connected level-1
no redistribute ipv4 connected level-2
no redistribute ipv6 connected level-1
no redistribute ipv6 connected level-2
interface r3-eth1
no isis circuit-type
isis network point-to-point
end
"""
)
r5 = tgen.gears["r5"]
r5.vtysh_cmd(
"""
configure
router isis 1
no redistribute ipv4 connected level-1
no redistribute ipv6 connected level-1
no redistribute ipv4 table 20 level-1
interface r5-eth0
no isis circuit-type
isis network point-to-point
end
"""
)
result = _check_isis_neighbor_json("r3", "r5", True, "Up")
assert result is True, result
result = _check_isis_neighbor_json("r5", "r3", True, "Up")
assert result is True, result
# Remove the configuration that affects the switch of IS-IS type.
# Configure the IS-IS type of r3 to transition from level-1-2 to level-2-only,
# while maintaining the IS-IS type of r5 as level-1.
# In this scenario,
# the expectation is that some neighbors do not exist or are in the Initializing state
r3.vtysh_cmd(
"""
configure
router isis 1
is-type level-2-only
end
"""
)
result = _check_isis_neighbor_json("r3", "r5", False, "Initializing")
assert result is True, result
result = _check_isis_neighbor_json("r5", "r3", False, "Initializing")
assert result is True, result
# Restore to initial configuration
logger.info("Checking 'restore to initial configuration'")
r3.vtysh_cmd(
"""
configure
interface r3-eth1
isis circuit-type level-1
no isis network point-to-point
router isis 1
no is-type
redistribute ipv4 connected level-1
redistribute ipv4 connected level-2
redistribute ipv6 connected level-1
redistribute ipv6 connected level-2
end
"""
)
r5.vtysh_cmd(
"""
configure
interface r5-eth0
isis circuit-type level-1
no isis network point-to-point
router isis 1
redistribute ipv4 connected level-1
redistribute ipv6 connected level-1
redistribute ipv4 table 20 level-1
end
"""
)
result = _check_isis_neighbor_json("r3", "r5", True, "Up")
assert result is True, result
result = _check_isis_neighbor_json("r5", "r3", True, "Up")
assert result is True, result
def test_isis_database_json():
"Check json struct in show isis database json"
@ -623,6 +725,65 @@ def test_isis_hello_padding_during_adjacency_formation():
assert result is True, result
def _check_isis_neighbor_json(
self, neighbor, neighbor_expected, neighbor_state_expected
):
tgen = get_topogen()
router = tgen.gears[self]
logger.info(
f"check_isis_neighbor_json {router} {neighbor} {neighbor_expected} {neighbor_state_expected}"
)
result = _check_isis_neighbor_exist(self, neighbor)
if result == True:
return _check_isis_neighbor_state(self, neighbor, neighbor_state_expected)
elif neighbor_expected == True:
return "{} with expected neighbor {} got none ".format(router.name, neighbor)
else:
return True
@retry(retry_timeout=60)
def _check_isis_neighbor_exist(self, neighbor):
tgen = get_topogen()
router = tgen.gears[self]
logger.info(f"check_isis_neighbor_exist {router} {neighbor}")
neighbor_json = router.vtysh_cmd("show isis neighbor json", isjson=True)
circuits = neighbor_json.get("areas", [])[0].get("circuits", [])
for circuit in circuits:
if "adj" in circuit and circuit["adj"] == neighbor:
return True
return "The neighbor {} of router {} has not been learned yet ".format(
neighbor, router.name
)
@retry(retry_timeout=5)
def _check_isis_neighbor_state(self, neighbor, neighbor_state_expected):
tgen = get_topogen()
router = tgen.gears[self]
logger.info(
f"check_isis_neighbor_state {router} {neighbor} {neighbor_state_expected}"
)
neighbor_json = router.vtysh_cmd(
"show isis neighbor {} json".format(neighbor), isjson=True
)
circuits = neighbor_json.get("areas", [])[0].get("circuits", [])
for circuit in circuits:
interface = circuit.get("interface", {})
if "state" in interface:
neighbor_state = interface["state"]
if neighbor_state == neighbor_state_expected:
return True
return "{} peer with expected neighbor_state {} got {} ".format(
router.name, neighbor_state_expected, neighbor_state
)
@retry(retry_timeout=10)
def check_last_iih_packet_for_padding(router, expect_padding):
logfilename = "{}/{}".format(router.gearlogdir, "isisd.log")