summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--isisd/isis_circuit.c2
-rw-r--r--isisd/isis_pdu.c3
-rw-r--r--tests/topotests/isis_topo1/test_isis_topo1.py161
3 files changed, 165 insertions, 1 deletions
diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c
index fa1ce3007f..9a967bc1e3 100644
--- a/isisd/isis_circuit.c
+++ b/isisd/isis_circuit.c
@@ -851,11 +851,13 @@ void isis_circuit_down(struct isis_circuit *circuit)
isis_dr_resign(circuit, 1);
circuit->u.bc.is_dr[0] = 0;
}
+ circuit->u.bc.run_dr_elect[0] = 0;
memset(circuit->u.bc.l1_desig_is, 0, ISIS_SYS_ID_LEN + 1);
if (circuit->u.bc.is_dr[1]) {
isis_dr_resign(circuit, 2);
circuit->u.bc.is_dr[1] = 0;
}
+ circuit->u.bc.run_dr_elect[1] = 0;
memset(circuit->u.bc.l2_desig_is, 0, ISIS_SYS_ID_LEN + 1);
memset(circuit->u.bc.snpa, 0, ETH_ALEN);
diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c
index 23238d314a..c2ada459eb 100644
--- a/isisd/isis_pdu.c
+++ b/isisd/isis_pdu.c
@@ -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);
diff --git a/tests/topotests/isis_topo1/test_isis_topo1.py b/tests/topotests/isis_topo1/test_isis_topo1.py
index 1cec2f16f0..f80f2e435f 100644
--- a/tests/topotests/isis_topo1/test_isis_topo1.py
+++ b/tests/topotests/isis_topo1/test_isis_topo1.py
@@ -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")