]> git.proxmox.com Git - mirror_frr.git/commitdiff
tests: Inroduced pim passive test cases
authorsarita patra <saritap@vmware.com>
Mon, 9 May 2022 11:03:52 +0000 (04:03 -0700)
committersarita patra <saritap@vmware.com>
Fri, 13 May 2022 06:51:22 +0000 (23:51 -0700)
Co-authored-by: Vijay Kumar Gupta <vijayg@vmware.com>
Signed-off-by: sarita patra <saritap@vmware.com>
tests/topotests/lib/pim.py
tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo3.py

index 1423f3fecc56a41508901f1b29120a8894b4a954..47892a521875389bc66068e8a6dc27dfd3285dd3 100644 (file)
@@ -3550,6 +3550,69 @@ class McastTesterHelper(HostApplicationHelper):
 
         return True
 
+
+def verify_pim_interface_traffic(tgen, input_dict, return_stats=True):
+    """
+    Verify ip pim interface traffice by running
+    "show ip pim interface traffic" cli
+
+    Parameters
+    ----------
+    * `tgen`: topogen object
+    * `input_dict(dict)`: defines DUT, what and from which interfaces
+                          traffic needs to be verified
+    Usage
+    -----
+    input_dict = {
+        "r1": {
+            "r1-r0-eth0": {
+                "helloRx": 0,
+                "helloTx": 1,
+                "joinRx": 0,
+                "joinTx": 0
+            }
+        }
+    }
+
+    result = verify_pim_interface_traffic(tgen, input_dict)
+
+    Returns
+    -------
+    errormsg(str) or True
+    """
+
+    logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
+
+    output_dict = {}
+    for dut in input_dict.keys():
+        if dut not in tgen.routers():
+            continue
+
+        rnode = tgen.routers()[dut]
+
+        logger.info("[DUT: %s]: Verifying pim interface traffic", dut)
+        show_pim_intf_traffic_json = run_frr_cmd(
+            rnode, "show ip pim interface traffic json", isjson=True
+        )
+
+        output_dict[dut] = {}
+        for intf, data in input_dict[dut].items():
+            interface_json = show_pim_intf_traffic_json[intf]
+            for state in data:
+
+                # Verify Tx/Rx
+                if state in interface_json:
+                    output_dict[dut][state] = interface_json[state]
+                else:
+                    errormsg = (
+                        "[DUT %s]: %s is not present"
+                        "for interface %s [FAILED]!! " % (dut, state, intf)
+                    )
+                    return errormsg
+
+    logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
+    return True if return_stats == False else output_dict
+
     # def cleanup(self):
     #     super(McastTesterHelper, self).cleanup()
 
index cbd10906487aa0f400d3ff9ef2cf0deab765f51f..b71c2d65ebd2b7f7a1fc0883603911bf36cc790d 100755 (executable)
@@ -54,6 +54,7 @@ import sys
 import time
 import datetime
 import pytest
+from time import sleep
 
 pytestmark = pytest.mark.pimd
 
@@ -95,6 +96,7 @@ from lib.pim import (
     verify_pim_rp_info,
     verify_multicast_flag_state,
     McastTesterHelper,
+    verify_pim_interface_traffic,
 )
 from lib.topolog import logger
 from lib.topojson import build_config_from_json
@@ -354,6 +356,45 @@ def find_tos_in_tcpdump(tgen, router, message, cap_file):
     return True
 
 
+def verify_pim_stats_increament(stats_before, stats_after):
+    """
+    API to compare pim interface control plane traffic
+
+    Parameters
+    ----------
+    * `stats_before` : Stats dictionary for any particular instance
+    * `stats_after` : Stats dictionary for any particular instance
+    """
+
+    for router, stats_data in stats_before.items():
+        for stats, value in stats_data.items():
+            if stats_before[router][stats] >= stats_after[router][stats]:
+                errormsg = (
+                    "[DUT: %s]: state %s value has not"
+                    " incremented, Initial value: %s, "
+                    "Current value: %s [FAILED!!]"
+                    % (
+                        router,
+                        stats,
+                        stats_before[router][stats],
+                        stats_after[router][stats],
+                    )
+                )
+                return errormsg
+
+            logger.info(
+                "[DUT: %s]: State %s value is "
+                "incremented, Initial value: %s, Current value: %s"
+                " [PASSED!!]",
+                router,
+                stats,
+                stats_before[router][stats],
+                stats_after[router][stats],
+            )
+
+    return True
+
+
 def test_verify_oil_when_join_prune_sent_scenario_1_p1(request):
     """
     TC_21_1:
@@ -4490,6 +4531,259 @@ def test_verify_multicast_traffic_when_FHR_connected_to_RP_p1(request):
     write_test_footer(tc_name)
 
 
+def test_PIM_passive_p1(request):
+    """
+    TC Verify PIM passive functionality"
+    """
+
+    tgen = get_topogen()
+    tc_name = request.node.name
+    write_test_header(tc_name)
+    app_helper.stop_all_hosts()
+    # Creating configuration from JSON
+    clear_mroute(tgen)
+    if tgen.routers_have_failure():
+        check_router_status(tgen)
+    reset_config_on_routers(tgen)
+    clear_pim_interface_traffic(tgen, topo)
+
+    step("Enable the PIM on all the interfaces of FRR1, FRR2, FRR3")
+    step(
+        "Enable IGMP of FRR1 interface and send IGMP joins "
+        " from FRR1 node for group range (225.1.1.1-5)"
+    )
+
+    intf_c1_i4 = topo["routers"]["c1"]["links"]["i4"]["interface"]
+
+    step(
+        "configure PIM passive on receiver interface to verify no impact on IGMP join"
+        "and multicast traffic on pim passive interface"
+    )
+
+    raw_config = {
+        "c1": {"raw_config": ["interface {}".format(intf_c1_i4), "ip pim passive"]}
+    }
+    result = apply_raw_config(tgen, raw_config)
+    assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+    step("configure IGMPv2 and send IGMP joinon on PIM passive interface")
+    input_dict = {
+        "c1": {"igmp": {"interfaces": {intf_c1_i4: {"igmp": {"version": "2"}}}}}
+    }
+    result = create_igmp_config(tgen, topo, input_dict)
+    assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
+
+    input_join = {"i4": topo["routers"]["i4"]["links"]["c1"]["interface"]}
+    for recvr, recvr_intf in input_join.items():
+        result = app_helper.run_join(recvr, IGMP_JOIN_RANGE_1, join_intf=recvr_intf)
+        assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
+
+    step("Configure static RP for (225.1.1.1-5) as R2")
+
+    input_dict = {
+        "r2": {
+            "pim": {
+                "rp": [
+                    {
+                        "rp_addr": topo["routers"]["r2"]["links"]["lo"]["ipv4"].split(
+                            "/"
+                        )[0],
+                        "group_addr_range": GROUP_RANGE_1,
+                    }
+                ]
+            }
+        }
+    }
+
+    result = create_pim_config(tgen, topo, input_dict)
+    assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+    step("Send Mcast traffic from C2 to all the groups ( 225.1.1.1 to 225.1.1.5)")
+
+    input_src = {"i5": topo["routers"]["i5"]["links"]["c2"]["interface"]}
+    for src, src_intf in input_src.items():
+        result = app_helper.run_traffic(src, IGMP_JOIN_RANGE_1, bind_intf=src_intf)
+        assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+    source_i5 = topo["routers"]["i5"]["links"]["c2"]["ipv4"].split("/")[0]
+
+    input_dict_starg = [
+        {
+            "dut": "c1",
+            "src_address": "*",
+            "iif": topo["routers"]["c1"]["links"]["l1"]["interface"],
+            "oil": topo["routers"]["c1"]["links"]["i4"]["interface"],
+        }
+    ]
+
+    input_dict_sg = [
+        {
+            "dut": "c1",
+            "src_address": source_i5,
+            "iif": topo["routers"]["c1"]["links"]["c2"]["interface"],
+            "oil": topo["routers"]["c1"]["links"]["i4"]["interface"],
+        }
+    ]
+
+    step("(*,G) and (S,G) created on f1 and node verify using 'show ip mroute'")
+
+    for data in input_dict_sg:
+        result = verify_mroutes(
+            tgen,
+            data["dut"],
+            data["src_address"],
+            IGMP_JOIN_RANGE_1,
+            data["iif"],
+            data["oil"],
+        )
+        assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+    for data in input_dict_sg:
+        result = verify_mroutes(
+            tgen,
+            data["dut"],
+            data["src_address"],
+            IGMP_JOIN_RANGE_1,
+            data["iif"],
+            data["oil"],
+        )
+        assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+    for data in input_dict_starg:
+        result = verify_mroutes(
+            tgen,
+            data["dut"],
+            data["src_address"],
+            IGMP_JOIN_RANGE_1,
+            data["iif"],
+            data["oil"],
+        )
+        assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+    intf_c1_c2 = topo["routers"]["c1"]["links"]["c2"]["interface"]
+    intf_c2_c1 = topo["routers"]["c2"]["links"]["c1"]["interface"]
+
+    step(
+        "configure PIM passive on upstream interface to verify"
+        "hello tx/rx counts are not incremented"
+    )
+
+    # Changing hello timer to 3sec for checking more number of packets
+
+    raw_config = {
+        "c1": {
+            "raw_config": [
+                "interface {}".format(intf_c1_c2),
+                "ip pim passive",
+                "ip pim hello 3",
+            ]
+        },
+        "c2": {"raw_config": ["interface {}".format(intf_c2_c1), "ip pim hello 3"]},
+    }
+    result = apply_raw_config(tgen, raw_config)
+    assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+    step("verify PIM hello tx/rx stats on C1")
+    state_dict = {
+        "c1": {
+            intf_c1_c2: ["helloTx", "helloRx"],
+        }
+    }
+
+    logger.info("waiting for 5 sec config to get apply and hello count update")
+    sleep(5)
+
+    c1_state_before = verify_pim_interface_traffic(tgen, state_dict)
+    assert isinstance(
+        c1_state_before, dict
+    ), "Testcase{} : Failed \n state_before is not dictionary \n " "Error: {}".format(
+        tc_name, result
+    )
+
+    logger.info(
+        "sleeping for 30 sec hello interval timer to verify count are not increamented"
+    )
+    sleep(35)
+
+    c1_state_after = verify_pim_interface_traffic(tgen, state_dict)
+    assert isinstance(
+        c1_state_after, dict
+    ), "Testcase{} : Failed \n state_before is not dictionary \n " "Error: {}".format(
+        tc_name, result
+    )
+
+    step("verify stats not increamented on c1")
+    result = verify_pim_stats_increament(c1_state_before, c1_state_after)
+    assert (
+        result is not True
+    ), "Testcase{} : Failed Error: {}" "stats incremented".format(tc_name, result)
+
+    step("No impact observed on mroutes")
+    for data in input_dict_sg:
+        result = verify_mroutes(
+            tgen,
+            data["dut"],
+            data["src_address"],
+            IGMP_JOIN_RANGE_1,
+            data["iif"],
+            data["oil"],
+        )
+        assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+    for data in input_dict_sg:
+        result = verify_mroutes(
+            tgen,
+            data["dut"],
+            data["src_address"],
+            IGMP_JOIN_RANGE_1,
+            data["iif"],
+            data["oil"],
+        )
+        assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+    for data in input_dict_starg:
+        result = verify_mroutes(
+            tgen,
+            data["dut"],
+            data["src_address"],
+            IGMP_JOIN_RANGE_1,
+            data["iif"],
+            data["oil"],
+        )
+        assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+    step("remove PIM passive and verify hello tx/rx is increamented")
+    raw_config = {
+        "c1": {
+            "raw_config": [
+                "interface {}".format(intf_c1_c2),
+                "no ip pim passive",
+                "ip pim hello 3",
+            ]
+        }
+    }
+    result = apply_raw_config(tgen, raw_config)
+    assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+    logger.info("waiting for 30 sec for pim hello to receive")
+    sleep(30)
+
+    c1_state_after = verify_pim_interface_traffic(tgen, state_dict)
+    assert isinstance(
+        c1_state_after, dict
+    ), "Testcase{} : Failed \n state_before is not dictionary \n " "Error: {}".format(
+        tc_name, result
+    )
+
+    step("verify stats increamented on c1 after removing pim passive")
+    result = verify_pim_stats_increament(c1_state_before, c1_state_after)
+    assert result is True, "Testcase{} : Failed Error: {}" "stats incremented".format(
+        tc_name, result
+    )
+
+    write_test_footer(tc_name)
+
+
 if __name__ == "__main__":
     args = ["-s"] + sys.argv[1:]
     sys.exit(pytest.main(args))