From 4306e785414cfb8d15bd4d2ca50a5b987ff46eab Mon Sep 17 00:00:00 2001 From: kcudnik Date: Thu, 23 May 2024 16:30:21 +0200 Subject: [PATCH 1/7] Test CRM tests --- azure-pipelines.yml | 119 - tests/test_acl.py | 927 ------- tests/test_acl_ctrl.py | 27 - tests/test_acl_egress_table.py | 176 -- tests/test_acl_l3v4v6.py | 99 - tests/test_acl_mclag.py | 205 -- tests/test_acl_portchannel.py | 223 -- tests/test_admin_status.py | 138 -- tests/test_bfd.py | 639 ----- tests/test_buffer_dynamic.py | 905 ------- tests/test_buffer_mode.py | 27 - tests/test_buffer_traditional.py | 355 --- tests/test_copp.py | 878 ------- tests/test_dash_acl.py | 854 ------- tests/test_dash_vnet.py | 345 --- tests/test_dirbcast.py | 102 - tests/test_drop_counters.py | 791 ------ tests/test_dtel.py | 407 --- tests/test_evpn_fdb.py | 387 --- tests/test_evpn_fdb_p2mp.py | 410 ---- tests/test_evpn_l3_vxlan.py | 632 ----- tests/test_evpn_l3_vxlan_p2mp.py | 649 ----- tests/test_evpn_tunnel.py | 258 -- tests/test_evpn_tunnel_p2mp.py | 216 -- tests/test_fabric.py | 91 - tests/test_fabric_capacity.py | 72 - tests/test_fabric_port.py | 48 - tests/test_fabric_port_isolation.py | 64 - tests/test_fdb.py | 388 --- tests/test_fdb_update.py | 327 --- tests/test_fdbsync.py | 420 ---- tests/test_fgnhg.py | 869 ------- tests/test_flex_counters.py | 845 ------- tests/test_gearbox.py | 203 -- tests/test_hash.py | 292 --- tests/test_inband_intf_mgmt_vrf.py | 168 -- tests/test_interface.py | 2296 ----------------- tests/test_intf_mac.py | 260 -- tests/test_ipv6_link_local.py | 112 - tests/test_macsec.py | 904 ------- tests/test_mclag_cfg.py | 210 -- tests/test_mclag_fdb.py | 587 ----- tests/test_mirror.py | 917 ------- tests/test_mirror_ipv6_combined.py | 479 ---- tests/test_mirror_ipv6_separate.py | 670 ----- tests/test_mirror_policer.py | 246 -- tests/test_mirror_port_erspan.py | 581 ----- tests/test_mirror_port_span.py | 525 ---- tests/test_mpls.py | 685 ------ tests/test_mux.py | 1587 ------------ tests/test_nat.py | 431 ---- tests/test_neighbor.py | 530 ---- tests/test_nhg.py | 2409 ------------------ tests/test_nvgre_tunnel.py | 381 --- tests/test_pbh.py | 1023 -------- tests/test_pfc.py | 136 -- tests/test_pfcwd.py | 302 --- tests/test_pg_drop_counter.py | 94 - tests/test_policer.py | 80 - tests/test_port.py | 312 --- tests/test_port_add_remove.py | 525 ---- tests/test_port_an.py | 359 --- tests/test_port_buffer_rel.py | 42 - tests/test_port_config.py | 235 -- tests/test_port_dpb.py | 105 - tests/test_port_dpb_acl.py | 190 -- tests/test_port_dpb_lag.py | 84 - tests/test_port_dpb_system.py | 867 ------- tests/test_port_dpb_vlan.py | 248 -- tests/test_port_fec_override.py | 46 - tests/test_port_lt.py | 139 -- tests/test_port_mac_learn.py | 189 -- tests/test_portchannel.py | 470 ---- tests/test_qos_map.py | 627 ----- tests/test_route.py | 1119 --------- tests/test_setro.py | 52 - tests/test_sflow.py | 347 --- tests/test_speed.py | 82 - tests/test_srv6.py | 633 ----- tests/test_storm_control.py | 316 --- tests/test_sub_port_intf.py | 1621 ------------ tests/test_switch.py | 105 - tests/test_tunnel.py | 365 --- tests/test_twamp.py | 182 -- tests/test_virtual_chassis.py | 979 -------- tests/test_vlan.py | 540 ---- tests/test_vnet.py | 3530 --------------------------- tests/test_vrf.py | 312 --- tests/test_vxlan_tunnel.py | 403 --- tests/test_warm_reboot.py | 2464 ------------------- tests/test_watermark.py | 310 --- tests/test_zmq.py | 104 - 92 files changed, 46903 deletions(-) delete mode 100644 tests/test_acl.py delete mode 100644 tests/test_acl_ctrl.py delete mode 100644 tests/test_acl_egress_table.py delete mode 100644 tests/test_acl_l3v4v6.py delete mode 100644 tests/test_acl_mclag.py delete mode 100644 tests/test_acl_portchannel.py delete mode 100644 tests/test_admin_status.py delete mode 100644 tests/test_bfd.py delete mode 100644 tests/test_buffer_dynamic.py delete mode 100644 tests/test_buffer_mode.py delete mode 100644 tests/test_buffer_traditional.py delete mode 100644 tests/test_copp.py delete mode 100644 tests/test_dash_acl.py delete mode 100644 tests/test_dash_vnet.py delete mode 100644 tests/test_dirbcast.py delete mode 100644 tests/test_drop_counters.py delete mode 100644 tests/test_dtel.py delete mode 100644 tests/test_evpn_fdb.py delete mode 100644 tests/test_evpn_fdb_p2mp.py delete mode 100644 tests/test_evpn_l3_vxlan.py delete mode 100644 tests/test_evpn_l3_vxlan_p2mp.py delete mode 100644 tests/test_evpn_tunnel.py delete mode 100644 tests/test_evpn_tunnel_p2mp.py delete mode 100644 tests/test_fabric.py delete mode 100644 tests/test_fabric_capacity.py delete mode 100644 tests/test_fabric_port.py delete mode 100644 tests/test_fabric_port_isolation.py delete mode 100644 tests/test_fdb.py delete mode 100644 tests/test_fdb_update.py delete mode 100644 tests/test_fdbsync.py delete mode 100644 tests/test_fgnhg.py delete mode 100644 tests/test_flex_counters.py delete mode 100644 tests/test_gearbox.py delete mode 100644 tests/test_hash.py delete mode 100644 tests/test_inband_intf_mgmt_vrf.py delete mode 100644 tests/test_interface.py delete mode 100644 tests/test_intf_mac.py delete mode 100644 tests/test_ipv6_link_local.py delete mode 100644 tests/test_macsec.py delete mode 100644 tests/test_mclag_cfg.py delete mode 100644 tests/test_mclag_fdb.py delete mode 100644 tests/test_mirror.py delete mode 100644 tests/test_mirror_ipv6_combined.py delete mode 100644 tests/test_mirror_ipv6_separate.py delete mode 100644 tests/test_mirror_policer.py delete mode 100644 tests/test_mirror_port_erspan.py delete mode 100644 tests/test_mirror_port_span.py delete mode 100644 tests/test_mpls.py delete mode 100644 tests/test_mux.py delete mode 100644 tests/test_nat.py delete mode 100644 tests/test_neighbor.py delete mode 100644 tests/test_nhg.py delete mode 100644 tests/test_nvgre_tunnel.py delete mode 100644 tests/test_pbh.py delete mode 100644 tests/test_pfc.py delete mode 100644 tests/test_pfcwd.py delete mode 100644 tests/test_pg_drop_counter.py delete mode 100644 tests/test_policer.py delete mode 100644 tests/test_port.py delete mode 100644 tests/test_port_add_remove.py delete mode 100644 tests/test_port_an.py delete mode 100644 tests/test_port_buffer_rel.py delete mode 100644 tests/test_port_config.py delete mode 100644 tests/test_port_dpb.py delete mode 100644 tests/test_port_dpb_acl.py delete mode 100644 tests/test_port_dpb_lag.py delete mode 100644 tests/test_port_dpb_system.py delete mode 100644 tests/test_port_dpb_vlan.py delete mode 100644 tests/test_port_fec_override.py delete mode 100644 tests/test_port_lt.py delete mode 100644 tests/test_port_mac_learn.py delete mode 100644 tests/test_portchannel.py delete mode 100644 tests/test_qos_map.py delete mode 100644 tests/test_route.py delete mode 100644 tests/test_setro.py delete mode 100644 tests/test_sflow.py delete mode 100644 tests/test_speed.py delete mode 100644 tests/test_srv6.py delete mode 100644 tests/test_storm_control.py delete mode 100644 tests/test_sub_port_intf.py delete mode 100644 tests/test_switch.py delete mode 100644 tests/test_tunnel.py delete mode 100644 tests/test_twamp.py delete mode 100644 tests/test_virtual_chassis.py delete mode 100644 tests/test_vlan.py delete mode 100644 tests/test_vnet.py delete mode 100644 tests/test_vrf.py delete mode 100644 tests/test_vxlan_tunnel.py delete mode 100644 tests/test_warm_reboot.py delete mode 100644 tests/test_watermark.py delete mode 100644 tests/test_zmq.py diff --git a/azure-pipelines.yml b/azure-pipelines.yml index e3255ba15b..1965e3ba7c 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -50,87 +50,6 @@ stages: archive_pytests: true archive_gcov: true -- stage: BuildAsan - dependsOn: [] - jobs: - - template: .azure-pipelines/build-template.yml - parameters: - arch: amd64 - pool: sonicbld - sonic_slave: sonic-slave-bullseye - common_lib_artifact_name: common-lib - swss_common_artifact_name: sonic-swss-common - sairedis_artifact_name: sonic-sairedis - artifact_name: sonic-swss-asan - asan: true - -- stage: BuildArm - dependsOn: Build - condition: succeeded('Build') - jobs: - - template: .azure-pipelines/build-template.yml - parameters: - arch: armhf - timeout: 240 - pool: sonicbld-armhf - sonic_slave: sonic-slave-bullseye-armhf - common_lib_artifact_name: common-lib.armhf - swss_common_artifact_name: sonic-swss-common.armhf - sairedis_artifact_name: sonic-sairedis.armhf - artifact_name: sonic-swss.armhf - archive_gcov: false - - - template: .azure-pipelines/build-template.yml - parameters: - arch: arm64 - timeout: 240 - pool: sonicbld-arm64 - sonic_slave: sonic-slave-bullseye-arm64 - common_lib_artifact_name: common-lib.arm64 - swss_common_artifact_name: sonic-swss-common.arm64 - sairedis_artifact_name: sonic-sairedis.arm64 - artifact_name: sonic-swss.arm64 - archive_gcov: false - -- stage: BuildBookworm - dependsOn: BuildArm - condition: succeeded('BuildArm') - jobs: - - template: .azure-pipelines/build-template.yml - parameters: - arch: amd64 - pool: sonicbld - sonic_slave: sonic-slave-bookworm - common_lib_artifact_name: common-lib - swss_common_artifact_name: sonic-swss-common-bookworm - sairedis_artifact_name: sonic-sairedis-bookworm - artifact_name: sonic-swss-bookworm - archive_gcov: false - - - template: .azure-pipelines/build-template.yml - parameters: - arch: armhf - timeout: 240 - pool: sonicbld-armhf - sonic_slave: sonic-slave-bookworm-armhf - common_lib_artifact_name: common-lib.armhf - swss_common_artifact_name: sonic-swss-common-bookworm.armhf - sairedis_artifact_name: sonic-sairedis-bookworm.armhf - artifact_name: sonic-swss-bookworm.armhf - archive_gcov: false - - - template: .azure-pipelines/build-template.yml - parameters: - arch: arm64 - timeout: 240 - pool: sonicbld-arm64 - sonic_slave: sonic-slave-bookworm-arm64 - common_lib_artifact_name: common-lib.arm64 - swss_common_artifact_name: sonic-swss-common-bookworm.arm64 - sairedis_artifact_name: sonic-sairedis-bookworm.arm64 - artifact_name: sonic-swss-bookworm.arm64 - archive_gcov: false - - stage: BuildDocker dependsOn: Build condition: succeeded('Build') @@ -142,18 +61,6 @@ stages: swss_artifact_name: sonic-swss artifact_name: docker-sonic-vs -- stage: BuildDockerAsan - dependsOn: BuildAsan - condition: succeeded('BuildAsan') - jobs: - - template: .azure-pipelines/build-docker-sonic-vs-template.yml - parameters: - swss_common_artifact_name: sonic-swss-common - sairedis_artifact_name: sonic-sairedis - swss_artifact_name: sonic-swss-asan - artifact_name: docker-sonic-vs-asan - asan: true - - stage: Test dependsOn: BuildDocker condition: succeeded('BuildDocker') @@ -164,29 +71,3 @@ stages: gcov_artifact_name: sonic-gcov sonic_slave: sonic-slave-bullseye archive_gcov: true - -- stage: TestAsan - dependsOn: BuildDockerAsan - condition: succeeded('BuildDockerAsan') - jobs: - - template: .azure-pipelines/test-docker-sonic-vs-template.yml - parameters: - log_artifact_name: log-asan - gcov_artifact_name: sonic-gcov - sonic_slave: sonic-slave-bullseye - docker_sonic_vs_name: docker-sonic-vs-asan - asan: true - -- stage: Gcov - condition: false - dependsOn: Test - jobs: - - template: .azure-pipelines/gcov.yml - parameters: - arch: amd64 - sonic_slave: sonic-slave-bullseye - swss_common_artifact_name: sonic-swss-common - sairedis_artifact_name: sonic-sairedis - swss_artifact_name: sonic-swss - artifact_name: sonic-gcov - archive_gcov: true diff --git a/tests/test_acl.py b/tests/test_acl.py deleted file mode 100644 index ed5789b2b0..0000000000 --- a/tests/test_acl.py +++ /dev/null @@ -1,927 +0,0 @@ -import pytest -from requests import request -import time - -L3_TABLE_TYPE = "L3" -L3_TABLE_NAME = "L3_TEST" -L3_BIND_PORTS = ["Ethernet0", "Ethernet4", "Ethernet8", "Ethernet12"] -L3_RULE_NAME = "L3_TEST_RULE" - -L3V6_TABLE_TYPE = "L3V6" -L3V6_TABLE_NAME = "L3_V6_TEST" -L3V6_BIND_PORTS = ["Ethernet0", "Ethernet4", "Ethernet8"] -L3V6_RULE_NAME = "L3V6_TEST_RULE" - -MCLAG_TABLE_TYPE = "MCLAG" -MCLAG_TABLE_NAME = "MCLAG_TEST" -MCLAG_BIND_PORTS = ["Ethernet0", "Ethernet4", "Ethernet8", "Ethernet12"] -MCLAG_RULE_NAME = "MCLAG_TEST_RULE" - -MIRROR_TABLE_TYPE = "MIRROR" -MIRROR_TABLE_NAME = "MIRROR_TEST" -MIRROR_BIND_PORTS = ["Ethernet0", "Ethernet4", "Ethernet8", "Ethernet12"] -MIRROR_RULE_NAME = "MIRROR_TEST_RULE" - -PFCWD_TABLE_TYPE = "PFCWD" -PFCWD_TABLE_NAME = "PFCWD_TEST" -PFCWD_BIND_PORTS = ["Ethernet0", "Ethernet4", "Ethernet8", "Ethernet12"] -class TestAcl: - @pytest.fixture(params=['ingress', 'egress']) - def l3_acl_table(self, dvs_acl, request): - try: - dvs_acl.create_acl_table(L3_TABLE_NAME, L3_TABLE_TYPE, L3_BIND_PORTS, stage=request.param) - yield dvs_acl.get_acl_table_ids(1)[0], request.param - finally: - dvs_acl.remove_acl_table(L3_TABLE_NAME) - dvs_acl.verify_acl_table_count(0) - - @pytest.fixture - def l3v6_acl_table(self, dvs_acl): - try: - dvs_acl.create_acl_table(L3V6_TABLE_NAME, - L3V6_TABLE_TYPE, - L3V6_BIND_PORTS) - yield dvs_acl.get_acl_table_ids(1)[0] - finally: - dvs_acl.remove_acl_table(L3V6_TABLE_NAME) - dvs_acl.verify_acl_table_count(0) - - @pytest.fixture - def mclag_acl_table(self, dvs_acl): - try: - dvs_acl.create_acl_table(MCLAG_TABLE_NAME, MCLAG_TABLE_TYPE, MCLAG_BIND_PORTS) - yield dvs_acl.get_acl_table_ids(1)[0] - finally: - dvs_acl.remove_acl_table(MCLAG_TABLE_NAME) - dvs_acl.verify_acl_table_count(0) - - @pytest.fixture - def mirror_acl_table(self, dvs_acl): - try: - dvs_acl.create_acl_table(MIRROR_TABLE_NAME, MIRROR_TABLE_TYPE, MIRROR_BIND_PORTS) - yield dvs_acl.get_acl_table_ids(1)[0] - finally: - dvs_acl.remove_acl_table(MIRROR_TABLE_NAME) - dvs_acl.verify_acl_table_count(0) - - @pytest.fixture(params=['ingress', 'egress']) - def pfcwd_acl_table(self, dvs_acl, request): - try: - dvs_acl.create_acl_table(PFCWD_TABLE_NAME, PFCWD_TABLE_TYPE, PFCWD_BIND_PORTS, request.param) - yield dvs_acl.get_acl_table_ids(1)[0], request.param - finally: - dvs_acl.remove_acl_table(PFCWD_TABLE_NAME) - dvs_acl.verify_acl_table_count(0) - - @pytest.fixture - def setup_teardown_neighbor(self, dvs): - try: - # NOTE: set_interface_status has a dependency on cdb within dvs, - # so we still need to setup the db. This should be refactored. - dvs.setup_db() - - # Bring up an IP interface with a neighbor - dvs.set_interface_status("Ethernet4", "up") - dvs.add_ip_address("Ethernet4", "10.0.0.1/24") - dvs.add_neighbor("Ethernet4", "10.0.0.2", "00:01:02:03:04:05") - - yield dvs.get_asic_db().wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP", 1)[0] - finally: - # Clean up the IP interface and neighbor - dvs.remove_neighbor("Ethernet4", "10.0.0.2") - dvs.remove_ip_address("Ethernet4", "10.0.0.1/24") - dvs.set_interface_status("Ethernet4", "down") - - def test_AclTableCreationDeletion(self, dvs_acl): - try: - dvs_acl.create_acl_table(L3_TABLE_NAME, L3_TABLE_TYPE, L3_BIND_PORTS) - - acl_table_id = dvs_acl.get_acl_table_ids(1)[0] - acl_table_group_ids = dvs_acl.get_acl_table_group_ids(len(L3_BIND_PORTS)) - - dvs_acl.verify_acl_table_group_members(acl_table_id, acl_table_group_ids, 1) - dvs_acl.verify_acl_table_port_binding(acl_table_id, L3_BIND_PORTS, 1) - # Verify status is written into STATE_DB - dvs_acl.verify_acl_table_status(L3_TABLE_NAME, "Active") - finally: - dvs_acl.remove_acl_table(L3_TABLE_NAME) - dvs_acl.verify_acl_table_count(0) - # Verify the STATE_DB entry is removed - dvs_acl.verify_acl_table_status(L3_TABLE_NAME, None) - - def test_InvalidAclTableCreationDeletion(self, dvs_acl): - try: - dvs_acl.create_acl_table("INVALID_ACL_TABLE", L3_TABLE_TYPE, "dummy_port", "invalid_stage") - # Verify status is written into STATE_DB - dvs_acl.verify_acl_table_status("INVALID_ACL_TABLE", "Inactive") - finally: - dvs_acl.remove_acl_table("INVALID_ACL_TABLE") - dvs_acl.verify_acl_table_count(0) - # Verify the STATE_DB entry is removed - dvs_acl.verify_acl_table_status("INVALID_ACL_TABLE", None) - - def test_InvalidAclRuleCreation(self, dvs_acl, l3_acl_table): - config_qualifiers = {"INVALID_QUALIFIER": "TEST"} - - dvs_acl.create_acl_rule(L3_TABLE_NAME, "INVALID_RULE", config_qualifiers) - # Verify status is written into STATE_DB - dvs_acl.verify_acl_rule_status(L3_TABLE_NAME, "INVALID_RULE", "Inactive") - - dvs_acl.remove_acl_rule(L3_TABLE_NAME, "INVALID_RULE") - # Verify the STATE_DB entry is removed - dvs_acl.verify_acl_rule_status(L3_TABLE_NAME, "INVALID_RULE", None) - dvs_acl.verify_no_acl_rules() - - def test_AclRuleUpdate(self, dvs_acl, l3_acl_table): - """The test is to verify there is no duplicated flex counter when updating an ACL rule - """ - config_qualifiers = {"SRC_IP": "10.10.10.10/32"} - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_SRC_IP": dvs_acl.get_simple_qualifier_comparator("10.10.10.10&mask:255.255.255.255") - } - - dvs_acl.create_acl_rule(L3_TABLE_NAME, L3_RULE_NAME, config_qualifiers) - dvs_acl.verify_acl_rule(expected_sai_qualifiers) - - acl_rule_id = dvs_acl.get_acl_rule_id() - counter_id = dvs_acl.get_acl_counter_oid() - - new_config_qualifiers = {"SRC_IP": "10.10.10.11/32"} - new_expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_SRC_IP": dvs_acl.get_simple_qualifier_comparator("10.10.10.11&mask:255.255.255.255") - } - dvs_acl.update_acl_rule(L3_TABLE_NAME, L3_RULE_NAME, new_config_qualifiers) - # Verify the rule has been updated - retry = 5 - while dvs_acl.get_acl_rule_id() == acl_rule_id and retry >= 0: - retry -= 1 - time.sleep(1) - assert retry > 0 - dvs_acl.verify_acl_rule(new_expected_sai_qualifiers) - # Verify the previous counter is removed - if counter_id: - dvs_acl.check_acl_counter_not_in_counters_map(counter_id) - dvs_acl.remove_acl_rule(L3_TABLE_NAME, L3_RULE_NAME) - dvs_acl.verify_no_acl_rules() - - def test_AclRuleL4SrcPort(self, dvs_acl, l3_acl_table): - config_qualifiers = {"L4_SRC_PORT": "65000"} - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_L4_SRC_PORT": dvs_acl.get_simple_qualifier_comparator("65000&mask:0xffff") - } - - dvs_acl.create_acl_rule(L3_TABLE_NAME, L3_RULE_NAME, config_qualifiers) - dvs_acl.verify_acl_rule(expected_sai_qualifiers) - # Verify status is written into STATE_DB - dvs_acl.verify_acl_rule_status(L3_TABLE_NAME, L3_RULE_NAME, "Active") - - dvs_acl.remove_acl_rule(L3_TABLE_NAME, L3_RULE_NAME) - # Verify the STATE_DB entry is removed - dvs_acl.verify_acl_rule_status(L3_TABLE_NAME, L3_RULE_NAME, None) - dvs_acl.verify_no_acl_rules() - - def test_AclRuleIpProtocol(self, dvs_acl, l3_acl_table): - config_qualifiers = {"IP_PROTOCOL": "6"} - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_IP_PROTOCOL": dvs_acl.get_simple_qualifier_comparator("6&mask:0xff") - } - - dvs_acl.create_acl_rule(L3_TABLE_NAME, L3_RULE_NAME, config_qualifiers) - dvs_acl.verify_acl_rule(expected_sai_qualifiers) - # Verify status is written into STATE_DB - dvs_acl.verify_acl_rule_status(L3_TABLE_NAME, L3_RULE_NAME, "Active") - - dvs_acl.remove_acl_rule(L3_TABLE_NAME, L3_RULE_NAME) - # Verify the STATE_DB entry is removed - dvs_acl.verify_acl_rule_status(L3_TABLE_NAME, L3_RULE_NAME, None) - dvs_acl.verify_no_acl_rules() - - def test_AclRuleTCPProtocolAppendedForTCPFlags(self, dvs_acl, l3_acl_table): - """ - Verify TCP Protocol number (6) will be appended for ACL rules matching TCP_FLAGS - """ - config_qualifiers = {"TCP_FLAGS": "0x07/0x3f"} - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_TCP_FLAGS": - dvs_acl.get_simple_qualifier_comparator("7&mask:0x3f"), - "SAI_ACL_ENTRY_ATTR_FIELD_IP_PROTOCOL": - dvs_acl.get_simple_qualifier_comparator("6&mask:0xff") - } - dvs_acl.create_acl_rule(L3_TABLE_NAME, L3_RULE_NAME, config_qualifiers) - dvs_acl.verify_acl_rule(expected_sai_qualifiers) - # Verify status is written into STATE_DB - dvs_acl.verify_acl_rule_status(L3_TABLE_NAME, L3_RULE_NAME, "Active") - - dvs_acl.remove_acl_rule(L3_TABLE_NAME, L3_RULE_NAME) - # Verify the STATE_DB entry is removed - dvs_acl.verify_acl_rule_status(L3_TABLE_NAME, L3_RULE_NAME, None) - dvs_acl.verify_no_acl_rules() - - def test_AclRuleNextHeader(self, dvs_acl, l3_acl_table): - config_qualifiers = {"NEXT_HEADER": "6"} - - # Shouldn't allow NEXT_HEADER on vanilla L3 tables. - dvs_acl.create_acl_rule(L3_TABLE_NAME, L3_RULE_NAME, config_qualifiers) - # Verify status is written into STATE_DB - dvs_acl.verify_acl_rule_status(L3_TABLE_NAME, L3_RULE_NAME, "Inactive") - dvs_acl.verify_no_acl_rules() - - dvs_acl.remove_acl_rule(L3_TABLE_NAME, L3_RULE_NAME) - # Verify the STATE_DB entry is removed - dvs_acl.verify_acl_rule_status(L3_TABLE_NAME, L3_RULE_NAME, None) - dvs_acl.verify_no_acl_rules() - - def test_V6AclRuleNextHeaderAppendedForTCPFlags(self, dvs_acl, l3v6_acl_table): - """ - Verify next heder (6) will be appended for IPv6 ACL rules matching TCP_FLAGS - """ - config_qualifiers = {"TCP_FLAGS": "0x07/0x3f"} - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_TCP_FLAGS": - dvs_acl.get_simple_qualifier_comparator("7&mask:0x3f"), - "SAI_ACL_ENTRY_ATTR_FIELD_IPV6_NEXT_HEADER": - dvs_acl.get_simple_qualifier_comparator("6&mask:0xff") - } - - dvs_acl.create_acl_rule(L3V6_TABLE_NAME, L3V6_RULE_NAME, config_qualifiers) - dvs_acl.verify_acl_rule(expected_sai_qualifiers) - # Verify status is written into STATE_DB - dvs_acl.verify_acl_rule_status(L3V6_TABLE_NAME, L3V6_RULE_NAME, "Active") - - dvs_acl.remove_acl_rule(L3V6_TABLE_NAME, L3V6_RULE_NAME) - # Verify the STATE_DB entry is removed - dvs_acl.verify_acl_rule_status(L3V6_TABLE_NAME, L3V6_RULE_NAME, None) - dvs_acl.verify_no_acl_rules() - - def test_AclRuleInPorts(self, dvs_acl, mirror_acl_table): - """ - Verify IN_PORTS matches on ACL rule. - Using MIRROR table type for IN_PORTS matches. - """ - config_qualifiers = { - "IN_PORTS": "Ethernet8,Ethernet12", - } - - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_IN_PORTS": dvs_acl.get_port_list_comparator(["Ethernet8", "Ethernet12"]) - } - - dvs_acl.create_acl_rule(MIRROR_TABLE_NAME, MIRROR_RULE_NAME, config_qualifiers) - # Verify status is written into STATE_DB - dvs_acl.verify_acl_rule_status(MIRROR_TABLE_NAME, MIRROR_RULE_NAME, "Active") - dvs_acl.verify_acl_rule(expected_sai_qualifiers) - - dvs_acl.remove_acl_rule(MIRROR_TABLE_NAME, MIRROR_RULE_NAME) - # Verify the STATE_DB entry is removed - dvs_acl.verify_acl_rule_status(MIRROR_TABLE_NAME, MIRROR_RULE_NAME, None) - dvs_acl.verify_no_acl_rules() - - def test_AclRuleOutPorts(self, dvs_acl, mclag_acl_table): - """ - Verify OUT_PORTS matches on ACL rule. - Using MCLAG table type for OUT_PORTS matches. - """ - config_qualifiers = { - "OUT_PORTS": "Ethernet8,Ethernet12", - } - - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_OUT_PORTS": dvs_acl.get_port_list_comparator(["Ethernet8", "Ethernet12"]) - } - - dvs_acl.create_acl_rule(MCLAG_TABLE_NAME, MCLAG_RULE_NAME, config_qualifiers) - dvs_acl.verify_acl_rule(expected_sai_qualifiers) - # Verify status is written into STATE_DB - dvs_acl.verify_acl_rule_status(MCLAG_TABLE_NAME, MCLAG_RULE_NAME, "Active") - - dvs_acl.remove_acl_rule(MCLAG_TABLE_NAME, MCLAG_RULE_NAME) - # Verify the STATE_DB entry is removed - dvs_acl.verify_acl_rule_status(MCLAG_TABLE_NAME, MCLAG_RULE_NAME, None) - dvs_acl.verify_no_acl_rules() - - def test_AclRuleInPortsNonExistingInterface(self, dvs_acl, mirror_acl_table): - """ - Using MIRROR table type as it has IN_PORTS matches. - """ - config_qualifiers = { - "IN_PORTS": "FOO_BAR_BAZ" - } - - dvs_acl.create_acl_rule(MIRROR_TABLE_NAME, MIRROR_RULE_NAME, config_qualifiers) - # Verify status is written into STATE_DB - dvs_acl.verify_acl_rule_status(MIRROR_TABLE_NAME, MIRROR_RULE_NAME, "Inactive") - dvs_acl.verify_no_acl_rules() - dvs_acl.remove_acl_rule(MIRROR_TABLE_NAME, MIRROR_RULE_NAME) - # Verify the STATE_DB entry is removed - dvs_acl.verify_acl_rule_status(MIRROR_TABLE_NAME, MIRROR_RULE_NAME, None) - - def test_AclRuleOutPortsNonExistingInterface(self, dvs_acl, mclag_acl_table): - """ - Using MCLAG table type as it has OUT_PORTS matches. - """ - config_qualifiers = { - "OUT_PORTS": "FOO_BAR_BAZ" - } - - dvs_acl.create_acl_rule(MCLAG_TABLE_NAME, MCLAG_RULE_NAME, config_qualifiers) - # Verify status is written into STATE_DB - dvs_acl.verify_acl_rule_status(MCLAG_TABLE_NAME, MCLAG_RULE_NAME, "Inactive") - dvs_acl.verify_no_acl_rules() - dvs_acl.remove_acl_rule(MCLAG_TABLE_NAME, MCLAG_RULE_NAME) - # Verify the STATE_DB entry is removed - dvs_acl.verify_acl_rule_status(MCLAG_TABLE_NAME, MCLAG_RULE_NAME, None) - - def test_AclRuleVlanId(self, dvs_acl, l3_acl_table): - config_qualifiers = {"VLAN_ID": "100"} - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_OUTER_VLAN_ID": dvs_acl.get_simple_qualifier_comparator("100&mask:0xfff") - } - - dvs_acl.create_acl_rule(L3_TABLE_NAME, L3_RULE_NAME, config_qualifiers) - # Verify status is written into STATE_DB - dvs_acl.verify_acl_rule_status(L3_TABLE_NAME, L3_RULE_NAME, "Active") - dvs_acl.verify_acl_rule(expected_sai_qualifiers) - - dvs_acl.remove_acl_rule(L3_TABLE_NAME, L3_RULE_NAME) - # Verify the STATE_DB entry is removed - dvs_acl.verify_acl_rule_status(L3_TABLE_NAME, L3_RULE_NAME, None) - dvs_acl.verify_no_acl_rules() - - def test_AclRuleIPTypeNonIpv4(self, dvs_acl, l3_acl_table): - config_qualifiers = {"IP_TYPE": "NON_IPv4"} - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_ACL_IP_TYPE": dvs_acl.get_simple_qualifier_comparator("SAI_ACL_IP_TYPE_NON_IPV4&mask:0xffffffffffffffff") - } - - dvs_acl.create_acl_rule(L3_TABLE_NAME, L3_RULE_NAME, config_qualifiers) - # Verify status is written into STATE_DB - dvs_acl.verify_acl_rule_status(L3_TABLE_NAME, L3_RULE_NAME, "Active") - dvs_acl.verify_acl_rule(expected_sai_qualifiers) - - dvs_acl.remove_acl_rule(L3_TABLE_NAME, L3_RULE_NAME) - # Verify the STATE_DB entry is removed - dvs_acl.verify_acl_rule_status(L3_TABLE_NAME, L3_RULE_NAME, None) - dvs_acl.verify_no_acl_rules() - - def test_V6AclTableCreationDeletion(self, dvs_acl): - try: - dvs_acl.create_acl_table(L3V6_TABLE_NAME, - L3V6_TABLE_TYPE, - L3V6_BIND_PORTS) - - acl_table_id = dvs_acl.get_acl_table_ids(1)[0] - acl_table_group_ids = dvs_acl.get_acl_table_group_ids(len(L3V6_BIND_PORTS)) - dvs_acl.verify_acl_table_group_members(acl_table_id, acl_table_group_ids, 1) - dvs_acl.verify_acl_table_port_binding(acl_table_id, L3V6_BIND_PORTS, 1) - # Verify status is written into STATE_DB - dvs_acl.verify_acl_table_status(L3V6_TABLE_NAME, "Active") - finally: - dvs_acl.remove_acl_table(L3V6_TABLE_NAME) - # Verify the STATE_DB entry is cleared - dvs_acl.verify_acl_table_status(L3V6_TABLE_NAME, None) - dvs_acl.verify_acl_table_count(0) - - def test_V6AclRuleIPTypeNonIpv6(self, dvs_acl, l3v6_acl_table): - config_qualifiers = {"IP_TYPE": "NON_IPv6"} - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_ACL_IP_TYPE": dvs_acl.get_simple_qualifier_comparator("SAI_ACL_IP_TYPE_NON_IPV6&mask:0xffffffffffffffff") - } - - dvs_acl.create_acl_rule(L3V6_TABLE_NAME, L3V6_RULE_NAME, config_qualifiers) - # Verify status is written into STATE_DB - dvs_acl.verify_acl_rule_status(L3V6_TABLE_NAME, L3V6_RULE_NAME, "Active") - dvs_acl.verify_acl_rule(expected_sai_qualifiers) - - dvs_acl.remove_acl_rule(L3V6_TABLE_NAME, L3V6_RULE_NAME) - # Verify the STATE_DB entry is removed - dvs_acl.verify_acl_rule_status(L3V6_TABLE_NAME, L3V6_RULE_NAME, None) - dvs_acl.verify_no_acl_rules() - - def test_V6AclRuleIPv6Any(self, dvs_acl, l3v6_acl_table): - config_qualifiers = {"IP_TYPE": "IPv6ANY"} - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_ACL_IP_TYPE": dvs_acl.get_simple_qualifier_comparator("SAI_ACL_IP_TYPE_IPV6ANY&mask:0xffffffffffffffff") - } - - dvs_acl.create_acl_rule(L3V6_TABLE_NAME, L3V6_RULE_NAME, config_qualifiers) - # Verify status is written into STATE_DB - dvs_acl.verify_acl_rule_status(L3V6_TABLE_NAME, L3V6_RULE_NAME, "Active") - dvs_acl.verify_acl_rule(expected_sai_qualifiers) - - dvs_acl.remove_acl_rule(L3V6_TABLE_NAME, L3V6_RULE_NAME) - # Verify the STATE_DB entry is removed - dvs_acl.verify_acl_rule_status(L3V6_TABLE_NAME, L3V6_RULE_NAME, None) - dvs_acl.verify_no_acl_rules() - - def test_V6AclRuleIPv6AnyDrop(self, dvs_acl, l3v6_acl_table): - config_qualifiers = {"IP_TYPE": "IPv6ANY"} - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_ACL_IP_TYPE": dvs_acl.get_simple_qualifier_comparator("SAI_ACL_IP_TYPE_IPV6ANY&mask:0xffffffffffffffff") - } - - dvs_acl.create_acl_rule(L3V6_TABLE_NAME, - L3V6_RULE_NAME, - config_qualifiers, - action="DROP") - dvs_acl.verify_acl_rule(expected_sai_qualifiers, action="DROP") - # Verify status is written into STATE_DB - dvs_acl.verify_acl_rule_status(L3V6_TABLE_NAME, L3V6_RULE_NAME, "Active") - - dvs_acl.remove_acl_rule(L3V6_TABLE_NAME, L3V6_RULE_NAME) - # Verify the STATE_DB entry is removed - dvs_acl.verify_acl_rule_status(L3V6_TABLE_NAME, L3V6_RULE_NAME, None) - dvs_acl.verify_no_acl_rules() - - # This test validates that backwards compatibility works as expected, it should - # be converted to a negative test after the 202012 release. - def test_V6AclRuleIpProtocol(self, dvs_acl, l3v6_acl_table): - config_qualifiers = {"IP_PROTOCOL": "6"} - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_IPV6_NEXT_HEADER": dvs_acl.get_simple_qualifier_comparator("6&mask:0xff") - } - - dvs_acl.create_acl_rule(L3V6_TABLE_NAME, L3V6_RULE_NAME, config_qualifiers) - dvs_acl.verify_acl_rule(expected_sai_qualifiers) - # Verify status is written into STATE_DB - dvs_acl.verify_acl_rule_status(L3V6_TABLE_NAME, L3V6_RULE_NAME, "Active") - - dvs_acl.remove_acl_rule(L3V6_TABLE_NAME, L3V6_RULE_NAME) - # Verify the STATE_DB entry is removed - dvs_acl.verify_acl_rule_status(L3V6_TABLE_NAME, L3V6_RULE_NAME, None) - dvs_acl.verify_no_acl_rules() - - def test_V6AclRuleNextHeader(self, dvs_acl, l3v6_acl_table): - config_qualifiers = {"NEXT_HEADER": "6"} - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_IPV6_NEXT_HEADER": dvs_acl.get_simple_qualifier_comparator("6&mask:0xff") - } - - dvs_acl.create_acl_rule(L3V6_TABLE_NAME, L3V6_RULE_NAME, config_qualifiers) - dvs_acl.verify_acl_rule(expected_sai_qualifiers) - # Verify status is written into STATE_DB - dvs_acl.verify_acl_rule_status(L3V6_TABLE_NAME, L3V6_RULE_NAME, "Active") - - dvs_acl.remove_acl_rule(L3V6_TABLE_NAME, L3V6_RULE_NAME) - # Verify the STATE_DB entry is removed - dvs_acl.verify_acl_rule_status(L3V6_TABLE_NAME, L3V6_RULE_NAME, None) - dvs_acl.verify_no_acl_rules() - - def test_V6AclRuleSrcIPv6(self, dvs_acl, l3v6_acl_table): - - config_qualifiers = {"SRC_IPV6": "2777::0/64"} - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_SRC_IPV6": dvs_acl.get_simple_qualifier_comparator("2777::&mask:ffff:ffff:ffff:ffff::") - } - - dvs_acl.create_acl_rule(L3V6_TABLE_NAME, L3V6_RULE_NAME, config_qualifiers) - dvs_acl.verify_acl_rule(expected_sai_qualifiers) - # Verify status is written into STATE_DB - dvs_acl.verify_acl_rule_status(L3V6_TABLE_NAME, L3V6_RULE_NAME, "Active") - - dvs_acl.remove_acl_rule(L3V6_TABLE_NAME, L3V6_RULE_NAME) - # Verify the STATE_DB entry is removed - dvs_acl.verify_acl_rule_status(L3V6_TABLE_NAME, L3V6_RULE_NAME, None) - dvs_acl.verify_no_acl_rules() - - def test_V6AclRuleDstIPv6(self, dvs_acl, l3v6_acl_table): - config_qualifiers = {"DST_IPV6": "2002::2/128"} - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_DST_IPV6": dvs_acl.get_simple_qualifier_comparator("2002::2&mask:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff") - } - - dvs_acl.create_acl_rule(L3V6_TABLE_NAME, L3V6_RULE_NAME, config_qualifiers) - dvs_acl.verify_acl_rule(expected_sai_qualifiers) - # Verify status is written into STATE_DB - dvs_acl.verify_acl_rule_status(L3V6_TABLE_NAME, L3V6_RULE_NAME, "Active") - - dvs_acl.remove_acl_rule(L3V6_TABLE_NAME, L3V6_RULE_NAME) - # Verify the STATE_DB entry is removed - dvs_acl.verify_acl_rule_status(L3V6_TABLE_NAME, L3V6_RULE_NAME, None) - dvs_acl.verify_no_acl_rules() - - def test_V6AclRuleL4SrcPort(self, dvs_acl, l3v6_acl_table): - config_qualifiers = {"L4_SRC_PORT": "65000"} - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_L4_SRC_PORT": dvs_acl.get_simple_qualifier_comparator("65000&mask:0xffff") - } - - dvs_acl.create_acl_rule(L3V6_TABLE_NAME, L3V6_RULE_NAME, config_qualifiers) - dvs_acl.verify_acl_rule(expected_sai_qualifiers) - # Verify status is written into STATE_DB - dvs_acl.verify_acl_rule_status(L3V6_TABLE_NAME, L3V6_RULE_NAME, "Active") - - dvs_acl.remove_acl_rule(L3V6_TABLE_NAME, L3V6_RULE_NAME) - # Verify the STATE_DB entry is removed - dvs_acl.verify_acl_rule_status(L3V6_TABLE_NAME, L3V6_RULE_NAME, None) - dvs_acl.verify_no_acl_rules() - - def test_V6AclRuleL4DstPort(self, dvs_acl, l3v6_acl_table): - config_qualifiers = {"L4_DST_PORT": "65001"} - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_L4_DST_PORT": dvs_acl.get_simple_qualifier_comparator("65001&mask:0xffff") - } - - dvs_acl.create_acl_rule(L3V6_TABLE_NAME, L3V6_RULE_NAME, config_qualifiers) - dvs_acl.verify_acl_rule(expected_sai_qualifiers) - # Verify status is written into STATE_DB - dvs_acl.verify_acl_rule_status(L3V6_TABLE_NAME, L3V6_RULE_NAME, "Active") - - dvs_acl.remove_acl_rule(L3V6_TABLE_NAME, L3V6_RULE_NAME) - # Verify the STATE_DB entry is removed - dvs_acl.verify_acl_rule_status(L3V6_TABLE_NAME, L3V6_RULE_NAME, None) - dvs_acl.verify_no_acl_rules() - - def test_V6AclRuleL4SrcPortRange(self, dvs_acl, l3v6_acl_table): - config_qualifiers = {"L4_SRC_PORT_RANGE": "1-100"} - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_ACL_RANGE_TYPE": dvs_acl.get_acl_range_comparator("SAI_ACL_RANGE_TYPE_L4_SRC_PORT_RANGE", "1,100") - } - - dvs_acl.create_acl_rule(L3V6_TABLE_NAME, L3V6_RULE_NAME, config_qualifiers) - dvs_acl.verify_acl_rule(expected_sai_qualifiers) - # Verify status is written into STATE_DB - dvs_acl.verify_acl_rule_status(L3V6_TABLE_NAME, L3V6_RULE_NAME, "Active") - - dvs_acl.remove_acl_rule(L3V6_TABLE_NAME, L3V6_RULE_NAME) - # Verify the STATE_DB entry is removed - dvs_acl.verify_acl_rule_status(L3V6_TABLE_NAME, L3V6_RULE_NAME, None) - dvs_acl.verify_no_acl_rules() - - def test_V6AclRuleL4DstPortRange(self, dvs_acl, l3v6_acl_table): - config_qualifiers = {"L4_DST_PORT_RANGE": "101-200"} - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_ACL_RANGE_TYPE": dvs_acl.get_acl_range_comparator("SAI_ACL_RANGE_TYPE_L4_DST_PORT_RANGE", "101,200") - } - - dvs_acl.create_acl_rule(L3V6_TABLE_NAME, L3V6_RULE_NAME, config_qualifiers) - dvs_acl.verify_acl_rule(expected_sai_qualifiers) - # Verify status is written into STATE_DB - dvs_acl.verify_acl_rule_status(L3V6_TABLE_NAME, L3V6_RULE_NAME, "Active") - - dvs_acl.remove_acl_rule(L3V6_TABLE_NAME, L3V6_RULE_NAME) - # Verify the STATE_DB entry is removed - dvs_acl.verify_acl_rule_status(L3V6_TABLE_NAME, L3V6_RULE_NAME, None) - dvs_acl.verify_no_acl_rules() - - def test_V6AclRuleVlanId(self, dvs_acl, l3v6_acl_table): - config_qualifiers = {"VLAN_ID": "100"} - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_OUTER_VLAN_ID": dvs_acl.get_simple_qualifier_comparator("100&mask:0xfff") - } - - dvs_acl.create_acl_rule(L3V6_TABLE_NAME, L3V6_RULE_NAME, config_qualifiers) - dvs_acl.verify_acl_rule(expected_sai_qualifiers) - # Verify status is written into STATE_DB - dvs_acl.verify_acl_rule_status(L3V6_TABLE_NAME, L3V6_RULE_NAME, "Active") - - dvs_acl.remove_acl_rule(L3V6_TABLE_NAME, L3V6_RULE_NAME) - # Verify the STATE_DB entry is removed - dvs_acl.verify_acl_rule_status(L3V6_TABLE_NAME, L3V6_RULE_NAME, None) - dvs_acl.verify_no_acl_rules() - - def test_InsertAclRuleBetweenPriorities(self, dvs_acl, l3_acl_table): - rule_priorities = ["10", "20", "30", "40"] - - config_qualifiers = { - "10": {"SRC_IP": "10.0.0.0/32"}, - "20": {"DST_IP": "104.44.94.0/23"}, - "30": {"DST_IP": "192.168.0.16/32"}, - "40": {"DST_IP": "100.64.0.0/10"}, - } - - config_actions = { - "10": "DROP", - "20": "DROP", - "30": "DROP", - "40": "FORWARD", - } - - expected_sai_qualifiers = { - "10": {"SAI_ACL_ENTRY_ATTR_FIELD_SRC_IP": dvs_acl.get_simple_qualifier_comparator("10.0.0.0&mask:255.255.255.255")}, - "20": {"SAI_ACL_ENTRY_ATTR_FIELD_DST_IP": dvs_acl.get_simple_qualifier_comparator("104.44.94.0&mask:255.255.254.0")}, - "30": {"SAI_ACL_ENTRY_ATTR_FIELD_DST_IP": dvs_acl.get_simple_qualifier_comparator("192.168.0.16&mask:255.255.255.255")}, - "40": {"SAI_ACL_ENTRY_ATTR_FIELD_DST_IP": dvs_acl.get_simple_qualifier_comparator("100.64.0.0&mask:255.192.0.0")}, - } - - for rule in rule_priorities: - dvs_acl.create_acl_rule(L3_TABLE_NAME, - f"PRIORITY_TEST_RULE_{rule}", - config_qualifiers[rule], action=config_actions[rule], - priority=rule) - # Verify status is written into STATE_DB - dvs_acl.verify_acl_rule_status(L3_TABLE_NAME, f"PRIORITY_TEST_RULE_{rule}", "Active") - - dvs_acl.verify_acl_rule_set(rule_priorities, config_actions, expected_sai_qualifiers) - - odd_priority = "21" - odd_rule = {"ETHER_TYPE": "4660"} - odd_sai_qualifier = {"SAI_ACL_ENTRY_ATTR_FIELD_ETHER_TYPE": dvs_acl.get_simple_qualifier_comparator("4660&mask:0xffff")} - - rule_priorities.append(odd_priority) - config_actions[odd_priority] = "DROP" - expected_sai_qualifiers[odd_priority] = odd_sai_qualifier - - dvs_acl.create_acl_rule(L3_TABLE_NAME, - f"PRIORITY_TEST_RULE_{odd_priority}", - odd_rule, - action="DROP", - priority=odd_priority) - dvs_acl.verify_acl_rule_set(rule_priorities, config_actions, expected_sai_qualifiers) - # Verify status is written into STATE_DB - dvs_acl.verify_acl_rule_status(L3_TABLE_NAME, f"PRIORITY_TEST_RULE_{odd_priority}", "Active") - for rule in rule_priorities: - dvs_acl.remove_acl_rule(L3_TABLE_NAME, f"PRIORITY_TEST_RULE_{rule}") - # Verify the STATE_DB entry is removed - dvs_acl.verify_acl_rule_status(L3_TABLE_NAME, f"PRIORITY_TEST_RULE_{rule}", None) - dvs_acl.verify_no_acl_rules() - - def test_RulesWithDiffMaskLengths(self, dvs_acl, l3_acl_table): - rule_priorities = ["10", "20", "30", "40", "50", "60"] - - config_qualifiers = { - "10": {"SRC_IP": "23.103.0.0/18"}, - "20": {"SRC_IP": "104.44.94.0/23"}, - "30": {"DST_IP": "172.16.0.0/12"}, - "40": {"DST_IP": "100.64.0.0/10"}, - "50": {"DST_IP": "104.146.32.0/19"}, - "60": {"SRC_IP": "21.0.0.0/8"}, - } - - config_actions = { - "10": "FORWARD", - "20": "FORWARD", - "30": "FORWARD", - "40": "FORWARD", - "50": "FORWARD", - "60": "FORWARD", - } - - expected_sai_qualifiers = { - "10": {"SAI_ACL_ENTRY_ATTR_FIELD_SRC_IP": dvs_acl.get_simple_qualifier_comparator("23.103.0.0&mask:255.255.192.0")}, - "20": {"SAI_ACL_ENTRY_ATTR_FIELD_SRC_IP": dvs_acl.get_simple_qualifier_comparator("104.44.94.0&mask:255.255.254.0")}, - "30": {"SAI_ACL_ENTRY_ATTR_FIELD_DST_IP": dvs_acl.get_simple_qualifier_comparator("172.16.0.0&mask:255.240.0.0")}, - "40": {"SAI_ACL_ENTRY_ATTR_FIELD_DST_IP": dvs_acl.get_simple_qualifier_comparator("100.64.0.0&mask:255.192.0.0")}, - "50": {"SAI_ACL_ENTRY_ATTR_FIELD_DST_IP": dvs_acl.get_simple_qualifier_comparator("104.146.32.0&mask:255.255.224.0")}, - "60": {"SAI_ACL_ENTRY_ATTR_FIELD_SRC_IP": dvs_acl.get_simple_qualifier_comparator("21.0.0.0&mask:255.0.0.0")}, - } - - for rule in rule_priorities: - dvs_acl.create_acl_rule(L3_TABLE_NAME, - f"MASK_TEST_RULE_{rule}", - config_qualifiers[rule], - action=config_actions[rule], - priority=rule) - # Verify status is written into STATE_DB - dvs_acl.verify_acl_rule_status(L3_TABLE_NAME, f"MASK_TEST_RULE_{rule}", "Active") - dvs_acl.verify_acl_rule_set(rule_priorities, config_actions, expected_sai_qualifiers) - - for rule in rule_priorities: - dvs_acl.remove_acl_rule(L3_TABLE_NAME, f"MASK_TEST_RULE_{rule}") - # Verify the STATE_DB entry is removed - dvs_acl.verify_acl_rule_status(L3_TABLE_NAME, f"MASK_TEST_RULE_{rule}", None) - dvs_acl.verify_no_acl_rules() - - def test_AclRuleIcmp(self, dvs_acl, l3_acl_table): - config_qualifiers = { - "ICMP_TYPE": "8", - "ICMP_CODE": "9" - } - - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_ICMP_TYPE": dvs_acl.get_simple_qualifier_comparator("8&mask:0xff"), - "SAI_ACL_ENTRY_ATTR_FIELD_ICMP_CODE": dvs_acl.get_simple_qualifier_comparator("9&mask:0xff") - } - - dvs_acl.create_acl_rule(L3_TABLE_NAME, L3_RULE_NAME, config_qualifiers) - dvs_acl.verify_acl_rule(expected_sai_qualifiers) - # Verify status is written into STATE_DB - dvs_acl.verify_acl_rule_status(L3_TABLE_NAME, L3_RULE_NAME, "Active") - - dvs_acl.remove_acl_rule(L3_TABLE_NAME, L3_RULE_NAME) - # Verify the STATE_DB entry is removed - dvs_acl.verify_acl_rule_status(L3_TABLE_NAME, L3_RULE_NAME, None) - dvs_acl.verify_no_acl_rules() - - dvs_acl.remove_acl_table(L3_TABLE_NAME) - dvs_acl.verify_acl_table_count(0) - - def test_AclRuleIcmpV6(self, dvs_acl, l3v6_acl_table): - config_qualifiers = { - "ICMPV6_TYPE": "8", - "ICMPV6_CODE": "9" - } - - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_ICMPV6_TYPE": dvs_acl.get_simple_qualifier_comparator("8&mask:0xff"), - "SAI_ACL_ENTRY_ATTR_FIELD_ICMPV6_CODE": dvs_acl.get_simple_qualifier_comparator("9&mask:0xff") - } - - dvs_acl.create_acl_rule(L3V6_TABLE_NAME, L3V6_RULE_NAME, config_qualifiers) - dvs_acl.verify_acl_rule(expected_sai_qualifiers) - # Verify status is written into STATE_DB - dvs_acl.verify_acl_rule_status(L3V6_TABLE_NAME, L3V6_RULE_NAME, "Active") - - dvs_acl.remove_acl_rule(L3V6_TABLE_NAME, L3V6_RULE_NAME) - # Verify the STATE_DB entry is removed - dvs_acl.verify_acl_rule_status(L3V6_TABLE_NAME, L3V6_RULE_NAME, None) - dvs_acl.verify_no_acl_rules() - - def test_AclRuleRedirect(self, dvs, dvs_acl, l3_acl_table, setup_teardown_neighbor): - config_qualifiers = {"L4_SRC_PORT": "65000"} - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_L4_SRC_PORT": dvs_acl.get_simple_qualifier_comparator("65000&mask:0xffff") - } - - dvs_acl.create_redirect_acl_rule(L3_TABLE_NAME, - L3_RULE_NAME, - config_qualifiers, - intf="Ethernet4", - ip="10.0.0.2", - priority="20") - - next_hop_id = setup_teardown_neighbor - dvs_acl.verify_redirect_acl_rule(expected_sai_qualifiers, next_hop_id, priority="20") - # Verify status is written into STATE_DB - dvs_acl.verify_acl_rule_status(L3_TABLE_NAME, L3_RULE_NAME, "Active") - dvs_acl.remove_acl_rule(L3_TABLE_NAME, L3_RULE_NAME) - # Verify the STATE_DB entry is removed - dvs_acl.verify_acl_rule_status(L3_TABLE_NAME, L3_RULE_NAME, None) - dvs_acl.verify_no_acl_rules() - - dvs_acl.create_redirect_acl_rule(L3_TABLE_NAME, - L3_RULE_NAME, - config_qualifiers, - intf="Ethernet4", - priority="20") - - intf_id = dvs.asic_db.port_name_map["Ethernet4"] - dvs_acl.verify_redirect_acl_rule(expected_sai_qualifiers, intf_id, priority="20") - # Verify status is written into STATE_DB - dvs_acl.verify_acl_rule_status(L3_TABLE_NAME, L3_RULE_NAME, "Active") - dvs_acl.remove_acl_rule(L3_TABLE_NAME, L3_RULE_NAME) - # Verify the STATE_DB entry is removed - dvs_acl.verify_acl_rule_status(L3_TABLE_NAME, L3_RULE_NAME, None) - dvs_acl.verify_no_acl_rules() - - def test_AclTableMandatoryMatchFields(self, dvs, pfcwd_acl_table): - """ - The test case is to verify stage particular matching fields is applied - """ - table_oid, stage = pfcwd_acl_table - match_in_ports = False - entry = dvs.asic_db.wait_for_entry("ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE", table_oid) - for k, v in entry.items(): - if k == "SAI_ACL_TABLE_ATTR_FIELD_IN_PORTS" and v == "true": - match_in_ports = True - - if stage == "ingress": - assert match_in_ports - else: - assert not match_in_ports - - def test_AclTableMandatoryRangeFields(self, dvs, l3_acl_table): - """ - The test case is to verify range qualifier is not applied for egress ACL - """ - table_oid, stage = l3_acl_table - match_range_qualifier = False - entry = dvs.asic_db.wait_for_entry("ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE", table_oid) - for k, v in entry.items(): - if k == "SAI_ACL_TABLE_ATTR_FIELD_ACL_RANGE_TYPE" and v == "true": - match_range_qualifier = True - - assert not match_range_qualifier - -class TestAclCrmUtilization: - @pytest.fixture(scope="class", autouse=True) - def configure_crm_polling_interval_for_test(self, dvs): - dvs.crm_poll_set("1") - - yield - - dvs.crm_poll_set("300") - - def test_ValidateAclTableBindingCrmUtilization(self, dvs, dvs_acl): - counter_db = dvs.get_counters_db() - - crm_port_stats = counter_db.get_entry("CRM", "ACL_STATS:INGRESS:PORT") - initial_acl_table_port_bindings_used = int(crm_port_stats.get("crm_stats_acl_table_used", 0)) - - crm_lag_stats = counter_db.get_entry("CRM", "ACL_STATS:INGRESS:LAG") - initial_acl_table_lag_bindings_used = int(crm_lag_stats.get("crm_stats_acl_table_used", 0)) - - dvs_acl.create_acl_table(L3_TABLE_NAME, L3_TABLE_TYPE, L3_BIND_PORTS) - dvs_acl.verify_acl_table_count(1) - - counter_db.wait_for_field_match( - "CRM", - "ACL_STATS:INGRESS:PORT", - {"crm_stats_acl_table_used": str(initial_acl_table_port_bindings_used + 1)} - ) - - counter_db.wait_for_field_match( - "CRM", - "ACL_STATS:INGRESS:LAG", - {"crm_stats_acl_table_used": str(initial_acl_table_lag_bindings_used + 1)} - ) - - dvs_acl.remove_acl_table(L3_TABLE_NAME) - dvs_acl.verify_acl_table_count(0) - - counter_db.wait_for_field_match( - "CRM", - "ACL_STATS:INGRESS:PORT", - {"crm_stats_acl_table_used": str(initial_acl_table_port_bindings_used)} - ) - - counter_db.wait_for_field_match( - "CRM", - "ACL_STATS:INGRESS:LAG", - {"crm_stats_acl_table_used": str(initial_acl_table_lag_bindings_used)} - ) - - -# TODO: Need to improve the clean-up/post-checks for these tests as currently we can't run anything -# afterwards. -class TestAclRuleValidation: - """Test class for cases that check if orchagent corectly validates ACL rules input.""" - - ACL_STAGE_CAPABILITY_TABLE_NAME = "ACL_STAGE_CAPABILITY_TABLE" - ACL_ACTION_LIST_FIELD_NAME = "action_list" - - def get_acl_actions_supported(self, dvs_acl, stage): - switch = dvs_acl.state_db.wait_for_entry(self.ACL_STAGE_CAPABILITY_TABLE_NAME, stage.upper()) - supported_actions = switch.get(self.ACL_ACTION_LIST_FIELD_NAME, None) - - if supported_actions: - supported_actions = supported_actions.split(",") - else: - supported_actions = [] - - return supported_actions - - def test_AclActionValidation(self, dvs, dvs_acl): - """ - The test overrides R/O SAI_SWITCH_ATTR_ACL_STAGE_INGRESS/EGRESS switch attributes - to check the case when orchagent refuses to process rules with action that is not - supported by the ASIC. - """ - - stage_name_map = { - "ingress": "SAI_SWITCH_ATTR_ACL_STAGE_INGRESS", - "egress": "SAI_SWITCH_ATTR_ACL_STAGE_EGRESS", - } - - for stage in stage_name_map: - action_values = self.get_acl_actions_supported(dvs_acl, stage) - - # virtual switch supports all actions - assert action_values - assert "PACKET_ACTION" in action_values - - sai_acl_stage = stage_name_map[stage] - - # mock switch attribute in VS so only REDIRECT action is supported on this stage - dvs.setReadOnlyAttr("SAI_OBJECT_TYPE_SWITCH", - sai_acl_stage, - # FIXME: here should use sai_serialize_value() for acl_capability_t - # but it is not available in VS testing infrastructure - "false:1:SAI_ACL_ACTION_TYPE_REDIRECT") - - # restart SWSS so orchagent will query updated switch attributes - dvs.stop_swss() - dvs.start_swss() - # reinit ASIC DB validator object - dvs.init_asic_db_validator() - - action_values = self.get_acl_actions_supported(dvs_acl, stage) - # Now, PACKET_ACTION is not supported and REDIRECT_ACTION is supported - assert "PACKET_ACTION" not in action_values - assert "REDIRECT_ACTION" in action_values - - # try to create a forward rule - try: - dvs_acl.create_acl_table(L3_TABLE_NAME, - L3_TABLE_TYPE, - L3_BIND_PORTS, - stage=stage) - - config_qualifiers = { - "ICMP_TYPE": "8" - } - - dvs_acl.create_acl_rule(L3_TABLE_NAME, L3_RULE_NAME, config_qualifiers) - dvs_acl.verify_no_acl_rules() - finally: - dvs_acl.remove_acl_rule(L3_TABLE_NAME, L3_RULE_NAME) - dvs_acl.remove_acl_table(L3_TABLE_NAME) - - dvs.runcmd("supervisorctl restart syncd") - dvs.stop_swss() - dvs.start_swss() - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_acl_ctrl.py b/tests/test_acl_ctrl.py deleted file mode 100644 index 7d8eea3153..0000000000 --- a/tests/test_acl_ctrl.py +++ /dev/null @@ -1,27 +0,0 @@ -TABLE_NAME = "CTRL_ACL_TEST" -RULE_NAME = "CTRL_ACL_TEST_RULE" - - -class TestPortChannelAcl: - def test_AclCtrl(self, dvs_acl): - # Create ACL table and ACL rule - dvs_acl.create_control_plane_acl_table(TABLE_NAME, ["SNMP"]) - dvs_acl.create_acl_rule(TABLE_NAME, RULE_NAME, {"L4_SRC_PORT": "8888"}, priority="88") - - # Verify that no ASIC rules are created - dvs_acl.verify_acl_table_count(0) - dvs_acl.verify_no_acl_rules() - - # Cleanup ACL data from Config DB - dvs_acl.remove_acl_rule(TABLE_NAME, RULE_NAME) - dvs_acl.remove_acl_table(TABLE_NAME) - - # Verify that the ASIC DB is clean - dvs_acl.verify_acl_table_count(0) - dvs_acl.verify_no_acl_rules() - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_acl_egress_table.py b/tests/test_acl_egress_table.py deleted file mode 100644 index c96af74644..0000000000 --- a/tests/test_acl_egress_table.py +++ /dev/null @@ -1,176 +0,0 @@ -import pytest - -TABLE_TYPE = "CUSTOM_L3" -CUSTOM_TABLE_TYPE_MATCHES = [ - "L4_SRC_PORT_RANGE", - "L4_DST_PORT_RANGE", - "ETHER_TYPE", - "TUNNEL_VNI", - "TC", - "INNER_IP_PROTOCOL", - "INNER_ETHER_TYPE", - "INNER_L4_SRC_PORT", - "INNER_L4_DST_PORT", - "VLAN_ID" -] -CUSTOM_TABLE_TYPE_BPOINT_TYPES = ["PORT","PORTCHANNEL"] -CUSTOM_TABLE_TYPE_ACTIONS = ["PACKET_ACTION,COUNTER"] -EXPECTED_ACTION_LIST = ['SAI_ACL_ACTION_TYPE_PACKET_ACTION','SAI_ACL_ACTION_TYPE_COUNTER'] -TABLE_NAME = "EGRESS_TEST" -BIND_PORTS = ["Ethernet0", "Ethernet4"] -RULE_NAME = "EGRESS_TEST_RULE" - - -class TestEgressAclTable: - @pytest.fixture - def egress_acl_table(self, dvs_acl): - try: - dvs_acl.create_acl_table_type(TABLE_TYPE, CUSTOM_TABLE_TYPE_MATCHES, CUSTOM_TABLE_TYPE_BPOINT_TYPES, CUSTOM_TABLE_TYPE_ACTIONS) - dvs_acl.create_acl_table(TABLE_NAME, TABLE_TYPE, BIND_PORTS, stage="egress") - yield dvs_acl.get_acl_table_ids(1)[0] - finally: - dvs_acl.remove_acl_table(TABLE_NAME) - dvs_acl.remove_acl_table_type(TABLE_TYPE) - dvs_acl.verify_acl_table_count(0) - - def test_EgressAclTableCreationDeletion(self, dvs_acl): - try: - dvs_acl.create_acl_table_type(TABLE_TYPE, CUSTOM_TABLE_TYPE_MATCHES, CUSTOM_TABLE_TYPE_BPOINT_TYPES, CUSTOM_TABLE_TYPE_ACTIONS) - dvs_acl.create_acl_table(TABLE_NAME, TABLE_TYPE, BIND_PORTS, stage="egress") - - acl_table_id = dvs_acl.get_acl_table_ids(1)[0] - acl_table_group_ids = dvs_acl.get_acl_table_group_ids(len(BIND_PORTS)) - - dvs_acl.verify_acl_table_group_members(acl_table_id, acl_table_group_ids, 1) - dvs_acl.verify_acl_table_port_binding(acl_table_id, BIND_PORTS, 1, stage="egress") - dvs_acl.verify_acl_table_action_list(acl_table_id, EXPECTED_ACTION_LIST) - finally: - dvs_acl.remove_acl_table(TABLE_NAME) - dvs_acl.remove_acl_table_type(TABLE_TYPE) - dvs_acl.verify_acl_table_count(0) - - def test_EgressAclRuleL4SrcPortRange(self, dvs_acl, egress_acl_table): - config_qualifiers = {"L4_SRC_PORT_RANGE": "0-1001"} - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_ACL_RANGE_TYPE": dvs_acl.get_acl_range_comparator("SAI_ACL_RANGE_TYPE_L4_SRC_PORT_RANGE", "0,1001") - } - - dvs_acl.create_acl_rule(TABLE_NAME, RULE_NAME, config_qualifiers, priority="999") - dvs_acl.verify_acl_rule(expected_sai_qualifiers, priority="999") - - dvs_acl.remove_acl_rule(TABLE_NAME, RULE_NAME) - dvs_acl.verify_no_acl_rules() - - def test_EgressAclRuleL4DstPortRange(self, dvs_acl, egress_acl_table): - config_qualifiers = {"L4_DST_PORT_RANGE": "1003-6666"} - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_ACL_RANGE_TYPE": dvs_acl.get_acl_range_comparator("SAI_ACL_RANGE_TYPE_L4_DST_PORT_RANGE", "1003,6666") - } - - dvs_acl.create_acl_rule(TABLE_NAME, RULE_NAME, config_qualifiers, priority="999") - dvs_acl.verify_acl_rule(expected_sai_qualifiers, priority="999") - - dvs_acl.remove_acl_rule(TABLE_NAME, RULE_NAME) - dvs_acl.verify_no_acl_rules() - - def test_EgressAclRuleL2EthType(self, dvs_acl, egress_acl_table): - config_qualifiers = {"ETHER_TYPE": "8000"} - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_ETHER_TYPE": dvs_acl.get_simple_qualifier_comparator("8000&mask:0xffff") - } - - dvs_acl.create_acl_rule(TABLE_NAME, RULE_NAME, config_qualifiers, action="DROP", priority="1000") - dvs_acl.verify_acl_rule(expected_sai_qualifiers, action="DROP", priority="1000") - - dvs_acl.remove_acl_rule(TABLE_NAME, RULE_NAME) - dvs_acl.verify_no_acl_rules() - - def test_EgressAclRuleTunnelVNI(self, dvs_acl, egress_acl_table): - config_qualifiers = {"TUNNEL_VNI": "5000"} - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_TUNNEL_VNI": dvs_acl.get_simple_qualifier_comparator("5000&mask:0xffffffff") - } - - dvs_acl.create_acl_rule(TABLE_NAME, RULE_NAME, config_qualifiers, action="DROP", priority="1000") - dvs_acl.verify_acl_rule(expected_sai_qualifiers, action="DROP", priority="1000") - - dvs_acl.remove_acl_rule(TABLE_NAME, RULE_NAME) - dvs_acl.verify_no_acl_rules() - - def test_EgressAclRuleTC(self, dvs_acl, egress_acl_table): - config_qualifiers = {"TC": "1"} - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_TC": dvs_acl.get_simple_qualifier_comparator("1&mask:0xff") - } - - dvs_acl.create_acl_rule(TABLE_NAME, RULE_NAME, config_qualifiers, action="DROP", priority="1000") - dvs_acl.verify_acl_rule(expected_sai_qualifiers, action="DROP", priority="1000") - - dvs_acl.remove_acl_rule(TABLE_NAME, RULE_NAME) - dvs_acl.verify_no_acl_rules() - - def test_EgressAclInnerIPProtocol(self, dvs_acl, egress_acl_table): - config_qualifiers = {"INNER_IP_PROTOCOL": "8"} - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_INNER_IP_PROTOCOL": dvs_acl.get_simple_qualifier_comparator("8&mask:0xff") - } - - dvs_acl.create_acl_rule(TABLE_NAME, RULE_NAME, config_qualifiers, action="DROP", priority="1000") - dvs_acl.verify_acl_rule(expected_sai_qualifiers, action="DROP", priority="1000") - - dvs_acl.remove_acl_rule(TABLE_NAME, RULE_NAME) - dvs_acl.verify_no_acl_rules() - - def test_EgressAclInnerEthType(self, dvs_acl, egress_acl_table): - config_qualifiers = {"INNER_ETHER_TYPE": "8000"} - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_INNER_ETHER_TYPE": dvs_acl.get_simple_qualifier_comparator("8000&mask:0xffff") - } - - dvs_acl.create_acl_rule(TABLE_NAME, RULE_NAME, config_qualifiers, action="DROP", priority="1000") - dvs_acl.verify_acl_rule(expected_sai_qualifiers, action="DROP", priority="1000") - - dvs_acl.remove_acl_rule(TABLE_NAME, RULE_NAME) - dvs_acl.verify_no_acl_rules() - - def test_EgressAclInnerL4SrcPort(self, dvs_acl, egress_acl_table): - config_qualifiers = {"INNER_L4_SRC_PORT": "999"} - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_INNER_L4_SRC_PORT": dvs_acl.get_simple_qualifier_comparator("999&mask:0xffff") - } - - dvs_acl.create_acl_rule(TABLE_NAME, RULE_NAME, config_qualifiers, action="DROP", priority="1000") - dvs_acl.verify_acl_rule(expected_sai_qualifiers, action="DROP", priority="1000") - - dvs_acl.remove_acl_rule(TABLE_NAME, RULE_NAME) - dvs_acl.verify_no_acl_rules() - - def test_EgressAclInnerL4DstPort(self, dvs_acl, egress_acl_table): - config_qualifiers = {"INNER_L4_DST_PORT": "999"} - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_INNER_L4_DST_PORT": dvs_acl.get_simple_qualifier_comparator("999&mask:0xffff") - } - - dvs_acl.create_acl_rule(TABLE_NAME, RULE_NAME, config_qualifiers, action="DROP", priority="1000") - dvs_acl.verify_acl_rule(expected_sai_qualifiers, action="DROP", priority="1000") - - dvs_acl.remove_acl_rule(TABLE_NAME, RULE_NAME) - dvs_acl.verify_no_acl_rules() - - def test_AclRuleVlanId(self, dvs_acl, egress_acl_table): - config_qualifiers = {"VLAN_ID": "100"} - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_OUTER_VLAN_ID": dvs_acl.get_simple_qualifier_comparator("100&mask:0xfff") - } - - dvs_acl.create_acl_rule(TABLE_NAME, RULE_NAME, config_qualifiers, action="DROP", priority="1000") - dvs_acl.verify_acl_rule(expected_sai_qualifiers, action="DROP", priority="1000") - - dvs_acl.remove_acl_rule(TABLE_NAME, RULE_NAME) - dvs_acl.verify_no_acl_rules() - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_acl_l3v4v6.py b/tests/test_acl_l3v4v6.py deleted file mode 100644 index 2a5e044f52..0000000000 --- a/tests/test_acl_l3v4v6.py +++ /dev/null @@ -1,99 +0,0 @@ -import pytest -from requests import request - -L3V4V6_TABLE_TYPE = "L3V4V6" -L3V4V6_TABLE_NAME = "L3_V4V6_TEST" -L3V4V6_BIND_PORTS = ["Ethernet0", "Ethernet4", "Ethernet8"] -L3V4V6_RULE_NAME = "L3V4V6_TEST_RULE" - -class TestAcl: - @pytest.fixture - def l3v4v6_acl_table(self, dvs_acl): - try: - dvs_acl.create_acl_table(L3V4V6_TABLE_NAME, - L3V4V6_TABLE_TYPE, - L3V4V6_BIND_PORTS) - yield dvs_acl.get_acl_table_ids(1)[0] - finally: - dvs_acl.remove_acl_table(L3V4V6_TABLE_NAME) - dvs_acl.verify_acl_table_count(0) - - @pytest.fixture - def setup_teardown_neighbor(self, dvs): - try: - # NOTE: set_interface_status has a dependency on cdb within dvs, - # so we still need to setup the db. This should be refactored. - dvs.setup_db() - - # Bring up an IP interface with a neighbor - dvs.set_interface_status("Ethernet4", "up") - dvs.add_ip_address("Ethernet4", "10.0.0.1/24") - dvs.add_neighbor("Ethernet4", "10.0.0.2", "00:01:02:03:04:05") - - yield dvs.get_asic_db().wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP", 1)[0] - finally: - # Clean up the IP interface and neighbor - dvs.remove_neighbor("Ethernet4", "10.0.0.2") - dvs.remove_ip_address("Ethernet4", "10.0.0.1/24") - dvs.set_interface_status("Ethernet4", "down") - - def test_L3V4V6AclTableCreationDeletion(self, dvs_acl): - try: - dvs_acl.create_acl_table(L3V4V6_TABLE_NAME, L3V4V6_TABLE_TYPE, L3V4V6_BIND_PORTS) - - acl_table_id = dvs_acl.get_acl_table_ids(1)[0] - acl_table_group_ids = dvs_acl.get_acl_table_group_ids(len(L3V4V6_BIND_PORTS)) - - dvs_acl.verify_acl_table_group_members(acl_table_id, acl_table_group_ids, 1) - dvs_acl.verify_acl_table_port_binding(acl_table_id, L3V4V6_BIND_PORTS, 1) - # Verify status is written into STATE_DB - dvs_acl.verify_acl_table_status(L3V4V6_TABLE_NAME, "Active") - finally: - dvs_acl.remove_acl_table(L3V4V6_TABLE_NAME) - dvs_acl.verify_acl_table_count(0) - # Verify the STATE_DB entry is removed - dvs_acl.verify_acl_table_status(L3V4V6_TABLE_NAME, None) - - def test_ValidAclRuleCreation_sip_dip(self, dvs_acl, l3v4v6_acl_table): - config_qualifiers = {"DST_IP": "20.0.0.1/32", - "SRC_IP": "10.0.0.0/32"}; - - dvs_acl.create_acl_rule(L3V4V6_TABLE_NAME, "VALID_RULE", config_qualifiers) - # Verify status is written into STATE_DB - dvs_acl.verify_acl_rule_status(L3V4V6_TABLE_NAME, "VALID_RULE", "Active") - - dvs_acl.remove_acl_rule(L3V4V6_TABLE_NAME, "VALID_RULE") - # Verify the STATE_DB entry is removed - dvs_acl.verify_acl_rule_status(L3V4V6_TABLE_NAME, "VALID_RULE", None) - dvs_acl.verify_no_acl_rules() - - def test_InvalidAclRuleCreation_sip_sipv6(self, dvs_acl, l3v4v6_acl_table): - config_qualifiers = {"SRC_IPV6": "2777::0/64", - "SRC_IP": "10.0.0.0/32"}; - - dvs_acl.create_acl_rule(L3V4V6_TABLE_NAME, "INVALID_RULE", config_qualifiers) - # Verify status is written into STATE_DB - dvs_acl.verify_acl_rule_status(L3V4V6_TABLE_NAME, "INVALID_RULE", "Inactive") - - dvs_acl.remove_acl_rule(L3V4V6_TABLE_NAME, "INVALID_RULE") - # Verify the STATE_DB entry is removed - dvs_acl.verify_acl_rule_status(L3V4V6_TABLE_NAME, "INVALID_RULE", None) - dvs_acl.verify_no_acl_rules() - - def test_InvalidAclRuleCreation_dip_sipv6(self, dvs_acl, l3v4v6_acl_table): - config_qualifiers = {"SRC_IPV6": "2777::0/64", - "DST_IP": "10.0.0.0/32"}; - - dvs_acl.create_acl_rule(L3V4V6_TABLE_NAME, "INVALID_RULE", config_qualifiers) - # Verify status is written into STATE_DB - dvs_acl.verify_acl_rule_status(L3V4V6_TABLE_NAME, "INVALID_RULE", "Inactive") - - dvs_acl.remove_acl_rule(L3V4V6_TABLE_NAME, "INVALID_RULE") - # Verify the STATE_DB entry is removed - dvs_acl.verify_acl_rule_status(L3V4V6_TABLE_NAME, "INVALID_RULE", None) - dvs_acl.verify_no_acl_rules() - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_acl_mclag.py b/tests/test_acl_mclag.py deleted file mode 100644 index fd3b4c75e3..0000000000 --- a/tests/test_acl_mclag.py +++ /dev/null @@ -1,205 +0,0 @@ -from swsscommon import swsscommon -import time -import re -import json - -class TestMclagAcl(object): - def setup_db(self, dvs): - self.pdb = swsscommon.DBConnector(0, dvs.redis_sock, 0) - self.adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - - def create_entry(self, tbl, key, pairs): - fvs = swsscommon.FieldValuePairs(pairs) - tbl.set(key, fvs) - time.sleep(1) - - def remove_entry(self, tbl, key): - tbl._del(key) - time.sleep(1) - - def create_entry_tbl(self, db, table, key, pairs): - tbl = swsscommon.Table(db, table) - self.create_entry(tbl, key, pairs) - - def remove_entry_tbl(self, db, table, key): - tbl = swsscommon.Table(db, table) - self.remove_entry(tbl, key) - - def create_entry_pst(self, db, table, key, pairs): - tbl = swsscommon.ProducerStateTable(db, table) - self.create_entry(tbl, key, pairs) - - def remove_entry_pst(self, db, table, key): - tbl = swsscommon.ProducerStateTable(db, table) - self.remove_entry(tbl, key) - - def get_acl_table_id(self, dvs): - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE") - keys = tbl.getKeys() - - for k in dvs.asicdb.default_acl_tables: - assert k in keys - - acl_tables = [k for k in keys if k not in dvs.asicdb.default_acl_tables] - if len(acl_tables) == 1: - return acl_tables[0] - else: - return None - - def verify_acl_group_num(self, expt): - atbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE_GROUP") - acl_table_groups = atbl.getKeys() - assert len(acl_table_groups) == expt - - for k in acl_table_groups: - (status, fvs) = atbl.get(k) - assert status == True - for fv in fvs: - if fv[0] == "SAI_ACL_TABLE_GROUP_ATTR_ACL_STAGE": - assert fv[1] == "SAI_ACL_STAGE_INGRESS" - elif fv[0] == "SAI_ACL_TABLE_GROUP_ATTR_ACL_BIND_POINT_TYPE_LIST": - assert fv[1] == "1:SAI_ACL_BIND_POINT_TYPE_PORT" - elif fv[0] == "SAI_ACL_TABLE_GROUP_ATTR_TYPE": - assert fv[1] == "SAI_ACL_TABLE_GROUP_TYPE_PARALLEL" - else: - assert False - - def verify_acl_group_member(self, acl_group_ids, acl_table_id): - atbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE_GROUP_MEMBER") - keys = atbl.getKeys() - - member_groups = [] - for k in keys: - (status, fvs) = atbl.get(k) - assert status == True - assert len(fvs) == 3 - for fv in fvs: - if fv[0] == "SAI_ACL_TABLE_GROUP_MEMBER_ATTR_ACL_TABLE_GROUP_ID": - assert fv[1] in acl_group_ids - member_groups.append(fv[1]) - elif fv[0] == "SAI_ACL_TABLE_GROUP_MEMBER_ATTR_ACL_TABLE_ID": - assert fv[1] == acl_table_id - elif fv[0] == "SAI_ACL_TABLE_GROUP_MEMBER_ATTR_PRIORITY": - assert True - else: - assert False - - assert set(member_groups) == set(acl_group_ids) - - def verify_acl_port_binding(self, dvs, bind_ports): - atbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE_GROUP") - acl_table_groups = atbl.getKeys() - assert len(acl_table_groups) == len(bind_ports) - - atbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_PORT") - port_groups = [] - for p in [dvs.asicdb.portnamemap[portname] for portname in bind_ports]: - (status, fvs) = atbl.get(p) - for fv in fvs: - if fv[0] == "SAI_PORT_ATTR_INGRESS_ACL": - assert fv[1] in acl_table_groups - port_groups.append(fv[1]) - - assert len(port_groups) == len(bind_ports) - assert set(port_groups) == set(acl_table_groups) - - def test_AclTableCreation(self, dvs, testlog): - """ - hmset ACL_TABLE_TABLE:mclag policy_desc "Mclag egress port isolate acl" type MCLAG ports Ethernet0,Ethernet4 - """ - self.setup_db(dvs) - - # create ACL_TABLE_TABLE in app db - bind_ports = ["Ethernet0", "Ethernet4"] - self.create_entry_pst( - self.pdb, - "ACL_TABLE_TABLE", "mclag", - [ - ("policy_desc", "Mclag egress port isolate acl"), - ("type", "MCLAG"), - ("ports", ",".join(bind_ports)), - ] - ) - - # check acl table in asic db - acl_table_id = self.get_acl_table_id(dvs) - assert acl_table_id is not None - - # check acl table group in asic db - self.verify_acl_group_num(2) - - # get acl table group ids and verify the id numbers - atbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE_GROUP") - acl_group_ids = atbl.getKeys() - assert len(acl_group_ids) == 2 - - # check acl table group member - self.verify_acl_group_member(acl_group_ids, acl_table_id) - - # check port binding - self.verify_acl_port_binding(dvs, bind_ports) - - def test_AclRuleOutPorts(self, dvs, testlog): - """ - hmset ACL_RULE_TABLE:mclag:mclag IP_TYPE ANY PACKET_ACTION DROP OUT_PORTS Ethernet8,Ethernet12 - """ - self.setup_db(dvs) - - # create acl rule - bind_ports = ["Ethernet8", "Ethernet12"] - self.create_entry_pst( - self.pdb, - "ACL_RULE_TABLE", "mclag:mclag", - [ - ("IP_TYPE", "ANY"), - ("PACKET_ACTION", "DROP"), - ("OUT_PORTS", ",".join(bind_ports)), - ] - ) - - # check acl rule table in asic db - acl_table_id = self.get_acl_table_id(dvs) - - atbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") - keys = atbl.getKeys() - - acl_entry = [k for k in keys if k not in dvs.asicdb.default_acl_entries] - assert len(acl_entry) == 1 - - (status, fvs) = atbl.get(acl_entry[0]) - assert status == True - - value = dict(fvs) - assert value["SAI_ACL_ENTRY_ATTR_TABLE_ID"] == acl_table_id - assert value["SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION"] == "SAI_PACKET_ACTION_DROP" - assert value["SAI_ACL_ENTRY_ATTR_FIELD_ACL_IP_TYPE"] == "SAI_ACL_IP_TYPE_ANY&mask:0xffffffffffffffff" - out_ports = value["SAI_ACL_ENTRY_ATTR_FIELD_OUT_PORTS"] - assert out_ports.startswith("2:") - assert dvs.asicdb.portnamemap["Ethernet8"] in out_ports - assert dvs.asicdb.portnamemap["Ethernet12"] in out_ports - - # remove acl rule - self.remove_entry_pst( - self.pdb, - "ACL_RULE_TABLE", "mclag:mclag" - ) - - # check acl rule in asic db - (status, fvs) = atbl.get(acl_entry[0]) - assert status == False - - # remove acl - self.remove_entry_pst( - self.pdb, - "ACL_TABLE_TABLE", "mclag:mclag" - ) - - # check acl in asic db - acl_table_id = self.get_acl_table_id(dvs) - assert acl_table_id is None - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_acl_portchannel.py b/tests/test_acl_portchannel.py deleted file mode 100644 index b912cbea2f..0000000000 --- a/tests/test_acl_portchannel.py +++ /dev/null @@ -1,223 +0,0 @@ -import time -import pytest - -from swsscommon import swsscommon - - -class TestPortChannelAcl(object): - def setup_db(self, dvs): - self.pdb = swsscommon.DBConnector(0, dvs.redis_sock, 0) - self.adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - self.cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) - - def create_port_channel(self, dvs, alias): - tbl = swsscommon.Table(self.cdb, "PORTCHANNEL") - fvs = swsscommon.FieldValuePairs([("admin_status", "up"), - ("mtu", "9100")]) - tbl.set(alias, fvs) - time.sleep(1) - - def remove_port_channel(self, dvs, alias): - tbl = swsscommon.Table(self.cdb, "PORTCHANNEL") - tbl._del(alias) - time.sleep(1) - - def add_port_channel_members(self, dvs, lag, members): - tbl = swsscommon.Table(self.cdb, "PORTCHANNEL_MEMBER") - fvs = swsscommon.FieldValuePairs([("NULL", "NULL")]) - for member in members: - tbl.set(lag + "|" + member, fvs) - time.sleep(1) - - def activate_port_channel_members(self, dvs, lag, members): - tbl = swsscommon.ProducerStateTable(self.pdb, "LAG_MEMBER_TABLE") - fvs = swsscommon.FieldValuePairs([("status", "enabled")]) - - for member in members: - tbl.set(lag + ":" + member, fvs) - time.sleep(1) - - def remove_port_channel_members(self, dvs, lag, members): - tbl = swsscommon.Table(self.cdb, "PORTCHANNEL_MEMBER") - for member in members: - tbl._del(lag + "|" + member) - time.sleep(1) - - def create_acl_table(self, dvs, table_name, ports): - tbl = swsscommon.Table(self.cdb, "ACL_TABLE") - fvs = swsscommon.FieldValuePairs([("POLICY_DESC", "LAG_ACL_TEST"), - ("TYPE", "L3"), - ("PORTS", ports)]) - tbl.set(table_name, fvs) - time.sleep(1) - - def remove_acl_table(self, dvs, table_name): - tbl = swsscommon.Table(self.cdb, "ACL_TABLE") - tbl._del(table_name) - time.sleep(1) - - def create_acl_rule(self, dvs, table_name, rule_name): - tbl = swsscommon.Table(self.cdb, "ACL_RULE") - fvs = swsscommon.FieldValuePairs([("PRIORITY", "88"), - ("PACKET_ACTION", "FORWARD"), - ("L4_SRC_PORT", "8888")]) - tbl.set(table_name + "|" + rule_name, fvs) - time.sleep(1) - - def remove_acl_rule(self, dvs, table_name, rule_name): - tbl = swsscommon.Table(self.cdb, "ACL_RULE") - tbl._del(table_name + "|" + rule_name, fvs) - time.sleep(1) - - def check_asic_table_existed(self, dvs): - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_LAG") - lag = tbl.getKeys()[0] - (status, fvs) = tbl.get(lag) - assert status == True - assert len(fvs) == 2 - for fv in fvs: - if fv[0] == "SAI_LAG_ATTR_INGRESS_ACL": - table_group_id = fv[1] - elif fv[0] == "NULL": - continue - else: - assert False - - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE_GROUP") - (status, fvs) = tbl.get(table_group_id) - assert status == True - assert len(fvs) == 3 - for fv in fvs: - if fv[0] == "SAI_ACL_TABLE_GROUP_ATTR_ACL_STAGE": - assert fv[1] == "SAI_ACL_STAGE_INGRESS" - elif fv[0] == "SAI_ACL_TABLE_GROUP_ATTR_ACL_BIND_POINT_TYPE_LIST": - assert fv[1] == "1:SAI_ACL_BIND_POINT_TYPE_LAG" - elif fv[0] == "SAI_ACL_TABLE_GROUP_ATTR_TYPE": - assert fv[1] == "SAI_ACL_TABLE_GROUP_TYPE_PARALLEL" - else: - assert False - - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE_GROUP_MEMBER") - member = tbl.getKeys()[0] - (status, fvs) = tbl.get(member) - assert status == True - assert len(fvs) == 3 - for fv in fvs: - if fv[0] == "SAI_ACL_TABLE_GROUP_MEMBER_ATTR_ACL_TABLE_GROUP_ID": - assert table_group_id == fv[1] - elif fv[0] == "SAI_ACL_TABLE_GROUP_MEMBER_ATTR_ACL_TABLE_ID": - table_id = fv[1] - elif fv[0] == "SAI_ACL_TABLE_GROUP_MEMBER_ATTR_PRIORITY": - assert fv[1] == "100" - else: - assert False - - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE") - (status, fvs) = tbl.get(table_id) - assert status == True - - def check_asic_table_absent(self, dvs): - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE") - acl_tables = tbl.getKeys() - for key in dvs.asicdb.default_acl_tables: - assert key in acl_tables - acl_tables = [k for k in acl_tables if k not in dvs.asicdb.default_acl_tables] - - assert len(acl_tables) == 0 - - # Frist create port channel - # Second create ACL table - def test_PortChannelAfterAcl(self, dvs): - self.setup_db(dvs) - dvs.crm_poll_set("1") - time.sleep(2) - - used_counter = dvs.getCrmCounterValue('ACL_STATS:INGRESS:LAG', 'crm_stats_acl_group_used') - if used_counter is None: - used_counter = 0 - # create port channel - self.create_port_channel(dvs, "PortChannel01") - - # create ACL table - self.create_acl_table(dvs, "LAG_ACL_TABLE", "PortChannel01") - - time.sleep(2) - - new_used_counter = dvs.getCrmCounterValue('ACL_STATS:INGRESS:LAG', 'crm_stats_acl_group_used') - if new_used_counter is None: - new_used_counter = 0 - assert new_used_counter - used_counter == 1 - # check ASIC table - self.check_asic_table_existed(dvs) - - # remove ACL table - self.remove_acl_table(dvs, "LAG_ACL_TABLE") - - # remove port channel - self.remove_port_channel(dvs, "PortChannel01") - - time.sleep(2) - new_new_used_counter = dvs.getCrmCounterValue('ACL_STATS:INGRESS:LAG', 'crm_stats_acl_group_used') - if new_new_used_counter is None: - new_new_used_counter = 0 - assert new_used_counter - new_new_used_counter == 1 - # slow down crm polling - dvs.crm_poll_set("10000") - - # Frist create ACL table - # Second create port channel - def test_PortChannelBeforeAcl(self, dvs): - self.setup_db(dvs) - - # create ACL table - self.create_acl_table(dvs, "LAG_ACL_TABLE", "PortChannel01") - - # create port channel - self.create_port_channel(dvs, "PortChannel01") - - time.sleep(1) - - # check ASIC table - self.check_asic_table_existed(dvs) - - # TODO: right now it is not supported to remove port before remove ACL - # table. Will swap the order after having it supported - # remove ACL table - self.remove_acl_table(dvs, "LAG_ACL_TABLE") - - # remove port channel - self.remove_port_channel(dvs, "PortChannel01") - - # ACL table cannot be created upon a member port of a port channel - def test_AclOnPortChannelMember(self, dvs): - self.setup_db(dvs) - - # create port channel - self.create_port_channel(dvs, "PortChannel01") - - # add port channel member - self.add_port_channel_members(dvs, "PortChannel01", ["Ethernet0", "Ethernet4"]) - self.activate_port_channel_members(dvs, "PortChannel01", ["Ethernet0", "Ethernet4"]) - - # create ACL table - self.create_acl_table(dvs, "LAG_ACL_TABLE", "Ethernet0") - - time.sleep(1) - - # check ASIC table - self.check_asic_table_absent(dvs) - - # remove_acl_table - self.remove_acl_table(dvs, "LAG_ACL_TABLE") - - # remove port channel member - self.remove_port_channel_members(dvs, "PortChannel01", ["Ethernet0", "Ethernet4"]) - - # remove port channel - self.remove_port_channel(dvs, "PortChannel01") - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_admin_status.py b/tests/test_admin_status.py deleted file mode 100644 index 6aac5cc691..0000000000 --- a/tests/test_admin_status.py +++ /dev/null @@ -1,138 +0,0 @@ -import time -import pytest - -from swsscommon import swsscommon - - -class TestAdminStatus(object): - def setup_db(self, dvs): - self.pdb = swsscommon.DBConnector(0, dvs.redis_sock, 0) - self.adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - self.countdb = swsscommon.DBConnector(2, dvs.redis_sock, 0) - self.cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) - self.sdb = swsscommon.DBConnector(6, dvs.redis_sock, 0) - - def set_admin_status(self, port, admin_status): - assert admin_status == "up" or admin_status == "down" - tbl = swsscommon.Table(self.cdb, "PORT") - fvs = swsscommon.FieldValuePairs([("admin_status", admin_status)]) - tbl.set(port, fvs) - time.sleep(1) - - def create_port_channel(self, dvs, alias): - tbl = swsscommon.Table(self.cdb, "PORTCHANNEL") - fvs = swsscommon.FieldValuePairs([("admin_status", "up"), - ("mtu", "9100")]) - tbl.set(alias, fvs) - time.sleep(1) - - def remove_port_channel(self, dvs, alias): - tbl = swsscommon.Table(self.cdb, "PORTCHANNEL") - tbl._del(alias) - time.sleep(1) - - def add_port_channel_members(self, dvs, lag, members): - tbl = swsscommon.Table(self.cdb, "PORTCHANNEL_MEMBER") - fvs = swsscommon.FieldValuePairs([("NULL", "NULL")]) - for member in members: - tbl.set(lag + "|" + member, fvs) - time.sleep(1) - - def remove_port_channel_members(self, dvs, lag, members): - tbl = swsscommon.Table(self.cdb, "PORTCHANNEL_MEMBER") - for member in members: - tbl._del(lag + "|" + member) - time.sleep(1) - - def update_host_tx_ready_status(self, dvs, port_id, switch_id, admin_state): - host_tx_ready = "SAI_PORT_HOST_TX_READY_STATUS_READY" if admin_state == "up" else "SAI_PORT_HOST_TX_READY_STATUS_NOT_READY" - ntf = swsscommon.NotificationProducer(dvs.adb, "NOTIFICATIONS") - fvp = swsscommon.FieldValuePairs() - ntf_data = "[{\"host_tx_ready_status\":\""+host_tx_ready+"\",\"port_id\":\""+port_id+"\",\"switch_id\":\""+switch_id+"\"}]" - ntf.send("port_host_tx_ready", ntf_data, fvp) - - def get_port_id(self, dvs, port_name): - port_name_map = swsscommon.Table(self.countdb, "COUNTERS_PORT_NAME_MAP") - status, returned_value = port_name_map.hget("", port_name) - assert status == True - return returned_value - - def check_admin_status(self, dvs, port, admin_status): - assert admin_status == "up" or admin_status == "down" - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_PORT") - (status, fvs) = tbl.get(dvs.asicdb.portnamemap[port]) - assert status == True - assert "SAI_PORT_ATTR_ADMIN_STATE" in [fv[0] for fv in fvs] - for fv in fvs: - if fv[0] == "SAI_PORT_ATTR_ADMIN_STATE": - assert fv[1] == "true" if admin_status == "up" else "false" - - def check_host_tx_ready_status(self, dvs, port, admin_status): - assert admin_status == "up" or admin_status == "down" - ptbl = swsscommon.Table(self.sdb, "PORT_TABLE") - (status, fvs) = ptbl.get(port) - assert status == True - assert "host_tx_ready" in [fv[0] for fv in fvs] - for fv in fvs: - if fv[0] == "host_tx_ready": - assert fv[1] == "true" if admin_status == "up" else "false" - - def test_PortChannelMemberAdminStatus(self, dvs, testlog): - self.setup_db(dvs) - - # create port channel - self.create_port_channel(dvs, "PortChannel6") - - # add port channel members - self.add_port_channel_members(dvs, "PortChannel6", - ["Ethernet0", "Ethernet4", "Ethernet8"]) - - # configure admin status to interface - self.set_admin_status("Ethernet0", "up") - self.set_admin_status("Ethernet4", "down") - self.set_admin_status("Ethernet8", "up") - - # check ASIC port database - self.check_admin_status(dvs, "Ethernet0", "up") - self.check_admin_status(dvs, "Ethernet4", "down") - self.check_admin_status(dvs, "Ethernet8", "up") - - # remove port channel members - self.remove_port_channel_members(dvs, "PortChannel6", - ["Ethernet0", "Ethernet4", "Ethernet8"]) - - # remove port channel - self.remove_port_channel(dvs, "PortChannel6") - - def test_PortHostTxReadiness(self, dvs, testlog): - dvs.setup_db() - self.setup_db(dvs) - - #Find switch_id - switch_id = dvs.getSwitchOid() - - # configure admin status to interface - self.set_admin_status("Ethernet0", "up") - self.set_admin_status("Ethernet4", "down") - self.set_admin_status("Ethernet8", "up") - - # check ASIC port database - self.check_admin_status(dvs, "Ethernet0", "up") - self.check_admin_status(dvs, "Ethernet4", "down") - self.check_admin_status(dvs, "Ethernet8", "up") - - self.update_host_tx_ready_status(dvs, self.get_port_id(dvs, "Ethernet0") , switch_id, "up") - self.update_host_tx_ready_status(dvs, self.get_port_id(dvs, "Ethernet4") , switch_id, "down") - self.update_host_tx_ready_status(dvs, self.get_port_id(dvs, "Ethernet8") , switch_id, "up") - time.sleep(3) - - # check host readiness status in PORT TABLE of STATE-DB - self.check_host_tx_ready_status(dvs, "Ethernet0", "up") - self.check_host_tx_ready_status(dvs, "Ethernet4", "down") - self.check_host_tx_ready_status(dvs, "Ethernet8", "up") - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_bfd.py b/tests/test_bfd.py deleted file mode 100644 index 5cd18bbe05..0000000000 --- a/tests/test_bfd.py +++ /dev/null @@ -1,639 +0,0 @@ -import pytest -import time - -from swsscommon import swsscommon - -class TestBfd(object): - def setup_db(self, dvs): - dvs.setup_db() - self.pdb = dvs.get_app_db() - self.adb = dvs.get_asic_db() - self.sdb = dvs.get_state_db() - self.cdb = dvs.get_config_db() - - def get_exist_bfd_session(self): - return set(self.adb.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_BFD_SESSION")) - - def create_bfd_session(self, key, pairs): - tbl = swsscommon.ProducerStateTable(self.pdb.db_connection, "BFD_SESSION_TABLE") - fvs = swsscommon.FieldValuePairs(list(pairs.items())) - tbl.set(key, fvs) - - def remove_bfd_session(self, key): - tbl = swsscommon.ProducerStateTable(self.pdb.db_connection, "BFD_SESSION_TABLE") - tbl._del(key) - - def check_asic_bfd_session_value(self, key, expected_values): - fvs = self.adb.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_BFD_SESSION", key) - for k, v in expected_values.items(): - assert fvs[k] == v - - def check_state_bfd_session_value(self, key, expected_values): - fvs = self.sdb.get_entry("BFD_SESSION_TABLE", key) - for k, v in expected_values.items(): - assert fvs[k] == v - - def update_bfd_session_state(self, dvs, session, state): - bfd_sai_state = {"Admin_Down": "SAI_BFD_SESSION_STATE_ADMIN_DOWN", - "Down": "SAI_BFD_SESSION_STATE_DOWN", - "Init": "SAI_BFD_SESSION_STATE_INIT", - "Up": "SAI_BFD_SESSION_STATE_UP"} - - ntf = swsscommon.NotificationProducer(dvs.adb, "NOTIFICATIONS") - fvp = swsscommon.FieldValuePairs() - ntf_data = "[{\"bfd_session_id\":\""+session+"\",\"session_state\":\""+bfd_sai_state[state]+"\"}]" - ntf.send("bfd_session_state_change", ntf_data, fvp) - - def update_bgp_global_dev_state(self, state): - tbl = swsscommon.Table(self.cdb.db_connection, "BGP_DEVICE_GLOBAL") - fvs = swsscommon.FieldValuePairs(list(state.items())) - key = "STATE" - tbl.set(key, fvs) - time.sleep(1) - - def set_tsa(self): - state = {"tsa_enabled": "true"} - self.update_bgp_global_dev_state(state) - - def clear_tsa(self): - state = {"tsa_enabled": "false"} - self.update_bgp_global_dev_state(state) - - - def test_addRemoveBfdSession(self, dvs): - self.setup_db(dvs) - - bfdSessions = self.get_exist_bfd_session() - - # Create BFD session - fieldValues = {"local_addr": "10.0.0.1","tos":"64"} - self.create_bfd_session("default:default:10.0.0.2", fieldValues) - self.adb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_BFD_SESSION", len(bfdSessions) + 1) - - # Checked created BFD session in ASIC_DB - createdSessions = self.get_exist_bfd_session() - bfdSessions - assert len(createdSessions) == 1 - - session = createdSessions.pop() - expected_adb_values = { - "SAI_BFD_SESSION_ATTR_SRC_IP_ADDRESS": "10.0.0.1", - "SAI_BFD_SESSION_ATTR_DST_IP_ADDRESS": "10.0.0.2", - "SAI_BFD_SESSION_ATTR_TYPE": "SAI_BFD_SESSION_TYPE_ASYNC_ACTIVE", - "SAI_BFD_SESSION_ATTR_TOS": "64", - "SAI_BFD_SESSION_ATTR_IPHDR_VERSION": "4" - } - self.check_asic_bfd_session_value(session, expected_adb_values) - - # Check STATE_DB entry related to the BFD session - expected_sdb_values = {"state": "Down", "type": "async_active", "local_addr" : "10.0.0.1", "tx_interval" :"1000", - "rx_interval" : "1000", "multiplier" : "10", "multihop": "false", "local_discriminator" : "1"} - self.check_state_bfd_session_value("default|default|10.0.0.2", expected_sdb_values) - - # Send BFD session state notification to update BFD session state - self.update_bfd_session_state(dvs, session, "Up") - time.sleep(2) - - # Confirm BFD session state in STATE_DB is updated as expected - expected_sdb_values["state"] = "Up" - self.check_state_bfd_session_value("default|default|10.0.0.2", expected_sdb_values) - - # Remove the BFD session - self.remove_bfd_session("default:default:10.0.0.2") - self.adb.wait_for_deleted_entry("ASIC_STATE:SAI_OBJECT_TYPE_BFD_SESSION", session) - - def test_addRemoveBfdSession_ipv6(self, dvs): - self.setup_db(dvs) - - bfdSessions = self.get_exist_bfd_session() - - # Create BFD session - fieldValues = {"local_addr": "2000::1"} - self.create_bfd_session("default:default:2000::2", fieldValues) - self.adb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_BFD_SESSION", len(bfdSessions) + 1) - - # Checked created BFD session in ASIC_DB - createdSessions = self.get_exist_bfd_session() - bfdSessions - assert len(createdSessions) == 1 - - session = createdSessions.pop() - expected_adb_values = { - "SAI_BFD_SESSION_ATTR_SRC_IP_ADDRESS": "2000::1", - "SAI_BFD_SESSION_ATTR_DST_IP_ADDRESS": "2000::2", - "SAI_BFD_SESSION_ATTR_TYPE": "SAI_BFD_SESSION_TYPE_ASYNC_ACTIVE", - "SAI_BFD_SESSION_ATTR_TOS": "192", - "SAI_BFD_SESSION_ATTR_IPHDR_VERSION": "6" - } - self.check_asic_bfd_session_value(session, expected_adb_values) - - # Check STATE_DB entry related to the BFD session - expected_sdb_values = {"state": "Down", "type": "async_active", "local_addr" : "2000::1", "tx_interval" :"1000", - "rx_interval" : "1000", "multiplier" : "10", "multihop": "false", "local_discriminator" : "2"} - self.check_state_bfd_session_value("default|default|2000::2", expected_sdb_values) - - # Send BFD session state notification to update BFD session state - self.update_bfd_session_state(dvs, session, "Init") - time.sleep(2) - - # Confirm BFD session state in STATE_DB is updated as expected - expected_sdb_values["state"] = "Init" - self.check_state_bfd_session_value("default|default|2000::2", expected_sdb_values) - - # Remove the BFD session - self.remove_bfd_session("default:default:2000::2") - self.adb.wait_for_deleted_entry("ASIC_STATE:SAI_OBJECT_TYPE_BFD_SESSION", session) - - def test_addRemoveBfdSession_interface(self, dvs): - self.setup_db(dvs) - - bfdSessions = self.get_exist_bfd_session() - - # Create BFD session - fieldValues = {"local_addr": "10.0.0.1", "dst_mac": "00:02:03:04:05:06"} - self.create_bfd_session("default:Ethernet0:10.0.0.2", fieldValues) - self.adb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_BFD_SESSION", len(bfdSessions) + 1) - - # Checked created BFD session in ASIC_DB - createdSessions = self.get_exist_bfd_session() - bfdSessions - assert len(createdSessions) == 1 - - session = createdSessions.pop() - expected_adb_values = { - "SAI_BFD_SESSION_ATTR_SRC_IP_ADDRESS": "10.0.0.1", - "SAI_BFD_SESSION_ATTR_DST_IP_ADDRESS": "10.0.0.2", - "SAI_BFD_SESSION_ATTR_TYPE": "SAI_BFD_SESSION_TYPE_ASYNC_ACTIVE", - "SAI_BFD_SESSION_ATTR_TOS": "192", - "SAI_BFD_SESSION_ATTR_IPHDR_VERSION": "4", - "SAI_BFD_SESSION_ATTR_HW_LOOKUP_VALID": "false", - "SAI_BFD_SESSION_ATTR_DST_MAC_ADDRESS": "00:02:03:04:05:06" - } - self.check_asic_bfd_session_value(session, expected_adb_values) - - # Check STATE_DB entry related to the BFD session - expected_sdb_values = {"state": "Down", "type": "async_active", "local_addr" : "10.0.0.1", "tx_interval" :"1000", - "rx_interval" : "1000", "multiplier" : "10", "multihop": "false", "local_discriminator" : "3"} - self.check_state_bfd_session_value("default|Ethernet0|10.0.0.2", expected_sdb_values) - - # Send BFD session state notification to update BFD session state - self.update_bfd_session_state(dvs, session, "Down") - time.sleep(2) - - # Confirm BFD session state in STATE_DB is updated as expected - expected_sdb_values["state"] = "Down" - self.check_state_bfd_session_value("default|Ethernet0|10.0.0.2", expected_sdb_values) - - # Remove the BFD session - self.remove_bfd_session("default:Ethernet0:10.0.0.2") - self.adb.wait_for_deleted_entry("ASIC_STATE:SAI_OBJECT_TYPE_BFD_SESSION", session) - - def test_addRemoveBfdSession_txrx_interval(self, dvs): - self.setup_db(dvs) - - bfdSessions = self.get_exist_bfd_session() - - # Create BFD session - fieldValues = {"local_addr": "10.0.0.1", "tx_interval": "300", "rx_interval": "500"} - self.create_bfd_session("default:default:10.0.0.2", fieldValues) - self.adb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_BFD_SESSION", len(bfdSessions) + 1) - - # Checked created BFD session in ASIC_DB - createdSessions = self.get_exist_bfd_session() - bfdSessions - assert len(createdSessions) == 1 - - session = createdSessions.pop() - expected_adb_values = { - "SAI_BFD_SESSION_ATTR_SRC_IP_ADDRESS": "10.0.0.1", - "SAI_BFD_SESSION_ATTR_DST_IP_ADDRESS": "10.0.0.2", - "SAI_BFD_SESSION_ATTR_TYPE": "SAI_BFD_SESSION_TYPE_ASYNC_ACTIVE", - "SAI_BFD_SESSION_ATTR_TOS": "192", - "SAI_BFD_SESSION_ATTR_IPHDR_VERSION": "4", - "SAI_BFD_SESSION_ATTR_MIN_TX": "300000", - "SAI_BFD_SESSION_ATTR_MIN_RX": "500000", - } - self.check_asic_bfd_session_value(session, expected_adb_values) - - # Check STATE_DB entry related to the BFD session - expected_sdb_values = {"state": "Down", "type": "async_active", "local_addr" : "10.0.0.1", "tx_interval" :"300", - "rx_interval" : "500", "multiplier" : "10", "multihop": "false", "local_discriminator" : "4"} - self.check_state_bfd_session_value("default|default|10.0.0.2", expected_sdb_values) - - # Send BFD session state notification to update BFD session state - self.update_bfd_session_state(dvs, session, "Admin_Down") - time.sleep(2) - - # Confirm BFD session state in STATE_DB is updated as expected - expected_sdb_values["state"] = "Admin_Down" - self.check_state_bfd_session_value("default|default|10.0.0.2", expected_sdb_values) - - # Remove the BFD session - self.remove_bfd_session("default:default:10.0.0.2") - self.adb.wait_for_deleted_entry("ASIC_STATE:SAI_OBJECT_TYPE_BFD_SESSION", session) - - def test_addRemoveBfdSession_multiplier(self, dvs): - self.setup_db(dvs) - - bfdSessions = self.get_exist_bfd_session() - - # Create BFD session - fieldValues = {"local_addr": "10.0.0.1", "multiplier": "5"} - self.create_bfd_session("default:default:10.0.0.2", fieldValues) - self.adb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_BFD_SESSION", len(bfdSessions) + 1) - - # Checked created BFD session in ASIC_DB - createdSessions = self.get_exist_bfd_session() - bfdSessions - assert len(createdSessions) == 1 - - session = createdSessions.pop() - expected_adb_values = { - "SAI_BFD_SESSION_ATTR_SRC_IP_ADDRESS": "10.0.0.1", - "SAI_BFD_SESSION_ATTR_DST_IP_ADDRESS": "10.0.0.2", - "SAI_BFD_SESSION_ATTR_TYPE": "SAI_BFD_SESSION_TYPE_ASYNC_ACTIVE", - "SAI_BFD_SESSION_ATTR_TOS": "192", - "SAI_BFD_SESSION_ATTR_IPHDR_VERSION": "4", - "SAI_BFD_SESSION_ATTR_MULTIPLIER": "5" - } - self.check_asic_bfd_session_value(session, expected_adb_values) - - # Check STATE_DB entry related to the BFD session - expected_sdb_values = {"state": "Down", "type": "async_active", "local_addr" : "10.0.0.1", "tx_interval" :"1000", - "rx_interval" : "1000", "multiplier" : "5", "multihop": "false", "local_discriminator" : "5"} - self.check_state_bfd_session_value("default|default|10.0.0.2", expected_sdb_values) - - # Send BFD session state notification to update BFD session state - self.update_bfd_session_state(dvs, session, "Up") - time.sleep(2) - - # Confirm BFD session state in STATE_DB is updated as expected - expected_sdb_values["state"] = "Up" - self.check_state_bfd_session_value("default|default|10.0.0.2", expected_sdb_values) - - # Remove the BFD session - self.remove_bfd_session("default:default:10.0.0.2") - self.adb.wait_for_deleted_entry("ASIC_STATE:SAI_OBJECT_TYPE_BFD_SESSION", session) - - def test_addRemoveBfdSession_multihop(self, dvs): - self.setup_db(dvs) - - bfdSessions = self.get_exist_bfd_session() - - # Create BFD session - fieldValues = {"local_addr": "10.0.0.1", "multihop": "true"} - self.create_bfd_session("default:default:10.0.0.2", fieldValues) - self.adb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_BFD_SESSION", len(bfdSessions) + 1) - - # Checked created BFD session in ASIC_DB - createdSessions = self.get_exist_bfd_session() - bfdSessions - assert len(createdSessions) == 1 - - session = createdSessions.pop() - expected_adb_values = { - "SAI_BFD_SESSION_ATTR_SRC_IP_ADDRESS": "10.0.0.1", - "SAI_BFD_SESSION_ATTR_DST_IP_ADDRESS": "10.0.0.2", - "SAI_BFD_SESSION_ATTR_TYPE": "SAI_BFD_SESSION_TYPE_ASYNC_ACTIVE", - "SAI_BFD_SESSION_ATTR_TOS": "192", - "SAI_BFD_SESSION_ATTR_IPHDR_VERSION": "4", - "SAI_BFD_SESSION_ATTR_MULTIHOP": "true" - } - self.check_asic_bfd_session_value(session, expected_adb_values) - - # Check STATE_DB entry related to the BFD session - expected_sdb_values = {"state": "Down", "type": "async_active", "local_addr" : "10.0.0.1", "tx_interval" :"1000", - "rx_interval" : "1000", "multiplier" : "10", "multihop": "true", "local_discriminator" : "6"} - self.check_state_bfd_session_value("default|default|10.0.0.2", expected_sdb_values) - - # Send BFD session state notification to update BFD session state - self.update_bfd_session_state(dvs, session, "Up") - time.sleep(2) - - # Confirm BFD session state in STATE_DB is updated as expected - expected_sdb_values["state"] = "Up" - self.check_state_bfd_session_value("default|default|10.0.0.2", expected_sdb_values) - - # Remove the BFD session - self.remove_bfd_session("default:default:10.0.0.2") - self.adb.wait_for_deleted_entry("ASIC_STATE:SAI_OBJECT_TYPE_BFD_SESSION", session) - - def test_addRemoveBfdSession_type(self, dvs): - self.setup_db(dvs) - - bfdSessions = self.get_exist_bfd_session() - - # Create BFD session - fieldValues = {"local_addr": "10.0.0.1", "type": "demand_active"} - self.create_bfd_session("default:default:10.0.0.2", fieldValues) - self.adb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_BFD_SESSION", len(bfdSessions) + 1) - - # Checked created BFD session in ASIC_DB - createdSessions = self.get_exist_bfd_session() - bfdSessions - assert len(createdSessions) == 1 - - session = createdSessions.pop() - expected_adb_values = { - "SAI_BFD_SESSION_ATTR_SRC_IP_ADDRESS": "10.0.0.1", - "SAI_BFD_SESSION_ATTR_DST_IP_ADDRESS": "10.0.0.2", - "SAI_BFD_SESSION_ATTR_TYPE": "SAI_BFD_SESSION_TYPE_DEMAND_ACTIVE", - "SAI_BFD_SESSION_ATTR_TOS": "192", - "SAI_BFD_SESSION_ATTR_IPHDR_VERSION": "4" - } - self.check_asic_bfd_session_value(session, expected_adb_values) - - # Check STATE_DB entry related to the BFD session - expected_sdb_values = {"state": "Down", "type": "demand_active", "local_addr" : "10.0.0.1", "tx_interval" :"1000", - "rx_interval" : "1000", "multiplier" : "10", "multihop": "false", "local_discriminator" : "7"} - self.check_state_bfd_session_value("default|default|10.0.0.2", expected_sdb_values) - - # Send BFD session state notification to update BFD session state - self.update_bfd_session_state(dvs, session, "Up") - time.sleep(2) - - # Confirm BFD session state in STATE_DB is updated as expected - expected_sdb_values["state"] = "Up" - self.check_state_bfd_session_value("default|default|10.0.0.2", expected_sdb_values) - - # Remove the BFD session - self.remove_bfd_session("default:default:10.0.0.2") - self.adb.wait_for_deleted_entry("ASIC_STATE:SAI_OBJECT_TYPE_BFD_SESSION", session) - - def test_multipleBfdSessions(self, dvs): - self.setup_db(dvs) - - bfdSessions = self.get_exist_bfd_session() - - # Create BFD session 1 - key1 = "default:default:10.0.0.2" - fieldValues = {"local_addr": "10.0.0.1"} - self.create_bfd_session(key1, fieldValues) - self.adb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_BFD_SESSION", len(bfdSessions) + 1) - - # Checked BFD session 1 in ASIC_DB - createdSessions = self.get_exist_bfd_session() - bfdSessions - bfdSessions = self.get_exist_bfd_session() - assert len(createdSessions) == 1 - - session1 = createdSessions.pop() - expected_adb_values = { - "SAI_BFD_SESSION_ATTR_SRC_IP_ADDRESS": "10.0.0.1", - "SAI_BFD_SESSION_ATTR_DST_IP_ADDRESS": "10.0.0.2", - "SAI_BFD_SESSION_ATTR_TYPE": "SAI_BFD_SESSION_TYPE_ASYNC_ACTIVE", - "SAI_BFD_SESSION_ATTR_TOS": "192", - "SAI_BFD_SESSION_ATTR_IPHDR_VERSION": "4" - } - self.check_asic_bfd_session_value(session1, expected_adb_values) - - # Check STATE_DB entry related to the BFD session 1 - key_state_db1 = "default|default|10.0.0.2" - expected_sdb_values1 = {"state": "Down", "type": "async_active", "local_addr" : "10.0.0.1", "tx_interval" :"1000", - "rx_interval" : "1000", "multiplier" : "10", "multihop": "false", "local_discriminator" : "8"} - self.check_state_bfd_session_value(key_state_db1, expected_sdb_values1) - - # Create BFD session 2 - key2 = "default:default:10.0.1.2" - fieldValues = {"local_addr": "10.0.0.1", "tx_interval": "300", "rx_interval": "500"} - self.create_bfd_session(key2, fieldValues) - self.adb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_BFD_SESSION", len(bfdSessions) + 1) - - # Checked BFD session 2 in ASIC_DB - createdSessions = self.get_exist_bfd_session() - bfdSessions - bfdSessions = self.get_exist_bfd_session() - assert len(createdSessions) == 1 - - session2 = createdSessions.pop() - expected_adb_values = { - "SAI_BFD_SESSION_ATTR_SRC_IP_ADDRESS": "10.0.0.1", - "SAI_BFD_SESSION_ATTR_DST_IP_ADDRESS": "10.0.1.2", - "SAI_BFD_SESSION_ATTR_TYPE": "SAI_BFD_SESSION_TYPE_ASYNC_ACTIVE", - "SAI_BFD_SESSION_ATTR_TOS": "192", - "SAI_BFD_SESSION_ATTR_IPHDR_VERSION": "4", - "SAI_BFD_SESSION_ATTR_MIN_TX": "300000", - "SAI_BFD_SESSION_ATTR_MIN_RX": "500000", - } - self.check_asic_bfd_session_value(session2, expected_adb_values) - - # Check STATE_DB entry related to the BFD session 2 - key_state_db2 = "default|default|10.0.1.2" - expected_sdb_values2 = {"state": "Down", "type": "async_active", "local_addr" : "10.0.0.1", "tx_interval" :"300", - "rx_interval" : "500", "multiplier" : "10", "multihop": "false", "local_discriminator" : "9"} - self.check_state_bfd_session_value(key_state_db2, expected_sdb_values2) - - # Create BFD session 3 - key3 = "default:default:2000::2" - fieldValues = {"local_addr": "2000::1", "type": "demand_active"} - self.create_bfd_session(key3, fieldValues) - self.adb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_BFD_SESSION", len(bfdSessions) + 1) - - # Checked BFD session 3 in ASIC_DB - createdSessions = self.get_exist_bfd_session() - bfdSessions - bfdSessions = self.get_exist_bfd_session() - assert len(createdSessions) == 1 - - session3 = createdSessions.pop() - expected_adb_values = { - "SAI_BFD_SESSION_ATTR_SRC_IP_ADDRESS": "2000::1", - "SAI_BFD_SESSION_ATTR_DST_IP_ADDRESS": "2000::2", - "SAI_BFD_SESSION_ATTR_TYPE": "SAI_BFD_SESSION_TYPE_DEMAND_ACTIVE", - "SAI_BFD_SESSION_ATTR_TOS": "192", - "SAI_BFD_SESSION_ATTR_IPHDR_VERSION": "6" - } - self.check_asic_bfd_session_value(session3, expected_adb_values) - - # Check STATE_DB entry related to the BFD session 3 - key_state_db3 = "default|default|2000::2" - expected_sdb_values3 = {"state": "Down", "type": "demand_active", "local_addr" : "2000::1", "tx_interval" :"1000", - "rx_interval" : "1000", "multiplier" : "10", "multihop": "false", "local_discriminator" : "10"} - self.check_state_bfd_session_value(key_state_db3, expected_sdb_values3) - - # Create BFD session 4 - key4 = "default:default:3000::2" - fieldValues = {"local_addr": "3000::1"} - self.create_bfd_session(key4, fieldValues) - self.adb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_BFD_SESSION", len(bfdSessions) + 1) - - # Checked BFD session 4 in ASIC_DB - createdSessions = self.get_exist_bfd_session() - bfdSessions - bfdSessions = self.get_exist_bfd_session() - assert len(createdSessions) == 1 - - session4 = createdSessions.pop() - expected_adb_values = { - "SAI_BFD_SESSION_ATTR_SRC_IP_ADDRESS": "3000::1", - "SAI_BFD_SESSION_ATTR_DST_IP_ADDRESS": "3000::2", - "SAI_BFD_SESSION_ATTR_TYPE": "SAI_BFD_SESSION_TYPE_ASYNC_ACTIVE", - "SAI_BFD_SESSION_ATTR_TOS": "192", - "SAI_BFD_SESSION_ATTR_IPHDR_VERSION": "6" - } - self.check_asic_bfd_session_value(session4, expected_adb_values) - - # Check STATE_DB entry related to the BFD session 4 - key_state_db4 = "default|default|3000::2" - expected_sdb_values4 = {"state": "Down", "type": "async_active", "local_addr" : "3000::1", "tx_interval" :"1000", - "rx_interval" : "1000", "multiplier" : "10", "multihop": "false", "local_discriminator" : "11"} - self.check_state_bfd_session_value(key_state_db4, expected_sdb_values4) - - # Update BFD session states - self.update_bfd_session_state(dvs, session1, "Up") - expected_sdb_values1["state"] = "Up" - self.update_bfd_session_state(dvs, session3, "Init") - expected_sdb_values3["state"] = "Init" - self.update_bfd_session_state(dvs, session4, "Admin_Down") - expected_sdb_values4["state"] = "Admin_Down" - time.sleep(2) - - # Confirm BFD session states in STATE_DB are updated as expected - self.check_state_bfd_session_value(key_state_db1, expected_sdb_values1) - self.check_state_bfd_session_value(key_state_db2, expected_sdb_values2) - self.check_state_bfd_session_value(key_state_db3, expected_sdb_values3) - self.check_state_bfd_session_value(key_state_db4, expected_sdb_values4) - - # Remove the BFD sessions - self.remove_bfd_session(key1) - self.adb.wait_for_deleted_entry("ASIC_STATE:SAI_OBJECT_TYPE_BFD_SESSION", session1) - self.remove_bfd_session(key2) - self.adb.wait_for_deleted_entry("ASIC_STATE:SAI_OBJECT_TYPE_BFD_SESSION", session2) - self.remove_bfd_session(key3) - self.adb.wait_for_deleted_entry("ASIC_STATE:SAI_OBJECT_TYPE_BFD_SESSION", session3) - self.remove_bfd_session(key4) - self.adb.wait_for_deleted_entry("ASIC_STATE:SAI_OBJECT_TYPE_BFD_SESSION", session4) - - def test_addRemoveBfdSession_with_tsa_case1(self, dvs): - # This is a test for BFD caching mechanism. - # This test sets up a BFD session with shutdown_bfd_during_tsa=true and checks state DB for session creation. - # Then TSA is applied and removal of the session is verified in app db. This is followed by TSB and finally the - # reinstated session is verified. - self.setup_db(dvs) - - bfdSessions = self.get_exist_bfd_session() - - # Create BFD session - fieldValues = {"local_addr": "10.0.0.1", "type": "demand_active", "shutdown_bfd_during_tsa": "true"} - self.create_bfd_session("default:default:10.0.0.2", fieldValues) - self.adb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_BFD_SESSION", len(bfdSessions) + 1) - - # Checked created BFD session in ASIC_DB - createdSessions = self.get_exist_bfd_session() - bfdSessions - assert len(createdSessions) == 1 - - session = createdSessions.pop() - expected_adb_values = { - "SAI_BFD_SESSION_ATTR_SRC_IP_ADDRESS": "10.0.0.1", - "SAI_BFD_SESSION_ATTR_DST_IP_ADDRESS": "10.0.0.2", - "SAI_BFD_SESSION_ATTR_TYPE": "SAI_BFD_SESSION_TYPE_DEMAND_ACTIVE", - "SAI_BFD_SESSION_ATTR_TOS": "192", - "SAI_BFD_SESSION_ATTR_IPHDR_VERSION": "4" - } - self.check_asic_bfd_session_value(session, expected_adb_values) - - # Check STATE_DB entry related to the BFD session - expected_sdb_values = {"state": "Down", "type": "demand_active", "local_addr" : "10.0.0.1", "tx_interval" :"1000", - "rx_interval" : "1000", "multiplier" : "10", "multihop": "false", "local_discriminator" : "12"} - self.check_state_bfd_session_value("default|default|10.0.0.2", expected_sdb_values) - - # Send BFD session state notification to update BFD session state - self.update_bfd_session_state(dvs, session, "Up") - time.sleep(2) - bfdSessions = self.get_exist_bfd_session() - # Confirm BFD session state in STATE_DB is updated as expected. - expected_sdb_values["state"] = "Up" - self.check_state_bfd_session_value("default|default|10.0.0.2", expected_sdb_values) - - #set TSA - self.set_tsa() - time.sleep(2) - - #ensure the session is removed. - self.adb.wait_for_deleted_entry("ASIC_STATE:SAI_OBJECT_TYPE_BFD_SESSION", session) - - #set TSB - self.clear_tsa() - time.sleep(2) - createdSessions = self.get_exist_bfd_session() - bfdSessions - session = createdSessions.pop() - expected_sdb_values["local_discriminator"] = "13" - self.update_bfd_session_state(dvs, session, "Up") - time.sleep(2) - # bfd session should come back - expected_sdb_values["state"] = "Up" - self.check_state_bfd_session_value("default|default|10.0.0.2", expected_sdb_values) - - # Remove the BFD session - - self.remove_bfd_session("default:default:10.0.0.2") - self.adb.wait_for_deleted_entry("ASIC_STATE:SAI_OBJECT_TYPE_BFD_SESSION", session) - - - def test_addRemoveBfdSession_with_tsa_case2(self, dvs): - # This is a test for BFD caching mechanism. - # This test sets up a BFD session with shutdown_bfd_during_tsa=true and checks state DB for session creation. - # Then TSA is applied and removal of the session is verified from app db. At this point the session is removed. - # This isfollowed by TSB. Since the session configuration has been removed during TSB, the BFD session should not - # start up. - self.setup_db(dvs) - - bfdSessions = self.get_exist_bfd_session() - - # Create BFD session - fieldValues = {"local_addr": "10.0.0.1", "type": "demand_active"} - self.create_bfd_session("default:default:10.0.0.2", fieldValues) - self.adb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_BFD_SESSION", len(bfdSessions) + 1) - - # Checked created BFD session in ASIC_DB - createdSessions = self.get_exist_bfd_session() - bfdSessions - assert len(createdSessions) == 1 - - session = createdSessions.pop() - expected_adb_values = { - "SAI_BFD_SESSION_ATTR_SRC_IP_ADDRESS": "10.0.0.1", - "SAI_BFD_SESSION_ATTR_DST_IP_ADDRESS": "10.0.0.2", - "SAI_BFD_SESSION_ATTR_TYPE": "SAI_BFD_SESSION_TYPE_DEMAND_ACTIVE", - "SAI_BFD_SESSION_ATTR_TOS": "192", - "SAI_BFD_SESSION_ATTR_IPHDR_VERSION": "4" - } - self.check_asic_bfd_session_value(session, expected_adb_values) - - # Check STATE_DB entry related to the BFD session - expected_sdb_values = {"state": "Down", "type": "demand_active", "local_addr" : "10.0.0.1", "tx_interval" :"1000", - "rx_interval" : "1000", "multiplier" : "10", "multihop": "false", "local_discriminator" : "14"} - self.check_state_bfd_session_value("default|default|10.0.0.2", expected_sdb_values) - - # Send BFD session state notification to update BFD session state - self.update_bfd_session_state(dvs, session, "Up") - time.sleep(2) - # Confirm BFD session state in STATE_DB is updated as expected. - expected_sdb_values["state"] = "Up" - self.check_state_bfd_session_value("default|default|10.0.0.2", expected_sdb_values) - - #set TSA - self.set_tsa() - time.sleep(2) - - #ensure the session is still present. - self.adb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_BFD_SESSION", len(bfdSessions) + 1) - self.check_state_bfd_session_value("default|default|10.0.0.2", expected_sdb_values) - - #set TSB - self.clear_tsa() - time.sleep(2) - - self.check_state_bfd_session_value("default|default|10.0.0.2", expected_sdb_values) - - # Remove the BFD session - self.remove_bfd_session("default:default:10.0.0.2") - self.adb.wait_for_deleted_entry("ASIC_STATE:SAI_OBJECT_TYPE_BFD_SESSION", session) - - def test_bfd_state_db_clear(self, dvs): - self.setup_db(dvs) - - bfdSessions = self.get_exist_bfd_session() - - # Create BFD session - fieldValues = {"local_addr": "10.0.0.1", "type": "demand_active"} - self.create_bfd_session("default:default:10.0.0.2", fieldValues) - self.adb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_BFD_SESSION", len(bfdSessions) + 1) - - # Checked created BFD session in ASIC_DB - createdSessions = self.get_exist_bfd_session() - bfdSessions - assert len(createdSessions) == 1 - dvs.stop_swss() - dvs.start_swss() - - time.sleep(5) - keys = self.sdb.get_keys("BFD_SESSION_TABLE") - assert len(keys) == 0 diff --git a/tests/test_buffer_dynamic.py b/tests/test_buffer_dynamic.py deleted file mode 100644 index 1813ebf430..0000000000 --- a/tests/test_buffer_dynamic.py +++ /dev/null @@ -1,905 +0,0 @@ -import time -import pytest -import re -import buffer_model - -from dvslib.dvs_common import PollingConfig - -@pytest.fixture -def dynamic_buffer(dvs): - buffer_model.enable_dynamic_buffer(dvs.get_config_db(), dvs.runcmd) - yield - buffer_model.disable_dynamic_buffer(dvs.get_config_db(), dvs.runcmd) - -@pytest.mark.usefixtures("dynamic_buffer") -class TestBufferMgrDyn(object): - DEFAULT_POLLING_CONFIG = PollingConfig(polling_interval=0.01, timeout=60, strict=True) - def setup_db(self, dvs): - self.initialized = False - self.cableLenTest1 = "15m" - self.cableLenTest2 = "25m" - self.speedToTest1 = "50000" - self.speedToTest2 = "10000" - - self.app_db = dvs.get_app_db() - self.asic_db = dvs.get_asic_db() - self.config_db = dvs.get_config_db() - self.state_db = dvs.get_state_db() - - fvs = self.config_db.wait_for_entry("PORT", "Ethernet0") - self.originalSpeed = fvs["speed"] - if self.originalSpeed == self.speedToTest1: - self.speedToTest1 = "100000" - elif self.originalSpeed == self.speedToTest2: - self.speedToTest2 = "100000" - elif self.originalSpeed == "": - self.originalSpeed = "100000" - - # Check whether cable length has been configured - fvs = self.config_db.wait_for_entry("CABLE_LENGTH", "AZURE") - self.originalCableLen = fvs["Ethernet0"] - self.cableLenBeforeTest = self.originalCableLen - if self.originalCableLen == self.cableLenTest1: - self.cableLenTest1 = "20m" - elif self.originalCableLen == self.cableLenTest2: - self.cableLenTest2 = "20m" - elif self.originalCableLen == "0m": - fvs["Ethernet0"] = "5m" - self.originalCableLen = "5m" - self.config_db.update_entry("CABLE_LENGTH", "AZURE", fvs) - - fvs = {"mmu_size": "12766208"} - self.state_db.create_entry("BUFFER_MAX_PARAM_TABLE", "global", fvs) - self.bufferMaxParameter = self.state_db.wait_for_entry("BUFFER_MAX_PARAM_TABLE", "Ethernet0") - - # The default lossless priority group will be removed ahead of staring test - # By doing so all the dynamically generated profiles will be removed and - # it's easy to identify the SAI OID of the new profile once it's created by - # comparing the new set of ASIC_STATE:BUFFER_PROFILE table against the initial one - pgs = self.config_db.get_keys('BUFFER_PG') - for key in pgs: - pg = self.config_db.get_entry('BUFFER_PG', key) - if pg['profile'] == 'NULL': - self.config_db.delete_entry('BUFFER_PG', key) - - # wait 5 seconds to make sure all the lossless PGs and profiles have been removed - seconds_delayed = 0 - lossless_profile_name_pattern = 'pg_lossless_([1-9][0-9]*000)_([1-9][0-9]*m)_profile' - max_delay_seconds = 10 - while seconds_delayed <= max_delay_seconds: - time.sleep(2) - seconds_delayed += 2 - - lossless_profile = None - profiles = self.app_db.get_keys('BUFFER_PROFILE_TABLE') - for key in profiles: - if re.search(lossless_profile_name_pattern, key): - lossless_profile = key - break - - if not lossless_profile: - break - - assert not lossless_profile, \ - "There is still lossless profile ({}) {} seconds after all lossless PGs have been removed".format(lossless_profile, seconds_delayed) - - time.sleep(10) - - self.setup_asic_db(dvs) - - self.initialized = True - - def cleanup_db(self, dvs): - # Clean up: restore the origin cable length - fvs = self.config_db.wait_for_entry("CABLE_LENGTH", "AZURE") - fvs["Ethernet0"] = self.cableLenBeforeTest - self.config_db.update_entry("CABLE_LENGTH", "AZURE", fvs) - - def setup_asic_db(self, dvs): - buffer_pool_set = set(self.asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_BUFFER_POOL")) - self.initProfileSet = set(self.asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_BUFFER_PROFILE")) - self.initPGSet = set(self.asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP")) - - ingress_lossless_pool = self.app_db.get_entry("BUFFER_POOL_TABLE", "ingress_lossless_pool") - self.ingress_lossless_pool_asic = None - - for key in buffer_pool_set: - bufferpool = self.asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_BUFFER_POOL", key) - if bufferpool["SAI_BUFFER_POOL_ATTR_TYPE"] == "SAI_BUFFER_POOL_TYPE_INGRESS": - if ingress_lossless_pool["size"] == bufferpool["SAI_BUFFER_POOL_ATTR_SIZE"]: - self.ingress_lossless_pool_asic = bufferpool - self.ingress_lossless_pool_oid = key - - def check_new_profile_in_asic_db(self, dvs, profile): - retry_count = 0 - self.newProfileInAsicDb = None - while retry_count < 5: - retry_count += 1 - diff = set(self.asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_BUFFER_PROFILE")) - self.initProfileSet - if len(diff) == 1: - self.newProfileInAsicDb = diff.pop() - break - else: - time.sleep(1) - assert self.newProfileInAsicDb, "Can't get SAI OID for newly created profile {} after retry {} times".format(profile, retry_count) - - # in case diff is empty, we just treat the newProfileInAsicDb cached the latest one - fvs = self.app_db.get_entry("BUFFER_PROFILE_TABLE", profile) - if fvs.get('dynamic_th'): - sai_threshold_value = fvs['dynamic_th'] - sai_threshold_mode = 'SAI_BUFFER_PROFILE_THRESHOLD_MODE_DYNAMIC' - sai_threshold_name = 'SAI_BUFFER_PROFILE_ATTR_SHARED_DYNAMIC_TH' - else: - sai_threshold_value = fvs['static_th'] - sai_threshold_mode = 'SAI_BUFFER_PROFILE_THRESHOLD_MODE_STATIC' - sai_threshold_name = 'SAI_BUFFER_PROFILE_ATTR_SHARED_STATIC_TH' - self.asic_db.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_BUFFER_PROFILE", self.newProfileInAsicDb, - {'SAI_BUFFER_PROFILE_ATTR_XON_TH': fvs['xon'], - 'SAI_BUFFER_PROFILE_ATTR_XOFF_TH': fvs['xoff'], - 'SAI_BUFFER_PROFILE_ATTR_RESERVED_BUFFER_SIZE': fvs['size'], - 'SAI_BUFFER_PROFILE_ATTR_POOL_ID': self.ingress_lossless_pool_oid, - 'SAI_BUFFER_PROFILE_ATTR_THRESHOLD_MODE': sai_threshold_mode, - sai_threshold_name: sai_threshold_value}, - self.DEFAULT_POLLING_CONFIG) - - def make_lossless_profile_name(self, speed, cable_length, mtu = None, dynamic_th = None): - extra = "" - if mtu: - extra += "_mtu" + mtu - if dynamic_th: - extra += "_th" + dynamic_th - - return "pg_lossless_" + speed + "_" + cable_length + extra + "_profile" - - def change_cable_length(self, cable_length): - cable_lengths = self.config_db.get_entry('CABLE_LENGTH', 'AZURE') - cable_lengths['Ethernet0'] = cable_length - self.config_db.update_entry('CABLE_LENGTH', 'AZURE', cable_lengths) - - def check_queues_after_port_startup(self, dvs): - self.app_db.wait_for_field_match("BUFFER_QUEUE_TABLE", "{}:0-2".format("Ethernet0"), {"profile": "egress_lossy_profile"}) - self.app_db.wait_for_field_match("BUFFER_QUEUE_TABLE", "{}:3-4".format("Ethernet0"), {"profile": "egress_lossless_profile"}) - self.app_db.wait_for_field_match("BUFFER_QUEUE_TABLE", "{}:5-6".format("Ethernet0"), {"profile": "egress_lossy_profile"}) - - def test_changeSpeed(self, dvs, testlog): - self.setup_db(dvs) - - # Startup interface - dvs.port_admin_set('Ethernet0', 'up') - self.check_queues_after_port_startup(dvs) - - # Configure lossless PG 3-4 on interface - self.config_db.update_entry('BUFFER_PG', 'Ethernet0|3-4', {'profile': 'NULL'}) - - # Change speed to speed1 and verify whether the profile has been updated - dvs.port_field_set("Ethernet0", "speed", self.speedToTest1) - - expectedProfile = self.make_lossless_profile_name(self.speedToTest1, self.originalCableLen) - self.app_db.wait_for_entry("BUFFER_PROFILE_TABLE", expectedProfile) - self.check_new_profile_in_asic_db(dvs, expectedProfile) - - # Check whether buffer pg align - bufferPg = self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:3-4", {"profile": expectedProfile}) - - # Remove lossless PG - self.config_db.delete_entry('BUFFER_PG', 'Ethernet0|3-4') - self.app_db.wait_for_deleted_entry("BUFFER_PG_TABLE", "Ethernet0:3-4") - - # Change speed to speed2 and verify - dvs.port_field_set("Ethernet0", "speed", self.speedToTest2) - expectedProfile = self.make_lossless_profile_name(self.speedToTest2, self.originalCableLen) - - # Re-add another lossless PG - self.config_db.update_entry('BUFFER_PG', 'Ethernet0|6', {'profile': 'NULL'}) - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:6", {"profile": expectedProfile}) - - # Remove the lossless PG 6 - self.config_db.delete_entry('BUFFER_PG', 'Ethernet0|6') - self.app_db.wait_for_deleted_entry("BUFFER_PG_TABLE", "Ethernet0:6") - - # Remove the lossless PG 3-4 and revert speed - dvs.port_field_set("Ethernet0", "speed", self.originalSpeed) - self.config_db.update_entry('BUFFER_PG', 'Ethernet0|3-4', {'profile': 'NULL'}) - - expectedProfile = self.make_lossless_profile_name(self.originalSpeed, self.originalCableLen) - self.app_db.wait_for_entry("BUFFER_PROFILE_TABLE", expectedProfile) - self.check_new_profile_in_asic_db(dvs, expectedProfile) - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:3-4", {"profile": expectedProfile}) - - # Remove lossless PG 3-4 on interface - self.config_db.delete_entry('BUFFER_PG', 'Ethernet0|3-4') - self.app_db.wait_for_deleted_entry("BUFFER_PG_TABLE", "Ethernet0:3-4") - - # Shutdown interface - dvs.port_admin_set('Ethernet0', 'down') - - self.cleanup_db(dvs) - - @pytest.mark.skip(reason="Failing. Under investigation") - def test_changeCableLen(self, dvs, testlog): - self.setup_db(dvs) - - # Startup interface - dvs.port_admin_set('Ethernet0', 'up') - - # Configure lossless PG 3-4 on interface - self.config_db.update_entry('BUFFER_PG', 'Ethernet0|3-4', {'profile': 'NULL'}) - - # Change to new cable length - self.change_cable_length(self.cableLenTest1) - expectedProfile = self.make_lossless_profile_name(self.originalSpeed, self.cableLenTest1) - self.app_db.wait_for_entry("BUFFER_PROFILE_TABLE", expectedProfile) - self.check_new_profile_in_asic_db(dvs, expectedProfile) - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:3-4", {"profile": expectedProfile}) - - # Remove the lossless PGs - self.config_db.delete_entry('BUFFER_PG', 'Ethernet0|3-4') - self.app_db.wait_for_deleted_entry("BUFFER_PG_TABLE", "Ethernet0:3-4") - - # Change to another cable length - self.change_cable_length(self.cableLenTest2) - # Check whether the old profile has been removed - self.app_db.wait_for_deleted_entry("BUFFER_PROFILE_TABLE", expectedProfile) - - # Re-add lossless PGs - self.config_db.update_entry('BUFFER_PG', 'Ethernet0|3-4', {'profile': 'NULL'}) - expectedProfile = self.make_lossless_profile_name(self.originalSpeed, self.cableLenTest2) - # Check the BUFFER_PROFILE_TABLE and BUFFER_PG_TABLE - self.app_db.wait_for_entry("BUFFER_PROFILE_TABLE", expectedProfile) - self.check_new_profile_in_asic_db(dvs, expectedProfile) - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:3-4", {"profile": expectedProfile}) - - # Revert the cable length - self.change_cable_length(self.originalCableLen) - # Check the BUFFER_PROFILE_TABLE and BUFFER_PG_TABLE - # we are not able to check whether the SAI OID is removed from ASIC DB here - # because sometimes the SAI OID in ASIC DB can be reused for the newly created profile - self.app_db.wait_for_deleted_entry("BUFFER_PROFILE_TABLE", expectedProfile) - - expectedProfile = self.make_lossless_profile_name(self.originalSpeed, self.originalCableLen) - self.app_db.wait_for_entry("BUFFER_PROFILE_TABLE", expectedProfile) - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:3-4", {"profile": expectedProfile}) - - # Remove lossless PG 3-4 on interface - self.config_db.delete_entry('BUFFER_PG', 'Ethernet0|3-4') - - # Shutdown interface - dvs.port_admin_set('Ethernet0', 'down') - - self.cleanup_db(dvs) - - def test_MultipleLosslessPg(self, dvs, testlog): - self.setup_db(dvs) - - # Startup interface - dvs.port_admin_set('Ethernet0', 'up') - - # Configure lossless PG 3-4 on interface - self.config_db.update_entry('BUFFER_PG', 'Ethernet0|3-4', {'profile': 'NULL'}) - - # Add another lossless PG - self.config_db.update_entry('BUFFER_PG', 'Ethernet0|6', {'profile': 'NULL'}) - expectedProfile = self.make_lossless_profile_name(self.originalSpeed, self.originalCableLen) - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:6", {"profile": expectedProfile}) - - # Change speed and check - dvs.port_field_set("Ethernet0", "speed", self.speedToTest1) - expectedProfile = self.make_lossless_profile_name(self.speedToTest1, self.originalCableLen) - self.app_db.wait_for_entry("BUFFER_PROFILE_TABLE", expectedProfile) - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:3-4", {"profile": expectedProfile}) - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:6", {"profile": expectedProfile}) - - # Change cable length and check - self.change_cable_length(self.cableLenTest1) - self.app_db.wait_for_deleted_entry("BUFFER_PROFILE_TABLE", expectedProfile) - expectedProfile = self.make_lossless_profile_name(self.speedToTest1, self.cableLenTest1) - self.app_db.wait_for_entry("BUFFER_PROFILE_TABLE", expectedProfile) - self.check_new_profile_in_asic_db(dvs, expectedProfile) - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:3-4", {"profile": expectedProfile}) - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:6", {"profile": expectedProfile}) - - # Revert the speed and cable length and check - self.change_cable_length(self.originalCableLen) - dvs.port_field_set("Ethernet0", "speed", self.originalSpeed) - self.app_db.wait_for_deleted_entry("BUFFER_PROFILE_TABLE", expectedProfile) - self.asic_db.wait_for_deleted_entry("ASIC_STATE:SAI_OBJECT_TYPE_BUFFER_PROFILE", self.newProfileInAsicDb) - expectedProfile = self.make_lossless_profile_name(self.originalSpeed, self.originalCableLen) - self.app_db.wait_for_entry("BUFFER_PROFILE_TABLE", expectedProfile) - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:3-4", {"profile": expectedProfile}) - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:6", {"profile": expectedProfile}) - - # Remove lossless PG 3-4 and 6 on interface - self.config_db.delete_entry('BUFFER_PG', 'Ethernet0|3-4') - self.config_db.delete_entry('BUFFER_PG', 'Ethernet0|6') - - # Shutdown interface - dvs.port_admin_set('Ethernet0', 'down') - - self.cleanup_db(dvs) - - def test_headroomOverride(self, dvs, testlog): - self.setup_db(dvs) - - # Startup interface - dvs.port_admin_set('Ethernet0', 'up') - - # Configure static profile - self.config_db.update_entry('BUFFER_PROFILE', 'test', - {'xon': '18432', - 'xoff': '16384', - 'size': '34816', - 'dynamic_th': '0', - 'pool': 'ingress_lossless_pool'}) - - self.app_db.wait_for_entry("BUFFER_PROFILE_TABLE", "test") - self.app_db.wait_for_exact_match("BUFFER_PROFILE_TABLE", "test", - { "pool" : "ingress_lossless_pool", - "xon" : "18432", - "xoff" : "16384", - "size" : "34816", - "dynamic_th" : "0" - }) - self.check_new_profile_in_asic_db(dvs, "test") - - # configure lossless PG 3-4 on interface - self.config_db.update_entry('BUFFER_PG', 'Ethernet0|3-4', {'profile': 'NULL'}) - - self.change_cable_length(self.cableLenTest1) - expectedProfile = self.make_lossless_profile_name(self.originalSpeed, self.cableLenTest1) - self.app_db.wait_for_entry("BUFFER_PROFILE_TABLE", expectedProfile) - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:3-4", {"profile": expectedProfile}) - - # configure lossless PG 3-4 with headroom override - self.config_db.update_entry('BUFFER_PG', 'Ethernet0|3-4', {'profile': 'test'}) - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:3-4", {"profile": "test"}) - # configure lossless PG 6 with headroom override - self.config_db.update_entry('BUFFER_PG', 'Ethernet0|6', {'profile': 'test'}) - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:6", {"profile": "test"}) - - # update the profile - self.config_db.update_entry('BUFFER_PROFILE', 'test', - {'xon': '18432', - 'xoff': '18432', - 'size': '36864', - 'dynamic_th': '0', - 'pool': 'ingress_lossless_pool'}) - self.app_db.wait_for_exact_match("BUFFER_PROFILE_TABLE", "test", - { "pool" : "ingress_lossless_pool", - "xon" : "18432", - "xoff" : "18432", - "size" : "36864", - "dynamic_th" : "0" - }) - self.check_new_profile_in_asic_db(dvs, "test") - - # remove all lossless PGs - self.config_db.delete_entry('BUFFER_PG', 'Ethernet0|3-4') - self.config_db.delete_entry('BUFFER_PG', 'Ethernet0|6') - - self.app_db.wait_for_deleted_entry("BUFFER_PG_TABLE", "Ethernet0:3-4") - self.app_db.wait_for_deleted_entry("BUFFER_PG_TABLE", "Ethernet0:6") - - # readd lossless PG with dynamic profile - self.config_db.update_entry('BUFFER_PG', 'Ethernet0|3-4', {'profile': 'NULL'}) - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:3-4", {"profile": expectedProfile}) - - # remove the headroom override profile - self.config_db.delete_entry('BUFFER_PROFILE', 'test') - self.app_db.wait_for_deleted_entry("BUFFER_PROFILE_TABLE", "test") - self.asic_db.wait_for_deleted_entry("ASIC_STATE:SAI_OBJECT_TYPE_BUFFER_PROFILE", self.newProfileInAsicDb) - - self.change_cable_length(self.originalCableLen) - self.app_db.wait_for_deleted_entry("BUFFER_PROFILE_TABLE", expectedProfile) - expectedProfile = self.make_lossless_profile_name(self.originalSpeed, self.originalCableLen) - self.app_db.wait_for_entry("BUFFER_PROFILE_TABLE", expectedProfile) - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:3-4", {"profile": expectedProfile}) - - # remove lossless PG 3-4 on interface - self.config_db.delete_entry('BUFFER_PG', 'Ethernet0|3-4') - - # Shutdown interface - dvs.port_admin_set('Ethernet0', 'down') - - self.cleanup_db(dvs) - - def test_mtuUpdate(self, dvs, testlog): - self.setup_db(dvs) - - # Startup interface - dvs.port_admin_set('Ethernet0', 'up') - - test_mtu = '1500' - default_mtu = '9100' - expectedProfileMtu = self.make_lossless_profile_name(self.originalSpeed, self.originalCableLen, mtu = test_mtu) - expectedProfileNormal = self.make_lossless_profile_name(self.originalSpeed, self.originalCableLen) - - # update the mtu on the interface - dvs.port_field_set("Ethernet0", "mtu", test_mtu) - - # configure lossless PG 3-4 on interface - self.config_db.update_entry('BUFFER_PG', 'Ethernet0|3-4', {'profile': 'NULL'}) - - self.app_db.wait_for_entry("BUFFER_PG_TABLE", "Ethernet0:3-4") - self.app_db.wait_for_entry("BUFFER_PROFILE_TABLE", expectedProfileMtu) - self.check_new_profile_in_asic_db(dvs, expectedProfileMtu) - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:3-4", {"profile": expectedProfileMtu}) - - dvs.port_field_set("Ethernet0", "mtu", default_mtu) - - self.app_db.wait_for_deleted_entry("BUFFER_PROFILE_TABLE", expectedProfileMtu) - self.app_db.wait_for_entry("BUFFER_PROFILE_TABLE", expectedProfileNormal) - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:3-4", {"profile": expectedProfileNormal}) - - # clear configuration - self.config_db.delete_entry('BUFFER_PG', 'Ethernet0|3-4') - - # Shutdown interface - dvs.port_admin_set('Ethernet0', 'down') - - self.cleanup_db(dvs) - - def test_nonDefaultAlpha(self, dvs, testlog): - self.setup_db(dvs) - - # Startup interface - dvs.port_admin_set('Ethernet0', 'up') - - test_dynamic_th_1 = '1' - expectedProfile_th1 = self.make_lossless_profile_name(self.originalSpeed, self.originalCableLen, dynamic_th = test_dynamic_th_1) - test_dynamic_th_2 = '2' - expectedProfile_th2 = self.make_lossless_profile_name(self.originalSpeed, self.originalCableLen, dynamic_th = test_dynamic_th_2) - - # add a profile with non-default dynamic_th - self.config_db.update_entry('BUFFER_PROFILE', 'non-default-dynamic', - {'dynamic_th': test_dynamic_th_1, - 'headroom_type': 'dynamic', - 'pool': 'ingress_lossless_pool'}) - - # configure lossless PG 3-4 on interface - self.config_db.update_entry('BUFFER_PG', 'Ethernet0|3-4', {'profile': 'non-default-dynamic'}) - - self.app_db.wait_for_entry("BUFFER_PROFILE_TABLE", expectedProfile_th1) - self.check_new_profile_in_asic_db(dvs, expectedProfile_th1) - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:3-4", {"profile": expectedProfile_th1}) - - # modify the profile to another dynamic_th - self.config_db.update_entry('BUFFER_PROFILE', 'non-default-dynamic', - {'dynamic_th': test_dynamic_th_2, - 'headroom_type': 'dynamic', - 'pool': 'ingress_lossless_pool'}) - - self.app_db.wait_for_deleted_entry("BUFFER_PROFILE_TABLE", expectedProfile_th1) - self.app_db.wait_for_entry("BUFFER_PROFILE_TABLE", expectedProfile_th2) - self.check_new_profile_in_asic_db(dvs, expectedProfile_th2) - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:3-4", {"profile": expectedProfile_th2}) - - # clear configuration - self.config_db.delete_entry('BUFFER_PG', 'Ethernet0|3-4') - self.config_db.delete_entry('BUFFER_PROFILE', 'non-default-dynamic') - - # Shutdown interface - dvs.port_admin_set('Ethernet0', 'down') - - self.cleanup_db(dvs) - - def test_sharedHeadroomPool(self, dvs, testlog): - self.setup_db(dvs) - - # Startup interface - dvs.port_admin_set('Ethernet0', 'up') - - # configure lossless PG 3-4 on interface and start up the interface - self.config_db.update_entry('BUFFER_PG', 'Ethernet0|3-4', {'profile': 'NULL'}) - - expectedProfile = self.make_lossless_profile_name(self.originalSpeed, self.originalCableLen) - self.app_db.wait_for_entry("BUFFER_PROFILE_TABLE", expectedProfile) - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:3-4", {"profile": expectedProfile}) - self.check_new_profile_in_asic_db(dvs, expectedProfile) - profileInApplDb = self.app_db.get_entry('BUFFER_PROFILE_TABLE', expectedProfile) - - # enable shared headroom pool by configuring over subscribe ratio - default_lossless_buffer_parameter = self.config_db.get_entry('DEFAULT_LOSSLESS_BUFFER_PARAMETER', 'AZURE') - over_subscribe_ratio = default_lossless_buffer_parameter.get('over_subscribe_ratio') - assert not over_subscribe_ratio or over_subscribe_ratio == '0', "Over subscribe ratio isn't 0" - - # config over subscribe ratio to 2 - default_lossless_buffer_parameter['over_subscribe_ratio'] = '2' - self.config_db.update_entry('DEFAULT_LOSSLESS_BUFFER_PARAMETER', 'AZURE', default_lossless_buffer_parameter) - - # check buffer profile: xoff should be removed from size - profileInApplDb['size'] = profileInApplDb['xon'] - self.app_db.wait_for_field_match('BUFFER_PROFILE_TABLE', expectedProfile, profileInApplDb) - self.check_new_profile_in_asic_db(dvs, expectedProfile) - - # Check ingress_lossless_pool between appldb and asicdb - # There are only two lossless PGs configured on one port. - # Hence the shared headroom pool size should be (pg xoff * 2 - private headroom) / over subscribe ratio (2) = xoff - private_headroom / 2. - ingress_lossless_pool_in_appldb = self.app_db.get_entry('BUFFER_POOL_TABLE', 'ingress_lossless_pool') - private_headroom = 10 * 1024 - shp_size = str(int(profileInApplDb['xoff']) - int(private_headroom / 2)) - ingress_lossless_pool_in_appldb['xoff'] = shp_size - # toggle shared headroom pool, it requires some time to update pools - time.sleep(20) - self.app_db.wait_for_field_match('BUFFER_POOL_TABLE', 'ingress_lossless_pool', ingress_lossless_pool_in_appldb) - ingress_lossless_pool_in_asicdb = self.asic_db.get_entry('ASIC_STATE:SAI_OBJECT_TYPE_BUFFER_PROFILE', self.ingress_lossless_pool_oid) - ingress_lossless_pool_in_asicdb['SAI_BUFFER_POOL_ATTR_XOFF_SIZE'] = shp_size - self.asic_db.wait_for_field_match('ASIC_STATE:SAI_OBJECT_TYPE_BUFFER_POOL', self.ingress_lossless_pool_oid, ingress_lossless_pool_in_asicdb) - - # config shared headroom pool size - shp_size = '204800' - ingress_lossless_pool_in_configdb = self.config_db.get_entry('BUFFER_POOL', 'ingress_lossless_pool') - ingress_lossless_pool_in_configdb['xoff'] = shp_size - self.config_db.update_entry('BUFFER_POOL', 'ingress_lossless_pool', ingress_lossless_pool_in_configdb) - # make sure the size is still equal to xon in the profile - self.app_db.wait_for_field_match('BUFFER_PROFILE_TABLE', expectedProfile, profileInApplDb) - self.check_new_profile_in_asic_db(dvs, expectedProfile) - - # config over subscribe ratio to 4 - default_lossless_buffer_parameter['over_subscribe_ratio'] = '4' - self.config_db.update_entry('DEFAULT_LOSSLESS_BUFFER_PARAMETER', 'AZURE', default_lossless_buffer_parameter) - # shp size wins in case both size and over subscribe ratio is configured - ingress_lossless_pool_in_appldb['xoff'] = shp_size - self.app_db.wait_for_field_match('BUFFER_POOL_TABLE', 'ingress_lossless_pool', ingress_lossless_pool_in_appldb) - ingress_lossless_pool_in_asicdb['SAI_BUFFER_POOL_ATTR_XOFF_SIZE'] = shp_size - self.asic_db.wait_for_field_match('ASIC_STATE:SAI_OBJECT_TYPE_BUFFER_POOL', self.ingress_lossless_pool_oid, ingress_lossless_pool_in_asicdb) - # make sure the size is still equal to xon in the profile - self.app_db.wait_for_field_match('BUFFER_PROFILE_TABLE', expectedProfile, profileInApplDb) - self.check_new_profile_in_asic_db(dvs, expectedProfile) - - # remove size configuration, new over subscribe ratio takes effect - ingress_lossless_pool_in_configdb['xoff'] = '0' - self.config_db.update_entry('BUFFER_POOL', 'ingress_lossless_pool', ingress_lossless_pool_in_configdb) - # shp size: (pg xoff * 2 - private headroom) / over subscribe ratio (4) - shp_size = str(int((2 * int(profileInApplDb['xoff']) - private_headroom) / 4)) - time.sleep(30) - ingress_lossless_pool_in_appldb['xoff'] = shp_size - self.app_db.wait_for_field_match('BUFFER_POOL_TABLE', 'ingress_lossless_pool', ingress_lossless_pool_in_appldb) - ingress_lossless_pool_in_asicdb['SAI_BUFFER_POOL_ATTR_XOFF_SIZE'] = shp_size - self.asic_db.wait_for_field_match('ASIC_STATE:SAI_OBJECT_TYPE_BUFFER_POOL', self.ingress_lossless_pool_oid, ingress_lossless_pool_in_asicdb) - # make sure the size is still equal to xon in the profile - self.app_db.wait_for_field_match('BUFFER_PROFILE_TABLE', expectedProfile, profileInApplDb) - self.check_new_profile_in_asic_db(dvs, expectedProfile) - - # remove over subscribe ratio configuration - default_lossless_buffer_parameter['over_subscribe_ratio'] = '0' - self.config_db.update_entry('DEFAULT_LOSSLESS_BUFFER_PARAMETER', 'AZURE', default_lossless_buffer_parameter) - # check whether shp size has been removed from both asic db and appl db - ingress_lossless_pool_in_appldb['xoff'] = '0' - self.app_db.wait_for_field_match('BUFFER_POOL_TABLE', 'ingress_lossless_pool', ingress_lossless_pool_in_appldb) - ingress_lossless_pool_in_asicdb['SAI_BUFFER_POOL_ATTR_XOFF_SIZE'] = '0' - self.asic_db.wait_for_field_match('ASIC_STATE:SAI_OBJECT_TYPE_BUFFER_POOL', self.ingress_lossless_pool_oid, ingress_lossless_pool_in_asicdb) - # make sure the size is equal to xon + xoff in the profile - profileInApplDb['size'] = str(int(profileInApplDb['xon']) + int(profileInApplDb['xoff'])) - self.app_db.wait_for_field_match('BUFFER_PROFILE_TABLE', expectedProfile, profileInApplDb) - self.check_new_profile_in_asic_db(dvs, expectedProfile) - - # remove lossless PG 3-4 on interface - self.config_db.delete_entry('BUFFER_PG', 'Ethernet0|3-4') - dvs.port_admin_set('Ethernet0', 'down') - - # Shutdown interface - dvs.port_admin_set('Ethernet0', 'down') - - self.cleanup_db(dvs) - - def test_shutdownPort(self, dvs, testlog): - self.setup_db(dvs) - - lossy_pg_reference_config_db = 'ingress_lossy_profile' - lossy_pg_reference_appl_db = 'ingress_lossy_profile' - lossy_queue_reference_config_db = 'egress_lossy_profile' - lossy_queue_reference_appl_db = 'egress_lossy_profile' - lossless_queue_reference_appl_db = 'egress_lossless_profile' - - lossy_pg_zero_reference = 'ingress_lossy_pg_zero_profile' - lossy_queue_zero_reference = 'egress_lossy_zero_profile' - lossless_queue_zero_reference = 'egress_lossless_zero_profile' - - # Startup interface - dvs.port_admin_set('Ethernet0', 'up') - - # Configure lossless PG 3-4 on interface - self.config_db.update_entry('BUFFER_PG', 'Ethernet0|3-4', {'profile': 'NULL'}) - expectedProfile = self.make_lossless_profile_name(self.originalSpeed, self.originalCableLen) - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:3-4", {"profile": expectedProfile}) - - # Shutdown port and check whether zero profiles have been applied on queues and the PG 0 - maximumQueues = int(self.bufferMaxParameter['max_queues']) - 1 - dvs.port_admin_set('Ethernet0', 'down') - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:0", {"profile": lossy_pg_zero_reference}) - self.app_db.wait_for_field_match("BUFFER_QUEUE_TABLE", "Ethernet0:0-2", {"profile": lossy_queue_zero_reference}) - self.app_db.wait_for_field_match("BUFFER_QUEUE_TABLE", "Ethernet0:3-4", {"profile": lossless_queue_zero_reference}) - self.app_db.wait_for_field_match("BUFFER_QUEUE_TABLE", "Ethernet0:5-6", {"profile": lossy_queue_zero_reference}) - self.app_db.wait_for_field_match("BUFFER_QUEUE_TABLE", "Ethernet0:7-{}".format(maximumQueues), {"profile": lossy_queue_zero_reference}) - self.app_db.wait_for_deleted_entry("BUFFER_PG_TABLE", "Ethernet0:3-4") - self.app_db.wait_for_deleted_entry("BUFFER_PROFILE", expectedProfile) - - # Add extra lossy and lossless PGs when a port is administratively down - self.config_db.update_entry('BUFFER_PG', 'Ethernet0|1', {'profile': lossy_pg_reference_config_db}) - self.config_db.update_entry('BUFFER_PG', 'Ethernet0|6', {'profile': 'NULL'}) - - # Add extra queue when a port is administratively down - self.config_db.update_entry('BUFFER_QUEUE', 'Ethernet0|8', {"profile": lossy_queue_reference_config_db}) - - # For queues, the slice in supported but not configured list should be '7-19'. - # After queue '8' is added, '7-19' should be removed and '7', '8', and '9-19' will be added - self.app_db.wait_for_deleted_entry("BUFFER_QUEUE_TABLE", "Ethernet0:7-{}".format(maximumQueues)) - self.app_db.wait_for_field_match("BUFFER_QUEUE_TABLE", "Ethernet0:7", {"profile": lossy_queue_zero_reference}) - self.app_db.wait_for_field_match("BUFFER_QUEUE_TABLE", "Ethernet0:8", {"profile": lossy_queue_zero_reference}) - self.app_db.wait_for_field_match("BUFFER_QUEUE_TABLE", "Ethernet0:9-{}".format(maximumQueues), {"profile": lossy_queue_zero_reference}) - # Make sure they have not been added to APPL_DB - time.sleep(30) - self.app_db.wait_for_deleted_entry("BUFFER_PG_TABLE", "Ethernet0:1") - self.app_db.wait_for_deleted_entry("BUFFER_PG_TABLE", "Ethernet0:6") - - # Startup port and check whether all the PGs have been added - dvs.port_admin_set('Ethernet0', 'up') - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:0", {"profile": lossy_pg_reference_appl_db}) - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:1", {"profile": lossy_pg_reference_appl_db}) - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:3-4", {"profile": expectedProfile}) - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:6", {"profile": expectedProfile}) - self.app_db.wait_for_field_match("BUFFER_QUEUE_TABLE", "Ethernet0:0-2", {"profile": lossy_queue_reference_appl_db}) - self.app_db.wait_for_field_match("BUFFER_QUEUE_TABLE", "Ethernet0:5-6", {"profile": lossy_queue_reference_appl_db}) - self.app_db.wait_for_field_match("BUFFER_QUEUE_TABLE", "Ethernet0:8", {"profile": lossy_queue_reference_appl_db}) - self.app_db.wait_for_field_match("BUFFER_QUEUE_TABLE", "Ethernet0:3-4", {"profile": lossless_queue_reference_appl_db}) - self.app_db.wait_for_deleted_entry("BUFFER_QUEUE_TABLE", "Ethernet0:7") - self.app_db.wait_for_deleted_entry("BUFFER_QUEUE_TABLE", "Ethernet0:9-{}".format(maximumQueues)) - - # Shutdown the port again to verify flow to remove buffer objects from an admin down port - dvs.port_admin_set('Ethernet0', 'down') - # First, check whether the objects have been correctly handled - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:0", {"profile": lossy_pg_zero_reference}) - self.app_db.wait_for_field_match("BUFFER_QUEUE_TABLE", "Ethernet0:0-2", {"profile": lossy_queue_zero_reference}) - self.app_db.wait_for_field_match("BUFFER_QUEUE_TABLE", "Ethernet0:3-4", {"profile": lossless_queue_zero_reference}) - self.app_db.wait_for_field_match("BUFFER_QUEUE_TABLE", "Ethernet0:5-6", {"profile": lossy_queue_zero_reference}) - self.app_db.wait_for_field_match("BUFFER_QUEUE_TABLE", "Ethernet0:7", {"profile": lossy_queue_zero_reference}) - self.app_db.wait_for_field_match("BUFFER_QUEUE_TABLE", "Ethernet0:8", {"profile": lossy_queue_zero_reference}) - self.app_db.wait_for_field_match("BUFFER_QUEUE_TABLE", "Ethernet0:9-{}".format(maximumQueues), {"profile": lossy_queue_zero_reference}) - self.app_db.wait_for_deleted_entry("BUFFER_PG_TABLE", "Ethernet0:3-4") - self.app_db.wait_for_deleted_entry("BUFFER_PG_TABLE", "Ethernet0:1") - self.app_db.wait_for_deleted_entry("BUFFER_PG_TABLE", "Ethernet0:6") - self.app_db.wait_for_deleted_entry("BUFFER_PROFILE", expectedProfile) - - # Remove buffer objects from an admon down port - self.config_db.delete_entry('BUFFER_QUEUE', 'Ethernet0|8') - self.config_db.delete_entry('BUFFER_PG', 'Ethernet0|1') - self.config_db.delete_entry('BUFFER_PG', 'Ethernet0|6') - - # Checking - self.app_db.wait_for_deleted_entry("BUFFER_QUEUE_TABLE", "Ethernet0:7") - self.app_db.wait_for_deleted_entry("BUFFER_QUEUE_TABLE", "Ethernet0:8") - self.app_db.wait_for_deleted_entry("BUFFER_QUEUE_TABLE", "Ethernet0:9-{}".format(maximumQueues)) - self.app_db.wait_for_field_match("BUFFER_QUEUE_TABLE", "Ethernet0:7-{}".format(maximumQueues), {"profile": lossy_queue_zero_reference}) - - # Startup again - dvs.port_admin_set('Ethernet0', 'up') - self.app_db.wait_for_field_match("BUFFER_QUEUE_TABLE", "Ethernet0:0-2", {"profile": lossy_queue_reference_appl_db}) - self.app_db.wait_for_field_match("BUFFER_QUEUE_TABLE", "Ethernet0:3-4", {"profile": lossless_queue_reference_appl_db}) - self.app_db.wait_for_field_match("BUFFER_QUEUE_TABLE", "Ethernet0:5-6", {"profile": lossy_queue_reference_appl_db}) - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:0", {"profile": lossy_pg_reference_appl_db}) - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:3-4", {"profile": expectedProfile}) - self.app_db.wait_for_deleted_entry("BUFFER_QUEUE_TABLE", "Ethernet0:7-{}".format(maximumQueues)) - - # Remove lossless PG 3-4 on interface - self.config_db.delete_entry('BUFFER_PG', 'Ethernet0|3-4') - - # Shutdown interface - dvs.port_admin_set('Ethernet0', 'down') - - self.cleanup_db(dvs) - - def test_autoNegPort(self, dvs, testlog): - self.setup_db(dvs) - - advertised_speeds = '10000,25000,50000' - maximum_advertised_speed = '50000' - if maximum_advertised_speed == self.originalSpeed: - # Let's make sure the configured speed isn't equal to maximum advertised speed - advertised_speeds = '10000,25000' - maximum_advertised_speed = '25000' - - # Startup interfaces - dvs.port_admin_set('Ethernet0', 'up') - - # Configure lossless PG 3-4 on the interface - self.config_db.update_entry('BUFFER_PG', 'Ethernet0|3-4', {'profile': 'NULL'}) - - # Enable port auto negotiation - dvs.port_field_set('Ethernet0','autoneg', 'on') - dvs.port_field_set('Ethernet0','adv_speeds', advertised_speeds) - - # Check the buffer profile. The maximum_advertised_speed should be used - expectedProfile = self.make_lossless_profile_name(maximum_advertised_speed, self.originalCableLen) - self.app_db.wait_for_entry("BUFFER_PG_TABLE", "Ethernet0:3-4") - self.app_db.wait_for_entry("BUFFER_PROFILE_TABLE", expectedProfile) - self.check_new_profile_in_asic_db(dvs, expectedProfile) - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:3-4", {"profile": expectedProfile}) - - # Configure another lossless PG on the interface - self.config_db.update_entry('BUFFER_PG', 'Ethernet0|6', {'profile': 'NULL'}) - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:6", {"profile": expectedProfile}) - - # Disable port auto negotiation - dvs.port_field_set('Ethernet0','autoneg', 'off') - - # Check the buffer profile. The configured speed should be used - expectedProfile = self.make_lossless_profile_name(self.originalSpeed, self.originalCableLen) - self.app_db.wait_for_entry("BUFFER_PROFILE_TABLE", expectedProfile) - self.check_new_profile_in_asic_db(dvs, expectedProfile) - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:3-4", {"profile": expectedProfile}) - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:6", {"profile": expectedProfile}) - - # Remove lossless PGs on the interface - self.config_db.delete_entry('BUFFER_PG', 'Ethernet0|3-4') - self.config_db.delete_entry('BUFFER_PG', 'Ethernet0|6') - - # Shutdown interface - dvs.port_admin_set('Ethernet0', 'down') - - self.cleanup_db(dvs) - - @pytest.mark.skip(reason="Failing. Under investigation") - def test_removeBufferPool(self, dvs, testlog): - self.setup_db(dvs) - # Initialize additional databases that are used by this test only - self.counter_db = dvs.get_counters_db() - self.flex_db = dvs.get_flex_db() - - try: - # Create a new pool - self.config_db.update_entry('BUFFER_POOL', 'ingress_test_pool', {'size': '0', 'mode': 'static', 'type': 'ingress'}) - - # Whether counterpoll is enabled? Enable it if not. - flex_counter = self.config_db.get_entry("FLEX_COUNTER_TABLE", "BUFFER_POOL_WATERMARK") - counter_poll_disabled = (not flex_counter or flex_counter["FLEX_COUNTER_STATUS"] != 'enable') - if counter_poll_disabled: - self.config_db.update_entry("FLEX_COUNTER_TABLE", "BUFFER_POOL_WATERMARK", {"FLEX_COUNTER_STATUS": "enable"}) - - # Check whether counter poll has been enabled - time.sleep(1) - poolmap = self.counter_db.wait_for_entry("COUNTERS_BUFFER_POOL_NAME_MAP", "") - assert poolmap["ingress_test_pool"] - self.flex_db.wait_for_entry("FLEX_COUNTER_TABLE", "BUFFER_POOL_WATERMARK_STAT_COUNTER:{}".format(poolmap["ingress_test_pool"])) - - self.config_db.delete_entry('BUFFER_POOL', 'ingress_test_pool') - oid_to_remove = poolmap.pop('ingress_test_pool') - self.counter_db.wait_for_field_match("COUNTERS_BUFFER_POOL_NAME_MAP", "", poolmap) - self.flex_db.wait_for_deleted_entry("FLEX_COUNTER_TABLE", "BUFFER_POOL_WATERMARK_STAT_COUNTER:{}".format(oid_to_remove)) - finally: - # Clean up: disable counterpoll if it was disabled - if counter_poll_disabled: - self.config_db.delete_entry("FLEX_COUNTER_TABLE", "BUFFER_POOL_WATERMARK") - - self.cleanup_db(dvs) - - def test_bufferPortMaxParameter(self, dvs, testlog): - self.setup_db(dvs) - - # Update log level so that we can analyze the log in case the test failed - logfvs = self.config_db.wait_for_entry("LOGGER", "buffermgrd") - old_log_level = logfvs.get("LOGLEVEL") - logfvs["LOGLEVEL"] = "INFO" - self.config_db.update_entry("LOGGER", "buffermgrd", logfvs) - - # Check whether port's maximum parameter has been exposed to STATE_DB - fvs = self.state_db.wait_for_entry("BUFFER_MAX_PARAM_TABLE", "Ethernet0") - assert int(fvs["max_queues"]) and int(fvs["max_priority_groups"]) - - _, oa_pid = dvs.runcmd("pgrep orchagent") - - try: - fvs["max_headroom_size"] = "122880" - self.state_db.update_entry("BUFFER_MAX_PARAM_TABLE", "Ethernet0", fvs) - - # Startup interface - dvs.port_admin_set('Ethernet0', 'up') - # Wait for the lossy profile to be handled - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:0", {"profile": "ingress_lossy_profile"}) - - # Stop orchagent to simulate the scenario that the system is during initialization - dvs.runcmd("kill -s SIGSTOP {}".format(oa_pid)) - - # Create a lossless profile - profile_fvs = {'xon': '19456', - 'xoff': '10240', - 'size': '29696', - 'dynamic_th': '0', - 'pool': 'ingress_lossless_pool'} - self.config_db.update_entry('BUFFER_PROFILE', 'test', profile_fvs) - - self.config_db.update_entry('BUFFER_PG', 'Ethernet0|3-4', {'profile': 'test'}) - - # Make sure the entry has been handled by buffermgrd and is pending on orchagent's queue - self.app_db.wait_for_field_match("_BUFFER_PG_TABLE", "Ethernet0:3-4", {"profile": "test"}) - - # Should not be added due to the maximum headroom exceeded - self.config_db.update_entry('BUFFER_PG', 'Ethernet0|1', {'profile': 'ingress_lossy_profile'}) - # Should not be added due to the maximum headroom exceeded - self.config_db.update_entry('BUFFER_PG', 'Ethernet0|6', {'profile': 'test'}) - - # Resume orchagent - dvs.runcmd("kill -s SIGCONT {}".format(oa_pid)) - - # Check whether BUFFER_PG_TABLE is updated as expected - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:3-4", {"profile": "test"}) - - keys = self.app_db.get_keys('BUFFER_PG_TABLE') - - assert 'Ethernet0:1' not in keys - assert 'Ethernet0:6' not in keys - - # Update the profile - profile_fvs['size'] = '28672' - profile_fvs['xoff'] = '9216' - self.config_db.update_entry('BUFFER_PROFILE', 'test', profile_fvs) - self.app_db.wait_for_field_match('BUFFER_PROFILE_TABLE', 'test', profile_fvs) - - # Verify a pending remove PG is not counted into the accumulative headroom - dvs.runcmd("kill -s SIGSTOP {}".format(oa_pid)) - - self.config_db.delete_entry('BUFFER_PG', 'Ethernet0|3-4') - # Should be added because PG 3-4 has been removed and there are sufficient headroom - self.config_db.update_entry('BUFFER_PG', 'Ethernet0|1', {'profile': 'ingress_lossy_profile'}) - - # Resume orchagent - dvs.runcmd("kill -s SIGCONT {}".format(oa_pid)) - - # Check whether BUFFER_PG_TABLE is updated as expected - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:1", {"profile": "ingress_lossy_profile"}) - finally: - dvs.runcmd("kill -s SIGCONT {}".format(oa_pid)) - - self.config_db.delete_entry('BUFFER_PG', 'Ethernet0|3-4') - self.config_db.delete_entry('BUFFER_PG', 'Ethernet0|1') - self.config_db.delete_entry('BUFFER_PG', 'Ethernet0|6') - self.config_db.delete_entry('BUFFER_PROFILE', 'test') - - fvs.pop("max_headroom_size") - self.state_db.delete_entry("BUFFER_MAX_PARAM_TABLE", "Ethernet0") - self.state_db.update_entry("BUFFER_MAX_PARAM_TABLE", "Ethernet0", fvs) - - if old_log_level: - logfvs["LOGLEVEL"] = old_log_level - self.config_db.update_entry("LOGGER", "buffermgrd", logfvs) - - dvs.port_admin_set('Ethernet0', 'down') - - self.cleanup_db(dvs) - - - def test_bufferPoolInitWithSHP(self, dvs, testlog): - self.setup_db(dvs) - - try: - # 1. Enable the shared headroom pool - default_lossless_buffer_parameter = self.config_db.get_entry('DEFAULT_LOSSLESS_BUFFER_PARAMETER', 'AZURE') - default_lossless_buffer_parameter['over_subscribe_ratio'] = '2' - self.config_db.update_entry('DEFAULT_LOSSLESS_BUFFER_PARAMETER', 'AZURE', default_lossless_buffer_parameter) - - # 2. Stop the orchagent - _, oa_pid = dvs.runcmd("pgrep orchagent") - dvs.runcmd("kill -s SIGSTOP {}".format(oa_pid)) - - # 3. Remove the size from CONFIG_DB|BUFFER_POOL.ingress_lossless_pool - original_ingress_lossless_pool = self.config_db.get_entry('BUFFER_POOL', 'ingress_lossless_pool') - try: - self.config_db.delete_field('BUFFER_POOL', 'ingress_lossless_pool', 'size') - self.config_db.delete_field('BUFFER_POOL', 'ingress_lossless_pool', 'xoff') - except Exception as e: - pass - - # 4. Remove the ingress_lossless_pool from the APPL_DB - self.app_db.delete_entry('BUFFER_POOL_TABLE', 'ingress_lossless_pool') - - # 5. Mock it by adding a "TABLE_SET" entry to trigger the fallback logic - self.app_db.update_entry("BUFFER_PG_TABLE_SET", "", {"NULL": "NULL"}) - - # 6. Invoke the lua plugin - _, output = dvs.runcmd("redis-cli --eval /usr/share/swss/buffer_pool_vs.lua") - assert "ingress_lossless_pool:2048:1024" in output - - finally: - self.config_db.update_entry('BUFFER_POOL', 'ingress_lossless_pool', original_ingress_lossless_pool) - self.config_db.delete_entry('DEFAULT_LOSSLESS_BUFFER_PARAMETER', 'AZURE') - self.app_db.delete_entry("BUFFER_PG_TABLE_SET", "") - dvs.runcmd("kill -s SIGCONT {}".format(oa_pid)) diff --git a/tests/test_buffer_mode.py b/tests/test_buffer_mode.py deleted file mode 100644 index 5d5eaac8b1..0000000000 --- a/tests/test_buffer_mode.py +++ /dev/null @@ -1,27 +0,0 @@ -import pytest -import time - -class TestBufferModel(object): - def test_bufferModel(self, dvs, testlog): - config_db = dvs.get_config_db() - metadata = config_db.get_entry("DEVICE_METADATA", "localhost") - assert metadata["buffer_model"] == "traditional" - - def test_update_bufferModel(self, dvs, testlog): - config_db = dvs.get_config_db() - app_db = dvs.get_app_db() - keys = app_db.get_keys("BUFFER_POOL_TABLE") - num_keys = len(keys) - - try: - fvs = {'buffer_model' : 'dynamic'} - config_db.update_entry("DEVICE_METADATA", "localhost", fvs) - fvs = {'mode':'dynamic', 'type':'egress'} - config_db.update_entry("BUFFER_POOL", "temp_pool", fvs) - time.sleep(2) - app_db.wait_for_n_keys("BUFFER_POOL_TABLE", num_keys) - - finally: - config_db.delete_entry("BUFFER_POOL", "temp_pool") - fvs = {'buffer_model' : 'traditional'} - config_db.update_entry("DEVICE_METADATA", "localhost", fvs) diff --git a/tests/test_buffer_traditional.py b/tests/test_buffer_traditional.py deleted file mode 100644 index 5e1f26bd50..0000000000 --- a/tests/test_buffer_traditional.py +++ /dev/null @@ -1,355 +0,0 @@ -import pytest -import time - - -class TestBuffer(object): - from conftest import DockerVirtualSwitch - lossless_pgs = [] - INTF = "Ethernet0" - - def setup_db(self, dvs): - from conftest import ApplDbValidator, AsicDbValidator - from dvslib.dvs_database import DVSDatabase - - self.app_db: ApplDbValidator = dvs.get_app_db() - self.asic_db: AsicDbValidator = dvs.get_asic_db() - self.config_db: DVSDatabase = dvs.get_config_db() - self.counter_db: DVSDatabase = dvs.get_counters_db() - - # enable PG watermark - self.set_pg_wm_status('enable') - - def get_pfc_enable_queues(self): - qos_map = self.config_db.get_entry("PORT_QOS_MAP", self.INTF) - return qos_map['pfc_enable'].split(',') - - def get_pg_oid(self, pg): - fvs = dict() - fvs = self.counter_db.get_entry("COUNTERS_PG_NAME_MAP", "") - return fvs[pg] - - def set_pg_wm_status(self, state): - fvs = {'FLEX_COUNTER_STATUS': state} - self.config_db.update_entry("FLEX_COUNTER_TABLE", "PG_WATERMARK", fvs) - time.sleep(1) - - def teardown(self): - # disable PG watermark - self.set_pg_wm_status('disable') - - def get_asic_buf_profile(self): - return set(self.asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_BUFFER_PROFILE")) - - def check_new_profile_in_asic_db(self, profile): - retry_count = 0 - self.new_profile = None - while retry_count < 5: - retry_count += 1 - diff = set(self.asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_BUFFER_PROFILE")) - self.orig_profiles - if len(diff) == 1: - self.new_profile = diff.pop() - break - else: - time.sleep(1) - assert self.new_profile, "Can't get SAI OID for newly created profile {} after retry {} times".format(profile, retry_count) - - def get_asic_buf_pg_profiles(self): - self.buf_pg_profile = dict() - for pg in self.pg_name_map: - buf_pg_entries = self.asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP", self.pg_name_map[pg]) - self.buf_pg_profile[pg] = buf_pg_entries["SAI_INGRESS_PRIORITY_GROUP_ATTR_BUFFER_PROFILE"] - - def change_cable_len(self, cable_len, extra_port=None): - fvs = dict() - fvs[self.INTF] = cable_len - if extra_port: - fvs[extra_port] = cable_len - self.config_db.update_entry("CABLE_LENGTH", "AZURE", fvs) - - def set_port_qos_table(self, port, pfc_enable_flag): - fvs=dict() - fvs['pfc_enable'] = pfc_enable_flag - self.config_db.update_entry("PORT_QOS_MAP", port, fvs) - self.lossless_pgs = pfc_enable_flag.split(',') - - def get_pg_name_map(self): - pg_name_map = dict() - for pg in self.lossless_pgs: - pg_name = "{}:{}".format(self.INTF, pg) - pg_name_map[pg_name] = self.get_pg_oid(pg_name) - return pg_name_map - - def check_syslog(self, dvs, marker, err_log, expected_cnt=1): - (exitcode, num) = dvs.runcmd(['sh', '-c', "awk \'/%s/,ENDFILE {print;}\' /var/log/syslog | grep \"%s\" | wc -l" % (marker, err_log)]) - assert num.strip() >= str(expected_cnt) - - @pytest.fixture - def setup_teardown_test(self, dvs): - self.setup_db(dvs) - self.set_port_qos_table(self.INTF, '3,4') - self.lossless_pg_combinations = ['3-4'] - time.sleep(2) - - yield - - self.teardown() - - def test_zero_cable_len_profile_update(self, dvs, setup_teardown_test): - orig_cable_len = None - orig_speed = None - try: - # get orig cable length and speed - fvs = self.config_db.get_entry("CABLE_LENGTH", "AZURE") - orig_cable_len = fvs[self.INTF] - if orig_cable_len == "0m": - fvs[self.INTF] = "300m" - cable_len_before_test = "300m" - self.config_db.update_entry("CABLE_LENGTH", "AZURE", fvs) - else: - cable_len_before_test = orig_cable_len - fvs = self.config_db.get_entry("PORT", self.INTF) - orig_speed = fvs["speed"] - - if orig_speed == "100000": - test_speed = "40000" - elif orig_speed == "40000": - test_speed = "100000" - test_cable_len = "0m" - - dvs.port_admin_set(self.INTF, "up") - # Make sure the buffer PG has been created - orig_lossless_profile = "pg_lossless_{}_{}_profile".format(orig_speed, cable_len_before_test) - self.app_db.wait_for_entry("BUFFER_PROFILE_TABLE", orig_lossless_profile) - self.pg_name_map = self.get_pg_name_map() - self.orig_profiles = self.get_asic_buf_profile() - - # check if the lossless profile for the test speed is already present - fvs = dict() - new_lossless_profile = "pg_lossless_{}_{}_profile".format(test_speed, cable_len_before_test) - fvs = self.app_db.get_entry("BUFFER_PROFILE_TABLE", new_lossless_profile) - if len(fvs): - profile_exp_cnt_diff = 0 - else: - profile_exp_cnt_diff = 1 - - # get the orig buf profiles attached to the pgs - self.get_asic_buf_pg_profiles() - - # change cable length to 'test_cable_len' - self.change_cable_len(test_cable_len) - - # change intf speed to 'test_speed' - dvs.port_field_set(self.INTF, "speed", test_speed) - test_lossless_profile = "pg_lossless_{}_{}_profile".format(test_speed, test_cable_len) - # buffer profile should not get created - self.app_db.wait_for_deleted_entry("BUFFER_PROFILE_TABLE", test_lossless_profile) - - # buffer pgs should still point to the original buffer profile - for pg in self.lossless_pg_combinations: - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", self.INTF + ":" + pg, {"profile": orig_lossless_profile}) - fvs = dict() - for pg in self.pg_name_map: - fvs["SAI_INGRESS_PRIORITY_GROUP_ATTR_BUFFER_PROFILE"] = self.buf_pg_profile[pg] - self.asic_db.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP", self.pg_name_map[pg], fvs) - - # change cable length to 'cable_len_before_test' - self.change_cable_len(cable_len_before_test) - - # change intf speed to 'test_speed' - dvs.port_field_set(self.INTF, "speed", test_speed) - if profile_exp_cnt_diff != 0: - # new profile will get created - self.app_db.wait_for_entry("BUFFER_PROFILE_TABLE", new_lossless_profile) - self.check_new_profile_in_asic_db(new_lossless_profile) - # verify that buffer pgs point to the new profile - fvs = dict() - for pg in self.pg_name_map: - fvs["SAI_INGRESS_PRIORITY_GROUP_ATTR_BUFFER_PROFILE"] = self.new_profile - self.asic_db.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP", self.pg_name_map[pg], fvs) - - else: - # verify that buffer pgs do not point to the old profile since we cannot deduce the new profile oid - fvs = dict() - for pg in self.pg_name_map: - fvs["SAI_INGRESS_PRIORITY_GROUP_ATTR_BUFFER_PROFILE"] = self.buf_pg_profile[pg] - self.asic_db.wait_for_field_negative_match("ASIC_STATE:SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP", self.pg_name_map[pg], fvs) - finally: - if orig_cable_len: - self.change_cable_len(orig_cable_len) - if orig_speed: - dvs.port_field_set(self.INTF, "speed", orig_speed) - dvs.port_admin_set(self.INTF, "down") - - # To verify the BUFFER_PG is not hardcoded to 3,4 - # buffermgrd will read 'pfc_enable' entry and apply lossless profile to that queue - def test_buffer_pg_update(self, dvs, setup_teardown_test): - orig_cable_len = None - orig_speed = None - test_speed = None - extra_port = "Ethernet4" - try: - # Retrieve cable len - fvs_cable_len = self.config_db.get_entry("CABLE_LENGTH", "AZURE") - orig_cable_len = fvs_cable_len[self.INTF] - if orig_cable_len == "0m": - cable_len_for_test = "300m" - fvs_cable_len[self.INTF] = cable_len_for_test - fvs_cable_len[extra_port] = cable_len_for_test - - self.config_db.update_entry("CABLE_LENGTH", "AZURE", fvs_cable_len) - else: - cable_len_for_test = orig_cable_len - # Ethernet4 is set to up, while no 'pfc_enable' available. `Ethernet0` is not supposed to be impacted - dvs.port_admin_set(extra_port, "up") - - dvs.port_admin_set(self.INTF, "up") - - # Retrieve port speed - fvs_port = self.config_db.get_entry("PORT", self.INTF) - orig_speed = fvs_port["speed"] - - # Make sure the buffer PG has been created - orig_lossless_profile = "pg_lossless_{}_{}_profile".format(orig_speed, cable_len_for_test) - self.app_db.wait_for_entry("BUFFER_PROFILE_TABLE", orig_lossless_profile) - self.pg_name_map = self.get_pg_name_map() - self.orig_profiles = self.get_asic_buf_profile() - - # get the orig buf profiles attached to the pgs - self.get_asic_buf_pg_profiles() - - # Update port speed - if orig_speed == "100000": - test_speed = "40000" - elif orig_speed == "40000": - test_speed = "100000" - # change intf speed to 'test_speed' - dvs.port_field_set(self.INTF, "speed", test_speed) - dvs.port_field_set(extra_port, "speed", test_speed) - # Verify new profile is generated - new_lossless_profile = "pg_lossless_{}_{}_profile".format(test_speed, cable_len_for_test) - self.app_db.wait_for_entry("BUFFER_PROFILE_TABLE", new_lossless_profile) - - # Verify BUFFER_PG is updated - for pg in self.lossless_pg_combinations: - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", self.INTF + ":" + pg, {"profile": new_lossless_profile}) - - fvs_negative = {} - for pg in self.pg_name_map: - # verify that buffer pgs do not point to the old profile since we cannot deduce the new profile oid - fvs_negative["SAI_INGRESS_PRIORITY_GROUP_ATTR_BUFFER_PROFILE"] = self.buf_pg_profile[pg] - self.asic_db.wait_for_field_negative_match("ASIC_STATE:SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP", self.pg_name_map[pg], fvs_negative) - - # Add pfc_enable field for extra port - self.set_port_qos_table(extra_port, '2,3,4,6') - self.lossless_pg_combinations = ['2-4', '6'] - time.sleep(1) - # Verify BUFFER_PG is updated when pfc_enable is available - for pg in self.lossless_pg_combinations: - self.app_db.wait_for_field_match("BUFFER_PG_TABLE", extra_port + ":" + pg, {"profile": new_lossless_profile}) - finally: - if orig_cable_len: - self.change_cable_len(orig_cable_len, extra_port) - if orig_speed: - dvs.port_field_set(self.INTF, "speed", orig_speed) - dvs.port_field_set(extra_port, "speed", orig_speed) - dvs.port_admin_set(self.INTF, "down") - dvs.port_admin_set(extra_port, "down") - - def test_no_pg_profile_for_speed_and_length(self, dvs: DockerVirtualSwitch, setup_teardown_test): - """ - Test to verify that buffermgrd correctly handles a scenario where no PG profile - is configured for a given speed (10000) and cable length (80m) for Ethernet0 (self.INTF). - """ - orig_cable_len = None - orig_port_speed = None - orig_port_status = None - orig_port_qos_map = None - - test_cable_len = "80m" # cable length must not exist for test_speed in - test_speed = "10000" - test_port_status ="down" # can be up or down, but it must exist in port configuration - test_port_pfc_enable = "3,4" # does not matter, but must exist - - try: - ################################## - ## Save original configurations ## - ################################## - - # Save original cable length - fvs_cable_len = self.config_db.get_entry("CABLE_LENGTH", "AZURE") - orig_cable_len = fvs_cable_len.get(self.INTF) if fvs_cable_len else None - - # Save original port speed and admin status - fvs_port = self.config_db.get_entry("PORT", self.INTF) - orig_port_speed = fvs_port.get("speed") if fvs_port else None - orig_port_status = fvs_port.get("admin_status") if fvs_port else None - - # Save original port qos map - fvs_qos_map = self.config_db.get_entry("PORT_QOS_MAP", self.INTF) - orig_cable_len = fvs_qos_map.get("pfc_enable") if fvs_qos_map else None - - ###################################### - ## Send configurations to CONFIG_DB ## - ###################################### - - # Configure cable length - self.change_cable_len(test_cable_len) - - # Configure port speed - dvs.port_field_set(self.INTF, "speed", test_speed) - - # Configure PFC enable - self.set_port_qos_table(self.INTF, test_port_pfc_enable) - - # Add marker to log to make syslog verification easier - # Set before setting admin status to not miss syslog - marker = dvs.add_log_marker() - - # Configure admin status - dvs.port_admin_set(self.INTF, test_port_status) - - # Wait for buffermgrd to process the changes - time.sleep(2) - - ################## - ## Verification ## - ################## - - - # Check syslog if this error is present. This is expected. - self.check_syslog(dvs, marker, "Failed to process invalid entry, drop it") - - finally: - ############################### - ## Revert to original values ## - ############################### - - # Revert values to original values - # If there are none, then assume entry/field never existed and should be deleted - - # Revert cable length - if orig_cable_len: - self.change_cable_len(orig_cable_len) - else: - self.config_db.delete_entry("CABLE_LENGTH", "AZURE") - - # Revert port speed - if orig_port_speed: - dvs.port_field_set(self.INTF, "speed", orig_port_speed) - else: - self.config_db.delete_field("PORT", self.INTF, "speed") - - # Revert admin status - if orig_port_status: - dvs.port_admin_set(self.INTF, orig_port_status) - else: - self.config_db.delete_field("PORT", self.INTF, "admin_status") - - # Revert port qos map - if orig_port_qos_map: - self.config_db.update_entry("PORT_QOS_MAP", self.INTF, orig_port_qos_map) - else: - self.config_db.delete_entry("PORT_QOS_MAP", self.INTF) - - - diff --git a/tests/test_copp.py b/tests/test_copp.py deleted file mode 100644 index 4163300a31..0000000000 --- a/tests/test_copp.py +++ /dev/null @@ -1,878 +0,0 @@ -import time -import os - -from swsscommon import swsscommon - - -field_to_sai_attr = { - "queue": "SAI_HOSTIF_TRAP_GROUP_ATTR_QUEUE", - "meter_type": "SAI_POLICER_ATTR_METER_TYPE", - "mode": "SAI_POLICER_ATTR_MODE", - "trap_action": "SAI_HOSTIF_TRAP_ATTR_PACKET_ACTION", - "trap_priority": "SAI_HOSTIF_TRAP_ATTR_TRAP_PRIORITY", - "cbs": "SAI_POLICER_ATTR_CBS", - "cir": "SAI_POLICER_ATTR_CIR", - "red_action": "SAI_POLICER_ATTR_RED_PACKET_ACTION" -} - -field_to_sai_obj_type = { - "queue": "SAI_OBJECT_TYPE_HOSTIF_TRAP_GROUP", - "meter_type": "SAI_OBJECT_TYPE_POLICER", - "mode": "SAI_OBJECT_TYPE_POLICER", - "trap_action": "SAI_OBJECT_TYPE_HOSTIF_TRAP", - "trap_priority": "SAI_OBJECT_TYPE_HOSTIF_TRAP", - "cbs": "SAI_OBJECT_TYPE_POLICER", - "cir": "SAI_OBJECT_TYPE_POLICER", - "red_action": "SAI_OBJECT_TYPE_POLICER", - "genetlink_mcgrp_name": "SAI_OBJECT_TYPE_HOSTIF", - "genetlink_name": "SAI_OBJECT_TYPE_HOSTIF" -} - -traps_to_trap_type = { - "stp": "SAI_HOSTIF_TRAP_TYPE_STP", - "lacp": "SAI_HOSTIF_TRAP_TYPE_LACP", - "eapol": "SAI_HOSTIF_TRAP_TYPE_EAPOL", - "lldp": "SAI_HOSTIF_TRAP_TYPE_LLDP", - "pvrst": "SAI_HOSTIF_TRAP_TYPE_PVRST", - "igmp_query": "SAI_HOSTIF_TRAP_TYPE_IGMP_TYPE_QUERY", - "igmp_leave": "SAI_HOSTIF_TRAP_TYPE_IGMP_TYPE_LEAVE", - "igmp_v1_report": "SAI_HOSTIF_TRAP_TYPE_IGMP_TYPE_V1_REPORT", - "igmp_v2_report": "SAI_HOSTIF_TRAP_TYPE_IGMP_TYPE_V2_REPORT", - "igmp_v3_report": "SAI_HOSTIF_TRAP_TYPE_IGMP_TYPE_V3_REPORT", - "sample_packet": "SAI_HOSTIF_TRAP_TYPE_SAMPLEPACKET", - "switch_cust_range": "SAI_HOSTIF_TRAP_TYPE_SWITCH_CUSTOM_RANGE_BASE", - "arp_req": "SAI_HOSTIF_TRAP_TYPE_ARP_REQUEST", - "arp_resp": "SAI_HOSTIF_TRAP_TYPE_ARP_RESPONSE", - "dhcp": "SAI_HOSTIF_TRAP_TYPE_DHCP", - "ospf": "SAI_HOSTIF_TRAP_TYPE_OSPF", - "pim": "SAI_HOSTIF_TRAP_TYPE_PIM", - "vrrp": "SAI_HOSTIF_TRAP_TYPE_VRRP", - "bgp": "SAI_HOSTIF_TRAP_TYPE_BGP", - "dhcpv6": "SAI_HOSTIF_TRAP_TYPE_DHCPV6", - "ospfv6": "SAI_HOSTIF_TRAP_TYPE_OSPFV6", - "isis": "SAI_HOSTIF_TRAP_TYPE_ISIS", - "vrrpv6": "SAI_HOSTIF_TRAP_TYPE_VRRPV6", - "bgpv6": "SAI_HOSTIF_TRAP_TYPE_BGPV6", - "neigh_discovery": "SAI_HOSTIF_TRAP_TYPE_IPV6_NEIGHBOR_DISCOVERY", - "mld_v1_v2": "SAI_HOSTIF_TRAP_TYPE_IPV6_MLD_V1_V2", - "mld_v1_report": "SAI_HOSTIF_TRAP_TYPE_IPV6_MLD_V1_REPORT", - "mld_v1_done": "SAI_HOSTIF_TRAP_TYPE_IPV6_MLD_V1_DONE", - "mld_v2_report": "SAI_HOSTIF_TRAP_TYPE_MLD_V2_REPORT", - "ip2me": "SAI_HOSTIF_TRAP_TYPE_IP2ME", - "ssh": "SAI_HOSTIF_TRAP_TYPE_SSH", - "snmp": "SAI_HOSTIF_TRAP_TYPE_SNMP", - "router_custom_range": "SAI_HOSTIF_TRAP_TYPE_ROUTER_CUSTOM_RANGE_BASE", - "l3_mtu_error": "SAI_HOSTIF_TRAP_TYPE_L3_MTU_ERROR", - "ttl_error": "SAI_HOSTIF_TRAP_TYPE_TTL_ERROR", - "udld": "SAI_HOSTIF_TRAP_TYPE_UDLD", - "bfd": "SAI_HOSTIF_TRAP_TYPE_BFD", - "bfdv6": "SAI_HOSTIF_TRAP_TYPE_BFDV6", - "src_nat_miss": "SAI_HOSTIF_TRAP_TYPE_SNAT_MISS", - "dest_nat_miss": "SAI_HOSTIF_TRAP_TYPE_DNAT_MISS", - "ldp": "SAI_HOSTIF_TRAP_TYPE_LDP", - "bfd_micro": "SAI_HOSTIF_TRAP_TYPE_BFD_MICRO", - "bfdv6_micro": "SAI_HOSTIF_TRAP_TYPE_BFDV6_MICRO" - } - -copp_group_default = { - "queue": "0", - "meter_type":"packets", - "mode":"sr_tcm", - "cir":"600", - "cbs":"600", - "red_action":"drop" -} - -copp_group_queue4_group1 = { - "trap_action":"trap", - "trap_priority":"4", - "queue": "4" -} - -copp_group_queue4_group2 = { - "trap_action":"copy", - "trap_priority":"4", - "queue": "4", - "meter_type":"packets", - "mode":"sr_tcm", - "cir":"600", - "cbs":"600", - "red_action":"drop" -} - -copp_group_queue4_group3 = { - "trap_action":"trap", - "trap_priority":"4", - "queue": "4" -} - -copp_group_queue1_group1 = { - "trap_action":"trap", - "trap_priority":"1", - "queue": "1", - "meter_type":"packets", - "mode":"sr_tcm", - "cir":"6000", - "cbs":"6000", - "red_action":"drop" -} - -copp_group_queue1_group2 = { - "trap_action":"trap", - "trap_priority":"1", - "queue": "1", - "meter_type":"packets", - "mode":"sr_tcm", - "cir":"600", - "cbs":"600", - "red_action":"drop" -} - -copp_group_queue2_group1 = { - "cbs": "1000", - "cir": "1000", - "genetlink_mcgrp_name": "packets", - "genetlink_name": "psample", - "meter_type": "packets", - "mode": "sr_tcm", - "queue": "2", - "red_action": "drop", - "trap_action": "trap", - "trap_priority": "1" -} - -copp_group_queue5_group1 = { - "cbs": "2000", - "cir": "2000", - "meter_type": "packets", - "mode": "sr_tcm", - "queue": "5", - "red_action": "drop", - "trap_action": "trap", - "trap_priority": "5" -} - -copp_trap = { - "bgp": ["bgp;bgpv6", copp_group_queue4_group1], - "lacp": ["lacp", copp_group_queue4_group1, "always_enabled"], - "arp": ["arp_req;arp_resp;neigh_discovery", copp_group_queue4_group2, "always_enabled"], - "lldp": ["lldp", copp_group_queue4_group3], - "dhcp": ["dhcp;dhcpv6", copp_group_queue4_group3], - "udld": ["udld", copp_group_queue4_group3, "always_enabled"], - "ip2me": ["ip2me", copp_group_queue1_group1, "always_enabled"], - "nat": ["src_nat_miss;dest_nat_miss", copp_group_queue1_group2], - "sflow": ["sample_packet", copp_group_queue2_group1], - "ttl": ["ttl_error", copp_group_default] -} - -disabled_traps = ["sample_packet"] - -policer_meter_map = { - "packets": "SAI_METER_TYPE_PACKETS", - "bytes": "SAI_METER_TYPE_BYTES" -} - -policer_mode_map = { - "sr_tcm": "SAI_POLICER_MODE_SR_TCM", - "tr_tcm": "SAI_POLICER_MODE_TR_TCM", - "storm": "SAI_POLICER_MODE_STORM_CONTROL" -} - - -packet_action_map = { - "drop": "SAI_PACKET_ACTION_DROP", - "forward": "SAI_PACKET_ACTION_FORWARD", - "copy": "SAI_PACKET_ACTION_COPY", - "copy_cancel": "SAI_PACKET_ACTION_COPY_CANCEL", - "trap": "SAI_PACKET_ACTION_TRAP", - "log": "SAI_PACKET_ACTION_LOG", - "deny": "SAI_PACKET_ACTION_DENY", - "transit": "SAI_PACKET_ACTION_TRANSIT" -} - -class TestCopp(object): - def setup_copp(self, dvs): - self.adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - self.cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) - self.trap_atbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_HOSTIF_TRAP") - self.trap_group_atbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_HOSTIF_TRAP_GROUP") - self.policer_atbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_POLICER") - self.hostiftbl_atbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_HOSTIF_TABLE_ENTRY") - self.hostif_atbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_HOSTIF") - self.trap_ctbl = swsscommon.Table(self.cdb, "COPP_TRAP") - self.trap_group_ctbl = swsscommon.Table(self.cdb, "COPP_GROUP") - self.feature_tbl = swsscommon.Table(self.cdb, "FEATURE") - fvs = swsscommon.FieldValuePairs([("state", "disabled")]) - self.feature_tbl.set("sflow", fvs) - time.sleep(2) - - - def validate_policer(self, policer_oid, field, value): - (status, fvs) = self.policer_atbl.get(policer_oid) - assert status == True - attr = field_to_sai_attr[field] - - attr_value = value - if field == "mode": - attr_value = policer_mode_map[value] - elif field == "meter_type": - attr_value = policer_meter_map[value] - elif field == "red_action": - attr_value = packet_action_map[value] - - for fv in fvs: - if (fv[0] == attr): - assert attr_value == fv[1] - - def validate_trap_group(self, trap_oid, trap_group): - (status, trap_fvs) = self.trap_atbl.get(trap_oid) - assert status == True - trap_group_oid = "" - policer_oid= "" - queue = "" - trap_action = "" - trap_priority = "" - - for fv in trap_fvs: - if fv[0] == "SAI_HOSTIF_TRAP_ATTR_PACKET_ACTION": - trap_action = fv[1] - elif fv[0] == "SAI_HOSTIF_TRAP_ATTR_TRAP_PRIORITY": - trap_priority = fv[1] - elif fv[0] == "SAI_HOSTIF_TRAP_ATTR_TRAP_GROUP": - trap_group_oid = fv[1] - - if trap_group_oid != "" and trap_group_oid != "oid:0x0": - (status, fvs) = self.trap_group_atbl.get(trap_group_oid) - assert status == True - for fv in fvs: - if fv[0] == "SAI_HOSTIF_TRAP_GROUP_ATTR_POLICER": - policer_oid = fv[1] - elif fv[0] == "SAI_HOSTIF_TRAP_GROUP_ATTR_QUEUE": - queue = fv[1] - - for keys in trap_group: - obj_type = field_to_sai_obj_type[keys] - if obj_type == "SAI_OBJECT_TYPE_POLICER": - assert policer_oid != "" - assert policer_oid != "oid:0x0" - self.validate_policer(policer_oid, keys, trap_group[keys]) - - elif obj_type == "SAI_OBJECT_TYPE_HOSTIF_TRAP_GROUP": - assert trap_group_oid != "" - assert trap_group_oid != "oid:0x0" - if keys == "queue": - assert queue == trap_group[keys] - else: - assert 0 - - elif obj_type == "SAI_OBJECT_TYPE_HOSTIF_TRAP": - if keys == "trap_action": - assert trap_action == packet_action_map[trap_group[keys]] - elif keys == "trap_priority": - assert trap_priority == trap_group[keys] - - elif obj_type == "SAI_OBJECT_TYPE_HOSTIF": - host_tbl_keys = self.hostiftbl_atbl.getKeys() - host_tbl_key = None - for host_tbl_entry in host_tbl_keys: - (status, fvs) = self.hostiftbl_atbl.get(host_tbl_entry) - assert status == True - for fv in fvs: - if fv[0] == "SAI_HOSTIF_TABLE_ENTRY_ATTR_TRAP_ID": - if fv[1] == trap_oid: - host_tbl_key = host_tbl_entry - break - if host_tbl_key != None: - break - assert host_tbl_key != None - (status, fvs) = self.hostiftbl_atbl.get(host_tbl_key) - hostif = None - for fv in fvs: - if fv[0] == "SAI_HOSTIF_TABLE_ENTRY_ATTR_HOST_IF": - hostif = fv[1] - elif fv[0] == "SAI_HOSTIF_TABLE_ENTRY_ATTR_CHANNEL_TYPE": - assert fv[1] == "SAI_HOSTIF_TABLE_ENTRY_CHANNEL_TYPE_GENETLINK" - assert hostif != None - (status, fvs) = self.hostif_atbl.get(hostif) - assert status == True - for fv in fvs: - if keys == "genetlink_mcgrp_name": - if fv[0] == "SAI_HOSTIF_ATTR_GENETLINK_MCGRP_NAME": - assert fv[1] == trap_group[keys] - if keys == "genetlink_name": - if fv[0] == "SAI_HOSTIF_ATTR_NAME": - assert fv[1] == trap_group[keys] - - def test_defaults(self, dvs, testlog): - self.setup_copp(dvs) - trap_keys = self.trap_atbl.getKeys() - for traps in copp_trap: - trap_info = copp_trap[traps] - trap_ids = trap_info[0].split(";") - trap_group = trap_info[1] - always_enabled = False - if len(trap_info) > 2: - always_enabled = True - for trap_id in trap_ids: - trap_type = traps_to_trap_type[trap_id] - trap_found = False - trap_group_oid = "" - for key in trap_keys: - (status, fvs) = self.trap_atbl.get(key) - assert status == True - for fv in fvs: - if fv[0] == "SAI_HOSTIF_TRAP_ATTR_TRAP_TYPE": - if fv[1] == trap_type: - trap_found = True - if trap_found: - self.validate_trap_group(key,trap_group) - break - if trap_id not in disabled_traps: - assert trap_found == True - - - def test_restricted_trap_sflow(self, dvs, testlog): - self.setup_copp(dvs) - fvs = swsscommon.FieldValuePairs([("state", "enabled")]) - self.feature_tbl.set("sflow", fvs) - time.sleep(2) - global copp_trap - - trap_keys = self.trap_atbl.getKeys() - for traps in copp_trap: - trap_info = copp_trap[traps] - trap_ids = trap_info[0].split(";") - trap_group = trap_info[1] - always_enabled = False - if len(trap_info) > 2: - always_enabled = True - if "sample_packet" not in trap_ids: - continue - trap_found = False - trap_type = traps_to_trap_type["sample_packet"] - for key in trap_keys: - (status, fvs) = self.trap_atbl.get(key) - assert status == True - for fv in fvs: - if fv[0] == "SAI_HOSTIF_TRAP_ATTR_TRAP_TYPE": - if fv[1] == trap_type: - trap_found = True - if trap_found: - self.validate_trap_group(key,trap_group) - break - assert trap_found == True - - - def test_policer_set(self, dvs, testlog): - self.setup_copp(dvs) - fvs = swsscommon.FieldValuePairs([("cbs", "900")]) - self.trap_group_ctbl.set("queue4_group2", fvs) - copp_group_queue4_group2["cbs"] = "900" - time.sleep(2) - global copp_trap - - trap_keys = self.trap_atbl.getKeys() - for traps in copp_trap: - trap_info = copp_trap[traps] - trap_ids = trap_info[0].split(";") - trap_group = trap_info[1] - always_enabled = False - if len(trap_info) > 2: - always_enabled = True - if trap_group != copp_group_queue4_group2: - continue - for trap_id in trap_ids: - trap_type = traps_to_trap_type[trap_id] - trap_found = False - trap_group_oid = "" - for key in trap_keys: - (status, fvs) = self.trap_atbl.get(key) - assert status == True - for fv in fvs: - if fv[0] == "SAI_HOSTIF_TRAP_ATTR_TRAP_TYPE": - if fv[1] == trap_type: - trap_found = True - if trap_found: - self.validate_trap_group(key,trap_group) - break - if trap_id not in disabled_traps: - assert trap_found == True - - def test_trap_group_set(self, dvs, testlog): - self.setup_copp(dvs) - global copp_trap - traps = "bgp,bgpv6" - fvs = swsscommon.FieldValuePairs([("trap_group", "queue1_group1")]) - self.trap_ctbl.set("bgp", fvs) - - for c_trap in copp_trap: - trap_info = copp_trap[c_trap] - ids = trap_info[0].replace(';', ',') - if traps == ids: - break - - trap_info[1] = copp_group_queue1_group1 - time.sleep(2) - - trap_keys = self.trap_atbl.getKeys() - trap_ids = traps.split(",") - trap_group = trap_info[1] - for trap_id in trap_ids: - trap_type = traps_to_trap_type[trap_id] - trap_found = False - trap_group_oid = "" - for key in trap_keys: - (status, fvs) = self.trap_atbl.get(key) - assert status == True - for fv in fvs: - if fv[0] == "SAI_HOSTIF_TRAP_ATTR_TRAP_TYPE": - if fv[1] == trap_type: - trap_found = True - if trap_found: - self.validate_trap_group(key,trap_group) - break - if trap_id not in disabled_traps: - assert trap_found == True - - def test_trap_ids_set(self, dvs, testlog): - self.setup_copp(dvs) - global copp_trap - traps = "bgp" - fvs = swsscommon.FieldValuePairs([("trap_ids", traps)]) - self.trap_ctbl.set("bgp", fvs) - time.sleep(2) - - old_traps = "bgp,bgpv6" - trap_keys = self.trap_atbl.getKeys() - for c_trap in copp_trap: - trap_info = copp_trap[c_trap] - ids = trap_info[0].replace(';', ',') - if old_traps == ids: - break - - trap_ids = old_traps.split(",") - trap_group = trap_info[1] - for trap_id in trap_ids: - trap_type = traps_to_trap_type[trap_id] - trap_found = False - trap_group_oid = "" - for key in trap_keys: - (status, fvs) = self.trap_atbl.get(key) - assert status == True - for fv in fvs: - if fv[0] == "SAI_HOSTIF_TRAP_ATTR_TRAP_TYPE": - if fv[1] == trap_type: - trap_found = True - if trap_found: - self.validate_trap_group(key,trap_group) - break - if trap_id == "bgp": - assert trap_found == True - elif trap_id == "bgpv6": - assert trap_found == False - - traps = "bgp,bgpv6" - fvs = swsscommon.FieldValuePairs([("trap_ids", traps)]) - self.trap_ctbl.set("bgp", fvs) - time.sleep(2) - - trap_keys = self.trap_atbl.getKeys() - trap_ids = traps.split(",") - trap_group = trap_info[1] - for trap_id in trap_ids: - trap_type = traps_to_trap_type[trap_id] - trap_found = False - trap_group_oid = "" - for key in trap_keys: - (status, fvs) = self.trap_atbl.get(key) - assert status == True - for fv in fvs: - if fv[0] == "SAI_HOSTIF_TRAP_ATTR_TRAP_TYPE": - if fv[1] == trap_type: - trap_found = True - if trap_found: - self.validate_trap_group(key,trap_group) - break - assert trap_found == True - - def test_trap_action_set(self, dvs, testlog): - self.setup_copp(dvs) - fvs = swsscommon.FieldValuePairs([("trap_action", "copy")]) - self.trap_group_ctbl.set("queue4_group1", fvs) - copp_group_queue4_group1["trap_action"] = "copy" - time.sleep(2) - global copp_trap - - trap_keys = self.trap_atbl.getKeys() - for traps in copp_trap: - trap_info = copp_trap[traps] - if trap_info[1] != copp_group_queue4_group1: - continue - trap_ids = trap_info[0].split(";") - trap_group = trap_info[1] - for trap_id in trap_ids: - trap_type = traps_to_trap_type[trap_id] - trap_found = False - trap_group_oid = "" - for key in trap_keys: - (status, fvs) = self.trap_atbl.get(key) - assert status == True - for fv in fvs: - if fv[0] == "SAI_HOSTIF_TRAP_ATTR_TRAP_TYPE": - if fv[1] == trap_type: - trap_found = True - if trap_found: - self.validate_trap_group(key,trap_group) - break - if trap_id not in disabled_traps: - assert trap_found == True - - - def test_new_trap_add(self, dvs, testlog): - self.setup_copp(dvs) - global copp_trap - traps = "eapol,isis,bfd_micro,bfdv6_micro,ldp" - fvs = swsscommon.FieldValuePairs([("trap_group", "queue1_group2"),("trap_ids", traps),("always_enabled", "true")]) - self.trap_ctbl.set(traps, fvs) - - - copp_trap["eapol"] = [traps, copp_group_queue1_group2, "always_enabled"] - time.sleep(2) - - trap_keys = self.trap_atbl.getKeys() - trap_ids = traps.split(",") - trap_group = copp_group_queue1_group2 - for trap_id in trap_ids: - trap_type = traps_to_trap_type[trap_id] - trap_found = False - trap_group_oid = "" - for key in trap_keys: - (status, fvs) = self.trap_atbl.get(key) - assert status == True - for fv in fvs: - if fv[0] == "SAI_HOSTIF_TRAP_ATTR_TRAP_TYPE": - if fv[1] == trap_type: - trap_found = True - if trap_found: - self.validate_trap_group(key,trap_group) - break - if trap_id not in disabled_traps: - assert trap_found == True - - def test_new_trap_del(self, dvs, testlog): - self.setup_copp(dvs) - global copp_trap - traps = "eapol,isis,bfd_micro,bfdv6_micro,ldp" - fvs = swsscommon.FieldValuePairs([("trap_group", "queue1_group2"),("trap_ids", traps)]) - self.trap_ctbl.set(traps, fvs) - for c_trap in copp_trap: - trap_info = copp_trap[c_trap] - ids = trap_info[0].replace(';', ',') - if traps == ids: - break - - trap_info[1] = copp_group_queue1_group2 - time.sleep(2) - - self.trap_ctbl._del(traps) - time.sleep(2) - trap_ids = traps.split(",") - trap_group = trap_info[1] - trap_keys = self.trap_atbl.getKeys() - for trap_id in trap_ids: - trap_type = traps_to_trap_type[trap_id] - trap_found = False - trap_group_oid = "" - for key in trap_keys: - (status, fvs) = self.trap_atbl.get(key) - assert status == True - for fv in fvs: - if fv[0] == "SAI_HOSTIF_TRAP_ATTR_TRAP_TYPE": - if fv[1] == trap_type: - trap_found = True - if trap_found: - self.validate_trap_group(key,trap_group) - break - if trap_id not in disabled_traps: - assert trap_found == False - - def test_new_trap_group_add(self, dvs, testlog): - self.setup_copp(dvs) - global copp_trap - traps = "igmp_v1_report" - list_val = list(copp_group_queue5_group1.items()) - - fvs = swsscommon.FieldValuePairs(list_val) - self.trap_group_ctbl.set("queue5_group1", fvs) - traps = "igmp_v1_report" - t_fvs = swsscommon.FieldValuePairs([("trap_group", "queue5_group1"),("trap_ids", "igmp_v1_report"),("always_enabled", "true")]) - self.trap_ctbl.set(traps, t_fvs) - for c_trap in copp_trap: - trap_info = copp_trap[c_trap] - ids = trap_info[0].replace(';', ',') - if traps == ids: - break - trap_info[1] = copp_group_queue5_group1 - time.sleep(2) - - trap_keys = self.trap_atbl.getKeys() - trap_ids = traps.split(",") - trap_group = trap_info[1] - for trap_id in trap_ids: - trap_type = traps_to_trap_type[trap_id] - trap_found = False - trap_group_oid = "" - for key in trap_keys: - (status, fvs) = self.trap_atbl.get(key) - assert status == True - for fv in fvs: - if fv[0] == "SAI_HOSTIF_TRAP_ATTR_TRAP_TYPE": - if fv[1] == trap_type: - trap_found = True - if trap_found: - self.validate_trap_group(key,trap_group) - break - if trap_id not in disabled_traps: - assert trap_found == True - - def test_new_trap_group_del(self, dvs, testlog): - self.setup_copp(dvs) - global copp_trap - traps = "igmp_v1_report" - list_val = list(copp_group_queue5_group1.items()) - - fvs = swsscommon.FieldValuePairs(list_val) - self.trap_group_ctbl.set("queue5_group1", fvs) - traps = "igmp_v1_report" - t_fvs = swsscommon.FieldValuePairs([("trap_group", "queue5_group1"),("trap_ids", "igmp_v1_report"),("always_enabled", "true")]) - self.trap_ctbl.set(traps, t_fvs) - for c_trap in copp_trap: - trap_info = copp_trap[c_trap] - ids = trap_info[0].replace(';', ',') - if traps == ids: - break - trap_info[1] = copp_group_queue5_group1 - - self.trap_group_ctbl._del("queue5_group1") - time.sleep(2) - - trap_keys = self.trap_atbl.getKeys() - trap_ids = traps.split(",") - trap_group = trap_info[1] - for trap_id in trap_ids: - trap_type = traps_to_trap_type[trap_id] - trap_found = False - trap_group_oid = "" - for key in trap_keys: - (status, fvs) = self.trap_atbl.get(key) - assert status == True - for fv in fvs: - if fv[0] == "SAI_HOSTIF_TRAP_ATTR_TRAP_TYPE": - if fv[1] == trap_type: - trap_found = True - if trap_found: - self.validate_trap_group(key,trap_group) - break - if trap_id not in disabled_traps: - assert trap_found != True - - def test_override_trap_grp_cfg_del (self, dvs, testlog): - self.setup_copp(dvs) - global copp_trap - fvs = swsscommon.FieldValuePairs([("cbs", "500"),("cir","500")]) - self.trap_group_ctbl.set("queue1_group1", fvs) - time.sleep(2) - - - self.trap_group_ctbl._del("queue1_group1") - time.sleep(2) - - - trap_keys = self.trap_atbl.getKeys() - for traps in copp_trap: - trap_info = copp_trap[traps] - if trap_info[1] != copp_group_queue1_group1: - continue - trap_ids = trap_info[0].split(";") - trap_group = trap_info[1] - for trap_id in trap_ids: - trap_type = traps_to_trap_type[trap_id] - trap_found = False - trap_group_oid = "" - for key in trap_keys: - (status, fvs) = self.trap_atbl.get(key) - assert status == True - for fv in fvs: - if fv[0] == "SAI_HOSTIF_TRAP_ATTR_TRAP_TYPE": - if fv[1] == trap_type: - trap_found = True - if trap_found: - self.validate_trap_group(key,trap_group) - break - if trap_id not in disabled_traps: - assert trap_found == True - - def test_override_trap_cfg_del(self, dvs, testlog): - self.setup_copp(dvs) - global copp_trap - traps = "ip2me,ssh" - fvs = swsscommon.FieldValuePairs([("trap_ids", "ip2me,ssh")]) - self.trap_ctbl.set("ip2me", fvs) - time.sleep(2) - - self.trap_ctbl._del("ip2me") - time.sleep(2) - trap_ids = traps.split(",") - trap_group = copp_trap["ip2me"][1] - trap_keys = self.trap_atbl.getKeys() - for trap_id in trap_ids: - trap_type = traps_to_trap_type[trap_id] - trap_found = False - trap_group_oid = "" - for key in trap_keys: - (status, fvs) = self.trap_atbl.get(key) - assert status == True - for fv in fvs: - if fv[0] == "SAI_HOSTIF_TRAP_ATTR_TRAP_TYPE": - if fv[1] == trap_type: - trap_found = True - if trap_found: - self.validate_trap_group(key,trap_group) - break - if trap_id not in disabled_traps: - if trap_id == "ip2me": - assert trap_found == True - elif trap_id == "ssh": - assert trap_found == False - - def test_empty_trap_cfg(self, dvs, testlog): - self.setup_copp(dvs) - global copp_trap - fvs = swsscommon.FieldValuePairs([("NULL","NULL")]) - self.trap_ctbl.set("ip2me", fvs) - time.sleep(2) - - trap_id = "ip2me" - trap_group = copp_trap["ip2me"][1] - trap_keys = self.trap_atbl.getKeys() - trap_type = traps_to_trap_type[trap_id] - trap_found = False - trap_group_oid = "" - for key in trap_keys: - (status, fvs) = self.trap_atbl.get(key) - assert status == True - for fv in fvs: - if fv[0] == "SAI_HOSTIF_TRAP_ATTR_TRAP_TYPE": - if fv[1] == trap_type: - trap_found = True - if trap_found: - self.validate_trap_group(key,trap_group) - break - assert trap_found == False - - self.trap_ctbl._del("ip2me") - time.sleep(2) - - trap_keys = self.trap_atbl.getKeys() - trap_type = traps_to_trap_type[trap_id] - trap_found = False - trap_group_oid = "" - for key in trap_keys: - (status, fvs) = self.trap_atbl.get(key) - assert status == True - for fv in fvs: - if fv[0] == "SAI_HOSTIF_TRAP_ATTR_TRAP_TYPE": - if fv[1] == trap_type: - trap_found = True - if trap_found: - self.validate_trap_group(key,trap_group) - break - assert trap_found == True - - - def test_disabled_feature_always_enabled_trap(self, dvs, testlog): - self.setup_copp(dvs) - fvs = swsscommon.FieldValuePairs([("trap_ids", "lldp"), ("trap_group", "queue4_group3"), ("always_enabled", "true")]) - self.trap_ctbl.set("lldp", fvs) - fvs = swsscommon.FieldValuePairs([("state", "disabled")]) - self.feature_tbl.set("lldp", fvs) - - time.sleep(2) - global copp_trap - - trap_keys = self.trap_atbl.getKeys() - for traps in copp_trap: - trap_info = copp_trap[traps] - trap_ids = trap_info[0].split(";") - trap_group = trap_info[1] - - if "lldp" not in trap_ids: - continue - - trap_found = False - trap_type = traps_to_trap_type["lldp"] - for key in trap_keys: - (status, fvs) = self.trap_atbl.get(key) - assert status == True - for fv in fvs: - if fv[0] == "SAI_HOSTIF_TRAP_ATTR_TRAP_TYPE": - if fv[1] == trap_type: - trap_found = True - if trap_found: - self.validate_trap_group(key,trap_group) - break - assert trap_found == True - - # change always_enabled to be false and check the trap is not installed: - fvs = swsscommon.FieldValuePairs([("trap_ids", "lldp"), ("trap_group", "queue4_group3"), ("always_enabled", "false")]) - self.trap_ctbl.set("lldp", fvs) - time.sleep(2) - - table_found = True - for key in trap_keys: - (status, fvs) = self.trap_atbl.get(key) - if status == False: - table_found = False - - # teardown - fvs = swsscommon.FieldValuePairs([("trap_ids", "lldp"), ("trap_group", "queue4_group3")]) - self.trap_ctbl.set("lldp", fvs) - fvs = swsscommon.FieldValuePairs([("state", "enabled")]) - self.feature_tbl.set("lldp", fvs) - - assert table_found == False - - def test_multi_feature_trap_add(self, dvs, testlog): - self.setup_copp(dvs) - global copp_trap - traps = "eapol" - fvs = swsscommon.FieldValuePairs([("state", "disbled")]) - self.feature_tbl.set("macsec", fvs) - fvs = swsscommon.FieldValuePairs([("state", "enabled")]) - self.feature_tbl.set("pac", fvs) - fvs = swsscommon.FieldValuePairs([("trap_group", "queue4_group1"),("trap_ids", traps)]) - self.trap_ctbl.set("pac", fvs) - - - copp_trap["eapol"] = [traps, copp_group_queue4_group1] - time.sleep(2) - - trap_keys = self.trap_atbl.getKeys() - trap_ids = traps.split(",") - trap_group = copp_group_queue4_group1 - for trap_id in trap_ids: - trap_type = traps_to_trap_type[trap_id] - trap_found = False - trap_group_oid = "" - for key in trap_keys: - (status, fvs) = self.trap_atbl.get(key) - assert status == True - for fv in fvs: - if fv[0] == "SAI_HOSTIF_TRAP_ATTR_TRAP_TYPE": - if fv[1] == trap_type: - trap_found = True - if trap_found: - self.validate_trap_group(key,trap_group) - break - if trap_id not in disabled_traps: - assert trap_found == True diff --git a/tests/test_dash_acl.py b/tests/test_dash_acl.py deleted file mode 100644 index c85fbf532b..0000000000 --- a/tests/test_dash_acl.py +++ /dev/null @@ -1,854 +0,0 @@ -from collections import namedtuple - -from swsscommon import swsscommon -from dvslib.dvs_database import DVSDatabase - -from dash_api.appliance_pb2 import * -from dash_api.vnet_pb2 import * -from dash_api.eni_pb2 import * -from dash_api.acl_group_pb2 import * -from dash_api.acl_rule_pb2 import * -from dash_api.acl_in_pb2 import * -from dash_api.acl_out_pb2 import * -from dash_api.prefix_tag_pb2 import * -from dash_api.types_pb2 import * - -from typing import Union -import time -import ipaddress -import socket -import binascii - -import pytest - -DVS_ENV = ["HWSKU=DPU-2P"] -NUM_PORTS = 2 - -ACL_GROUP_1 = "acl_group_1" -ACL_GROUP_2 = "acl_group_2" -ACL_GROUP_3 = "acl_group_3" -ACL_RULE_1 = "1" -ACL_RULE_2 = "2" -ACL_RULE_3 = "3" -ACL_STAGE_1 = "1" -ACL_STAGE_2 = "2" -ACL_STAGE_3 = "3" -TAG_1 = "tag_1" -TAG_2 = "tag_2" -TAG_3 = "tag_3" - -SAI_NULL_OID = "oid:0x0" - -PortRange = namedtuple('PortRange', ['min', 'max']) - -def to_string(value): - if isinstance(value, bool): - return "true" if value else "false" - elif isinstance(value, bytes): - return value - return str(value) - - -def get_sai_stage(outbound, v4, stage_num): - direction = "OUTBOUND" if outbound else "INBOUND" - ip_version = "V4" if v4 else "V6" - return "SAI_ENI_ATTR_{}_{}_STAGE{}_DASH_ACL_GROUP_ID".format(direction, ip_version, stage_num) - - -def prefix_list_to_set(prefix_list: str): - count, prefixes = prefix_list.split(":") - - ps = set(prefixes.split(",")) - assert len(ps) == int(count) - - return ps - - -def to_ip_prefix(prefix): - net = ipaddress.IPv4Network(prefix, False) - pfx = IpPrefix() - pfx.ip.ipv4 = socket.htonl(int(net.network_address)) - pfx.mask.ipv4 = socket.htonl(int(net.netmask)) - return pfx - - -class ProduceStateTable(object): - def __init__(self, database, table_name: str): - self.table = swsscommon.ProducerStateTable( - database.db_connection, - table_name) - self.keys = set() - - def __setitem__(self, key: str, pairs: Union[dict, list, tuple]): - pairs_str = [] - if isinstance(pairs, dict): - pairs = pairs.items() - for k, v in pairs: - pairs_str.append((to_string(k), to_string(v))) - self.table.set(key, pairs_str) - self.keys.add(key) - - def __delitem__(self, key: str): - self.table.delete(str(key)) - self.keys.discard(key) - - def get_keys(self): - return self.keys - - -class Table(object): - def __init__(self, database: DVSDatabase, table_name: str): - self.table_name = table_name - self.db = database - self.table = swsscommon.Table(database.db_connection, self.table_name) - - # Overload verification methods in DVSDatabase so we can use them per-table - # All methods from DVSDatabase that do not start with '_' are overloaded - # See the DVSDatabase class for info about the use of each method - # For each `func` in DVSDatabase, equivalent to: - # def func(self, **kwargs): - # return self.db.func(table_name=self.table_name, **kwargs) - # This means that we can call e.g. - # table_object.wait_for_n_keys(num_keys=1) - # instead of - # dvs.get_asic_db().wait_for_n_keys(table_name="ASIC_STATE:SAI_EXAMPLE_TABLE", num_keys=1) - overload_methods = [ - attr for attr in dir(DVSDatabase) - if not attr.startswith('_') and callable(getattr(DVSDatabase, attr)) - ] - for method_name in overload_methods: - setattr( - self, method_name, lambda method_name=method_name, - **kwargs: getattr(self.db, method_name)(table_name=self.table_name, **kwargs) - ) - - def __getitem__(self, key: str): - exists, result = self.table.get(str(key)) - if not exists: - return None - else: - return dict(result) - - -APPL_DB_TABLE_LIST = [ - swsscommon.APP_DASH_PREFIX_TAG_TABLE_NAME, - swsscommon.APP_DASH_ACL_IN_TABLE_NAME, - swsscommon.APP_DASH_ACL_OUT_TABLE_NAME, - swsscommon.APP_DASH_ACL_GROUP_TABLE_NAME, - swsscommon.APP_DASH_ACL_RULE_TABLE_NAME, - swsscommon.APP_DASH_ENI_TABLE_NAME, - swsscommon.APP_DASH_VNET_TABLE_NAME, - swsscommon.APP_DASH_APPLIANCE_TABLE_NAME -] - - -# TODO: At some point, orchagent will be update to write to some DB to indicate that it's finished -# processing updates for a given table. Once this is implemented, we can remove all the `sleep` -# statements in these tests and instead proactively check for the finished signal from orchagent -class DashAcl(object): - def __init__(self, dvs): - self.dvs = dvs - self.app_db_tables = [] - - for table in APPL_DB_TABLE_LIST: - pst = ProduceStateTable( - self.dvs.get_app_db(), table - ) - table_variable_name = "app_{}".format(table.lower()) - # Based on swsscommon convention for table names, assume - # e.g. swsscommon.APP_DASH_ENI_TABLE_NAME == "DASH_ENI_TABLE", therefore - # the ProducerStateTable object for swsscommon.APP_DASH_ENI_TABLE_NAME - # will be accessible as `self.app_dash_eni_table` - setattr(self, table_variable_name, pst) - self.app_db_tables.append(pst) - - self.asic_dash_acl_rule_table = Table( - self.dvs.get_asic_db(), "ASIC_STATE:SAI_OBJECT_TYPE_DASH_ACL_RULE") - self.asic_dash_acl_group_table = Table( - self.dvs.get_asic_db(), "ASIC_STATE:SAI_OBJECT_TYPE_DASH_ACL_GROUP") - self.asic_eni_table = Table( - self.dvs.get_asic_db(), "ASIC_STATE:SAI_OBJECT_TYPE_ENI") - self.asic_vip_table = Table( - self.dvs.get_asic_db(), "ASIC_STATE:SAI_OBJECT_TYPE_VIP_ENTRY") - self.asic_vnet_table = Table( - self.dvs.get_asic_db(), "ASIC_STATE:SAI_OBJECT_TYPE_VNET") - - self.asic_db_tables = [ - self.asic_dash_acl_group_table, - self.asic_dash_acl_rule_table, - self.asic_eni_table, - self.asic_vip_table, - self.asic_vnet_table - ] - - def create_prefix_tag(self, name, ip_version, prefixes): - pb = PrefixTag() - pb.ip_version = ip_version - for prefix in prefixes: - pb.prefix_list.append(to_ip_prefix(prefix)) - self.app_dash_prefix_tag_table[str(name)] = {"pb": pb.SerializeToString()} - - def remove_prefix_tag(self, tag_id): - del self.app_dash_prefix_tag_table[str(tag_id)] - - def create_acl_rule(self, group_id, rule_id, action, terminating, priority, protocol=None, - src_addr=None, dst_addr=None, - src_tag=None, dst_tag=None, - src_port=None, dst_port=None): - pb = AclRule() - pb.priority = priority - pb.action = action - pb.terminating = terminating - - if protocol: - map(pb.protocol.append, protocol) - - if src_addr: - for addr in src_addr: - pb.src_addr.append(to_ip_prefix(addr)) - - if dst_addr: - for addr in dst_addr: - pb.dst_addr.append(to_ip_prefix(addr)) - - if src_tag: - for tag in src_tag: - pb.src_tag.append(tag.encode()) - - if dst_tag: - for tag in dst_tag: - pb.dst_tag.append(tag.encode()) - - if src_port: - for pr in src_port: - vr = ValueOrRange() - vr.range.min = pr.min - vr.range.max = pr.max - pb.src_port.append(vr) - - if dst_port: - for pr in dst_port: - vr = ValueOrRange() - vr.range.min = pr.min - vr.range.max = pr.max - pb.dst_port.append(vr) - - self.app_dash_acl_rule_table[str(group_id) + ":" + str(rule_id)] = {"pb": pb.SerializeToString()} - - - def remove_acl_rule(self, group_id, rule_id): - del self.app_dash_acl_rule_table[str(group_id) + ":" + str(rule_id)] - - def create_acl_group(self, group_id, ip_version): - pb = AclGroup() - pb.ip_version = IpVersion.IP_VERSION_IPV4 - self.app_dash_acl_group_table[str(group_id)] = {"pb": pb.SerializeToString()} - - def remove_acl_group(self, group_id): - del self.app_dash_acl_group_table[str(group_id)] - - def create_appliance(self, name, pb): - self.app_dash_appliance_table[str(name)] = {"pb": pb.SerializeToString()} - - def remove_appliance(self, name): - del self.app_dash_appliance_table[str(name)] - - def create_eni(self, eni, pb): - self.app_dash_eni_table[str(eni)] = {"pb": pb.SerializeToString()} - - def remove_eni(self, eni): - del self.app_dash_eni_table[str(eni)] - - def create_vnet(self, vnet, pb): - self.app_dash_vnet_table[str(vnet)] = {"pb": pb.SerializeToString()} - - def remove_vnet(self, vnet): - del self.app_dash_vnet_table[str(vnet)] - - def bind_acl_in(self, eni, stage, v4_group_id = None, v6_group_id = None): - pb = AclIn() - if v4_group_id: - pb.v4_acl_group_id = v4_group_id - if v6_group_id: - pb.v6_acl_group_id = v6_group_id - self.app_dash_acl_in_table[str( - eni) + ":" + str(stage)] = {"pb": pb.SerializeToString()} - - def unbind_acl_in(self, eni, stage): - del self.app_dash_acl_in_table[str(eni) + ":" + str(stage)] - - def bind_acl_out(self, eni, stage, v4_group_id = None, v6_group_id = None): - pb = AclIn() - if v4_group_id: - pb.v4_acl_group_id = v4_group_id - if v6_group_id: - pb.v6_acl_group_id = v6_group_id - self.app_dash_acl_out_table[str( - eni) + ":" + str(stage)] = {"pb": pb.SerializeToString()} - - def unbind_acl_out(self, eni, stage): - del self.app_dash_acl_out_table[str(eni) + ":" + str(stage)] - - - -class TestAcl(object): - @pytest.fixture - def ctx(self, dvs): - self.vnet_name = "vnet1" - self.eni_name = "eth0" - self.appliance_name = "default_app" - self.vm_vni = "4321" - self.appliance_sip = "10.20.30.40" - self.vni = "1" - self.mac_address = "01:23:45:67:89:ab" - self.underlay_ip = "1.1.1.1" - - acl_context = DashAcl(dvs) - pb = Appliance() - pb.sip.ipv4 = socket.htonl(int(ipaddress.ip_address(self.appliance_sip))) - pb.vm_vni = int(self.vm_vni) - - acl_context.create_appliance(self.appliance_name, pb) - pb = Vnet() - pb.vni = int(self.vni) - - acl_context.create_vnet(self.vnet_name, pb) - pb = Eni() - pb.vnet = self.vnet_name - pb.mac_address = bytes.fromhex(self.mac_address.replace(":", "")) - pb.underlay_ip.ipv4 = socket.htonl(int(ipaddress.ip_address(self.underlay_ip))) - acl_context.create_eni(self.eni_name, pb) - - acl_context.asic_vip_table.wait_for_n_keys(num_keys=1) - acl_context.asic_vnet_table.wait_for_n_keys(num_keys=1) - acl_context.asic_eni_table.wait_for_n_keys(num_keys=1) - - yield acl_context - - # Manually cleanup by deleting all remaining APPL_DB keys - for table in acl_context.app_db_tables: - keys = table.get_keys() - for key in list(keys): - del table[key] - - for table in acl_context.asic_db_tables: - table.wait_for_n_keys(num_keys=0) - - def bind_acl_group(self, ctx, stage_id, group_id, group_oid): - ctx.bind_acl_in(self.eni_name, stage_id, group_id) - self.verify_group_is_bound_to_eni(ctx, stage_id, group_oid) - - def verify_group_is_bound_to_eni(self, ctx, stage_id, group_oid): - eni_key = ctx.asic_eni_table.get_keys()[0] - sai_stage = get_sai_stage(outbound=False, v4=True, stage_num=stage_id) - ctx.asic_eni_table.wait_for_field_match(key=eni_key, expected_fields={sai_stage: group_oid}) - assert sai_stage in ctx.asic_eni_table[eni_key] - assert ctx.asic_eni_table[eni_key][sai_stage] == group_oid - - def test_acl_flow(self, ctx): - ctx.create_acl_group(ACL_GROUP_1, IpVersion.IP_VERSION_IPV4) - - ctx.create_acl_rule(ACL_GROUP_1, ACL_RULE_1, - priority=1, action=Action.ACTION_PERMIT, terminating=False, - src_addr=["192.168.0.1/32", "192.168.1.2/30"], dst_addr=["192.168.0.1/32", "192.168.1.2/30"], - src_port=[PortRange(0,1)], dst_port=[PortRange(0,1)]) - - rule1_id= ctx.asic_dash_acl_rule_table.wait_for_n_keys(num_keys=1)[0] - group1_id= ctx.asic_dash_acl_group_table.wait_for_n_keys(num_keys=1)[0] - rule1_attr = ctx.asic_dash_acl_rule_table[rule1_id] - assert rule1_attr["SAI_DASH_ACL_RULE_ATTR_PRIORITY"] == "1" - assert rule1_attr["SAI_DASH_ACL_RULE_ATTR_ACTION"] == "SAI_DASH_ACL_RULE_ACTION_PERMIT_AND_CONTINUE" - assert rule1_attr["SAI_DASH_ACL_RULE_ATTR_DASH_ACL_GROUP_ID"] == group1_id - assert rule1_attr["SAI_DASH_ACL_RULE_ATTR_DIP"] == "2:192.168.0.1/32,192.168.1.0/30" - assert rule1_attr["SAI_DASH_ACL_RULE_ATTR_SIP"] == "2:192.168.0.1/32,192.168.1.0/30" - assert rule1_attr["SAI_DASH_ACL_RULE_ATTR_DST_PORT"] == "1:0,1" - assert rule1_attr["SAI_DASH_ACL_RULE_ATTR_SRC_PORT"] == "1:0,1" - assert rule1_attr["SAI_DASH_ACL_RULE_ATTR_PROTOCOL"].split(":")[0] == "256" - group1_attr = ctx.asic_dash_acl_group_table[group1_id] - assert group1_attr["SAI_DASH_ACL_GROUP_ATTR_IP_ADDR_FAMILY"] == "SAI_IP_ADDR_FAMILY_IPV4" - - # Create multiple rules - ctx.create_acl_rule(ACL_GROUP_1, ACL_RULE_2, - priority=2, action=Action.ACTION_PERMIT, terminating=False, - src_addr=["192.168.0.1/32", "192.168.1.2/30"], dst_addr=["192.168.0.1/32", "192.168.1.2/30"], - src_port=[PortRange(0,1)], dst_port=[PortRange(0,1)]) - ctx.create_acl_rule(ACL_GROUP_1, ACL_RULE_2, - priority=2, action=Action.ACTION_PERMIT, terminating=False, - src_addr=["192.168.0.1/32", "192.168.1.2/30"], dst_addr=["192.168.0.1/32", "192.168.1.2/30"], - src_port=[PortRange(0,1)], dst_port=[PortRange(0,1)]) - ctx.create_acl_rule(ACL_GROUP_1, ACL_RULE_3, - priority=3, action=Action.ACTION_PERMIT, terminating=False, - src_addr=["192.168.0.1/32", "192.168.1.2/30"], dst_addr=["192.168.0.1/32", "192.168.1.2/30"], - src_port=[PortRange(0,1)], dst_port=[PortRange(0,1)]) - ctx.asic_dash_acl_rule_table.wait_for_n_keys(num_keys=3) - ctx.unbind_acl_in(self.eni_name, ACL_STAGE_1) - ctx.remove_acl_rule(ACL_GROUP_1, ACL_RULE_1) - ctx.remove_acl_rule(ACL_GROUP_1, ACL_RULE_2) - ctx.remove_acl_rule(ACL_GROUP_1, ACL_RULE_3) - ctx.remove_acl_group(ACL_GROUP_1) - ctx.asic_dash_acl_rule_table.wait_for_n_keys(num_keys=0) - ctx.asic_dash_acl_group_table.wait_for_n_keys(num_keys=0) - - def test_acl_group(self, ctx): - ctx.create_acl_group(ACL_GROUP_1, IpVersion.IP_VERSION_IPV6) - - ctx.create_acl_rule(ACL_GROUP_1, ACL_RULE_1, - priority=1, action=Action.ACTION_PERMIT, terminating=False, - src_addr=["192.168.0.1/32", "192.168.1.2/30"], dst_addr=["192.168.0.1/32", "192.168.1.2/30"], - src_port=[PortRange(0,1)], dst_port=[PortRange(0,1)]) - - ctx.asic_dash_acl_group_table.wait_for_n_keys(num_keys=1) - - # Remove group before removing its rule - ctx.remove_acl_group(ACL_GROUP_1) - # Wait a few seconds to make sure no changes are made - # since group still contains a rule - time.sleep(3) - ctx.asic_dash_acl_group_table.wait_for_n_keys(num_keys=1) - - ctx.remove_acl_rule(ACL_GROUP_1, ACL_RULE_1) - ctx.asic_dash_acl_group_table.wait_for_n_keys(num_keys=0) - - def test_empty_acl_group_binding(self, ctx): - """ - Verifies behavior when binding ACL groups - """ - eni_key = ctx.asic_eni_table.get_keys()[0] - sai_stage = get_sai_stage(outbound=True, v4=True, stage_num=ACL_STAGE_1) - - ctx.create_acl_group(ACL_GROUP_1, IpVersion.IP_VERSION_IPV4) - acl_group_key = ctx.asic_dash_acl_group_table.wait_for_n_keys(num_keys=1)[0] - ctx.bind_acl_out(self.eni_name, ACL_STAGE_1, v4_group_id = ACL_GROUP_1) - time.sleep(3) - # Binding should not happen yet because the ACL group is empty - assert sai_stage not in ctx.asic_eni_table[eni_key] - - ctx.create_acl_rule(ACL_GROUP_1, ACL_RULE_1, - priority=1, action=Action.ACTION_PERMIT, terminating=False, - src_addr=["192.168.0.1/32", "192.168.1.2/30"], dst_addr=["192.168.0.1/32", "192.168.1.2/30"], - src_port=[PortRange(0,1)], dst_port=[PortRange(0,1)]) - - # Now that the group contains a rule, expect binding to occur - ctx.bind_acl_out(self.eni_name, ACL_STAGE_1, v4_group_id = ACL_GROUP_1) - ctx.asic_eni_table.wait_for_field_match(key=eni_key, expected_fields={sai_stage: acl_group_key}) - - # Unbinding should occur immediately - ctx.unbind_acl_out(self.eni_name, ACL_STAGE_1) - ctx.asic_eni_table.wait_for_field_match(key=eni_key, expected_fields={sai_stage: SAI_NULL_OID}) - - def test_acl_rule_after_group_bind(self, ctx): - eni_key = ctx.asic_eni_table.get_keys()[0] - sai_stage = get_sai_stage(outbound=False, v4=True, stage_num=ACL_STAGE_1) - - ctx.create_acl_group(ACL_GROUP_1, IpVersion.IP_VERSION_IPV4) - acl_group_key = ctx.asic_dash_acl_group_table.wait_for_n_keys(num_keys=1)[0] - ctx.create_acl_rule(ACL_GROUP_1, ACL_RULE_1, - priority=1, action=Action.ACTION_PERMIT, terminating=False, - src_addr=["192.168.0.1/32", "192.168.1.2/30"], dst_addr=["192.168.0.1/32", "192.168.1.2/30"], - src_port=[PortRange(0,1)], dst_port=[PortRange(0,1)]) - ctx.asic_dash_acl_rule_table.wait_for_n_keys(num_keys=1) - - self.bind_acl_group(ctx, ACL_STAGE_1, ACL_GROUP_1, acl_group_key) - - # The new rule should not be created since the group is bound - ctx.create_acl_rule(ACL_GROUP_1, ACL_RULE_2, - priority=2, action=Action.ACTION_PERMIT, terminating=False, - src_addr=["192.168.0.1/32", "192.168.1.2/30"], dst_addr=["192.168.0.1/32", "192.168.1.2/30"], - src_port=[PortRange(0,1)], dst_port=[PortRange(0,1)]) - time.sleep(3) - ctx.asic_dash_acl_rule_table.wait_for_n_keys(num_keys=1) - - # Unbinding the group - ctx.unbind_acl_in(self.eni_name, ACL_STAGE_1) - ctx.asic_eni_table.wait_for_field_match(key=eni_key, expected_fields={sai_stage: SAI_NULL_OID}) - - # Now the rule can be created since the group is no longer bound - ctx.create_acl_rule(ACL_GROUP_1, ACL_RULE_2, - priority=2, action=Action.ACTION_PERMIT, terminating=False, - src_addr=["192.168.0.1/32", "192.168.1.2/30"], dst_addr=["192.168.0.1/32", "192.168.1.2/30"], - src_port=[PortRange(0,1)], dst_port=[PortRange(0,1)]) - ctx.asic_dash_acl_rule_table.wait_for_n_keys(num_keys=2) - - # cleanup - ctx.remove_acl_rule(ACL_GROUP_1, ACL_RULE_1) - ctx.remove_acl_rule(ACL_GROUP_1, ACL_RULE_2) - ctx.remove_acl_group(ACL_GROUP_1) - - def test_acl_group_binding(self, ctx): - eni_key = ctx.asic_eni_table.get_keys()[0] - sai_stage = get_sai_stage(outbound=False, v4=True, stage_num=ACL_STAGE_2) - - ctx.create_acl_group(ACL_GROUP_2, IpVersion.IP_VERSION_IPV4) - acl_group_key = ctx.asic_dash_acl_group_table.wait_for_n_keys(num_keys=1)[0] - - ctx.create_acl_rule(ACL_GROUP_2, ACL_RULE_1, - priority=1, action=Action.ACTION_PERMIT, terminating=False, - src_addr=["192.168.0.1/32", "192.168.1.2/30"], dst_addr=["192.168.0.1/32", "192.168.1.2/30"], - src_port=[PortRange(0,1)], dst_port=[PortRange(0,1)]) - - ctx.bind_acl_in(self.eni_name, ACL_STAGE_2, v4_group_id = ACL_GROUP_2) - # Binding should occurr immediately since we added a rule to the group prior to binding - ctx.asic_eni_table.wait_for_field_match(key=eni_key, expected_fields={sai_stage: acl_group_key}) - - ctx.unbind_acl_in(self.eni_name, ACL_STAGE_2) - ctx.asic_eni_table.wait_for_field_match(key=eni_key, expected_fields={sai_stage: SAI_NULL_OID}) - - def test_acl_rule(self, ctx): - # Create acl rule before acl group - ctx.create_acl_rule(ACL_GROUP_1, ACL_RULE_1, - priority=1, action=Action.ACTION_PERMIT, terminating=False, - src_addr=["192.168.0.1/32", "192.168.1.2/30"], dst_addr=["192.168.0.1/32", "192.168.1.2/30"], - src_port=[PortRange(0,1)], dst_port=[PortRange(0,1)]) - time.sleep(3) - ctx.asic_dash_acl_rule_table.wait_for_n_keys(num_keys=0) - ctx.create_acl_group(ACL_GROUP_1, IpVersion.IP_VERSION_IPV4) - - ctx.asic_dash_acl_rule_table.wait_for_n_keys(num_keys=1) - - # Create acl rule with nonexistent acl group, which should never get programmed to ASIC_DB - ctx.create_acl_rule("0", "0", - priority=1, action=Action.ACTION_PERMIT, terminating=False, - src_addr=["192.168.0.1/32", "192.168.1.2/30"], dst_addr=["192.168.0.1/32", "192.168.1.2/30"], - src_port=[PortRange(0,1)], dst_port=[PortRange(0,1)]) - time.sleep(3) - ctx.asic_dash_acl_rule_table.wait_for_n_keys(num_keys=1) - - ctx.create_acl_rule(ACL_GROUP_1, ACL_RULE_2, - priority=1, action=Action.ACTION_PERMIT, terminating=False, - src_addr=["192.168.0.1/32", "192.168.1.2/30"], dst_addr=["192.168.0.1/32", "192.168.1.2/30"], - src_port=[PortRange(0,1)], dst_port=[PortRange(0,1)]) - ctx.asic_dash_acl_rule_table.wait_for_n_keys(num_keys=2) - - ctx.remove_acl_rule(ACL_GROUP_1, ACL_RULE_1) - ctx.remove_acl_rule(ACL_GROUP_1, ACL_RULE_2) - ctx.remove_acl_group(ACL_GROUP_1) - ctx.asic_dash_acl_rule_table.wait_for_n_keys(num_keys=0) - ctx.asic_dash_acl_group_table.wait_for_n_keys(num_keys=0) - - - @pytest.mark.parametrize("bind_group", [True, False]) - def test_prefix_single_tag(self, ctx, bind_group): - tag1_prefixes = {"1.1.1.0/24", "2.2.0.0/16"} - ctx.create_prefix_tag(TAG_1, IpVersion.IP_VERSION_IPV4, tag1_prefixes) - - tag2_prefixes = {"192.168.1.0/30", "192.168.2.0/30", "192.168.3.0/30"} - ctx.create_prefix_tag(TAG_2, IpVersion.IP_VERSION_IPV4, tag2_prefixes) - - ctx.create_acl_group(ACL_GROUP_1, IpVersion.IP_VERSION_IPV4) - group1_id = ctx.asic_dash_acl_group_table.wait_for_n_keys(num_keys=1)[0] - - ctx.create_acl_rule(ACL_GROUP_1, ACL_RULE_1, - priority=1, action=Action.ACTION_PERMIT, terminating=False, - src_tag=[TAG_1], dst_tag=[TAG_2], - src_port=[PortRange(0,1)], dst_port=[PortRange(0,1)]) - - rule1_id= ctx.asic_dash_acl_rule_table.wait_for_n_keys(num_keys=1)[0] - rule1_attr = ctx.asic_dash_acl_rule_table[rule1_id] - - assert prefix_list_to_set(rule1_attr["SAI_DASH_ACL_RULE_ATTR_SIP"]) == tag1_prefixes - assert prefix_list_to_set(rule1_attr["SAI_DASH_ACL_RULE_ATTR_DIP"]) == tag2_prefixes - - if bind_group: - self.bind_acl_group(ctx, ACL_STAGE_1, ACL_GROUP_1, group1_id) - - tag1_prefixes = {"1.1.2.0/24", "2.3.0.0/16"} - ctx.create_prefix_tag(TAG_1, IpVersion.IP_VERSION_IPV4, tag1_prefixes) - - time.sleep(3) - - rule1_id= ctx.asic_dash_acl_rule_table.wait_for_n_keys(num_keys=1)[0] - rule1_attr = ctx.asic_dash_acl_rule_table[rule1_id] - - if bind_group: - new_group1_id = ctx.asic_dash_acl_group_table.wait_for_n_keys(num_keys=1)[0] - assert new_group1_id != group1_id - self.verify_group_is_bound_to_eni(ctx, ACL_STAGE_1, new_group1_id) - - assert prefix_list_to_set(rule1_attr["SAI_DASH_ACL_RULE_ATTR_SIP"]) == tag1_prefixes - assert prefix_list_to_set(rule1_attr["SAI_DASH_ACL_RULE_ATTR_DIP"]) == tag2_prefixes - - tag2_prefixes = {"192.168.2.0/30", "192.168.3.0/30"} - ctx.create_prefix_tag(TAG_2, IpVersion.IP_VERSION_IPV4, tag2_prefixes) - - time.sleep(3) - - ctx.asic_dash_acl_group_table.wait_for_n_keys(num_keys=1) - rule1_id = ctx.asic_dash_acl_rule_table.wait_for_n_keys(num_keys=1)[0] - rule1_attr = ctx.asic_dash_acl_rule_table[rule1_id] - - assert prefix_list_to_set(rule1_attr["SAI_DASH_ACL_RULE_ATTR_SIP"]) == tag1_prefixes - assert prefix_list_to_set(rule1_attr["SAI_DASH_ACL_RULE_ATTR_DIP"]) == tag2_prefixes - - if bind_group: - ctx.unbind_acl_in(self.eni_name, ACL_STAGE_1) - - ctx.remove_acl_rule(ACL_GROUP_1, ACL_RULE_1) - ctx.remove_acl_group(ACL_GROUP_1) - ctx.remove_prefix_tag(TAG_1) - ctx.remove_prefix_tag(TAG_2) - - @pytest.mark.parametrize("bind_group", [True, False]) - def test_multiple_tags(self, ctx, bind_group): - tag1_prefixes = {"1.1.1.0/24", "2.2.0.0/16"} - ctx.create_prefix_tag(TAG_1, IpVersion.IP_VERSION_IPV4, tag1_prefixes) - - tag2_prefixes = {"192.168.1.0/30", "192.168.2.0/30", "192.168.1.0/30"} - ctx.create_prefix_tag(TAG_2, IpVersion.IP_VERSION_IPV4, tag2_prefixes) - - tag3_prefixes = {"3.3.0.0/16", "3.4.0.0/16", "4.4.4.0/24", "5.5.5.0/24"} - ctx.create_prefix_tag(TAG_3, IpVersion.IP_VERSION_IPV4, tag3_prefixes) - - ctx.create_acl_group(ACL_GROUP_1, IpVersion.IP_VERSION_IPV4) - group1_id = ctx.asic_dash_acl_group_table.wait_for_n_keys(num_keys=1)[0] - - # Create acl rule before acl group - ctx.create_acl_rule(ACL_GROUP_1, ACL_RULE_1, - priority=1, action=Action.ACTION_PERMIT, terminating=False, - src_tag=[TAG_1, TAG_2], dst_tag=[TAG_2, TAG_3], - src_port=[PortRange(0,1)], dst_port=[PortRange(0,1)]) - - rule1_id= ctx.asic_dash_acl_rule_table.wait_for_n_keys(num_keys=1)[0] - rule1_attr = ctx.asic_dash_acl_rule_table[rule1_id] - - assert prefix_list_to_set(rule1_attr["SAI_DASH_ACL_RULE_ATTR_SIP"]) == tag1_prefixes.union(tag2_prefixes) - assert prefix_list_to_set(rule1_attr["SAI_DASH_ACL_RULE_ATTR_DIP"]) == tag2_prefixes.union(tag3_prefixes) - - if bind_group: - self.bind_acl_group(ctx, ACL_STAGE_1, ACL_GROUP_1, group1_id) - - tag2_prefixes = {"192.168.10.0/30", "192.168.11.0/30", "192.168.12.0/30"} - ctx.create_prefix_tag(TAG_2, IpVersion.IP_VERSION_IPV4, tag2_prefixes) - - tag3_prefixes = {"3.13.0.0/16", "3.14.0.0/16", "4.14.4.0/24", "5.15.5.0/24"} - ctx.create_prefix_tag(TAG_3, IpVersion.IP_VERSION_IPV4, tag3_prefixes) - - time.sleep(3) - - if bind_group: - new_group1_id = ctx.asic_dash_acl_group_table.wait_for_n_keys(num_keys=1)[0] - assert new_group1_id != group1_id - - self.verify_group_is_bound_to_eni(ctx, ACL_STAGE_1, new_group1_id) - - rule1_id= ctx.asic_dash_acl_rule_table.wait_for_n_keys(num_keys=1)[0] - rule1_attr = ctx.asic_dash_acl_rule_table[rule1_id] - - assert prefix_list_to_set(rule1_attr["SAI_DASH_ACL_RULE_ATTR_SIP"]) == tag1_prefixes.union(tag2_prefixes) - assert prefix_list_to_set(rule1_attr["SAI_DASH_ACL_RULE_ATTR_DIP"]) == tag2_prefixes.union(tag3_prefixes) - - if bind_group: - ctx.unbind_acl_in(self.eni_name, ACL_STAGE_1) - - ctx.remove_acl_rule(ACL_GROUP_1, ACL_RULE_1) - ctx.remove_acl_group(ACL_GROUP_1) - ctx.remove_prefix_tag(TAG_1) - ctx.remove_prefix_tag(TAG_2) - ctx.remove_prefix_tag(TAG_3) - - @pytest.mark.parametrize("bind_group", [True, False]) - def test_multiple_tags_and_prefixes(self, ctx, bind_group): - tag1_prefixes = {"1.1.1.0/24", "2.2.0.0/16"} - ctx.create_prefix_tag(TAG_1, IpVersion.IP_VERSION_IPV4, tag1_prefixes) - - tag2_prefixes = {"192.168.1.0/30", "192.168.2.0/30", "192.168.3.0/30"} - ctx.create_prefix_tag(TAG_2, IpVersion.IP_VERSION_IPV4, tag2_prefixes) - - tag3_prefixes = {"3.3.0.0/16", "3.4.0.0/16", "4.4.4.0/24", "5.5.5.0/24"} - ctx.create_prefix_tag(TAG_3, IpVersion.IP_VERSION_IPV4, tag3_prefixes) - - ctx.create_acl_group(ACL_GROUP_1, IpVersion.IP_VERSION_IPV4) - group1_id = ctx.asic_dash_acl_group_table.wait_for_n_keys(num_keys=1)[0] - - prefix_list = {"10.0.0.0/8", "11.1.1.0/24", "11.1.2.0/24"} - - # Create acl rule before acl group - ctx.create_acl_rule(ACL_GROUP_1, ACL_RULE_1, - priority=1, action=Action.ACTION_PERMIT, terminating=False, - src_tag=[TAG_1, TAG_2, TAG_3], dst_addr=prefix_list, - src_port=[PortRange(0,1)], dst_port=[PortRange(0,1)]) - - rule1_id= ctx.asic_dash_acl_rule_table.wait_for_n_keys(num_keys=1)[0] - rule1_attr = ctx.asic_dash_acl_rule_table[rule1_id] - - super_set = set() - super_set.update(tag1_prefixes, tag2_prefixes, tag3_prefixes) - - assert prefix_list_to_set(rule1_attr["SAI_DASH_ACL_RULE_ATTR_SIP"]) == super_set - assert prefix_list_to_set(rule1_attr["SAI_DASH_ACL_RULE_ATTR_DIP"]) == prefix_list - - if bind_group: - self.bind_acl_group(ctx, ACL_STAGE_1, ACL_GROUP_1, group1_id) - - tag1_prefixes = {"1.1.1.0/24", "2.2.0.0/16"} - ctx.create_prefix_tag(TAG_1, IpVersion.IP_VERSION_IPV4, tag1_prefixes) - - tag2_prefixes = {"192.168.1.2/32", "192.168.2.2/32", "192.168.1.2/32"} - ctx.create_prefix_tag(TAG_2, IpVersion.IP_VERSION_IPV4, tag2_prefixes) - - tag3_prefixes = {"3.3.0.0/16", "3.4.0.0/16", "4.4.4.0/24", "5.5.5.0/24"} - ctx.create_prefix_tag(TAG_3, IpVersion.IP_VERSION_IPV4, tag3_prefixes) - - time.sleep(3) - - if bind_group: - new_group1_id = ctx.asic_dash_acl_group_table.wait_for_n_keys(num_keys=1)[0] - assert new_group1_id != group1_id - self.verify_group_is_bound_to_eni(ctx, ACL_STAGE_1, new_group1_id) - - rule1_id= ctx.asic_dash_acl_rule_table.wait_for_n_keys(num_keys=1)[0] - rule1_attr = ctx.asic_dash_acl_rule_table[rule1_id] - - super_set = set() - super_set.update(tag1_prefixes, tag2_prefixes, tag3_prefixes) - - assert prefix_list_to_set(rule1_attr["SAI_DASH_ACL_RULE_ATTR_SIP"]) == super_set - assert prefix_list_to_set(rule1_attr["SAI_DASH_ACL_RULE_ATTR_DIP"]) == prefix_list - - if bind_group: - ctx.unbind_acl_in(self.eni_name, ACL_STAGE_1) - - ctx.remove_acl_rule(ACL_GROUP_1, ACL_RULE_1) - ctx.remove_acl_group(ACL_GROUP_1) - ctx.remove_prefix_tag(TAG_1) - ctx.remove_prefix_tag(TAG_2) - ctx.remove_prefix_tag(TAG_3) - - @pytest.mark.parametrize("bind_group", [True, False]) - def test_multiple_groups_prefix_single_tag(self, ctx, bind_group): - groups = [ACL_GROUP_1, ACL_GROUP_2, ACL_GROUP_3] - stages = [ACL_STAGE_1, ACL_STAGE_2, ACL_STAGE_3] - - tag1_prefixes = {"1.1.1.0/24", "2.2.0.0/16"} - ctx.create_prefix_tag(TAG_1, IpVersion.IP_VERSION_IPV4, tag1_prefixes) - - for group in groups: - ctx.create_acl_group(group, IpVersion.IP_VERSION_IPV4) - ctx.create_acl_rule(group, ACL_RULE_1, - priority=1, action=Action.ACTION_PERMIT, terminating=False, - src_tag=[TAG_1], dst_addr=["192.168.1.2/30", "192.168.2.2/30", "192.168.3.2/30"], - src_port=[PortRange(0,1)], dst_port=[PortRange(0,1)]) - - group_ids = ctx.asic_dash_acl_group_table.wait_for_n_keys(num_keys=3) - rule_ids = ctx.asic_dash_acl_rule_table.wait_for_n_keys(num_keys=3) - - for rid in rule_ids: - rule_attrs = ctx.asic_dash_acl_rule_table[rid] - assert prefix_list_to_set(rule_attrs["SAI_DASH_ACL_RULE_ATTR_SIP"]) == tag1_prefixes - - if bind_group: - eni_stages = [] - eni_key = ctx.asic_eni_table.get_keys()[0] - for stage, group in zip(stages, groups): - ctx.bind_acl_in(self.eni_name, stage, group) - eni_stages.append(get_sai_stage(outbound=False, v4=True, stage_num=stage)) - - ctx.asic_eni_table.wait_for_fields(key=eni_key, expected_fields=eni_stages) - for stage in eni_stages: - assert ctx.asic_eni_table[eni_key][stage] in group_ids - - tag1_prefixes = {"1.1.2.0/24", "2.3.0.0/16"} - ctx.create_prefix_tag(TAG_1, IpVersion.IP_VERSION_IPV4, tag1_prefixes) - - time.sleep(3) - - rule_ids = ctx.asic_dash_acl_rule_table.wait_for_n_keys(num_keys=3) - - for rid in rule_ids: - rule_attrs = ctx.asic_dash_acl_rule_table[rid] - assert prefix_list_to_set(rule_attrs["SAI_DASH_ACL_RULE_ATTR_SIP"]) == tag1_prefixes - - if bind_group: - new_group_ids = ctx.asic_dash_acl_group_table.wait_for_n_keys(num_keys=3) - - ctx.asic_eni_table.wait_for_fields(key=eni_key, expected_fields=eni_stages) - for stage in eni_stages: - assert ctx.asic_eni_table[eni_key][stage] in new_group_ids - - for stage in stages: - ctx.unbind_acl_in(self.eni_name, stage) - - for group in groups: - ctx.remove_acl_rule(group, ACL_RULE_1) - ctx.remove_acl_group(group) - - ctx.remove_prefix_tag(TAG_1) - ctx.remove_prefix_tag(TAG_2) - - def test_tag_remove(self, ctx): - tag1_prefixes = {"1.1.1.0/24", "2.2.0.0/16"} - ctx.create_prefix_tag(TAG_1, IpVersion.IP_VERSION_IPV4, tag1_prefixes) - - ctx.create_acl_group(ACL_GROUP_1, IpVersion.IP_VERSION_IPV4) - ctx.asic_dash_acl_group_table.wait_for_n_keys(num_keys=1)[0] - - # Create acl rule before acl group - ctx.create_acl_rule(ACL_GROUP_1, ACL_RULE_1, - priority=1, action=Action.ACTION_PERMIT, terminating=False, - src_tag=[TAG_1], dst_addr=["192.168.1.2/30", "192.168.2.2/30", "192.168.3.2/30"], - src_port=[PortRange(0,1)], dst_port=[PortRange(0,1)]) - - - rule1_id= ctx.asic_dash_acl_rule_table.wait_for_n_keys(num_keys=1)[0] - rule1_attr = ctx.asic_dash_acl_rule_table[rule1_id] - - assert prefix_list_to_set(rule1_attr["SAI_DASH_ACL_RULE_ATTR_SIP"]) == tag1_prefixes - - ctx.remove_prefix_tag(TAG_1) - time.sleep(1) - - ctx.create_acl_rule(ACL_GROUP_1, ACL_RULE_1, - priority=2, action=Action.ACTION_DENY, terminating=False, - src_tag=[TAG_1], dst_addr=["192.168.1.2/30", "192.168.2.2/30", "192.168.3.2/30"], - src_port=[PortRange(0,1)], dst_port=[PortRange(0,1)]) - - rule2_id= ctx.asic_dash_acl_rule_table.wait_for_n_keys(num_keys=1)[0] - rule2_attr = ctx.asic_dash_acl_rule_table[rule2_id] - - assert prefix_list_to_set(rule2_attr["SAI_DASH_ACL_RULE_ATTR_SIP"]) == tag1_prefixes - - ctx.remove_acl_rule(ACL_GROUP_1, ACL_RULE_1) - ctx.remove_acl_rule(ACL_GROUP_1, ACL_RULE_2) - ctx.remove_acl_group(ACL_GROUP_1) - ctx.remove_prefix_tag(TAG_1) - ctx.remove_prefix_tag(TAG_2) - - def test_tag_create_delay(self, ctx): - ctx.create_acl_group(ACL_GROUP_1, IpVersion.IP_VERSION_IPV4) - ctx.asic_dash_acl_group_table.wait_for_n_keys(num_keys=1)[0] - - # Create acl rule before the TAG1, TAG_2 - ctx.create_acl_rule(ACL_GROUP_1, ACL_RULE_1, - priority=1, action=Action.ACTION_PERMIT, terminating=False, - src_tag=[TAG_1], dst_tag=[TAG_2], - src_port=[PortRange(0,1)], dst_port=[PortRange(0,1)]) - - # The rule should not be created since the TAG_1, TAG_2 are not created yet - time.sleep(3) - ctx.asic_dash_acl_rule_table.wait_for_n_keys(num_keys=0) - - tagsrc_prefixes = {"1.2.3.4/32", "5.6.0.0/16"} - ctx.create_prefix_tag(TAG_1, IpVersion.IP_VERSION_IPV4, tagsrc_prefixes) - - # The rule should not be created since the TAG_2 is not created yet - time.sleep(3) - ctx.asic_dash_acl_rule_table.wait_for_n_keys(num_keys=0) - - tagdst_prefixes = {"10.20.30.40/32", "50.60.0.0/16"} - ctx.create_prefix_tag(TAG_2, IpVersion.IP_VERSION_IPV4, tagdst_prefixes) - - rule_id= ctx.asic_dash_acl_rule_table.wait_for_n_keys(num_keys=1)[0] - rule_attr = ctx.asic_dash_acl_rule_table[rule_id] - - assert prefix_list_to_set(rule_attr["SAI_DASH_ACL_RULE_ATTR_SIP"]) == tagsrc_prefixes - assert prefix_list_to_set(rule_attr["SAI_DASH_ACL_RULE_ATTR_DIP"]) == tagdst_prefixes - - ctx.remove_acl_rule(ACL_GROUP_1, ACL_RULE_1) - ctx.remove_acl_group(ACL_GROUP_1) - ctx.remove_prefix_tag(TAG_1) - ctx.remove_prefix_tag(TAG_2) - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down -# before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_dash_vnet.py b/tests/test_dash_vnet.py deleted file mode 100644 index ec9c56b2a0..0000000000 --- a/tests/test_dash_vnet.py +++ /dev/null @@ -1,345 +0,0 @@ -from swsscommon import swsscommon - -from dash_api.appliance_pb2 import * -from dash_api.vnet_pb2 import * -from dash_api.eni_pb2 import * -from dash_api.route_pb2 import * -from dash_api.route_rule_pb2 import * -from dash_api.vnet_mapping_pb2 import * -from dash_api.route_type_pb2 import * -from dash_api.types_pb2 import * - -import typing -import time -import binascii -import uuid -import ipaddress -import sys -import socket - - -DVS_ENV = ["HWSKU=DPU-2P"] -NUM_PORTS = 2 - -def to_string(value): - if isinstance(value, bool): - return "true" if value else "false" - elif isinstance(value, bytes): - return value - return str(value) - - -class ProduceStateTable(object): - def __init__(self, database, table_name: str): - self.table = swsscommon.ProducerStateTable( - database.db_connection, - table_name) - - def __setitem__(self, key: str, pairs: typing.Union[dict, list, tuple]): - pairs_str = [] - if isinstance(pairs, dict): - pairs = pairs.items() - for k, v in pairs: - pairs_str.append((to_string(k), to_string(v))) - self.table.set(key, pairs_str) - - def __delitem__(self, key: str): - self.table.delete(str(key)) - - -class Table(object): - def __init__(self, database, table_name: str): - self.table_name = table_name - self.table = swsscommon.Table(database.db_connection, self.table_name) - - def __getitem__(self, key: str): - exists, result = self.table.get(str(key)) - if not exists: - return None - else: - return dict(result) - - def get_keys(self): - return self.table.getKeys() - - def get_newly_created_oid(self, old_oids): - new_oids = self.asic_db.wait_for_n_keys(table, len(old_oids) + 1) - oid = [ids for ids in new_oids if ids not in old_oids] - return oid[0] - - -class Dash(object): - def __init__(self, dvs): - self.dvs = dvs - self.app_dash_appliance_table = ProduceStateTable( - self.dvs.get_app_db(), "DASH_APPLIANCE_TABLE") - self.asic_direction_lookup_table = Table( - self.dvs.get_asic_db(), "ASIC_STATE:SAI_OBJECT_TYPE_DIRECTION_LOOKUP_ENTRY") - self.asic_vip_table = Table( - self.dvs.get_asic_db(), "ASIC_STATE:SAI_OBJECT_TYPE_VIP_ENTRY") - self.app_dash_vnet_table = ProduceStateTable( - self.dvs.get_app_db(), "DASH_VNET_TABLE") - self.asic_dash_vnet_table = Table( - self.dvs.get_asic_db(), "ASIC_STATE:SAI_OBJECT_TYPE_VNET") - self.app_dash_eni_table = ProduceStateTable( - self.dvs.get_app_db(), "DASH_ENI_TABLE") - self.asic_eni_table = Table( - self.dvs.get_asic_db(), "ASIC_STATE:SAI_OBJECT_TYPE_ENI") - self.asic_eni_ether_addr_map_table = Table( - self.dvs.get_asic_db(), "ASIC_STATE:SAI_OBJECT_TYPE_ENI_ETHER_ADDRESS_MAP_ENTRY") - self.app_dash_vnet_map_table = ProduceStateTable( - self.dvs.get_app_db(), "DASH_VNET_MAPPING_TABLE") - self.asic_dash_outbound_ca_to_pa_table = Table( - self.dvs.get_asic_db(), "ASIC_STATE:SAI_OBJECT_TYPE_OUTBOUND_CA_TO_PA_ENTRY") - self.asic_pa_validation_table = Table( - self.dvs.get_asic_db(), "ASIC_STATE:SAI_OBJECT_TYPE_PA_VALIDATION_ENTRY") - self.app_dash_route_table = ProduceStateTable( - self.dvs.get_app_db(), "DASH_ROUTE_TABLE") - self.app_dash_route_rule_table = ProduceStateTable( - self.dvs.get_app_db(), "DASH_ROUTE_RULE_TABLE") - self.asic_outbound_routing_table = Table( - self.dvs.get_asic_db(), "ASIC_STATE:SAI_OBJECT_TYPE_OUTBOUND_ROUTING_ENTRY") - self.asic_inbound_routing_rule_table = Table( - self.dvs.get_asic_db(), "ASIC_STATE:SAI_OBJECT_TYPE_INBOUND_ROUTING_ENTRY") - - def create_appliance(self, appliance_id, attr_maps: dict): - self.app_dash_appliance_table[str(appliance_id)] = attr_maps - - def remove_appliance(self, appliance_id): - del self.app_dash_appliance_table[str(appliance_id)] - - def create_vnet(self, vnet, attr_maps: dict): - self.app_dash_vnet_table[str(vnet)] = attr_maps - - def remove_vnet(self, vnet): - del self.app_dash_vnet_table[str(vnet)] - - def create_eni(self, eni, attr_maps: dict): - self.app_dash_eni_table[str(eni)] = attr_maps - - def remove_eni(self, eni): - del self.app_dash_eni_table[str(eni)] - - def create_vnet_map(self, vnet, ip, attr_maps: dict): - self.app_dash_vnet_map_table[str(vnet) + ":" + str(ip)] = attr_maps - - def remove_vnet_map(self, vnet, ip): - del self.app_dash_vnet_map_table[str(vnet) + ":" + str(ip)] - - def create_outbound_routing(self, mac_string, ip, attr_maps: dict): - self.app_dash_route_table[str(mac_string) + ":" + str(ip)] = attr_maps - - def remove_outbound_routing(self, mac_string, ip): - del self.app_dash_route_table[str(mac_string) + ":" + str(ip)] - - def create_inbound_routing(self, mac_string, vni, ip, attr_maps: dict): - self.app_dash_route_rule_table[str(mac_string) + ":" + str(vni) + ":" + str(ip)] = attr_maps - - def remove_inbound_routing(self, mac_string, vni, ip): - del self.app_dash_route_rule_table[str(mac_string) + ":" + str(vni) + ":" + str(ip)] - -class TestDash(object): - def test_appliance(self, dvs): - dashobj = Dash(dvs) - self.appliance_id = "100" - self.sip = "10.0.0.1" - self.vm_vni = "4321" - pb = Appliance() - pb.sip.ipv4 = socket.htonl(int(ipaddress.ip_address(self.sip))) - pb.vm_vni = int(self.vm_vni) - dashobj.create_appliance(self.appliance_id, {"pb": pb.SerializeToString()}) - time.sleep(3) - - direction_entries = dashobj.asic_direction_lookup_table.get_keys() - assert direction_entries - fvs = dashobj.asic_direction_lookup_table[direction_entries[0]] - for fv in fvs.items(): - if fv[0] == "SAI_DIRECTION_LOOKUP_ENTRY_ATTR_ACTION": - assert fv[1] == "SAI_DIRECTION_LOOKUP_ENTRY_ACTION_SET_OUTBOUND_DIRECTION" - vip_entries = dashobj.asic_vip_table.get_keys() - assert vip_entries - fvs = dashobj.asic_vip_table[vip_entries[0]] - for fv in fvs.items(): - if fv[0] == "SAI_VIP_ENTRY_ATTR_ACTION": - assert fv[1] == "SAI_VIP_ENTRY_ACTION_ACCEPT" - return dashobj - - def test_vnet(self, dvs): - dashobj = Dash(dvs) - self.vnet = "Vnet1" - self.vni = "45654" - self.guid = "559c6ce8-26ab-4193-b946-ccc6e8f930b2" - pb = Vnet() - pb.vni = int(self.vni) - pb.guid.value = bytes.fromhex(uuid.UUID(self.guid).hex) - dashobj.create_vnet(self.vnet, {"pb": pb.SerializeToString()}) - time.sleep(3) - vnets = dashobj.asic_dash_vnet_table.get_keys() - assert vnets - self.vnet_oid = vnets[0] - vnet_attr = dashobj.asic_dash_vnet_table[self.vnet_oid] - assert vnet_attr["SAI_VNET_ATTR_VNI"] == "45654" - return dashobj - - def test_eni(self, dvs): - dashobj = Dash(dvs) - self.vnet = "Vnet1" - self.mac_string = "F4939FEFC47E" - self.mac_address = "F4:93:9F:EF:C4:7E" - self.eni_id = "497f23d7-f0ac-4c99-a98f-59b470e8c7bd" - self.underlay_ip = "25.1.1.1" - self.admin_state = "enabled" - pb = Eni() - pb.eni_id = self.eni_id - pb.mac_address = bytes.fromhex(self.mac_address.replace(":", "")) - pb.underlay_ip.ipv4 = socket.htonl(int(ipaddress.ip_address(self.underlay_ip))) - pb.admin_state = State.STATE_ENABLED - pb.vnet = self.vnet - dashobj.create_eni(self.mac_string, {"pb": pb.SerializeToString()}) - time.sleep(3) - vnets = dashobj.asic_dash_vnet_table.get_keys() - assert vnets - self.vnet_oid = vnets[0] - enis = dashobj.asic_eni_table.get_keys() - assert enis - self.eni_oid = enis[0]; - fvs = dashobj.asic_eni_table[enis[0]] - for fv in fvs.items(): - if fv[0] == "SAI_ENI_ATTR_VNET_ID": - assert fv[1] == str(self.vnet_oid) - if fv[0] == "SAI_ENI_ATTR_PPS": - assert fv[1] == 0 - if fv[0] == "SAI_ENI_ATTR_CPS": - assert fv[1] == 0 - if fv[0] == "SAI_ENI_ATTR_FLOWS": - assert fv[1] == 0 - if fv[0] == "SAI_ENI_ATTR_ADMIN_STATE": - assert fv[1] == "true" - - time.sleep(3) - eni_addr_maps = dashobj.asic_eni_ether_addr_map_table.get_keys() - assert eni_addr_maps - fvs = dashobj.asic_eni_ether_addr_map_table[eni_addr_maps[0]] - for fv in fvs.items(): - if fv[0] == "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ENI_ID": - assert fv[1] == str(self.eni_oid) - - # test admin state update - pb.admin_state = State.STATE_DISABLED - dashobj.create_eni(self.mac_string, {"pb": pb.SerializeToString()}) - time.sleep(3) - enis = dashobj.asic_eni_table.get_keys() - assert len(enis) == 1 - assert enis[0] == self.eni_oid - eni_attrs = dashobj.asic_eni_table[self.eni_oid] - assert eni_attrs["SAI_ENI_ATTR_ADMIN_STATE"] == "false" - - return dashobj - - def test_vnet_map(self, dvs): - dashobj = Dash(dvs) - self.vnet = "Vnet1" - self.ip1 = "10.1.1.1" - self.ip2 = "10.1.1.2" - self.mac_address = "F4:93:9F:EF:C4:7E" - self.routing_type = "vnet_encap" - self.underlay_ip = "101.1.2.3" - pb = VnetMapping() - pb.mac_address = bytes.fromhex(self.mac_address.replace(":", "")) - pb.action_type = RoutingType.ROUTING_TYPE_VNET_ENCAP - pb.underlay_ip.ipv4 = socket.htonl(int(ipaddress.ip_address(self.underlay_ip))) - - dashobj.create_vnet_map(self.vnet, self.ip1, {"pb": pb.SerializeToString()}) - dashobj.create_vnet_map(self.vnet, self.ip2, {"pb": pb.SerializeToString()}) - time.sleep(3) - - vnet_ca_to_pa_maps = dashobj.asic_dash_outbound_ca_to_pa_table.get_keys() - assert len(vnet_ca_to_pa_maps) >= 2 - fvs = dashobj.asic_dash_outbound_ca_to_pa_table[vnet_ca_to_pa_maps[0]] - for fv in fvs.items(): - if fv[0] == "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_UNDERLAY_DIP": - assert fv[1] == "101.1.2.3" - if fv[0] == "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_OVERLAY_DMAC": - assert fv[1] == "F4:93:9F:EF:C4:7E" - - vnet_pa_validation_maps = dashobj.asic_pa_validation_table.get_keys() - assert vnet_pa_validation_maps - fvs = dashobj.asic_pa_validation_table[vnet_pa_validation_maps[0]] - for fv in fvs.items(): - if fv[0] == "SAI_PA_VALIDATION_ENTRY_ATTR_ACTION": - assert fv[1] == "SAI_PA_VALIDATION_ENTRY_ACTION_PERMIT" - return dashobj - - def test_outbound_routing(self, dvs): - dashobj = Dash(dvs) - self.vnet = "Vnet1" - self.mac_string = "F4939FEFC47E" - self.ip = "10.1.0.0/24" - self.action_type = "vnet_direct" - self.overlay_ip= "10.0.0.6" - pb = Route() - pb.action_type = RoutingType.ROUTING_TYPE_VNET_DIRECT - pb.vnet_direct.vnet = self.vnet - pb.vnet_direct.overlay_ip.ipv4 = socket.htonl(int(ipaddress.ip_address(self.overlay_ip))) - dashobj.create_outbound_routing(self.mac_string, self.ip, {"pb": pb.SerializeToString()}) - time.sleep(3) - - outbound_routing_entries = dashobj.asic_outbound_routing_table.get_keys() - assert outbound_routing_entries - fvs = dashobj.asic_outbound_routing_table[outbound_routing_entries[0]] - for fv in fvs.items(): - if fv[0] == "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_ACTION": - assert fv[1] == "SAI_OUTBOUND_ROUTING_ENTRY_ACTION_ROUTE_VNET_DIRECT" - if fv[0] == "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_OVERLAY_IP": - assert fv[1] == "10.0.0.6" - assert "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_DST_VNET_ID" in fvs - return dashobj - - def test_inbound_routing(self, dvs): - dashobj = Dash(dvs) - self.mac_string = "F4939FEFC47E" - self.vnet = "Vnet1" - self.vni = "3251" - self.ip = "10.1.1.1" - self.action_type = "decap" - self.pa_validation = "true" - self.priority = "1" - self.protocol = "0" - pb = RouteRule() -# pb.action_type = RoutingType.ROUTING_TYPE_DECAP - pb.pa_validation = True - pb.priority = int(self.priority) - pb.protocol = int(self.protocol) - pb.vnet = self.vnet - - dashobj.create_inbound_routing(self.mac_string, self.vni, self.ip, {"pb": pb.SerializeToString()}) - time.sleep(3) - - inbound_routing_entries = dashobj.asic_inbound_routing_rule_table.get_keys() - assert inbound_routing_entries - fvs = dashobj.asic_inbound_routing_rule_table[inbound_routing_entries[0]] - for fv in fvs.items(): - if fv[0] == "SAI_INBOUND_ROUTING_ENTRY_ATTR_ACTION": - assert fv[1] == "SAI_INBOUND_ROUTING_ENTRY_ACTION_VXLAN_DECAP_PA_VALIDATE" - return dashobj - - def test_cleanup(self, dvs): - dashobj = Dash(dvs) - self.vnet = "Vnet1" - self.mac_string = "F4939FEFC47E" - self.vni = "3251" - self.sip = "10.1.1.1" - self.dip = "10.1.0.0/24" - self.appliance_id = "100" - dashobj.remove_inbound_routing(self.mac_string, self.vni, self.sip) - dashobj.remove_outbound_routing(self.mac_string, self.dip) - dashobj.remove_eni(self.mac_string) - dashobj.remove_vnet_map(self.vnet, self.sip) - dashobj.remove_vnet(self.vnet) - dashobj.remove_appliance(self.appliance_id) - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down -# before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_dirbcast.py b/tests/test_dirbcast.py deleted file mode 100644 index d5669d2c4f..0000000000 --- a/tests/test_dirbcast.py +++ /dev/null @@ -1,102 +0,0 @@ -import time -import re -import json -import pytest - -from swsscommon import swsscommon - - -class TestDirectedBroadcast(object): - def test_DirectedBroadcast(self, dvs, testlog): - - db = swsscommon.DBConnector(4, dvs.redis_sock, 0) - adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - - # create vlan in config db - tbl = swsscommon.Table(db, "VLAN") - fvs = swsscommon.FieldValuePairs([("vlanid", "100")]) - tbl.set("Vlan100", fvs) - - # create a vlan member in config db - tbl = swsscommon.Table(db, "VLAN_MEMBER") - fvs = swsscommon.FieldValuePairs([("tagging_mode", "tagged")]) - tbl.set("Vlan100|Ethernet24", fvs) - - time.sleep(1) - - # create vlan interface in config db - tbl = swsscommon.Table(db, "VLAN_INTERFACE") - fvs = swsscommon.FieldValuePairs([("family", "IPv4")]) - tbl.set("Vlan100", fvs) - tbl.set("Vlan100|192.169.0.1/27", fvs) - - time.sleep(1) - - # check vlan in asic db - atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - keys = atbl.getKeys() - vlan_oid = None - - for key in keys: - if key == dvs.asicdb.default_vlan_id: - continue - - (status, fvs) = atbl.get(key) - assert status == True - - if fvs[0][0] == "SAI_VLAN_ATTR_VLAN_ID": - assert fvs[0][1] == '100' - vlan_oid = key - - assert vlan_oid != None - - # check router interface in asic db - atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") - keys = atbl.getKeys() - rif_oid = None - - for key in keys: - (status, fvs) = atbl.get(key) - assert status == True - for fv in fvs: - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_VLAN_ID": - assert vlan_oid == fv[1] - rif_oid = key - - assert rif_oid != None - - # check neighbor entry in asic db - atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY") - keys = atbl.getKeys() - dir_bcast = False - - for key in keys: - neigh = json.loads(key) - - if neigh['ip'] == "192.169.0.31": - dir_bcast = True - assert neigh['rif'] == rif_oid - (status, fvs) = atbl.get(key) - assert status == True - if fvs[0][0] == "SAI_NEIGHBOR_ENTRY_ATTR_DST_MAC_ADDRESS": - assert fvs[0][1] == "FF:FF:FF:FF:FF:FF" - - assert dir_bcast - - # Explicitly add a neighbor entry with BCAST MAC and check if its in ASIC_DB - dvs.runcmd("ip neigh replace 192.169.0.30 lladdr FF:FF:FF:FF:FF:FF dev Vlan100") - - time.sleep(1) - - keys = atbl.getKeys() - for key in keys: - neigh = json.loads(key) - - if neigh['ip'] == "192.169.0.30": - assert False - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_drop_counters.py b/tests/test_drop_counters.py deleted file mode 100644 index cd089be917..0000000000 --- a/tests/test_drop_counters.py +++ /dev/null @@ -1,791 +0,0 @@ -import time -import pytest - -from swsscommon import swsscommon - -# Supported drop counters -PORT_INGRESS_DROPS = 'PORT_INGRESS_DROPS' -PORT_EGRESS_DROPS = 'PORT_EGRESS_DROPS' -SWITCH_INGRESS_DROPS = 'SWITCH_INGRESS_DROPS' -SWITCH_EGRESS_DROPS = 'SWITCH_EGRESS_DROPS' - -# Debug Counter Table -DEBUG_COUNTER_TABLE = 'DEBUG_COUNTER' -DROP_REASON_TABLE = 'DEBUG_COUNTER_DROP_REASON' - -# Debug Counter Capability Table -CAPABILITIES_TABLE = 'DEBUG_COUNTER_CAPABILITIES' -CAP_COUNT = 'count' -CAP_REASONS = 'reasons' -SUPPORTED_COUNTER_CAPABILITIES = [CAP_COUNT, CAP_REASONS] -INGRESS_COUNTER_TYPES = [PORT_INGRESS_DROPS, SWITCH_INGRESS_DROPS] -EGRESS_COUNTER_TYPES = [PORT_EGRESS_DROPS, SWITCH_EGRESS_DROPS] -SUPPORTED_COUNTER_TYPES = INGRESS_COUNTER_TYPES + EGRESS_COUNTER_TYPES - -# Debug Counter Flex Counter Group -FLEX_COUNTER_GROUP_TABLE = 'FLEX_COUNTER_GROUP_TABLE' -DEBUG_COUNTER_FLEX_GROUP = 'DEBUG_COUNTER' -FLEX_STATS_MODE_FIELD = 'STATS_MODE' -FLEX_POLL_INTERVAL_FIELD = 'POLL_INTERVAL' -FLEX_STATUS_FIELD = 'FLEX_COUNTER_STATUS' -FLEX_STATUS_ENABLE = 'enable' -EXPECTED_FLEX_STATS_MODE = 'STATS_MODE_READ' -EXPECTED_POLL_INTERVAL_THRESHOLD = 0 -EXPECTED_FLEX_GROUP_FIELDS = [FLEX_STATS_MODE_FIELD, FLEX_POLL_INTERVAL_FIELD, FLEX_STATUS_FIELD] - -# Debug Counter Flex Counters -FLEX_COUNTER_TABLE = 'FLEX_COUNTER_TABLE:DEBUG_COUNTER' -PORT_DEBUG_COUNTER_LIST = 'PORT_DEBUG_COUNTER_ID_LIST' -SWITCH_DEBUG_COUNTER_LIST = 'SWITCH_DEBUG_COUNTER_ID_LIST' -PORT_STAT_BASE = 'SAI_PORT_STAT_IN_CONFIGURED_DROP_REASONS_0_DROPPED_PKTS' -PORT_STAT_INDEX_1 = 'SAI_PORT_STAT_IN_CONFIGURED_DROP_REASONS_1_DROPPED_PKTS' -SWITCH_STAT_BASE = 'SAI_SWITCH_STAT_IN_CONFIGURED_DROP_REASONS_0_DROPPED_PKTS' -SWITCH_STAT_INDEX_1 = 'SAI_SWITCH_STAT_IN_CONFIGURED_DROP_REASONS_1_DROPPED_PKTS' - -# ASIC DB Fields -ASIC_STATE_TABLE = 'ASIC_STATE:SAI_OBJECT_TYPE_DEBUG_COUNTER' -ASIC_COUNTER_TYPE_FIELD = 'SAI_DEBUG_COUNTER_ATTR_TYPE' -ASIC_COUNTER_INGRESS_REASON_LIST_FIELD = 'SAI_DEBUG_COUNTER_ATTR_IN_DROP_REASON_LIST' -ASIC_COUNTER_EGRESS_REASON_LIST_FIELD = 'SAI_DEBUG_COUNTER_ATTR_OUT_DROP_REASON_LIST' -ASIC_COUNTER_PORT_IN_TYPE = 'SAI_DEBUG_COUNTER_TYPE_PORT_IN_DROP_REASONS' -ASIC_COUNTER_PORT_OUT_TYPE = 'SAI_DEBUG_COUNTER_TYPE_PORT_OUT_DROP_REASONS' -ASIC_COUNTER_SWITCH_IN_TYPE = 'SAI_DEBUG_COUNTER_TYPE_SWITCH_IN_DROP_REASONS' -ASIC_COUNTER_SWITCH_OUT_TYPE = 'SAI_DEBUG_COUNTER_TYPE_SWITCH_OUT_DROP_REASONS' -EXPECTED_ASIC_FIELDS = [ASIC_COUNTER_TYPE_FIELD, ASIC_COUNTER_INGRESS_REASON_LIST_FIELD, ASIC_COUNTER_EGRESS_REASON_LIST_FIELD] -EXPECTED_NUM_ASIC_FIELDS = 2 - -# port to be add and removed -PORT = "Ethernet0" -PORT_TABLE_NAME = "PORT" - -@pytest.mark.usefixtures('dvs_port_manager') -# FIXME: It is really annoying to have to re-run tests due to inconsistent timing, should -# implement some sort of polling interface for checking ASIC/flex counter tables after -# applying changes to config DB -class TestDropCounters(object): - def setup_db(self, dvs): - self.asic_db = swsscommon.DBConnector(1, dvs.redis_sock, 0) - self.config_db = swsscommon.DBConnector(4, dvs.redis_sock, 0) - self.flex_db = swsscommon.DBConnector(5, dvs.redis_sock, 0) - self.state_db = swsscommon.DBConnector(6, dvs.redis_sock, 0) - self.counters_db = swsscommon.DBConnector(2, dvs.redis_sock, 0) - - def genericGetAndAssert(self, table, key): - status, fields = table.get(key) - assert status - return fields - - def checkFlexCounterGroup(self): - flex_group_table = swsscommon.Table(self.flex_db, FLEX_COUNTER_GROUP_TABLE) - status, group_vars = flex_group_table.get(DEBUG_COUNTER_FLEX_GROUP) - assert status - assert len(group_vars) == len(EXPECTED_FLEX_GROUP_FIELDS) - - for var in group_vars: - assert len(var) == 2 - group_field = var[0] - group_contents = var[1] - - assert group_field in EXPECTED_FLEX_GROUP_FIELDS - - if group_field == FLEX_STATS_MODE_FIELD: - assert group_contents == EXPECTED_FLEX_STATS_MODE - elif group_field == FLEX_POLL_INTERVAL_FIELD: - assert int(group_contents) > EXPECTED_POLL_INTERVAL_THRESHOLD - elif group_field == FLEX_STATUS_FIELD: - assert group_contents == FLEX_STATUS_ENABLE - else: - assert False - - def checkFlexState(self, stats, counter_list_type): - flex_counter_table = swsscommon.Table(self.flex_db, FLEX_COUNTER_TABLE) - - for oid in flex_counter_table.getKeys(): - attributes = self.genericGetAndAssert(flex_counter_table, oid) - assert len(attributes) == 1 - field, tracked_stats = attributes[0] - assert field == counter_list_type - for stat in stats: - assert stat in tracked_stats - - def checkASICState(self, counter, counter_type, reasons): - asic_state_table = swsscommon.Table(self.asic_db, ASIC_STATE_TABLE) - asic_counter_params = self.genericGetAndAssert(asic_state_table, counter) - if len(asic_counter_params) != EXPECTED_NUM_ASIC_FIELDS: - return False - - for param in asic_counter_params: - param_name = param[0] - param_contents = param[1] - - if param_name not in EXPECTED_ASIC_FIELDS: - return False - - if param_name == ASIC_COUNTER_TYPE_FIELD: - if param_contents != counter_type: - return False - elif param_name == ASIC_COUNTER_INGRESS_REASON_LIST_FIELD: - if int(param_contents[0]) != len(reasons): - return False - - for reason in reasons: - if reason not in param_contents: - return False - else: - return False - - return True - - def create_drop_counter(self, name, counter_type): - debug_counter_table = swsscommon.Table(self.config_db, DEBUG_COUNTER_TABLE) - counter_metadata = swsscommon.FieldValuePairs([('type', counter_type)]) - debug_counter_table.set(name, counter_metadata) - - def add_drop_reason(self, name, drop_reason): - drop_reason_table = swsscommon.Table(self.config_db, '{}|{}'.format(DROP_REASON_TABLE, name)) - drop_reason_entry = swsscommon.FieldValuePairs([('NULL', 'NULL')]) - drop_reason_table.set(drop_reason, drop_reason_entry) - - def remove_drop_reason(self, name, drop_reason): - drop_reason_table = swsscommon.Table(self.config_db, '{}|{}'.format(DROP_REASON_TABLE, name)) - drop_reason_table._del(drop_reason) - - def delete_drop_counter(self, name): - debug_counter_table = swsscommon.Table(self.config_db, DEBUG_COUNTER_TABLE) - debug_counter_table._del(name) - - def test_deviceCapabilitiesTablePopulated(self, dvs, testlog): - """ - This test verifies that DebugCounterOrch has succesfully queried - the capabilities for this device and populated state DB with the - correct values. - """ - self.setup_db(dvs) - - # Check that the capabilities table 1) exists and 2) has been populated - # for each type of counter - capabilities_table = swsscommon.Table(self.state_db, CAPABILITIES_TABLE) - counter_types = capabilities_table.getKeys() - assert len(counter_types) == len(SUPPORTED_COUNTER_TYPES) - - # Check that the data for each counter type is consistent - for counter_type in SUPPORTED_COUNTER_TYPES: - assert counter_type in counter_types - - # By definiton, each capability entry should contain exactly the same fields - counter_capabilities = self.genericGetAndAssert(capabilities_table, counter_type) - assert len(counter_capabilities) == len(SUPPORTED_COUNTER_CAPABILITIES) - - # Check that the values of each field actually match the - # capabilities currently defined in the virtual switch - for capability in counter_capabilities: - assert len(capability) == 2 - capability_name = capability[0] - capability_contents = capability[1] - - assert capability_name in SUPPORTED_COUNTER_CAPABILITIES - - if capability_name == CAP_COUNT: - assert int(capability_contents) == 3 - elif capability_name == CAP_REASONS and counter_type in INGRESS_COUNTER_TYPES: - assert len(capability_contents.split(',')) == 3 - elif capability_name == CAP_REASONS and counter_type in EGRESS_COUNTER_TYPES: - assert len(capability_contents.split(',')) == 2 - else: - assert False - - def test_flexCounterGroupInitialized(self, dvs, testlog): - """ - This test verifies that DebugCounterOrch has succesfully - setup a flex counter group for the drop counters. - """ - self.setup_db(dvs) - self.checkFlexCounterGroup() - - def test_createAndRemoveDropCounterBasic(self, dvs, testlog): - """ - This test verifies that a drop counter can succesfully be - created and deleted. - """ - self.setup_db(dvs) - - asic_state_table = swsscommon.Table(self.asic_db, ASIC_STATE_TABLE) - flex_counter_table = swsscommon.Table(self.flex_db, FLEX_COUNTER_TABLE) - - name = 'TEST' - reason = 'L3_ANY' - - self.create_drop_counter(name, PORT_INGRESS_DROPS) - - # Because no reasons have been added to the counter yet, nothing should - # be put in ASIC DB and the flex counters should not start polling yet. - assert len(asic_state_table.getKeys()) == 0 - assert len(flex_counter_table.getKeys()) == 0 - - self.add_drop_reason(name, reason) - time.sleep(3) - - # Verify that the flex counters have been created to poll the new - # counter. - self.checkFlexState([PORT_STAT_BASE], PORT_DEBUG_COUNTER_LIST) - - # Verify that the drop counter has been added to ASIC DB with the - # correct reason added. - asic_keys = asic_state_table.getKeys() - assert len(asic_keys) == 1 - assert self.checkASICState(asic_keys[0], ASIC_COUNTER_PORT_IN_TYPE, [reason]) - - self.delete_drop_counter(name) - time.sleep(3) - - # Verify that the counter has been removed from ASIC DB and the flex - # counters have been torn down. - assert len(asic_state_table.getKeys()) == 0 - assert len(flex_counter_table.getKeys()) == 0 - - # Cleanup for the next test. - self.remove_drop_reason(name, reason) - - def test_createAndRemoveDropCounterReversed(self, dvs, testlog): - """ - This test verifies that a drop counter can succesfully be created - and deleted when the drop reasons are added before the counter is - created. - """ - self.setup_db(dvs) - - asic_state_table = swsscommon.Table(self.asic_db, ASIC_STATE_TABLE) - flex_counter_table = swsscommon.Table(self.flex_db, FLEX_COUNTER_TABLE) - - name = 'TEST' - reason = 'L3_ANY' - - self.add_drop_reason(name, reason) - - # Because the actual counter has not been created yet, nothing should - # be put in ASIC DB and the flex counters should not start polling yet. - assert len(asic_state_table.getKeys()) == 0 - assert len(flex_counter_table.getKeys()) == 0 - - self.create_drop_counter(name, PORT_INGRESS_DROPS) - time.sleep(3) - - # Verify that the flex counters have been created to poll the new - # counter. - self.checkFlexState([PORT_STAT_BASE], PORT_DEBUG_COUNTER_LIST) - - # Verify that the drop counter has been added to ASIC DB with the - # correct reason added. - asic_keys = asic_state_table.getKeys() - assert len(asic_keys) == 1 - assert self.checkASICState(asic_keys[0], ASIC_COUNTER_PORT_IN_TYPE, [reason]) - - self.delete_drop_counter(name) - time.sleep(3) - - # Verify that the counter has been removed from ASIC DB and the flex - # counters have been torn down. - assert len(asic_state_table.getKeys()) == 0 - assert len(flex_counter_table.getKeys()) == 0 - - # Cleanup for the next test. - self.remove_drop_reason(name, reason) - - def test_createCounterWithInvalidCounterType(self, dvs, testlog): - """ - This test verifies that the state of the system is unaffected - when an invalid counter type is passed to CONFIG DB. - """ - self.setup_db(dvs) - - asic_state_table = swsscommon.Table(self.asic_db, ASIC_STATE_TABLE) - flex_counter_table = swsscommon.Table(self.flex_db, FLEX_COUNTER_TABLE) - - name = 'BAD_CTR' - reason = 'L3_ANY' - - self.create_drop_counter(name, 'THIS_IS_DEFINITELY_NOT_A_VALID_COUNTER_TYPE') - self.add_drop_reason(name, reason) - time.sleep(3) - - # Verify that nothing has been added to ASIC DB and no flex counters - # were created. - assert len(asic_state_table.getKeys()) == 0 - assert len(flex_counter_table.getKeys()) == 0 - - # Cleanup for the next test. - self.delete_drop_counter(name) - self.remove_drop_reason(name, reason) - - def test_createCounterWithInvalidDropReason(self, dvs, testlog): - """ - This test verifies that the state of the system is unaffected - when an invalid drop reason is passed to CONFIG DB. - """ - self.setup_db(dvs) - - asic_state_table = swsscommon.Table(self.asic_db, ASIC_STATE_TABLE) - flex_counter_table = swsscommon.Table(self.flex_db, FLEX_COUNTER_TABLE) - - name = 'BAD_CTR' - reason = 'THIS_IS_DEFINITELY_NOT_A_VALID_DROP_REASON' - - self.create_drop_counter(name, SWITCH_INGRESS_DROPS) - self.add_drop_reason(name, reason) - time.sleep(3) - - # Verify that nothing has been added to ASIC DB and no flex counters - # were created. - assert len(asic_state_table.getKeys()) == 0 - assert len(flex_counter_table.getKeys()) == 0 - - # Cleanup for the next test. - self.delete_drop_counter(name) - self.remove_drop_reason(name, reason) - - def test_addReasonToInitializedCounter(self, dvs, testlog): - """ - This test verifies that a drop reason can be added to a counter - that has already been initialized. - """ - self.setup_db(dvs) - - asic_state_table = swsscommon.Table(self.asic_db, ASIC_STATE_TABLE) - flex_counter_table = swsscommon.Table(self.flex_db, FLEX_COUNTER_TABLE) - - name = 'ADD_TEST' - reason1 = 'L3_ANY' - - self.create_drop_counter(name, SWITCH_INGRESS_DROPS) - self.add_drop_reason(name, reason1) - time.sleep(3) - - # Verify that a counter has been created. We will verify the state of - # the counter in the next step. - assert len(asic_state_table.getKeys()) == 1 - self.checkFlexState([SWITCH_STAT_BASE], SWITCH_DEBUG_COUNTER_LIST) - - reason2 = 'ACL_ANY' - self.add_drop_reason(name, reason2) - time.sleep(3) - - # Verify that the drop counter has been added to ASIC DB, including the - # reason that was added. - asic_keys = asic_state_table.getKeys() - assert len(asic_keys) == 1 - assert self.checkASICState(asic_keys[0], ASIC_COUNTER_SWITCH_IN_TYPE, [reason1, reason2]) - - # Cleanup for the next test. - self.delete_drop_counter(name) - self.remove_drop_reason(name, reason1) - self.remove_drop_reason(name, reason2) - - def test_removeReasonFromInitializedCounter(self, dvs, testlog): - """ - This test verifies that a drop reason can be removed from a counter - that has already been initialized without deleting the counter. - """ - self.setup_db(dvs) - - asic_state_table = swsscommon.Table(self.asic_db, ASIC_STATE_TABLE) - flex_counter_table = swsscommon.Table(self.flex_db, FLEX_COUNTER_TABLE) - - name = 'ADD_TEST' - reason1 = 'L3_ANY' - reason2 = 'ACL_ANY' - - self.create_drop_counter(name, SWITCH_INGRESS_DROPS) - self.add_drop_reason(name, reason1) - self.add_drop_reason(name, reason2) - time.sleep(3) - - # Verify that a counter has been created. We will verify the state of - # the counter in the next step. - assert len(asic_state_table.getKeys()) == 1 - self.checkFlexState([SWITCH_STAT_BASE], SWITCH_DEBUG_COUNTER_LIST) - - self.remove_drop_reason(name, reason2) - time.sleep(3) - - # Verify that the drop counter has been added to ASIC DB, excluding the - # reason that was removed. - asic_keys = asic_state_table.getKeys() - assert len(asic_keys) == 1 - assert self.checkASICState(asic_keys[0], ASIC_COUNTER_SWITCH_IN_TYPE, [reason1]) - - # Cleanup for the next test. - self.delete_drop_counter(name) - self.remove_drop_reason(name, reason1) - - def test_removeAllDropReasons(self, dvs, testlog): - """ - This test verifies that it is not possible to remove all drop - reasons from a drop counter. - """ - self.setup_db(dvs) - - asic_state_table = swsscommon.Table(self.asic_db, ASIC_STATE_TABLE) - flex_counter_table = swsscommon.Table(self.flex_db, FLEX_COUNTER_TABLE) - - name = 'ADD_TEST' - reason1 = 'L3_ANY' - - self.create_drop_counter(name, SWITCH_INGRESS_DROPS) - self.add_drop_reason(name, reason1) - time.sleep(3) - - # Verify that a counter has been created. We will verify the state of - # the counter in the next step. - assert len(asic_state_table.getKeys()) == 1 - self.checkFlexState([SWITCH_STAT_BASE], SWITCH_DEBUG_COUNTER_LIST) - - self.remove_drop_reason(name, reason1) - time.sleep(3) - - # Verify that the drop counter has been added to ASIC DB, including the - # last reason that we attempted to remove. - asic_keys = asic_state_table.getKeys() - assert len(asic_keys) == 1 - assert self.checkASICState(asic_keys[0], ASIC_COUNTER_SWITCH_IN_TYPE, [reason1]) - - # Cleanup for the next test. - self.delete_drop_counter(name) - - def test_addDropReasonMultipleTimes(self, dvs, testlog): - """ - This test verifies that the same drop reason can be added multiple - times without affecting the system. - """ - self.setup_db(dvs) - - asic_state_table = swsscommon.Table(self.asic_db, ASIC_STATE_TABLE) - flex_counter_table = swsscommon.Table(self.flex_db, FLEX_COUNTER_TABLE) - - name = 'ADD_TEST' - reason1 = 'L3_ANY' - - self.create_drop_counter(name, SWITCH_INGRESS_DROPS) - self.add_drop_reason(name, reason1) - time.sleep(3) - - # Verify that a counter has been created. We will verify the state of - # the counter in the next step. - assert len(asic_state_table.getKeys()) == 1 - self.checkFlexState([SWITCH_STAT_BASE], SWITCH_DEBUG_COUNTER_LIST) - - reason2 = 'ACL_ANY' - self.add_drop_reason(name, reason2) - time.sleep(3) - - # Verify that the drop counter has been added to ASIC DB, including the - # reason that was added. - asic_keys = asic_state_table.getKeys() - assert len(asic_keys) == 1 - assert self.checkASICState(asic_keys[0], ASIC_COUNTER_SWITCH_IN_TYPE, [reason1, reason2]) - - self.add_drop_reason(name, reason2) - time.sleep(3) - - # Verify that the ASIC state is the same as before adding the redundant - # drop reason. - asic_keys = asic_state_table.getKeys() - assert len(asic_keys) == 1 - assert self.checkASICState(asic_keys[0], ASIC_COUNTER_SWITCH_IN_TYPE, [reason1, reason2]) - - # Cleanup for the next test. - self.delete_drop_counter(name) - self.remove_drop_reason(name, reason1) - self.remove_drop_reason(name, reason2) - - def test_addInvalidDropReason(self, dvs, testlog): - """ - This test verifies that adding a drop reason to a counter that is - not recognized will not affect the system. - """ - self.setup_db(dvs) - - asic_state_table = swsscommon.Table(self.asic_db, ASIC_STATE_TABLE) - flex_counter_table = swsscommon.Table(self.flex_db, FLEX_COUNTER_TABLE) - - name = 'ADD_TEST' - reason1 = 'L3_ANY' - - self.create_drop_counter(name, SWITCH_INGRESS_DROPS) - self.add_drop_reason(name, reason1) - time.sleep(3) - - # Verify that a counter has been created. We will verify the state of - # the counter in the next step. - assert len(asic_state_table.getKeys()) == 1 - self.checkFlexState([SWITCH_STAT_BASE], SWITCH_DEBUG_COUNTER_LIST) - - reason2 = 'ACL_ANY' - self.add_drop_reason(name, reason2) - time.sleep(3) - - # Verify that the drop counter has been added to ASIC DB, including the - # reason that was added. - asic_keys = asic_state_table.getKeys() - assert len(asic_keys) == 1 - assert self.checkASICState(asic_keys[0], ASIC_COUNTER_SWITCH_IN_TYPE, [reason1, reason2]) - - dummy_reason = 'ZOBOOMBAFOO' - self.add_drop_reason(name, dummy_reason) - time.sleep(3) - - # Verify that the ASIC state is the same as before adding the invalid - # drop reason. - asic_keys = asic_state_table.getKeys() - assert len(asic_keys) == 1 - assert self.checkASICState(asic_keys[0], ASIC_COUNTER_SWITCH_IN_TYPE, [reason1, reason2]) - - # Cleanup for the next test. - self.delete_drop_counter(name) - self.remove_drop_reason(name, reason1) - self.remove_drop_reason(name, reason2) - - def test_removeDropReasonMultipleTimes(self, dvs, testlog): - """ - This test verifies that removing a drop reason multiple times will - not affect the system. - """ - self.setup_db(dvs) - - asic_state_table = swsscommon.Table(self.asic_db, ASIC_STATE_TABLE) - flex_counter_table = swsscommon.Table(self.flex_db, FLEX_COUNTER_TABLE) - - name = 'ADD_TEST' - reason1 = 'L3_ANY' - reason2 = 'ACL_ANY' - - self.create_drop_counter(name, SWITCH_INGRESS_DROPS) - self.add_drop_reason(name, reason1) - self.add_drop_reason(name, reason2) - time.sleep(3) - - # Verify that a counter has been created. We will verify the state of - # the counter in the next step. - assert len(asic_state_table.getKeys()) == 1 - self.checkFlexState([SWITCH_STAT_BASE], SWITCH_DEBUG_COUNTER_LIST) - - self.remove_drop_reason(name, reason2) - time.sleep(3) - - # Verify that the drop counter has been added to ASIC DB, excluding the - # reason that was removed. - asic_keys = asic_state_table.getKeys() - assert len(asic_keys) == 1 - assert self.checkASICState(asic_keys[0], ASIC_COUNTER_SWITCH_IN_TYPE, [reason1]) - - self.remove_drop_reason(name, reason2) - time.sleep(3) - - # Verify that the ASIC state is the same as before the redundant - # remove operation. - asic_keys = asic_state_table.getKeys() - assert len(asic_keys) == 1 - assert self.checkASICState(asic_keys[0], ASIC_COUNTER_SWITCH_IN_TYPE, [reason1]) - - # Cleanup for the next test. - self.delete_drop_counter(name) - self.remove_drop_reason(name, reason1) - - def test_removeNonexistentDropReason(self, dvs, testlog): - """ - This test verifies that removing a drop reason that does not exist - on the device will not affect the system. - """ - self.setup_db(dvs) - - asic_state_table = swsscommon.Table(self.asic_db, ASIC_STATE_TABLE) - flex_counter_table = swsscommon.Table(self.flex_db, FLEX_COUNTER_TABLE) - - name = 'ADD_TEST' - reason1 = 'L3_ANY' - reason2 = 'ACL_ANY' - - self.create_drop_counter(name, SWITCH_INGRESS_DROPS) - self.add_drop_reason(name, reason1) - time.sleep(3) - - # Verify the counter has been created and is in the correct state. - asic_keys = asic_state_table.getKeys() - assert len(asic_keys) == 1 - assert self.checkASICState(asic_keys[0], ASIC_COUNTER_SWITCH_IN_TYPE, [reason1]) - - self.remove_drop_reason(name, reason2) - time.sleep(3) - - # Verify that the ASIC state is unchanged after the nonexistent remove. - asic_keys = asic_state_table.getKeys() - assert len(asic_keys) == 1 - assert self.checkASICState(asic_keys[0], ASIC_COUNTER_SWITCH_IN_TYPE, [reason1]) - - # Cleanup for the next test. - self.delete_drop_counter(name) - self.remove_drop_reason(name, reason1) - - def test_removeInvalidDropReason(self, dvs, testlog): - """ - This test verifies that removing a drop reason that is not recognized - will not affect the system. - """ - self.setup_db(dvs) - - asic_state_table = swsscommon.Table(self.asic_db, ASIC_STATE_TABLE) - flex_counter_table = swsscommon.Table(self.flex_db, FLEX_COUNTER_TABLE) - - name = 'ADD_TEST' - reason1 = 'L3_ANY' - bogus_reason = 'LIVE_LAUGH_LOVE' - - self.create_drop_counter(name, SWITCH_INGRESS_DROPS) - self.add_drop_reason(name, reason1) - time.sleep(3) - - # Verify the counter has been created and is in the correct state. - asic_keys = asic_state_table.getKeys() - assert len(asic_keys) == 1 - assert self.checkASICState(asic_keys[0], ASIC_COUNTER_SWITCH_IN_TYPE, [reason1]) - - self.remove_drop_reason(name, bogus_reason) - time.sleep(3) - - # Verify that the ASIC state is unchanged after the bad remove. - asic_keys = asic_state_table.getKeys() - assert len(asic_keys) == 1 - assert self.checkASICState(asic_keys[0], ASIC_COUNTER_SWITCH_IN_TYPE, [reason1]) - - # Cleanup for the next test. - self.delete_drop_counter(name) - self.remove_drop_reason(name, reason1) - - def getPortOid(self, dvs, port_name): - port_name_map = swsscommon.Table(self.counters_db, "COUNTERS_PORT_NAME_MAP") - status, returned_value = port_name_map.hget("", port_name); - assert status == True - return returned_value - - def test_add_remove_port(self, dvs, testlog): - """ - This test verifies that debug counters are removed when we remove a port - and debug counters are added each time we add ports (if debug counter is enabled) - """ - self.setup_db(dvs) - - # save port info - cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) - tbl = swsscommon.Table(cdb, PORT_TABLE_NAME) - (status, fvs) = tbl.get(PORT) - assert status == True - - # get counter oid - oid = self.getPortOid(dvs, PORT) - - # verifies debug coutner dont exist for port - flex_counter_table = swsscommon.Table(self.flex_db, FLEX_COUNTER_TABLE) - status, fields = flex_counter_table.get(oid) - assert len(fields) == 0 - - # add debug counters - name1 = 'DEBUG_0' - reason1 = 'L3_ANY' - name2 = 'DEBUG_1' - reason2 = 'L2_ANY' - - self.create_drop_counter(name1, PORT_INGRESS_DROPS) - self.add_drop_reason(name1, reason1) - - self.create_drop_counter(name2, PORT_EGRESS_DROPS) - self.add_drop_reason(name2, reason2) - time.sleep(3) - - # verifies debug counter exist for port - flex_counter_table = swsscommon.Table(self.flex_db, FLEX_COUNTER_TABLE) - status, fields = flex_counter_table.get(oid) - assert status == True - assert len(fields) == 1 - - # remove port and wait until it was removed from ASIC DB - self.dvs_port.remove_port(PORT) - dvs.get_asic_db().wait_for_deleted_entry("ASIC_STATE:SAI_OBJECT_TYPE_PORT", oid) - - # verify that debug counter were removed - status, fields = flex_counter_table.get(oid) - assert len(fields) == 0 - - # add port and wait until the port is added on asic db - num_of_keys_without_port = len(dvs.get_asic_db().get_keys("ASIC_STATE:SAI_OBJECT_TYPE_PORT")) - tbl.set(PORT, fvs) - dvs.get_asic_db().wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_PORT", num_of_keys_without_port + 1) - dvs.get_counters_db().wait_for_fields("COUNTERS_PORT_NAME_MAP", "", [PORT]) - - # verifies that debug counters were added for port - oid = self.getPortOid(dvs, PORT) - status, fields = flex_counter_table.get(oid) - assert status == True - assert len(fields) == 1 - - # Cleanup for the next test. - self.delete_drop_counter(name1) - self.remove_drop_reason(name1, reason1) - - self.delete_drop_counter(name2) - self.remove_drop_reason(name2, reason2) - - def test_createAndDeleteMultipleCounters(self, dvs, testlog): - """ - This test verifies that creating and deleting multiple drop counters - at the same time works correctly. - """ - self.setup_db(dvs) - - asic_state_table = swsscommon.Table(self.asic_db, ASIC_STATE_TABLE) - flex_counter_table = swsscommon.Table(self.flex_db, FLEX_COUNTER_TABLE) - - name1 = 'DEBUG_0' - reason1 = 'L3_ANY' - - name2 = 'DEBUG_1' - reason2 = 'ACL_ANY' - - self.create_drop_counter(name1, PORT_INGRESS_DROPS) - self.add_drop_reason(name1, reason1) - - self.create_drop_counter(name2, PORT_INGRESS_DROPS) - self.add_drop_reason(name2, reason2) - - time.sleep(5) - - # Verify that the flex counters are correctly tracking two different - # drop counters. - self.checkFlexState([PORT_STAT_BASE, PORT_STAT_INDEX_1], PORT_DEBUG_COUNTER_LIST) - - # Verify that there are two entries in the ASIC DB, one for each counter. - asic_keys = asic_state_table.getKeys() - assert len(asic_keys) == 2 - for key in asic_keys: - assert (self.checkASICState(key, ASIC_COUNTER_PORT_IN_TYPE, [reason1]) or self.checkASICState(key, ASIC_COUNTER_PORT_IN_TYPE, [reason2])) - - self.delete_drop_counter(name2) - self.remove_drop_reason(name2, reason2) - time.sleep(3) - - # Verify that the flex counters are tracking ONE drop counter after - # the update. - self.checkFlexState([PORT_STAT_BASE], PORT_DEBUG_COUNTER_LIST) - - # Verify that there is ONE entry in the ASIC DB after the update. - asic_keys = asic_state_table.getKeys() - assert len(asic_keys) == 1 - assert self.checkASICState(asic_keys[0], ASIC_COUNTER_PORT_IN_TYPE, [reason1]) - - # Cleanup for the next test. - self.delete_drop_counter(name1) - self.remove_drop_reason(name1, reason1) - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_dtel.py b/tests/test_dtel.py deleted file mode 100644 index c8e86d6b7d..0000000000 --- a/tests/test_dtel.py +++ /dev/null @@ -1,407 +0,0 @@ -import time -import re -import json -import pytest - -from swsscommon import swsscommon - - -class TestDtel(object): - def test_DtelGlobalAttribs(self, dvs, testlog): - - db = swsscommon.DBConnector(4, dvs.redis_sock, 0) - adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - - # create DTel global attributes in config db - tbl = swsscommon.Table(db, "DTEL") - - fvs = swsscommon.FieldValuePairs([("SWITCH_ID", "1")]) - tbl.set("SWITCH_ID", fvs) - - fvs = swsscommon.FieldValuePairs([("FLOW_STATE_CLEAR_CYCLE", "10")]) - tbl.set("FLOW_STATE_CLEAR_CYCLE", fvs) - - fvs = swsscommon.FieldValuePairs([("LATENCY_SENSITIVITY", "100")]) - tbl.set("LATENCY_SENSITIVITY", fvs) - - fvs = swsscommon.FieldValuePairs([("INT_ENDPOINT", "TRUE")]) - tbl.set("INT_ENDPOINT", fvs) - - fvs = swsscommon.FieldValuePairs([("INT_TRANSIT", "TRUE")]) - tbl.set("INT_TRANSIT", fvs) - - fvs = swsscommon.FieldValuePairs([("POSTCARD", "TRUE")]) - tbl.set("POSTCARD", fvs) - - fvs = swsscommon.FieldValuePairs([("DROP_REPORT", "TRUE")]) - tbl.set("DROP_REPORT", fvs) - - fvs = swsscommon.FieldValuePairs([("QUEUE_REPORT", "TRUE")]) - tbl.set("QUEUE_REPORT", fvs) - - fvs = swsscommon.FieldValuePairs([("Ethernet0", "Ethernet0"), ("Ethernet4", "Ethernet4")]) - tbl.set("SINK_PORT_LIST", fvs) - - fvs = swsscommon.FieldValuePairs([("INT_L4_DSCP_VALUE", "128"), ("INT_L4_DSCP_MASK", "255")]) - tbl.set("INT_L4_DSCP", fvs) - - time.sleep(1) - - atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_DTEL") - keys = atbl.getKeys() - assert len(keys) > 0 - - for k in keys: - (status, fvs) = atbl.get(k) - assert status == True - - for fv in fvs: - if fv[0] == "SAI_DTEL_ATTR_SWITCH_ID": - assert fv[1] == "1" - elif fv[0] == "SAI_DTEL_ATTR_FLOW_STATE_CLEAR_CYCLE": - assert fv[1] == "10" - elif fv[0] == "SAI_DTEL_ATTR_LATENCY_SENSITIVITY": - assert fv[1] == "100" - elif fv[0] == "SAI_DTEL_ATTR_INT_ENDPOINT_ENABLE": - assert fv[1] == "true" - elif fv[0] == "SAI_DTEL_ATTR_INT_TRANSIT_ENABLE": - assert fv[1] == "true" - elif fv[0] == "SAI_DTEL_ATTR_POSTCARD_ENABLE": - assert fv[1] == "true" - elif fv[0] == "SAI_DTEL_ATTR_DROP_REPORT_ENABLE": - assert fv[1] == "true" - elif fv[0] == "SAI_DTEL_ATTR_QUEUE_REPORT_ENABLE": - assert fv[1] == "true" - elif fv[0] == "SAI_DTEL_ATTR_INT_L4_DSCP": - assert fv[1] == "128&mask:0xff" - elif fv[0] == "SAI_DTEL_ATTR_SINK_PORT_LIST": - assert True - - tbl._del("SWITCH_ID") - tbl._del("FLOW_STATE_CLEAR_CYCLE") - tbl._del("LATENCY_SENSITIVITY") - tbl._del("INT_ENDPOINT") - tbl._del("INT_TRANSIT") - tbl._del("POSTCARD") - tbl._del("DROP_REPORT") - tbl._del("QUEUE_REPORT") - tbl._del("SINK_PORT_LIST") - - def test_DtelReportSessionAttribs(self, dvs, testlog): - - db = swsscommon.DBConnector(4, dvs.redis_sock, 0) - adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - - # create DTel report session attributes in config db - tbl = swsscommon.Table(db, "DTEL_REPORT_SESSION") - - fvs = swsscommon.FieldValuePairs([("SRC_IP", "10.10.10.1"), - ("DST_IP_LIST", "20.20.20.1;20.20.20.2;20.20.20.3"), - ("VRF", "default"), - ("TRUNCATE_SIZE", "256"), - ("UDP_DEST_PORT", "2000")]) - tbl.set("RS-1", fvs) - - time.sleep(1) - - atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_DTEL_REPORT_SESSION") - keys = atbl.getKeys() - assert len(keys) > 0 - - for k in keys: - (status, fvs) = atbl.get(k) - assert status == True - - for fv in fvs: - if fv[0] == "SAI_DTEL_REPORT_SESSION_ATTR_SRC_IP": - assert fv[1] == "10.10.10.1" - elif fv[0] == "SAI_DTEL_REPORT_SESSION_ATTR_DST_IP_LIST": - assert fv[1] == "3:20.20.20.1,20.20.20.2,20.20.20.3" - elif fv[0] == "SAI_DTEL_REPORT_SESSION_ATTR_VIRTUAL_ROUTER_ID": - assert True - elif fv[0] == "SAI_DTEL_REPORT_SESSION_ATTR_TRUNCATE_SIZE": - assert fv[1] == "256" - elif fv[0] == "SAI_DTEL_REPORT_SESSION_ATTR_UDP_DST_PORT": - assert fv[1] == "2000" - else: - assert False - - tbl._del("RS-1") - - def test_DtelINTSessionAttribs(self, dvs, testlog): - - db = swsscommon.DBConnector(4, dvs.redis_sock, 0) - adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - - # create DTel INT session attributes in config db - tbl = swsscommon.Table(db, "DTEL_INT_SESSION") - - fvs = swsscommon.FieldValuePairs([("MAX_HOP_COUNT", "50"), - ("COLLECT_SWITCH_ID", "TRUE"), - ("COLLECT_INGRESS_TIMESTAMP", "TRUE"), - ("COLLECT_EGRESS_TIMESTAMP", "TRUE"), - ("COLLECT_SWITCH_PORTS", "TRUE"), - ("COLLECT_QUEUE_INFO", "TRUE")]) - tbl.set("INT-1", fvs) - - time.sleep(1) - - atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_DTEL_INT_SESSION") - keys = atbl.getKeys() - assert len(keys) > 0 - - for k in keys: - (status, fvs) = atbl.get(k) - assert status == True - - for fv in fvs: - if fv[0] == "SAI_DTEL_INT_SESSION_ATTR_MAX_HOP_COUNT": - assert fv[1] == "50" - elif fv[0] == "SAI_DTEL_INT_SESSION_ATTR_COLLECT_SWITCH_ID": - assert fv[1] == "true" - elif fv[0] == "SAI_DTEL_INT_SESSION_ATTR_COLLECT_INGRESS_TIMESTAMP": - assert fv[1] == "true" - elif fv[0] == "SAI_DTEL_INT_SESSION_ATTR_COLLECT_EGRESS_TIMESTAMP": - assert fv[1] == "true" - elif fv[0] == "SAI_DTEL_INT_SESSION_ATTR_COLLECT_SWITCH_PORTS": - assert fv[1] == "true" - elif fv[0] == "SAI_DTEL_INT_SESSION_ATTR_COLLECT_QUEUE_INFO": - assert fv[1] == "true" - else: - assert False - - tbl._del("INT-1") - - def test_DtelQueueReportAttribs(self, dvs, testlog): - - db = swsscommon.DBConnector(4, dvs.redis_sock, 0) - adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - - # create DTel queue report attributes in config db - tbl = swsscommon.Table(db, "DTEL_QUEUE_REPORT") - - fvs = swsscommon.FieldValuePairs([("QUEUE_DEPTH_THRESHOLD", "1000"), - ("QUEUE_LATENCY_THRESHOLD", "2000"), - ("THRESHOLD_BREACH_QUOTA", "3000"), - ("REPORT_TAIL_DROP", "TRUE")]) - tbl.set("Ethernet0|0", fvs) - - time.sleep(1) - - atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_DTEL_QUEUE_REPORT") - keys = atbl.getKeys() - assert len(keys) > 0 - - for k in keys: - (status, fvs) = atbl.get(k) - assert status == True - - for fv in fvs: - if fv[0] == "SAI_DTEL_QUEUE_REPORT_ATTR_DEPTH_THRESHOLD": - assert fv[1] == "1000" - elif fv[0] == "SAI_DTEL_QUEUE_REPORT_ATTR_LATENCY_THRESHOLD": - assert fv[1] == "2000" - elif fv[0] == "SAI_DTEL_QUEUE_REPORT_ATTR_BREACH_QUOTA": - assert fv[1] == "3000" - elif fv[0] == "SAI_DTEL_QUEUE_REPORT_ATTR_TAIL_DROP": - assert fv[1] == "true" - elif fv[0] == "SAI_DTEL_QUEUE_REPORT_ATTR_QUEUE_ID": - assert True - else: - assert False - - tbl._del("Ethernet0|0") - - def test_DtelFlowWatchlist(self, dvs, testlog): - self.db = swsscommon.DBConnector(4, dvs.redis_sock, 0) - self.adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - self.table = "DTEL_FLOW_WATCHLIST" - - fields_1=[("PRIORITY", "30"), - ("ETHER_TYPE", "0x800"), - ("L4_DST_PORT", "1674"), - ("FLOW_OP", "POSTCARD"), - ("REPORT_ALL_PACKETS", "FALSE"), - ("DROP_REPORT_ENABLE", "TRUE"), - ("TAIL_DROP_REPORT_ENABLE", "TRUE")] - fields_2=[("PRIORITY", "40"), - ("ETHER_TYPE", "0x800"), - ("L4_DST_PORT", "1674"), - ("FLOW_OP", "POSTCARD"), - ("REPORT_ALL_PACKETS", "TRUE"), - ("DROP_REPORT_ENABLE", "FALSE"), - ("TAIL_DROP_REPORT_ENABLE", "FALSE")] - fields_3=[("PRIORITY", "50"), - ("ETHER_TYPE", "0x800"), - ("L4_DST_PORT", "1674"), - ("FLOW_OP", "POSTCARD"), - ("REPORT_ALL_PACKETS", "TRUE")] - fields_4=[("PRIORITY", "60"), - ("ETHER_TYPE", "0x800"), - ("L4_DST_PORT", "1674"), - ("REPORT_ALL_PACKETS", "TRUE"), - ("DROP_REPORT_ENABLE", "TRUE"), - ("TAIL_DROP_REPORT_ENABLE", "TRUE")] - fields_5=[("PRIORITY", "70"), - ("ETHER_TYPE", "0x800"), - ("L4_DST_PORT", "1674"), - ("FLOW_OP", "NOP"), - ("REPORT_ALL_PACKETS", "FALSE"), - ("DROP_REPORT_ENABLE", "TRUE"), - ("TAIL_DROP_REPORT_ENABLE", "TRUE")] - listfield = [fields_1, fields_2, fields_3, fields_4, fields_5] - - for field in listfield: - k = listfield.index(field) - rule = "RULE-" + str(k) - self._create_dtel_acl_rule(self.table, rule, field) - self._check_dtel_acl_rule(dvs, rule) - self._remove_dtel_acl_rule(self.table, rule) - - def _create_dtel_acl_rule(self, table, rule, field): - tbl = swsscommon.Table(self.db, "ACL_RULE") - fvs = swsscommon.FieldValuePairs(field) - tbl.set(table + "|" + rule, fvs) - time.sleep(1) - - def _remove_dtel_acl_rule(self, table, rule): - tbl = swsscommon.Table(self.db, "ACL_RULE") - tbl._del(table + "|" + rule) - time.sleep(1) - - def _check_dtel_acl_rule(self, dvs, rule): - time.sleep(1) - atbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") - keys = atbl.getKeys() - acl_entry = [k for k in keys if k not in dvs.asicdb.default_acl_entries] - assert len(acl_entry) != 0 - (status, fvs) = atbl.get(acl_entry[0]) - value = dict(fvs) - assert status - - if rule == "RULE-0": - assert value["SAI_ACL_ENTRY_ATTR_PRIORITY"] == "30" - assert value["SAI_ACL_ENTRY_ATTR_FIELD_ETHER_TYPE"] == "2048&mask:0xffff" - assert value["SAI_ACL_ENTRY_ATTR_FIELD_L4_DST_PORT"] == "1674&mask:0xffff" - assert value["SAI_ACL_ENTRY_ATTR_ACTION_ACL_DTEL_FLOW_OP"] == "SAI_ACL_DTEL_FLOW_OP_POSTCARD" - assert value["SAI_ACL_ENTRY_ATTR_ACTION_DTEL_REPORT_ALL_PACKETS"] == "disabled" - assert value["SAI_ACL_ENTRY_ATTR_ACTION_DTEL_DROP_REPORT_ENABLE"] == "true" - assert value["SAI_ACL_ENTRY_ATTR_ACTION_DTEL_TAIL_DROP_REPORT_ENABLE"] == "true" - elif rule == "RULE-1": - assert value["SAI_ACL_ENTRY_ATTR_PRIORITY"] == "40" - assert value["SAI_ACL_ENTRY_ATTR_FIELD_ETHER_TYPE"] == "2048&mask:0xffff" - assert value["SAI_ACL_ENTRY_ATTR_FIELD_L4_DST_PORT"] == "1674&mask:0xffff" - assert value["SAI_ACL_ENTRY_ATTR_ACTION_ACL_DTEL_FLOW_OP"] == "SAI_ACL_DTEL_FLOW_OP_POSTCARD" - assert value["SAI_ACL_ENTRY_ATTR_ACTION_DTEL_REPORT_ALL_PACKETS"] == "true" - assert value["SAI_ACL_ENTRY_ATTR_ACTION_DTEL_DROP_REPORT_ENABLE"] == "disabled" - assert value["SAI_ACL_ENTRY_ATTR_ACTION_DTEL_TAIL_DROP_REPORT_ENABLE"] == "disabled" - elif rule == "RULE-2": - assert value["SAI_ACL_ENTRY_ATTR_PRIORITY"] == "50" - assert value["SAI_ACL_ENTRY_ATTR_FIELD_ETHER_TYPE"] == "2048&mask:0xffff" - assert value["SAI_ACL_ENTRY_ATTR_FIELD_L4_DST_PORT"] == "1674&mask:0xffff" - assert value["SAI_ACL_ENTRY_ATTR_ACTION_ACL_DTEL_FLOW_OP"] == "SAI_ACL_DTEL_FLOW_OP_POSTCARD" - assert value["SAI_ACL_ENTRY_ATTR_ACTION_DTEL_REPORT_ALL_PACKETS"] == "true" - elif rule == "RULE-3": - assert value["SAI_ACL_ENTRY_ATTR_PRIORITY"] == "60" - assert value["SAI_ACL_ENTRY_ATTR_FIELD_ETHER_TYPE"] == "2048&mask:0xffff" - assert value["SAI_ACL_ENTRY_ATTR_FIELD_L4_DST_PORT"] == "1674&mask:0xffff" - assert value["SAI_ACL_ENTRY_ATTR_ACTION_DTEL_REPORT_ALL_PACKETS"] == "true" - assert value["SAI_ACL_ENTRY_ATTR_ACTION_DTEL_DROP_REPORT_ENABLE"] == "true" - assert value["SAI_ACL_ENTRY_ATTR_ACTION_DTEL_TAIL_DROP_REPORT_ENABLE"] == "true" - elif rule == "RULE-4": - assert value["SAI_ACL_ENTRY_ATTR_PRIORITY"] == "70" - assert value["SAI_ACL_ENTRY_ATTR_FIELD_ETHER_TYPE"] == "2048&mask:0xffff" - assert value["SAI_ACL_ENTRY_ATTR_FIELD_L4_DST_PORT"] == "1674&mask:0xffff" - assert value["SAI_ACL_ENTRY_ATTR_ACTION_ACL_DTEL_FLOW_OP"] == "SAI_ACL_DTEL_FLOW_OP_NOP" - assert value["SAI_ACL_ENTRY_ATTR_ACTION_DTEL_REPORT_ALL_PACKETS"] == "disabled" - assert value["SAI_ACL_ENTRY_ATTR_ACTION_DTEL_DROP_REPORT_ENABLE"] == "true" - assert value["SAI_ACL_ENTRY_ATTR_ACTION_DTEL_TAIL_DROP_REPORT_ENABLE"] == "true" - - def test_DtelEventAttribs(self, dvs, testlog): - - db = swsscommon.DBConnector(4, dvs.redis_sock, 0) - adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - - # first create DTel report session in config db - rtbl = swsscommon.Table(db, "DTEL_REPORT_SESSION") - - fvs = swsscommon.FieldValuePairs([("SRC_IP", "10.10.10.1"), - ("DST_IP_LIST", "20.20.20.1;20.20.20.2;20.20.20.3"), - ("VRF", "default"), - ("TRUNCATE_SIZE", "256"), - ("UDP_DEST_PORT", "2000")]) - rtbl.set("RS-1", fvs) - - # create DTel event attributes in config db - tbl = swsscommon.Table(db, "DTEL_EVENT") - - fvs = swsscommon.FieldValuePairs([("EVENT_REPORT_SESSION", "RS-1"), - ("EVENT_DSCP_VALUE", "65")]) - tbl.set("EVENT_TYPE_FLOW_STATE", fvs) - - fvs = swsscommon.FieldValuePairs([("EVENT_REPORT_SESSION", "RS-1"), - ("EVENT_DSCP_VALUE", "64")]) - tbl.set("EVENT_TYPE_FLOW_REPORT_ALL_PACKETS", fvs) - - fvs = swsscommon.FieldValuePairs([("EVENT_REPORT_SESSION", "RS-1"), - ("EVENT_DSCP_VALUE", "63")]) - tbl.set("EVENT_TYPE_FLOW_TCPFLAG", fvs) - - fvs = swsscommon.FieldValuePairs([("EVENT_REPORT_SESSION", "RS-1"), - ("EVENT_DSCP_VALUE", "62")]) - tbl.set("EVENT_TYPE_QUEUE_REPORT_THRESHOLD_BREACH", fvs) - - fvs = swsscommon.FieldValuePairs([("EVENT_REPORT_SESSION", "RS-1"), - ("EVENT_DSCP_VALUE", "61")]) - tbl.set("EVENT_TYPE_QUEUE_REPORT_TAIL_DROP", fvs) - - fvs = swsscommon.FieldValuePairs([("EVENT_REPORT_SESSION", "RS-1"), - ("EVENT_DSCP_VALUE", "60")]) - tbl.set("EVENT_TYPE_DROP_REPORT", fvs) - - time.sleep(1) - - atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_DTEL_EVENT") - keys = atbl.getKeys() - assert len(keys) > 0 - - for k in keys: - (status, fvs) = atbl.get(k) - assert status == True - - expected_dscp = None - actual_dscp = None - for fv in fvs: - if fv[0] == "SAI_DTEL_EVENT_ATTR_TYPE": - if fv[1] == "SAI_DTEL_EVENT_TYPE_QUEUE_REPORT_TAIL_DROP": - expected_dscp = "61" - elif fv[1] == "SAI_DTEL_EVENT_TYPE_DROP_REPORT": - expected_dscp = "60" - elif fv[1] == "SAI_DTEL_EVENT_TYPE_QUEUE_REPORT_THRESHOLD_BREACH": - expected_dscp = "62" - elif fv[1] == "SAI_DTEL_EVENT_TYPE_FLOW_TCPFLAG": - expected_dscp = "63" - elif fv[1] == "SAI_DTEL_EVENT_TYPE_FLOW_REPORT_ALL_PACKETS": - expected_dscp = "64" - elif fv[1] == "SAI_DTEL_EVENT_TYPE_FLOW_STATE": - expected_dscp = "65" - elif fv[0] == "SAI_DTEL_EVENT_ATTR_REPORT_SESSION": - assert True - elif fv[0] == "SAI_DTEL_EVENT_ATTR_DSCP_VALUE": - actual_dscp = fv[1] - - assert actual_dscp == expected_dscp - - rtbl._del("RS-1") - tbl._del("EVENT_TYPE_FLOW_STATE") - tbl._del("EVENT_TYPE_FLOW_REPORT_ALL_PACKETS") - tbl._del("EVENT_TYPE_FLOW_TCPFLAG") - tbl._del("EVENT_TYPE_QUEUE_REPORT_THRESHOLD_BREACH") - tbl._del("EVENT_TYPE_QUEUE_REPORT_TAIL_DROP") - tbl._del("EVENT_TYPE_DROP_REPORT") - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_evpn_fdb.py b/tests/test_evpn_fdb.py deleted file mode 100644 index 3c9a217747..0000000000 --- a/tests/test_evpn_fdb.py +++ /dev/null @@ -1,387 +0,0 @@ -from swsscommon import swsscommon -import time -from evpn_tunnel import VxlanTunnel,VxlanEvpnHelper - -def get_vxlan_p2p_tunnel_bp(db, remote_ip): - tnl_id = None - bp = None - print("remote_ip = " + remote_ip) - attributes = [("SAI_TUNNEL_ATTR_TYPE", "SAI_TUNNEL_TYPE_VXLAN"), - ("SAI_TUNNEL_ATTR_ENCAP_DST_IP", remote_ip) - ] - tbl = swsscommon.Table(db, "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL") - keys = tbl.getKeys() - for key in keys: - status, fvs = tbl.get(key) - assert status, "Error reading from table ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL" - attrs = dict(attributes) - num_match = 0 - for k, v in fvs: - print("attr:value="+str(k)+":"+str(v)) - if k in attrs and attrs[k] == v: - num_match += 1 - if num_match == len(attributes): - tnl_id = str(key) - break - else: - tnl_id = None - - print("tnl_id = "+str(tnl_id)) - if tnl_id != None: - tbl = swsscommon.Table(db, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") - keys = tbl.getKeys() - for key in keys: - status, fvs = tbl.get(key) - assert status, "Error reading from table ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT" - for k, v in fvs: - print("attr:value="+str(k)+":"+str(v)) - if k == "SAI_BRIDGE_PORT_ATTR_TUNNEL_ID" and tnl_id == v: - bp = key - break - if bp != None: - break - else: - pass - print("bp = "+str(bp)) - return bp - - -def test_evpnFdb(dvs, testlog): - vxlan_obj = VxlanTunnel() - helper = VxlanEvpnHelper() - dvs.setup_db() - - dvs.clear_fdb() - time.sleep(2) - - #Find switch_id - switch_id = dvs.getSwitchOid() - print("Switch_id="+str(switch_id)) - - vlan_before = helper.how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - - # create vlan - print("Creating Vlan3") - dvs.create_vlan("3") - time.sleep(2) - - vlan_after = helper.how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - assert vlan_after - vlan_before == 1, "The Vlan3 wasn't created" - print("Vlan3 is created") - - # Find the vlan_oid to be used in DB communications - vlan_oid_3 = dvs.getVlanOid("3") - assert vlan_oid_3 is not None, "Could not find Vlan_oid" - print("Vlan-3 vlan_oid="+str(vlan_oid_3)) - - bp_before = helper.how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") - vm_before = helper.how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") - - print("Making Ethernet0 as a member of Vlan3") - dvs.create_vlan_member("3", "Ethernet0") - time.sleep(2) - - # check that the vlan information was propagated - bp_after = helper.how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") - vm_after = helper.how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") - - assert bp_after - bp_before == 1, "The bridge port wasn't created" - assert vm_after - vm_before == 1, "The vlan member wasn't added" - print("Ethernet0 is a member of Vlan3") - - # Get mapping between interface name and its bridge port_id - iface_2_bridge_port_id = dvs.get_map_iface_bridge_port_id(dvs.adb) - - #create SIP side of tunnel - source_tnl_name = "source_vtep_name" - source_tnl_ip = "7.7.7.7" - vxlan_obj.create_vxlan_tunnel(dvs, source_tnl_name, source_tnl_ip) - time.sleep(1) - - - nvo_name = "evpn_nvo" - vxlan_obj.create_evpn_nvo(dvs, nvo_name, source_tnl_name) - time.sleep(1) - - - map_name_vlan_3 = "map_3_3" - vxlan_obj.create_vxlan_tunnel_map(dvs, source_tnl_name, map_name_vlan_3, "3", "Vlan3") - time.sleep(1) - - - remote_ip_6 = "6.6.6.6" - vxlan_obj.create_evpn_remote_vni(dvs, "Vlan3", remote_ip_6, "3") - remote_ip_8 = "8.8.8.8" - vxlan_obj.create_evpn_remote_vni(dvs, "Vlan3", remote_ip_8, "3") - time.sleep(1) - - #UT-1 Evpn Mac add from remote when tunnels are already created - mac = "52:54:00:25:06:E9" - print("Creating Evpn FDB Vlan3:"+mac.lower()+":6.6.6.6 in APP-DB") - helper.create_entry_pst( - dvs.pdb, - "VXLAN_FDB_TABLE", "Vlan3:"+mac.lower(), - [ - ("remote_vtep", remote_ip_6), - ("type", "dynamic"), - ("vni", "3") - ] - ) - time.sleep(1) - - tnl_bp_oid_6 = get_vxlan_p2p_tunnel_bp(dvs.adb, remote_ip_6) - - # check that the FDB entry is inserted into ASIC DB - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [("mac", mac), ("bvid", vlan_oid_3)], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_STATIC"), - ("SAI_FDB_ENTRY_ATTR_ALLOW_MAC_MOVE", "true"), - ("SAI_FDB_ENTRY_ATTR_ENDPOINT_IP", remote_ip_6), - ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", str(tnl_bp_oid_6)), - ] - ) - assert ok == True, str(extra) - print("EVPN FDB Vlan3:"+mac.lower()+":"+remote_ip_6+" is created in ASIC-DB") - - time.sleep(1) - - #UT-2 Evpn Mac del from remote - mac = "52:54:00:25:06:E9" - print("Deleting Evpn FDB Vlan3:"+mac.lower()+":6.6.6.6 in APP-DB") - helper.delete_entry_pst( - dvs.pdb, - "VXLAN_FDB_TABLE", "Vlan3:"+mac.lower() - ) - time.sleep(1) - - # check that the FDB entry is deleted from ASIC DB - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [("mac", mac), ("bvid", vlan_oid_3)], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_STATIC"), - ("SAI_FDB_ENTRY_ATTR_ALLOW_MAC_MOVE", "true"), - ("SAI_FDB_ENTRY_ATTR_ENDPOINT_IP", remote_ip_6), - ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", str(tnl_bp_oid_6)), - ] - ) - assert ok == False, str(extra) - print("EVPN FDB Vlan3:"+mac.lower()+":"+remote_ip_6+" is deleted from ASIC-DB") - - time.sleep(1) - - #UT-3 Evpn Mac add from remote when local mac is already present - mac = "52:54:00:25:06:E9" - - print("Creating Local dynamic FDB Vlan3:"+mac.lower()+":Ethernet0 in APP-DB") - # Create Dynamic MAC entry in APP DB - helper.create_entry_pst( - dvs.pdb, - "FDB_TABLE", "Vlan3:"+mac.lower(), - [ - ("port", "Ethernet0"), - ("type", "dynamic"), - ] - ) - - time.sleep(1) - #raw_input("Check ASIC_DB.........") - - # check that the FDB entry was added in ASIC DB - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [("mac", mac), ("bvid", vlan_oid_3)], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_DYNAMIC"), - ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", iface_2_bridge_port_id["Ethernet0"])] - ) - assert ok, str(extra) - print("Dynamic FDB Vlan3:"+mac.lower()+":Ethernet0 is created in Asic-DB") - - # check that the FDB entry was added in STATE DB - mac1_found, extra = dvs.is_table_entry_exists(dvs.sdb, "FDB_TABLE", - "Vlan3:"+mac.lower(), - [("port", "Ethernet0"), - ("type", "dynamic"), - ] - ) - assert mac1_found, str(extra) - print("FDB Vlan3:"+mac+":Ethernet0 is created in STATE-DB") - - print("Creating Evpn FDB Vlan3:"+mac.lower()+":6.6.6.6 in APP-DB") - helper.create_entry_pst( - dvs.pdb, - "VXLAN_FDB_TABLE", "Vlan3:"+mac.lower(), - [ - ("remote_vtep", remote_ip_6), - ("type", "dynamic"), - ("vni", "3") - ] - ) - time.sleep(1) - - - # check that the FDB entry is inserted into ASIC DB - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [("mac", mac), ("bvid", str(dvs.getVlanOid("3")))], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_STATIC"), - ("SAI_FDB_ENTRY_ATTR_ALLOW_MAC_MOVE", "true"), - ("SAI_FDB_ENTRY_ATTR_ENDPOINT_IP", remote_ip_6), - ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", str(tnl_bp_oid_6)), - ] - ) - assert ok, str(extra) - print("EVPN FDB Vlan3:"+mac.lower()+":"+remote_ip_6+" is created in ASIC-DB") - - # check that the Local FDB entry is deleted from STATE DB - mac1_found, extra = dvs.is_table_entry_exists(dvs.sdb, "FDB_TABLE", - "Vlan3:"+mac.lower(), - [("port", "Ethernet0"), - ("type", "dynamic"), - ] - ) - assert mac1_found == False, str(extra) - print("FDB Vlan3:"+mac+":Ethernet0 is deleted from STATE-DB") - - time.sleep(1) - - - #UT-4 Evpn Sticky Mac add from remote - mac = "52:54:00:25:06:E9" - print("Creating Evpn Sticky FDB Vlan3:"+mac.lower()+":6.6.6.6 in APP-DB") - helper.create_entry_pst( - dvs.pdb, - "VXLAN_FDB_TABLE", "Vlan3:"+mac.lower(), - [ - ("remote_vtep", remote_ip_6), - ("type", "static"), - ("vni", "3") - ] - ) - time.sleep(1) - - - # check that the FDB entry is inserted into ASIC DB - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [("mac", mac), ("bvid", str(dvs.getVlanOid("3")))], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_STATIC"), - ("SAI_FDB_ENTRY_ATTR_ENDPOINT_IP", remote_ip_6), - ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", str(tnl_bp_oid_6)), - ] - ) - assert ok, str(extra) - print("EVPN Sticky FDB Vlan3:"+mac.lower()+":"+remote_ip_6+" is created in ASIC-DB") - - #raw_input("Check ASIC_DB.........") - - #UT-8 Evpn Mac add from remote when tunnels are already created - mac = "52:54:00:25:06:E9" - print("Creating Evpn FDB Vlan3:"+mac.lower()+":6.6.6.6 in APP-DB") - helper.create_entry_pst( - dvs.pdb, - "VXLAN_FDB_TABLE", "Vlan3:"+mac.lower(), - [ - ("remote_vtep", remote_ip_6), - ("type", "dynamic"), - ("vni", "3") - ] - ) - time.sleep(1) - - #raw_input("Check ASIC_DB.........") - - # check that the FDB entry is inserted into ASIC DB - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [("mac", mac), ("bvid", vlan_oid_3)], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_STATIC"), - ("SAI_FDB_ENTRY_ATTR_ALLOW_MAC_MOVE", "true"), - ("SAI_FDB_ENTRY_ATTR_ENDPOINT_IP", remote_ip_6), - ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", str(tnl_bp_oid_6)), - ] - ) - assert ok == True, str(extra) - print("EVPN FDB Vlan3:"+mac.lower()+":"+remote_ip_6+" is created in ASIC-DB") - - time.sleep(1) - - tnl_bp_oid_8 = get_vxlan_p2p_tunnel_bp(dvs.adb, remote_ip_8) - - print("Creating Evpn FDB Vlan3:"+mac.lower()+":8.8.8.8 in APP-DB") - helper.create_entry_pst( - dvs.pdb, - "VXLAN_FDB_TABLE", "Vlan3:"+mac.lower(), - [ - ("remote_vtep", remote_ip_8), - ("type", "dynamic"), - ("vni", "3") - ] - ) - time.sleep(1) - - #raw_input("Check ASIC_DB.........") - - # check that the FDB entry is inserted into ASIC DB - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [("mac", mac), ("bvid", vlan_oid_3)], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_STATIC"), - ("SAI_FDB_ENTRY_ATTR_ALLOW_MAC_MOVE", "true"), - ("SAI_FDB_ENTRY_ATTR_ENDPOINT_IP", remote_ip_8), - ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", str(tnl_bp_oid_8)), - ] - ) - assert ok == True, str(extra) - print("EVPN FDB Vlan3:"+mac.lower()+":"+remote_ip_8+" is created in ASIC-DB") - - time.sleep(1) - - #UT-9 Local mac move (delete and learn) when remote is already added - mac = "52:54:00:25:06:E9" - print("Deleting FDB Vlan3:52-54-00-25-06-E9:8.8.8.8 in ASIC-DB") - helper.delete_entry_tbl(dvs.adb, "ASIC_STATE", "SAI_OBJECT_TYPE_FDB_ENTRY:{\"bvid\":\""+vlan_oid_3+"\",\"mac\":\""+mac+"\",\"switch_id\":\""+switch_id+"\"}") - - ntf = swsscommon.NotificationProducer(dvs.adb, "NOTIFICATIONS") - fvp = swsscommon.FieldValuePairs() - ntf_data = "[{\"fdb_entry\":\"{\\\"bvid\\\":\\\""+vlan_oid_3+"\\\",\\\"mac\\\":\\\""+mac+"\\\",\\\"switch_id\\\":\\\""+switch_id+"\\\"}\",\"fdb_event\":\"SAI_FDB_EVENT_AGED\",\"list\":[{\"id\":\"SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID\",\"value\":\""+str(tnl_bp_oid_8)+"\"}]}]" - ntf.send("fdb_event", ntf_data, fvp) - - time.sleep(2) - - #raw_input("Check ASIC_DB.........") - - print("Creating FDB Vlan3:52-54-00-25-06-E9:Ethernet0 in ASIC-DB") - helper.create_entry_tbl( - dvs.adb, - "ASIC_STATE", "SAI_OBJECT_TYPE_FDB_ENTRY:{\"bvid\":\""+vlan_oid_3+"\",\"mac\":\"52:54:00:25:06:E9\",\"switch_id\":\""+switch_id+"\"}", - [ - ("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_DYNAMIC"), - ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", iface_2_bridge_port_id["Ethernet0"]), - ] - ) - - ntf = swsscommon.NotificationProducer(dvs.adb, "NOTIFICATIONS") - fvp = swsscommon.FieldValuePairs() - ntf_data = "[{\"fdb_entry\":\"{\\\"bvid\\\":\\\""+vlan_oid_3+"\\\",\\\"mac\\\":\\\"52:54:00:25:06:E9\\\",\\\"switch_id\\\":\\\""+switch_id+"\\\"}\",\"fdb_event\":\"SAI_FDB_EVENT_LEARNED\",\"list\":[{\"id\":\"SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID\",\"value\":\""+iface_2_bridge_port_id["Ethernet0"]+"\"}]}]" - ntf.send("fdb_event", ntf_data, fvp) - - time.sleep(2) - - #raw_input("Check ASIC_DB.........") - - # check that the FDB entry was added in ASIC DB - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [("mac", "52:54:00:25:06:E9"), ("bvid", vlan_oid_3)], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_DYNAMIC"), - ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", iface_2_bridge_port_id["Ethernet0"])] - ) - assert ok, str(extra) - print("FDB Vlan3:52-54-00-25-06-E9:Ethernet0 is created in ASIC-DB") - - # check that the FDB entry was added in STATE DB - mac1_found, extra = dvs.is_table_entry_exists(dvs.sdb, "FDB_TABLE", - "Vlan3:52:54:00:25:06:e9", - [("port", "Ethernet0"), - ("type", "dynamic"), - ] - ) - assert mac1_found, str(extra) - print("FDB Vlan3:52-54-00-25-06-E9:Ethernet0 is created in STATE-DB") - - - dvs.remove_vlan_member("3", "Ethernet0") - dvs.remove_vlan("3") diff --git a/tests/test_evpn_fdb_p2mp.py b/tests/test_evpn_fdb_p2mp.py deleted file mode 100644 index 5aa407966c..0000000000 --- a/tests/test_evpn_fdb_p2mp.py +++ /dev/null @@ -1,410 +0,0 @@ -from swsscommon import swsscommon -import time -from evpn_tunnel import VxlanTunnel,VxlanEvpnHelper - -DVS_ENV = ["HWSKU=Mellanox-SN2700"] - -def get_vxlan_p2mp_tunnel_bp(db, src_ip): - tnl_id = None - bp = None - print("src_ip = " + src_ip) - attributes = [("SAI_TUNNEL_ATTR_TYPE", "SAI_TUNNEL_TYPE_VXLAN"), - ("SAI_TUNNEL_ATTR_PEER_MODE", "SAI_TUNNEL_PEER_MODE_P2MP"), - ("SAI_TUNNEL_ATTR_ENCAP_SRC_IP", src_ip) - ] - tbl = swsscommon.Table(db, "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL") - keys = tbl.getKeys() - for key in keys: - status, fvs = tbl.get(key) - assert status, "Error reading from table ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL" - attrs = dict(attributes) - num_match = 0 - for k, v in fvs: - print("attr:value="+str(k)+":"+str(v)) - if k in attrs and attrs[k] == v: - num_match += 1 - if num_match == len(attributes): - tnl_id = str(key) - break - else: - tnl_id = None - - print("tnl_id = "+str(tnl_id)) - if tnl_id != None: - tbl = swsscommon.Table(db, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") - keys = tbl.getKeys() - for key in keys: - status, fvs = tbl.get(key) - assert status, "Error reading from table ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT" - for k, v in fvs: - print("attr:value="+str(k)+":"+str(v)) - if k == "SAI_BRIDGE_PORT_ATTR_TUNNEL_ID" and tnl_id == v: - bp = key - break - if bp != None: - break - else: - pass - print("bp = "+str(bp)) - return bp - - -def test_evpnFdbP2MP(dvs, testlog): - vxlan_obj = VxlanTunnel() - helper = VxlanEvpnHelper() - dvs.setup_db() - - dvs.clear_fdb() - time.sleep(2) - - #Find switch_id - switch_id = dvs.getSwitchOid() - print("Switch_id="+str(switch_id)) - - vlan_before = helper.how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - - # create vlan - print("Creating Vlan3") - dvs.create_vlan("3") - time.sleep(2) - - vlan_after = helper.how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - assert vlan_after - vlan_before == 1, "The Vlan3 wasn't created" - print("Vlan3 is created") - - # Find the vlan_oid to be used in DB communications - vlan_oid_3 = dvs.getVlanOid("3") - assert vlan_oid_3 is not None, "Could not find Vlan_oid" - print("Vlan-3 vlan_oid="+str(vlan_oid_3)) - - bp_before = helper.how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") - vm_before = helper.how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") - - print("Making Ethernet0 as a member of Vlan3") - dvs.create_vlan_member("3", "Ethernet0") - time.sleep(2) - - # check that the vlan information was propagated - bp_after = helper.how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") - vm_after = helper.how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") - - assert bp_after - bp_before == 1, "The bridge port wasn't created" - assert vm_after - vm_before == 1, "The vlan member wasn't added" - print("Ethernet0 is a member of Vlan3") - - # Get mapping between interface name and its bridge port_id - iface_2_bridge_port_id = dvs.get_map_iface_bridge_port_id(dvs.adb) - - #create SIP side of tunnel - source_tnl_name = "source_vtep_name" - source_tnl_ip = "7.7.7.7" - vxlan_obj.create_vxlan_tunnel(dvs, source_tnl_name, source_tnl_ip) - time.sleep(1) - - nvo_name = "evpn_nvo" - vxlan_obj.create_evpn_nvo(dvs, nvo_name, source_tnl_name) - time.sleep(1) - - map_name_vlan_3 = "map_3_3" - vxlan_obj.create_vxlan_tunnel_map(dvs, source_tnl_name, map_name_vlan_3, "3", "Vlan3") - time.sleep(1) - - remote_ip_6 = "6.6.6.6" - vxlan_obj.create_evpn_remote_vni(dvs, "Vlan3", remote_ip_6, "3") - remote_ip_8 = "8.8.8.8" - vxlan_obj.create_evpn_remote_vni(dvs, "Vlan3", remote_ip_8, "3") - time.sleep(1) - - #UT-1 Evpn Mac add from remote when tunnels are already created - mac = "52:54:00:25:06:E9" - print("Creating Evpn FDB Vlan3:"+mac.lower()+":6.6.6.6 in APP-DB") - helper.create_entry_pst( - dvs.pdb, - "VXLAN_FDB_TABLE", "Vlan3:"+mac.lower(), - [ - ("remote_vtep", remote_ip_6), - ("type", "dynamic"), - ("vni", "3") - ] - ) - time.sleep(1) - - tnl_bp_oid_6 = get_vxlan_p2mp_tunnel_bp(dvs.adb, source_tnl_ip) - - # check that the FDB entry is inserted into ASIC DB - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [("mac", mac), ("bvid", vlan_oid_3)], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_STATIC"), - ("SAI_FDB_ENTRY_ATTR_ALLOW_MAC_MOVE", "true"), - ("SAI_FDB_ENTRY_ATTR_ENDPOINT_IP", remote_ip_6), - ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", str(tnl_bp_oid_6)), - ] - ) - assert ok == True, str(extra) - print("EVPN FDB Vlan3:"+mac.lower()+":"+remote_ip_6+" is created in ASIC-DB") - - time.sleep(1) - - #UT-2 Evpn Mac del from remote - mac = "52:54:00:25:06:E9" - print("Deleting Evpn FDB Vlan3:"+mac.lower()+":6.6.6.6 in APP-DB") - helper.delete_entry_pst( - dvs.pdb, - "VXLAN_FDB_TABLE", "Vlan3:"+mac.lower() - ) - time.sleep(1) - - # check that the FDB entry is deleted from ASIC DB - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [("mac", mac), ("bvid", vlan_oid_3)], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_STATIC"), - ("SAI_FDB_ENTRY_ATTR_ALLOW_MAC_MOVE", "true"), - ("SAI_FDB_ENTRY_ATTR_ENDPOINT_IP", remote_ip_6), - ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", str(tnl_bp_oid_6)), - ] - ) - assert ok == False, str(extra) - print("EVPN FDB Vlan3:"+mac.lower()+":"+remote_ip_6+" is deleted from ASIC-DB") - - time.sleep(1) - - #UT-3 Evpn Mac add from remote when local mac is already present - mac = "52:54:00:25:06:E9" - - print("Creating Local dynamic FDB Vlan3:"+mac.lower()+":Ethernet0 in APP-DB") - # Create Dynamic MAC entry in APP DB - helper.create_entry_pst( - dvs.pdb, - "FDB_TABLE", "Vlan3:"+mac.lower(), - [ - ("port", "Ethernet0"), - ("type", "dynamic"), - ] - ) - - time.sleep(1) - - # check that the FDB entry was added in ASIC DB - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [("mac", mac), ("bvid", vlan_oid_3)], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_DYNAMIC"), - ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", iface_2_bridge_port_id["Ethernet0"])] - ) - assert ok, str(extra) - print("Dynamic FDB Vlan3:"+mac.lower()+":Ethernet0 is created in Asic-DB") - - # check that the FDB entry was added in STATE DB - mac1_found, extra = dvs.is_table_entry_exists(dvs.sdb, "FDB_TABLE", - "Vlan3:"+mac.lower(), - [("port", "Ethernet0"), - ("type", "dynamic"), - ] - ) - assert mac1_found, str(extra) - print("FDB Vlan3:"+mac+":Ethernet0 is created in STATE-DB") - - print("Creating Evpn FDB Vlan3:"+mac.lower()+":6.6.6.6 in APP-DB") - helper.create_entry_pst( - dvs.pdb, - "VXLAN_FDB_TABLE", "Vlan3:"+mac.lower(), - [ - ("remote_vtep", remote_ip_6), - ("type", "dynamic"), - ("vni", "3") - ] - ) - time.sleep(1) - - - # check that the FDB entry is inserted into ASIC DB - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [("mac", mac), ("bvid", str(dvs.getVlanOid("3")))], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_STATIC"), - ("SAI_FDB_ENTRY_ATTR_ALLOW_MAC_MOVE", "true"), - ("SAI_FDB_ENTRY_ATTR_ENDPOINT_IP", remote_ip_6), - ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", str(tnl_bp_oid_6)), - ] - ) - assert ok, str(extra) - print("EVPN FDB Vlan3:"+mac.lower()+":"+remote_ip_6+" is created in ASIC-DB") - - # check that the Local FDB entry is deleted from STATE DB - mac1_found, extra = dvs.is_table_entry_exists(dvs.sdb, "FDB_TABLE", - "Vlan3:"+mac.lower(), - [("port", "Ethernet0"), - ("type", "dynamic"), - ] - ) - assert mac1_found == False, str(extra) - print("FDB Vlan3:"+mac+":Ethernet0 is deleted from STATE-DB") - - time.sleep(1) - - - #UT-4 Evpn Sticky Mac add from remote - mac = "52:54:00:25:06:E9" - print("Creating Evpn Sticky FDB Vlan3:"+mac.lower()+":6.6.6.6 in APP-DB") - helper.create_entry_pst( - dvs.pdb, - "VXLAN_FDB_TABLE", "Vlan3:"+mac.lower(), - [ - ("remote_vtep", remote_ip_6), - ("type", "static"), - ("vni", "3") - ] - ) - time.sleep(1) - - - # check that the FDB entry is inserted into ASIC DB - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [("mac", mac), ("bvid", str(dvs.getVlanOid("3")))], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_STATIC"), - ("SAI_FDB_ENTRY_ATTR_ENDPOINT_IP", remote_ip_6), - ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", str(tnl_bp_oid_6)), - ] - ) - assert ok, str(extra) - print("EVPN Sticky FDB Vlan3:"+mac.lower()+":"+remote_ip_6+" is created in ASIC-DB") - - #UT-8 Evpn Mac add from remote when tunnels are already created - mac = "52:54:00:25:06:E9" - print("Creating Evpn FDB Vlan3:"+mac.lower()+":6.6.6.6 in APP-DB") - helper.create_entry_pst( - dvs.pdb, - "VXLAN_FDB_TABLE", "Vlan3:"+mac.lower(), - [ - ("remote_vtep", remote_ip_6), - ("type", "dynamic"), - ("vni", "3") - ] - ) - time.sleep(1) - - # check that the FDB entry is inserted into ASIC DB - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [("mac", mac), ("bvid", vlan_oid_3)], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_STATIC"), - ("SAI_FDB_ENTRY_ATTR_ALLOW_MAC_MOVE", "true"), - ("SAI_FDB_ENTRY_ATTR_ENDPOINT_IP", remote_ip_6), - ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", str(tnl_bp_oid_6)), - ] - ) - assert ok == True, str(extra) - print("EVPN FDB Vlan3:"+mac.lower()+":"+remote_ip_6+" is created in ASIC-DB") - - time.sleep(1) - - tnl_bp_oid_8 = get_vxlan_p2mp_tunnel_bp(dvs.adb, source_tnl_ip) - - print("Creating Evpn FDB Vlan3:"+mac.lower()+":8.8.8.8 in APP-DB") - helper.create_entry_pst( - dvs.pdb, - "VXLAN_FDB_TABLE", "Vlan3:"+mac.lower(), - [ - ("remote_vtep", remote_ip_8), - ("type", "dynamic"), - ("vni", "3") - ] - ) - time.sleep(1) - - # check that the FDB entry is inserted into ASIC DB - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [("mac", mac), ("bvid", vlan_oid_3)], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_STATIC"), - ("SAI_FDB_ENTRY_ATTR_ALLOW_MAC_MOVE", "true"), - ("SAI_FDB_ENTRY_ATTR_ENDPOINT_IP", remote_ip_8), - ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", str(tnl_bp_oid_8)), - ] - ) - assert ok == True, str(extra) - print("EVPN FDB Vlan3:"+mac.lower()+":"+remote_ip_8+" is created in ASIC-DB") - - time.sleep(1) - - #UT-9 Local mac move (delete and learn) when remote is already added - mac = "52:54:00:25:06:E9" - print("Deleting FDB Vlan3:52-54-00-25-06-E9:8.8.8.8 in ASIC-DB") - helper.delete_entry_tbl(dvs.adb, "ASIC_STATE", "SAI_OBJECT_TYPE_FDB_ENTRY:{\"bvid\":\""+vlan_oid_3+"\",\"mac\":\""+mac+"\",\"switch_id\":\""+switch_id+"\"}") - - ntf = swsscommon.NotificationProducer(dvs.adb, "NOTIFICATIONS") - fvp = swsscommon.FieldValuePairs() - ntf_data = "[{\"fdb_entry\":\"{\\\"bvid\\\":\\\""+vlan_oid_3+"\\\",\\\"mac\\\":\\\""+mac+"\\\",\\\"switch_id\\\":\\\""+switch_id+"\\\"}\",\"fdb_event\":\"SAI_FDB_EVENT_AGED\",\"list\":[{\"id\":\"SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID\",\"value\":\""+str(tnl_bp_oid_8)+"\"}]}]" - ntf.send("fdb_event", ntf_data, fvp) - - time.sleep(2) - - print("Creating FDB Vlan3:52-54-00-25-06-E9:Ethernet0 in ASIC-DB") - helper.create_entry_tbl( - dvs.adb, - "ASIC_STATE", "SAI_OBJECT_TYPE_FDB_ENTRY:{\"bvid\":\""+vlan_oid_3+"\",\"mac\":\"52:54:00:25:06:E9\",\"switch_id\":\""+switch_id+"\"}", - [ - ("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_DYNAMIC"), - ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", iface_2_bridge_port_id["Ethernet0"]), - ] - ) - - ntf = swsscommon.NotificationProducer(dvs.adb, "NOTIFICATIONS") - fvp = swsscommon.FieldValuePairs() - ntf_data = "[{\"fdb_entry\":\"{\\\"bvid\\\":\\\""+vlan_oid_3+"\\\",\\\"mac\\\":\\\"52:54:00:25:06:E9\\\",\\\"switch_id\\\":\\\""+switch_id+"\\\"}\",\"fdb_event\":\"SAI_FDB_EVENT_LEARNED\",\"list\":[{\"id\":\"SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID\",\"value\":\""+iface_2_bridge_port_id["Ethernet0"]+"\"}]}]" - ntf.send("fdb_event", ntf_data, fvp) - - time.sleep(2) - - # check that the FDB entry was added in ASIC DB - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [("mac", "52:54:00:25:06:E9"), ("bvid", vlan_oid_3)], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_DYNAMIC"), - ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", iface_2_bridge_port_id["Ethernet0"])] - ) - assert ok, str(extra) - print("FDB Vlan3:52-54-00-25-06-E9:Ethernet0 is created in ASIC-DB") - - # check that the FDB entry was added in STATE DB - mac1_found, extra = dvs.is_table_entry_exists(dvs.sdb, "FDB_TABLE", - "Vlan3:52:54:00:25:06:e9", - [("port", "Ethernet0"), - ("type", "dynamic"), - ] - ) - assert mac1_found, str(extra) - print("FDB Vlan3:52-54-00-25-06-E9:Ethernet0 is created in STATE-DB") - - #UT-10 Evpn Mac add from remote when tunnels are not created - mac = "52:54:00:25:06:E1" - remote_ip_9 = "9.9.9.9" - print("Creating Evpn FDB Vlan3:"+mac.lower()+":9.9.9.9 in APP-DB") - helper.create_entry_pst( - dvs.pdb, - "VXLAN_FDB_TABLE", "Vlan3:"+mac.lower(), - [ - ("remote_vtep", remote_ip_9), - ("type", "dynamic"), - ("vni", "3") - ] - ) - time.sleep(1) - - #Adding remote VNI later - vxlan_obj.create_evpn_remote_vni(dvs, "Vlan3", remote_ip_9, "3") - time.sleep(1) - tnl_bp_oid_9 = get_vxlan_p2mp_tunnel_bp(dvs.adb, source_tnl_ip) - - # check that the FDB entry is inserted into ASIC DB - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [("mac", mac), ("bvid", vlan_oid_3)], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_STATIC"), - ("SAI_FDB_ENTRY_ATTR_ALLOW_MAC_MOVE", "true"), - ("SAI_FDB_ENTRY_ATTR_ENDPOINT_IP", remote_ip_9), - ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", str(tnl_bp_oid_9)), - ] - ) - assert ok == True, str(extra) - print("EVPN FDB Vlan3:"+mac.lower()+":"+remote_ip_9+" is created in ASIC-DB") - - time.sleep(1) - - - dvs.remove_vlan_member("3", "Ethernet0") - dvs.remove_vlan("3") diff --git a/tests/test_evpn_l3_vxlan.py b/tests/test_evpn_l3_vxlan.py deleted file mode 100644 index 8820f484e6..0000000000 --- a/tests/test_evpn_l3_vxlan.py +++ /dev/null @@ -1,632 +0,0 @@ -from swsscommon import swsscommon -import random -import pytest -from pprint import pprint -from evpn_tunnel import VxlanTunnel,VxlanEvpnHelper -import time - -class TestL3Vxlan(object): - - def get_vxlan_obj(self): - return VxlanTunnel() - - def get_vxlan_helper(self): - return VxlanEvpnHelper() - - def setup_db(self, dvs): - self.pdb = swsscommon.DBConnector(0, dvs.redis_sock, 0) - self.adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - self.cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) - self.sdb = swsscommon.DBConnector(6, dvs.redis_sock, 0) - -# Test 1 - Create and Delete SIP Tunnel and VRF VNI Map entries -# @pytest.mark.skip(reason="Starting Route Orch, VRF Orch to be merged") -# @pytest.mark.dev_sanity - def test_sip_tunnel_vrf_vni_map(self, dvs, testlog): - vxlan_obj = self.get_vxlan_obj() - helper = self.get_vxlan_helper() - - self.setup_db(dvs) - tunnel_name = 'tunnel_2' - map_name = 'map_1000_100' - vrf_map_name = 'evpn_map_1000_Vrf-RED' - - vxlan_obj.fetch_exist_entries(dvs) - - print ("\n\nTesting Create and Delete SIP Tunnel and VRF VNI Map entries") - print ("\tCreate SIP Tunnel") - vxlan_obj.create_vlan1(dvs,"Vlan100") - vxlan_obj.check_vlan_obj(dvs, "100") - vxlan_obj.create_vxlan_tunnel(dvs, tunnel_name, '6.6.6.6') - vxlan_obj.create_evpn_nvo(dvs, 'nvo1', tunnel_name) - - print ("\tCreate Vlan-VNI map and VRF-VNI map") - vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') - - vxlan_obj.create_vrf(dvs, "Vrf-RED") - vxlan_obj.create_vxlan_vrf_tunnel_map(dvs, 'Vrf-RED', '1000') - - print ("\tTesting VRF-VNI map in APP DB") - vlanlist = ['100'] - vnilist = ['1000'] - - exp_attrs = [ - ("vni", "1000"), - ] - exp_attr = {} - for an in range(len(exp_attrs)): - exp_attr[exp_attrs[an][0]] = exp_attrs[an][1] - - helper.check_object(self.pdb, "VRF_TABLE", 'Vrf-RED', exp_attr) - - exp_attrs1 = [ - ("vni", "1000"), - ("vlan", "Vlan100"), - ] - exp_attr1 = {} - for an in range(len(exp_attrs1)): - exp_attr1[exp_attrs1[an][0]] = exp_attrs1[an][1] - - helper.check_object(self.pdb, "VXLAN_VRF_TABLE", "%s:%s" % (tunnel_name, vrf_map_name), exp_attr1) - - print ("\tTesting SIP Tunnel Creation") - vxlan_obj.check_vxlan_sip_tunnel(dvs, tunnel_name, '6.6.6.6', vlanlist, vnilist, tunnel_map_entry_count = 2) - - print ("\tTesting Tunnel Vlan VNI Map Entry") - vxlan_obj.check_vxlan_tunnel_map_entry_removed(dvs, tunnel_name, vlanlist, vnilist) - - print ("\tTesting Tunnel VRF VNI Map Entry") - vxlan_obj.check_vxlan_tunnel_vrf_map_entry(dvs, tunnel_name, 'Vrf-RED', '1000') - - print ("\tTesting Tunnel VRF VNI Map Entry removal") - vxlan_obj.remove_vxlan_vrf_tunnel_map(dvs, 'Vrf-RED') - vxlan_obj.remove_vrf(dvs, "Vrf-RED") - vxlan_obj.check_vxlan_tunnel_vrf_map_entry_remove(dvs, tunnel_name, 'Vrf-RED', '1000') - - print ("\tTesting Tunnel Vlan VNI Map entry removal") - vxlan_obj.check_vxlan_tunnel_map_entry(dvs, tunnel_name, vlanlist, vnilist) - vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') - vxlan_obj.check_vxlan_tunnel_map_entry_delete(dvs, tunnel_name, vlanlist, vnilist) - - print ("\tTesting SIP Tunnel Deletion") - vxlan_obj.remove_vxlan_tunnel(dvs, tunnel_name) - vxlan_obj.remove_evpn_nvo(dvs, 'nvo1') - time.sleep(2) - vxlan_obj.check_vxlan_sip_tunnel_delete(dvs, tunnel_name, '6.6.6.6') - vxlan_obj.remove_vlan(dvs, "100") - - -# Test 2 - Create and Delete DIP Tunnel on adding and removing prefix route -# @pytest.mark.skip(reason="Starting Route Orch, VRF Orch to be merged") -# @pytest.mark.dev_sanity - def test_prefix_route_create_tunnel(self, dvs, testlog): - vxlan_obj = self.get_vxlan_obj() - helper = self.get_vxlan_helper() - - self.setup_db(dvs) - tunnel_name = 'tunnel_2' - map_name = 'map_1000_100' - vrf_map_name = 'evpn_map_1000_Vrf-RED' - vxlan_obj.fetch_exist_entries(dvs) - - print ("\n\nTesting Create and Delete DIP Tunnel on adding and removing prefix route") - print ("\tCreate SIP Tunnel") - vlan_ids = helper.get_exist_entries(dvs, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - vlan_oid = vxlan_obj.create_vlan(dvs,"Vlan100", vlan_ids) - vxlan_obj.create_vxlan_tunnel(dvs, tunnel_name, '6.6.6.6') - vxlan_obj.create_evpn_nvo(dvs, 'nvo1', tunnel_name) - - print ("\tCreate Vlan-VNI map and VRF-VNI map") - vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') - - print ("\tTesting VRF-VNI map in APP DB") - vxlan_obj.create_vrf(dvs, "Vrf-RED") - vxlan_obj.create_vxlan_vrf_tunnel_map(dvs, 'Vrf-RED', '1000') - - vlanlist = ['100'] - vnilist = ['1000'] - - exp_attrs = [ - ("vni", "1000"), - ] - exp_attr = {} - for an in range(len(exp_attrs)): - exp_attr[exp_attrs[an][0]] = exp_attrs[an][1] - - helper.check_object(self.pdb, "VRF_TABLE", 'Vrf-RED', exp_attr) - - exp_attrs1 = [ - ("vni", "1000"), - ("vlan", "Vlan100"), - ] - exp_attr1 = {} - for an in range(len(exp_attrs1)): - exp_attr1[exp_attrs1[an][0]] = exp_attrs1[an][1] - - helper.check_object(self.pdb, "VXLAN_VRF_TABLE", "%s:%s" % (tunnel_name, vrf_map_name), exp_attr1) - - print ("\tTesting SIP Tunnel Creation") - vxlan_obj.check_vxlan_sip_tunnel(dvs, tunnel_name, '6.6.6.6', vlanlist, vnilist, tunnel_map_entry_count = 2) - - print ("\tTesting Tunnel Vlan Map Entry") - vxlan_obj.check_vxlan_tunnel_map_entry_removed(dvs, tunnel_name, vlanlist, vnilist) - - print ("\tTesting Tunnel Vrf Map Entry") - vxlan_obj.check_vxlan_tunnel_vrf_map_entry(dvs, tunnel_name, 'Vrf-RED', '1000') - - print ("\tTesting VLAN 100 interface creation") - vxlan_obj.create_vlan_interface(dvs, "Vlan100", "Ethernet24", "Vrf-RED", "100.100.3.1/24") - vxlan_obj.check_router_interface(dvs, 'Vrf-RED', vlan_oid, 2) - - print ("\tTest VRF IPv4 Route with Tunnel Nexthop Add") - vxlan_obj.fetch_exist_entries(dvs) - vxlan_obj.create_vrf_route(dvs, "80.80.1.0/24", 'Vrf-RED', '7.7.7.7', "Vlan100", "00:11:11:11:11:11", '1000') - vxlan_obj.check_vrf_routes(dvs, "80.80.1.0/24", 'Vrf-RED', '7.7.7.7', tunnel_name, "00:11:11:11:11:11", '1000') - - print ("\tTest VRF IPv4 Route with Tunnel Nexthop Delete") - vxlan_obj.delete_vrf_route(dvs, "80.80.1.0/24", 'Vrf-RED') - vxlan_obj.check_del_tunnel_nexthop(dvs, 'Vrf-RED', '7.7.7.7', tunnel_name, "00:11:11:11:11:11", '1000') - vxlan_obj.check_del_vrf_routes(dvs, "80.80.1.0/24", 'Vrf-RED') - - print ("\tTesting Tunnel Vrf Map Entry removal") - vxlan_obj.remove_vxlan_vrf_tunnel_map(dvs, 'Vrf-RED') - vxlan_obj.check_vxlan_tunnel_vrf_map_entry_remove(dvs, tunnel_name, 'Vrf-RED', '1000') - - print ("\tTesting Vlan 100 interface delete") - vxlan_obj.delete_vlan_interface(dvs, "Vlan100", "100.100.3.1/24") - vxlan_obj.check_del_router_interface(dvs, "Vlan100") - - print ("\tTesting Tunnel Map entry removal") - vxlan_obj.check_vxlan_tunnel_map_entry(dvs, tunnel_name, vlanlist, vnilist) - vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') - vxlan_obj.check_vxlan_tunnel_map_entry_delete(dvs, tunnel_name, vlanlist, vnilist) - - print ("\tTesting SIP Tunnel Deletion") - vxlan_obj.remove_vxlan_tunnel(dvs, tunnel_name) - vxlan_obj.remove_evpn_nvo(dvs, 'nvo1') - time.sleep(2) - vxlan_obj.check_vxlan_sip_tunnel_delete(dvs, tunnel_name, '6.6.6.6') - vxlan_obj.remove_vrf(dvs, "Vrf-RED") - vxlan_obj.remove_vlan_member(dvs, "100", "Ethernet24") - vxlan_obj.remove_vlan(dvs, "100") - - -# Test 3 - Create and Delete DIP Tunnel and Test IPv4 route and overlay nexthop add and delete -# @pytest.mark.skip(reason="Starting Route Orch, VRF Orch to be merged") -# @pytest.mark.dev_sanity - def test_tunnel_ipv4_routes(self, dvs, testlog): - vxlan_obj = self.get_vxlan_obj() - helper = self.get_vxlan_helper() - - self.setup_db(dvs) - tunnel_name = 'tunnel_2' - map_name = 'map_1000_100' - vrf_map_name = 'evpn_map_1000_Vrf-RED' - vxlan_obj.fetch_exist_entries(dvs) - - print ("\n\nTesting IPv4 Route and Overlay Nexthop Add and Delete") - print ("\tCreate SIP Tunnel") - vxlan_obj.create_vlan1(dvs,"Vlan100") - vxlan_obj.check_vlan_obj(dvs, "100") - vxlan_obj.create_vxlan_tunnel(dvs, tunnel_name, '6.6.6.6') - vxlan_obj.create_evpn_nvo(dvs, 'nvo1', tunnel_name) - - print ("\tCreate Vlan-VNI map and VRF-VNI map") - vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') - - vxlan_obj.create_vrf(dvs, "Vrf-RED") - vxlan_obj.create_vxlan_vrf_tunnel_map(dvs, 'Vrf-RED', '1000') - - print ("\tTesting VRF-VNI map in APP DB") - vlanlist = ['100'] - vnilist = ['1000'] - - exp_attrs = [ - ("vni", "1000"), - ] - exp_attr = {} - for an in range(len(exp_attrs)): - exp_attr[exp_attrs[an][0]] = exp_attrs[an][1] - - helper.check_object(self.pdb, "VRF_TABLE", 'Vrf-RED', exp_attr) - - exp_attrs1 = [ - ("vni", "1000"), - ("vlan", "Vlan100"), - ] - exp_attr1 = {} - for an in range(len(exp_attrs1)): - exp_attr1[exp_attrs1[an][0]] = exp_attrs1[an][1] - - helper.check_object(self.pdb, "VXLAN_VRF_TABLE", "%s:%s" % (tunnel_name, vrf_map_name), exp_attr1) - - print ("\tTesting SIP Tunnel Creation") - vxlan_obj.check_vxlan_sip_tunnel(dvs, tunnel_name, '6.6.6.6', vlanlist, vnilist, tunnel_map_entry_count = 2) - - print ("\tTesting Tunnel Vlan Map Entry") - vxlan_obj.check_vxlan_tunnel_map_entry_removed(dvs, tunnel_name, vlanlist, vnilist) - - print ("\tTesting Tunnel Vrf Map Entry") - vxlan_obj.check_vxlan_tunnel_vrf_map_entry(dvs, tunnel_name, 'Vrf-RED', '1000') - - print ("\tTesting VLAN 100 interface creation") - vxlan_obj.create_vlan_interface(dvs, "Vlan100", "Ethernet24", "Vrf-RED", "100.100.3.1/24") - vxlan_obj.check_router_interface(dvs, 'Vrf-RED', vxlan_obj.vlan_id_map['100'], 2) - - print ("\tTest VRF IPv4 Route with Tunnel Nexthop 7.7.7.7 Add") - vxlan_obj.fetch_exist_entries(dvs) - vxlan_obj.create_vrf_route(dvs, "80.80.1.0/24", 'Vrf-RED', '7.7.7.7', "Vlan100", "00:11:11:11:11:11", '1000') - vxlan_obj.check_vrf_routes(dvs, "80.80.1.0/24", 'Vrf-RED', '7.7.7.7', tunnel_name, "00:11:11:11:11:11", '1000') - - print ("\tTest VRF IPv4 Route with Tunnel Nexthop 7.7.7.7 Delete") - vxlan_obj.delete_vrf_route(dvs, "80.80.1.0/24", 'Vrf-RED') - vxlan_obj.check_del_tunnel_nexthop(dvs, 'Vrf-RED', '7.7.7.7', tunnel_name, "00:11:11:11:11:11", '1000') - vxlan_obj.check_del_vrf_routes(dvs, "80.80.1.0/24", 'Vrf-RED') - - print ("\n\nTesting IPv4 Route and Overlay Nexthop Update") - print ("\tTest VRF IPv4 Route with Tunnel Nexthop 7.7.7.7 Add") - vxlan_obj.fetch_exist_entries(dvs) - vxlan_obj.create_vrf_route(dvs, "80.80.1.0/24", 'Vrf-RED', '7.7.7.7', "Vlan100", "00:11:11:11:11:11", '1000') - vxlan_obj.check_vrf_routes(dvs, "80.80.1.0/24", 'Vrf-RED', '7.7.7.7', tunnel_name, "00:11:11:11:11:11", '1000') - - print ("\tTest Tunnel Nexthop change from 7.7.7.7 to 8.8.8.8") - vxlan_obj.create_vrf_route(dvs, "80.80.1.0/24", 'Vrf-RED', '8.8.8.8', "Vlan100", "00:22:22:22:22:22", '1000') - vxlan_obj.check_vrf_routes(dvs, "80.80.1.0/24", 'Vrf-RED', '8.8.8.8', tunnel_name, "00:22:22:22:22:22", '1000', 1) - - print ("\tTest Previous Tunnel Nexthop 7.7.7.7 is removed") - vxlan_obj.check_del_tunnel_nexthop(dvs, 'Vrf-RED', '7.7.7.7', tunnel_name, "00:11:11:11:11:11", '1000') - - print ("\tTest VRF IPv4 Route and Tunnel Nexthop 8.8.8.8 Delete") - vxlan_obj.fetch_exist_entries(dvs) - vxlan_obj.delete_vrf_route(dvs, "80.80.1.0/24", 'Vrf-RED') - vxlan_obj.check_del_tunnel_nexthop(dvs, 'Vrf-RED', '8.8.8.8', tunnel_name, "00:22:22:22:22:22", '1000') - vxlan_obj.check_del_vrf_routes(dvs, "80.80.1.0/24", 'Vrf-RED') - - print ("\n\nTest VRF IPv4 Route with ECMP Tunnel Nexthop Add and Delete") - vxlan_obj.fetch_exist_entries(dvs) - - ecmp_nexthop_attr = [ - ("nexthop", "7.7.7.7,8.8.8.8"), - ("ifname", "Vlan100,Vlan100"), - ("vni_label", "1000,1000"), - ("router_mac", "00:11:11:11:11:11,00:22:22:22:22:22"), - ] - - print ("\tTest VRF IPv4 Route with ECMP Tunnel Nexthop [7.7.7.7 , 8.8.8.8] Add") - vxlan_obj.create_vrf_route_ecmp(dvs, "80.80.1.0/24", 'Vrf-RED', ecmp_nexthop_attr) - - nh_count = 2 - ecmp_nhid_list = vxlan_obj.check_vrf_routes_ecmp(dvs, "80.80.1.0/24", 'Vrf-RED', tunnel_name, nh_count) - assert nh_count == len(ecmp_nhid_list) - vxlan_obj.check_add_tunnel_nexthop(dvs, ecmp_nhid_list[0], '7.7.7.7', tunnel_name, '00:11:11:11:11:11', '1000') - vxlan_obj.check_add_tunnel_nexthop(dvs, ecmp_nhid_list[1], '8.8.8.8', tunnel_name, '00:22:22:22:22:22', '1000') - - print ("\tTest VRF IPv4 Route with ECMP Tunnel Nexthop [7.7.7.7 , 8.8.8.8] Delete") - vxlan_obj.fetch_exist_entries(dvs) - vxlan_obj.delete_vrf_route(dvs, "80.80.1.0/24", 'Vrf-RED') - helper.check_deleted_object(self.adb, vxlan_obj.ASIC_NEXT_HOP, ecmp_nhid_list[0]) - helper.check_deleted_object(self.adb, vxlan_obj.ASIC_NEXT_HOP, ecmp_nhid_list[1]) - - vxlan_obj.check_vrf_routes_ecmp_nexthop_grp_del(dvs, 2) - vxlan_obj.check_del_vrf_routes(dvs, "80.80.1.0/24", 'Vrf-RED') - - print ("\n\nTest VRF IPv4 Multiple Route with ECMP Tunnel Nexthop Add and Delete") - vxlan_obj.fetch_exist_entries(dvs) - - ecmp_nexthop_attr = [ - ("nexthop", "7.7.7.7,8.8.8.8"), - ("ifname", "Vlan100,Vlan100"), - ("vni_label", "1000,1000"), - ("router_mac", "00:11:11:11:11:11,00:22:22:22:22:22"), - ] - - print ("\tTest VRF IPv4 Multiple Route with ECMP Tunnel Nexthop [7.7.7.7 , 8.8.8.8] Add") - vxlan_obj.create_vrf_route_ecmp(dvs, "80.80.1.0/24", 'Vrf-RED', ecmp_nexthop_attr) - - nh_count = 2 - ecmp_nhid_list = vxlan_obj.check_vrf_routes_ecmp(dvs, "80.80.1.0/24", 'Vrf-RED', tunnel_name, nh_count) - assert nh_count == len(ecmp_nhid_list) - vxlan_obj.check_add_tunnel_nexthop(dvs, ecmp_nhid_list[0], '7.7.7.7', tunnel_name, '00:11:11:11:11:11', '1000') - vxlan_obj.check_add_tunnel_nexthop(dvs, ecmp_nhid_list[1], '8.8.8.8', tunnel_name, '00:22:22:22:22:22', '1000') - - nh_count = 2 - vxlan_obj.create_vrf_route_ecmp(dvs, "90.90.1.0/24", 'Vrf-RED', ecmp_nexthop_attr) - ecmp_nhid_list = vxlan_obj.check_vrf_routes_ecmp(dvs, "90.90.1.0/24", 'Vrf-RED', tunnel_name, nh_count) - assert nh_count == len(ecmp_nhid_list) - vxlan_obj.check_add_tunnel_nexthop(dvs, ecmp_nhid_list[0], '7.7.7.7', tunnel_name, '00:11:11:11:11:11', '1000') - vxlan_obj.check_add_tunnel_nexthop(dvs, ecmp_nhid_list[1], '8.8.8.8', tunnel_name, '00:22:22:22:22:22', '1000') - - print ("\tTest VRF IPv4 Multiple Route with ECMP Tunnel Nexthop [7.7.7.7 , 8.8.8.8] Delete") - vxlan_obj.fetch_exist_entries(dvs) - vxlan_obj.delete_vrf_route(dvs, "80.80.1.0/24", 'Vrf-RED') - vxlan_obj.check_del_vrf_routes(dvs, "80.80.1.0/24", 'Vrf-RED') - vxlan_obj.fetch_exist_entries(dvs) - vxlan_obj.delete_vrf_route(dvs, "90.90.1.0/24", 'Vrf-RED') - vxlan_obj.check_del_vrf_routes(dvs, "90.90.1.0/24", 'Vrf-RED') - helper.check_deleted_object(self.adb, vxlan_obj.ASIC_NEXT_HOP, ecmp_nhid_list[0]) - helper.check_deleted_object(self.adb, vxlan_obj.ASIC_NEXT_HOP, ecmp_nhid_list[1]) - - vxlan_obj.check_vrf_routes_ecmp_nexthop_grp_del(dvs, 2) - - print ("\n\nTest VRF IPv4 Route with Tunnel Nexthop update from non-ECMP to ECMP") - print ("\tTest VRF IPv4 Route with Tunnel Nexthop 7.7.7.7 Add") - vxlan_obj.fetch_exist_entries(dvs) - vxlan_obj.create_vrf_route(dvs, "80.80.1.0/24", 'Vrf-RED', '7.7.7.7', "Vlan100", "00:11:11:11:11:11", '1000') - vxlan_obj.check_vrf_routes(dvs, "80.80.1.0/24", 'Vrf-RED', '7.7.7.7', tunnel_name, "00:11:11:11:11:11", '1000') - - ecmp_nexthop_attr = [ - ("nexthop", "7.7.7.7,8.8.8.8"), - ("ifname", "Vlan100,Vlan100"), - ("vni_label", "1000,1000"), - ("router_mac", "00:11:11:11:11:11,00:22:22:22:22:22"), - ] - - print ("\tTest VRF IPv4 Route with ECMP Tunnel Nexthop [7.7.7.7 , 8.8.8.8] Udpate") - vxlan_obj.create_vrf_route_ecmp(dvs, "80.80.1.0/24", 'Vrf-RED', ecmp_nexthop_attr) - - nh_count = 2 - ecmp_nhid_list = vxlan_obj.check_vrf_routes_ecmp(dvs, "80.80.1.0/24", 'Vrf-RED', tunnel_name, nh_count, 1) - assert nh_count == len(ecmp_nhid_list) - vxlan_obj.check_add_tunnel_nexthop(dvs, ecmp_nhid_list[0], '7.7.7.7', tunnel_name, '00:11:11:11:11:11', '1000') - vxlan_obj.check_add_tunnel_nexthop(dvs, ecmp_nhid_list[1], '8.8.8.8', tunnel_name, '00:22:22:22:22:22', '1000') - - print ("\n\nTest VRF IPv4 Route with Tunnel Nexthop update from ECMP to non-ECMP") - print ("\tTest VRF IPv4 Route with Tunnel Nexthop 8.8.8.8 Update") - vxlan_obj.create_vrf_route(dvs, "80.80.1.0/24", 'Vrf-RED', '8.8.8.8', "Vlan100", "00:22:22:22:22:22", '1000') - vxlan_obj.check_vrf_routes(dvs, "80.80.1.0/24", 'Vrf-RED', '8.8.8.8', tunnel_name, "00:22:22:22:22:22", '1000', 1) - - print ("\tTest Tunnel Nexthop 7.7.7.7 is deleted") - vxlan_obj.check_del_tunnel_nexthop(dvs, 'Vrf-RED', '7.7.7.7', tunnel_name, "00:11:11:11:11:11", '1000') - - print ("\tTest Tunnel Nexthop ECMP Group is deleted") - vxlan_obj.check_vrf_routes_ecmp_nexthop_grp_del(dvs, 2) - - print ("\tTest VRF IPv4 Route with Tunnel Nexthop 8.8.8.8 Delete") - vxlan_obj.fetch_exist_entries(dvs) - vxlan_obj.delete_vrf_route(dvs, "80.80.1.0/24", 'Vrf-RED') - - vxlan_obj.check_del_tunnel_nexthop(dvs, 'Vrf-RED', '8.8.8.8', tunnel_name, "00:22:22:22:22:22", '1000') - vxlan_obj.check_del_vrf_routes(dvs, "80.80.1.0/24", 'Vrf-RED') - - print ("\n\nTest DIP and SIP Tunnel Deletion ") - print ("\tTesting Tunnel Vrf VNI Map Entry removal") - vxlan_obj.remove_vxlan_vrf_tunnel_map(dvs, 'Vrf-RED') - vxlan_obj.check_vxlan_tunnel_vrf_map_entry_remove(dvs, tunnel_name, 'Vrf-RED', '1000') - - print ("\tTesting Vlan 100 interface delete") - vxlan_obj.delete_vlan_interface(dvs, "Vlan100", "100.100.3.1/24") - vxlan_obj.check_del_router_interface(dvs, "Vlan100") - - print ("\tTesting Tunnel Map entry removal") - vxlan_obj.check_vxlan_tunnel_map_entry(dvs, tunnel_name, vlanlist, vnilist) - vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') - vxlan_obj.check_vxlan_tunnel_map_entry_delete(dvs, tunnel_name, vlanlist, vnilist) - - print ("\tTesting SIP Tunnel Deletion") - vxlan_obj.remove_vxlan_tunnel(dvs, tunnel_name) - vxlan_obj.remove_evpn_nvo(dvs, 'nvo1') - time.sleep(2) - vxlan_obj.check_vxlan_sip_tunnel_delete(dvs, tunnel_name, '6.6.6.6') - vxlan_obj.remove_vrf(dvs, "Vrf-RED") - vxlan_obj.remove_vlan_member(dvs, "100", "Ethernet24") - vxlan_obj.remove_vlan(dvs, "100") - - -# Test 4 - Create and Delete DIP Tunnel and Test IPv6 route and overlay nexthop add and delete -# @pytest.mark.skip(reason="Starting Route Orch, VRF Orch to be merged") -# @pytest.mark.dev_sanity - def test_tunnel_ipv6_routes(self, dvs, testlog): - vxlan_obj = self.get_vxlan_obj() - helper = self.get_vxlan_helper() - - self.setup_db(dvs) - tunnel_name = 'tunnel_2' - map_name = 'map_1000_100' - vrf_map_name = 'evpn_map_1000_Vrf-RED' - vxlan_obj.fetch_exist_entries(dvs) - - print ("\n\nTesting IPv6 Route and Overlay Nexthop Add and Delete") - print ("\tCreate SIP Tunnel") - vxlan_obj.create_vlan1(dvs,"Vlan100") - vxlan_obj.check_vlan_obj(dvs, "100") - vxlan_obj.create_vxlan_tunnel(dvs, tunnel_name, '6.6.6.6') - vxlan_obj.create_evpn_nvo(dvs, 'nvo1', tunnel_name) - - print ("\tCreate Vlan-VNI map and VRF-VNI map") - vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') - - print ("\tTesting VRF-VNI map in APP DB") - vxlan_obj.create_vrf(dvs, "Vrf-RED") - vxlan_obj.create_vxlan_vrf_tunnel_map(dvs, 'Vrf-RED', '1000') - - vlanlist = ['100'] - vnilist = ['1000'] - - exp_attrs = [ - ("vni", "1000"), - ] - exp_attr = {} - for an in range(len(exp_attrs)): - exp_attr[exp_attrs[an][0]] = exp_attrs[an][1] - - print ("\tCheck VRF Table in APP DB") - helper.check_object(self.pdb, "VRF_TABLE", 'Vrf-RED', exp_attr) - - exp_attrs1 = [ - ("vni", "1000"), - ("vlan", "Vlan100"), - ] - exp_attr1 = {} - for an in range(len(exp_attrs1)): - exp_attr1[exp_attrs1[an][0]] = exp_attrs1[an][1] - - helper.check_object(self.pdb, "VXLAN_VRF_TABLE", "%s:%s" % (tunnel_name, vrf_map_name), exp_attr1) - - print ("\tTesting SIP Tunnel Creation") - vxlan_obj.check_vxlan_sip_tunnel(dvs, tunnel_name, '6.6.6.6', vlanlist, vnilist, tunnel_map_entry_count = 2) - - print ("\tTesting Tunnel Vlan Map Entry") - vxlan_obj.check_vxlan_tunnel_map_entry_removed(dvs, tunnel_name, vlanlist, vnilist) - - print ("\tTesting Tunnel Vrf Map Entry") - vxlan_obj.check_vxlan_tunnel_vrf_map_entry(dvs, tunnel_name, 'Vrf-RED', '1000') - - - vxlan_obj.fetch_exist_entries(dvs) - print ("\tTesting VLAN 100 interface creation") - vxlan_obj.create_vlan_interface(dvs, "Vlan100", "Ethernet24", "Vrf-RED", "2001::8/64") - vxlan_obj.check_router_interface(dvs, 'Vrf-RED', vxlan_obj.vlan_id_map['100'], 2) - - print ("\tTest VRF IPv6 Route with Tunnel Nexthop Add") - vxlan_obj.fetch_exist_entries(dvs) - vxlan_obj.create_vrf_route(dvs, "2002::8/64", 'Vrf-RED', '7.7.7.7', "Vlan100", "00:11:11:11:11:11", '1000') - vxlan_obj.check_vrf_routes(dvs, "2002::8/64", 'Vrf-RED', '7.7.7.7', tunnel_name, "00:11:11:11:11:11", '1000') - - print ("\tTest VRF IPv6 Route with Tunnel Nexthop Delete") - vxlan_obj.delete_vrf_route(dvs, "2002::8/64", 'Vrf-RED') - vxlan_obj.check_del_tunnel_nexthop(dvs, 'Vrf-RED', '7.7.7.7', tunnel_name, "00:11:11:11:11:11", '1000') - vxlan_obj.check_del_vrf_routes(dvs, "2002::8/64", 'Vrf-RED') - - print ("\n\nTesting IPv6 Route and Overlay Nexthop Update") - print ("\tTest VRF IPv6 Route with Tunnel Nexthop 7.7.7.7 Add") - vxlan_obj.fetch_exist_entries(dvs) - vxlan_obj.create_vrf_route(dvs, "2002::8/64", 'Vrf-RED', '7.7.7.7', "Vlan100", "00:11:11:11:11:11", '1000') - vxlan_obj.check_vrf_routes(dvs, "2002::8/64", 'Vrf-RED', '7.7.7.7', tunnel_name, "00:11:11:11:11:11", '1000') - - print ("\tTest Tunnel Nexthop change from 7.7.7.7 to 8.8.8.8") - vxlan_obj.create_vrf_route(dvs, "2002::8/64", 'Vrf-RED', '8.8.8.8', "Vlan100", "00:22:22:22:22:22", '1000') - vxlan_obj.check_vrf_routes(dvs, "2002::8/64", 'Vrf-RED', '8.8.8.8', tunnel_name, "00:22:22:22:22:22", '1000', 1) - - print ("\tTest Previous Tunnel Nexthop 7.7.7.7 is removed") - vxlan_obj.check_del_tunnel_nexthop(dvs, 'Vrf-RED', '7.7.7.7', tunnel_name, "00:11:11:11:11:11", '1000') - - print ("\tTest VRF IPv6 Route and Tunnel Nexthop 8.8.8.8 Delete") - vxlan_obj.fetch_exist_entries(dvs) - vxlan_obj.delete_vrf_route(dvs, "2002::8/64", 'Vrf-RED') - vxlan_obj.check_del_tunnel_nexthop(dvs, 'Vrf-RED', '8.8.8.8', tunnel_name, "00:22:22:22:22:22", '1000') - vxlan_obj.check_del_vrf_routes(dvs, "2002::8/64", 'Vrf-RED') - - print ("\n\nTest VRF IPv6 Route with ECMP Tunnel Nexthop Add and delete") - vxlan_obj.fetch_exist_entries(dvs) - - ecmp_nexthop_attr = [ - ("nexthop", "7.7.7.7,8.8.8.8"), - ("ifname", "Vlan100,Vlan100"), - ("vni_label", "1000,1000"), - ("router_mac", "00:11:11:11:11:11,00:22:22:22:22:22"), - ] - - print ("\tTest VRF IPv6 Route with ECMP Tunnel Nexthop [7.7.7.7 , 8.8.8.8] Add") - vxlan_obj.create_vrf_route_ecmp(dvs, "2002::8/64", 'Vrf-RED', ecmp_nexthop_attr) - - nh_count = 2 - ecmp_nhid_list = vxlan_obj.check_vrf_routes_ecmp(dvs, "2002::8/64", 'Vrf-RED', tunnel_name, nh_count) - assert nh_count == len(ecmp_nhid_list) - vxlan_obj.check_add_tunnel_nexthop(dvs, ecmp_nhid_list[0], '7.7.7.7', tunnel_name, '00:11:11:11:11:11', '1000') - vxlan_obj.check_add_tunnel_nexthop(dvs, ecmp_nhid_list[1], '8.8.8.8', tunnel_name, '00:22:22:22:22:22', '1000') - - print ("\tTest VRF IPv6 Route with ECMP Tunnel Nexthop [7.7.7.7 , 8.8.8.8] Delete") - vxlan_obj.fetch_exist_entries(dvs) - vxlan_obj.delete_vrf_route(dvs, "2002::8/64", 'Vrf-RED') - helper.check_deleted_object(self.adb, vxlan_obj.ASIC_NEXT_HOP, ecmp_nhid_list[0]) - helper.check_deleted_object(self.adb, vxlan_obj.ASIC_NEXT_HOP, ecmp_nhid_list[1]) - - vxlan_obj.check_vrf_routes_ecmp_nexthop_grp_del(dvs, 2) - vxlan_obj.check_del_vrf_routes(dvs, "2002::8/64", 'Vrf-RED') - - print ("\n\nTest VRF IPv6 Route with Tunnel Nexthop update from non-ECMP to ECMP") - print ("\tTest VRF IPv6 Route with Tunnel Nexthop 7.7.7.7 Add") - vxlan_obj.fetch_exist_entries(dvs) - vxlan_obj.create_vrf_route(dvs, "2002::8/64", 'Vrf-RED', '7.7.7.7', "Vlan100", "00:11:11:11:11:11", '1000') - vxlan_obj.check_vrf_routes(dvs, "2002::8/64", 'Vrf-RED', '7.7.7.7', tunnel_name, "00:11:11:11:11:11", '1000') - - print ("\tTest VRF IPv4 Route with ECMP Tunnel Nexthop [7.7.7.7 , 8.8.8.8] Udpate") - ecmp_nexthop_attr = [ - ("nexthop", "7.7.7.7,8.8.8.8"), - ("ifname", "Vlan100,Vlan100"), - ("vni_label", "1000,1000"), - ("router_mac", "00:11:11:11:11:11,00:22:22:22:22:22"), - ] - - vxlan_obj.create_vrf_route_ecmp(dvs, "2002::8/64", 'Vrf-RED', ecmp_nexthop_attr) - - nh_count = 2 - ecmp_nhid_list = vxlan_obj.check_vrf_routes_ecmp(dvs, "2002::8/64", 'Vrf-RED', tunnel_name, nh_count, 1) - assert nh_count == len(ecmp_nhid_list) - vxlan_obj.check_add_tunnel_nexthop(dvs, ecmp_nhid_list[0], '7.7.7.7', tunnel_name, '00:11:11:11:11:11', '1000') - vxlan_obj.check_add_tunnel_nexthop(dvs, ecmp_nhid_list[1], '8.8.8.8', tunnel_name, '00:22:22:22:22:22', '1000') - - print ("\n\nTest VRF IPv6 Route with Tunnel Nexthop update from ECMP to non-ECMP") - print ("\tTest VRF IPv6 Route with Tunnel Nexthop 8.8.8.8 Update") - vxlan_obj.create_vrf_route(dvs, "2002::8/64", 'Vrf-RED', '8.8.8.8', "Vlan100", "00:22:22:22:22:22", '1000') - vxlan_obj.check_vrf_routes(dvs, "2002::8/64", 'Vrf-RED', '8.8.8.8', tunnel_name, "00:22:22:22:22:22", '1000', 1) - - print ("\tTest Tunnel Nexthop 7.7.7.7 is deleted") - vxlan_obj.check_del_tunnel_nexthop(dvs, 'Vrf-RED', '7.7.7.7', tunnel_name, "00:11:11:11:11:11", '1000') - - print ("\tTest Tunnel Nexthop ECMP Group is deleted") - vxlan_obj.check_vrf_routes_ecmp_nexthop_grp_del(dvs, 2) - - print ("\tTest VRF IPv6 Route with Tunnel Nexthop 8.8.8.8 Delete") - vxlan_obj.fetch_exist_entries(dvs) - vxlan_obj.delete_vrf_route(dvs, "2002::8/64", 'Vrf-RED') - - vxlan_obj.check_del_tunnel_nexthop(dvs, 'Vrf-RED', '8.8.8.8', tunnel_name, "00:22:22:22:22:22", '1000') - vxlan_obj.check_del_vrf_routes(dvs, "2002::8/64", 'Vrf-RED') - - print ("\n\nTest DIP and SIP Tunnel Deletion ") - print ("\tTesting Tunnel Vrf Map Entry removal") - vxlan_obj.remove_vxlan_vrf_tunnel_map(dvs, 'Vrf-RED') - vxlan_obj.check_vxlan_tunnel_vrf_map_entry_remove(dvs, tunnel_name, 'Vrf-RED', '1000') - - print ("\tTesting Vlan 100 interface delete") - vxlan_obj.delete_vlan_interface(dvs, "Vlan100", "2001::8/64") - vxlan_obj.check_del_router_interface(dvs, "Vlan100") - - print ("\tTesting Tunnel Map entry removal") - vxlan_obj.check_vxlan_tunnel_map_entry(dvs, tunnel_name, vlanlist, vnilist) - vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') - vxlan_obj.check_vxlan_tunnel_map_entry_delete(dvs, tunnel_name, vlanlist, vnilist) - - print ("\tTesting SIP Tunnel Deletion") - vxlan_obj.remove_vxlan_tunnel(dvs, tunnel_name) - vxlan_obj.remove_evpn_nvo(dvs, 'nvo1') - time.sleep(2) - vxlan_obj.check_vxlan_sip_tunnel_delete(dvs, tunnel_name, '6.6.6.6') - vxlan_obj.remove_vrf(dvs, "Vrf-RED") - vxlan_obj.remove_vlan_member(dvs, "100", "Ethernet24") - vxlan_obj.remove_vlan(dvs, "100") - - - def test_vrf_state_db_update(self, dvs, testlog): - vxlan_obj = self.get_vxlan_obj() - helper = self.get_vxlan_helper() - - self.setup_db(dvs) - tunnel_name = 'tunnel_2' - map_name = 'map_1000_100' - vrf_map_name = 'evpn_map_1000_Vrf-RED' - - vxlan_obj.fetch_exist_entries(dvs) - - - vxlan_obj.create_vrf(dvs, "Vrf-RED") - vxlan_obj.create_vxlan_vrf_tunnel_map(dvs, 'Vrf-RED', '1000') - - time.sleep(2) - #adding nvo after - vxlan_obj.create_vxlan_tunnel(dvs, tunnel_name, '6.6.6.6') - vxlan_obj.create_evpn_nvo(dvs, 'nvo1', tunnel_name) - exp_attr = [ - ("state", "ok"), - ] - helper.check_object(self.sdb, "VRF_OBJECT_TABLE", 'Vrf-RED', exp_attr) - vxlan_obj.remove_vxlan_vrf_tunnel_map(dvs, 'Vrf-RED') - vxlan_obj.remove_vrf(dvs, "Vrf-RED") - vxlan_obj.remove_vxlan_tunnel(dvs, tunnel_name) - vxlan_obj.remove_evpn_nvo(dvs, 'nvo1') - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_evpn_l3_vxlan_p2mp.py b/tests/test_evpn_l3_vxlan_p2mp.py deleted file mode 100644 index f3041979eb..0000000000 --- a/tests/test_evpn_l3_vxlan_p2mp.py +++ /dev/null @@ -1,649 +0,0 @@ -from swsscommon import swsscommon -from evpn_tunnel import VxlanTunnel,VxlanEvpnHelper -import time - -DVS_ENV = ["HWSKU=Mellanox-SN2700"] - -class TestL3VxlanP2MP(object): - - def get_vxlan_obj(self): - return VxlanTunnel() - - def get_vxlan_helper(self): - return VxlanEvpnHelper() - - def setup_db(self, dvs): - self.pdb = swsscommon.DBConnector(0, dvs.redis_sock, 0) - self.adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - self.cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) - -# Test 1 - Create and Delete SIP Tunnel and VRF VNI Map entries -# @pytest.mark.skip(reason="Starting Route Orch, VRF Orch to be merged") -# @pytest.mark.dev_sanity - def test_sip_tunnel_vrf_vni_map(self, dvs, testlog): - vxlan_obj = self.get_vxlan_obj() - helper = self.get_vxlan_helper() - - self.setup_db(dvs) - tunnel_name = 'tunnel_2' - map_name = 'map_1000_100' - vrf_map_name = 'evpn_map_1000_Vrf-RED' - - vxlan_obj.fetch_exist_entries(dvs) - - print ("\n\nTesting Create and Delete SIP Tunnel and VRF VNI Map entries") - print ("\tCreate SIP Tunnel") - vxlan_obj.create_vlan1(dvs,"Vlan100") - vxlan_obj.create_vxlan_tunnel(dvs, tunnel_name, '6.6.6.6') - vxlan_obj.create_evpn_nvo(dvs, 'nvo1', tunnel_name) - - vxlan_obj.create_vrf(dvs, "Vrf-RED") - vxlan_obj.create_vxlan_vrf_tunnel_map(dvs, 'Vrf-RED', '1000') - - print ("\tCreate Vlan-VNI map and VRF-VNI map") - vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') - - print ("\tTesting VRF-VNI map in APP DB") - vlanlist = ['100'] - vnilist = ['1000'] - - exp_attrs = [ - ("vni", "1000"), - ] - exp_attr = {} - for an in range(len(exp_attrs)): - exp_attr[exp_attrs[an][0]] = exp_attrs[an][1] - - helper.check_object(self.pdb, "VRF_TABLE", 'Vrf-RED', exp_attr) - - exp_attrs1 = [ - ("vni", "1000"), - ("vlan", "Vlan100"), - ] - exp_attr1 = {} - for an in range(len(exp_attrs1)): - exp_attr1[exp_attrs1[an][0]] = exp_attrs1[an][1] - - helper.check_object(self.pdb, "VXLAN_VRF_TABLE", "%s:%s" % (tunnel_name, vrf_map_name), exp_attr1) - - print ("\tTesting SIP Tunnel Creation") - vxlan_obj.check_vxlan_sip_tunnel(dvs, tunnel_name, '6.6.6.6', vlanlist, vnilist, ignore_bp=False, tunnel_map_entry_count=2) - - print ("\tTesting Tunnel Vlan VNI Map Entry") - vxlan_obj.check_vxlan_tunnel_map_entry_removed(dvs, tunnel_name, vlanlist, vnilist) - - print ("\tTesting Tunnel VRF VNI Map Entry") - vxlan_obj.check_vxlan_tunnel_vrf_map_entry(dvs, tunnel_name, 'Vrf-RED', '1000') - - print ("\tTesting Tunnel VRF VNI Map Entry removal") - vxlan_obj.remove_vxlan_vrf_tunnel_map(dvs, 'Vrf-RED') - vxlan_obj.remove_vrf(dvs, "Vrf-RED") - vxlan_obj.check_vxlan_tunnel_vrf_map_entry_remove(dvs, tunnel_name, 'Vrf-RED', '1000') - - print ("\tTesting Tunnel Vlan VNI Map entry removal") - vxlan_obj.check_vxlan_tunnel_map_entry(dvs, tunnel_name, vlanlist, vnilist) - vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') - vxlan_obj.check_vxlan_tunnel_map_entry_delete(dvs, tunnel_name, vlanlist, vnilist) - - print ("\tTesting SIP Tunnel Deletion") - vxlan_obj.remove_vxlan_tunnel(dvs, tunnel_name) - vxlan_obj.remove_evpn_nvo(dvs, 'nvo1') - time.sleep(2) - vxlan_obj.check_vxlan_sip_tunnel_delete(dvs, tunnel_name, '6.6.6.6', ignore_bp=False) - vxlan_obj.remove_vlan(dvs, "100") - - -# Test 2 - Remote end point add -# @pytest.mark.skip(reason="Starting Route Orch, VRF Orch to be merged") -# @pytest.mark.dev_sanity - def test_prefix_route_create_remote_endpoint(self, dvs, testlog): - vxlan_obj = self.get_vxlan_obj() - helper = self.get_vxlan_helper() - - self.setup_db(dvs) - tunnel_name = 'tunnel_2' - map_name = 'map_1000_100' - vrf_map_name = 'evpn_map_1000_Vrf-RED' - vxlan_obj.fetch_exist_entries(dvs) - - print ("\tCreate SIP Tunnel") - vlan_ids = vxlan_obj.helper.get_exist_entries(dvs, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - vlan_oid = vxlan_obj.create_vlan(dvs,"Vlan100", vlan_ids) - vxlan_obj.create_vxlan_tunnel(dvs, tunnel_name, '6.6.6.6') - vxlan_obj.create_evpn_nvo(dvs, 'nvo1', tunnel_name) - - print ("\tCreate Vlan-VNI map and VRF-VNI map") - vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') - - print ("\tTesting VRF-VNI map in APP DB") - vxlan_obj.create_vrf(dvs, "Vrf-RED") - vxlan_obj.create_vxlan_vrf_tunnel_map(dvs, 'Vrf-RED', '1000') - - vlanlist = ['100'] - vnilist = ['1000'] - - exp_attrs = [ - ("vni", "1000"), - ] - exp_attr = {} - for an in range(len(exp_attrs)): - exp_attr[exp_attrs[an][0]] = exp_attrs[an][1] - - helper.check_object(self.pdb, "VRF_TABLE", 'Vrf-RED', exp_attr) - - exp_attrs1 = [ - ("vni", "1000"), - ("vlan", "Vlan100"), - ] - exp_attr1 = {} - for an in range(len(exp_attrs1)): - exp_attr1[exp_attrs1[an][0]] = exp_attrs1[an][1] - - helper.check_object(self.pdb, "VXLAN_VRF_TABLE", "%s:%s" % (tunnel_name, vrf_map_name), exp_attr1) - - print ("\tTesting SIP Tunnel Creation") - vxlan_obj.check_vxlan_sip_tunnel(dvs, tunnel_name, '6.6.6.6', vlanlist, vnilist, ignore_bp=False, tunnel_map_entry_count=2) - - print ("\tTesting Tunnel Vlan Map Entry") - vxlan_obj.check_vxlan_tunnel_map_entry_removed(dvs, tunnel_name, vlanlist, vnilist) - - print ("\tTesting Tunnel Vrf Map Entry") - vxlan_obj.check_vxlan_tunnel_vrf_map_entry(dvs, tunnel_name, 'Vrf-RED', '1000') - - print ("\tTesting VLAN 100 interface creation") - vxlan_obj.create_vlan_interface(dvs, "Vlan100", "Ethernet24", "Vrf-RED", "100.100.3.1/24") - vxlan_obj.check_router_interface(dvs, 'Vrf-RED', vlan_oid, 2) - - print ("\tTest VRF IPv4 Route with Tunnel Nexthop Add") - vxlan_obj.fetch_exist_entries(dvs) - vxlan_obj.create_vrf_route(dvs, "80.80.1.0/24", 'Vrf-RED', '7.7.7.7', "Vlan100", "00:11:11:11:11:11", '1000') - vxlan_obj.check_vrf_routes(dvs, "80.80.1.0/24", 'Vrf-RED', '7.7.7.7', tunnel_name, "00:11:11:11:11:11", '1000') - - print ("\tTest VRF IPv4 Route with Tunnel Nexthop Delete") - vxlan_obj.delete_vrf_route(dvs, "80.80.1.0/24", 'Vrf-RED') - vxlan_obj.check_del_tunnel_nexthop(dvs, 'Vrf-RED', '7.7.7.7', tunnel_name, "00:11:11:11:11:11", '1000') - vxlan_obj.check_del_vrf_routes(dvs, "80.80.1.0/24", 'Vrf-RED') - - print ("\tTesting Tunnel Vrf Map Entry removal") - vxlan_obj.remove_vxlan_vrf_tunnel_map(dvs, 'Vrf-RED') - vxlan_obj.check_vxlan_tunnel_vrf_map_entry_remove(dvs, tunnel_name, 'Vrf-RED', '1000') - - print ("\tTesting Vlan 100 interface delete") - vxlan_obj.delete_vlan_interface(dvs, "Vlan100", "100.100.3.1/24") - vxlan_obj.check_del_router_interface(dvs, "Vlan100") - - print ("\tTesting Tunnel Map entry removal") - vxlan_obj.check_vxlan_tunnel_map_entry(dvs, tunnel_name, vlanlist, vnilist) - vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') - vxlan_obj.check_vxlan_tunnel_map_entry_delete(dvs, tunnel_name, vlanlist, vnilist) - - print ("\tTesting SIP Tunnel Deletion") - vxlan_obj.remove_vxlan_tunnel(dvs, tunnel_name) - vxlan_obj.remove_evpn_nvo(dvs, 'nvo1') - time.sleep(2) - vxlan_obj.check_vxlan_sip_tunnel_delete(dvs, tunnel_name, '6.6.6.6', ignore_bp=False) - vxlan_obj.remove_vrf(dvs, "Vrf-RED") - vxlan_obj.remove_vlan_member(dvs, "100", "Ethernet24") - vxlan_obj.remove_vlan(dvs, "100") - - -# Test 3 - Create and Delete remote end point and Test IPv4 route and overlay nexthop add and delete -# @pytest.mark.dev_sanity - def test_remote_ipv4_routes(self, dvs, testlog): - vxlan_obj = self.get_vxlan_obj() - helper = self.get_vxlan_helper() - - self.setup_db(dvs) - tunnel_name = 'tunnel_2' - map_name = 'map_1000_100' - vrf_map_name = 'evpn_map_1000_Vrf-RED' - vxlan_obj.fetch_exist_entries(dvs) - - print ("\n\nTesting IPv4 Route and Overlay Nexthop Add and Delete") - print ("\tCreate SIP Tunnel") - vxlan_obj.create_vlan1(dvs,"Vlan100") - vxlan_obj.check_vlan_obj(dvs, "100") - vxlan_obj.create_vxlan_tunnel(dvs, tunnel_name, '6.6.6.6') - vxlan_obj.create_evpn_nvo(dvs, 'nvo1', tunnel_name) - - print ("\tCreate Vlan-VNI map and VRF-VNI map") - vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') - - vxlan_obj.create_vrf(dvs, "Vrf-RED") - vxlan_obj.create_vxlan_vrf_tunnel_map(dvs, 'Vrf-RED', '1000') - - print ("\tTesting VRF-VNI map in APP DB") - vlanlist = ['100'] - vnilist = ['1000'] - - exp_attrs = [ - ("vni", "1000"), - ] - exp_attr = {} - for an in range(len(exp_attrs)): - exp_attr[exp_attrs[an][0]] = exp_attrs[an][1] - - helper.check_object(self.pdb, "VRF_TABLE", 'Vrf-RED', exp_attr) - - exp_attrs1 = [ - ("vni", "1000"), - ("vlan", "Vlan100"), - ] - exp_attr1 = {} - for an in range(len(exp_attrs1)): - exp_attr1[exp_attrs1[an][0]] = exp_attrs1[an][1] - - helper.check_object(self.pdb, "VXLAN_VRF_TABLE", "%s:%s" % (tunnel_name, vrf_map_name), exp_attr1) - - print ("\tTesting SIP Tunnel Creation") - vxlan_obj.check_vxlan_sip_tunnel(dvs, tunnel_name, '6.6.6.6', vlanlist, vnilist, ignore_bp=False, tunnel_map_entry_count=2) - - print ("\tTesting Tunnel Vlan Map Entry") - vxlan_obj.check_vxlan_tunnel_map_entry_removed(dvs, tunnel_name, vlanlist, vnilist) - - print ("\tTesting Tunnel Vrf Map Entry") - vxlan_obj.check_vxlan_tunnel_vrf_map_entry(dvs, tunnel_name, 'Vrf-RED', '1000') - - print ("\tTesting VLAN 100 interface creation") - vxlan_obj.create_vlan_interface(dvs, "Vlan100", "Ethernet24", "Vrf-RED", "100.100.3.1/24") - vxlan_obj.check_router_interface(dvs, 'Vrf-RED', vxlan_obj.vlan_id_map['100'], 2) - - print ("\tTest VRF IPv4 Route with Tunnel Nexthop 7.7.7.7 Add") - vxlan_obj.fetch_exist_entries(dvs) - vxlan_obj.create_vrf_route(dvs, "80.80.1.0/24", 'Vrf-RED', '7.7.7.7', "Vlan100", "00:11:11:11:11:11", '1000') - vxlan_obj.check_vrf_routes(dvs, "80.80.1.0/24", 'Vrf-RED', '7.7.7.7', tunnel_name, "00:11:11:11:11:11", '1000') - - print ("\tTest VRF IPv4 Route with Tunnel Nexthop 7.7.7.7 Delete") - vxlan_obj.delete_vrf_route(dvs, "80.80.1.0/24", 'Vrf-RED') - vxlan_obj.check_del_tunnel_nexthop(dvs, 'Vrf-RED', '7.7.7.7', tunnel_name, "00:11:11:11:11:11", '1000') - vxlan_obj.check_del_vrf_routes(dvs, "80.80.1.0/24", 'Vrf-RED') - - print ("\n\nTesting IPv4 Route and Overlay Nexthop Update") - print ("\tTest VRF IPv4 Route with Tunnel Nexthop 7.7.7.7 Add") - vxlan_obj.fetch_exist_entries(dvs) - vxlan_obj.create_vrf_route(dvs, "80.80.1.0/24", 'Vrf-RED', '7.7.7.7', "Vlan100", "00:11:11:11:11:11", '1000') - vxlan_obj.check_vrf_routes(dvs, "80.80.1.0/24", 'Vrf-RED', '7.7.7.7', tunnel_name, "00:11:11:11:11:11", '1000') - - print ("\tTest Tunnel Nexthop change from 7.7.7.7 to 8.8.8.8") - vxlan_obj.create_vrf_route(dvs, "80.80.1.0/24", 'Vrf-RED', '8.8.8.8', "Vlan100", "00:22:22:22:22:22", '1000') - vxlan_obj.check_vrf_routes(dvs, "80.80.1.0/24", 'Vrf-RED', '8.8.8.8', tunnel_name, "00:22:22:22:22:22", '1000', 1) - - print ("\tTest Previous Tunnel Nexthop 7.7.7.7 is removed") - vxlan_obj.check_del_tunnel_nexthop(dvs, 'Vrf-RED', '7.7.7.7', tunnel_name, "00:11:11:11:11:11", '1000') - - print ("\tTest VRF IPv4 Route and Tunnel Nexthop 8.8.8.8 Delete") - vxlan_obj.fetch_exist_entries(dvs) - vxlan_obj.delete_vrf_route(dvs, "80.80.1.0/24", 'Vrf-RED') - vxlan_obj.check_del_tunnel_nexthop(dvs, 'Vrf-RED', '8.8.8.8', tunnel_name, "00:22:22:22:22:22", '1000') - vxlan_obj.check_del_vrf_routes(dvs, "80.80.1.0/24", 'Vrf-RED') - - print ("\n\nTest VRF IPv4 Route with ECMP Tunnel Nexthop Add and Delete") - vxlan_obj.fetch_exist_entries(dvs) - - ecmp_nexthop_attr = [ - ("nexthop", "7.7.7.7,8.8.8.8"), - ("ifname", "Vlan100,Vlan100"), - ("vni_label", "1000,1000"), - ("router_mac", "00:11:11:11:11:11,00:22:22:22:22:22"), - ] - - print ("\tTest VRF IPv4 Route with ECMP Tunnel Nexthop [7.7.7.7 , 8.8.8.8] Add") - vxlan_obj.create_vrf_route_ecmp(dvs, "80.80.1.0/24", 'Vrf-RED', ecmp_nexthop_attr) - - nh_count = 2 - ecmp_nhid_list = vxlan_obj.check_vrf_routes_ecmp(dvs, "80.80.1.0/24", 'Vrf-RED', tunnel_name, nh_count) - assert nh_count == len(ecmp_nhid_list) - vxlan_obj.check_add_tunnel_nexthop(dvs, ecmp_nhid_list[0], '7.7.7.7', tunnel_name, '00:11:11:11:11:11', '1000') - vxlan_obj.check_add_tunnel_nexthop(dvs, ecmp_nhid_list[1], '8.8.8.8', tunnel_name, '00:22:22:22:22:22', '1000') - - print ("\tTest VRF IPv4 Route with ECMP Tunnel Nexthop [7.7.7.7 , 8.8.8.8] Delete") - vxlan_obj.fetch_exist_entries(dvs) - vxlan_obj.delete_vrf_route(dvs, "80.80.1.0/24", 'Vrf-RED') - helper.check_deleted_object(self.adb, vxlan_obj.ASIC_NEXT_HOP, ecmp_nhid_list[0]) - helper.check_deleted_object(self.adb, vxlan_obj.ASIC_NEXT_HOP, ecmp_nhid_list[1]) - - vxlan_obj.check_vrf_routes_ecmp_nexthop_grp_del(dvs, 2) - vxlan_obj.check_del_vrf_routes(dvs, "80.80.1.0/24", 'Vrf-RED') - - print ("\n\nTest VRF IPv4 Route with Tunnel Nexthop update from non-ECMP to ECMP") - print ("\tTest VRF IPv4 Route with Tunnel Nexthop 7.7.7.7 Add") - vxlan_obj.fetch_exist_entries(dvs) - vxlan_obj.create_vrf_route(dvs, "80.80.1.0/24", 'Vrf-RED', '7.7.7.7', "Vlan100", "00:11:11:11:11:11", '1000') - vxlan_obj.check_vrf_routes(dvs, "80.80.1.0/24", 'Vrf-RED', '7.7.7.7', tunnel_name, "00:11:11:11:11:11", '1000') - - ecmp_nexthop_attr = [ - ("nexthop", "7.7.7.7,8.8.8.8"), - ("ifname", "Vlan100,Vlan100"), - ("vni_label", "1000,1000"), - ("router_mac", "00:11:11:11:11:11,00:22:22:22:22:22"), - ] - - print ("\tTest VRF IPv4 Route with ECMP Tunnel Nexthop [7.7.7.7 , 8.8.8.8] Udpate") - vxlan_obj.create_vrf_route_ecmp(dvs, "80.80.1.0/24", 'Vrf-RED', ecmp_nexthop_attr) - - nh_count = 2 - ecmp_nhid_list = vxlan_obj.check_vrf_routes_ecmp(dvs, "80.80.1.0/24", 'Vrf-RED', tunnel_name, nh_count, 1) - assert nh_count == len(ecmp_nhid_list) - vxlan_obj.check_add_tunnel_nexthop(dvs, ecmp_nhid_list[0], '7.7.7.7', tunnel_name, '00:11:11:11:11:11', '1000') - vxlan_obj.check_add_tunnel_nexthop(dvs, ecmp_nhid_list[1], '8.8.8.8', tunnel_name, '00:22:22:22:22:22', '1000') - - print ("\n\nTest VRF IPv4 Route with Tunnel Nexthop update from ECMP to non-ECMP") - print ("\tTest VRF IPv4 Route with Tunnel Nexthop 8.8.8.8 Update") - vxlan_obj.create_vrf_route(dvs, "80.80.1.0/24", 'Vrf-RED', '8.8.8.8', "Vlan100", "00:22:22:22:22:22", '1000') - vxlan_obj.check_vrf_routes(dvs, "80.80.1.0/24", 'Vrf-RED', '8.8.8.8', tunnel_name, "00:22:22:22:22:22", '1000', 1) - - print ("\tTest Tunnel Nexthop 7.7.7.7 is deleted") - vxlan_obj.check_del_tunnel_nexthop(dvs, 'Vrf-RED', '7.7.7.7', tunnel_name, "00:11:11:11:11:11", '1000') - - print ("\tTest Tunnel Nexthop ECMP Group is deleted") - vxlan_obj.check_vrf_routes_ecmp_nexthop_grp_del(dvs, 2) - - print ("\tTest VRF IPv4 Route with Tunnel Nexthop 8.8.8.8 Delete") - vxlan_obj.fetch_exist_entries(dvs) - vxlan_obj.delete_vrf_route(dvs, "80.80.1.0/24", 'Vrf-RED') - - vxlan_obj.check_del_tunnel_nexthop(dvs, 'Vrf-RED', '8.8.8.8', tunnel_name, "00:22:22:22:22:22", '1000') - vxlan_obj.check_del_vrf_routes(dvs, "80.80.1.0/24", 'Vrf-RED') - - print ("\n\nTest Remote end point remove and SIP Tunnel Deletion ") - print ("\tTesting Tunnel Vrf VNI Map Entry removal") - vxlan_obj.remove_vxlan_vrf_tunnel_map(dvs, 'Vrf-RED') - vxlan_obj.check_vxlan_tunnel_vrf_map_entry_remove(dvs, tunnel_name, 'Vrf-RED', '1000') - - print ("\tTesting Vlan 100 interface delete") - vxlan_obj.delete_vlan_interface(dvs, "Vlan100", "100.100.3.1/24") - vxlan_obj.check_del_router_interface(dvs, "Vlan100") - - print ("\tTesting Tunnel Map entry removal") - vxlan_obj.check_vxlan_tunnel_map_entry(dvs, tunnel_name, vlanlist, vnilist) - vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') - vxlan_obj.check_vxlan_tunnel_map_entry_delete(dvs, tunnel_name, vlanlist, vnilist) - - print ("\tTesting SIP Tunnel Deletion") - vxlan_obj.remove_vxlan_tunnel(dvs, tunnel_name) - vxlan_obj.remove_evpn_nvo(dvs, 'nvo1') - time.sleep(2) - vxlan_obj.check_vxlan_sip_tunnel_delete(dvs, tunnel_name, '6.6.6.6', ignore_bp=False) - vxlan_obj.remove_vrf(dvs, "Vrf-RED") - vxlan_obj.remove_vlan_member(dvs, "100", "Ethernet24") - vxlan_obj.remove_vlan(dvs, "100") - - -# Test 4 - Create and Delete remote endpoint and Test IPv6 route and overlay nexthop add and delete -# @pytest.mark.skip(reason="Starting Route Orch, VRF Orch to be merged") -# @pytest.mark.dev_sanity - def test_remote_ipv6_routes(self, dvs, testlog): - vxlan_obj = self.get_vxlan_obj() - helper = self.get_vxlan_helper() - - self.setup_db(dvs) - tunnel_name = 'tunnel_2' - map_name = 'map_1000_100' - vrf_map_name = 'evpn_map_1000_Vrf-RED' - vxlan_obj.fetch_exist_entries(dvs) - - print ("\n\nTesting IPv6 Route and Overlay Nexthop Add and Delete") - print ("\tCreate SIP Tunnel") - vxlan_obj.create_vlan1(dvs,"Vlan100") - vxlan_obj.check_vlan_obj(dvs, "100") - vxlan_obj.create_vxlan_tunnel(dvs, tunnel_name, '6.6.6.6') - vxlan_obj.create_evpn_nvo(dvs, 'nvo1', tunnel_name) - - print ("\tCreate Vlan-VNI map and VRF-VNI map") - vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') - - print ("\tTesting VRF-VNI map in APP DB") - vxlan_obj.create_vrf(dvs, "Vrf-RED") - vxlan_obj.create_vxlan_vrf_tunnel_map(dvs, 'Vrf-RED', '1000') - - vlanlist = ['100'] - vnilist = ['1000'] - - exp_attrs = [ - ("vni", "1000"), - ] - exp_attr = {} - for an in range(len(exp_attrs)): - exp_attr[exp_attrs[an][0]] = exp_attrs[an][1] - - print ("\tCheck VRF Table in APP DB") - helper.check_object(self.pdb, "VRF_TABLE", 'Vrf-RED', exp_attr) - - exp_attrs1 = [ - ("vni", "1000"), - ("vlan", "Vlan100"), - ] - exp_attr1 = {} - for an in range(len(exp_attrs1)): - exp_attr1[exp_attrs1[an][0]] = exp_attrs1[an][1] - - helper.check_object(self.pdb, "VXLAN_VRF_TABLE", "%s:%s" % (tunnel_name, vrf_map_name), exp_attr1) - - print ("\tTesting SIP Tunnel Creation") - vxlan_obj.check_vxlan_sip_tunnel(dvs, tunnel_name, '6.6.6.6', vlanlist, vnilist, ignore_bp=False, tunnel_map_entry_count=2) - - print ("\tTesting Tunnel Vlan Map Entry") - vxlan_obj.check_vxlan_tunnel_map_entry_removed(dvs, tunnel_name, vlanlist, vnilist) - - print ("\tTesting Tunnel Vrf Map Entry") - vxlan_obj.check_vxlan_tunnel_vrf_map_entry(dvs, tunnel_name, 'Vrf-RED', '1000') - - vxlan_obj.fetch_exist_entries(dvs) - print ("\tTesting VLAN 100 interface creation") - vxlan_obj.create_vlan_interface(dvs, "Vlan100", "Ethernet24", "Vrf-RED", "2001::8/64") - vxlan_obj.check_router_interface(dvs, 'Vrf-RED', vxlan_obj.vlan_id_map['100'], 2) - - print ("\tTest VRF IPv6 Route with Tunnel Nexthop Add") - vxlan_obj.fetch_exist_entries(dvs) - vxlan_obj.create_vrf_route(dvs, "2002::8/64", 'Vrf-RED', '7.7.7.7', "Vlan100", "00:11:11:11:11:11", '1000') - vxlan_obj.check_vrf_routes(dvs, "2002::8/64", 'Vrf-RED', '7.7.7.7', tunnel_name, "00:11:11:11:11:11", '1000') - - print ("\tTest VRF IPv6 Route with Tunnel Nexthop Delete") - vxlan_obj.delete_vrf_route(dvs, "2002::8/64", 'Vrf-RED') - vxlan_obj.check_del_tunnel_nexthop(dvs, 'Vrf-RED', '7.7.7.7', tunnel_name, "00:11:11:11:11:11", '1000') - vxlan_obj.check_del_vrf_routes(dvs, "2002::8/64", 'Vrf-RED') - - print ("\n\nTesting IPv6 Route and Overlay Nexthop Update") - print ("\tTest VRF IPv6 Route with Tunnel Nexthop 7.7.7.7 Add") - vxlan_obj.fetch_exist_entries(dvs) - vxlan_obj.create_vrf_route(dvs, "2002::8/64", 'Vrf-RED', '7.7.7.7', "Vlan100", "00:11:11:11:11:11", '1000') - vxlan_obj.check_vrf_routes(dvs, "2002::8/64", 'Vrf-RED', '7.7.7.7', tunnel_name, "00:11:11:11:11:11", '1000') - - print ("\tTest Tunnel Nexthop change from 7.7.7.7 to 8.8.8.8") - vxlan_obj.create_vrf_route(dvs, "2002::8/64", 'Vrf-RED', '8.8.8.8', "Vlan100", "00:22:22:22:22:22", '1000') - vxlan_obj.check_vrf_routes(dvs, "2002::8/64", 'Vrf-RED', '8.8.8.8', tunnel_name, "00:22:22:22:22:22", '1000', 1) - - print ("\tTest Previous Tunnel Nexthop 7.7.7.7 is removed") - vxlan_obj.check_del_tunnel_nexthop(dvs, 'Vrf-RED', '7.7.7.7', tunnel_name, "00:11:11:11:11:11", '1000') - - print ("\tTest VRF IPv6 Route and Tunnel Nexthop 8.8.8.8 Delete") - vxlan_obj.fetch_exist_entries(dvs) - vxlan_obj.delete_vrf_route(dvs, "2002::8/64", 'Vrf-RED') - vxlan_obj.check_del_tunnel_nexthop(dvs, 'Vrf-RED', '8.8.8.8', tunnel_name, "00:22:22:22:22:22", '1000') - vxlan_obj.check_del_vrf_routes(dvs, "2002::8/64", 'Vrf-RED') - - print ("\n\nTest VRF IPv6 Route with ECMP Tunnel Nexthop Add and delete") - vxlan_obj.fetch_exist_entries(dvs) - - ecmp_nexthop_attr = [ - ("nexthop", "7.7.7.7,8.8.8.8"), - ("ifname", "Vlan100,Vlan100"), - ("vni_label", "1000,1000"), - ("router_mac", "00:11:11:11:11:11,00:22:22:22:22:22"), - ] - - print ("\tTest VRF IPv6 Route with ECMP Tunnel Nexthop [7.7.7.7 , 8.8.8.8] Add") - vxlan_obj.create_vrf_route_ecmp(dvs, "2002::8/64", 'Vrf-RED', ecmp_nexthop_attr) - - nh_count = 2 - ecmp_nhid_list = vxlan_obj.check_vrf_routes_ecmp(dvs, "2002::8/64", 'Vrf-RED', tunnel_name, nh_count) - assert nh_count == len(ecmp_nhid_list) - vxlan_obj.check_add_tunnel_nexthop(dvs, ecmp_nhid_list[0], '7.7.7.7', tunnel_name, '00:11:11:11:11:11', '1000') - vxlan_obj.check_add_tunnel_nexthop(dvs, ecmp_nhid_list[1], '8.8.8.8', tunnel_name, '00:22:22:22:22:22', '1000') - - print ("\tTest VRF IPv6 Route with ECMP Tunnel Nexthop [7.7.7.7 , 8.8.8.8] Delete") - vxlan_obj.fetch_exist_entries(dvs) - vxlan_obj.delete_vrf_route(dvs, "2002::8/64", 'Vrf-RED') - helper.check_deleted_object(self.adb, vxlan_obj.ASIC_NEXT_HOP, ecmp_nhid_list[0]) - helper.check_deleted_object(self.adb, vxlan_obj.ASIC_NEXT_HOP, ecmp_nhid_list[1]) - - vxlan_obj.check_vrf_routes_ecmp_nexthop_grp_del(dvs, 2) - vxlan_obj.check_del_vrf_routes(dvs, "2002::8/64", 'Vrf-RED') - - print ("\n\nTest VRF IPv6 Route with Tunnel Nexthop update from non-ECMP to ECMP") - print ("\tTest VRF IPv6 Route with Tunnel Nexthop 7.7.7.7 Add") - vxlan_obj.fetch_exist_entries(dvs) - vxlan_obj.create_vrf_route(dvs, "2002::8/64", 'Vrf-RED', '7.7.7.7', "Vlan100", "00:11:11:11:11:11", '1000') - vxlan_obj.check_vrf_routes(dvs, "2002::8/64", 'Vrf-RED', '7.7.7.7', tunnel_name, "00:11:11:11:11:11", '1000') - - print ("\tTest VRF IPv4 Route with ECMP Tunnel Nexthop [7.7.7.7 , 8.8.8.8] Udpate") - ecmp_nexthop_attr = [ - ("nexthop", "7.7.7.7,8.8.8.8"), - ("ifname", "Vlan100,Vlan100"), - ("vni_label", "1000,1000"), - ("router_mac", "00:11:11:11:11:11,00:22:22:22:22:22"), - ] - - vxlan_obj.create_vrf_route_ecmp(dvs, "2002::8/64", 'Vrf-RED', ecmp_nexthop_attr) - - nh_count = 2 - ecmp_nhid_list = vxlan_obj.check_vrf_routes_ecmp(dvs, "2002::8/64", 'Vrf-RED', tunnel_name, nh_count, 1) - assert nh_count == len(ecmp_nhid_list) - vxlan_obj.check_add_tunnel_nexthop(dvs, ecmp_nhid_list[0], '7.7.7.7', tunnel_name, '00:11:11:11:11:11', '1000') - vxlan_obj.check_add_tunnel_nexthop(dvs, ecmp_nhid_list[1], '8.8.8.8', tunnel_name, '00:22:22:22:22:22', '1000') - - print ("\n\nTest VRF IPv6 Route with Tunnel Nexthop update from ECMP to non-ECMP") - print ("\tTest VRF IPv6 Route with Tunnel Nexthop 8.8.8.8 Update") - vxlan_obj.create_vrf_route(dvs, "2002::8/64", 'Vrf-RED', '8.8.8.8', "Vlan100", "00:22:22:22:22:22", '1000') - vxlan_obj.check_vrf_routes(dvs, "2002::8/64", 'Vrf-RED', '8.8.8.8', tunnel_name, "00:22:22:22:22:22", '1000', 1) - - print ("\tTest Tunnel Nexthop 7.7.7.7 is deleted") - vxlan_obj.check_del_tunnel_nexthop(dvs, 'Vrf-RED', '7.7.7.7', tunnel_name, "00:11:11:11:11:11", '1000') - - print ("\tTest Tunnel Nexthop ECMP Group is deleted") - vxlan_obj.check_vrf_routes_ecmp_nexthop_grp_del(dvs, 2) - - print ("\tTest VRF IPv6 Route with Tunnel Nexthop 8.8.8.8 Delete") - vxlan_obj.fetch_exist_entries(dvs) - vxlan_obj.delete_vrf_route(dvs, "2002::8/64", 'Vrf-RED') - - vxlan_obj.check_del_tunnel_nexthop(dvs, 'Vrf-RED', '8.8.8.8', tunnel_name, "00:22:22:22:22:22", '1000') - vxlan_obj.check_del_vrf_routes(dvs, "2002::8/64", 'Vrf-RED') - - print ("\n\nTest remote endpoint and SIP Tunnel Deletion ") - print ("\tTesting Tunnel Vrf Map Entry removal") - vxlan_obj.remove_vxlan_vrf_tunnel_map(dvs, 'Vrf-RED') - vxlan_obj.check_vxlan_tunnel_vrf_map_entry_remove(dvs, tunnel_name, 'Vrf-RED', '1000') - - print ("\tTesting Vlan 100 interface delete") - vxlan_obj.delete_vlan_interface(dvs, "Vlan100", "2001::8/64") - vxlan_obj.check_del_router_interface(dvs, "Vlan100") - - print ("\tTesting Tunnel Map entry removal") - vxlan_obj.check_vxlan_tunnel_map_entry(dvs, tunnel_name, vlanlist, vnilist) - vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') - vxlan_obj.check_vxlan_tunnel_map_entry_delete(dvs, tunnel_name, vlanlist, vnilist) - - print ("\tTesting SIP Tunnel Deletion") - vxlan_obj.remove_vxlan_tunnel(dvs, tunnel_name) - vxlan_obj.remove_evpn_nvo(dvs, 'nvo1') - time.sleep(2) - vxlan_obj.check_vxlan_sip_tunnel_delete(dvs, tunnel_name, '6.6.6.6', ignore_bp=False) - vxlan_obj.remove_vrf(dvs, "Vrf-RED") - vxlan_obj.remove_vlan_member(dvs, "100", "Ethernet24") - vxlan_obj.remove_vlan(dvs, "100") - - def test_prefix_route_create_on_l2_vni(self, dvs, testlog): - vxlan_obj = self.get_vxlan_obj() - helper = self.get_vxlan_helper() - - self.setup_db(dvs) - tunnel_name = 'tunnel_2' - map_name = 'map_1000_100' - vrf_map_name = 'evpn_map_1000_Vrf-RED' - vxlan_obj.fetch_exist_entries(dvs) - - print ("\tCreate SIP Tunnel") - vlan_ids = vxlan_obj.helper.get_exist_entries(dvs, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - vlan_oid = vxlan_obj.create_vlan(dvs,"Vlan100", vlan_ids) - vxlan_obj.check_vlan_obj(dvs, "100") - vxlan_obj.create_vxlan_tunnel(dvs, tunnel_name, '6.6.6.6') - vxlan_obj.create_evpn_nvo(dvs, 'nvo1', tunnel_name) - - print ("\tCreate Vlan-VNI map") - vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') - - print ("\tTesting VRF-VNI map in APP DB") - vxlan_obj.create_vrf(dvs, "Vrf-RED") - - vlanlist = ['100'] - vnilist = ['1000'] - - print ("\tTesting SIP Tunnel Creation") - vxlan_obj.check_vxlan_sip_tunnel(dvs, tunnel_name, '6.6.6.6', vlanlist, vnilist, ignore_bp=False, tunnel_map_entry_count=1) - - print ("\tTesting VLAN 100 interface creation") - vxlan_obj.create_vlan_interface(dvs, "Vlan100", "Ethernet24", "Vrf-RED", "100.100.3.1/24") - vxlan_obj.check_router_interface(dvs, 'Vrf-RED', vlan_oid, 2) - - print ("\tTest if IPv4 Route with Tunnel Nexthop Add is not created") - vxlan_obj.create_vrf_route(dvs, "80.80.1.0/24", 'Vrf-RED', '7.7.7.7', "Vlan100", "00:11:11:11:11:11", '1000') - vxlan_obj.check_vrf_routes_absence(dvs, "80.80.1.0/24", 'Vrf-RED', '7.7.7.7', tunnel_name, "00:11:11:11:11:11", '1000') - - print ("\tCreate Vlan-VNI map and VRF-VNI map") - vxlan_obj.create_vxlan_vrf_tunnel_map(dvs, 'Vrf-RED', '1000') - - exp_attrs = [ - ("vni", "1000"), - ] - exp_attr = {} - for an in range(len(exp_attrs)): - exp_attr[exp_attrs[an][0]] = exp_attrs[an][1] - - helper.check_object(self.pdb, "VRF_TABLE", 'Vrf-RED', exp_attr) - - exp_attrs1 = [ - ("vni", "1000"), - ("vlan", "Vlan100"), - ] - exp_attr1 = {} - for an in range(len(exp_attrs1)): - exp_attr1[exp_attrs1[an][0]] = exp_attrs1[an][1] - - helper.check_object(self.pdb, "VXLAN_VRF_TABLE", "%s:%s" % (tunnel_name, vrf_map_name), exp_attr1) - vxlan_obj.check_vxlan_tunnel_map_entry_removed(dvs, tunnel_name, vlanlist, vnilist) - vxlan_obj.check_vxlan_tunnel_vrf_map_entry(dvs, tunnel_name, 'Vrf-RED', '1000') - print ("\tTest VRF IPv4 Route with Tunnel Nexthop Add") - vxlan_obj.check_vrf_routes(dvs, "80.80.1.0/24", 'Vrf-RED', '7.7.7.7', tunnel_name, "00:11:11:11:11:11", '1000') - - print ("\tTest VRF IPv4 Route with Tunnel Nexthop Delete") - vxlan_obj.delete_vrf_route(dvs, "80.80.1.0/24", 'Vrf-RED') - vxlan_obj.check_del_tunnel_nexthop(dvs, 'Vrf-RED', '7.7.7.7', tunnel_name, "00:11:11:11:11:11", '1000') - vxlan_obj.check_del_vrf_routes(dvs, "80.80.1.0/24", 'Vrf-RED') - - print ("\tTesting Tunnel Vrf Map Entry removal") - vxlan_obj.remove_vxlan_vrf_tunnel_map(dvs, 'Vrf-RED') - vxlan_obj.check_vxlan_tunnel_vrf_map_entry_remove(dvs, tunnel_name, 'Vrf-RED', '1000') - - print ("\tTesting Vlan 100 interface delete") - vxlan_obj.delete_vlan_interface(dvs, "Vlan100", "100.100.3.1/24") - vxlan_obj.check_del_router_interface(dvs, "Vlan100") - - print ("\tTesting Tunnel Map entry removal") - vxlan_obj.check_vxlan_tunnel_map_entry(dvs, tunnel_name, vlanlist, vnilist) - vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') - vxlan_obj.check_vxlan_tunnel_map_entry_delete(dvs, tunnel_name, vlanlist, vnilist) - - print ("\tTesting SIP Tunnel Deletion") - vxlan_obj.remove_vxlan_tunnel(dvs, tunnel_name) - vxlan_obj.remove_evpn_nvo(dvs, 'nvo1') - time.sleep(2) - vxlan_obj.check_vxlan_sip_tunnel_delete(dvs, tunnel_name, '6.6.6.6', ignore_bp=False) - vxlan_obj.remove_vrf(dvs, "Vrf-RED") - vxlan_obj.remove_vlan_member(dvs, "100", "Ethernet24") - vxlan_obj.remove_vlan(dvs, "100") - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_evpn_tunnel.py b/tests/test_evpn_tunnel.py deleted file mode 100644 index 86f5ad53f6..0000000000 --- a/tests/test_evpn_tunnel.py +++ /dev/null @@ -1,258 +0,0 @@ -import json -import random -import pytest -from pprint import pprint -from evpn_tunnel import VxlanTunnel - -class TestVxlanOrch(object): - - def get_vxlan_obj(self): - return VxlanTunnel() - -# Test 1 - Create and Delete SIP Tunnel and Map entries - def test_p2mp_tunnel(self, dvs, testlog): - vxlan_obj = self.get_vxlan_obj() - - tunnel_name = 'tunnel_1' - map_name = 'map_1000_100' - map_name_1 = 'map_1001_101' - map_name_2 = 'map_1002_102' - - vxlan_obj.fetch_exist_entries(dvs) - - vxlan_obj.create_vlan1(dvs,"Vlan100") - vxlan_obj.create_vlan1(dvs,"Vlan101") - vxlan_obj.create_vlan1(dvs,"Vlan102") - vxlan_obj.create_vxlan_tunnel(dvs, tunnel_name, '6.6.6.6') - vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') - vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name_1, '1001', 'Vlan101') - vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name_2, '1002', 'Vlan102') - - vlanlist = ['100', '101', '102'] - vnilist = ['1000', '1001', '1002'] - - print("Testing SIP Tunnel Creation") - vxlan_obj.check_vxlan_sip_tunnel(dvs, tunnel_name, '6.6.6.6', vlanlist, vnilist) - - print("Testing Tunnel Map Entry") - vxlan_obj.check_vxlan_tunnel_map_entry(dvs, tunnel_name, vlanlist, vnilist) - - print("Testing Tunnel Map entry removal") - vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') - vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name_1, '1001', 'Vlan101') - vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name_2, '1002', 'Vlan102') - vxlan_obj.check_vxlan_tunnel_map_entry_delete(dvs, tunnel_name, vlanlist, vnilist) - - print("Testing SIP Tunnel Deletion") - vxlan_obj.remove_vxlan_tunnel(dvs, tunnel_name) - vxlan_obj.check_vxlan_sip_tunnel_delete(dvs, tunnel_name, '6.6.6.6') - -# Test 2 - DIP Tunnel Tests - def test_p2p_tunnel(self, dvs, testlog): - vxlan_obj = self.get_vxlan_obj() - - tunnel_name = 'tunnel_2' - map_name = 'map_1000_100' - map_name_1 = 'map_1001_101' - map_name_2 = 'map_1002_102' - vlanlist = ['100', '101', '102'] - vnilist = ['1000', '1001', '1002'] - - vxlan_obj.fetch_exist_entries(dvs) - vxlan_obj.create_vlan1(dvs,"Vlan100") - vxlan_obj.create_vlan1(dvs,"Vlan101") - vxlan_obj.create_vlan1(dvs,"Vlan102") - vxlan_obj.create_vxlan_tunnel(dvs, tunnel_name, '6.6.6.6') - vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') - vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name_1, '1001', 'Vlan101') - vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name_2, '1002', 'Vlan102') - - vxlan_obj.check_vxlan_sip_tunnel(dvs, tunnel_name, '6.6.6.6', vlanlist, vnilist) - vxlan_obj.check_vxlan_tunnel_map_entry(dvs, tunnel_name, vlanlist, vnilist) - - vxlan_obj.create_evpn_nvo(dvs, 'nvo1', tunnel_name) - vxlan_obj.create_evpn_remote_vni(dvs, 'Vlan100', '7.7.7.7', '1000') - - print("Testing DIP tunnel creation") - vxlan_obj.check_vxlan_dip_tunnel(dvs, tunnel_name, '6.6.6.6', '7.7.7.7') - print("Testing VLAN 100 extension") - vxlan_obj.check_vlan_extension(dvs, '100', '7.7.7.7') - - vxlan_obj.create_evpn_remote_vni(dvs, 'Vlan101', '7.7.7.7', '1001') - vxlan_obj.create_evpn_remote_vni(dvs, 'Vlan102', '7.7.7.7', '1002') - - print("Testing DIP tunnel not created again") - vxlan_obj.check_vxlan_dip_tunnel(dvs, tunnel_name, '6.6.6.6', '7.7.7.7') - - print("Testing VLAN 101 extension") - vxlan_obj.check_vlan_extension(dvs, '101', '7.7.7.7') - - print("Testing VLAN 102 extension") - vxlan_obj.check_vlan_extension(dvs, '102', '7.7.7.7') - - print("Testing another DIP tunnel to 8.8.8.8") - vxlan_obj.create_evpn_remote_vni(dvs, 'Vlan100', '8.8.8.8', '1000') - print("Testing DIP tunnel creation to 8.8.8.8") - vxlan_obj.check_vxlan_dip_tunnel(dvs, tunnel_name, '6.6.6.6', '8.8.8.8') - print("Testing VLAN 100 extension to 8.8.8.8 and 7.7.7.7") - vxlan_obj.check_vlan_extension(dvs, '100', '8.8.8.8') - vxlan_obj.check_vlan_extension(dvs, '100', '7.7.7.7') - - print("Testing Vlan Extension removal") - vxlan_obj.remove_evpn_remote_vni(dvs, 'Vlan100', '7.7.7.7') - vxlan_obj.remove_evpn_remote_vni(dvs, 'Vlan101', '7.7.7.7') - vxlan_obj.check_vlan_extension_delete(dvs, '100', '7.7.7.7') - vxlan_obj.check_vlan_extension_delete(dvs, '101', '7.7.7.7') - print("Testing DIP tunnel not deleted") - vxlan_obj.check_vxlan_dip_tunnel(dvs, tunnel_name, '6.6.6.6', '7.7.7.7') - - print("Testing Last Vlan removal and DIP tunnel delete") - vxlan_obj.remove_evpn_remote_vni(dvs, 'Vlan102', '7.7.7.7') - vxlan_obj.check_vlan_extension_delete(dvs, '102', '7.7.7.7') - vxlan_obj.check_vxlan_dip_tunnel_delete(dvs, '7.7.7.7') - - print("Testing Last Vlan removal and DIP tunnel delete for 8.8.8.8") - vxlan_obj.remove_evpn_remote_vni(dvs, 'Vlan100', '8.8.8.8') - vxlan_obj.check_vlan_extension_delete(dvs, '100', '8.8.8.8') - vxlan_obj.check_vxlan_dip_tunnel_delete(dvs, '8.8.8.8') - - vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') - vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name_1, '1001', 'Vlan101') - vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name_2, '1002', 'Vlan102') - vxlan_obj.check_vxlan_tunnel_map_entry_delete(dvs, tunnel_name, vlanlist, vnilist) - - print("Testing SIP Tunnel Deletion") - vxlan_obj.remove_evpn_nvo(dvs, 'nvo1') - vxlan_obj.remove_vxlan_tunnel(dvs, tunnel_name) - vxlan_obj.check_vxlan_sip_tunnel_delete(dvs, tunnel_name, '6.6.6.6') - - -# Test 3 - Create and Delete SIP Tunnel and Map entries - def test_p2mp_tunnel_with_dip(self, dvs, testlog): - vxlan_obj = self.get_vxlan_obj() - - tunnel_name = 'tunnel_2' - map_name = 'map_1000_100' - map_name_1 = 'map_1001_101' - map_name_2 = 'map_1002_102' - - vxlan_obj.fetch_exist_entries(dvs) - - vxlan_obj.create_vlan1(dvs,"Vlan100") - vxlan_obj.create_vlan1(dvs,"Vlan101") - vxlan_obj.create_vlan1(dvs,"Vlan102") - vxlan_obj.create_vxlan_tunnel(dvs, tunnel_name, '6.6.6.6', '2.2.2.2', False) - vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') - vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name_1, '1001', 'Vlan101') - vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name_2, '1002', 'Vlan102') - - vlanlist = ['100', '101', '102'] - vnilist = ['1000', '1001', '1002'] - - print("Testing SIP Tunnel Creation") - vxlan_obj.check_vxlan_sip_tunnel(dvs, tunnel_name, '6.6.6.6', vlanlist, vnilist, '2.2.2.2', False) - - print("Testing Tunnel Map Entry") - vxlan_obj.check_vxlan_tunnel_map_entry(dvs, tunnel_name, vlanlist, vnilist) - - print("Testing Tunnel Map entry removal") - vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') - vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name_1, '1001', 'Vlan101') - vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name_2, '1002', 'Vlan102') - vxlan_obj.check_vxlan_tunnel_map_entry_delete(dvs, tunnel_name, vlanlist, vnilist) - - print("Testing SIP Tunnel Deletion") - vxlan_obj.remove_vxlan_tunnel(dvs, tunnel_name) - vxlan_obj.check_vxlan_sip_tunnel_delete(dvs, tunnel_name, '6.6.6.6') - vxlan_obj.remove_vlan(dvs, "100") - vxlan_obj.remove_vlan(dvs, "101") - vxlan_obj.remove_vlan(dvs, "102") - - def test_delayed_vlan_vni_map(self, dvs, testlog): - vxlan_obj = self.get_vxlan_obj() - - tunnel_name = 'tunnel_2' - map_name = 'map_1000_100' - map_name_1 = 'map_1001_101' - vlanlist = ['100'] - vnilist = ['1000'] - - vxlan_obj.fetch_exist_entries(dvs) - vxlan_obj.create_vlan1(dvs,"Vlan100") - vxlan_obj.create_vlan1(dvs,"Vlan101") - - vxlan_obj.create_vxlan_tunnel(dvs, tunnel_name, '6.6.6.6') - vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') - - vxlan_obj.check_vxlan_sip_tunnel(dvs, tunnel_name, '6.6.6.6', vlanlist, vnilist, tunnel_map_entry_count = 1) - vxlan_obj.check_vxlan_tunnel_map_entry(dvs, tunnel_name, vlanlist, vnilist) - - vxlan_obj.create_evpn_nvo(dvs, 'nvo1', tunnel_name) - - vxlan_obj.create_evpn_remote_vni(dvs, 'Vlan101', '7.7.7.7', '1001') - vxlan_obj.check_vxlan_dip_tunnel_not_created(dvs, tunnel_name, '6.6.6.6', '7.7.7.7') - vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name_1, '1001', 'Vlan101') - - print("Testing VLAN 101 extension") - vxlan_obj.check_vxlan_dip_tunnel(dvs, tunnel_name, '6.6.6.6', '7.7.7.7') - vxlan_obj.check_vlan_extension(dvs, '101', '7.7.7.7') - - print("Testing Vlan Extension removal") - vxlan_obj.remove_evpn_remote_vni(dvs, 'Vlan101', '7.7.7.7') - vxlan_obj.check_vlan_extension_delete(dvs, '101', '7.7.7.7') - vxlan_obj.check_vxlan_dip_tunnel_delete(dvs, '7.7.7.7') - - vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') - vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name_1, '1001', 'Vlan101') - vxlan_obj.check_vxlan_tunnel_map_entry_delete(dvs, tunnel_name, vlanlist, vnilist) - - print("Testing SIP Tunnel Deletion") - vxlan_obj.remove_evpn_nvo(dvs, 'nvo1') - vxlan_obj.remove_vxlan_tunnel(dvs, tunnel_name) - vxlan_obj.check_vxlan_sip_tunnel_delete(dvs, tunnel_name, '6.6.6.6') - vxlan_obj.remove_vlan(dvs, "100") - vxlan_obj.remove_vlan(dvs, "101") - - def test_invalid_vlan_extension(self, dvs, testlog): - vxlan_obj = self.get_vxlan_obj() - - tunnel_name = 'tunnel_2' - map_name = 'map_1000_100' - map_name_1 = 'map_1001_101' - vlanlist = ['100'] - vnilist = ['1000'] - - vxlan_obj.fetch_exist_entries(dvs) - vxlan_obj.create_vlan1(dvs,"Vlan100") - - vxlan_obj.create_vxlan_tunnel(dvs, tunnel_name, '6.6.6.6') - vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') - - vxlan_obj.check_vxlan_sip_tunnel(dvs, tunnel_name, '6.6.6.6', vlanlist, vnilist, tunnel_map_entry_count = 1) - vxlan_obj.check_vxlan_tunnel_map_entry(dvs, tunnel_name, vlanlist, vnilist) - - vxlan_obj.create_evpn_nvo(dvs, 'nvo1', tunnel_name) - - vxlan_obj.create_vrf(dvs, "Vrf-RED") - vxlan_obj.create_vxlan_vrf_tunnel_map(dvs, 'Vrf-RED', '1000') - - vxlan_obj.create_evpn_remote_vni(dvs, 'Vlan100', '7.7.7.7', '1000') - vxlan_obj.check_vlan_extension_not_created(dvs, '100', '7.7.7.7') - - vxlan_obj.remove_vxlan_vrf_tunnel_map(dvs, 'Vrf-RED') - vxlan_obj.remove_vrf(dvs, "Vrf-RED") - vxlan_obj.check_vxlan_dip_tunnel(dvs, tunnel_name, '6.6.6.6', '7.7.7.7') - print("Testing VLAN 100 extension") - vxlan_obj.check_vlan_extension(dvs, '100', '7.7.7.7') - - print("Testing Vlan Extension removal") - vxlan_obj.remove_evpn_remote_vni(dvs, 'Vlan100', '7.7.7.7') - vxlan_obj.check_vlan_extension_delete(dvs, '100', '7.7.7.7') - - vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') - vxlan_obj.check_vxlan_tunnel_map_entry_delete(dvs, tunnel_name, vlanlist, vnilist) - - print("Testing SIP Tunnel Deletion") - vxlan_obj.remove_evpn_nvo(dvs, 'nvo1') - vxlan_obj.remove_vxlan_tunnel(dvs, tunnel_name) - vxlan_obj.check_vxlan_sip_tunnel_delete(dvs, tunnel_name, '6.6.6.6') diff --git a/tests/test_evpn_tunnel_p2mp.py b/tests/test_evpn_tunnel_p2mp.py deleted file mode 100644 index bbbb786f9a..0000000000 --- a/tests/test_evpn_tunnel_p2mp.py +++ /dev/null @@ -1,216 +0,0 @@ -from evpn_tunnel import VxlanTunnel - -DVS_ENV = ["HWSKU=Mellanox-SN2700"] - -class TestVxlanOrchP2MP(object): - - def get_vxlan_obj(self): - return VxlanTunnel() - -# Test 1 - Create and Delete SIP Tunnel and Map entries - def test_p2mp_tunnel(self, dvs, testlog): - vxlan_obj = self.get_vxlan_obj() - - tunnel_name = 'tunnel_1' - map_name = 'map_1000_100' - map_name_1 = 'map_1001_101' - map_name_2 = 'map_1002_102' - - vxlan_obj.fetch_exist_entries(dvs) - - vxlan_obj.create_vlan1(dvs,"Vlan100") - vxlan_obj.create_vlan1(dvs,"Vlan101") - vxlan_obj.create_vlan1(dvs,"Vlan102") - vxlan_obj.create_vxlan_tunnel(dvs, tunnel_name, '6.6.6.6') - vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') - vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name_1, '1001', 'Vlan101') - vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name_2, '1002', 'Vlan102') - - vlanlist = ['100', '101', '102'] - vnilist = ['1000', '1001', '1002'] - - print("Testing SIP Tunnel Creation") - vxlan_obj.check_vxlan_sip_tunnel(dvs, tunnel_name, '6.6.6.6', vlanlist, vnilist, ignore_bp=False) - - print("Testing Tunnel Map Entry") - vxlan_obj.check_vxlan_tunnel_map_entry(dvs, tunnel_name, vlanlist, vnilist) - - print("Testing Tunnel Map entry removal") - vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') - vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name_1, '1001', 'Vlan101') - vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name_2, '1002', 'Vlan102') - vxlan_obj.check_vxlan_tunnel_map_entry_delete(dvs, tunnel_name, vlanlist, vnilist) - - print("Testing SIP Tunnel Deletion") - vxlan_obj.remove_vxlan_tunnel(dvs, tunnel_name) - vxlan_obj.check_vxlan_sip_tunnel_delete(dvs, tunnel_name, '6.6.6.6', ignore_bp=False) - -# Test 2 - Vlan extension Tests - def test_vlan_extension(self, dvs, testlog): - vxlan_obj = self.get_vxlan_obj() - - tunnel_name = 'tunnel_2' - map_name = 'map_1000_100' - map_name_1 = 'map_1001_101' - map_name_2 = 'map_1002_102' - vlanlist = ['100', '101', '102'] - vnilist = ['1000', '1001', '1002'] - - vxlan_obj.fetch_exist_entries(dvs) - vxlan_obj.create_vlan1(dvs,"Vlan100") - vxlan_obj.create_vlan1(dvs,"Vlan101") - vxlan_obj.create_vlan1(dvs,"Vlan102") - vxlan_obj.create_vxlan_tunnel(dvs, tunnel_name, '6.6.6.6') - vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') - vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name_1, '1001', 'Vlan101') - vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name_2, '1002', 'Vlan102') - - vxlan_obj.check_vxlan_sip_tunnel(dvs, tunnel_name, '6.6.6.6', vlanlist, vnilist, ignore_bp=False) - vxlan_obj.check_vxlan_tunnel_map_entry(dvs, tunnel_name, vlanlist, vnilist) - - vxlan_obj.create_evpn_nvo(dvs, 'nvo1', tunnel_name) - vxlan_obj.create_evpn_remote_vni(dvs, 'Vlan100', '7.7.7.7', '1000') - - print("Testing VLAN 100 extension") - vxlan_obj.check_vlan_extension_p2mp(dvs, '100', '6.6.6.6', '7.7.7.7') - - vxlan_obj.create_evpn_remote_vni(dvs, 'Vlan101', '7.7.7.7', '1001') - vxlan_obj.create_evpn_remote_vni(dvs, 'Vlan102', '7.7.7.7', '1002') - - print("Testing VLAN 101 extension") - vxlan_obj.check_vlan_extension_p2mp(dvs, '101', '6.6.6.6', '7.7.7.7') - - print("Testing VLAN 102 extension") - vxlan_obj.check_vlan_extension_p2mp(dvs, '102', '6.6.6.6', '7.7.7.7') - - print("Testing another remote endpoint to 8.8.8.8") - vxlan_obj.create_evpn_remote_vni(dvs, 'Vlan100', '8.8.8.8', '1000') - print("Testing remote endpoint creation to 8.8.8.8") - - print("Testing VLAN 100 extension to 8.8.8.8 and 7.7.7.7") - vxlan_obj.check_vlan_extension_p2mp(dvs, '100', '6.6.6.6', '8.8.8.8') - vxlan_obj.check_vlan_extension_p2mp(dvs, '100', '6.6.6.6', '7.7.7.7') - - print("Testing Vlan Extension removal") - vxlan_obj.remove_evpn_remote_vni(dvs, 'Vlan100', '7.7.7.7') - vxlan_obj.remove_evpn_remote_vni(dvs, 'Vlan101', '7.7.7.7') - vxlan_obj.check_vlan_extension_delete_p2mp(dvs, '100', '6.6.6.6', '7.7.7.7') - vxlan_obj.check_vlan_extension_delete_p2mp(dvs, '101', '6.6.6.6', '7.7.7.7') - - print("Testing Last Vlan removal and remote endpoint delete") - vxlan_obj.remove_evpn_remote_vni(dvs, 'Vlan102', '7.7.7.7') - vxlan_obj.check_vlan_extension_delete_p2mp(dvs, '102', '6.6.6.6', '7.7.7.7') - - print("Testing Last Vlan removal and remote endpoint delete for 8.8.8.8") - vxlan_obj.remove_evpn_remote_vni(dvs, 'Vlan100', '8.8.8.8') - vxlan_obj.check_vlan_extension_delete_p2mp(dvs, '100', '6.6.6.6', '8.8.8.8') - - print("Testing remote endpoint again to 8.8.8.8") - vxlan_obj.create_evpn_remote_vni(dvs, 'Vlan100', '8.8.8.8', '1000') - print("Testing remote endpoint creation to 8.8.8.8") - - print("Testing VLAN 100 extension to 8.8.8.8") - vxlan_obj.check_vlan_extension_p2mp(dvs, '100', '6.6.6.6', '8.8.8.8') - - print("Testing Last Vlan removal and remote endpoint delete for 8.8.8.8") - vxlan_obj.remove_evpn_remote_vni(dvs, 'Vlan100', '8.8.8.8') - vxlan_obj.check_vlan_extension_delete_p2mp(dvs, '100', '6.6.6.6', '8.8.8.8') - - vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') - vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name_1, '1001', 'Vlan101') - vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name_2, '1002', 'Vlan102') - vxlan_obj.check_vxlan_tunnel_map_entry_delete(dvs, tunnel_name, vlanlist, vnilist) - - print("Testing SIP Tunnel Deletion") - vxlan_obj.remove_evpn_nvo(dvs, 'nvo1') - vxlan_obj.remove_vxlan_tunnel(dvs, tunnel_name) - vxlan_obj.check_vxlan_sip_tunnel_delete(dvs, tunnel_name, '6.6.6.6', ignore_bp=False) - vxlan_obj.remove_vlan(dvs, "100") - vxlan_obj.remove_vlan(dvs, "101") - vxlan_obj.remove_vlan(dvs, "102") - - def test_delayed_vlan_vni_map(self, dvs, testlog): - vxlan_obj = self.get_vxlan_obj() - - tunnel_name = 'tunnel_2' - map_name = 'map_1000_100' - map_name_1 = 'map_1001_101' - vlanlist = ['100'] - vnilist = ['1000'] - - vxlan_obj.fetch_exist_entries(dvs) - vxlan_obj.create_vlan1(dvs,"Vlan100") - vxlan_obj.create_vlan1(dvs,"Vlan101") - - vxlan_obj.create_vxlan_tunnel(dvs, tunnel_name, '6.6.6.6') - vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') - - vxlan_obj.check_vxlan_sip_tunnel(dvs, tunnel_name, '6.6.6.6', vlanlist, vnilist, ignore_bp=False, tunnel_map_entry_count = 1) - vxlan_obj.check_vxlan_tunnel_map_entry(dvs, tunnel_name, vlanlist, vnilist) - - vxlan_obj.create_evpn_nvo(dvs, 'nvo1', tunnel_name) - - vxlan_obj.create_evpn_remote_vni(dvs, 'Vlan101', '7.7.7.7', '1001') - vxlan_obj.check_vlan_extension_not_created_p2mp(dvs, '101', '6.6.6.6', '7.7.7.7') - vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name_1, '1001', 'Vlan101') - - print("Testing VLAN 101 extension") - vxlan_obj.check_vlan_extension_p2mp(dvs, '101', '6.6.6.6', '7.7.7.7') - - print("Testing Vlan Extension removal") - vxlan_obj.remove_evpn_remote_vni(dvs, 'Vlan101', '7.7.7.7') - vxlan_obj.check_vlan_extension_delete_p2mp(dvs, '101', '6.6.6.6', '7.7.7.7') - - vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') - vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name_1, '1001', 'Vlan101') - vxlan_obj.check_vxlan_tunnel_map_entry_delete(dvs, tunnel_name, vlanlist, vnilist) - - print("Testing SIP Tunnel Deletion") - vxlan_obj.remove_evpn_nvo(dvs, 'nvo1') - vxlan_obj.remove_vxlan_tunnel(dvs, tunnel_name) - vxlan_obj.check_vxlan_sip_tunnel_delete(dvs, tunnel_name, '6.6.6.6', ignore_bp=False) - vxlan_obj.remove_vlan(dvs, "100") - vxlan_obj.remove_vlan(dvs, "101") - - def test_invalid_vlan_extension(self, dvs, testlog): - vxlan_obj = self.get_vxlan_obj() - - tunnel_name = 'tunnel_2' - map_name = 'map_1000_100' - map_name_1 = 'map_1001_101' - vlanlist = ['100'] - vnilist = ['1000'] - - vxlan_obj.fetch_exist_entries(dvs) - vxlan_obj.create_vlan1(dvs,"Vlan100") - - vxlan_obj.create_vxlan_tunnel(dvs, tunnel_name, '6.6.6.6') - vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') - - vxlan_obj.check_vxlan_sip_tunnel(dvs, tunnel_name, '6.6.6.6', vlanlist, vnilist, ignore_bp=False, tunnel_map_entry_count = 1) - vxlan_obj.check_vxlan_tunnel_map_entry(dvs, tunnel_name, vlanlist, vnilist) - - vxlan_obj.create_evpn_nvo(dvs, 'nvo1', tunnel_name) - - vxlan_obj.create_vrf(dvs, "Vrf-RED") - vxlan_obj.create_vxlan_vrf_tunnel_map(dvs, 'Vrf-RED', '1000') - - vxlan_obj.create_evpn_remote_vni(dvs, 'Vlan100', '7.7.7.7', '1000') - vxlan_obj.check_vlan_extension_not_created_p2mp(dvs, '100', '6.6.6.6', '7.7.7.7') - - vxlan_obj.remove_vxlan_vrf_tunnel_map(dvs, 'Vrf-RED') - vxlan_obj.remove_vrf(dvs, "Vrf-RED") - print("Testing VLAN 100 extension") - vxlan_obj.check_vlan_extension_p2mp(dvs, '100', '6.6.6.6', '7.7.7.7') - - print("Testing Vlan Extension removal") - vxlan_obj.remove_evpn_remote_vni(dvs, 'Vlan100', '7.7.7.7') - vxlan_obj.check_vlan_extension_delete_p2mp(dvs, '100', '6.6.6.6', '7.7.7.7') - - vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') - vxlan_obj.check_vxlan_tunnel_map_entry_delete(dvs, tunnel_name, vlanlist, vnilist) - - print("Testing SIP Tunnel Deletion") - vxlan_obj.remove_evpn_nvo(dvs, 'nvo1') - vxlan_obj.remove_vxlan_tunnel(dvs, tunnel_name) - vxlan_obj.check_vxlan_sip_tunnel_delete(dvs, tunnel_name, '6.6.6.6', ignore_bp=False) diff --git a/tests/test_fabric.py b/tests/test_fabric.py deleted file mode 100644 index 72ad828790..0000000000 --- a/tests/test_fabric.py +++ /dev/null @@ -1,91 +0,0 @@ -from swsscommon import swsscommon -from dvslib.dvs_database import DVSDatabase -import ast -import json - -# Fabric counters -NUMBER_OF_RETRIES = 10 - -counter_group_meta = { - 'fabric_port_counter': { - 'key': 'FABRIC_PORT', - 'group_name': 'FABRIC_PORT_STAT_COUNTER', - 'name_map': 'COUNTERS_FABRIC_PORT_NAME_MAP', - 'post_test': 'post_port_counter_test', - }, - 'fabric_queue_counter': { - 'key': 'FABRIC_QUEUE', - 'group_name': 'FABRIC_QUEUE_STAT_COUNTER', - 'name_map': 'COUNTERS_FABRIC_QUEUE_NAME_MAP', - }, -} - -class TestVirtualChassis(object): - - def wait_for_id_list(self, flex_db, stat, name, oid): - for retry in range(NUMBER_OF_RETRIES): - id_list = flex_db.db_connection.hgetall("FLEX_COUNTER_TABLE:" + stat + ":" + oid).items() - if len(id_list) > 0: - return - else: - time.sleep(1) - - assert False, "No ID list for counter " + str(name) - - def verify_flex_counters_populated(self, flex_db, counters_db, map, stat): - counters_keys = counters_db.db_connection.hgetall(map) - for counter_entry in counters_keys.items(): - name = counter_entry[0] - oid = counter_entry[1] - self.wait_for_id_list(flex_db, stat, name, oid) - - def test_voq_switch(self, vst): - """Test VOQ switch objects configuration. - - This test validates configuration of switch creation objects required for - VOQ switches. The switch_type, max_cores and switch_id attributes configuration - are verified. For the System port config list, it is verified that all the - configured system ports are avaiable in the asic db by checking the count. - """ - - if vst is None: - return - - dvss = vst.dvss - for name in dvss.keys(): - dvs = dvss[name] - # Get the config info - config_db = dvs.get_config_db() - metatbl = config_db.get_entry("DEVICE_METADATA", "localhost") - - cfg_switch_type = metatbl.get("switch_type") - if cfg_switch_type == "fabric": - flex_db = dvs.get_flex_db() - counters_db = dvs.get_counters_db() - for ct in counter_group_meta.keys(): - meta_data = counter_group_meta[ct] - counter_key = meta_data['key'] - counter_stat = meta_data['group_name'] - counter_map = meta_data['name_map'] - self.verify_flex_counters_populated(flex_db, counters_db, counter_map, counter_stat) - - port_counters_keys = counters_db.db_connection.hgetall(meta_data['name_map']) - port_counters_stat_keys = flex_db.get_keys("FLEX_COUNTER_TABLE:" + meta_data['group_name']) - for port_stat in port_counters_stat_keys: - assert port_stat in dict(port_counters_keys.items()).values(), "Non port created on PORT_STAT_COUNTER group: {}".format(port_stat) - - # update some config_db entries - cfg_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - tb = swsscommon.Table(cfg_db, "FABRIC_PORT") - fvs = swsscommon.FieldValuePairs([("isolateStatus","True")]) - tb.set("FABRIC_PORT|Fabric0", fvs ) - fvs = swsscommon.FieldValuePairs([("forceUnisolateStatus", "1")]) - tb.set("FABRIC_PORT|Fabric0", fvs ) - else: - print( "We do not check switch type:", cfg_switch_type ) - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass - diff --git a/tests/test_fabric_capacity.py b/tests/test_fabric_capacity.py deleted file mode 100644 index 91bb1b5e94..0000000000 --- a/tests/test_fabric_capacity.py +++ /dev/null @@ -1,72 +0,0 @@ -import random -from dvslib.dvs_database import DVSDatabase -from dvslib.dvs_common import PollingConfig - - -class TestVirtualChassis(object): - def test_voq_switch_fabric_capacity(self, vst): - """Test basic fabric capacity infrastructure in VOQ switchs. - - This test validates that when fabric links get isolated, the fabric capacity - get updated in the state_db. - When the link get unisolated, the fabric capacity get set back as well. - """ - - dvss = vst.dvss - for name in dvss.keys(): - dvs = dvss[name] - # Get the config information and choose a linecard or fabric card to test. - config_db = dvs.get_config_db() - metatbl = config_db.get_entry("DEVICE_METADATA", "localhost") - - cfg_switch_type = metatbl.get("switch_type") - if cfg_switch_type == "fabric": - - # get state_db infor - sdb = dvs.get_state_db() - # There are 16 fabric ports in the test environment. - # Choose one link to test. - portNum = random.randint(1, 16) - cdb_port = "Fabric"+str(portNum) - sdb_port = "PORT"+str(portNum) - - max_poll = PollingConfig(polling_interval=60, timeout=600, strict=True) - - # setup test environment - sdb.update_entry("FABRIC_PORT_TABLE", sdb_port, {"TEST": "TEST"}) - - # get current fabric capacity - capacity = sdb.get_entry("FABRIC_CAPACITY_TABLE", "FABRIC_CAPACITY_DATA")['operating_links'] - if sdb.get_entry("FABRIC_PORT_TABLE", sdb_port)['STATUS'] == 'up': - try: - # clean up the testing port. - # set TEST_CRC_ERRORS to 0 - # set TEST_CODE_ERRORS to 0 - sdb.update_entry("FABRIC_PORT_TABLE", sdb_port, {"TEST_CRC_ERRORS":"0"}) - sdb.update_entry("FABRIC_PORT_TABLE", sdb_port, {"TEST_CODE_ERRORS": "0"}) - - # isolate the link from config_db - config_db.update_entry("FABRIC_PORT", cdb_port, {"isolateStatus": "True"}) - sdb.wait_for_field_match("FABRIC_PORT_TABLE", sdb_port, {"ISOLATED": "1"}, polling_config=max_poll) - # check if capacity reduced - sdb.wait_for_field_negative_match("FABRIC_CAPACITY_TABLE", "FABRIC_CAPACITY_DATA", {'operating_links': capacity}, polling_config=max_poll) - # unisolate the link from config_db - config_db.update_entry("FABRIC_PORT", cdb_port, {"isolateStatus": "False"}) - sdb.wait_for_field_match("FABRIC_PORT_TABLE", sdb_port, {"ISOLATED": "0"}, polling_config=max_poll) - sdb.wait_for_field_match("FABRIC_CAPACITY_TABLE", "FABRIC_CAPACITY_DATA", {'operating_links': capacity}, polling_config=max_poll) - finally: - # cleanup - sdb.update_entry("FABRIC_PORT_TABLE", sdb_port, {"TEST_CRC_ERRORS": "0"}) - sdb.update_entry("FABRIC_PORT_TABLE", sdb_port, {"TEST_CODE_ERRORS": "0"}) - sdb.update_entry("FABRIC_PORT_TABLE", sdb_port, {"TEST": "product"}) - else: - print("The link ", port, " is down") - else: - print("We do not check switch type:", cfg_switch_type) - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass - diff --git a/tests/test_fabric_port.py b/tests/test_fabric_port.py deleted file mode 100644 index a7ad9958b0..0000000000 --- a/tests/test_fabric_port.py +++ /dev/null @@ -1,48 +0,0 @@ -from swsscommon import swsscommon -from dvslib.dvs_database import DVSDatabase - - -class TestVirtualChassis(object): - def test_voq_switch_fabric_link(self, vst): - """Test fabric link manual isolation commands in VOQ switch. - - By issuing config fabric port isolation command, the value - of isolateStatus field in config_db get changed. This test validates appl_db - updates of a fabric link isolateStatus as the value in config_db changed. - """ - - dvss = vst.dvss - for name in dvss.keys(): - dvs = dvss[name] - # Get the config info - config_db = dvs.get_config_db() - metatbl = config_db.get_entry("DEVICE_METADATA", "localhost") - - cfg_switch_type = metatbl.get("switch_type") - if cfg_switch_type == "fabric": - - # get config_db information - cdb = dvs.get_config_db() - - # set config_db to isolateStatus: True - cdb.update_entry("FABRIC_PORT", "Fabric1", {"isolateStatus": "True"}) - cdb.wait_for_field_match("FABRIC_PORT", "Fabric1", {"isolateStatus": "True"}) - - # check if appl_db value changes to isolateStatus: True - adb = dvs.get_app_db() - adb.wait_for_field_match("FABRIC_PORT_TABLE", "Fabric1", {"isolateStatus": "True"}) - - # cleanup - cdb.update_entry("FABRIC_PORT", "Fabric1", {"isolateStatus": "False"}) - cdb.wait_for_field_match("FABRIC_PORT", "Fabric1", {"isolateStatus": "False"}) - adb.wait_for_field_match("FABRIC_PORT_TABLE", "Fabric1", {"isolateStatus": "False"}) - else: - print( "We do not check switch type:", cfg_switch_type ) - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass - - diff --git a/tests/test_fabric_port_isolation.py b/tests/test_fabric_port_isolation.py deleted file mode 100644 index d1b57a019f..0000000000 --- a/tests/test_fabric_port_isolation.py +++ /dev/null @@ -1,64 +0,0 @@ -import random -from dvslib.dvs_database import DVSDatabase -from dvslib.dvs_common import PollingConfig - - -class TestVirtualChassis(object): - def test_voq_switch_fabric_link(self, vst): - """Test basic fabric link monitoring infrastructure in VOQ switchs. - - This test validates that fabric links get isolated if they experienced some errors. - And the link get unisolated if it clears the error for several consecutive polls. - """ - - dvss = vst.dvss - for name in dvss.keys(): - dvs = dvss[name] - # Get the config information and choose a linecard or fabric card to test. - config_db = dvs.get_config_db() - metatbl = config_db.get_entry("DEVICE_METADATA", "localhost") - - cfg_switch_type = metatbl.get("switch_type") - if cfg_switch_type == "fabric": - - # get state_db infor - sdb = dvs.get_state_db() - # key - port = "PORT1" - # There are 16 fabric ports in the test environment. - portNum = random.randint(1, 16) - port = "PORT"+str(portNum) - # wait for link monitoring algorithm skips init pollings - sdb.update_entry("FABRIC_PORT_TABLE", port, {"TEST": "TEST"}) - max_poll = PollingConfig(polling_interval=60, timeout=1200, strict=True) - if sdb.get_entry("FABRIC_PORT_TABLE", port)['STATUS'] == 'up': - try: - # clean up the system for the testing port. - # set TEST_CRC_ERRORS to 0 - # set TEST_CODE_ERRORS to 0 - # set TEST to "TEST" - sdb.update_entry("FABRIC_PORT_TABLE", port, {"TEST_CRC_ERRORS":"0"}) - sdb.update_entry("FABRIC_PORT_TABLE", port, {"TEST_CODE_ERRORS": "0"}) - # inject testing errors and wait for link get isolated. - sdb.update_entry("FABRIC_PORT_TABLE", port, {"TEST_CRC_ERRORS": "2"}) - sdb.wait_for_field_match("FABRIC_PORT_TABLE", port, {"AUTO_ISOLATED": "1"}, polling_config=max_poll) - - # clear the testing errors and wait for link get unisolated. - sdb.update_entry("FABRIC_PORT_TABLE", port, {"TEST_CRC_ERRORS": "0"}) - sdb.wait_for_field_match("FABRIC_PORT_TABLE", port, {"AUTO_ISOLATED": "0"}, polling_config=max_poll) - finally: - # cleanup - sdb.update_entry("FABRIC_PORT_TABLE", port, {"TEST_CRC_ERRORS": "0"}) - sdb.update_entry("FABRIC_PORT_TABLE", port, {"TEST_CODE_ERRORS": "0"}) - sdb.update_entry("FABRIC_PORT_TABLE", port, {"TEST": "product"}) - else: - print("The link ", port, " is down") - else: - print("We do not check switch type:", cfg_switch_type) - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass - diff --git a/tests/test_fdb.py b/tests/test_fdb.py deleted file mode 100644 index 06c79f230f..0000000000 --- a/tests/test_fdb.py +++ /dev/null @@ -1,388 +0,0 @@ -import os -import sys -import time -import json -import pytest - -from swsscommon import swsscommon -from distutils.version import StrictVersion - -def create_entry(tbl, key, pairs): - fvs = swsscommon.FieldValuePairs(pairs) - tbl.set(key, fvs) - - # FIXME: better to wait until DB create them - time.sleep(1) - -def create_entry_tbl(db, table, key, pairs): - tbl = swsscommon.Table(db, table) - create_entry(tbl, key, pairs) - -def create_entry_pst(db, table, key, pairs): - tbl = swsscommon.ProducerStateTable(db, table) - create_entry(tbl, key, pairs) - -def how_many_entries_exist(db, table): - tbl = swsscommon.Table(db, table) - return len(tbl.getKeys()) - - -class TestFdb(object): - def test_FdbWarmRestartNotifications(self, dvs, testlog): - dvs.setup_db() - - dvs.clear_fdb() - - dvs.crm_poll_set("1") - - dvs.setReadOnlyAttr('SAI_OBJECT_TYPE_SWITCH', 'SAI_SWITCH_ATTR_AVAILABLE_FDB_ENTRY', '1000') - - time.sleep(2) - counter_before = dvs.getCrmCounterValue('STATS', 'crm_stats_fdb_entry_used') - - # create vlan; create vlan member - dvs.create_vlan("6") - dvs.create_vlan_member("6", "Ethernet64") - dvs.create_vlan_member("6", "Ethernet68") - - # Put Ethernet72 and Ethernet76 into vlan 7 in untagged mode, they will have pvid of 7 - # and into vlan8 in tagged mode - dvs.create_vlan("7") - dvs.create_vlan_member("7", "Ethernet72") - dvs.create_vlan_member("7", "Ethernet76") - - dvs.create_vlan("8") - dvs.create_vlan_member_tagged("8", "Ethernet72") - dvs.create_vlan_member_tagged("8", "Ethernet76") - - - # Get mapping between interface name and its bridge port_id - time.sleep(2) - iface_2_bridge_port_id = dvs.get_map_iface_bridge_port_id(dvs.adb) - - # check FDB learning mode - ok, extra = dvs.is_table_entry_exists(dvs.adb, 'ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT', - iface_2_bridge_port_id["Ethernet64"], - [("SAI_BRIDGE_PORT_ATTR_FDB_LEARNING_MODE", "SAI_BRIDGE_PORT_FDB_LEARNING_MODE_HW")]) - assert ok, str(extra) - ok, extra = dvs.is_table_entry_exists(dvs.adb, 'ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT', - iface_2_bridge_port_id["Ethernet68"], - [("SAI_BRIDGE_PORT_ATTR_FDB_LEARNING_MODE", "SAI_BRIDGE_PORT_FDB_LEARNING_MODE_HW")]) - assert ok, str(extra) - - ok, extra = dvs.is_table_entry_exists(dvs.adb, 'ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT', - iface_2_bridge_port_id["Ethernet72"], - [("SAI_BRIDGE_PORT_ATTR_FDB_LEARNING_MODE", "SAI_BRIDGE_PORT_FDB_LEARNING_MODE_HW")]) - assert ok, str(extra) - - ok, extra = dvs.is_table_entry_exists(dvs.adb, 'ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT', - iface_2_bridge_port_id["Ethernet76"], - [("SAI_BRIDGE_PORT_ATTR_FDB_LEARNING_MODE", "SAI_BRIDGE_PORT_FDB_LEARNING_MODE_HW")]) - assert ok, str(extra) - - # check fdb aging attr - ok, extra = dvs.all_table_entry_has_no(dvs.adb, 'ASIC_STATE:SAI_OBJECT_TYPE_SWITCH', - ".*", - ["SAI_SWITCH_ATTR_FDB_AGING_TIME"]) - - # bring up vlan and member - dvs.set_interface_status("Vlan6", "up") - dvs.set_interface_status("Vlan7", "up") - dvs.set_interface_status("Vlan8", "up") - - dvs.add_ip_address("Vlan6", "6.6.6.1/24") - dvs.add_ip_address("Vlan7", "7.7.7.1/24") - dvs.add_ip_address("Vlan8", "8.8.8.1/24") - - dvs.set_interface_status("Ethernet64", "up") - dvs.set_interface_status("Ethernet68", "up") - dvs.set_interface_status("Ethernet72", "up") - dvs.set_interface_status("Ethernet76", "up") - dvs.servers[16].runcmd("ifconfig eth0 6.6.6.6/24 up") - dvs.servers[16].runcmd("ip route add default via 6.6.6.1") - dvs.servers[17].runcmd("ifconfig eth0 6.6.6.7/24 up") - dvs.servers[17].runcmd("ip route add default via 6.6.6.1") - - dvs.servers[18].runcmd("vconfig add eth0 8") - dvs.servers[18].runcmd("ifconfig eth0.8 8.8.8.6/24 up") - dvs.servers[18].runcmd("ip route add default via 8.8.8.1") - - dvs.servers[19].runcmd("vconfig add eth0 8") - dvs.servers[19].runcmd("ifconfig eth0.8 8.8.8.7/24 up") - dvs.servers[19].runcmd("ip route add default via 8.8.8.1") - - dvs.servers[18].runcmd("ifconfig eth0 7.7.7.6/24 up") - dvs.servers[18].runcmd("ip route add default via 7.7.7.1") - dvs.servers[19].runcmd("ifconfig eth0 7.7.7.7/24 up") - dvs.servers[19].runcmd("ip route add default via 7.7.7.1") - - # get neighbor and arp entry - time.sleep(2) - rc = dvs.servers[16].runcmd("ping -c 1 6.6.6.7") - assert rc == 0 - rc = dvs.servers[17].runcmd("ping -c 1 6.6.6.6") - assert rc == 0 - - # get neighbor and arp entry - time.sleep(2) - rc = dvs.servers[18].runcmd("ping -c 1 8.8.8.7") - assert rc == 0 - rc = dvs.servers[19].runcmd("ping -c 1 8.8.8.6") - assert rc == 0 - - time.sleep(2) - rc = dvs.servers[18].runcmd("ping -c 1 -I 7.7.7.6 7.7.7.7") - assert rc == 0 - rc = dvs.servers[19].runcmd("ping -c 1 -I 7.7.7.7 7.7.7.6") - assert rc == 0 - - # check that the FDB entries were inserted into ASIC DB - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_DYNAMIC"), - ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", iface_2_bridge_port_id["Ethernet64"]), - ] - ) - assert ok, str(extra) - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_DYNAMIC"), - ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", iface_2_bridge_port_id["Ethernet68"]), - ] - ) - assert ok, str(extra) - - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_DYNAMIC"), - ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", iface_2_bridge_port_id["Ethernet72"]), - ] - ) - assert ok, str(extra) - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_DYNAMIC"), - ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", iface_2_bridge_port_id["Ethernet76"]), - ] - ) - assert ok, str(extra) - - time.sleep(2) - counter_inserted = dvs.getCrmCounterValue('STATS', 'crm_stats_fdb_entry_used') - # vlan 6: Ethernet64, Ethernet68; - # vlan 7: Ethernet72, Ethernet76; - # vlan 8 (tagged): Ethernet72, Ethernet76; - # 6 FDB entries wil be created in total - assert counter_inserted - counter_before == 6 - - # check that the FDB entries were inserted into State DB for Ethernet64, Ethernet68 with Vlan6 - ok, extra = dvs.is_table_entry_exists(dvs.sdb, "FDB_TABLE", - "Vlan6:.*", - [("port", "Ethernet64"), - ("type", "dynamic"), - ] - ) - assert ok, str(extra) - ok, extra = dvs.is_table_entry_exists(dvs.sdb, "FDB_TABLE", - "Vlan6:*", - [("port", "Ethernet68"), - ("type", "dynamic"), - ] - ) - assert ok, str(extra) - - # check that the FDB entries were inserted into State DB, - # Vlan7(untagged) in the key for Ethernet72, Ethernet76 - ok, extra = dvs.is_table_entry_exists(dvs.sdb, "FDB_TABLE", - "Vlan7:.*", - [("port", "Ethernet72"), - ("type", "dynamic"), - ] - ) - assert ok, str(extra) - ok, extra = dvs.is_table_entry_exists(dvs.sdb, "FDB_TABLE", - "Vlan7:*", - [("port", "Ethernet76"), - ("type", "dynamic"), - ] - ) - assert ok, str(extra) - - # check that the FDB entries were inserted into State DB, - # Vlan8 (tagged) in the key for Ethernet72, Ethernet76 - ok, extra = dvs.is_table_entry_exists(dvs.sdb, "FDB_TABLE", - "Vlan8:.*", - [("port", "Ethernet72"), - ("type", "dynamic"), - ] - ) - assert ok, str(extra) - ok, extra = dvs.is_table_entry_exists(dvs.sdb, "FDB_TABLE", - "Vlan8:*", - [("port", "Ethernet76"), - ("type", "dynamic"), - ] - ) - assert ok, str(extra) - - # enable warm restart - dvs.warm_restart_swss("true") - - # freeze orchagent for warm restart - (exitcode, result) = dvs.runcmd("/usr/bin/orchagent_restart_check", include_stderr=False) - assert result == "RESTARTCHECK succeeded\n" - time.sleep(2) - - try: - # restart orchagent - dvs.stop_swss() - - # check FDB learning mode - ok, extra = dvs.all_table_entry_has(dvs.adb, 'ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT', - ".*", - [("SAI_BRIDGE_PORT_ATTR_FDB_LEARNING_MODE", "SAI_BRIDGE_PORT_FDB_LEARNING_MODE_DISABLE")]) - assert ok, str(extra) - # check FDB aging time - ok, extra = dvs.all_table_entry_has(dvs.adb, 'ASIC_STATE:SAI_OBJECT_TYPE_SWITCH', - ".*", - [("SAI_SWITCH_ATTR_FDB_AGING_TIME", "0")]) - assert ok, str(extra) - - dvs.start_swss() - time.sleep(2) - - # Get mapping between interface name and its bridge port_id - # Note: they are changed - iface_2_bridge_port_id = dvs.get_map_iface_bridge_port_id(dvs.adb) - - # check that the FDB entries were inserted into ASIC DB - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_DYNAMIC"), - ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", iface_2_bridge_port_id["Ethernet64"]), - ] - ) - assert ok, str(extra) - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_DYNAMIC"), - ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", iface_2_bridge_port_id["Ethernet68"]), - ] - ) - assert ok, str(extra) - - # check that the FDB entries were inserted into ASIC DB - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_DYNAMIC"), - ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", iface_2_bridge_port_id["Ethernet72"]), - ] - ) - assert ok, str(extra) - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_DYNAMIC"), - ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", iface_2_bridge_port_id["Ethernet76"]), - ] - ) - assert ok, str(extra) - - # check FDB learning mode - ok, extra = dvs.is_table_entry_exists(dvs.adb, 'ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT', - iface_2_bridge_port_id["Ethernet64"], - [("SAI_BRIDGE_PORT_ATTR_FDB_LEARNING_MODE", "SAI_BRIDGE_PORT_FDB_LEARNING_MODE_HW")]) - assert ok, str(extra) - ok, extra = dvs.is_table_entry_exists(dvs.adb, 'ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT', - iface_2_bridge_port_id["Ethernet68"], - [("SAI_BRIDGE_PORT_ATTR_FDB_LEARNING_MODE", "SAI_BRIDGE_PORT_FDB_LEARNING_MODE_HW")]) - assert ok, str(extra) - - ok, extra = dvs.is_table_entry_exists(dvs.adb, 'ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT', - iface_2_bridge_port_id["Ethernet72"], - [("SAI_BRIDGE_PORT_ATTR_FDB_LEARNING_MODE", "SAI_BRIDGE_PORT_FDB_LEARNING_MODE_HW")]) - assert ok, str(extra) - ok, extra = dvs.is_table_entry_exists(dvs.adb, 'ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT', - iface_2_bridge_port_id["Ethernet76"], - [("SAI_BRIDGE_PORT_ATTR_FDB_LEARNING_MODE", "SAI_BRIDGE_PORT_FDB_LEARNING_MODE_HW")]) - assert ok, str(extra) - - time.sleep(2) - counter_restarted = dvs.getCrmCounterValue('STATS', 'crm_stats_fdb_entry_used') - assert counter_inserted == counter_restarted - - # check fdb aging attr - ok, extra = dvs.all_table_entry_has_no(dvs.adb, 'ASIC_STATE:SAI_OBJECT_TYPE_SWITCH', - ".*", - ["SAI_SWITCH_ATTR_FDB_AGING_TIME"]) - - finally: - # disable warm restart - dvs.warm_restart_swss("false") - # slow down crm polling - dvs.crm_poll_set("10000") - - def test_FdbAddedAfterMemberCreated(self, dvs, testlog): - dvs.setup_db() - - dvs.clear_fdb() - time.sleep(2) - - # create a FDB entry in Application DB - create_entry_pst( - dvs.pdb, - "FDB_TABLE", "Vlan2:52-54-00-25-06-E9", - [ - ("port", "Ethernet0"), - ("type", "dynamic"), - ] - ) - - vlan_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - bp_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") - vm_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") - - # create vlan - dvs.create_vlan("2") - time.sleep(1) - - # Get bvid from vlanid - ok, bvid = dvs.get_vlan_oid(dvs.adb, "2") - assert ok, bvid - - # check that the FDB entry wasn't inserted into ASIC DB - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [("mac", "52:54:00:25:06:E9"), ("bvid", bvid)], []) - assert ok == False, "The fdb entry leaked to ASIC" - - # create vlan member - dvs.create_vlan_member("2", "Ethernet0") - time.sleep(1) - - # check that the vlan information was propagated - vlan_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - bp_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") - vm_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") - - assert vlan_after - vlan_before == 1, "The Vlan2 wasn't created" - assert bp_after - bp_before == 1, "The bridge port wasn't created" - assert vm_after - vm_before == 1, "The vlan member wasn't added" - - # Get mapping between interface name and its bridge port_id - iface_2_bridge_port_id = dvs.get_map_iface_bridge_port_id(dvs.adb) - - # check that the FDB entry was inserted into ASIC DB - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [("mac", "52:54:00:25:06:E9"), ("bvid", bvid)], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_DYNAMIC"), - ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", iface_2_bridge_port_id["Ethernet0"])]) - assert ok, str(extra) - - dvs.clear_fdb() - dvs.remove_vlan_member("2", "Ethernet0") - dvs.remove_vlan("2") - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_fdb_update.py b/tests/test_fdb_update.py deleted file mode 100644 index 128dc3773b..0000000000 --- a/tests/test_fdb_update.py +++ /dev/null @@ -1,327 +0,0 @@ -import os -import sys -import time -import json -import pytest - -from swsscommon import swsscommon -from distutils.version import StrictVersion - -class TestFdbUpdate(object): - def create_entry(self, tbl, key, pairs): - fvs = swsscommon.FieldValuePairs(pairs) - tbl.set(key, fvs) - time.sleep(1) - - def remove_entry(self, tbl, key): - tbl._del(key) - time.sleep(1) - - def create_entry_tbl(self, db, table, key, pairs): - tbl = swsscommon.Table(db, table) - self.create_entry(tbl, key, pairs) - - def remove_entry_tbl(self, db, table, key): - tbl = swsscommon.Table(db, table) - self.remove_entry(tbl, key) - - def create_entry_pst(self, db, table, key, pairs): - tbl = swsscommon.ProducerStateTable(db, table) - self.create_entry(tbl, key, pairs) - - def remove_entry_pst(self, db, table, key): - tbl = swsscommon.ProducerStateTable(db, table) - self.remove_entry(tbl, key) - - def how_many_entries_exist(self, db, table): - tbl = swsscommon.Table(db, table) - return len(tbl.getKeys()) - - def get_mac_by_bridge_id(self, dvs, bridge_id): - tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") - keys = tbl.getKeys() - - mac = [] - for key in keys: - (status, fvs) = tbl.get(key) - assert status - value = dict(fvs) - if value["SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID"] == bridge_id: - try: - d_key = json.loads(key) - except ValueError: - d_key = json.loads('{' + key + '}') - mac.append(d_key["mac"]) - return mac - - def test_FDBAddedAndUpdated(self, dvs, testlog): - dvs.setup_db() - dvs.clear_fdb() - time.sleep(2) - - # create a FDB entry in Application DB - self.create_entry_pst( - dvs.pdb, - "FDB_TABLE", "Vlan2:52-54-00-25-06-E9", - [ - ("port", "Ethernet0"), - ("type", "dynamic"), - ] - ) - - # check that the FDB entry wasn't inserted into ASIC DB - assert self.how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 0, "The fdb entry leaked to ASIC" - - vlan_before = self.how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - bp_before = self.how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") - vm_before = self.how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") - - # create vlan - self.create_entry_tbl( - dvs.cdb, - "VLAN", "Vlan2", - [ - ("vlanid", "2"), - ] - ) - - # create vlan member entry in Config db - self.create_entry_tbl( - dvs.cdb, - "VLAN_MEMBER", "Vlan2|Ethernet0", - [ - ("tagging_mode", "untagged"), - ] - ) - - # check that the vlan information was propagated - vlan_after = self.how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - bp_after = self.how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") - vm_after = self.how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") - - assert vlan_after - vlan_before == 1, "The Vlan2 wasn't created" - assert bp_after - bp_before == 1, "The bridge port wasn't created" - assert vm_after - vm_before == 1, "The vlan member wasn't added" - - # Get bvid from vlanid - ok, bvid = dvs.get_vlan_oid(dvs.adb, "2") - assert ok, bvid - - # Get mapping between interface name and its bridge port_id - iface_2_bridge_port_id = dvs.get_map_iface_bridge_port_id(dvs.adb) - - # check that the FDB entry was inserted into ASIC DB - assert self.how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 1, "The fdb entry wasn't inserted to ASIC" - - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [("mac", "52:54:00:25:06:E9"), ("bvid", bvid)], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_DYNAMIC"), - ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", iface_2_bridge_port_id["Ethernet0"])]) - assert ok, str(extra) - - # create vlan member entry in Config DB - self.create_entry_tbl( - dvs.cdb, - "VLAN_MEMBER", "Vlan2|Ethernet4", - [ - ("tagging_mode", "untagged"), - ] - ) - - # update FDB entry port in Application DB - self.create_entry_pst( - dvs.pdb, - "FDB_TABLE", "Vlan2:52-54-00-25-06-E9", - [ - ("port", "Ethernet4"), - ("type", "dynamic"), - ] - ) - - # Get mapping between interface name and its bridge port_id - iface_2_bridge_port_id = dvs.get_map_iface_bridge_port_id(dvs.adb) - - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [("mac", "52:54:00:25:06:E9"), ("bvid", bvid)], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_DYNAMIC"), - ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", iface_2_bridge_port_id["Ethernet4"])]) - assert ok, str(extra) - - # remove FDB entry from Application DB - self.remove_entry_pst( - dvs.pdb, - "FDB_TABLE", "Vlan2:52-54-00-25-06-E9" - ) - - # remove vlan member entry from Config DB - self.remove_entry_tbl( - dvs.cdb, - "VLAN_MEMBER", "Vlan2|Ethernet4" - ) - self.remove_entry_tbl( - dvs.cdb, - "VLAN_MEMBER", "Vlan2|Ethernet0" - ) - - # remove vlan entry from Config DB - self.remove_entry_tbl( - dvs.cdb, - "VLAN", "Vlan2" - ) - - def test_FDBLearnedAndUpdated(self, dvs, testlog): - dvs.setup_db() - - dvs.clear_fdb() - - # create vlan; create vlan member - dvs.create_vlan("6") - dvs.create_vlan_member("6", "Ethernet64") - dvs.create_vlan_member("6", "Ethernet68") - dvs.create_vlan_member("6", "Ethernet72") - - # Get mapping between interface name and its bridge port_id - time.sleep(2) - iface_2_bridge_port_id = dvs.get_map_iface_bridge_port_id(dvs.adb) - - # bring up vlan and member - dvs.set_interface_status("Vlan6", "up") - - dvs.add_ip_address("Vlan6", "6.6.6.1/24") - - dvs.set_interface_status("Ethernet64", "up") - dvs.set_interface_status("Ethernet68", "up") - dvs.set_interface_status("Ethernet72", "up") - - dvs.servers[16].runcmd("ifconfig eth0 hw ether 00:00:00:00:00:11") - dvs.servers[16].runcmd("ifconfig eth0 6.6.6.6/24 up") - dvs.servers[16].runcmd("ip route add default via 6.6.6.1") - dvs.servers[17].runcmd("ifconfig eth0 hw ether 00:00:00:00:17:11") - dvs.servers[17].runcmd("ifconfig eth0 6.6.6.7/24 up") - dvs.servers[17].runcmd("ip route add default via 6.6.6.1") - time.sleep(2) - - # get neighbor and arp entry - rc = dvs.servers[16].runcmd("ping -c 1 6.6.6.7") - assert rc == 0 - rc = dvs.servers[17].runcmd("ping -c 1 6.6.6.6") - assert rc == 0 - time.sleep(2) - - # check that the FDB entries were inserted into ASIC DB - Ethernet64_mac = self.get_mac_by_bridge_id(dvs, iface_2_bridge_port_id["Ethernet64"]) - assert "00:00:00:00:00:11" in Ethernet64_mac - - # update FDB entry port in Application DB - self.create_entry_pst( - dvs.pdb, - "FDB_TABLE", "Vlan6:00-00-00-00-00-11", - [ - ("port", "Ethernet72"), - ("type", "dynamic"), - ] - ) - - # check that the FDB entry was updated in ASIC DB - Ethernet72_mac = self.get_mac_by_bridge_id(dvs, iface_2_bridge_port_id["Ethernet72"]) - assert "00:00:00:00:00:11" in Ethernet72_mac, "Updating fdb entry to Ethernet72 failed" - - Ethernet64_mac = self.get_mac_by_bridge_id(dvs, iface_2_bridge_port_id["Ethernet64"]) - assert "00:00:00:00:00:11" not in Ethernet64_mac, "Updating fdb entry from Ethernet64 failed" - - # remove FDB entry from Application DB - self.remove_entry_pst( - dvs.pdb, - "FDB_TABLE", "Vlan6:00-00-00-00-00-11" - ) - - # restore the default value of the servers - dvs.servers[16].runcmd("ip route del default via 6.6.6.1") - dvs.servers[16].runcmd("ifconfig eth0 0 down") - dvs.servers[17].runcmd("ip route del default via 6.6.6.1") - dvs.servers[17].runcmd("ifconfig eth0 0 down") - dvs.servers[18].runcmd("ifconfig eth0 0 down") - - # bring down port - dvs.set_interface_status("Ethernet64", "down") - dvs.set_interface_status("Ethernet68", "down") - dvs.set_interface_status("Ethernet72", "down") - - # remove vlan ip - dvs.remove_ip_address("Vlan6", "6.6.6.1/24") - - # bring down vlan - dvs.set_interface_status("Vlan6", "down") - - # remove vlan member; remove vlan - dvs.remove_vlan_member("6", "Ethernet64") - dvs.remove_vlan_member("6", "Ethernet68") - dvs.remove_vlan_member("6", "Ethernet72") - dvs.remove_vlan("6") - - # clear fdb - dvs.clear_fdb() - - def test_FDBLearnedAndFlushed(self, dvs, testlog): - dvs.setup_db() - - dvs.clear_fdb() - - VLAN = "9" - VLAN_NAME = "Vlan9" - PORT = "Ethernet80" - server = 20 - server_mac = "00:00:00:00:20:11" - - # create vlan; create vlan member - dvs.create_vlan(VLAN) - dvs.create_vlan_member(VLAN, PORT) - time.sleep(2) - - # Get mapping between interface name and its bridge port_id - iface_2_bridge_port_id = dvs.get_map_iface_bridge_port_id(dvs.adb) - - # bring up vlan and member - dvs.set_interface_status(VLAN_NAME, "up") - dvs.add_ip_address(VLAN_NAME, "7.7.7.1/24") - dvs.set_interface_status(PORT, "up") - - dvs.servers[server].runcmd("ifconfig eth0 hw ether {}".format(server_mac)) - dvs.servers[server].runcmd("ifconfig eth0 7.7.7.7/24 up") - - # get neighbor and arp entry - rc = dvs.servers[server].runcmd("ping -c 1 7.7.7.1") - assert rc == 0 - time.sleep(2) - - # check that the FDB entries were inserted into ASIC DB - mac = self.get_mac_by_bridge_id(dvs, iface_2_bridge_port_id[PORT]) - assert server_mac in mac - - # bring down port - dvs.servers[server].runcmd("ip link set down dev eth0") == 0 - #dvs.set_interface_status(PORT, "down") - time.sleep(2) - - # fdb should be flushed - mac = self.get_mac_by_bridge_id(dvs, iface_2_bridge_port_id[PORT]) - assert not mac - - # remove vlan ip - dvs.remove_ip_address(VLAN_NAME, "7.7.7.1/24") - - # bring down vlan - dvs.set_interface_status(VLAN_NAME, "down") - - # remove vlan member; remove vlan - dvs.remove_vlan_member(VLAN, PORT) - dvs.remove_vlan(VLAN) - - # restore the default value of the servers - dvs.servers[server].runcmd("ifconfig eth0 0 down") - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_fdbsync.py b/tests/test_fdbsync.py deleted file mode 100644 index 8d85e8458e..0000000000 --- a/tests/test_fdbsync.py +++ /dev/null @@ -1,420 +0,0 @@ -import time -import json -import pytest -import pdb - -from swsscommon import swsscommon - -def create_entry(tbl, key, pairs): - fvs = swsscommon.FieldValuePairs(pairs) - tbl.set(key, fvs) - time.sleep(1) - -def create_entry_tbl(db, table, separator, key, pairs): - tbl = swsscommon.Table(db, table) - create_entry(tbl, key, pairs) - -def delete_entry_tbl(db, table, key): - tbl = swsscommon.Table(db, table) - tbl._del(key) - time.sleep(1) - -def create_evpn_nvo(dvs, nvoname, tnlname): - conf_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - - attrs = [ - ("source_vtep", tnlname), - ] - - # create the VXLAN tunnel Term entry in Config DB - create_entry_tbl( - conf_db, - "VXLAN_EVPN_NVO", '|', nvoname, - attrs, - ) - -def remove_evpn_nvo(dvs, nvoname): - conf_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - delete_entry_tbl(conf_db, "VXLAN_EVPN_NVO", nvoname, ) - -def set_admin_status(dvs, interface, status): - tbl = swsscommon.Table(dvs.cdb, "PORT") - fvs = swsscommon.FieldValuePairs([("admin_status", status)]) - tbl.set(interface, fvs) - time.sleep(1) - -tunnel_name = 'vxlan' -tunnel_vlan = 'Vlan20' -tunnel_device = 'vxlan-20' -tunnel_vlan_id = '20' -tunnel_vni = '10020' -tunnel_src_ip = '12.1.1.1' -tunnel_remote_ip = '10.0.0.7' -tunnel_remote_fdb = '00:11:01:00:00:01' -tunnel_remote_fdb2 = '12:34:55:12:34:56' -tunnel_remote_fdb_type = 'dynamic' -tunnel_remote_fdb_type_static = 'static' -state_db_name = 'FDB_TABLE' -local_intf = 'Ethernet8' -local_intf2 = 'Ethernet12' -tunnel_name_nvo = 'nvo' -app_fdb_name = 'VXLAN_FDB_TABLE:' -tunnel_remote_imet = '00:00:00:00:00:00' -tunnel_remote_imet_type = 'permanent' -app_imet_name = 'VXLAN_REMOTE_VNI_TABLE:' - -class TestFdbsync(object): - - - def test_AddLocalFDB(self, dvs, testlog): - dvs.setup_db() - create_evpn_nvo(dvs, tunnel_name_nvo , tunnel_name) - - set_admin_status(dvs, local_intf, "up") - - # create vlan; create vlan member - dvs.create_vlan(tunnel_vlan_id) - dvs.create_vlan_member(tunnel_vlan_id, local_intf) - - create_entry_tbl( - dvs.sdb, - state_db_name, '|', tunnel_vlan + ':' + tunnel_remote_fdb, - [ - ("port", local_intf), - ("type", tunnel_remote_fdb_type), - ] - ) - # check that the FDB entries were inserted into State DB - ok, extra = dvs.is_table_entry_exists(dvs.sdb, state_db_name, - tunnel_vlan + ":.*", - [("port", local_intf), - ("type", tunnel_remote_fdb_type), - ] - ) - assert ok, str(extra) - - (exitcode, output) = dvs.runcmd(['sh', '-c', "bridge fdb show | grep " + tunnel_remote_fdb + " | wc -l"]) - num = int(output.strip()) - assert num == 1 - - delete_entry_tbl( - dvs.sdb, - state_db_name, tunnel_vlan + ':' + tunnel_remote_fdb, - ) - - (exitcode, output) = dvs.runcmd(['sh', '-c', "bridge fdb show | grep " + tunnel_remote_fdb]) - assert output == '' - remove_evpn_nvo(dvs, tunnel_name_nvo) - - def test_AddLocalFDBWithOutNVO(self, dvs, testlog): - dvs.setup_db() - set_admin_status(dvs, local_intf, "up") - - # create vlan; create vlan member - dvs.create_vlan(tunnel_vlan_id) - dvs.create_vlan_member(tunnel_vlan_id, local_intf) - - create_entry_tbl( - dvs.sdb, - state_db_name, '|', tunnel_vlan + ':' + tunnel_remote_fdb, - [ - ("port", local_intf), - ("type", tunnel_remote_fdb_type), - ] - ) - - (exitcode, output) = dvs.runcmd(['sh', '-c', "bridge fdb show | grep " + tunnel_remote_fdb ]) - assert output == '' - - delete_entry_tbl( - dvs.sdb, - state_db_name, tunnel_vlan + ':' + tunnel_remote_fdb, - ) - - def test_AddLocalFDBPortUpdate(self, dvs, testlog): - dvs.setup_db() - create_evpn_nvo(dvs, tunnel_name_nvo, tunnel_name) - - set_admin_status(dvs, local_intf, "up") - set_admin_status(dvs, local_intf2, "up") - - # create vlan; create vlan member - dvs.create_vlan(tunnel_vlan_id) - dvs.create_vlan_member(tunnel_vlan_id, local_intf) - dvs.create_vlan_member(tunnel_vlan_id, local_intf2) - - #pdb.set_trace() - - create_entry_tbl( - dvs.sdb, - state_db_name, '|', tunnel_vlan + ':' + tunnel_remote_fdb, - [ - ("port", local_intf), - ("type", tunnel_remote_fdb_type), - ] - ) - - (exitcode, output) = dvs.runcmd(['sh', '-c', "bridge fdb show | grep " + tunnel_remote_fdb + " | wc -l"]) - num = int(output.strip()) - assert num == 1 - - (exitcode, output) = dvs.runcmd(['sh', '-c', "bridge fdb show | grep " + tunnel_remote_fdb]) - assert local_intf in output - - create_entry_tbl( - dvs.sdb, - state_db_name, '|', tunnel_vlan + ':' + tunnel_remote_fdb, - [ - ("port", local_intf2), - ("type", tunnel_remote_fdb_type), - ] - ) - # check that the FDB entries were inserted into State DB - ok, extra = dvs.is_table_entry_exists(dvs.sdb, state_db_name, - tunnel_vlan + ":.*", - [("port", local_intf2), - ("type", tunnel_remote_fdb_type), - ] - ) - assert ok, str(extra) - - (exitcode, output) = dvs.runcmd(['sh', '-c', "bridge fdb show | grep " + tunnel_remote_fdb + " | wc -l"]) - num = int(output.strip()) - assert num == 1 - - (exitcode, output) = dvs.runcmd(['sh', '-c', "bridge fdb show | grep " + tunnel_remote_fdb]) - assert local_intf2 in output - - - delete_entry_tbl( - dvs.sdb, - state_db_name, tunnel_vlan + ':' + tunnel_remote_fdb, - ) - - (exitcode, output) = dvs.runcmd(['sh', '-c', "bridge fdb show | grep " + tunnel_remote_fdb]) - assert output == '' - remove_evpn_nvo(dvs, tunnel_name_nvo) - - def test_AddLocalStaticFDB(self, dvs, testlog): - dvs.setup_db() - create_evpn_nvo(dvs, tunnel_name_nvo, tunnel_name) - - set_admin_status(dvs, local_intf, "up") - - # create vlan; create vlan member - dvs.create_vlan(tunnel_vlan_id) - dvs.create_vlan_member(tunnel_vlan_id, local_intf) - - create_entry_tbl( - dvs.sdb, - state_db_name, '|', tunnel_vlan + ':' + tunnel_remote_fdb, - [ - ("port", local_intf), - ("type", tunnel_remote_fdb_type_static), - ] - ) - - # check that the FDB entries were inserted into State DB - ok, extra = dvs.is_table_entry_exists(dvs.sdb, state_db_name, - tunnel_vlan + ":.*", - [("port", local_intf), - ("type", tunnel_remote_fdb_type_static), - ] - ) - assert ok, str(extra) - - (exitcode, output) = dvs.runcmd(['sh', '-c', "bridge fdb show | grep " + tunnel_remote_fdb + " | wc -l"]) - num = int(output.strip()) - assert num == 1 - - (exitcode, output) = dvs.runcmd(['sh', '-c', "bridge fdb show | grep " + tunnel_remote_fdb]) - assert tunnel_remote_fdb_type_static in output - - delete_entry_tbl( - dvs.sdb, - state_db_name, tunnel_vlan + ':' + tunnel_remote_fdb, - ) - - (exitcode, output) = dvs.runcmd(['sh', '-c', "bridge fdb show | grep " + tunnel_remote_fdb]) - assert output == '' - remove_evpn_nvo(dvs, tunnel_name_nvo) - - def test_AddVxlanFDB(self, dvs, testlog): - dvs.setup_db() - create_evpn_nvo(dvs, tunnel_name_nvo, tunnel_name) - - dvs.runcmd("ip link add {} type vxlan id {} local {}".format(tunnel_device, tunnel_vni, tunnel_src_ip)) - dvs.runcmd("ip link set up {}".format(tunnel_device)) - dvs.runcmd("bridge fdb add {} dev {} dst {} self {}".format(tunnel_remote_fdb2, tunnel_device, tunnel_remote_ip, tunnel_remote_fdb_type_static)) - - # Check in the APP DB for the FDB entry to be present APP_VXLAN_FDB_TABLE_NAME "APP_VXLAN_FDB_TABLE_NAME" - # check application database - tbl = swsscommon.Table(dvs.pdb, app_fdb_name+tunnel_vlan) - intf_entries = tbl.getKeys() - assert len(intf_entries) == 1 - assert intf_entries[0] == tunnel_remote_fdb2 - (status, fvs) = tbl.get(intf_entries[0]) - assert status == True - assert len(fvs) == 3 - for fv in fvs: - if fv[0] == "remote_vtep": - assert fv[1] == tunnel_remote_ip - elif fv[0] == "type": - assert fv[1] == tunnel_remote_fdb_type_static - elif fv[0] == "vni": - assert fv[1] == tunnel_vni - else: - assert False - - # Remove the fdb entry, and check the APP_DB - dvs.runcmd("bridge fdb del {} dev {} dst {} self {}".format(tunnel_remote_fdb2, tunnel_device, tunnel_remote_ip, tunnel_remote_fdb_type_static)) - ebl = swsscommon.Table(dvs.pdb, app_fdb_name+tunnel_vlan) - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - def test_AddVxlanIMET(self, dvs, testlog): - - dvs.setup_db() - create_evpn_nvo(dvs, tunnel_name_nvo, tunnel_name) - - dvs.runcmd("ip link add {} type vxlan id {} local {}".format(tunnel_device, tunnel_vni, tunnel_src_ip)) - dvs.runcmd("ip link set up {}".format(tunnel_device)) - dvs.runcmd("bridge fdb add {} dev {} dst {} self {}".format(tunnel_remote_imet, tunnel_device, tunnel_remote_ip, tunnel_remote_imet_type)) - - # Check in the APP DB for the FDB entry to be present APP_VXLAN_FDB_TABLE_NAME "APP_VXLAN_FDB_TABLE_NAME" - # check application database - tbl = swsscommon.Table(dvs.pdb, app_imet_name+tunnel_vlan) - intf_entries = tbl.getKeys() - assert len(intf_entries) == 1 - assert intf_entries[0] == tunnel_remote_ip - (status, fvs) = tbl.get(intf_entries[0]) - assert status == True - assert len(fvs) == 1 - for fv in fvs: - if fv[0] == "vni": - assert fv[1] == tunnel_vni - else: - assert False - - # Remove the fdb entry, and check the APP_DB - dvs.runcmd("bridge fdb del {} dev {} dst {} self {}".format(tunnel_remote_imet, tunnel_device, tunnel_remote_ip, tunnel_remote_imet_type)) - tbl = swsscommon.Table(dvs.pdb, app_imet_name+tunnel_vlan) - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - def test_VxlanFDBToLocal(self, dvs, testlog): - dvs.setup_db() - create_evpn_nvo(dvs, tunnel_name_nvo, tunnel_name) - - dvs.runcmd("ip link add {} type vxlan id {} local {}".format(tunnel_device, tunnel_vni, tunnel_src_ip)) - dvs.runcmd("ip link set up {}".format(tunnel_device)) - dvs.runcmd("bridge fdb add {} dev {} dst {} self {}".format(tunnel_remote_fdb2, tunnel_device, tunnel_remote_ip, tunnel_remote_fdb_type)) - - # Check in the APP DB for the FDB entry to be present APP_VXLAN_FDB_TABLE_NAME "APP_VXLAN_FDB_TABLE_NAME" - # check application database - tbl = swsscommon.Table(dvs.pdb, app_fdb_name+tunnel_vlan) - intf_entries = tbl.getKeys() - assert len(intf_entries) == 1 - assert intf_entries[0] == tunnel_remote_fdb2 - (status, fvs) = tbl.get(intf_entries[0]) - assert status == True - assert len(fvs) == 3 - for fv in fvs: - if fv[0] == "remote_vtep": - assert fv[1] == tunnel_remote_ip - elif fv[0] == "type": - assert fv[1] == tunnel_remote_fdb_type - elif fv[0] == "vni": - assert fv[1] == tunnel_vni - else: - assert False - - create_evpn_nvo(dvs, tunnel_name_nvo, tunnel_name) - - set_admin_status(dvs, local_intf, "up") - - # create vlan; create vlan member - dvs.create_vlan(tunnel_vlan_id) - dvs.create_vlan_member(tunnel_vlan_id, local_intf) - - create_entry_tbl( - dvs.sdb, - state_db_name, '|', tunnel_vlan + ':' + tunnel_remote_fdb2, - [ - ("port", local_intf), - ("type", tunnel_remote_fdb_type), - ] - ) - # check that the FDB entries were inserted into State DB - ok, extra = dvs.is_table_entry_exists(dvs.sdb, state_db_name, - tunnel_vlan + ":.*", - [("port", local_intf), - ("type", tunnel_remote_fdb_type), - ] - ) - assert ok, str(extra) - - (exitcode, output) = dvs.runcmd(['sh', '-c', "bridge fdb show | grep " + tunnel_remote_fdb2 + " | grep Ethernet8 | wc -l"]) - num = int(output.strip()) - assert num == 1 - - delete_entry_tbl( - dvs.sdb, - state_db_name, tunnel_vlan + ':' + tunnel_remote_fdb2, - ) - - def test_LocalFDBToVxlan(self, dvs, testlog): - dvs.setup_db() - create_evpn_nvo(dvs, tunnel_name_nvo, tunnel_name) - - set_admin_status(dvs, local_intf, "up") - - # create vlan; create vlan member - dvs.create_vlan(tunnel_vlan_id) - dvs.create_vlan_member(tunnel_vlan_id, local_intf) - - create_entry_tbl( - dvs.sdb, - state_db_name, '|', tunnel_vlan + ':' + tunnel_remote_fdb, - [ - ("port", local_intf), - ("type", tunnel_remote_fdb_type), - ] - ) - # check that the FDB entries were inserted into State DB - ok, extra = dvs.is_table_entry_exists(dvs.sdb, state_db_name, - tunnel_vlan + ":.*", - [("port", local_intf), - ("type", tunnel_remote_fdb_type), - ] - ) - assert ok, str(extra) - - (exitcode, output) = dvs.runcmd(['sh', '-c', "bridge fdb show | grep " + tunnel_remote_fdb + " | wc -l"]) - num = int(output.strip()) - assert num == 1 - - #pdb.set_trace() - dvs.runcmd("ip link add {} type vxlan id {} local {}".format(tunnel_device, tunnel_vni, tunnel_src_ip)) - dvs.runcmd("ip link set up {}".format(tunnel_device)) - dvs.runcmd("bridge fdb add {} dev {} dst {} self {}".format(tunnel_remote_fdb, tunnel_device, tunnel_remote_ip, tunnel_remote_fdb_type)) - - # Check in the APP DB for the FDB entry to be present APP_VXLAN_FDB_TABLE_NAME "APP_VXLAN_FDB_TABLE_NAME" - # check application database - tbl = swsscommon.Table(dvs.pdb, app_fdb_name+tunnel_vlan) - intf_entries = tbl.getKeys() - assert len(intf_entries) == 1 - assert intf_entries[0] == tunnel_remote_fdb - (status, fvs) = tbl.get(intf_entries[0]) - assert status == True - assert len(fvs) == 3 - for fv in fvs: - if fv[0] == "remote_vtep": - assert fv[1] == tunnel_remote_ip - elif fv[0] == "type": - assert fv[1] == tunnel_remote_fdb_type - elif fv[0] == "vni": - assert fv[1] == tunnel_vni - else: - assert False - diff --git a/tests/test_fgnhg.py b/tests/test_fgnhg.py deleted file mode 100644 index 645853e24c..0000000000 --- a/tests/test_fgnhg.py +++ /dev/null @@ -1,869 +0,0 @@ -import os -import re -import time -import json -import pytest - -from dvslib.dvs_common import wait_for_result -from swsscommon import swsscommon - -IF_TB = 'INTERFACE' -VLAN_TB = 'VLAN' -VLAN_MEMB_TB = 'VLAN_MEMBER' -VLAN_IF_TB = 'VLAN_INTERFACE' -VLAN_IF = 'VLAN_INTERFACE' -FG_NHG = 'FG_NHG' -FG_NHG_PREFIX = 'FG_NHG_PREFIX' -FG_NHG_MEMBER = 'FG_NHG_MEMBER' -ROUTE_TB = "ROUTE_TABLE" -ASIC_ROUTE_TB = "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY" -ASIC_NHG = "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP" -ASIC_NHG_MEMB = "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER" -ASIC_NH_TB = "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP" -ASIC_RIF = "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE" - -def create_entry(db, table, key, pairs): - db.create_entry(table, key, pairs) - programmed_table = db.wait_for_entry(table,key) - assert programmed_table != {} - -def remove_entry(db, table, key): - db.delete_entry(table, key) - db.wait_for_deleted_entry(table,key) - -def get_asic_route_key(asic_db, ipprefix): - route_exists = False - key = '' - keys = asic_db.get_keys(ASIC_ROUTE_TB) - for k in keys: - rt_key = json.loads(k) - - if rt_key['dest'] == ipprefix: - route_exists = True - key = k - break - assert route_exists - return key - -def validate_asic_nhg_fine_grained_ecmp(asic_db, ipprefix, size): - def _access_function(): - false_ret = (False, '') - keys = asic_db.get_keys(ASIC_ROUTE_TB) - key = '' - route_exists = False - for k in keys: - rt_key = json.loads(k) - if rt_key['dest'] == ipprefix: - route_exists = True - key = k - if not route_exists: - return false_ret - - fvs = asic_db.get_entry(ASIC_ROUTE_TB, key) - if not fvs: - return false_ret - - nhgid = fvs.get("SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID") - fvs = asic_db.get_entry(ASIC_NHG, nhgid) - if not fvs: - return false_ret - - nhg_type = fvs.get("SAI_NEXT_HOP_GROUP_ATTR_TYPE") - if nhg_type != "SAI_NEXT_HOP_GROUP_TYPE_FINE_GRAIN_ECMP": - return false_ret - nhg_cfg_size = fvs.get("SAI_NEXT_HOP_GROUP_ATTR_CONFIGURED_SIZE") - if int(nhg_cfg_size) != size: - return false_ret - return (True, nhgid) - - _, result = wait_for_result(_access_function, - failure_message="Fine Grained ECMP route not found") - return result - -def validate_asic_nhg_router_interface(asic_db, ipprefix): - def _access_function(): - false_ret = (False, '') - keys = asic_db.get_keys(ASIC_ROUTE_TB) - key = '' - route_exists = False - for k in keys: - rt_key = json.loads(k) - if rt_key['dest'] == ipprefix: - route_exists = True - key = k - if not route_exists: - return false_ret - - fvs = asic_db.get_entry(ASIC_ROUTE_TB, key) - if not fvs: - return false_ret - - rifid = fvs.get("SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID") - fvs = asic_db.get_entry(ASIC_RIF, rifid) - if not fvs: - return false_ret - - return (True, rifid) - _, result = wait_for_result(_access_function, failure_message="Route pointing to RIF not found") - return result - -def validate_asic_nhg_regular_ecmp(asic_db, ipprefix): - def _access_function(): - false_ret = (False, '') - keys = asic_db.get_keys(ASIC_ROUTE_TB) - key = '' - route_exists = False - for k in keys: - rt_key = json.loads(k) - if rt_key['dest'] == ipprefix: - route_exists = True - key = k - if not route_exists: - return false_ret - - fvs = asic_db.get_entry(ASIC_ROUTE_TB, key) - if not fvs: - return false_ret - - nhgid = fvs.get("SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID") - fvs = asic_db.get_entry(ASIC_NHG, nhgid) - if not fvs: - return false_ret - - nhg_type = fvs.get("SAI_NEXT_HOP_GROUP_ATTR_TYPE") - if nhg_type != "SAI_NEXT_HOP_GROUP_TYPE_DYNAMIC_UNORDERED_ECMP": - return false_ret - return (True, nhgid) - _, result = wait_for_result(_access_function, failure_message="SAI_NEXT_HOP_GROUP_TYPE_DYNAMIC_UNORDERED_ECMP not found") - return result - -def get_nh_oid_map(asic_db): - nh_oid_map = {} - keys = asic_db.get_keys(ASIC_NH_TB) - for key in keys: - fvs = asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP", key) - assert fvs != {} - nh_oid_map[key] = fvs["SAI_NEXT_HOP_ATTR_IP"] - - assert nh_oid_map != {} - return nh_oid_map - -def verify_programmed_fg_asic_db_entry(asic_db,nh_memb_exp_count,nh_oid_map,nhgid,bucket_size): - def _access_function(): - false_ret = (False, None) - ret = True - nh_memb_count = {} - for key in nh_memb_exp_count: - nh_memb_count[key] = 0 - - members = asic_db.get_keys(ASIC_NHG_MEMB) - memb_dict = {} - - for member in members: - fvs = asic_db.get_entry(ASIC_NHG_MEMB, member) - if fvs == {}: - return false_ret - index = -1 - nh_oid = "0" - memb_nhgid = "0" - for key, val in fvs.items(): - if key == "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_INDEX": - index = int(val) - elif key == "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID": - nh_oid = val - elif key == "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID": - memb_nhgid = val - if memb_nhgid == "0": - print("memb_nhgid was not set") - return false_ret - if memb_nhgid != nhgid: - continue - if (index == -1 or - nh_oid == "0" or - nh_oid_map.get(nh_oid,"NULL") == "NULL" or - nh_oid_map.get(nh_oid) not in nh_memb_exp_count): - print("Invalid nh: nh_oid " + nh_oid + " index " + str(index)) - if nh_oid_map.get(nh_oid,"NULL") == "NULL": - print("nh_oid is null") - if nh_oid_map.get(nh_oid) not in nh_memb_exp_count: - print("nh_memb_exp_count is " + str(nh_memb_exp_count) + " nh_oid_map val is " + nh_oid_map.get(nh_oid)) - return false_ret - memb_dict[index] = nh_oid_map.get(nh_oid) - idxs = [0]*bucket_size - for idx,memb in memb_dict.items(): - nh_memb_count[memb] = 1 + nh_memb_count[memb] - idxs[idx] = idxs[idx] + 1 - - for key in nh_memb_exp_count: - ret = ret and (nh_memb_count[key] == nh_memb_exp_count[key]) - for idx in idxs: - ret = ret and (idx == 1) - if ret != True: - print("Expected member count was " + str(nh_memb_exp_count) + " Received was " + str(nh_memb_count)) - print("Indexes arr was " + str(idxs)) - return (ret, nh_memb_count) - - status, result = wait_for_result(_access_function) - assert status, f"Exact match not found: expected={nh_memb_exp_count}, received={result}" - return result - -def shutdown_link(dvs, db, port): - dvs.servers[port].runcmd("ip link set down dev eth0") == 0 - db.wait_for_field_match("PORT_TABLE", "Ethernet%d" % (port * 4), {"oper_status": "down"}) - -def startup_link(dvs, db, port): - dvs.servers[port].runcmd("ip link set up dev eth0") == 0 - db.wait_for_field_match("PORT_TABLE", "Ethernet%d" % (port * 4), {"oper_status": "up"}) - -def run_warm_reboot(dvs): - dvs.warm_restart_swss("true") - - # Stop swss before modifing the configDB - dvs.stop_swss() - - # start to apply new port_config.ini - dvs.start_swss() - dvs.runcmd(['sh', '-c', 'supervisorctl start neighsyncd']) - dvs.runcmd(['sh', '-c', 'supervisorctl start restore_neighbors']) - -def verify_programmed_fg_state_db_entry(state_db, fg_nhg_prefix, nh_memb_exp_count): - memb_dict = nh_memb_exp_count - keys = state_db.get_keys("FG_ROUTE_TABLE") - assert len(keys) != 0 - for key in keys: - if key != fg_nhg_prefix: - continue - fvs = state_db.get_entry("FG_ROUTE_TABLE", key) - assert fvs != {} - for key, value in fvs.items(): - assert value in nh_memb_exp_count - memb_dict[value] = memb_dict[value] - 1 - - for idx,memb in memb_dict.items(): - assert memb == 0 - -def validate_fine_grained_asic_n_state_db_entries(asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size): - state_db_entry_memb_exp_count = {} - - for ip, cnt in nh_memb_exp_count.items(): - state_db_entry_memb_exp_count[ip + '@' + ip_to_if_map[ip]] = cnt - - verify_programmed_fg_asic_db_entry(asic_db,nh_memb_exp_count,nh_oid_map,nhgid,bucket_size) - verify_programmed_fg_state_db_entry(state_db, fg_nhg_prefix, state_db_entry_memb_exp_count) - -def program_route_and_validate_fine_grained_ecmp(app_db, asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size): - ips = "" - ifs = "" - for ip in nh_memb_exp_count: - if ips == "": - ips = ip - ifs = ip_to_if_map[ip] - else: - ips = ips + "," + ip - ifs = ifs + "," + ip_to_if_map[ip] - - ps = swsscommon.ProducerStateTable(app_db, ROUTE_TB) - fvs = swsscommon.FieldValuePairs([("nexthop", ips), ("ifname", ifs)]) - ps.set(fg_nhg_prefix, fvs) - validate_fine_grained_asic_n_state_db_entries(asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - -def create_interface_n_fg_ecmp_config(dvs, nh_range_start, nh_range_end, fg_nhg_name): - ip_to_if_map = {} - app_db = dvs.get_app_db() - config_db = dvs.get_config_db() - fvs_nul = {"NULL": "NULL"} - for i in range(nh_range_start, nh_range_end): - if_name_key = "Ethernet" + str(i*4) - ip_pref_key = "Ethernet" + str(i*4) + "|10.0.0." + str(i*2) + "/31" - create_entry(config_db, IF_TB, if_name_key, fvs_nul) - create_entry(config_db, IF_TB, ip_pref_key, fvs_nul) - dvs.port_admin_set(if_name_key, "up") - shutdown_link(dvs, app_db, i) - startup_link(dvs, app_db, i) - bank = 1 - if i >= (nh_range_end - nh_range_start)/2: - bank = 0 - fvs = {"FG_NHG": fg_nhg_name, "bank": str(bank)} - create_entry(config_db, FG_NHG_MEMBER, "10.0.0." + str(1 + i*2), fvs) - ip_to_if_map["10.0.0." + str(1 + i*2)] = if_name_key - dvs.runcmd("arp -s 10.0.0." + str(1 + i*2) + " 00:00:00:00:00:" + str(1 + i*2)) - return ip_to_if_map - -def remove_interface_n_fg_ecmp_config(dvs, nh_range_start, nh_range_end, fg_nhg_name): - app_db = dvs.get_app_db() - config_db = dvs.get_config_db() - for i in range(nh_range_start, nh_range_end): - if_name_key = "Ethernet" + str(i*4) - ip_pref_key = "Ethernet" + str(i*4) + "|10.0.0." + str(i*2) + "/31" - remove_entry(config_db, IF_TB, if_name_key) - remove_entry(config_db, IF_TB, ip_pref_key) - dvs.port_admin_set(if_name_key, "down") - shutdown_link(dvs, app_db, i) - remove_entry(config_db, FG_NHG_MEMBER, "10.0.0." + str(1 + i*2)) - remove_entry(config_db, FG_NHG, fg_nhg_name) - -def fine_grained_ecmp_base_test(dvs, match_mode): - app_db = dvs.get_app_db() - asic_db = dvs.get_asic_db() - config_db = dvs.get_config_db() - state_db = dvs.get_state_db() - fvs_nul = {"NULL": "NULL"} - NUM_NHs = 6 - fg_nhg_name = "fgnhg_v4" - fg_nhg_prefix = "2.2.2.0/24" - bucket_size = 60 - ip_to_if_map = {} - - fvs = {"bucket_size": str(bucket_size), "match_mode": match_mode} - create_entry(config_db, FG_NHG, fg_nhg_name, fvs) - - if match_mode == 'route-based': - fvs = {"FG_NHG": fg_nhg_name} - create_entry(config_db, FG_NHG_PREFIX, fg_nhg_prefix, fvs) - - for i in range(0,NUM_NHs): - if_name_key = "Ethernet" + str(i*4) - vlan_name_key = "Vlan" + str((i+1)*4) - ip_pref_key = vlan_name_key + "|10.0.0." + str(i*2) + "/31" - fvs = {"vlanid": str((i+1)*4)} - create_entry(config_db, VLAN_TB, vlan_name_key, fvs) - fvs = {"tagging_mode": "untagged"} - create_entry(config_db, VLAN_MEMB_TB, vlan_name_key + "|" + if_name_key, fvs) - create_entry(config_db, VLAN_IF_TB, vlan_name_key, fvs_nul) - create_entry(config_db, VLAN_IF_TB, ip_pref_key, fvs_nul) - dvs.port_admin_set(if_name_key, "up") - dvs.servers[i].runcmd("ip link set down dev eth0") == 0 - dvs.servers[i].runcmd("ip link set up dev eth0") == 0 - bank = 0 - if i >= NUM_NHs/2: - bank = 1 - fvs = {"FG_NHG": fg_nhg_name, "bank": str(bank), "link": if_name_key} - create_entry(config_db, FG_NHG_MEMBER, "10.0.0." + str(1 + i*2), fvs) - ip_to_if_map["10.0.0." + str(1 + i*2)] = vlan_name_key - - # Wait for the software to receive the entries - time.sleep(1) - - ps = swsscommon.ProducerStateTable(app_db.db_connection, ROUTE_TB) - fvs = swsscommon.FieldValuePairs([("nexthop","10.0.0.7,10.0.0.9,10.0.0.11"), - ("ifname", "Vlan16,Vlan20,Vlan24")]) - ps.set(fg_nhg_prefix, fvs) - # No ASIC_DB entry we can wait for since ARP is not resolved yet, - # We just use sleep so that the sw receives this entry - time.sleep(1) - - adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - rtbl = swsscommon.Table(adb, ASIC_ROUTE_TB) - keys = rtbl.getKeys() - found_route = False - for k in keys: - rt_key = json.loads(k) - - if rt_key['dest'] == fg_nhg_prefix: - found_route = True - break - - # Since we didn't populate ARP yet, route should point to RIF for kernel arp resolution to occur - assert (found_route == True) - validate_asic_nhg_router_interface(asic_db, fg_nhg_prefix) - - asic_nh_count = len(asic_db.get_keys(ASIC_NH_TB)) - dvs.runcmd("arp -s 10.0.0.1 00:00:00:00:00:01") - dvs.runcmd("arp -s 10.0.0.3 00:00:00:00:00:02") - dvs.runcmd("arp -s 10.0.0.5 00:00:00:00:00:03") - dvs.runcmd("arp -s 10.0.0.9 00:00:00:00:00:05") - dvs.runcmd("arp -s 10.0.0.11 00:00:00:00:00:06") - asic_db.wait_for_n_keys(ASIC_NH_TB, asic_nh_count + 5) - - asic_db.wait_for_n_keys(ASIC_NHG_MEMB, bucket_size) - nhgid = validate_asic_nhg_fine_grained_ecmp(asic_db, fg_nhg_prefix, bucket_size) - - nh_oid_map = get_nh_oid_map(asic_db) - - ### Test scenarios with bank 0 having 0 members up and only bank 1 having members - # ARP is not resolved for 10.0.0.7, so fg nhg should be created without 10.0.0.7 - nh_memb_exp_count = {"10.0.0.9":30,"10.0.0.11":30} - validate_fine_grained_asic_n_state_db_entries(asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - - # Resolve ARP for 10.0.0.7 - asic_nh_count = len(asic_db.get_keys(ASIC_NH_TB)) - dvs.runcmd("arp -s 10.0.0.7 00:00:00:00:00:04") - asic_db.wait_for_n_keys(ASIC_NH_TB, asic_nh_count + 1) - nh_oid_map = get_nh_oid_map(asic_db) - - # Now that ARP was resolved, 10.0.0.7 should be added as a valid fg nhg member - nh_memb_exp_count = {"10.0.0.7":20,"10.0.0.9":20,"10.0.0.11":20} - validate_fine_grained_asic_n_state_db_entries(asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - - # Test warm reboot - run_warm_reboot(dvs) - asic_db.wait_for_n_keys(ASIC_NHG_MEMB, bucket_size) - nhgid = validate_asic_nhg_fine_grained_ecmp(asic_db, fg_nhg_prefix, bucket_size) - nh_oid_map = get_nh_oid_map(asic_db) - nh_memb_exp_count = {"10.0.0.7":20,"10.0.0.9":20,"10.0.0.11":20} - validate_fine_grained_asic_n_state_db_entries(asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - - # Bring down 1 next hop in bank 1 - nh_memb_exp_count = {"10.0.0.7":30,"10.0.0.11":30} - program_route_and_validate_fine_grained_ecmp(app_db.db_connection, asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - - # Bring down 2 next hop and bring up 1 next hop in bank 1 - nh_memb_exp_count = {"10.0.0.9":60} - program_route_and_validate_fine_grained_ecmp(app_db.db_connection, asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - - # Bring up 1 next hop in bank 1 - nh_memb_exp_count = {"10.0.0.7":20,"10.0.0.9":20,"10.0.0.11":20} - program_route_and_validate_fine_grained_ecmp(app_db.db_connection, asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - - # Bring up some next-hops in bank 0 for the 1st time - nh_memb_exp_count = {"10.0.0.1":10,"10.0.0.3":10,"10.0.0.5":10,"10.0.0.7":10,"10.0.0.9":10,"10.0.0.11":10} - program_route_and_validate_fine_grained_ecmp(app_db.db_connection, asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - - # Test warm reboot - run_warm_reboot(dvs) - asic_db.wait_for_n_keys(ASIC_NHG_MEMB, bucket_size) - nhgid = validate_asic_nhg_fine_grained_ecmp(asic_db, fg_nhg_prefix, bucket_size) - nh_oid_map = get_nh_oid_map(asic_db) - nh_memb_exp_count = {"10.0.0.1":10,"10.0.0.3":10,"10.0.0.5":10,"10.0.0.7":10,"10.0.0.9":10,"10.0.0.11":10} - validate_fine_grained_asic_n_state_db_entries(asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - - # Bring down 1 next-hop from bank 0, and 2 next-hops from bank 1 - nh_memb_exp_count = {"10.0.0.1":15,"10.0.0.5":15,"10.0.0.11":30} - program_route_and_validate_fine_grained_ecmp(app_db.db_connection, asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - - # Bring down 1 member and bring up 1 member in bank 0 at the same time - nh_memb_exp_count = {"10.0.0.1":15,"10.0.0.3":15,"10.0.0.11":30} - program_route_and_validate_fine_grained_ecmp(app_db.db_connection, asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - - # Bring down 2 members and bring up 1 member in bank 0 at the same time - nh_memb_exp_count = {"10.0.0.5":30,"10.0.0.11":30} - program_route_and_validate_fine_grained_ecmp(app_db.db_connection, asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - - # Bring up 2 members and bring down 1 member in bank 0 at the same time - nh_memb_exp_count = {"10.0.0.1":15,"10.0.0.3":15,"10.0.0.11":30} - program_route_and_validate_fine_grained_ecmp(app_db.db_connection, asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - - # Bringup arbitrary # of next-hops from both banks at the same time - nh_memb_exp_count = {"10.0.0.1":10,"10.0.0.3":10,"10.0.0.5":10,"10.0.0.7":10,"10.0.0.9":10,"10.0.0.11":10} - program_route_and_validate_fine_grained_ecmp(app_db.db_connection, asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - - # Bring all next-hops in bank 1 down - nh_memb_exp_count = {"10.0.0.1":20,"10.0.0.3":20,"10.0.0.5":20} - program_route_and_validate_fine_grained_ecmp(app_db.db_connection, asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - - # Make next-hop changes to bank 0 members, given bank 1 is still down - nh_memb_exp_count = {"10.0.0.1":30,"10.0.0.5":30} - program_route_and_validate_fine_grained_ecmp(app_db.db_connection, asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - - # Bringup 1 member in bank 1 again - nh_memb_exp_count = {"10.0.0.1":15,"10.0.0.5":15,"10.0.0.11":30} - program_route_and_validate_fine_grained_ecmp(app_db.db_connection, asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - - # Test 2nd,3rd memb up in bank - nh_memb_exp_count = {"10.0.0.1":15,"10.0.0.5":15,"10.0.0.7":10,"10.0.0.9":10,"10.0.0.11":10} - program_route_and_validate_fine_grained_ecmp(app_db.db_connection, asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - - # bring all links down one by one - shutdown_link(dvs, app_db, 0) - shutdown_link(dvs, app_db, 1) - nh_memb_exp_count = {"10.0.0.5":30,"10.0.0.7":10,"10.0.0.9":10,"10.0.0.11":10} - validate_fine_grained_asic_n_state_db_entries(asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - - shutdown_link(dvs, app_db, 2) - nh_memb_exp_count = {"10.0.0.7":20,"10.0.0.9":20,"10.0.0.11":20} - validate_fine_grained_asic_n_state_db_entries(asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - - shutdown_link(dvs, app_db, 3) - nh_memb_exp_count = {"10.0.0.9":30,"10.0.0.11":30} - validate_fine_grained_asic_n_state_db_entries(asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - - shutdown_link(dvs, app_db, 4) - nh_memb_exp_count = {"10.0.0.11":60} - validate_fine_grained_asic_n_state_db_entries(asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - - # Bring down last link, there shouldn't be a crash or other bad orchagent state because of this - shutdown_link(dvs, app_db, 5) - # Nothing to check for in this case, sleep 1s for the shutdown to reach sw - time.sleep(1) - - # bring all links up one by one - startup_link(dvs, app_db, 3) - startup_link(dvs, app_db, 4) - asic_db.wait_for_n_keys(ASIC_NHG_MEMB, bucket_size) - nhgid = validate_asic_nhg_fine_grained_ecmp(asic_db, fg_nhg_prefix, bucket_size) - nh_oid_map = get_nh_oid_map(asic_db) - nh_memb_exp_count = {"10.0.0.7":30,"10.0.0.9":30} - validate_fine_grained_asic_n_state_db_entries(asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - - startup_link(dvs, app_db, 5) - # Perform a route table update, Update the route to contain 10.0.0.3 as well, since Ethernet4 associated with it - # is link down, it should make no difference - fvs = swsscommon.FieldValuePairs([("nexthop","10.0.0.1,10.0.0.3,10.0.0.5,10.0.0.7,10.0.0.9,10.0.0.11"), - ("ifname","Vlan4,Vlan8,Vlan12,Vlan16,Vlan20,Vlan24")]) - ps.set(fg_nhg_prefix, fvs) - - # 10.0.0.11 associated with newly brought up link 5 should be updated in FG ecmp - # 10.0.0.3 addition per above route table change should have no effect - nh_memb_exp_count = {"10.0.0.7":20,"10.0.0.9":20,"10.0.0.11":20} - validate_fine_grained_asic_n_state_db_entries(asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - - startup_link(dvs, app_db, 2) - nh_memb_exp_count = {"10.0.0.5":30,"10.0.0.7":10,"10.0.0.9":10,"10.0.0.11":10} - validate_fine_grained_asic_n_state_db_entries(asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - - startup_link(dvs, app_db, 0) - nh_memb_exp_count = {"10.0.0.1":15,"10.0.0.5":15,"10.0.0.7":10,"10.0.0.9":10,"10.0.0.11":10} - validate_fine_grained_asic_n_state_db_entries(asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - - # remove fgnhg member - remove_entry(config_db, "FG_NHG_MEMBER", "10.0.0.1") - nh_memb_exp_count = {"10.0.0.5":30,"10.0.0.7":10,"10.0.0.9":10,"10.0.0.11":10} - validate_fine_grained_asic_n_state_db_entries(asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - - # add fgnhg member - fvs = {"FG_NHG": fg_nhg_name, "bank": "0"} - create_entry(config_db, FG_NHG_MEMBER, "10.0.0.1", fvs) - nh_memb_exp_count = {"10.0.0.1":15,"10.0.0.5":15,"10.0.0.7":10,"10.0.0.9":10,"10.0.0.11":10} - validate_fine_grained_asic_n_state_db_entries(asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - - # Remove route - asic_rt_key = get_asic_route_key(asic_db, fg_nhg_prefix) - ps._del(fg_nhg_prefix) - - # validate routes and nhg member in asic db, route entry in state db are removed - asic_db.wait_for_deleted_entry(ASIC_ROUTE_TB, asic_rt_key) - asic_db.wait_for_n_keys(ASIC_NHG_MEMB, 0) - state_db.wait_for_n_keys("FG_ROUTE_TABLE", 0) - - if match_mode == 'route-based': - remove_entry(config_db, "FG_NHG_PREFIX", fg_nhg_prefix) - # Nothing we can wait for in terms of db entries, we sleep here - # to give the sw enough time to delete the entry - time.sleep(1) - - # Add an ECMP route, since we deleted the FG_NHG_PREFIX it should see - # standard(non-Fine grained) ECMP behavior - fvs = swsscommon.FieldValuePairs([("nexthop","10.0.0.7,10.0.0.9,10.0.0.11"), - ("ifname", "Vlan16,Vlan20,Vlan24")]) - ps.set(fg_nhg_prefix, fvs) - validate_asic_nhg_regular_ecmp(asic_db, fg_nhg_prefix) - asic_db.wait_for_n_keys(ASIC_NHG_MEMB, 3) - - # add fgnhg prefix: The regular route should transition to fine grained ECMP - fvs = {"FG_NHG": fg_nhg_name} - create_entry(config_db, FG_NHG_PREFIX, fg_nhg_prefix, fvs) - - # Validate the transistion to Fine Grained ECMP - asic_db.wait_for_n_keys(ASIC_NHG_MEMB, bucket_size) - nhgid = validate_asic_nhg_fine_grained_ecmp(asic_db, fg_nhg_prefix, bucket_size) - - nh_oid_map = {} - nh_oid_map = get_nh_oid_map(asic_db) - - nh_memb_exp_count = {"10.0.0.7":20,"10.0.0.9":20,"10.0.0.11":20} - validate_fine_grained_asic_n_state_db_entries(asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - - # remove fgnhg prefix: The fine grained route should transition to regular ECMP/route - remove_entry(config_db, "FG_NHG_PREFIX", fg_nhg_prefix) - - # Validate regular ECMP - validate_asic_nhg_regular_ecmp(asic_db, fg_nhg_prefix) - asic_db.wait_for_n_keys(ASIC_NHG_MEMB, 3) - state_db.wait_for_n_keys("FG_ROUTE_TABLE", 0) - - # remove prefix entry - asic_rt_key = get_asic_route_key(asic_db, fg_nhg_prefix) - ps._del(fg_nhg_prefix) - asic_db.wait_for_deleted_entry(ASIC_ROUTE_TB, asic_rt_key) - asic_db.wait_for_n_keys(ASIC_NHG_MEMB, 0) - - # Cleanup all FG, arp and interface - remove_entry(config_db, "FG_NHG", fg_nhg_name) - - for i in range(0,NUM_NHs): - if_name_key = "Ethernet" + str(i*4) - vlan_name_key = "Vlan" + str((i+1)*4) - ip_pref_key = vlan_name_key + "|10.0.0." + str(i*2) + "/31" - remove_entry(config_db, VLAN_IF_TB, ip_pref_key) - remove_entry(config_db, VLAN_IF_TB, vlan_name_key) - remove_entry(config_db, VLAN_MEMB_TB, vlan_name_key + "|" + if_name_key) - remove_entry(config_db, VLAN_TB, vlan_name_key) - dvs.port_admin_set(if_name_key, "down") - dvs.servers[i].runcmd("ip link set down dev eth0") == 0 - remove_entry(config_db, "FG_NHG_MEMBER", "10.0.0." + str(1 + i*2)) - - -class TestFineGrainedNextHopGroup(object): - def test_fgnhg_matchmode_route(self, dvs, testlog): - ''' - Test for match_mode route-based - ''' - fine_grained_ecmp_base_test(dvs, 'route-based') - - def test_fgnhg_matchmode_nexthop(self, dvs, testlog): - ''' - Test for match_mode nexthop-based - ''' - fine_grained_ecmp_base_test(dvs, 'nexthop-based') - - def test_fgnhg_more_nhs_nondiv_bucket_size(self, dvs, testlog): - ''' - Test Fine Grained ECMP with a greater number of FG members and - bigger bucket size, such that the no. of nhs are not divisible by - bucket size. Use a different physical interface type for dynamicitiy. - ''' - app_db = dvs.get_app_db() - asic_db = dvs.get_asic_db() - config_db = dvs.get_config_db() - state_db = dvs.get_state_db() - - fg_nhg_name = "fgnhg_v4" - fg_nhg_prefix = "3.3.3.0/24" - # Test with non-divisible bucket size - bucket_size = 128 - NUM_NHs = 10 - - nh_oid_map = {} - - # Initialize base config - fvs = {"bucket_size": str(bucket_size)} - create_entry(config_db, FG_NHG, fg_nhg_name, fvs) - - fvs = {"FG_NHG": fg_nhg_name} - create_entry(config_db, FG_NHG_PREFIX, fg_nhg_prefix, fvs) - - asic_nh_count = len(asic_db.get_keys(ASIC_NH_TB)) - ip_to_if_map = create_interface_n_fg_ecmp_config(dvs, 0, NUM_NHs, fg_nhg_name) - asic_db.wait_for_n_keys(ASIC_NH_TB, asic_nh_count + NUM_NHs) - - # Program the route - ps = swsscommon.ProducerStateTable(app_db.db_connection, ROUTE_TB) - fvs = swsscommon.FieldValuePairs([("nexthop","10.0.0.1,10.0.0.11"), - ("ifname", "Ethernet0,Ethernet20")]) - ps.set(fg_nhg_prefix, fvs) - - # Validate that the correct ASIC DB elements were setup per Fine Grained ECMP - asic_db.wait_for_n_keys(ASIC_NHG_MEMB, bucket_size) - nhgid = validate_asic_nhg_fine_grained_ecmp(asic_db, fg_nhg_prefix, bucket_size) - - nh_oid_map = get_nh_oid_map(asic_db) - - # The route had been created with 0 members in bank - nh_memb_exp_count = {"10.0.0.1":64,"10.0.0.11":64} - validate_fine_grained_asic_n_state_db_entries(asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - - # Add 2 nhs to both bank 0 and bank 1 - nh_memb_exp_count = {"10.0.0.1":22,"10.0.0.3":21,"10.0.0.5":21,"10.0.0.11":22, - "10.0.0.13":21,"10.0.0.15":21} - program_route_and_validate_fine_grained_ecmp(app_db.db_connection, asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - - # Add 2 more nhs to both bank 0 and bank 1 - nh_memb_exp_count = {"10.0.0.1":13,"10.0.0.3":13,"10.0.0.5":13,"10.0.0.7":12, - "10.0.0.9":13,"10.0.0.11":13,"10.0.0.13":13,"10.0.0.15":13,"10.0.0.17":12,"10.0.0.19":13} - program_route_and_validate_fine_grained_ecmp(app_db.db_connection, asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - - # Remove 1 nh from bank 0 and remove 2 nhs from bank 1 - nh_memb_exp_count = {"10.0.0.3":16,"10.0.0.5":16,"10.0.0.7":16,"10.0.0.9":16, - "10.0.0.11":22,"10.0.0.13":21,"10.0.0.19":21} - program_route_and_validate_fine_grained_ecmp(app_db.db_connection, asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - - # Remove 1 nh from bank 0 and add 1 nh to bank 1 - nh_memb_exp_count = {"10.0.0.3":22,"10.0.0.7":21,"10.0.0.9":21,"10.0.0.13":16, - "10.0.0.15":16,"10.0.0.17":16,"10.0.0.19":16} - program_route_and_validate_fine_grained_ecmp(app_db.db_connection, asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - - # Remove 2 nh from bank 0 and remove 3 nh from bank 1 - nh_memb_exp_count = {"10.0.0.7":64,"10.0.0.11":64} - program_route_and_validate_fine_grained_ecmp(app_db.db_connection, asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - - # Add 2 nhs to bank 0 and remove all nh from bank 1 - nh_memb_exp_count = {"10.0.0.5":42,"10.0.0.7":44,"10.0.0.9":42} - program_route_and_validate_fine_grained_ecmp(app_db.db_connection, asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - - # Add 2 nhs to bank 0 and add 1 nh to bank 1 - nh_memb_exp_count = {"10.0.0.1":12,"10.0.0.3":13,"10.0.0.5":13,"10.0.0.7":13, - "10.0.0.9":13,"10.0.0.11":64} - program_route_and_validate_fine_grained_ecmp(app_db.db_connection, asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - - # Remove route - # remove prefix entry - asic_rt_key = get_asic_route_key(asic_db, fg_nhg_prefix) - ps._del(fg_nhg_prefix) - asic_db.wait_for_deleted_entry(ASIC_ROUTE_TB, asic_rt_key) - asic_db.wait_for_n_keys(ASIC_NHG_MEMB, 0) - asic_db.wait_for_n_keys(ASIC_NHG, 0) - - # cleanup all config - remove_interface_n_fg_ecmp_config(dvs, 0, NUM_NHs, fg_nhg_name) - remove_entry(config_db, FG_NHG_PREFIX, fg_nhg_prefix) - - def test_fgnhg_matchmode_nexthop_multi_route(self, dvs, testlog): - ''' - Test route/nh transitions to/from Fine Grained ECMP and Regular ECMP. - Create multiple prefixes pointing to the Fine Grained nhs and ensure - fine grained ECMP ASIC objects were created for this scenario as expected. - ''' - app_db = dvs.get_app_db() - asic_db = dvs.get_asic_db() - config_db = dvs.get_config_db() - state_db = dvs.get_state_db() - fvs_nul = {"NULL": "NULL"} - - fg_nhg_name = "fgnhg_v4" - fg_nhg_prefix = "3.3.3.0/24" - # Test with non-divisible bucket size - bucket_size = 128 - NUM_NHs = 4 - NUM_NHs_non_fgnhg = 2 - - nh_oid_map = {} - - # Initialize base config - fvs = {"bucket_size": str(bucket_size), "match_mode": "nexthop-based"} - create_entry(config_db, FG_NHG, fg_nhg_name, fvs) - - asic_nh_count = len(asic_db.get_keys(ASIC_NH_TB)) - ip_to_if_map = create_interface_n_fg_ecmp_config(dvs, 0, NUM_NHs, fg_nhg_name) - - # Create 2 more interface + IPs for non-fine grained ECMP validation - for i in range(NUM_NHs, NUM_NHs + NUM_NHs_non_fgnhg): - if_name_key = "Ethernet" + str(i*4) - ip_pref_key = "Ethernet" + str(i*4) + "|10.0.0." + str(i*2) + "/31" - create_entry(config_db, IF_TB, if_name_key, fvs_nul) - create_entry(config_db, IF_TB, ip_pref_key, fvs_nul) - dvs.port_admin_set(if_name_key, "up") - shutdown_link(dvs, app_db, i) - startup_link(dvs, app_db, i) - dvs.runcmd("arp -s 10.0.0." + str(1 + i*2) + " 00:00:00:00:00:" + str(1 + i*2)) - - asic_db.wait_for_n_keys(ASIC_NH_TB, asic_nh_count + NUM_NHs + NUM_NHs_non_fgnhg) - - # Program the route - ps = swsscommon.ProducerStateTable(app_db.db_connection, ROUTE_TB) - fvs = swsscommon.FieldValuePairs([("nexthop","10.0.0.1,10.0.0.5"), - ("ifname", "Ethernet0,Ethernet8")]) - ps.set(fg_nhg_prefix, fvs) - - # Validate that the correct ASIC DB elements were setup per Fine Grained ECMP - asic_db.wait_for_n_keys(ASIC_NHG_MEMB, bucket_size) - nhgid = validate_asic_nhg_fine_grained_ecmp(asic_db, fg_nhg_prefix, bucket_size) - - nh_oid_map = get_nh_oid_map(asic_db) - - # The route had been created with 0 members in bank - nh_memb_exp_count = {"10.0.0.1":64,"10.0.0.5":64} - validate_fine_grained_asic_n_state_db_entries(asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - - # Add a 2nd prefix associated with the same set of next-hops - fg_nhg_prefix_2 = "5.5.5.0/16" - fvs = swsscommon.FieldValuePairs([("nexthop","10.0.0.1,10.0.0.5"), - ("ifname", "Ethernet0,Ethernet8")]) - ps.set(fg_nhg_prefix_2, fvs) - asic_db.wait_for_n_keys(ASIC_NHG_MEMB, bucket_size*2) - nhgid_2 = validate_asic_nhg_fine_grained_ecmp(asic_db, fg_nhg_prefix_2, bucket_size) - nh_memb_exp_count = {"10.0.0.1":64,"10.0.0.5":64} - validate_fine_grained_asic_n_state_db_entries(asic_db, state_db, ip_to_if_map, - fg_nhg_prefix_2, nh_memb_exp_count, nh_oid_map, nhgid_2, bucket_size) - - # Add a 3rd prefix with a next-hop(10.0.0.9) not defined for FG ECMP - # Should end up as regular ECMP - fg_nhg_prefix_3 = "6.6.6.0/16" - fvs = swsscommon.FieldValuePairs([("nexthop","10.0.0.1,10.0.0.5,10.0.0.9"), - ("ifname", "Ethernet0,Ethernet8,Ethernet16")]) - ps.set(fg_nhg_prefix_3, fvs) - validate_asic_nhg_regular_ecmp(asic_db, fg_nhg_prefix_3) - asic_db.wait_for_n_keys(ASIC_NHG_MEMB, bucket_size*2 + 3) - # Remove the 10.0.0.9 next-hop, it should now transition to Fine Grained ECMP - fvs = swsscommon.FieldValuePairs([("nexthop","10.0.0.1,10.0.0.5"), - ("ifname", "Ethernet0,Ethernet8")]) - ps.set(fg_nhg_prefix_3, fvs) - nhgid_3 = validate_asic_nhg_fine_grained_ecmp(asic_db, fg_nhg_prefix_3, bucket_size) - asic_db.wait_for_n_keys(ASIC_NHG_MEMB, bucket_size*3) - nh_memb_exp_count = {"10.0.0.1":64,"10.0.0.5":64} - validate_fine_grained_asic_n_state_db_entries(asic_db, state_db, ip_to_if_map, - fg_nhg_prefix_3, nh_memb_exp_count, nh_oid_map, nhgid_3, bucket_size) - # Add the 10.0.0.9 next-hop again, it should transition back to regular ECMP - fvs = swsscommon.FieldValuePairs([("nexthop","10.0.0.1,10.0.0.5,10.0.0.9"), - ("ifname", "Ethernet0,Ethernet8,Ethernet16")]) - ps.set(fg_nhg_prefix_3, fvs) - validate_asic_nhg_regular_ecmp(asic_db, fg_nhg_prefix_3) - asic_db.wait_for_n_keys(ASIC_NHG_MEMB, bucket_size*2 + 3) - # Delete the prefix - asic_rt_key = get_asic_route_key(asic_db, fg_nhg_prefix_3) - ps._del(fg_nhg_prefix_3) - asic_db.wait_for_deleted_entry(ASIC_ROUTE_TB, asic_rt_key) - asic_db.wait_for_n_keys(ASIC_NHG_MEMB, bucket_size*2) - - # Change FG nhs for one route, ensure that the other route nh is unaffected - nh_memb_exp_count = {"10.0.0.1":32,"10.0.0.3":32,"10.0.0.5":32,"10.0.0.7":32} - program_route_and_validate_fine_grained_ecmp(app_db.db_connection, asic_db, state_db, ip_to_if_map, - fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) - nh_memb_exp_count = {"10.0.0.1":64,"10.0.0.5":64} - validate_fine_grained_asic_n_state_db_entries(asic_db, state_db, ip_to_if_map, - fg_nhg_prefix_2, nh_memb_exp_count, nh_oid_map, nhgid_2, bucket_size) - - # Remove route - # remove prefix entry - asic_rt_key = get_asic_route_key(asic_db, fg_nhg_prefix) - ps._del(fg_nhg_prefix) - asic_db.wait_for_deleted_entry(ASIC_ROUTE_TB, asic_rt_key) - asic_db.wait_for_n_keys(ASIC_NHG_MEMB, bucket_size) - # Ensure that 2nd route is still here and then delete it - nh_memb_exp_count = {"10.0.0.1":64,"10.0.0.5":64} - validate_fine_grained_asic_n_state_db_entries(asic_db, state_db, ip_to_if_map, - fg_nhg_prefix_2, nh_memb_exp_count, nh_oid_map, nhgid_2, bucket_size) - # Delete the 2nd route as well - asic_rt_key = get_asic_route_key(asic_db, fg_nhg_prefix_2) - ps._del(fg_nhg_prefix_2) - asic_db.wait_for_deleted_entry(ASIC_ROUTE_TB, asic_rt_key) - asic_db.wait_for_n_keys(ASIC_NHG_MEMB, 0) - asic_db.wait_for_n_keys(ASIC_NHG, 0) - - # cleanup all entries - remove_interface_n_fg_ecmp_config(dvs, 0, NUM_NHs+NUM_NHs_non_fgnhg, fg_nhg_name) - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_flex_counters.py b/tests/test_flex_counters.py deleted file mode 100644 index f590b7748c..0000000000 --- a/tests/test_flex_counters.py +++ /dev/null @@ -1,845 +0,0 @@ -import time -import pytest - -from swsscommon import swsscommon - -TUNNEL_TYPE_MAP = "COUNTERS_TUNNEL_TYPE_MAP" -ROUTE_TO_PATTERN_MAP = "COUNTERS_ROUTE_TO_PATTERN_MAP" -NUMBER_OF_RETRIES = 10 -CPU_PORT_OID = "0x0" - -counter_group_meta = { - 'port_counter': { - 'key': 'PORT', - 'group_name': 'PORT_STAT_COUNTER', - 'name_map': 'COUNTERS_PORT_NAME_MAP', - 'post_test': 'post_port_counter_test', - }, - 'queue_counter': { - 'key': 'QUEUE', - 'group_name': 'QUEUE_STAT_COUNTER', - 'name_map': 'COUNTERS_QUEUE_NAME_MAP', - }, - 'queue_watermark_counter': { - 'key': 'QUEUE_WATERMARK', - 'group_name': 'QUEUE_WATERMARK_STAT_COUNTER', - 'name_map': 'COUNTERS_QUEUE_NAME_MAP', - }, - 'rif_counter': { - 'key': 'RIF', - 'group_name': 'RIF_STAT_COUNTER', - 'name_map': 'COUNTERS_RIF_NAME_MAP', - 'pre_test': 'pre_rif_counter_test', - 'post_test': 'post_rif_counter_test', - }, - 'buffer_pool_watermark_counter': { - 'key': 'BUFFER_POOL_WATERMARK', - 'group_name': 'BUFFER_POOL_WATERMARK_STAT_COUNTER', - 'name_map': 'COUNTERS_BUFFER_POOL_NAME_MAP', - }, - 'port_buffer_drop_counter': { - 'key': 'PORT_BUFFER_DROP', - 'group_name': 'PORT_BUFFER_DROP_STAT', - 'name_map': 'COUNTERS_PORT_NAME_MAP', - }, - 'pg_drop_counter': { - 'key': 'PG_DROP', - 'group_name': 'PG_DROP_STAT_COUNTER', - 'name_map': 'COUNTERS_PG_NAME_MAP', - }, - 'pg_watermark_counter': { - 'key': 'PG_WATERMARK', - 'group_name': 'PG_WATERMARK_STAT_COUNTER', - 'name_map': 'COUNTERS_PG_NAME_MAP', - }, - 'trap_flow_counter': { - 'key': 'FLOW_CNT_TRAP', - 'group_name': 'HOSTIF_TRAP_FLOW_COUNTER', - 'name_map': 'COUNTERS_TRAP_NAME_MAP', - 'post_test': 'post_trap_flow_counter_test', - }, - 'tunnel_counter': { - 'key': 'TUNNEL', - 'group_name': 'TUNNEL_STAT_COUNTER', - 'name_map': 'COUNTERS_TUNNEL_NAME_MAP', - 'pre_test': 'pre_vxlan_tunnel_counter_test', - 'post_test': 'post_vxlan_tunnel_counter_test', - }, - 'acl_counter': { - 'key': 'ACL', - 'group_name': 'ACL_STAT_COUNTER', - 'name_map': 'ACL_COUNTER_RULE_MAP', - 'pre_test': 'pre_acl_tunnel_counter_test', - 'post_test': 'post_acl_tunnel_counter_test', - }, - 'route_flow_counter': { - 'key': 'FLOW_CNT_ROUTE', - 'group_name': 'ROUTE_FLOW_COUNTER', - 'name_map': 'COUNTERS_ROUTE_NAME_MAP', - 'pre_test': 'pre_route_flow_counter_test', - 'post_test': 'post_route_flow_counter_test', - } -} - -class TestFlexCounters(object): - - def setup_dbs(self, dvs): - self.config_db = dvs.get_config_db() - self.flex_db = dvs.get_flex_db() - self.counters_db = dvs.get_counters_db() - self.app_db = dvs.get_app_db() - - def wait_for_table(self, table): - for retry in range(NUMBER_OF_RETRIES): - counters_keys = self.counters_db.db_connection.hgetall(table) - if len(counters_keys) > 0: - return - else: - time.sleep(1) - - assert False, str(table) + " not created in Counters DB" - - def wait_for_table_empty(self, table): - for retry in range(NUMBER_OF_RETRIES): - counters_keys = self.counters_db.db_connection.hgetall(table) - if len(counters_keys) == 0: - return - else: - time.sleep(1) - - assert False, str(table) + " is still in Counters DB" - - def wait_for_id_list(self, stat, name, oid): - for retry in range(NUMBER_OF_RETRIES): - id_list = self.flex_db.db_connection.hgetall("FLEX_COUNTER_TABLE:" + stat + ":" + oid).items() - if len(id_list) > 0: - return - else: - time.sleep(1) - - assert False, "No ID list for counter " + str(name) - - def wait_for_id_list_remove(self, stat, name, oid): - for retry in range(NUMBER_OF_RETRIES): - id_list = self.flex_db.db_connection.hgetall("FLEX_COUNTER_TABLE:" + stat + ":" + oid).items() - if len(id_list) == 0: - return - else: - time.sleep(1) - - assert False, "ID list for counter " + str(name) + " is still there" - - def wait_for_interval_set(self, group, interval): - interval_value = None - for retry in range(NUMBER_OF_RETRIES): - interval_value = self.flex_db.db_connection.hget("FLEX_COUNTER_GROUP_TABLE:" + group, 'POLL_INTERVAL') - if interval_value == interval: - return - else: - time.sleep(1) - - assert False, "Polling interval is not applied to FLEX_COUNTER_GROUP_TABLE for group {}, expect={}, actual={}".format(group, interval, interval_value) - - def wait_for_buffer_pg_queue_counter(self, map, port, index, isSet): - for retry in range(NUMBER_OF_RETRIES): - counter_oid = self.counters_db.db_connection.hget(map, port + ':' + index) - if (isSet and counter_oid): - return counter_oid - elif (not isSet and not counter_oid): - return None - else: - time.sleep(1) - - assert False, "Counter not {} for port: {}, type: {}, index: {}".format("created" if isSet else "removed", port, map, index) - - def verify_no_flex_counters_tables(self, counter_stat): - counters_stat_keys = self.flex_db.get_keys("FLEX_COUNTER_TABLE:" + counter_stat) - assert len(counters_stat_keys) == 0, "FLEX_COUNTER_TABLE:" + str(counter_stat) + " tables exist before enabling the flex counter group" - - def verify_no_flex_counters_tables_after_delete(self, counter_stat): - for retry in range(NUMBER_OF_RETRIES): - counters_stat_keys = self.flex_db.get_keys("FLEX_COUNTER_TABLE:" + counter_stat + ":") - if len(counters_stat_keys) == 0: - return - else: - time.sleep(1) - assert False, "FLEX_COUNTER_TABLE:" + str(counter_stat) + " tables exist after removing the entries" - - def verify_flex_counters_populated(self, map, stat): - counters_keys = self.counters_db.db_connection.hgetall(map) - for counter_entry in counters_keys.items(): - name = counter_entry[0] - oid = counter_entry[1] - self.wait_for_id_list(stat, name, oid) - - def verify_tunnel_type_vxlan(self, meta_data, type_map): - counters_keys = self.counters_db.db_connection.hgetall(meta_data['name_map']) - for counter_entry in counters_keys.items(): - oid = counter_entry[1] - fvs = self.counters_db.get_entry(type_map, "") - assert fvs != {} - assert fvs.get(oid) == "SAI_TUNNEL_TYPE_VXLAN" - - def verify_only_phy_ports_created(self, meta_data): - port_counters_keys = self.counters_db.db_connection.hgetall(meta_data['name_map']) - port_counters_stat_keys = self.flex_db.get_keys("FLEX_COUNTER_TABLE:" + meta_data['group_name']) - for port_stat in port_counters_stat_keys: - assert port_stat in dict(port_counters_keys.items()).values(), "Non PHY port created on PORT_STAT_COUNTER group: {}".format(port_stat) - - def set_flex_counter_group_status(self, group, map, status='enable', check_name_map=True): - group_stats_entry = {"FLEX_COUNTER_STATUS": status} - self.config_db.create_entry("FLEX_COUNTER_TABLE", group, group_stats_entry) - if check_name_map: - if status == 'enable': - self.wait_for_table(map) - else: - self.wait_for_table_empty(map) - - def set_flex_counter_group_interval(self, key, group, interval): - group_stats_entry = {"POLL_INTERVAL": interval} - self.config_db.create_entry("FLEX_COUNTER_TABLE", key, group_stats_entry) - self.wait_for_interval_set(group, interval) - - def set_only_config_db_buffers_field(self, value): - fvs = {'create_only_config_db_buffers' : value} - self.config_db.update_entry("DEVICE_METADATA", "localhost", fvs) - - @pytest.mark.parametrize("counter_type", counter_group_meta.keys()) - def test_flex_counters(self, dvs, counter_type): - """ - The test will check there are no flex counters tables on FlexCounter DB when the counters are disabled. - After enabling each counter group, the test will check the flow of creating flex counters tables on FlexCounter DB. - For some counter types the MAPS on COUNTERS DB will be created as well after enabling the counter group, this will be also verified on this test. - """ - self.setup_dbs(dvs) - meta_data = counter_group_meta[counter_type] - counter_key = meta_data['key'] - counter_stat = meta_data['group_name'] - counter_map = meta_data['name_map'] - pre_test = meta_data.get('pre_test') - post_test = meta_data.get('post_test') - meta_data['dvs'] = dvs - - self.verify_no_flex_counters_tables(counter_stat) - - if pre_test: - cb = getattr(self, pre_test) - cb(meta_data) - - self.set_flex_counter_group_status(counter_key, counter_map) - self.verify_flex_counters_populated(counter_map, counter_stat) - self.set_flex_counter_group_interval(counter_key, counter_stat, '2500') - - if post_test: - cb = getattr(self, post_test) - cb(meta_data) - - def pre_rif_counter_test(self, meta_data): - self.config_db.db_connection.hset('INTERFACE|Ethernet0', "NULL", "NULL") - self.config_db.db_connection.hset('INTERFACE|Ethernet0|192.168.0.1/24', "NULL", "NULL") - - def pre_vxlan_tunnel_counter_test(self, meta_data): - self.config_db.db_connection.hset("VLAN|Vlan10", "vlanid", "10") - self.config_db.db_connection.hset("VXLAN_TUNNEL|vtep1", "src_ip", "1.1.1.1") - self.config_db.db_connection.hset("VXLAN_TUNNEL_MAP|vtep1|map_100_Vlan10", "vlan", "Vlan10") - self.config_db.db_connection.hset("VXLAN_TUNNEL_MAP|vtep1|map_100_Vlan10", "vni", "100") - - def pre_acl_tunnel_counter_test(self, meta_data): - self.config_db.create_entry('ACL_TABLE', 'DATAACL', - { - 'STAGE': 'INGRESS', - 'PORTS': 'Ethernet0', - 'TYPE': 'L3' - } - ) - self.config_db.create_entry('ACL_RULE', 'DATAACL|RULE0', - { - 'ETHER_TYPE': '2048', - 'PACKET_ACTION': 'FORWARD', - 'PRIORITY': '9999' - } - ) - - def pre_route_flow_counter_test(self, meta_data): - dvs = meta_data['dvs'] - self.config_db.create_entry('FLOW_COUNTER_ROUTE_PATTERN', '1.1.0.0/16', - { - 'max_match_count': '30' - } - ) - self.config_db.create_entry('FLOW_COUNTER_ROUTE_PATTERN', '2000::/64', - { - 'max_match_count': '30' - } - ) - - self.create_l3_intf("Ethernet0", "") - self.add_ip_address("Ethernet0", "10.0.0.0/31") - self.set_admin_status("Ethernet0", "up") - dvs.servers[0].runcmd("ip address add 10.0.0.1/31 dev eth0") - dvs.servers[0].runcmd("ip route add default via 10.0.0.0") - dvs.servers[0].runcmd("ping -c 1 10.0.0.1") - dvs.runcmd("vtysh -c \"configure terminal\" -c \"ip route 1.1.1.0/24 10.0.0.1\"") - - self.create_l3_intf("Ethernet4", "") - self.set_admin_status("Ethernet4", "up") - self.add_ip_address("Ethernet4", "2001::1/64") - dvs.runcmd("sysctl -w net.ipv6.conf.all.forwarding=1") - dvs.servers[1].runcmd("ip -6 address add 2001::2/64 dev eth0") - dvs.servers[1].runcmd("ip -6 route add default via 2001::1") - time.sleep(2) - dvs.servers[1].runcmd("ping -6 -c 1 2001::1") - dvs.runcmd("vtysh -c \"configure terminal\" -c \"ipv6 route 2000::/64 2001::2\"") - - def post_rif_counter_test(self, meta_data): - self.config_db.db_connection.hdel('INTERFACE|Ethernet0|192.168.0.1/24', "NULL") - - def post_port_counter_test(self, meta_data): - self.verify_only_phy_ports_created(meta_data) - - def post_trap_flow_counter_test(self, meta_data): - """Post verification for test_flex_counters for trap_flow_counter. Steps: - 1. Disable test_flex_counters - 2. Verify name map and counter ID list are cleared - 3. Clear trap ids to avoid affecting further test cases - - Args: - meta_data (object): flex counter meta data - """ - counters_keys = self.counters_db.db_connection.hgetall(meta_data['name_map']) - self.set_flex_counter_group_status(meta_data['key'], meta_data['name_map'], 'disable') - - for counter_entry in counters_keys.items(): - self.wait_for_id_list_remove(meta_data['group_name'], counter_entry[0], counter_entry[1]) - self.wait_for_table_empty(meta_data['name_map']) - - def post_vxlan_tunnel_counter_test(self, meta_data): - self.verify_tunnel_type_vxlan(meta_data, TUNNEL_TYPE_MAP) - self.config_db.delete_entry("VLAN","Vlan10") - self.config_db.delete_entry("VLAN_TUNNEL","vtep1") - self.config_db.delete_entry("VLAN_TUNNEL_MAP","vtep1|map_100_Vlan10") - self.verify_no_flex_counters_tables_after_delete(meta_data['group_name']) - - def post_acl_tunnel_counter_test(self, meta_data): - self.config_db.delete_entry('ACL_RULE', 'DATAACL|RULE0') - self.config_db.delete_entry('ACL_TABLE', 'DATAACL') - - def post_route_flow_counter_test(self, meta_data): - dvs = meta_data['dvs'] - # Verify prefix to route pattern name map - self.wait_for_table(ROUTE_TO_PATTERN_MAP) - - # Remove route pattern and verify related couters are removed - v4_name_map_key = '1.1.1.0/24' - counter_oid = self.counters_db.db_connection.hget(meta_data['name_map'], v4_name_map_key) - assert counter_oid - self.config_db.delete_entry('FLOW_COUNTER_ROUTE_PATTERN', '1.1.0.0/16') - self.wait_for_id_list_remove(meta_data['group_name'], v4_name_map_key, counter_oid) - counter_oid = self.counters_db.db_connection.hget(meta_data['name_map'], v4_name_map_key) - assert not counter_oid - route_pattern = self.counters_db.db_connection.hget(ROUTE_TO_PATTERN_MAP, v4_name_map_key) - assert not route_pattern - - # Disable route flow counter and verify all counters are removed - v6_name_map_key = '2000::/64' - counter_oid = self.counters_db.db_connection.hget(meta_data['name_map'], v6_name_map_key) - assert counter_oid - self.set_flex_counter_group_status(meta_data['key'], meta_data['name_map'], 'disable') - self.wait_for_id_list_remove(meta_data['group_name'], v6_name_map_key, counter_oid) - self.wait_for_table_empty(meta_data['name_map']) - self.wait_for_table_empty(ROUTE_TO_PATTERN_MAP) - - dvs.runcmd("vtysh -c \"configure terminal\" -c \"no ip route {} 10.0.0.1\"".format(v4_name_map_key)) - self.remove_ip_address("Ethernet0", "10.0.0.0/31") - self.remove_l3_intf("Ethernet0") - self.set_admin_status("Ethernet0", "down") - dvs.servers[0].runcmd("ip route del default dev eth0") - dvs.servers[0].runcmd("ip address del 10.0.0.1/31 dev eth0") - - dvs.runcmd("vtysh -c \"configure terminal\" -c \"no ipv6 route 2000::/64 2001::2\"") - self.remove_ip_address("Ethernet4", "2001::1/64") - self.remove_l3_intf("Ethernet4") - self.set_admin_status("Ethernet4", "down") - dvs.servers[1].runcmd("ip -6 route del default dev eth0") - dvs.servers[1].runcmd("ip -6 address del 2001::2/64 dev eth0") - self.config_db.delete_entry('FLOW_COUNTER_ROUTE_PATTERN', '2000::/64') - - def test_add_remove_trap(self, dvs): - """Test steps: - 1. Enable trap_flow_counter - 2. Remove a COPP trap - 3. Verify counter is automatically unbind - 4. Add the COPP trap back - 5. Verify counter is added back - - Args: - dvs (object): virtual switch object - """ - self.setup_dbs(dvs) - meta_data = counter_group_meta['trap_flow_counter'] - self.set_flex_counter_group_status(meta_data['key'], meta_data['name_map']) - - removed_trap = None - changed_group = None - trap_ids = None - copp_groups = self.app_db.db_connection.keys('COPP_TABLE:*') - for copp_group in copp_groups: - trap_ids = self.app_db.db_connection.hget(copp_group, 'trap_ids') - if trap_ids and ',' in trap_ids: - trap_ids = [x.strip() for x in trap_ids.split(',')] - removed_trap = trap_ids.pop() - changed_group = copp_group.split(':')[1] - break - - if not removed_trap: - pytest.skip('There is not copp group with more than 1 traps, skip rest of the test') - - oid = None - for _ in range(NUMBER_OF_RETRIES): - counters_keys = self.counters_db.db_connection.hgetall(meta_data['name_map']) - if removed_trap in counters_keys: - oid = counters_keys[removed_trap] - break - else: - time.sleep(1) - - assert oid, 'trap counter is not created for {}'.format(removed_trap) - self.wait_for_id_list(meta_data['group_name'], removed_trap, oid) - - app_copp_table = swsscommon.ProducerStateTable(self.app_db.db_connection, 'COPP_TABLE') - app_copp_table.set(changed_group, [('trap_ids', ','.join(trap_ids))]) - self.wait_for_id_list_remove(meta_data['group_name'], removed_trap, oid) - counters_keys = self.counters_db.db_connection.hgetall(meta_data['name_map']) - assert removed_trap not in counters_keys - - trap_ids.append(removed_trap) - app_copp_table.set(changed_group, [('trap_ids', ','.join(trap_ids))]) - - oid = None - for _ in range(NUMBER_OF_RETRIES): - counters_keys = self.counters_db.db_connection.hgetall(meta_data['name_map']) - if removed_trap in counters_keys: - oid = counters_keys[removed_trap] - break - else: - time.sleep(1) - - assert oid, 'Add trap {}, but trap counter is not created'.format(removed_trap) - self.wait_for_id_list(meta_data['group_name'], removed_trap, oid) - self.set_flex_counter_group_status(meta_data['key'], meta_data['name_map'], 'disable') - - def test_remove_trap_group(self, dvs): - """Remove trap group and verify that all related trap counters are removed - - Args: - dvs (object): virtual switch object - """ - self.setup_dbs(dvs) - meta_data = counter_group_meta['trap_flow_counter'] - self.set_flex_counter_group_status(meta_data['key'], meta_data['name_map']) - - removed_group = None - trap_ids = None - copp_groups = self.app_db.db_connection.keys('COPP_TABLE:*') - for copp_group in copp_groups: - trap_ids = self.app_db.db_connection.hget(copp_group, 'trap_ids') - if trap_ids and trap_ids.strip(): - removed_group = copp_group.split(':')[1] - break - - if not removed_group: - pytest.skip('There is not copp group with at least 1 traps, skip rest of the test') - - trap_ids = [x.strip() for x in trap_ids.split(',')] - for _ in range(NUMBER_OF_RETRIES): - counters_keys = self.counters_db.db_connection.hgetall(meta_data['name_map']) - found = True - for trap_id in trap_ids: - if trap_id not in counters_keys: - found = False - break - if found: - break - else: - time.sleep(1) - - assert found, 'Not all trap id found in name map' - for trap_id in trap_ids: - self.wait_for_id_list(meta_data['group_name'], trap_id, counters_keys[trap_id]) - - app_copp_table = swsscommon.ProducerStateTable(self.app_db.db_connection, 'COPP_TABLE') - app_copp_table._del(removed_group) - - for trap_id in trap_ids: - self.wait_for_id_list_remove(meta_data['group_name'], trap_id, counters_keys[trap_id]) - - counters_keys = self.counters_db.db_connection.hgetall(meta_data['name_map']) - for trap_id in trap_ids: - assert trap_id not in counters_keys - - self.set_flex_counter_group_status(meta_data['key'], meta_data['name_map'], 'disable') - - def test_update_route_pattern(self, dvs): - self.setup_dbs(dvs) - self.config_db.create_entry('FLOW_COUNTER_ROUTE_PATTERN', '1.1.0.0/16', - { - 'max_match_count': '30' - } - ) - self.create_l3_intf("Ethernet0", "") - self.create_l3_intf("Ethernet4", "") - self.add_ip_address("Ethernet0", "10.0.0.0/31") - self.add_ip_address("Ethernet4", "10.0.0.2/31") - self.set_admin_status("Ethernet0", "up") - self.set_admin_status("Ethernet4", "up") - # set ip address and default route - dvs.servers[0].runcmd("ip address add 10.0.0.1/31 dev eth0") - dvs.servers[0].runcmd("ip route add default via 10.0.0.0") - dvs.servers[1].runcmd("ip address add 10.0.0.3/31 dev eth0") - dvs.servers[1].runcmd("ip route add default via 10.0.0.2") - dvs.servers[0].runcmd("ping -c 1 10.0.0.3") - - dvs.runcmd("vtysh -c \"configure terminal\" -c \"ip route 1.1.1.0/24 10.0.0.1\"") - dvs.runcmd("vtysh -c \"configure terminal\" -c \"ip route 2.2.2.0/24 10.0.0.3\"") - - meta_data = counter_group_meta['route_flow_counter'] - self.set_flex_counter_group_status(meta_data['key'], meta_data['name_map']) - self.wait_for_table(meta_data['name_map']) - self.wait_for_table(ROUTE_TO_PATTERN_MAP) - counter_oid = self.counters_db.db_connection.hget(meta_data['name_map'], '1.1.1.0/24') - self.wait_for_id_list(meta_data['group_name'], '1.1.1.0/24', counter_oid) - assert not self.counters_db.db_connection.hget(meta_data['name_map'], '2.2.2.0/24') - assert not self.counters_db.db_connection.hget(ROUTE_TO_PATTERN_MAP, '2.2.2.0/24') - - self.config_db.delete_entry('FLOW_COUNTER_ROUTE_PATTERN', '1.1.0.0/16') - self.wait_for_id_list_remove(meta_data['group_name'], '1.1.1.0/24', counter_oid) - self.wait_for_table_empty(meta_data['name_map']) - self.wait_for_table_empty(ROUTE_TO_PATTERN_MAP) - assert not self.counters_db.db_connection.hget(meta_data['name_map'], '1.1.1.0/24') - assert not self.counters_db.db_connection.hget(ROUTE_TO_PATTERN_MAP, '1.1.1.0/24') - - self.config_db.create_entry('FLOW_COUNTER_ROUTE_PATTERN', '2.2.0.0/16', - { - 'max_match_count': '30' - } - ) - self.wait_for_table(meta_data['name_map']) - self.wait_for_table(ROUTE_TO_PATTERN_MAP) - counter_oid = self.counters_db.db_connection.hget(meta_data['name_map'], '2.2.2.0/24') - self.wait_for_id_list(meta_data['group_name'], '2.2.2.0/24', counter_oid) - - self.set_flex_counter_group_status(meta_data['key'], meta_data['name_map'], 'disable') - self.wait_for_id_list_remove(meta_data['group_name'], '2.2.2.0/24', counter_oid) - self.wait_for_table_empty(meta_data['name_map']) - self.wait_for_table_empty(ROUTE_TO_PATTERN_MAP) - - self.config_db.delete_entry('FLOW_COUNTER_ROUTE_PATTERN', '2.2.0.0/16') - dvs.runcmd("vtysh -c \"configure terminal\" -c \"no ip route {} 10.0.0.1\"".format('1.1.1.0/24')) - dvs.runcmd("vtysh -c \"configure terminal\" -c \"no ip route {} 10.0.0.3\"".format('2.2.2.0/24')) - - # remove ip address - self.remove_ip_address("Ethernet0", "10.0.0.0/31") - self.remove_ip_address("Ethernet4", "10.0.0.2/31") - - # remove l3 interface - self.remove_l3_intf("Ethernet0") - self.remove_l3_intf("Ethernet4") - - self.set_admin_status("Ethernet0", "down") - self.set_admin_status("Ethernet4", "down") - - # remove ip address and default route - dvs.servers[0].runcmd("ip route del default dev eth0") - dvs.servers[0].runcmd("ip address del 10.0.0.1/31 dev eth0") - - dvs.servers[1].runcmd("ip route del default dev eth0") - dvs.servers[1].runcmd("ip address del 10.0.0.3/31 dev eth0") - - def test_add_remove_route_flow_counter(self, dvs): - self.setup_dbs(dvs) - self.config_db.create_entry('FLOW_COUNTER_ROUTE_PATTERN', '1.1.0.0/16', - { - 'max_match_count': '30' - } - ) - meta_data = counter_group_meta['route_flow_counter'] - self.set_flex_counter_group_status(meta_data['key'], meta_data['name_map'], check_name_map=False) - - self.create_l3_intf("Ethernet0", "") - self.add_ip_address("Ethernet0", "10.0.0.0/31") - self.set_admin_status("Ethernet0", "up") - dvs.servers[0].runcmd("ip address add 10.0.0.1/31 dev eth0") - dvs.servers[0].runcmd("ip route add default via 10.0.0.0") - dvs.servers[0].runcmd("ping -c 1 10.0.0.1") - dvs.runcmd("vtysh -c \"configure terminal\" -c \"ip route 1.1.1.0/24 10.0.0.1\"") - - self.wait_for_table(meta_data['name_map']) - self.wait_for_table(ROUTE_TO_PATTERN_MAP) - counter_oid = self.counters_db.db_connection.hget(meta_data['name_map'], '1.1.1.0/24') - self.wait_for_id_list(meta_data['group_name'], '1.1.1.0/24', counter_oid) - - dvs.runcmd("vtysh -c \"configure terminal\" -c \"no ip route {} 10.0.0.1\"".format('1.1.1.0/24')) - self.wait_for_id_list_remove(meta_data['group_name'], '1.1.1.0/24', counter_oid) - self.wait_for_table_empty(meta_data['name_map']) - self.wait_for_table_empty(ROUTE_TO_PATTERN_MAP) - - self.config_db.delete_entry('FLOW_COUNTER_ROUTE_PATTERN', '1.1.0.0/16') - self.set_flex_counter_group_status(meta_data['key'], meta_data['group_name'], 'disable') - - # remove ip address - self.remove_ip_address("Ethernet0", "10.0.0.0/31") - - # remove l3 interface - self.remove_l3_intf("Ethernet0") - - self.set_admin_status("Ethernet0", "down") - - # remove ip address and default route - dvs.servers[0].runcmd("ip route del default dev eth0") - dvs.servers[0].runcmd("ip address del 10.0.0.1/31 dev eth0") - - def test_router_flow_counter_max_match_count(self, dvs): - self.setup_dbs(dvs) - self.config_db.create_entry('FLOW_COUNTER_ROUTE_PATTERN', '1.1.0.0/16', - { - 'max_match_count': '1' - } - ) - meta_data = counter_group_meta['route_flow_counter'] - self.set_flex_counter_group_status(meta_data['key'], meta_data['name_map'], check_name_map=False) - self.create_l3_intf("Ethernet0", "") - self.create_l3_intf("Ethernet4", "") - self.add_ip_address("Ethernet0", "10.0.0.0/31") - self.add_ip_address("Ethernet4", "10.0.0.2/31") - self.set_admin_status("Ethernet0", "up") - self.set_admin_status("Ethernet4", "up") - # set ip address and default route - dvs.servers[0].runcmd("ip address add 10.0.0.1/31 dev eth0") - dvs.servers[0].runcmd("ip route add default via 10.0.0.0") - dvs.servers[1].runcmd("ip address add 10.0.0.3/31 dev eth0") - dvs.servers[1].runcmd("ip route add default via 10.0.0.2") - dvs.servers[0].runcmd("ping -c 1 10.0.0.3") - dvs.runcmd("vtysh -c \"configure terminal\" -c \"ip route 1.1.1.0/24 10.0.0.1\"") - dvs.runcmd("vtysh -c \"configure terminal\" -c \"ip route 1.1.2.0/24 10.0.0.3\"") - - self.wait_for_table(meta_data['name_map']) - self.wait_for_table(ROUTE_TO_PATTERN_MAP) - counter_oid = self.counters_db.db_connection.hget(meta_data['name_map'], '1.1.1.0/24') - self.wait_for_id_list(meta_data['group_name'], '1.1.1.0/24', counter_oid) - assert not self.counters_db.db_connection.hget(meta_data['name_map'], '1.1.2.0/24') - self.config_db.update_entry('FLOW_COUNTER_ROUTE_PATTERN', '1.1.0.0/16', - { - 'max_match_count': '2' - } - ) - for _ in range(NUMBER_OF_RETRIES): - counter_oid = self.counters_db.db_connection.hget(meta_data['name_map'], '1.1.2.0/24') - if not counter_oid: - time.sleep(1) - else: - break - assert counter_oid - self.wait_for_id_list(meta_data['group_name'], '1.1.2.0/24', counter_oid) - - self.config_db.update_entry('FLOW_COUNTER_ROUTE_PATTERN', '1.1.0.0/16', - { - 'max_match_count': '1' - } - ) - - for _ in range(NUMBER_OF_RETRIES): - counters_keys = self.counters_db.db_connection.hgetall(meta_data['name_map']) - if len(counters_keys) == 1: - break - else: - time.sleep(1) - - assert len(counters_keys) == 1 - - to_remove = '1.1.2.0/24' if '1.1.2.0/24' in counters_keys else '1.1.1.0/24' - to_remove_nexthop = '10.0.0.3' if '1.1.2.0/24' in counters_keys else '10.0.0.1' - to_bound = '1.1.2.0/24' if '1.1.1.0/24' == to_remove else '1.1.1.0/24' - to_bound_nexthop = '10.0.0.1' if '1.1.2.0/24' in counters_keys else '10.0.0.3' - - dvs.runcmd("vtysh -c \"configure terminal\" -c \"no ip route {} {}\"".format(to_remove, to_remove_nexthop)) - for _ in range(NUMBER_OF_RETRIES): - counter_oid = self.counters_db.db_connection.hget(meta_data['name_map'], to_bound) - if not counter_oid: - time.sleep(1) - else: - break - assert counter_oid - self.wait_for_id_list(meta_data['group_name'], to_bound, counter_oid) - counters_keys = self.counters_db.db_connection.hgetall(meta_data['name_map']) - assert to_remove not in counters_keys - assert to_bound in counters_keys - counters_keys = self.counters_db.db_connection.hgetall(ROUTE_TO_PATTERN_MAP) - assert to_remove not in counters_keys - assert to_bound in counters_keys - - dvs.runcmd("vtysh -c \"configure terminal\" -c \"no ip route {} {}\"".format(to_bound, to_bound_nexthop)) - - # remove ip address - self.remove_ip_address("Ethernet0", "10.0.0.0/31") - self.remove_ip_address("Ethernet4", "10.0.0.2/31") - - # remove l3 interface - self.remove_l3_intf("Ethernet0") - self.remove_l3_intf("Ethernet4") - - self.set_admin_status("Ethernet0", "down") - self.set_admin_status("Ethernet4", "down") - - # remove ip address and default route - dvs.servers[0].runcmd("ip route del default dev eth0") - dvs.servers[0].runcmd("ip address del 10.0.0.1/31 dev eth0") - - dvs.servers[1].runcmd("ip route del default dev eth0") - dvs.servers[1].runcmd("ip address del 10.0.0.3/31 dev eth0") - self.config_db.delete_entry('FLOW_COUNTER_ROUTE_PATTERN', '1.1.0.0/16') - - def create_l3_intf(self, interface, vrf_name): - if len(vrf_name) == 0: - self.config_db.create_entry("INTERFACE", interface, {"NULL": "NULL"}) - else: - self.config_db.create_entry("INTERFACE", interface, {"vrf_name": vrf_name}) - - def remove_l3_intf(self, interface): - self.config_db.delete_entry("INTERFACE", interface) - - def add_ip_address(self, interface, ip): - self.config_db.create_entry("INTERFACE", interface + "|" + ip, {"NULL": "NULL"}) - - def remove_ip_address(self, interface, ip): - self.config_db.delete_entry("INTERFACE", interface + "|" + ip) - - def set_admin_status(self, interface, status): - self.config_db.update_entry("PORT", interface, {"admin_status": status}) - - @pytest.mark.parametrize('counter_type', [('queue_counter'), ('pg_drop_counter')]) - def test_create_only_config_db_buffers_false(self, dvs, counter_type): - """ - Test steps: - 1. By default the configuration knob 'create_only_config_db_value' is missing. - 2. Get the counter OID for the interface 'Ethernet0:7' from the counters database. - 3. Perform assertions based on the 'create_only_config_db_value': - - If 'create_only_config_db_value' is 'false' or does not exist, assert that the counter OID has a valid OID value. - - Args: - dvs (object): virtual switch object - counter_type (str): The type of counter being tested - """ - self.setup_dbs(dvs) - meta_data = counter_group_meta[counter_type] - self.set_flex_counter_group_status(meta_data['key'], meta_data['name_map']) - - counter_oid = self.counters_db.db_connection.hget(meta_data['name_map'], 'Ethernet0:7') - assert counter_oid is not None, "Counter OID should have a valid OID value when create_only_config_db_value is 'false' or does not exist" - - def test_create_remove_buffer_pg_watermark_counter(self, dvs): - """ - Test steps: - 1. Reset config_db - 2. Set 'create_only_config_db_buffers' to 'true' - 3. Enable PG flex counters. - 4. Configure new buffer prioriy group for a port - 5. Verify counter is automatically created - 6. Remove the new buffer prioriy group for the port - 7. Verify counter is automatically removed - - Args: - dvs (object): virtual switch object - """ - dvs.restart() - self.setup_dbs(dvs) - self.set_only_config_db_buffers_field('true') - meta_data = counter_group_meta['pg_watermark_counter'] - - self.set_flex_counter_group_status(meta_data['key'], meta_data['name_map']) - - self.config_db.update_entry('BUFFER_PG', 'Ethernet0|1', {'profile': 'ingress_lossy_profile'}) - counter_oid = self.wait_for_buffer_pg_queue_counter(meta_data['name_map'], 'Ethernet0', '1', True) - self.wait_for_id_list(meta_data['group_name'], "Ethernet0", counter_oid) - - self.config_db.delete_entry('BUFFER_PG', 'Ethernet0|1') - self.wait_for_buffer_pg_queue_counter(meta_data['name_map'], 'Ethernet0', '1', False) - self.wait_for_id_list_remove(meta_data['group_name'], "Ethernet0", counter_oid) - - @pytest.mark.parametrize('counter_type', [('queue_counter'), ('pg_drop_counter')]) - def test_create_only_config_db_buffers_true(self, dvs, counter_type): - """ - Test steps: - 1. The 'create_only_config_db_buffers' was set to 'true' by previous test. - 2. Get the counter OID for the interface 'Ethernet0:7' from the counters database. - 3. Perform assertions based on the 'create_only_config_db_value': - - If 'create_only_config_db_value' is 'true', assert that the counter OID is None. - - Args: - dvs (object): virtual switch object - counter_type (str): The type of counter being tested - """ - self.setup_dbs(dvs) - meta_data = counter_group_meta[counter_type] - self.set_flex_counter_group_status(meta_data['key'], meta_data['name_map']) - - counter_oid = self.counters_db.db_connection.hget(meta_data['name_map'], 'Ethernet0:7') - assert counter_oid is None, "Counter OID should be None when create_only_config_db_value is 'true'" - - def test_create_remove_buffer_queue_counter(self, dvs): - """ - Test steps: - 1. Enable Queue flex counters. - 2. Configure new buffer queue for a port - 3. Verify counter is automatically created - 4. Remove the new buffer queue for the port - 5. Verify counter is automatically removed - - Args: - dvs (object): virtual switch object - """ - self.setup_dbs(dvs) - meta_data = counter_group_meta['queue_counter'] - - self.set_flex_counter_group_status(meta_data['key'], meta_data['name_map']) - - self.config_db.update_entry('BUFFER_QUEUE', 'Ethernet0|7', {'profile': 'egress_lossless_profile'}) - counter_oid = self.wait_for_buffer_pg_queue_counter(meta_data['name_map'], 'Ethernet0', '7', True) - self.wait_for_id_list(meta_data['group_name'], "Ethernet0", counter_oid) - - self.config_db.delete_entry('BUFFER_QUEUE', 'Ethernet0|7') - self.wait_for_buffer_pg_queue_counter(meta_data['name_map'], 'Ethernet0', '7', False) - self.wait_for_id_list_remove(meta_data['group_name'], "Ethernet0", counter_oid) - - def test_create_remove_buffer_watermark_queue_pg_counter(self, dvs): - """ - Test steps: - 1. Enable Queue/Watermark/PG-drop flex counters. - 2. Configure new buffer queue for a port - 3. Verify counters is automatically created - 4. Remove the new buffer queue for the port - 5. Verify counters is automatically removed - - Args: - dvs (object): virtual switch object - """ - self.setup_dbs(dvs) - - # set flex counter - for counterpoll_type, meta_data in counter_group_meta.items(): - if 'queue' in counterpoll_type or 'pg' in counterpoll_type: - self.set_flex_counter_group_status(meta_data['key'], meta_data['name_map']) - - self.config_db.update_entry('BUFFER_PG', 'Ethernet0|7', {'profile': 'ingress_lossy_profile'}) - self.config_db.update_entry('BUFFER_QUEUE', 'Ethernet0|7', {'profile': 'egress_lossless_profile'}) - - for counterpoll_type, meta_data in counter_group_meta.items(): - if 'queue' in counterpoll_type or 'pg' in counterpoll_type: - counter_oid = self.wait_for_buffer_pg_queue_counter(meta_data['name_map'], 'Ethernet0', '7', True) - self.wait_for_id_list(meta_data['group_name'], "Ethernet0", counter_oid) - - self.config_db.delete_entry('BUFFER_QUEUE', 'Ethernet0|7') - self.config_db.delete_entry('BUFFER_PG', 'Ethernet0|7') - for counterpoll_type, meta_data in counter_group_meta.items(): - if 'queue' in counterpoll_type or 'pg' in counterpoll_type: - self.wait_for_buffer_pg_queue_counter(meta_data['name_map'], 'Ethernet0', '7', False) - self.wait_for_id_list_remove(meta_data['group_name'], "Ethernet0", counter_oid) diff --git a/tests/test_gearbox.py b/tests/test_gearbox.py deleted file mode 100644 index 6707213990..0000000000 --- a/tests/test_gearbox.py +++ /dev/null @@ -1,203 +0,0 @@ -# This test suite covers the functionality of gearbox feature -import time -import os -import pytest -from swsscommon import swsscommon -from dvslib.dvs_database import DVSDatabase -from dvslib.dvs_common import PollingConfig, wait_for_result - -# module specific dvs env variables -DVS_ENV = ["HWSKU=brcm_gearbox_vs"] - -class Gearbox(object): - def __init__(self, dvs): - db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - t = swsscommon.Table(db, "_GEARBOX_TABLE") - assert len(t.getKeys()) > 0 - sr = t.getTableNameSeparator() - - # "_GEARBOX_TABLE:phy:1" - # "_GEARBOX_TABLE:phy:1:ports:0" - # "_GEARBOX_TABLE:phy:1:lanes:200" - self.phys = {} - phy_table = swsscommon.Table(db, sr.join([t.getKeyName(""), "phy"])) - for i in [x for x in phy_table.getKeys() if sr not in x]: - (status, fvs) = phy_table.get(i) - assert status == True - self.phys[i] = {"attrs" : dict(fvs)} - - port_table = swsscommon.Table(db, sr.join([phy_table.getKeyName(i), "ports"])) - port_list = [x for x in port_table.getKeys() if sr not in x] - self.phys[i]["port_table"] = port_table - self.phys[i]["ports"] = {} - for j in port_list: - (status, fvs) = port_table.get(j) - assert status == True - self.phys[i]["ports"][j] = dict(fvs) - - lane_table = swsscommon.Table(db, sr.join([phy_table.getKeyName(i), "lanes"])) - lane_list = [x for x in lane_table.getKeys() if sr not in x] - self.phys[i]["lanes"] = {} - for j in lane_list: - (status, fvs) = lane_table.get(j) - assert status == True - self.phys[i]["lanes"][j] = dict(fvs) - - # "_GEARBOX_TABLE:interface:0" - self.interfaces = {} - intf_table = swsscommon.Table(db, sr.join([t.getKeyName(""), "interface"])) - for i in [x for x in intf_table.getKeys() if sr not in x]: - (status, fvs) = intf_table.get(i) - assert status == True - self.interfaces[i] = dict(fvs) - - def SanityCheck(self, testlog): - """ - Verify data integrity of Gearbox objects in APPL_DB - """ - for i in self.interfaces: - phy_id = self.interfaces[i]["phy_id"] - assert phy_id in self.phys - assert self.interfaces[i]["index"] in self.phys[phy_id]["ports"] - - for lane in self.interfaces[i]["system_lanes"].split(','): - assert lane in self.phys[phy_id]["lanes"] - for lane in self.interfaces[i]["line_lanes"].split(','): - assert lane in self.phys[phy_id]["lanes"] - -class GBAsic(DVSDatabase): - def __init__(self, db_id: int, connector: str, gearbox: Gearbox): - DVSDatabase.__init__(self, db_id, connector) - self.gearbox = gearbox - self.ports = {} - self.port_oid_to_intf_idx = {} - self._wait_for_gb_asic_db_to_initialize() - - for connector in self.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_PORT_CONNECTOR"): - fvs = self.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_PORT_CONNECTOR", connector) - system_port_oid = fvs.get("SAI_PORT_CONNECTOR_ATTR_SYSTEM_SIDE_PORT_ID") - line_port_oid = fvs.get("SAI_PORT_CONNECTOR_ATTR_LINE_SIDE_PORT_ID") - - fvs = self.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_PORT", system_port_oid) - system_lanes = fvs.get("SAI_PORT_ATTR_HW_LANE_LIST").split(":")[-1] - - fvs = self.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_PORT", line_port_oid) - line_lanes = fvs.get("SAI_PORT_ATTR_HW_LANE_LIST").split(":")[-1] - - for i in self.gearbox.interfaces: - intf = self.gearbox.interfaces[i] - if intf["system_lanes"] == system_lanes: - assert intf["line_lanes"] == line_lanes - self.ports[intf["index"]] = (system_port_oid, line_port_oid) - self.port_oid_to_intf_idx[system_port_oid] = (i, True) - self.port_oid_to_intf_idx[line_port_oid] = (i, False) - - assert len(self.ports) == len(self.gearbox.interfaces) - - for serdes in self.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_PORT_SERDES"): - fvs = self.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_PORT_SERDES", serdes) - port_oid = fvs.get("SAI_PORT_SERDES_ATTR_PORT_ID") - intf_idx, is_system = self.port_oid_to_intf_idx[port_oid] - intf = self.gearbox.interfaces[ intf_idx ] - appl_db_key_prefix = 'system_' if is_system else 'line_' - for asic_db_key, appl_db_key_suffix in [ - ("SAI_PORT_SERDES_ATTR_TX_FIR_MAIN", "tx_fir_main"), - ("SAI_PORT_SERDES_ATTR_TX_FIR_PRE1", "tx_fir_pre1"), - ("SAI_PORT_SERDES_ATTR_TX_FIR_PRE2", "tx_fir_pre2"), - ("SAI_PORT_SERDES_ATTR_TX_FIR_PRE3", "tx_fir_pre3"), - ("SAI_PORT_SERDES_ATTR_TX_FIR_POST1", "tx_fir_post1"), - ("SAI_PORT_SERDES_ATTR_TX_FIR_POST2", "tx_fir_post2"), - ("SAI_PORT_SERDES_ATTR_TX_FIR_POST3", "tx_fir_post3"), - ]: - if asic_db_key not in fvs: - continue - asic_db_value = fvs.get(asic_db_key).split(":")[-1] - assert intf[appl_db_key_prefix + appl_db_key_suffix] == asic_db_value - - def _wait_for_gb_asic_db_to_initialize(self) -> None: - """Wait up to 30 seconds for the default fields to appear in ASIC DB.""" - def _verify_db_contents(): - if len(self.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_SWITCH")) != \ - len(self.gearbox.phys): - return (False, None) - - if len(self.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_PORT")) != \ - 2 * len(self.gearbox.interfaces): - return (False, None) - - if len(self.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_PORT_CONNECTOR")) != \ - len(self.gearbox.interfaces): - return (False, None) - - return (True, None) - - # Verify that GB ASIC DB has been fully initialized - init_polling_config = PollingConfig(2, 30, strict=True) - wait_for_result(_verify_db_contents, init_polling_config) - -@pytest.fixture(scope="module") -def gearbox(dvs): - return Gearbox(dvs) - -@pytest.fixture(scope="module") -def gbasic(dvs, gearbox): - return GBAsic(swsscommon.GB_ASIC_DB, dvs.redis_sock, gearbox) - -@pytest.fixture(scope="module") -def enable_port_counter(dvs): - flex_counter_table = swsscommon.Table(dvs.get_config_db().db_connection, - "FLEX_COUNTER_TABLE") - - # Enable port counter - flex_counter_table.hset("PORT", "FLEX_COUNTER_STATUS", "enable") - yield - # Disable port counter - flex_counter_table.hdel("PORT", "FLEX_COUNTER_STATUS") - -class TestGearbox(object): - def test_GearboxSanity(self, gearbox, testlog): - gearbox.SanityCheck(testlog) - - def test_GearboxCounter(self, dvs, gbasic, enable_port_counter, testlog): - counters_db = DVSDatabase(swsscommon.COUNTERS_DB, dvs.redis_sock) - gb_counters_db = DVSDatabase(swsscommon.GB_COUNTERS_DB, dvs.redis_sock) - - intf = gbasic.gearbox.interfaces["0"] - port_oid = counters_db.get_entry("COUNTERS_PORT_NAME_MAP", "")[intf["name"]] - system_port_oid, line_port_oid = gbasic.ports["0"] - - fvs = gb_counters_db.wait_for_entry("COUNTERS", system_port_oid) - assert fvs.get("SAI_PORT_STAT_IF_OUT_ERRORS") - - fvs = gb_counters_db.wait_for_entry("COUNTERS", line_port_oid) - assert fvs.get("SAI_PORT_STAT_IF_IN_ERRORS") - - fvs = counters_db.wait_for_entry("COUNTERS", port_oid) - assert fvs.get("SAI_PORT_STAT_IF_IN_ERRORS") - - fvs = counters_db.wait_for_entry("COUNTERS", port_oid) - assert fvs.get("SAI_PORT_STAT_IF_IN_ERRORS") - - def test_GbAsicFEC(self, gbasic, testlog): - - # set fec rs on port 0 of phy 1 - fvs = swsscommon.FieldValuePairs([("system_fec","rs")]) - gbasic.gearbox.phys["1"]["port_table"].set("0", fvs) - fvs = swsscommon.FieldValuePairs([("line_fec","rs")]) - gbasic.gearbox.phys["1"]["port_table"].set("0", fvs) - - """FIXME: uncomment it after GearboxOrch is implemented - # validate if fec rs is pushed to system/line port in gb asic db - system_port_oid, line_port_oid = gbasic.ports["0"] - expected_fields = {"SAI_PORT_ATTR_FEC_MODE":"SAI_PORT_FEC_MODE_RS"} - gbasic.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", \ - system_port_oid, expected_fields) - gbasic.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", \ - line_port_oid, expected_fields) - """ - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_hash.py b/tests/test_hash.py deleted file mode 100644 index b84dd91eaf..0000000000 --- a/tests/test_hash.py +++ /dev/null @@ -1,292 +0,0 @@ -import pytest -import logging - - -logging.basicConfig(level=logging.INFO) -hashlogger = logging.getLogger(__name__) - - -HASH_FIELD_LIST = [ - "DST_MAC", - "SRC_MAC", - "ETHERTYPE", - "IP_PROTOCOL", - "DST_IP", - "SRC_IP", - "L4_DST_PORT", - "L4_SRC_PORT" -] -INNER_HASH_FIELD_LIST = [ - "INNER_DST_MAC", - "INNER_SRC_MAC", - "INNER_ETHERTYPE", - "INNER_IP_PROTOCOL", - "INNER_DST_IP", - "INNER_SRC_IP", - "INNER_L4_DST_PORT", - "INNER_L4_SRC_PORT" -] -DEFAULT_HASH_FIELD_LIST = [ - "DST_MAC", - "SRC_MAC", - "ETHERTYPE", - "IN_PORT" -] -HASH_ALGORITHM = [ - "CRC", - "XOR", - "RANDOM", - "CRC_32LO", - "CRC_32HI", - "CRC_CCITT", - "CRC_XOR" -] - -SAI_HASH_FIELD_LIST = [ - "SAI_NATIVE_HASH_FIELD_DST_MAC", - "SAI_NATIVE_HASH_FIELD_SRC_MAC", - "SAI_NATIVE_HASH_FIELD_ETHERTYPE", - "SAI_NATIVE_HASH_FIELD_IP_PROTOCOL", - "SAI_NATIVE_HASH_FIELD_DST_IP", - "SAI_NATIVE_HASH_FIELD_SRC_IP", - "SAI_NATIVE_HASH_FIELD_L4_DST_PORT", - "SAI_NATIVE_HASH_FIELD_L4_SRC_PORT" -] -SAI_INNER_HASH_FIELD_LIST = [ - "SAI_NATIVE_HASH_FIELD_INNER_DST_MAC", - "SAI_NATIVE_HASH_FIELD_INNER_SRC_MAC", - "SAI_NATIVE_HASH_FIELD_INNER_ETHERTYPE", - "SAI_NATIVE_HASH_FIELD_INNER_IP_PROTOCOL", - "SAI_NATIVE_HASH_FIELD_INNER_DST_IP", - "SAI_NATIVE_HASH_FIELD_INNER_SRC_IP", - "SAI_NATIVE_HASH_FIELD_INNER_L4_DST_PORT", - "SAI_NATIVE_HASH_FIELD_INNER_L4_SRC_PORT" -] -SAI_DEFAULT_HASH_FIELD_LIST = [ - "SAI_NATIVE_HASH_FIELD_DST_MAC", - "SAI_NATIVE_HASH_FIELD_SRC_MAC", - "SAI_NATIVE_HASH_FIELD_ETHERTYPE", - "SAI_NATIVE_HASH_FIELD_IN_PORT" -] -SAI_HASH_ALGORITHM = [ - "SAI_HASH_ALGORITHM_CRC", - "SAI_HASH_ALGORITHM_XOR", - "SAI_HASH_ALGORITHM_RANDOM", - "SAI_HASH_ALGORITHM_CRC_32LO", - "SAI_HASH_ALGORITHM_CRC_32HI", - "SAI_HASH_ALGORITHM_CRC_CCITT", - "SAI_HASH_ALGORITHM_CRC_XOR" -] - - -@pytest.mark.usefixtures("dvs_hash_manager") -@pytest.mark.usefixtures("dvs_switch_manager") -class TestHashBasicFlows: - @pytest.fixture(scope="class") - def hashData(self, dvs_hash_manager): - hashlogger.info("Initialize HASH data") - - hashlogger.info("Verify HASH count") - self.dvs_hash.verify_hash_count(0) - - hashlogger.info("Get ECMP/LAG HASH id") - hashIdList = sorted(self.dvs_hash.get_hash_ids()) - - # Assumption: VS has only two HASH objects: ECMP, LAG - meta_dict = { - "ecmp": hashIdList[0], - "lag": hashIdList[1] - } - - yield meta_dict - - hashlogger.info("Deinitialize HASH data") - - @pytest.fixture(scope="class") - def switchData(self, dvs_switch_manager): - hashlogger.info("Initialize SWITCH data") - - hashlogger.info("Verify SWITCH count") - self.dvs_switch.verify_switch_count(0) - - hashlogger.info("Get SWITCH id") - switchIdList = self.dvs_switch.get_switch_ids() - - # Assumption: VS has only one SWITCH object - meta_dict = { - "id": switchIdList[0] - } - - yield meta_dict - - hashlogger.info("Deinitialize SWITCH data") - - @pytest.mark.parametrize( - "hash,field", [ - pytest.param( - "ecmp", - "ecmp_hash", - id="ecmp-hash" - ), - pytest.param( - "lag", - "lag_hash", - id="lag-hash" - ) - ] - ) - @pytest.mark.parametrize( - "hfList,saiHfList", [ - pytest.param( - ",".join(HASH_FIELD_LIST), - SAI_HASH_FIELD_LIST, - id="outer-frame" - ), - pytest.param( - ",".join(INNER_HASH_FIELD_LIST), - SAI_INNER_HASH_FIELD_LIST, - id="inner-frame" - ) - ] - ) - def test_HashSwitchGlobalConfiguration(self, hash, field, hfList, saiHfList, testlog, hashData): - attr_dict = { - field: hfList - } - - hashlogger.info("Update {} hash".format(hash.upper())) - self.dvs_hash.update_switch_hash( - qualifiers=attr_dict - ) - - hashId = hashData[hash] - sai_attr_dict = { - "SAI_HASH_ATTR_NATIVE_HASH_FIELD_LIST": saiHfList - } - - hashlogger.info("Validate {} hash".format(hash.upper())) - self.dvs_hash.verify_hash_generic( - sai_hash_id=hashId, - sai_qualifiers=sai_attr_dict - ) - - @pytest.mark.parametrize( - "hash,field", [ - pytest.param( - "ecmp", - "ecmp_hash", - id="ecmp-hash" - ), - pytest.param( - "lag", - "lag_hash", - id="lag-hash" - ) - ] - ) - def test_HashDefaultSwitchGlobalConfiguration(self, hash, field, testlog, hashData): - attr_dict = { - field: ",".join(DEFAULT_HASH_FIELD_LIST) - } - - hashlogger.info("Update {} hash".format(hash.upper())) - self.dvs_hash.update_switch_hash( - qualifiers=attr_dict - ) - - hashId = hashData[hash] - sai_attr_dict = { - "SAI_HASH_ATTR_NATIVE_HASH_FIELD_LIST": SAI_DEFAULT_HASH_FIELD_LIST - } - - hashlogger.info("Validate {} hash".format(hash.upper())) - self.dvs_hash.verify_hash_generic( - sai_hash_id=hashId, - sai_qualifiers=sai_attr_dict - ) - - @pytest.mark.parametrize( - "algorithm,attr,field", [ - pytest.param( - "ecmp", - "SAI_SWITCH_ATTR_ECMP_DEFAULT_HASH_ALGORITHM", - "ecmp_hash_algorithm", - id="ecmp-hash-algorithm" - ), - pytest.param( - "lag", - "SAI_SWITCH_ATTR_LAG_DEFAULT_HASH_ALGORITHM", - "lag_hash_algorithm", - id="lag-hash-algorithm" - ) - ] - ) - @pytest.mark.parametrize( - "value", HASH_ALGORITHM - ) - def test_HashAlgorithmSwitchGlobalConfiguration(self, algorithm, attr, field, value, testlog, switchData): - attr_dict = { - field: value - } - - hashlogger.info("Update {} hash algorithm".format(algorithm.upper())) - self.dvs_hash.update_switch_hash( - qualifiers=attr_dict - ) - - switchId = switchData["id"] - sai_attr_dict = { - attr: SAI_HASH_ALGORITHM[HASH_ALGORITHM.index(value)] - } - - hashlogger.info("Validate {} hash algorithm".format(algorithm.upper())) - self.dvs_switch.verify_switch( - sai_switch_id=switchId, - sai_qualifiers=sai_attr_dict - ) - - @pytest.mark.parametrize( - "algorithm,attr,field", [ - pytest.param( - "ecmp", - "SAI_SWITCH_ATTR_ECMP_DEFAULT_HASH_ALGORITHM", - "ecmp_hash_algorithm", - id="ecmp-hash-algorithm" - ), - pytest.param( - "lag", - "SAI_SWITCH_ATTR_LAG_DEFAULT_HASH_ALGORITHM", - "lag_hash_algorithm", - id="lag-hash-algorithm" - ) - ] - ) - @pytest.mark.parametrize( - "value", [ "CRC" ] - ) - def test_HashDefaultAlgorithmSwitchGlobalConfiguration(self, algorithm, attr, field, value, testlog, switchData): - attr_dict = { - field: value - } - - hashlogger.info("Update {} hash algorithm".format(algorithm.upper())) - self.dvs_hash.update_switch_hash( - qualifiers=attr_dict - ) - - switchId = switchData["id"] - sai_attr_dict = { - attr: SAI_HASH_ALGORITHM[HASH_ALGORITHM.index(value)] - } - - hashlogger.info("Validate {} hash algorithm".format(algorithm.upper())) - self.dvs_switch.verify_switch( - sai_switch_id=switchId, - sai_qualifiers=sai_attr_dict - ) - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_inband_intf_mgmt_vrf.py b/tests/test_inband_intf_mgmt_vrf.py deleted file mode 100644 index 4b1b8c86ed..0000000000 --- a/tests/test_inband_intf_mgmt_vrf.py +++ /dev/null @@ -1,168 +0,0 @@ -import time -import pytest - -from swsscommon import swsscommon - -MGMT_VRF_NAME = 'mgmt' -INBAND_INTF_NAME = 'Ethernet4' - -class TestInbandInterface(object): - def setup_db(self, dvs): - self.appl_db = swsscommon.DBConnector(0, dvs.redis_sock, 0) - self.asic_db = dvs.get_asic_db() - self.cfg_db = swsscommon.DBConnector(4, dvs.redis_sock, 0) - - def add_mgmt_vrf(self, dvs): - initial_entries = set(self.asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER")) - dvs.runcmd("ip link add mgmt type vrf table 5000") - dvs.runcmd("ifconfig mgmt up") - time.sleep(2) - - # check application database - tbl = swsscommon.Table(self.appl_db, 'VRF_TABLE') - vrf_keys = tbl.getKeys() - assert len(vrf_keys) == 0 - - tbl = swsscommon.Table(self.cfg_db, 'MGMT_VRF_CONFIG') - fvs = swsscommon.FieldValuePairs([('mgmtVrfEnabled', 'true'), ('in_band_mgmt_enabled', 'true')]) - tbl.set('vrf_global', fvs) - time.sleep(1) - - # check application database - tbl = swsscommon.Table(self.appl_db, 'VRF_TABLE') - vrf_keys = tbl.getKeys() - assert len(vrf_keys) == 1 - assert vrf_keys[0] == MGMT_VRF_NAME - - # check SAI database info present in ASIC_DB - self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER", len(initial_entries) + 1) - current_entries = set(self.asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER")) - assert len(current_entries - initial_entries) == 1 - return list(current_entries - initial_entries)[0] - - def del_inband_mgmt_vrf(self): - tbl = swsscommon.Table(self.cfg_db, 'MGMT_VRF_CONFIG') - fvs = swsscommon.FieldValuePairs([('mgmtVrfEnabled', 'true'), ('in_band_mgmt_enabled', 'false')]) - tbl.set('vrf_global', fvs) - time.sleep(5) - - # check application database - tbl = swsscommon.Table(self.appl_db, 'VRF_TABLE') - vrf_keys = tbl.getKeys() - assert len(vrf_keys) == 0 - - def del_mgmt_vrf(self, dvs): - dvs.runcmd("ip link del mgmt") - tbl = swsscommon.Table(self.cfg_db, 'MGMT_VRF_CONFIG') - tbl._del('vrf_global') - time.sleep(5) - - def create_inband_intf(self, interface): - cfg_tbl = cfg_key = cfg_fvs = None - if interface.startswith('PortChannel'): - tbl_name = 'PORTCHANNEL_INTERFACE' - cfg_tbl = 'PORTCHANNEL' - cfg_key = interface - cfg_fvs = swsscommon.FieldValuePairs([("admin_status", "up"), - ("mtu", "9100")]) - elif interface.startswith('Vlan'): - tbl_name = 'VLAN_INTERFACE' - cfg_tbl = 'VLAN' - vlan_id = interface[len('Vlan'):] - cfg_key = 'Vlan' + vlan_id - cfg_fvs = swsscommon.FieldValuePairs([("vlanid", vlan_id)]) - elif interface.startswith('Loopback'): - tbl_name = 'LOOPBACK_INTERFACE' - else: - tbl_name = 'INTERFACE' - if cfg_tbl is not None: - tbl = swsscommon.Table(self.cfg_db, cfg_tbl) - tbl.set(cfg_key, cfg_fvs) - time.sleep(1) - fvs = swsscommon.FieldValuePairs([('vrf_name', MGMT_VRF_NAME)]) - tbl = swsscommon.Table(self.cfg_db, tbl_name) - tbl.set(interface, fvs) - time.sleep(1) - - def remove_inband_intf(self, interface): - cfg_tbl = cfg_key = None - if interface.startswith('PortChannel'): - tbl_name = 'PORTCHANNEL_INTERFACE' - cfg_tbl = 'PORTCHANNEL' - cfg_key = interface - elif interface.startswith('Vlan'): - tbl_name = 'VLAN_INTERFACE' - cfg_tbl = 'VLAN' - vlan_id = interface[len('Vlan'):] - cfg_key = 'Vlan' + vlan_id - elif interface.startswith('Loopback'): - tbl_name = 'LOOPBACK_INTERFACE' - else: - tbl_name = 'INTERFACE' - tbl = swsscommon.Table(self.cfg_db, tbl_name) - tbl._del(interface) - time.sleep(1) - if cfg_tbl is not None: - tbl = swsscommon.Table(self.cfg_db, cfg_tbl) - tbl._del(cfg_key) - time.sleep(1) - - def test_MgmtVrf(self, dvs, testlog): - self.setup_db(dvs) - - vrf_oid = self.add_mgmt_vrf(dvs) - self.del_inband_mgmt_vrf() - self.del_mgmt_vrf(dvs) - - @pytest.mark.parametrize('intf_name', ['Ethernet4', 'Vlan100', 'PortChannel5', 'Loopback1']) - def test_InbandIntf(self, intf_name, dvs, testlog): - self.setup_db(dvs) - - vrf_oid = self.add_mgmt_vrf(dvs) - self.create_inband_intf(intf_name) - - # check application database - tbl = swsscommon.Table(self.appl_db, 'INTF_TABLE') - intf_keys = tbl.getKeys() - status, fvs = tbl.get(intf_name) - assert status == True - for fv in fvs: - if fv[0] == 'vrf_name': - assert fv[1] == MGMT_VRF_NAME - - if not intf_name.startswith('Loopback'): - # check ASIC router interface database - # one loopback router interface one port based router interface - intf_entries = self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE", 2) - for key in intf_entries: - fvs = self.asic_db.wait_for_entry("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE", key) - loopback = False - intf_vrf_oid = None - for k, v in fvs.items(): - if k == 'SAI_ROUTER_INTERFACE_ATTR_TYPE' and v == 'SAI_ROUTER_INTERFACE_TYPE_LOOPBACK': - loopback = True - break - if k == 'SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID': - intf_vrf_oid = v - if loopback: - continue - assert intf_vrf_oid == vrf_oid - - self.remove_inband_intf(intf_name) - time.sleep(1) - # check application database - tbl = swsscommon.Table(self.appl_db, 'INTF_TABLE') - intf_keys = tbl.getKeys() - assert len(intf_keys) == 0 - - if not intf_name.startswith('Loopback'): - self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE", 1) - - self.del_inband_mgmt_vrf() - self.del_mgmt_vrf(dvs) - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_interface.py b/tests/test_interface.py deleted file mode 100644 index 98f1527152..0000000000 --- a/tests/test_interface.py +++ /dev/null @@ -1,2296 +0,0 @@ -import time -import json -import pytest - -from swsscommon import swsscommon - -VLAN_SUB_INTERFACE_SEPARATOR = '.' - -class TestRouterInterface(object): - def setup_db(self, dvs): - self.pdb = swsscommon.DBConnector(0, dvs.redis_sock, 0) - self.adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - self.cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) - - def set_admin_status(self, dvs, interface, status): - if interface.startswith("PortChannel"): - tbl_name = "PORTCHANNEL" - elif interface.startswith("Vlan"): - tbl_name = "VLAN" - else: - tbl_name = "PORT" - tbl = swsscommon.Table(self.cdb, tbl_name) - fvs = swsscommon.FieldValuePairs([("admin_status", status)]) - tbl.set(interface, fvs) - time.sleep(1) - - # when using FRR, route cannot be inserted if the neighbor is not - # connected. thus it is mandatory to force the interface up manually - if interface.startswith("PortChannel"): - dvs.runcmd("bash -c 'echo " + ("1" if status == "up" else "0") +\ - " > /sys/class/net/" + interface + "/carrier'") - time.sleep(1) - - def create_vrf(self, vrf_name): - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER") - initial_entries = set(tbl.getKeys()) - - tbl = swsscommon.Table(self.cdb, "VRF") - fvs = swsscommon.FieldValuePairs([('empty', 'empty')]) - tbl.set(vrf_name, fvs) - time.sleep(1) - - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER") - current_entries = set(tbl.getKeys()) - assert len(current_entries - initial_entries) == 1 - return list(current_entries - initial_entries)[0] - - def remove_vrf(self, vrf_name): - tbl = swsscommon.Table(self.cdb, "VRF") - tbl._del(vrf_name) - time.sleep(1) - - def create_l3_intf(self, interface, vrf_name): - if interface.startswith("PortChannel"): - tbl_name = "PORTCHANNEL_INTERFACE" - elif interface.startswith("Vlan"): - tbl_name = "VLAN_INTERFACE" - elif interface.startswith("Loopback"): - tbl_name = "LOOPBACK_INTERFACE" - else: - tbl_name = "INTERFACE" - if len(vrf_name) == 0: - fvs = swsscommon.FieldValuePairs([("NULL", "NULL")]) - else: - fvs = swsscommon.FieldValuePairs([("vrf_name", vrf_name)]) - tbl = swsscommon.Table(self.cdb, tbl_name) - tbl.set(interface, fvs) - time.sleep(1) - - def remove_l3_intf(self, interface): - if interface.startswith("PortChannel"): - tbl_name = "PORTCHANNEL_INTERFACE" - elif interface.startswith("Vlan"): - tbl_name = "VLAN_INTERFACE" - elif interface.startswith("Loopback"): - tbl_name = "LOOPBACK_INTERFACE" - else: - tbl_name = "INTERFACE" - tbl = swsscommon.Table(self.cdb, tbl_name) - tbl._del(interface) - time.sleep(1) - - def add_ip_address(self, interface, ip): - if interface.startswith("PortChannel"): - tbl_name = "PORTCHANNEL_INTERFACE" - elif interface.startswith("Vlan"): - tbl_name = "VLAN_INTERFACE" - elif interface.startswith("Loopback"): - tbl_name = "LOOPBACK_INTERFACE" - else: - tbl_name = "INTERFACE" - tbl = swsscommon.Table(self.cdb, tbl_name) - fvs = swsscommon.FieldValuePairs([("NULL", "NULL")]) - tbl.set(interface + "|" + ip, fvs) - time.sleep(1) - - def remove_ip_address(self, interface, ip): - if interface.startswith("PortChannel"): - tbl_name = "PORTCHANNEL_INTERFACE" - elif interface.startswith("Vlan"): - tbl_name = "VLAN_INTERFACE" - elif interface.startswith("Loopback"): - tbl_name = "LOOPBACK_INTERFACE" - else: - tbl_name = "INTERFACE" - tbl = swsscommon.Table(self.cdb, tbl_name) - tbl._del(interface + "|" + ip) - time.sleep(1) - - def set_mtu(self, interface, mtu): - if interface.startswith("PortChannel"): - tbl_name = "PORTCHANNEL" - elif interface.startswith("Vlan"): - tbl_name = "VLAN" - else: - tbl_name = "PORT" - tbl = swsscommon.Table(self.cdb, tbl_name) - fvs = swsscommon.FieldValuePairs([("mtu", mtu)]) - tbl.set(interface, fvs) - time.sleep(1) - - def test_PortInterfaceAddRemoveIpv6Address(self, dvs, testlog): - self.setup_db(dvs) - - # create interface - self.create_l3_intf("Ethernet8", "") - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE") - (status, fvs) = tbl.get("Ethernet8") - assert status == True - for fv in fvs: - assert fv[0] != "vrf_name" - - # bring up interface - # NOTE: For IPv6, only when the interface is up will the netlink message - # get generated. - self.set_admin_status(dvs, "Ethernet8", "up") - - # assign IP to interface - self.add_ip_address("Ethernet8", "fc00::1/126") - time.sleep(2) # IPv6 netlink message needs longer time - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:Ethernet8") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 1 - assert intf_entries[0] == "fc00::1/126" - - (status, fvs) = tbl.get(tbl.getKeys()[0]) - assert status == True - assert len(fvs) == 2 - for fv in fvs: - if fv[0] == "scope": - assert fv[1] == "global" - elif fv[0] == "family": - assert fv[1] == "IPv6" - else: - assert False - - # check ASIC router interface database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") - intf_entries = tbl.getKeys() - # one loopback router interface one port based router interface - assert len(intf_entries) == 2 - - for key in intf_entries: - (status, fvs) = tbl.get(key) - assert status == True - # a port based router interface has five field/value tuples - if len(fvs) == 5: - for fv in fvs: - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_TYPE": - assert fv[1] == "SAI_ROUTER_INTERFACE_TYPE_PORT" - # the default MTU without any configuration is 9100 - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_MTU": - assert fv[1] == "9100" - - # check ASIC route database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - for key in tbl.getKeys(): - route = json.loads(key) - if route["dest"] == "fc00::/126": - subnet_found = True - if route["dest"] == "fc00::1/128": - ip2me_found = True - - assert subnet_found and ip2me_found - - # remove IP from interface - self.remove_ip_address("Ethernet8", "fc00::1/126") - - # remove interface - self.remove_l3_intf("Ethernet8") - - # bring down interface - self.set_admin_status(dvs, "Ethernet8", "down") - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:Ethernet8") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - tbl = swsscommon.Table(self.pdb, "INTF_TABLE") - intf_entries = tbl.getKeys() - for entry in intf_entries: - assert entry[0] != "Ethernet8" - - # check ASIC database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - for key in tbl.getKeys(): - route = json.loads(key) - if route["dest"] == "fc00::/126": - assert False - if route["dest"] == "fc00::1/128": - assert False - - def test_PortInterfaceAddRemoveIpv4Address(self, dvs, testlog): - self.setup_db(dvs) - - # bring up interface - self.set_admin_status(dvs, "Ethernet8", "up") - - # create interface - self.create_l3_intf("Ethernet8", "") - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE") - (status, fvs) = tbl.get("Ethernet8") - assert status == True - for fv in fvs: - assert fv[0] != "vrf_name" - - # assign IP to interface - self.add_ip_address("Ethernet8", "10.0.0.4/31") - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:Ethernet8") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 1 - assert intf_entries[0] == "10.0.0.4/31" - - (status, fvs) = tbl.get(tbl.getKeys()[0]) - assert status == True - assert len(fvs) == 2 - for fv in fvs: - if fv[0] == "scope": - assert fv[1] == "global" - elif fv[0] == "family": - assert fv[1] == "IPv4" - else: - assert False - - # check ASIC router interface database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") - intf_entries = tbl.getKeys() - # one loopback router interface one port based router interface - assert len(intf_entries) == 2 - - for key in intf_entries: - (status, fvs) = tbl.get(key) - assert status == True - # a port based router interface has five field/value tuples - if len(fvs) == 5: - for fv in fvs: - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_TYPE": - assert fv[1] == "SAI_ROUTER_INTERFACE_TYPE_PORT" - # the default MTU without any configuration is 9100 - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_MTU": - assert fv[1] == "9100" - - # check ASIC route database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - for key in tbl.getKeys(): - route = json.loads(key) - if route["dest"] == "10.0.0.4/31": - subnet_found = True - if route["dest"] == "10.0.0.4/32": - ip2me_found = True - - assert subnet_found and ip2me_found - - # remove IP from interface - self.remove_ip_address("Ethernet8", "10.0.0.4/31") - - # remove interface - self.remove_l3_intf("Ethernet8") - - # bring down interface - self.set_admin_status(dvs, "Ethernet8", "down") - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:Ethernet8") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - tbl = swsscommon.Table(self.pdb, "INTF_TABLE") - intf_entries = tbl.getKeys() - for entry in intf_entries: - assert entry[0] != "Ethernet8" - - # check ASIC database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - for key in tbl.getKeys(): - route = json.loads(key) - if route["dest"] == "10.0.0.4/31": - assert False - if route["dest"] == "10.0.0.4/32": - assert False - - def test_PortInterfaceSetMtu(self, dvs, testlog): - self.setup_db(dvs) - - # create interface - self.create_l3_intf("Ethernet16", "") - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE") - (status, fvs) = tbl.get("Ethernet16") - assert status == True - for fv in fvs: - assert fv[0] != "vrf_name" - - # assign IP to interface - self.add_ip_address("Ethernet16", "20.0.0.8/29") - - # configure MTU to interface - self.set_mtu("Ethernet16", "8888") - - # check ASIC router interface database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") - intf_entries = tbl.getKeys() - # one loopback router interface one port based router interface - assert len(intf_entries) == 2 - - for key in intf_entries: - (status, fvs) = tbl.get(key) - assert status == True - # a port based router interface has five field/value tuples - if len(fvs) == 5: - for fv in fvs: - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_TYPE": - assert fv[1] == "SAI_ROUTER_INTERFACE_TYPE_PORT" - # assert the new value set to the router interface - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_MTU": - assert fv[1] == "8888" - - # remove IP from interface - self.remove_ip_address("Ethernet16", "20.0.0.8/29") - - # remove interface - self.remove_l3_intf("Ethernet16") - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:Ethernet16") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - tbl = swsscommon.Table(self.pdb, "INTF_TABLE") - intf_entries = tbl.getKeys() - for entry in intf_entries: - assert entry[0] != "Ethernet16" - - # check ASIC database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - for key in tbl.getKeys(): - route = json.loads(key) - if route["dest"] == "20.0.0.8/29": - assert False - if route["dest"] == "20.0.0.8/32": - assert False - - def test_PortInterfaceAddRemoveIpv6AddressWithVrf(self, dvs, testlog): - self.setup_db(dvs) - - # bring up interface - self.set_admin_status(dvs, "Ethernet8", "up") - - # create vrf - vrf_oid = self.create_vrf("Vrf_0") - - # create interface with vrf - self.create_l3_intf("Ethernet8", "Vrf_0") - - # check interface's vrf - tbl = swsscommon.Table(self.pdb, "INTF_TABLE") - (status, fvs) = tbl.get("Ethernet8") - assert status == True - for fv in fvs: - if fv[0] == "vrf_name": - assert fv[1] == "Vrf_0" - vrf_found = True - break - assert vrf_found == True - - # check linux kernel - (exitcode, result) = dvs.runcmd(['sh', '-c', "ip link show Ethernet8 | grep Vrf"]) - assert "Vrf_0" in result - - # assign IP to interface - self.add_ip_address("Ethernet8", "fc00::1/126") - time.sleep(2) # IPv6 netlink message needs longer time - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:Ethernet8") - intf_entries = tbl.getKeys() - - assert len(intf_entries) == 1 - assert intf_entries[0] == "fc00::1/126" - - (status, fvs) = tbl.get(tbl.getKeys()[0]) - assert status == True - assert len(fvs) == 2 - for fv in fvs: - if fv[0] == "scope": - assert fv[1] == "global" - elif fv[0] == "family": - assert fv[1] == "IPv6" - else: - assert False - - # check ASIC router interface database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") - intf_entries = tbl.getKeys() - # one loopback router interface one port based router interface - assert len(intf_entries) == 2 - - for key in intf_entries: - (status, fvs) = tbl.get(key) - assert status == True - # a port based router interface has five field/value tuples - if len(fvs) == 5: - for fv in fvs: - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_TYPE": - assert fv[1] == "SAI_ROUTER_INTERFACE_TYPE_PORT" - # the default MTU without any configuration is 9100 - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_MTU": - assert fv[1] == "9100" - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": - assert fv[1] == vrf_oid - - # check ASIC route database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - for key in tbl.getKeys(): - route = json.loads(key) - if route["dest"] == "fc00::/126": - subnet_found = True - assert route["vr"] == vrf_oid - if route["dest"] == "fc00::1/128": - ip2me_found = True - assert route["vr"] == vrf_oid - - assert subnet_found and ip2me_found - - # remove IP from interface - self.remove_ip_address("Ethernet8", "fc00::1/126") - - # remove vrf from interface - self.remove_l3_intf("Ethernet8") - - # remove vrf - self.remove_vrf("Vrf_0") - - # bring down interface - self.set_admin_status(dvs, "Ethernet8", "down") - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:Ethernet8") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - # check linux kernel - (exitcode, result) = dvs.runcmd(['sh', '-c', "ip link show Ethernet8 | grep Vrf"]) - assert "Vrf_0" not in result - - tbl = swsscommon.Table(self.pdb, "INTF_TABLE") - intf_entries = tbl.getKeys() - for entry in intf_entries: - assert entry[0] != "Ethernet8" - - tbl = swsscommon.Table(self.pdb, "VRF") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - # check ASIC database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - for key in tbl.getKeys(): - route = json.loads(key) - if route["dest"] == "fc00::/126": - assert False - if route["dest"] == "fc00::1/128": - assert False - - def test_PortInterfaceAddRemoveIpv4AddressWithVrf(self, dvs, testlog): - self.setup_db(dvs) - - # bring up interface - self.set_admin_status(dvs, "Ethernet8", "up") - - # create vrf - vrf_oid = self.create_vrf("Vrf_0") - - # create interface with vrf - self.create_l3_intf("Ethernet8", "Vrf_0") - - # check interface's vrf - tbl = swsscommon.Table(self.pdb, "INTF_TABLE") - (status, fvs) = tbl.get("Ethernet8") - assert status == True - for fv in fvs: - if fv[0] == "vrf_name": - assert fv[1] == "Vrf_0" - vrf_found = True - break - assert vrf_found == True - - # assign IP to interface - self.add_ip_address("Ethernet8", "10.0.0.4/31") - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:Ethernet8") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 1 - assert intf_entries[0] == "10.0.0.4/31" - - (status, fvs) = tbl.get(tbl.getKeys()[0]) - assert status == True - assert len(fvs) == 2 - for fv in fvs: - if fv[0] == "scope": - assert fv[1] == "global" - elif fv[0] == "family": - assert fv[1] == "IPv4" - else: - assert False - - # check ASIC router interface database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") - intf_entries = tbl.getKeys() - # one loopback router interface one port based router interface - assert len(intf_entries) == 2 - - for key in intf_entries: - (status, fvs) = tbl.get(key) - assert status == True - # a port based router interface has five field/value tuples - if len(fvs) == 5: - for fv in fvs: - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_TYPE": - assert fv[1] == "SAI_ROUTER_INTERFACE_TYPE_PORT" - # the default MTU without any configuration is 9100 - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_MTU": - assert fv[1] == "9100" - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": - assert fv[1] == vrf_oid - - # check ASIC route database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - for key in tbl.getKeys(): - route = json.loads(key) - if route["dest"] == "10.0.0.4/31": - subnet_found = True - assert route["vr"] == vrf_oid - if route["dest"] == "10.0.0.4/32": - ip2me_found = True - assert route["vr"] == vrf_oid - - assert subnet_found and ip2me_found - - # remove IP from interface - self.remove_ip_address("Ethernet8", "10.0.0.4/31") - - # remove interface - self.remove_l3_intf("Ethernet8") - - # remove vrf - self.remove_vrf("Vrf_0") - - # bring down interface - self.set_admin_status(dvs, "Ethernet8", "down") - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:Ethernet8") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - tbl = swsscommon.Table(self.pdb, "INTF_TABLE") - intf_entries = tbl.getKeys() - for entry in intf_entries: - assert entry[0] != "Ethernet8" - - tbl = swsscommon.Table(self.pdb, "VRF") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - # check ASIC database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - for key in tbl.getKeys(): - route = json.loads(key) - if route["dest"] == "10.0.0.4/31": - assert False - if route["dest"] == "10.0.0.4/32": - assert False - - def test_PortInterfaceAddSameIpv4AddressWithDiffVrf(self, dvs, testlog): - self.setup_db(dvs) - - for i in [0, 4]: - # record ASIC router interface database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") - old_intf_entries = set(tbl.getKeys()) - - # record ASIC router entry database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - old_route_entries = set(tbl.getKeys()) - - intf_name = "Ethernet" + str(i) - vrf_name = "Vrf_" + str(i) - - # bring up interface - self.set_admin_status(dvs, intf_name, "up") - - # create vrf - vrf_oid = self.create_vrf(vrf_name) - - # create interface with vrf - self.create_l3_intf(intf_name, vrf_name) - - # check interface's vrf - tbl = swsscommon.Table(self.pdb, "INTF_TABLE") - (status, fvs) = tbl.get(intf_name) - assert status == True - for fv in fvs: - if fv[0] == "vrf_name": - assert fv[1] == vrf_name - vrf_found = True - break - assert vrf_found == True - - # assign IP to interface - self.add_ip_address(intf_name, "10.0.0.4/31") - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:" + intf_name) - intf_entries = tbl.getKeys() - assert len(intf_entries) == 1 - assert intf_entries[0] == "10.0.0.4/31" - - (status, fvs) = tbl.get(tbl.getKeys()[0]) - assert status == True - assert len(fvs) == 2 - for fv in fvs: - if fv[0] == "scope": - assert fv[1] == "global" - elif fv[0] == "family": - assert fv[1] == "IPv4" - else: - assert False - - # check ASIC router interface database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") - current_intf_entries = set(tbl.getKeys()) - intf_entries = list(current_intf_entries - old_intf_entries) - for key in intf_entries: - (status, fvs) = tbl.get(key) - assert status == True - # a port based router interface has five field/value tuples - if len(fvs) == 5: - for fv in fvs: - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_TYPE": - assert fv[1] == "SAI_ROUTER_INTERFACE_TYPE_PORT" - # the default MTU without any configuration is 9100 - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_MTU": - assert fv[1] == "9100" - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": - assert fv[1] == vrf_oid - - # check ASIC route database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - current_route_entries = set(tbl.getKeys()) - route_entries = list(current_route_entries - old_route_entries) - - for key in route_entries: - route = json.loads(key) - if route["dest"] == "10.0.0.4/31": - subnet_found = True - assert route["vr"] == vrf_oid - if route["dest"] == "10.0.0.4/32": - ip2me_found = True - assert route["vr"] == vrf_oid - - assert subnet_found and ip2me_found - - - for i in [0, 4]: - # check ASIC router interface database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") - old_intf_entries = set(tbl.getKeys()) - - intf_name = "Ethernet" + str(i) - vrf_name = "Vrf_" + str(i) - - # remove IP from interface - self.remove_ip_address(intf_name, "10.0.0.4/31") - - # remove interface - self.remove_l3_intf(intf_name) - - # remove vrf - self.remove_vrf(vrf_name) - - # bring down interface - self.set_admin_status(dvs, intf_name, "down") - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:" + intf_name) - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - tbl = swsscommon.Table(self.pdb, "INTF_TABLE") - intf_entries = tbl.getKeys() - for entry in intf_entries: - assert entry[0] != "Ethernet0" and entry[0] != "Ethernet4" - - tbl = swsscommon.Table(self.pdb, "VRF") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - # check ASIC database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - for key in tbl.getKeys(): - route = json.loads(key) - if route["dest"] == "10.0.0.4/31": - assert False - if route["dest"] == "10.0.0.4/32": - assert False - - def create_port_channel(self, alias): - tbl = swsscommon.Table(self.cdb, "PORTCHANNEL") - fvs = swsscommon.FieldValuePairs([("admin_status", "up"), - ("mtu", "9100")]) - tbl.set(alias, fvs) - time.sleep(1) - - def remove_port_channel(self, alias): - tbl = swsscommon.Table(self.cdb, "PORTCHANNEL") - tbl._del(alias) - time.sleep(1) - - def add_port_channel_members(self, lag, members): - tbl = swsscommon.Table(self.cdb, "PORTCHANNEL_MEMBER") - fvs = swsscommon.FieldValuePairs([("NULL", "NULL")]) - for member in members: - tbl.set(lag + "|" + member, fvs) - time.sleep(1) - - def remove_port_channel_members(self, lag, members): - tbl = swsscommon.Table(self.cdb, "PORTCHANNEL_MEMBER") - for member in members: - tbl._del(lag + "|" + member) - time.sleep(1) - - def test_LagInterfaceAddRemoveIpv6Address(self, dvs, testlog): - self.setup_db(dvs) - - # create port channel - self.create_port_channel("PortChannel001") - - # bring up interface - self.set_admin_status(dvs, "PortChannel001", "up") - - # create l3 interface - self.create_l3_intf("PortChannel001", "") - - # assign IP to interface - self.add_ip_address("PortChannel001", "fc00::1/126") - time.sleep(2) # IPv6 netlink message needs longer time - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:PortChannel001") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 1 - assert intf_entries[0] == "fc00::1/126" - - (status, fvs) = tbl.get(tbl.getKeys()[0]) - assert status == True - assert len(fvs) == 2 - for fv in fvs: - if fv[0] == "scope": - assert fv[1] == "global" - elif fv[0] == "family": - assert fv[1] == "IPv6" - else: - assert False - - # check ASIC router interface database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") - intf_entries = tbl.getKeys() - # one loopback router interface one port based router interface - assert len(intf_entries) == 2 - - for key in intf_entries: - (status, fvs) = tbl.get(key) - assert status == True - # a port based router interface has five field/value tuples - if len(fvs) == 5: - for fv in fvs: - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_TYPE": - assert fv[1] == "SAI_ROUTER_INTERFACE_TYPE_PORT" - # the default MTU without any configuration is 9100 - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_MTU": - assert fv[1] == "9100" - - # check ASIC route database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - for key in tbl.getKeys(): - route = json.loads(key) - if route["dest"] == "fc00::/126": - subnet_found = True - if route["dest"] == "fc00::1/128": - ip2me_found = True - - assert subnet_found and ip2me_found - - # remove IP from interface - self.remove_ip_address("PortChannel001", "fc00::1/126") - - # remove interface - self.remove_l3_intf("PortChannel001") - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:PortChannel001") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - tbl = swsscommon.Table(self.pdb, "INTF_TABLE") - intf_entries = tbl.getKeys() - for entry in intf_entries: - assert entry[0] != "PortChannel001" - - # check ASIC database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - for key in tbl.getKeys(): - route = json.loads(key) - if route["dest"] == "fc00::/126": - assert False - if route["dest"] == "fc00::1/128": - assert False - - # remove port channel - self.remove_port_channel("PortChannel001") - - def test_LagInterfaceAddRemoveIpv4Address(self, dvs, testlog): - self.setup_db(dvs) - - # create port channel - self.create_port_channel("PortChannel001") - - # bring up interface - self.set_admin_status(dvs, "PortChannel001", "up") - - # create l3 interface - self.create_l3_intf("PortChannel001", "") - - # assign IP to interface - self.add_ip_address("PortChannel001", "30.0.0.4/31") - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:PortChannel001") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 1 - assert intf_entries[0] == "30.0.0.4/31" - - (status, fvs) = tbl.get(tbl.getKeys()[0]) - assert status == True - assert len(fvs) == 2 - for fv in fvs: - if fv[0] == "scope": - assert fv[1] == "global" - elif fv[0] == "family": - assert fv[1] == "IPv4" - else: - assert False - - # check ASIC router interface database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") - intf_entries = tbl.getKeys() - # one loopback router interface one port based router interface - assert len(intf_entries) == 2 - - for key in intf_entries: - (status, fvs) = tbl.get(key) - assert status == True - # a port based router interface has five field/value tuples - if len(fvs) == 5: - for fv in fvs: - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_TYPE": - assert fv[1] == "SAI_ROUTER_INTERFACE_TYPE_PORT" - # the default MTU without any configuration is 9100 - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_MTU": - assert fv[1] == "9100" - - # check ASIC route database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - for key in tbl.getKeys(): - route = json.loads(key) - if route["dest"] == "30.0.0.4/31": - subnet_found = True - if route["dest"] == "30.0.0.4/32": - ip2me_found = True - - assert subnet_found and ip2me_found - - # remove IP from interface - self.remove_ip_address("PortChannel001", "30.0.0.4/31") - - # remove l3 interface - self.remove_l3_intf("PortChannel001") - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:PortChannel001") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - tbl = swsscommon.Table(self.pdb, "INTF_TABLE") - intf_entries = tbl.getKeys() - for entry in intf_entries: - assert entry[0] != "PortChannel001" - - # check ASIC database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - for key in tbl.getKeys(): - route = json.loads(key) - if route["dest"] == "30.0.0.4/31": - assert False - if route["dest"] == "30.0.0.4/32": - assert False - - # remove port channel - self.remove_port_channel("PortChannel001") - - @pytest.mark.skip(reason="vs image issue: Azure/sonic-sairedis#574") - def test_LagInterfaceSetMtu(self, dvs, testlog): - self.setup_db(dvs) - - # create port channel - self.create_port_channel("PortChannel002") - - # add port channel members - self.add_port_channel_members("PortChannel002", ["Ethernet0", "Ethernet4"]) - - # create l3 interface - self.create_l3_intf("PortChannel002", "") - - # assign IP to interface - self.add_ip_address("PortChannel002", "40.0.0.8/29") - - # configure MTU to interface - self.set_mtu("PortChannel002", "8888") - - # check ASIC router interface database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") - intf_entries = tbl.getKeys() - # one loopback router interface one port based router interface - assert len(intf_entries) == 2 - - for key in intf_entries: - (status, fvs) = tbl.get(key) - assert status == True - # a port based router interface has five field/value tuples - if len(fvs) == 5: - for fv in fvs: - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_TYPE": - assert fv[1] == "SAI_ROUTER_INTERFACE_TYPE_PORT" - # assert the new value set to the router interface - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_MTU": - assert fv[1] == "8888" - - # check ASIC port database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_PORT") - port_entries = tbl.getKeys() - - for key in port_entries: - (status, fvs) = tbl.get(key) - assert status == True - # a member port configured with MTU will have six field/value tuples - if len(fvs) == 6: - for fv in fvs: - # asser the new value 8888 + 22 = 8910 set to the port - if fv[0] == "SAI_PORT_ATTR_MTU": - assert fv[1] == "8910" - - # remove IP from interface - self.remove_ip_address("PortChannel002", "40.0.0.8/29") - - # remove l3 interface - self.remove_l3_intf("PortChannel002") - - # remove port channel members - self.remove_port_channel_members("PortChannel002", ["Ethernet0", "Ethernet4"]) - - # remove port channel - self.remove_port_channel("PortChannel002") - - def test_LagInterfaceAddRemoveIpv6AddressWithVrf(self, dvs, testlog): - self.setup_db(dvs) - - # create vrf - vrf_oid = self.create_vrf("Vrf_0") - - # create port channel - self.create_port_channel("PortChannel001") - - # bring up interface - self.set_admin_status(dvs, "PortChannel001", "up") - - # create l3 interface - self.create_l3_intf("PortChannel001", "Vrf_0") - - # check interface's vrf - tbl = swsscommon.Table(self.pdb, "INTF_TABLE") - (status, fvs) = tbl.get("PortChannel001") - assert status == True - for fv in fvs: - if fv[0] == "vrf_name": - assert fv[1] == "Vrf_0" - vrf_found = True - break - assert vrf_found == True - - # assign IP to interface - self.add_ip_address("PortChannel001", "fc00::1/126") - time.sleep(2) # IPv6 netlink message needs longer time - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:PortChannel001") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 1 - assert intf_entries[0] == "fc00::1/126" - - (status, fvs) = tbl.get(tbl.getKeys()[0]) - assert status == True - assert len(fvs) == 2 - for fv in fvs: - if fv[0] == "scope": - assert fv[1] == "global" - elif fv[0] == "family": - assert fv[1] == "IPv6" - else: - assert False - - # check ASIC router interface database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") - intf_entries = tbl.getKeys() - # one loopback router interface one port based router interface - assert len(intf_entries) == 2 - - for key in intf_entries: - (status, fvs) = tbl.get(key) - assert status == True - # a port based router interface has five field/value tuples - if len(fvs) == 5: - for fv in fvs: - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_TYPE": - assert fv[1] == "SAI_ROUTER_INTERFACE_TYPE_PORT" - # the default MTU without any configuration is 9100 - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_MTU": - assert fv[1] == "9100" - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": - assert fv[1] == vrf_oid - # check ASIC route database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - for key in tbl.getKeys(): - route = json.loads(key) - if route["dest"] == "fc00::/126": - subnet_found = True - assert route["vr"] == vrf_oid - if route["dest"] == "fc00::1/128": - ip2me_found = True - assert route["vr"] == vrf_oid - - assert subnet_found and ip2me_found - - # remove IP from interface - self.remove_ip_address("PortChannel001", "fc00::1/126") - - # remove interface - self.remove_l3_intf("PortChannel001") - - # remove vrf - self.remove_vrf("Vrf_0") - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:PortChannel001") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - tbl = swsscommon.Table(self.pdb, "INTF_TABLE") - intf_entries = tbl.getKeys() - for entry in intf_entries: - assert entry[0] != "PortChannel001" - - tbl = swsscommon.Table(self.pdb, "VRF") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - # check ASIC database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - for key in tbl.getKeys(): - route = json.loads(key) - if route["dest"] == "fc00::1/126": - assert False - if route["dest"] == "fc00::1/128": - assert False - - # remove port channel - self.remove_port_channel("PortChannel001") - - def test_LagInterfaceAddRemoveIpv4AddressWithVrf(self, dvs, testlog): - self.setup_db(dvs) - - # create port channel - self.create_port_channel("PortChannel001") - - # create vrf - vrf_oid = self.create_vrf("Vrf_0") - - # create interface with vrf - self.create_l3_intf("PortChannel001", "Vrf_0") - - # bring up interface - self.set_admin_status(dvs, "PortChannel001", "up") - - # check interface's vrf - tbl = swsscommon.Table(self.pdb, "INTF_TABLE") - (status, fvs) = tbl.get("PortChannel001") - assert status == True - for fv in fvs: - if fv[0] == "vrf_name": - assert fv[1] == "Vrf_0" - vrf_found = True - break - assert vrf_found == True - - # check linux kernel - (exitcode, result) = dvs.runcmd(['sh', '-c', "ip link show PortChannel001 | grep Vrf"]) - assert "Vrf_0" in result - - # assign IP to interface - self.add_ip_address("PortChannel001", "30.0.0.4/31") - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:PortChannel001") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 1 - assert intf_entries[0] == "30.0.0.4/31" - - (status, fvs) = tbl.get(tbl.getKeys()[0]) - assert status == True - assert len(fvs) == 2 - for fv in fvs: - if fv[0] == "scope": - assert fv[1] == "global" - elif fv[0] == "family": - assert fv[1] == "IPv4" - else: - assert False - - # check ASIC router interface database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") - intf_entries = tbl.getKeys() - # one loopback router interface one port based router interface - assert len(intf_entries) == 2 - - for key in intf_entries: - (status, fvs) = tbl.get(key) - assert status == True - # a port based router interface has five field/value tuples - if len(fvs) == 5: - for fv in fvs: - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_TYPE": - assert fv[1] == "SAI_ROUTER_INTERFACE_TYPE_PORT" - # the default MTU without any configuration is 9100 - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_MTU": - assert fv[1] == "9100" - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": - assert fv[1] == vrf_oid - - # check ASIC route database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - for key in tbl.getKeys(): - route = json.loads(key) - if route["dest"] == "30.0.0.4/31": - subnet_found = True - assert route["vr"] == vrf_oid - if route["dest"] == "30.0.0.4/32": - ip2me_found = True - assert route["vr"] == vrf_oid - - assert subnet_found and ip2me_found - - # remove IP from interface - self.remove_ip_address("PortChannel001", "30.0.0.4/31") - - # remove l3 interface - self.remove_l3_intf("PortChannel001") - - # check linux kernel - (exitcode, result) = dvs.runcmd(['sh', '-c', "ip link show PortChannel001 | grep Vrf"]) - assert "Vrf_0" not in result - - # remove vrf - self.remove_vrf("Vrf_0") - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:PortChannel001") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - tbl = swsscommon.Table(self.pdb, "INTF_TABLE") - intf_entries = tbl.getKeys() - for entry in intf_entries: - assert entry[0] != "PortChannel001" - - tbl = swsscommon.Table(self.pdb, "VRF") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - # check ASIC database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - for key in tbl.getKeys(): - route = json.loads(key) - if route["dest"] == "30.0.0.4/31": - assert False - if route["dest"] == "30.0.0.4/32": - assert False - - # remove port channel - self.remove_port_channel("PortChannel001") - - def create_vlan(self, vlan_id): - tbl = swsscommon.Table(self.cdb, "VLAN") - fvs = swsscommon.FieldValuePairs([("vlanid", vlan_id)]) - tbl.set("Vlan" + vlan_id, fvs) - time.sleep(1) - - def remove_vlan(self, vlan_id): - tbl = swsscommon.Table(self.cdb, "VLAN") - tbl._del("Vlan" + vlan_id) - time.sleep(1) - - def create_vlan_member(self, vlan_id, interface): - tbl = swsscommon.Table(self.cdb, "VLAN_MEMBER") - fvs = swsscommon.FieldValuePairs([("tagging_mode", "untagged")]) - tbl.set("Vlan" + vlan_id + "|" + interface, fvs) - time.sleep(1) - - def remove_vlan_member(self, vlan_id, interface): - tbl = swsscommon.Table(self.cdb, "VLAN_MEMBER") - tbl._del("Vlan" + vlan_id + "|" + interface) - time.sleep(1) - - def test_VLanInterfaceAddRemoveIpv6Address(self, dvs, testlog): - self.setup_db(dvs) - - # create vlan - self.create_vlan("10") - - # add vlan member - self.create_vlan_member("10", "Ethernet0") - - # bring up interface - self.set_admin_status(dvs, "Ethernet0", "up") - self.set_admin_status(dvs, "Vlan10", "up") - - # create vlan interface - self.create_l3_intf("Vlan10", "") - - # assign IP to interface - self.add_ip_address("Vlan10", "fc00::1/126") - time.sleep(2) # IPv6 netlink message needs longer time - - # check asic database and get vlan_oid - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - vlan_entries = [k for k in tbl.getKeys() if k != dvs.asicdb.default_vlan_id] - assert len(vlan_entries) == 1 - vlan_oid = vlan_entries[0] - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:Vlan10") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 1 - assert intf_entries[0] == "fc00::1/126" - - (status, fvs) = tbl.get(tbl.getKeys()[0]) - assert status == True - assert len(fvs) == 2 - for fv in fvs: - if fv[0] == "scope": - assert fv[1] == "global" - elif fv[0] == "family": - assert fv[1] == "IPv6" - else: - assert False - - # check ASIC router interface database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") - intf_entries = tbl.getKeys() - # one loopback router interface one vlan router interface - assert len(intf_entries) == 2 - - for key in intf_entries: - (status, fvs) = tbl.get(key) - assert status == True - if len(fvs) == 5: - for fv in fvs: - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_TYPE": - assert fv[1] == "SAI_ROUTER_INTERFACE_TYPE_VLAN" - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_VLAN_ID": - assert fv[1] == vlan_oid - - # check ASIC route database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - for key in tbl.getKeys(): - route = json.loads(key) - if route["dest"] == "fc00::/126": - subnet_found = True - if route["dest"] == "fc00::1/128": - ip2me_found = True - - assert subnet_found and ip2me_found - - # remove IP from interface - self.remove_ip_address("Vlan10", "fc00::1/126") - - # remove interface - self.remove_l3_intf("Vlan10") - - # remove vlan member - self.remove_vlan_member("10", "Ethernet0") - - # remove vlan - self.remove_vlan("10") - - # bring down interface - self.set_admin_status(dvs, "Ethernet0", "down") - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:Vlan10") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - tbl = swsscommon.Table(self.pdb, "INTF_TABLE") - intf_entries = tbl.getKeys() - for entry in intf_entries: - assert entry[0] != "Vlan10" - - # check ASIC database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - for key in tbl.getKeys(): - route = json.loads(key) - if route["dest"] == "fc00::/126": - assert False - if route["dest"] == "fc00::1/128": - assert False - - def test_VLanInterfaceAddRemoveIpv4Address(self, dvs, testlog): - self.setup_db(dvs) - - # create vlan - self.create_vlan("10") - - # add vlan member - self.create_vlan_member("10", "Ethernet0") - - # bring up interface - self.set_admin_status(dvs, "Ethernet0", "up") - self.set_admin_status(dvs, "Vlan10", "up") - - #create vlan interface - self.create_l3_intf("Vlan10", "") - - # assign IP to interface - self.add_ip_address("Vlan10", "10.0.0.4/31") - - # check asic database and get vlan_oid - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - vlan_entries = [k for k in tbl.getKeys() if k != dvs.asicdb.default_vlan_id] - assert len(vlan_entries) == 1 - vlan_oid = vlan_entries[0] - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:Vlan10") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 1 - assert intf_entries[0] == "10.0.0.4/31" - - (status, fvs) = tbl.get(tbl.getKeys()[0]) - assert status == True - assert len(fvs) == 2 - for fv in fvs: - if fv[0] == "scope": - assert fv[1] == "global" - elif fv[0] == "family": - assert fv[1] == "IPv4" - else: - assert False - - # check ASIC router interface database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") - intf_entries = tbl.getKeys() - # one loopback router interface one vlan router interface - assert len(intf_entries) == 2 - - for key in intf_entries: - (status, fvs) = tbl.get(key) - assert status == True - if len(fvs) == 5: - for fv in fvs: - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_TYPE": - assert fv[1] == "SAI_ROUTER_INTERFACE_TYPE_VLAN" - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_VLAN_ID": - assert fv[1] == vlan_oid - - # check ASIC route database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - for key in tbl.getKeys(): - route = json.loads(key) - if route["dest"] == "10.0.0.4/31": - subnet_found = True - if route["dest"] == "10.0.0.4/32": - ip2me_found = True - - assert subnet_found and ip2me_found - - # remove IP from interface - self.remove_ip_address("Vlan10", "10.0.0.4/31") - - # remove vlan interface - self.remove_l3_intf("Vlan10") - - # remove vlan member - self.remove_vlan_member("10", "Ethernet0") - - # remove vlan - self.remove_vlan("10") - - # bring down interface - self.set_admin_status(dvs, "Ethernet0", "down") - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:Vlan10") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - tbl = swsscommon.Table(self.pdb, "VLAN_TABLE") - intf_entries = tbl.getKeys() - for entry in intf_entries: - assert entry[0] != "Vlan10" - - # check ASIC database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - for key in tbl.getKeys(): - route = json.loads(key) - if route["dest"] == "10.0.0.4/31": - assert False - if route["dest"] == "10.0.0.4/32": - assert False - - def test_VLanInterfaceAddRemoveIpv6AddressWithVrf(self, dvs, testlog): - self.setup_db(dvs) - - # create vlan - self.create_vlan("10") - - # add vlan member - self.create_vlan_member("10", "Ethernet0") - - # bring up interface - self.set_admin_status(dvs, "Ethernet0", "up") - self.set_admin_status(dvs, "Vlan10", "up") - - # create vrf - vrf_oid = self.create_vrf("Vrf_0") - - # create vlan interface - self.create_l3_intf("Vlan10", "Vrf_0") - - # check linux kernel - (exitcode, result) = dvs.runcmd(['sh', '-c', "ip link show Vlan10 | grep Vrf"]) - assert "Vrf_0" in result - - # assign IP to interface - self.add_ip_address("Vlan10", "fc00::1/126") - time.sleep(2) # IPv6 netlink message needs longer time - - # check interface's vrf - tbl = swsscommon.Table(self.pdb, "INTF_TABLE") - (status, fvs) = tbl.get("Vlan10") - assert status == True - for fv in fvs: - if fv[0] == "vrf_name": - assert fv[1] == "Vrf_0" - vrf_found = True - break - assert vrf_found == True - - # check asic database and get vlan_oid - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - vlan_entries = [k for k in tbl.getKeys() if k != dvs.asicdb.default_vlan_id] - assert len(vlan_entries) == 1 - vlan_oid = vlan_entries[0] - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:Vlan10") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 1 - assert intf_entries[0] == "fc00::1/126" - - (status, fvs) = tbl.get(tbl.getKeys()[0]) - assert status == True - assert len(fvs) == 2 - for fv in fvs: - if fv[0] == "scope": - assert fv[1] == "global" - elif fv[0] == "family": - assert fv[1] == "IPv6" - else: - assert False - - # check ASIC router interface database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") - intf_entries = tbl.getKeys() - # one loopback router interface one vlan router interface - assert len(intf_entries) == 2 - - for key in intf_entries: - (status, fvs) = tbl.get(key) - assert status == True - if len(fvs) == 5: - for fv in fvs: - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_TYPE": - assert fv[1] == "SAI_ROUTER_INTERFACE_TYPE_VLAN" - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_VLAN_ID": - assert fv[1] == vlan_oid - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": - assert fv[1] == vrf_oid - - # check ASIC route database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - for key in tbl.getKeys(): - route = json.loads(key) - if route["dest"] == "fc00::/126": - subnet_found = True - assert route["vr"] == vrf_oid - if route["dest"] == "fc00::1/128": - ip2me_found = True - assert route["vr"] == vrf_oid - - assert subnet_found and ip2me_found - - # remove IP from interface - self.remove_ip_address("Vlan10", "fc00::1/126") - - # remove vlan interface - self.remove_l3_intf("Vlan10") - - # check linux kernel - (exitcode, result) = dvs.runcmd(['sh', '-c', "ip link show Vlan10 | grep Vrf"]) - assert "Vrf_0" not in result - - # remove vlan member - self.remove_vlan_member("10", "Ethernet0") - - # remove vlan - self.remove_vlan("10") - - # bring down interface - self.set_admin_status(dvs, "Ethernet0", "down") - - # remove vrf - self.remove_vrf("Vrf_0") - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:Vlan10") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - tbl = swsscommon.Table(self.pdb, "INTF_TABLE") - intf_entries = tbl.getKeys() - for entry in intf_entries: - assert entry[0] != "Vlan10" - - # check ASIC database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - for key in tbl.getKeys(): - route = json.loads(key) - if route["dest"] == "fc00::/126": - assert False - if route["dest"] == "fc00::1/128": - assert False - - def test_VLanInterfaceAddRemoveIpv4AddressWithVrf(self, dvs, testlog): - self.setup_db(dvs) - - # create vlan - self.create_vlan("10") - - # add vlan member - self.create_vlan_member("10", "Ethernet0") - - # bring up interface - self.set_admin_status(dvs, "Ethernet0", "up") - self.set_admin_status(dvs, "Vlan10", "up") - - # create vrf - vrf_oid = self.create_vrf("Vrf_0") - - # create vlan interface - self.create_l3_intf("Vlan10", "Vrf_0") - - # assign IP to interface - self.add_ip_address("Vlan10", "10.0.0.4/31") - - # check interface's vrf - tbl = swsscommon.Table(self.pdb, "INTF_TABLE") - (status, fvs) = tbl.get("Vlan10") - assert status == True - for fv in fvs: - if fv[0] == "vrf_name": - assert fv[1] == "Vrf_0" - vrf_found = True - break - assert vrf_found == True - - # check asic database and get vlan_oid - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - vlan_entries = [k for k in tbl.getKeys() if k != dvs.asicdb.default_vlan_id] - assert len(vlan_entries) == 1 - vlan_oid = vlan_entries[0] - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:Vlan10") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 1 - assert intf_entries[0] == "10.0.0.4/31" - - (status, fvs) = tbl.get(tbl.getKeys()[0]) - assert status == True - assert len(fvs) == 2 - for fv in fvs: - if fv[0] == "scope": - assert fv[1] == "global" - elif fv[0] == "family": - assert fv[1] == "IPv4" - else: - assert False - - # check ASIC router interface database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") - intf_entries = tbl.getKeys() - # one loopback router interface one vlan router interface - assert len(intf_entries) == 2 - - for key in intf_entries: - (status, fvs) = tbl.get(key) - assert status == True - if len(fvs) == 5: - for fv in fvs: - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_TYPE": - assert fv[1] == "SAI_ROUTER_INTERFACE_TYPE_VLAN" - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_VLAN_ID": - assert fv[1] == vlan_oid - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": - assert fv[1] == vrf_oid - - # check ASIC route database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - for key in tbl.getKeys(): - route = json.loads(key) - if route["dest"] == "10.0.0.4/31": - subnet_found = True - assert route["vr"] == vrf_oid - if route["dest"] == "10.0.0.4/32": - ip2me_found = True - assert route["vr"] == vrf_oid - - assert subnet_found and ip2me_found - - # remove IP from interface - self.remove_ip_address("Vlan10", "10.0.0.4/31") - - # remove vlan interface - self.remove_l3_intf("Vlan10") - - # remove vlan member - self.remove_vlan_member("10", "Ethernet0") - - # remove vlan - self.remove_vlan("10") - - # bring down interface - self.set_admin_status(dvs, "Ethernet0", "down") - - # remove vrf - self.remove_vrf("Vrf_0") - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:Vlan10") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - tbl = swsscommon.Table(self.pdb, "VLAN_TABLE") - intf_entries = tbl.getKeys() - for entry in intf_entries: - assert entry[0] != "Vlan10" - - # check ASIC database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - for key in tbl.getKeys(): - route = json.loads(key) - if route["dest"] == "10.0.0.4/31": - assert False - if route["dest"] == "10.0.0.4/32": - assert False - - def test_LoopbackInterfacesAddRemoveIpv4Address(self, dvs, testlog): - self.setup_db(dvs) - - # Create loopback interfaces - self.create_l3_intf("Loopback0", "") - self.create_l3_intf("Loopback1", "") - - # add ip address - self.add_ip_address("Loopback0", "10.1.0.1/32") - self.add_ip_address("Loopback1", "10.1.0.2/32") - - # Check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:Loopback0") - intf_entries = tbl.getKeys() - assert intf_entries[0] == "10.1.0.1/32" - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:Loopback1") - intf_entries = tbl.getKeys() - assert intf_entries[0] == "10.1.0.2/32" - - # Check ASIC database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - for key in tbl.getKeys(): - route = json.loads(key) - if route["dest"] == "10.1.0.1/32": - lo0_ip2me_found = True - if route["dest"] == "10.1.0.2/32": - lo1_ip2me_found = True - - assert lo0_ip2me_found and lo1_ip2me_found - - # Remove ip address - self.remove_ip_address("Loopback0", "10.1.0.1/32") - self.remove_ip_address("Loopback1", "10.1.0.2/32") - - # Remove interface - self.remove_l3_intf("Loopback0") - self.remove_l3_intf("Loopback1") - - # Check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:Loopback0") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:Loopback1") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - # Check ASIC database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - for key in tbl.getKeys(): - route = json.loads(key) - if route["dest"] == "10.1.0.1/32": - assert False - if route["dest"] == "10.1.0.2/32": - assert False - - def test_LoopbackInterfacesAddRemoveIpv6Address(self, dvs, testlog): - self.setup_db(dvs) - - # Create loopback interfaces - self.create_l3_intf("Loopback0", "") - self.create_l3_intf("Loopback1", "") - - # add ip address - self.add_ip_address("Loopback0", "fc00::1/128") - self.add_ip_address("Loopback1", "fd00::1/128") - time.sleep(2) # IPv6 netlink message needs longer time - - # Check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:Loopback0") - intf_entries = tbl.getKeys() - assert intf_entries[0] == "fc00::1/128" - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:Loopback1") - intf_entries = tbl.getKeys() - assert intf_entries[0] == "fd00::1/128" - - # Check ASIC database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - for key in tbl.getKeys(): - route = json.loads(key) - if route["dest"] == "fc00::1/128": - lo0_ip2me_found = True - if route["dest"] == "fd00::1/128": - lo1_ip2me_found = True - - assert lo0_ip2me_found and lo1_ip2me_found - - # Remove ip address - self.remove_ip_address("Loopback0", "fc00::1/128") - self.remove_ip_address("Loopback1", "fd00::1/128") - - # Remove interface - self.remove_l3_intf("Loopback0") - self.remove_l3_intf("Loopback1") - - # Check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:Loopback0") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:Loopback1") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - # Check ASIC database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - for key in tbl.getKeys(): - route = json.loads(key) - if route["dest"] == "fc00::1/128": - assert False - if route["dest"] == "fd00::1/128": - assert False - - def test_LoopbackInterfaceIpv4AddressWithVrf(self, dvs, testlog): - self.setup_db(dvs) - - for i in [0, 1]: - # record ASIC router interface database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") - old_intf_entries = set(tbl.getKeys()) - - # record ASIC router entry database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - old_route_entries = set(tbl.getKeys()) - - intf_name = "Loopback" + str(i) - vrf_name = "Vrf_" + str(i) - - # create vrf - vrf_oid = self.create_vrf(vrf_name) - - # create interface with vrf - self.create_l3_intf(intf_name, vrf_name) - - # check linux kernel - (exitcode, result) = dvs.runcmd(['sh', '-c', "ip link show %s | grep Vrf" % intf_name]) - assert "%s" % vrf_name in result - - # check interface's vrf - tbl = swsscommon.Table(self.pdb, "INTF_TABLE") - (status, fvs) = tbl.get(intf_name) - assert status == True - for fv in fvs: - if fv[0] == "vrf_name": - assert fv[1] == vrf_name - vrf_found = True - break - assert vrf_found == True - - # assign IP to interface - self.add_ip_address(intf_name, "10.0.0.4/32") - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:" + intf_name) - intf_entries = tbl.getKeys() - assert len(intf_entries) == 1 - assert intf_entries[0] == "10.0.0.4/32" - - (status, fvs) = tbl.get(tbl.getKeys()[0]) - assert status == True - assert len(fvs) == 2 - for fv in fvs: - if fv[0] == "scope": - assert fv[1] == "global" - elif fv[0] == "family": - assert fv[1] == "IPv4" - else: - assert False - - # check ASIC router interface database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") - current_intf_entries = set(tbl.getKeys()) - intf_entries = list(current_intf_entries - old_intf_entries) - for key in intf_entries: - (status, fvs) = tbl.get(key) - assert status == True - # a port based router interface has five field/value tuples - if len(fvs) == 5: - for fv in fvs: - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_TYPE": - assert fv[1] == "SAI_ROUTER_INTERFACE_TYPE_PORT" - # the default MTU without any configuration is 9100 - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_MTU": - assert fv[1] == "9100" - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": - assert fv[1] == vrf_oid - - # check ASIC route database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - current_route_entries = set(tbl.getKeys()) - route_entries = list(current_route_entries - old_route_entries) - - for key in route_entries: - route = json.loads(key) - if route["dest"] == "10.0.0.4/32": - ip2me_found = True - assert route["vr"] == vrf_oid - - assert ip2me_found - - - for i in [0, 1]: - # check ASIC router interface database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") - old_intf_entries = set(tbl.getKeys()) - - intf_name = "Loopback" + str(i) - vrf_name = "Vrf_" + str(i) - - # remove IP from interface - self.remove_ip_address(intf_name, "10.0.0.4/32") - - # remove interface - self.remove_l3_intf(intf_name) - - # remove vrf - self.remove_vrf(vrf_name) - - # check linux kernel - (exitcode, result) = dvs.runcmd(['sh', '-c', "ip link show %s | grep Vrf" % intf_name]) - assert "%s" % vrf_name not in result - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:" + intf_name) - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - tbl = swsscommon.Table(self.pdb, "INTF_TABLE") - intf_entries = tbl.getKeys() - for entry in intf_entries: - assert entry[0] != "Loopback0" and entry[0] != "Loopback1" - - tbl = swsscommon.Table(self.pdb, "VRF") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - # check ASIC database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - for key in tbl.getKeys(): - route = json.loads(key) - if route["dest"] == "10.0.0.4/32": - assert False - - - def create_ipv6_link_local(self, interface): - if interface.startswith("PortChannel"): - tbl_name = "PORTCHANNEL_INTERFACE" - elif interface.startswith("Vlan"): - tbl_name = "VLAN_INTERFACE" - else: - tbl_name = "INTERFACE" - - fvs = swsscommon.FieldValuePairs([("ipv6_use_link_local_only", "enable")]) - tbl = swsscommon.Table(self.cdb, tbl_name) - tbl.set(interface, fvs) - time.sleep(1) - - def remove_ipv6_link_local(self, interface): - if interface.startswith("PortChannel"): - tbl_name = "PORTCHANNEL_INTERFACE" - elif interface.startswith("Vlan"): - tbl_name = "VLAN_INTERFACE" - else: - tbl_name = "INTERFACE" - tbl = swsscommon.Table(self.cdb, tbl_name) - tbl._del(interface) - time.sleep(1) - - def test_InterfaceIpv6LinkLocalOnly(self, dvs, testlog): - # Check enable/disable ipv6-link-local mode for physical interface - self.setup_db(dvs) - - # create ipv6 link local interface - self.create_ipv6_link_local("Ethernet8") - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE") - (status, fvs) = tbl.get("Ethernet8") - assert status == True - for fv in fvs: - if fv[0] == "ipv6_use_link_local_only": - ipv6_link_local_found = True - assert fv[1] == "enable" - - assert ipv6_link_local_found - - # bring up interface - self.set_admin_status(dvs, "Ethernet8", "up") - - # check ASIC router interface database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") - intf_entries = tbl.getKeys() - # one loopback router interface one port based router interface - assert len(intf_entries) == 2 - - for key in intf_entries: - (status, fvs) = tbl.get(key) - assert status == True - # a port based router interface has five field/value tuples - if len(fvs) >= 5: - for fv in fvs: - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_TYPE": - assert fv[1] == "SAI_ROUTER_INTERFACE_TYPE_PORT" - # the default MTU without any configuration is 9100 - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_MTU": - assert fv[1] == "9100" - - # remove ipv6 link local interface - self.remove_ipv6_link_local("Ethernet8") - - # bring down interface - self.set_admin_status(dvs, "Ethernet8", "down") - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:Ethernet8") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - tbl = swsscommon.Table(self.pdb, "INTF_TABLE") - intf_entries = tbl.getKeys() - for entry in intf_entries: - assert entry[0] != "Ethernet8" - - # check ASIC router interface database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") - intf_entries = tbl.getKeys() - # one loopback router interface - assert len(intf_entries) == 1 - - def test_LagInterfaceIpv6LinkLocalOnly(self, dvs, testlog): - # Check enable/disable ipv6-link-local mode for lag interface - self.setup_db(dvs) - - # create port channel - self.create_port_channel("PortChannel001") - - # bring up interface - self.set_admin_status(dvs, "PortChannel001", "up") - - # create ipv6 link local interface - self.create_ipv6_link_local("PortChannel001") - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE") - (status, fvs) = tbl.get("PortChannel001") - assert status == True - for fv in fvs: - if fv[0] == "ipv6_use_link_local_only": - ipv6_link_local_found = True - assert fv[1] == "enable" - - assert ipv6_link_local_found - - # check ASIC router interface database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") - intf_entries = tbl.getKeys() - # one loopback router interface one port based router interface - assert len(intf_entries) == 2 - - for key in intf_entries: - (status, fvs) = tbl.get(key) - assert status == True - # a port based router interface has five field/value tuples - if len(fvs) >= 5: - for fv in fvs: - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_TYPE": - assert fv[1] == "SAI_ROUTER_INTERFACE_TYPE_PORT" - # the default MTU without any configuration is 9100 - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_MTU": - assert fv[1] == "9100" - - # remove ipv6 link local interface - self.remove_ipv6_link_local("PortChannel001") - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:PortChannel001") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - tbl = swsscommon.Table(self.pdb, "INTF_TABLE") - intf_entries = tbl.getKeys() - for entry in intf_entries: - assert entry[0] != "PortChannel001" - - # check ASIC router interface database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") - intf_entries = tbl.getKeys() - # one loopback router interface - assert len(intf_entries) == 1 - - # remove port channel - self.remove_port_channel("PortChannel001") - - - def test_VLanInterfaceIpv6LinkLocalOnly(self, dvs, testlog): - # Check enable/disable ipv6-link-local mode for vlan interface - self.setup_db(dvs) - - # create vlan - self.create_vlan("10") - - # add vlan member - self.create_vlan_member("10", "Ethernet0") - - # bring up interface - self.set_admin_status(dvs, "Ethernet0", "up") - self.set_admin_status(dvs, "Vlan10", "up") - - # create ipv6 link local interface - self.create_ipv6_link_local("Vlan10") - - # check asic database and get vlan_oid - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - vlan_entries = [k for k in tbl.getKeys() if k != dvs.asicdb.default_vlan_id] - assert len(vlan_entries) == 1 - vlan_oid = vlan_entries[0] - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE") - (status, fvs) = tbl.get("Vlan10") - assert status == True - for fv in fvs: - if fv[0] == "ipv6_use_link_local_only": - ipv6_link_local_found = True - assert fv[1] == "enable" - - assert ipv6_link_local_found - - # check ASIC router interface database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") - intf_entries = tbl.getKeys() - # one loopback router interface one vlan router interface - assert len(intf_entries) == 2 - - for key in intf_entries: - (status, fvs) = tbl.get(key) - assert status == True - if len(fvs) >= 5: - for fv in fvs: - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_TYPE": - assert fv[1] == "SAI_ROUTER_INTERFACE_TYPE_VLAN" - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_VLAN_ID": - assert fv[1] == vlan_oid - - - # remove ipv6 link local interface - self.remove_ipv6_link_local("Vlan10") - - # remove vlan member - self.remove_vlan_member("10", "Ethernet0") - - # remove vlan - self.remove_vlan("10") - - # bring down interface - self.set_admin_status(dvs, "Ethernet0", "down") - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:Vlan10") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - tbl = swsscommon.Table(self.pdb, "INTF_TABLE") - intf_entries = tbl.getKeys() - for entry in intf_entries: - assert entry[0] != "Vlan10" - - # check ASIC router interface database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") - intf_entries = tbl.getKeys() - # one loopback router interface - assert len(intf_entries) == 1 - - def set_loopback_action(self, interface, action): - if interface.startswith("PortChannel"): - tbl_name = "PORTCHANNEL_INTERFACE" - elif interface.startswith("Vlan"): - tbl_name = "VLAN_INTERFACE" - else: - sub_intf_sep_idx = interface.find(VLAN_SUB_INTERFACE_SEPARATOR) - if sub_intf_sep_idx != -1: - tbl_name = "VLAN_SUB_INTERFACE" - else: - tbl_name = "INTERFACE" - - fvs = swsscommon.FieldValuePairs([("loopback_action", action)]) - tbl = swsscommon.Table(self.cdb, tbl_name) - tbl.set(interface, fvs) - time.sleep(1) - - def loopback_action_test(self, iface, action): - # create interface - self.create_l3_intf(iface, "") - - # set interface loopback action in config db - self.set_loopback_action(iface, action) - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE") - (status, fvs) = tbl.get(iface) - assert status == True - - action_found = False - for fv in fvs: - if fv[0] == "loopback_action": - action_found = True - assert fv[1] == action - assert action_found == True - - # check asic db - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") - intf_entries = tbl.getKeys() - - action_map = {"drop": "SAI_PACKET_ACTION_DROP", "forward": "SAI_PACKET_ACTION_FORWARD"} - action_found = False - for key in intf_entries: - (status, fvs) = tbl.get(key) - assert status == True - - for fv in fvs: - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_LOOPBACK_PACKET_ACTION": - action_found = True - assert fv[1] == action_map[action] - assert action_found == True - - # remove interface - self.remove_l3_intf(iface) - - def test_interfaceLoopbackActionDrop(self, dvs, testlog): - self.setup_db(dvs) - self.loopback_action_test("Ethernet8", "drop") - - def test_interfaceLoopbackActionForward(self, dvs, testlog): - self.setup_db(dvs) - self.loopback_action_test("Ethernet8", "forward") - - def test_subInterfaceLoopbackActionDrop(self, dvs, testlog): - self.setup_db(dvs) - self.loopback_action_test("Ethernet8.1", "drop") - - def test_subInterfaceLoopbackActionForward(self, dvs, testlog): - self.setup_db(dvs) - self.loopback_action_test("Ethernet8.1", "forward") - - def test_vlanInterfaceLoopbackActionDrop(self, dvs, testlog): - self.setup_db(dvs) - self.create_vlan("10") - self.loopback_action_test("Vlan10", "drop") - self.remove_vlan("10") - - def test_vlanInterfaceLoopbackActionForward(self, dvs, testlog): - self.setup_db(dvs) - self.create_vlan("20") - self.loopback_action_test("Vlan20", "forward") - self.remove_vlan("20") - - def test_portChannelInterfaceLoopbackActionDrop(self, dvs, testlog): - self.setup_db(dvs) - self.create_port_channel("PortChannel009") - self.loopback_action_test("PortChannel009", "drop") - self.remove_port_channel("PortChannel009") - - def test_portChannelInterfaceLoopbackActionForward(self, dvs, testlog): - self.setup_db(dvs) - self.create_port_channel("PortChannel010") - self.loopback_action_test("PortChannel010", "forward") - self.remove_port_channel("PortChannel010") - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_intf_mac.py b/tests/test_intf_mac.py deleted file mode 100644 index a2665c1cab..0000000000 --- a/tests/test_intf_mac.py +++ /dev/null @@ -1,260 +0,0 @@ -from swsscommon import swsscommon - -import time -import json - -class TestRouterInterfaceMac(object): - def add_ip_address(self, dvs, interface, ip): - tbl = swsscommon.Table(dvs.cdb, "INTERFACE") - fvs = swsscommon.FieldValuePairs([("mac_addr", "00:00:00:00:00:00")]) - tbl.set(interface, fvs) - fvs = swsscommon.FieldValuePairs([("NULL", "NULL")]) - tbl.set(interface + "|" + ip, fvs) - time.sleep(1) - - def remove_ip_address(self, dvs, interface, ip): - tbl = swsscommon.Table(dvs.cdb, "INTERFACE") - tbl._del(interface + "|" + ip); - tbl.hdel(interface, "mac_addr") - time.sleep(1) - - def set_mac(self, dvs, interface, mac): - tbl = swsscommon.Table(dvs.cdb, "INTERFACE") - fvs = swsscommon.FieldValuePairs([("mac_addr", mac)]) - tbl.set(interface, fvs) - time.sleep(1) - - def remove_mac(self, dvs, interface): - tbl = swsscommon.Table(dvs.cdb, "INTERFACE") - tbl.hdel(interface, "mac_addr") - time.sleep(1) - - def find_mac(self, dvs, interface, mac): - port_oid = dvs.asicdb.portnamemap[interface] - - tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") - intf_entries = tbl.getKeys() - for key in intf_entries: - (status, fvs) = tbl.get(key) - assert status == True - values = dict(fvs) - if "SAI_ROUTER_INTERFACE_TYPE_PORT" != values["SAI_ROUTER_INTERFACE_ATTR_TYPE"]: - continue - if port_oid == values["SAI_ROUTER_INTERFACE_ATTR_PORT_ID"] and mac == values["SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS"]: - return True - return False - - def test_InterfaceSetMac(self, dvs, testlog): - dvs.setup_db() - - # assign IP to interface - self.add_ip_address(dvs, "Ethernet8", "10.0.0.4/31") - - # set MAC to interface - self.set_mac(dvs, "Ethernet8", "6C:EC:5A:11:22:33") - - # check application database - tbl = swsscommon.Table(dvs.pdb, "INTF_TABLE") - (status, fvs) = tbl.get("Ethernet8") - assert status == True - values = dict(fvs) - assert values["mac_addr"] == "6C:EC:5A:11:22:33" - - time.sleep(3) - - # check ASIC router interface database - src_mac_addr_found = self.find_mac(dvs, "Ethernet8", "6C:EC:5A:11:22:33") - assert src_mac_addr_found == True - - # remove IP from interface - self.remove_ip_address(dvs, "Ethernet8", "10.0.0.4/31") - - # remove MAC from interface - self.remove_mac(dvs, "Ethernet8") - - def test_InterfaceChangeMac(self, dvs, testlog): - dvs.setup_db() - - # assign IP to interface - self.add_ip_address(dvs, "Ethernet12", "12.0.0.4/31") - - # set MAC to interface - self.set_mac(dvs, "Ethernet12", "6C:EC:5A:22:33:44") - - # change interface MAC - self.set_mac(dvs, "Ethernet12", "6C:EC:5A:33:44:55") - - # check application database - tbl = swsscommon.Table(dvs.pdb, "INTF_TABLE") - (status, fvs) = tbl.get("Ethernet12") - assert status == True - values = dict(fvs) - assert values["mac_addr"] == "6C:EC:5A:33:44:55" - - time.sleep(3) - - # check ASIC router interface database - src_mac_addr_found = self.find_mac(dvs, "Ethernet12", "6C:EC:5A:33:44:55") - assert src_mac_addr_found == True - - # remove IP from interface - self.remove_ip_address(dvs, "Ethernet12", "12.0.0.4/31") - - # remove MAC from interface - self.remove_mac(dvs, "Ethernet12") - -class TestLagRouterInterfaceMac(object): - def create_port_channel(self, dvs, alias): - tbl = swsscommon.Table(dvs.cdb, "PORTCHANNEL") - fvs = swsscommon.FieldValuePairs([("admin_status", "up"), - ("mtu", "9100")]) - tbl.set(alias, fvs) - time.sleep(1) - - def remove_port_channel(self, dvs, alias): - tbl = swsscommon.Table(dvs.cdb, "PORTCHANNEL") - tbl._del(alias) - time.sleep(1) - - def add_port_channel_members(self, dvs, lag, members): - tbl = swsscommon.Table(dvs.cdb, "PORTCHANNEL_MEMBER") - fvs = swsscommon.FieldValuePairs([("NULL", "NULL")]) - for member in members: - tbl.set(lag + "|" + member, fvs) - time.sleep(1) - - def remove_port_channel_members(self, dvs, lag, members): - tbl = swsscommon.Table(dvs.cdb, "PORTCHANNEL_MEMBER") - for member in members: - tbl._del(lag + "|" + member) - time.sleep(1) - - def add_ip_address(self, dvs, interface, ip): - tbl = swsscommon.Table(dvs.cdb, "PORTCHANNEL_INTERFACE") - fvs = swsscommon.FieldValuePairs([("mac_addr", "00:00:00:00:00:00")]) - tbl.set(interface, fvs) - fvs = swsscommon.FieldValuePairs([("NULL", "NULL")]) - tbl.set(interface + "|" + ip, fvs) - time.sleep(1) - - def remove_ip_address(self, dvs, interface, ip): - tbl = swsscommon.Table(dvs.cdb, "PORTCHANNEL_INTERFACE") - tbl._del(interface + "|" + ip); - tbl.hdel(interface, "mac_addr") - time.sleep(1) - - def set_mac(self, dvs, interface, mac): - tbl = swsscommon.Table(dvs.cdb, "PORTCHANNEL_INTERFACE") - fvs = swsscommon.FieldValuePairs([("mac_addr", mac)]) - tbl.set(interface, fvs) - time.sleep(1) - - def remove_mac(self, dvs, interface): - tbl = swsscommon.Table(dvs.cdb, "PORTCHANNEL_INTERFACE") - tbl.hdel(interface, "mac_addr") - time.sleep(1) - - def find_mac(self, dvs, lag_oid, mac): - tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") - intf_entries = tbl.getKeys() - - for key in intf_entries: - (status, fvs) = tbl.get(key) - assert status == True - values = dict(fvs) - if "SAI_ROUTER_INTERFACE_TYPE_PORT" != values["SAI_ROUTER_INTERFACE_ATTR_TYPE"]: - continue - if lag_oid == values["SAI_ROUTER_INTERFACE_ATTR_PORT_ID"] and mac == values["SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS"]: - return True - return False - - def test_InterfaceSetMac(self, dvs, testlog): - dvs.setup_db() - - # create port channel - self.create_port_channel(dvs, "PortChannel001") - - # assign IP to interface - self.add_ip_address(dvs, "PortChannel001", "30.0.0.4/31") - - # set MAC to interface - self.set_mac(dvs, "PortChannel001", "6C:EC:5A:11:22:33") - - # check application database - tbl = swsscommon.Table(dvs.pdb, "INTF_TABLE") - (status, fvs) = tbl.get("PortChannel001") - assert status == True - values = dict(fvs) - assert values["mac_addr"] == "6C:EC:5A:11:22:33" - - # get PortChannel oid; When sonic-swss pr885 is complete, you can get oid directly from COUNTERS_LAG_NAME_MAP, which would be better. - lag_tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_LAG") - lag_entries = lag_tbl.getKeys() - # At this point there should be only one lag in the system, which is PortChannel001. - assert len(lag_entries) == 1 - lag_oid = lag_entries[0] - - time.sleep(3) - - # check ASIC router interface database - src_mac_addr_found = self.find_mac(dvs, lag_oid, "6C:EC:5A:11:22:33") - assert src_mac_addr_found == True - - # remove IP from interface - self.remove_ip_address(dvs, "PortChannel001", "30.0.0.4/31") - - # remove MAC from interface - self.remove_mac(dvs, "PortChannel001") - - # remove port channel - self.remove_port_channel(dvs, "PortChannel001") - - def test_InterfaceChangeMac(self, dvs, testlog): - dvs.setup_db() - - # create port channel - self.create_port_channel(dvs, "PortChannel002") - - # assign IP to interface - self.add_ip_address(dvs, "PortChannel002", "32.0.0.4/31") - - # set MAC to interface - self.set_mac(dvs, "PortChannel002", "6C:EC:5A:22:33:44") - - # change interface MAC - self.set_mac(dvs, "PortChannel002", "6C:EC:5A:33:44:55") - - # check application database - tbl = swsscommon.Table(dvs.pdb, "INTF_TABLE") - (status, fvs) = tbl.get("PortChannel002") - assert status == True - values = dict(fvs) - assert values["mac_addr"] == "6C:EC:5A:33:44:55" - - # get PortChannel oid; When sonic-swss pr885 is complete, you can get oid directly from COUNTERS_LAG_NAME_MAP, which would be better. - lag_tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_LAG") - lag_entries = lag_tbl.getKeys() - # At this point there should be only one lag in the system, which is PortChannel002. - assert len(lag_entries) == 1 - lag_oid = lag_entries[0] - - time.sleep(3) - - # check ASIC router interface database - src_mac_addr_found = self.find_mac(dvs, lag_oid, "6C:EC:5A:33:44:55") - assert src_mac_addr_found == True - - # remove IP from interface - self.remove_ip_address(dvs, "PortChannel002", "32.0.0.4/31") - - # remove MAC from interface - self.remove_mac(dvs, "PortChannel002") - - # remove port channel - self.remove_port_channel(dvs, "PortChannel002") - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_ipv6_link_local.py b/tests/test_ipv6_link_local.py deleted file mode 100644 index 048b8f2e17..0000000000 --- a/tests/test_ipv6_link_local.py +++ /dev/null @@ -1,112 +0,0 @@ -import time -import json -import pytest - -from swsscommon import swsscommon - -class TestIPv6LinkLocal(object): - def setup_db(self, dvs): - self.pdb = dvs.get_app_db() - self.adb = dvs.get_asic_db() - self.cdb = dvs.get_config_db() - - def set_admin_status(self, interface, status): - self.cdb.update_entry("PORT", interface, {"admin_status": status}) - - def add_ip_address(self, interface, ip): - self.cdb.create_entry("INTERFACE", interface + "|" + ip, {"NULL": "NULL"}) - time.sleep(2) - - def remove_ip_address(self, interface, ip): - self.cdb.delete_entry("INTERFACE", interface + "|" + ip) - time.sleep(2) - - def create_ipv6_link_local_intf(self, interface): - self.cdb.create_entry("INTERFACE", interface, {"ipv6_use_link_local_only": "enable"}) - time.sleep(2) - - def remove_ipv6_link_local_intf(self, interface): - self.cdb.delete_entry("INTERFACE", interface) - time.sleep(2) - - def test_NeighborAddRemoveIpv6LinkLocal(self, dvs, testlog): - self.setup_db(dvs) - - # create ipv6 link local intf - self.create_ipv6_link_local_intf("Ethernet0") - self.create_ipv6_link_local_intf("Ethernet4") - - # bring up interface - self.set_admin_status("Ethernet0", "up") - self.set_admin_status("Ethernet4", "up") - - # set ip address - self.add_ip_address("Ethernet0", "2000::1/64") - self.add_ip_address("Ethernet4", "2001::1/64") - dvs.runcmd("sysctl -w net.ipv6.conf.all.forwarding=1") - dvs.runcmd("sysctl -w net.ipv6.conf.default.forwarding=1") - - # set ip address and default route - dvs.servers[0].runcmd("ip -6 address add 2000::2/64 dev eth0") - dvs.servers[0].runcmd("ip -6 route add default via 2000::1") - - dvs.servers[1].runcmd("ip -6 address add 2001::2/64 dev eth0") - dvs.servers[1].runcmd("ip -6 route add default via 2001::1") - time.sleep(2) - - # get neighbor entry - dvs.servers[0].runcmd("ping -6 -c 1 2001::2") - time.sleep(2) - - # Neigh entries should contain Ipv6-link-local neighbors, should be 4 - neigh_entries = self.pdb.get_keys("NEIGH_TABLE") - assert (len(neigh_entries) == 4) - - found_entry = False - for key in neigh_entries: - if (key.find("Ethernet4:2001::2") or key.find("Ethernet0:2000::2")): - found_entry = True - - assert found_entry - - # remove ip address - self.remove_ip_address("Ethernet0", "2000::1/64") - self.remove_ip_address("Ethernet4", "2001::1/64") - - # remove ipv6 link local intf - self.remove_ipv6_link_local_intf("Ethernet0") - self.remove_ipv6_link_local_intf("Ethernet4") - - # Neigh entries should not contain Ipv6-link-local neighbors, should be 2 - neigh_after_entries = self.pdb.get_keys("NEIGH_TABLE") - print(neigh_after_entries) - assert (len(neigh_after_entries) == 2) - - found_existing_entry = False - for key in neigh_entries: - if (key.find("Ethernet4:2001::2") or key.find("Ethernet0:2000::2")): - found_existing_entry = True - - assert found_existing_entry - - self.set_admin_status("Ethernet0", "down") - self.set_admin_status("Ethernet4", "down") - - # remove ip address and default route - dvs.servers[0].runcmd("ip -6 route del default dev eth0") - dvs.servers[0].runcmd("ip -6 address del 2000::2/64 dev eth0") - - dvs.servers[1].runcmd("ip -6 route del default dev eth0") - dvs.servers[1].runcmd("ip -6 address del 2001::2/64 dev eth0") - - dvs.runcmd("sysctl -w net.ipv6.conf.all.forwarding=0") - dvs.runcmd("sysctl -w net.ipv6.conf.default.forwarding=0") - - neigh_entries = self.pdb.get_keys("NEIGH_TABLE") - assert (len(neigh_entries) == 0) - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass - diff --git a/tests/test_macsec.py b/tests/test_macsec.py deleted file mode 100644 index 9dc5a4ed53..0000000000 --- a/tests/test_macsec.py +++ /dev/null @@ -1,904 +0,0 @@ -from swsscommon import swsscommon -from swsscommon.swsscommon import CounterTable, MacsecCounter -import conftest - -import time -import functools -import typing -import re -import time - - -def to_string(value): - if isinstance(value, bool): - return "true" if value else "false" - return str(value) - - -class Table(object): - def __init__(self, database: conftest.DVSDatabase, table_name: str): - self.db = database - self.table_name = table_name - - def convert_key(self, key: str): - return key - - def __setitem__(self, key: str, pairs: dict): - pairs_str = {} - for k, v in pairs.items(): - pairs_str[to_string(k)] = to_string(v) - key = self.convert_key(key) - if self.__getitem__(key) is None: - self.db.create_entry(self.table_name, key, pairs_str) - else: - self.db.update_entry(self.table_name, key, pairs_str) - - def __getitem__(self, key: str): - key = self.convert_key(key) - return self.db.get_entry(self.table_name, key) - - def __delitem__(self, key: str): - key = self.convert_key(key) - self.db.delete_entry(self.table_name, key) - - def wait(self, key: str): - key = self.convert_key(key) - # return True - return self.db.wait_for_entry(self.table_name, key) - - def wait_delete(self, key: str): - key = self.convert_key(key) - # return True - return self.db.wait_for_deleted_entry(self.table_name, key) - - -class ProduceStateTable(object): - def __init__(self, database: conftest.DVSDatabase, table_name: str): - self.table = swsscommon.ProducerStateTable( - database.db_connection, - table_name) - - def __setitem__(self, key: str, pairs: typing.Union[dict, list, tuple]): - pairs_str = [] - if isinstance(pairs, dict): - pairs = pairs.items() - for k, v in pairs: - pairs_str.append((to_string(k), to_string(v))) - self.table.set(key, pairs_str) - - def __delitem__(self, key: str): - self.table.delete(key) - - -class AppDBTable(ProduceStateTable): - SEPARATOR = ":" - - def __init__(self, dvs: conftest.DockerVirtualSwitch, table_name: str): - super(AppDBTable, self).__init__(dvs.get_app_db(), table_name) - - -class StateDBTable(Table): - SEPARATOR = "|" - - def __init__(self, dvs: conftest.DockerVirtualSwitch, table_name: str): - super(StateDBTable, self).__init__(dvs.get_state_db(), table_name) - - def convert_key(self, key: str): - return key.translate( - str.maketrans( - AppDBTable.SEPARATOR, - StateDBTable.SEPARATOR)) - - -class ConfigTable(Table): - - def __init__(self, dvs: conftest.DockerVirtualSwitch, table_name: str): - super(ConfigTable, self).__init__(dvs.get_config_db(), table_name) - - -def gen_sci(macsec_system_identifier: str, macsec_port_identifier: int) -> str: - macsec_system_identifier = macsec_system_identifier.translate( - str.maketrans("", "", ":.-")) - sci = "{}{}".format( - macsec_system_identifier, - str(macsec_port_identifier).zfill(4)).lower() - return sci - - -def gen_sc_key( - separator: str, - port_name: str, - macsec_system_identifier: str, - macsec_port_identifier: int) -> str: - sci = gen_sci(macsec_system_identifier, macsec_port_identifier) - key = "{}{}{}".format( - port_name, - separator, - sci) - return key - - -def gen_sa_key( - separator: str, - port_name: str, - macsec_system_identifier: str, - macsec_port_identifier: int, - an: int): - sc_key = gen_sc_key( - separator, - port_name, - macsec_system_identifier, - macsec_port_identifier) - key = "{}{}{}".format(sc_key, separator, an) - return key - - -def macsec_sc(separator: str = AppDBTable.SEPARATOR): - def inner(func: typing.Callable) -> typing.Callable: - @functools.wraps(func) - def wrap_func( - self, - port_name: str, - macsec_system_identifier: str, - macsec_port_identifier: int, - *args, - **kwargs) -> typing.Any: - key = gen_sc_key( - separator, - port_name, - macsec_system_identifier, - macsec_port_identifier) - return func(self, key, *args, **kwargs) - return wrap_func - return inner - - -def macsec_sa(separator: str = AppDBTable.SEPARATOR): - def inner(func: typing.Callable) -> typing.Callable: - @functools.wraps(func) - def wrap_func( - self, - port_name: str, - macsec_system_identifier: str, - macsec_port_identifier: int, - an: int, - *args, - **kwargs) -> typing.Any: - key = gen_sa_key( - separator, - port_name, - macsec_system_identifier, - macsec_port_identifier, - an) - return func(self, key, *args, **kwargs) - return wrap_func - return inner - - -class WPASupplicantMock(object): - def __init__(self, dvs: conftest.DockerVirtualSwitch): - self.dvs = dvs - self.app_port_table = AppDBTable( - self.dvs, swsscommon.APP_MACSEC_PORT_TABLE_NAME) - self.app_receive_sc_table = AppDBTable( - self.dvs, swsscommon.APP_MACSEC_INGRESS_SC_TABLE_NAME) - self.app_transmit_sc_table = AppDBTable( - self.dvs, swsscommon.APP_MACSEC_EGRESS_SC_TABLE_NAME) - self.app_receive_sa_table = AppDBTable( - self.dvs, swsscommon.APP_MACSEC_INGRESS_SA_TABLE_NAME) - self.app_transmit_sa_table = AppDBTable( - self.dvs, swsscommon.APP_MACSEC_EGRESS_SA_TABLE_NAME) - self.state_port_table = StateDBTable( - self.dvs, swsscommon.STATE_MACSEC_PORT_TABLE_NAME) - self.state_receive_sc_table = StateDBTable( - self.dvs, swsscommon.STATE_MACSEC_INGRESS_SC_TABLE_NAME) - self.state_transmit_sc_table = StateDBTable( - self.dvs, swsscommon.STATE_MACSEC_EGRESS_SC_TABLE_NAME) - self.state_receive_sa_table = StateDBTable( - self.dvs, swsscommon.STATE_MACSEC_INGRESS_SA_TABLE_NAME) - self.state_transmit_sa_table = StateDBTable( - self.dvs, swsscommon.STATE_MACSEC_EGRESS_SA_TABLE_NAME) - - def init_macsec_port(self, port_name: str): - self.app_port_table[port_name] = { - "enable": False, - "cipher_suite": "GCM-AES-128", - } - self.state_port_table.wait(port_name) - - def deinit_macsec_port(self, port_name: str): - del self.app_port_table[port_name] - self.state_port_table.wait_delete(port_name) - - def config_macsec_port( - self, - port_name: str, - config: typing.Dict[str, typing.Any]): - self.app_port_table[port_name] = config - - def set_macsec_control(self, port_name: str, enable: bool): - self.app_port_table[port_name] = {"enable": True} - - @macsec_sc() - def create_receive_sc(self, sci: str): - self.app_receive_sc_table[sci] = {"NULL": "NULL"} - self.state_receive_sc_table.wait(sci) - - @macsec_sc() - def delete_receive_sc(self, sci: str): - del self.app_receive_sc_table[sci] - self.state_receive_sc_table.wait_delete(sci) - - @macsec_sc() - def create_transmit_sc(self, sci: str): - self.app_transmit_sc_table[sci] = {"encoding_an": 0} - self.state_transmit_sc_table.wait(sci) - - @macsec_sc() - def delete_transmit_sc(self, sci: str): - del self.app_transmit_sc_table[sci] - self.state_transmit_sc_table.wait_delete(sci) - - def check_valid_sa_parameter( - self, - sak: str, - auth_key: str, - lowest_acceptable_pn: int, - ssci: int, - salt: str) -> bool: - # Check SAK is hex string - int(sak, 16) - assert( - len(sak) == 32 or len(sak) == 64, - "Wrong length {} sak {}".format( - len(sak), - sak)) - # Check auth_key is valid - int(auth_key, 16) - assert( - len(auth_key) == 32, - "Wrong length {} auth_key {}".format( - len(auth_key), - auth_key)) - # Check lowest acceptable packet number is valid - assert( - lowest_acceptable_pn > 0, - "Wrong packet number {}".format(lowest_acceptable_pn)) - return True - - @macsec_sa() - def create_receive_sa( - self, - sai: str, - sak: str, - auth_key: str, - lowest_acceptable_pn: int, - ssci: int, - salt: str): - assert( - self.check_valid_sa_parameter( - sak, - auth_key, - lowest_acceptable_pn, - ssci, - salt), - "Wrong parameter to MACsec receive SA") - self.app_receive_sa_table[sai] = { - "active": False, "sak": sak, "auth_key": auth_key, - "lowest_acceptable_pn": lowest_acceptable_pn, - "ssci": ssci, "salt": salt} - - @macsec_sa() - def delete_receive_sa(self, sai: str): - del self.app_receive_sa_table[sai] - self.state_receive_sa_table.wait_delete(sai) - - @macsec_sa() - def set_enable_receive_sa(self, sai: str, enable: bool): - self.app_receive_sa_table[sai] = {"active": enable} - if enable: - self.state_receive_sa_table.wait(sai) - - @macsec_sa() - def create_transmit_sa( - self, - sai: str, - sak: str, - auth_key: str, - init_pn: int, - ssci: int, - salt: str): - assert( - self.check_valid_sa_parameter( - sak, - auth_key, - init_pn, - ssci, - salt), - "Wrong parameter to MACsec receive SA") - self.app_transmit_sa_table[sai] = { - "sak": sak, "auth_key": auth_key, - "next_pn": init_pn, "ssci": ssci, "salt": salt} - - @macsec_sa() - def delete_transmit_sa(self, sai: str): - del self.app_transmit_sa_table[sai] - self.state_transmit_sa_table.wait_delete(sai) - - @macsec_sa() - def set_macsec_pn( - self, - sai: str, - pn: int): - self.app_transmit_sa_table[sai] = {"next_pn": pn} - - @macsec_sc() - def set_enable_transmit_sa(self, sci: str, an: int, enable: bool): - if enable: - self.app_transmit_sc_table[sci] = {"encoding_an": an} - assert( - self.state_transmit_sa_table.wait( - "{}{}{}".format( - sci, - StateDBTable.SEPARATOR, - an))) - - -class MACsecInspector(object): - def __init__(self, dvs: conftest.DockerVirtualSwitch): - self.dvs = dvs - - def __load_macsec_info(self, port_name: str) -> (bool, str): - return self.dvs.runcmd("ip macsec show {}".format(port_name)) - - def get_macsec_port(self, port_name: str) -> str: - exitcode, info = self.__load_macsec_info(port_name) - if exitcode != 0 or not info: - return "" - print(info) - return info - - def get_macsec_sc( - self, - port_name: str, - macsec_system_identifier: str, - macsec_port_identifier: int) -> str: - info = self.get_macsec_port(port_name) - if not info: - return "" - macsec_system_identifier = macsec_system_identifier.translate( - str.maketrans("", "", ":.-")) - sci = "{}{}".format( - macsec_system_identifier, - str(macsec_port_identifier).zfill(4)) - sc_pattern = r"(TXSC|RXSC):\s*{}[ \w,]+\n?(?:\s*\d:[,\w ]+\n?)*".format( - sci) - info = re.search(sc_pattern, info, re.IGNORECASE) - if not info: - return "" - print(info.group(0)) - return info.group(0) - - def get_macsec_sa( - self, - port_name: str, - macsec_system_identifier: str, - macsec_port_identifier: str, - an: int) -> str: - info = self.get_macsec_sc( - port_name, - macsec_system_identifier, - macsec_port_identifier) - if not info: - return "" - sa_pattern = r"\s*{}:\s*PN\s*\d+[,\w ]+\n?".format(an) - info = re.search(sa_pattern, info, re.IGNORECASE) - if not info: - return "" - print(info.group(0)) - return info.group(0) - - @macsec_sa() - def get_macsec_xpn_counter( - self, - sai: str) -> int: - counter_table = CounterTable(self.dvs.get_counters_db().db_connection) - for i in range(3): - r, value = counter_table.hget( - MacsecCounter(), - sai, - "SAI_MACSEC_SA_ATTR_CURRENT_XPN") - if r: return int(value) - time.sleep(1) # wait a moment for polling counter - - return None - - -class TestMACsec(object): - def init_macsec( - self, - wpa: WPASupplicantMock, - port_name: str, - local_mac_address: str, - macsec_port_identifier: int): - wpa.init_macsec_port(port_name) - wpa.config_macsec_port(port_name, {"enable_protect": True}) - wpa.config_macsec_port(port_name, {"enable_encrypt": True}) - wpa.config_macsec_port( - port_name, - { - "enable_replay_protect": True, - "replay_window": 0 - }) - wpa.set_macsec_control(port_name, False) - wpa.create_transmit_sc( - port_name, - local_mac_address, - macsec_port_identifier) - - def establish_macsec( - self, - wpa: WPASupplicantMock, - port_name: str, - local_mac_address: str, - peer_mac_address: str, - macsec_port_identifier: int, - an: int, - sak: str, - packet_number: int, - auth_key: str, - ssci: int, - salt: str): - wpa.create_receive_sc( - port_name, - peer_mac_address, - macsec_port_identifier) - wpa.create_receive_sa( - port_name, - peer_mac_address, - macsec_port_identifier, - an, - sak, - auth_key, - packet_number, - ssci, - salt) - wpa.create_transmit_sa( - port_name, - local_mac_address, - macsec_port_identifier, - an, - sak, - auth_key, - packet_number, - ssci, - salt) - wpa.set_enable_receive_sa( - port_name, - peer_mac_address, - macsec_port_identifier, - an, - True) - wpa.set_macsec_control(port_name, True) - wpa.set_enable_transmit_sa( - port_name, - local_mac_address, - macsec_port_identifier, - an, - True) - - def rekey_macsec( - self, - wpa: WPASupplicantMock, - port_name: str, - local_mac_address: str, - peer_mac_address: str, - macsec_port_identifier: int, - an: int, - last_an: int, - sak: str, - packet_number: int, - auth_key: str, - ssci: int, - salt: str): - wpa.set_macsec_pn( - port_name, - local_mac_address, - macsec_port_identifier, - an, - 0x00000000C0000000) - wpa.create_receive_sa( - port_name, - peer_mac_address, - macsec_port_identifier, - an, - sak, - auth_key, - packet_number, - ssci, - salt) - wpa.create_transmit_sa( - port_name, - local_mac_address, - macsec_port_identifier, - an, - sak, - auth_key, - packet_number, - ssci, - salt) - wpa.set_enable_receive_sa( - port_name, - peer_mac_address, - macsec_port_identifier, - an, - True) - wpa.set_macsec_control(port_name, True) - wpa.set_enable_transmit_sa( - port_name, - local_mac_address, - macsec_port_identifier, - an, - True) - wpa.set_enable_transmit_sa( - port_name, - local_mac_address, - macsec_port_identifier, - last_an, - False) - wpa.delete_transmit_sa( - port_name, - local_mac_address, - macsec_port_identifier, - last_an) - wpa.set_enable_receive_sa( - port_name, - peer_mac_address, - macsec_port_identifier, - last_an, - False) - wpa.delete_receive_sa( - port_name, - peer_mac_address, - macsec_port_identifier, - last_an) - - def deinit_macsec( - self, - wpa: WPASupplicantMock, - inspector: MACsecInspector, - port_name: str, - macsec_port: str, - local_mac_address: str, - peer_mac_address: str, - macsec_port_identifier: int, - last_an: int): - wpa.set_enable_receive_sa( - port_name, - peer_mac_address, - macsec_port_identifier, - last_an, - False) - wpa.delete_receive_sa( - port_name, - peer_mac_address, - macsec_port_identifier, - last_an) - assert( - not inspector.get_macsec_sa( - macsec_port, - peer_mac_address, - macsec_port_identifier, - last_an)) - wpa.delete_receive_sc( - port_name, - peer_mac_address, - macsec_port_identifier) - assert( - not inspector.get_macsec_sc( - macsec_port, - peer_mac_address, - macsec_port_identifier)) - wpa.set_enable_transmit_sa( - port_name, - local_mac_address, - macsec_port_identifier, - last_an, - False) - wpa.delete_transmit_sa( - port_name, - local_mac_address, - macsec_port_identifier, - last_an) - assert( - not inspector.get_macsec_sa( - macsec_port, - local_mac_address, - macsec_port_identifier, - last_an)) - wpa.delete_transmit_sc( - port_name, - local_mac_address, - macsec_port_identifier) - assert( - not inspector.get_macsec_sc( - macsec_port, - local_mac_address, - macsec_port_identifier)) - wpa.deinit_macsec_port(port_name) - - def test_macsec_term_orch(self, dvs: conftest.DockerVirtualSwitch, testlog): - port_name = "Ethernet0" - local_mac_address = "00-15-5D-78-FF-C1" - peer_mac_address = "00-15-5D-78-FF-C2" - macsec_port_identifier = 1 - macsec_port = "macsec_eth1" - sak = "0" * 32 - auth_key = "0" * 32 - packet_number = 1 - ssci = 1 - salt = "0" * 24 - - wpa = WPASupplicantMock(dvs) - inspector = MACsecInspector(dvs) - - self.init_macsec( - wpa, - port_name, - local_mac_address, - macsec_port_identifier) - self.establish_macsec( - wpa, - port_name, - local_mac_address, - peer_mac_address, - macsec_port_identifier, - 0, - sak, - packet_number, - auth_key, - ssci, - salt) - assert(inspector.get_macsec_port(macsec_port)) - assert( - inspector.get_macsec_sc( - macsec_port, - local_mac_address, - macsec_port_identifier)) - assert( - inspector.get_macsec_sc( - macsec_port, - peer_mac_address, - macsec_port_identifier)) - assert( - inspector.get_macsec_sa( - macsec_port, - local_mac_address, - macsec_port_identifier, - 0)) - assert( - inspector.get_macsec_sa( - macsec_port, - peer_mac_address, - macsec_port_identifier, - 0)) - assert( - inspector.get_macsec_xpn_counter( - port_name, - local_mac_address, - macsec_port_identifier, - 0) == packet_number) - assert( - inspector.get_macsec_xpn_counter( - port_name, - peer_mac_address, - macsec_port_identifier, - 0) == packet_number) - self.rekey_macsec( - wpa, - port_name, - local_mac_address, - peer_mac_address, - macsec_port_identifier, - 1, - 0, - sak, - packet_number, - auth_key, - ssci, - salt) - assert( - inspector.get_macsec_sa( - macsec_port, - local_mac_address, - macsec_port_identifier, - 1)) - assert( - inspector.get_macsec_sa( - macsec_port, - peer_mac_address, - macsec_port_identifier, - 1)) - assert( - inspector.get_macsec_xpn_counter( - port_name, - local_mac_address, - macsec_port_identifier, - 1) == packet_number) - assert( - inspector.get_macsec_xpn_counter( - port_name, - peer_mac_address, - macsec_port_identifier, - 1) == packet_number) - assert( - not inspector.get_macsec_sa( - macsec_port, - local_mac_address, - macsec_port_identifier, - 0)) - assert( - not inspector.get_macsec_sa( - macsec_port, - peer_mac_address, - macsec_port_identifier, - 0)) - assert( - not inspector.get_macsec_xpn_counter( - port_name, - local_mac_address, - macsec_port_identifier, - 0) == packet_number) - assert( - not inspector.get_macsec_xpn_counter( - port_name, - peer_mac_address, - macsec_port_identifier, - 0) == packet_number) - # Exit MACsec port - self.deinit_macsec( - wpa, - inspector, - port_name, - macsec_port, - local_mac_address, - peer_mac_address, - macsec_port_identifier, - 1) - assert(not inspector.get_macsec_port(macsec_port)) - - def test_macsec_attribute_change(self, dvs: conftest.DockerVirtualSwitch, testlog): - port_name = "Ethernet0" - local_mac_address = "00-15-5D-78-FF-C1" - peer_mac_address = "00-15-5D-78-FF-C2" - macsec_port_identifier = 1 - macsec_port = "macsec_eth1" - sak = "0" * 32 - auth_key = "0" * 32 - packet_number = 1 - ssci = 1 - salt = "0" * 24 - - wpa = WPASupplicantMock(dvs) - inspector = MACsecInspector(dvs) - - self.init_macsec( - wpa, - port_name, - local_mac_address, - macsec_port_identifier) - wpa.set_macsec_control(port_name, True) - wpa.config_macsec_port(port_name, {"enable_encrypt": False}) - wpa.config_macsec_port(port_name, {"cipher_suite": "GCM-AES-256"}) - self.establish_macsec( - wpa, - port_name, - local_mac_address, - peer_mac_address, - macsec_port_identifier, - 0, - sak, - packet_number, - auth_key, - ssci, - salt) - macsec_info = inspector.get_macsec_port(macsec_port) - assert("encrypt off" in macsec_info) - assert("GCM-AES-256" in macsec_info) - self.deinit_macsec( - wpa, - inspector, - port_name, - macsec_port, - local_mac_address, - peer_mac_address, - macsec_port_identifier, - 0) - - def test_macsec_with_portchannel(self, dvs: conftest.DockerVirtualSwitch, testlog): - - # Set MACsec enabled on Ethernet0 - ConfigTable(dvs, "PORT")["Ethernet0"] = {"macsec" : "test"} - StateDBTable(dvs, "FEATURE")["macsec"] = {"state": "enabled"} - - # Setup Port-channel - ConfigTable(dvs, "PORTCHANNEL")["PortChannel001"] = {"admin": "up", "mtu": "9100", "oper_status": "up"} - time.sleep(1) - - # create port channel member - ConfigTable(dvs, "PORTCHANNEL_MEMBER")["PortChannel001|Ethernet0"] = {"NULL": "NULL"} - ConfigTable(dvs, "PORTCHANNEL_INTERFACE")["PortChannel001"] = {"NULL": "NULL"} - ConfigTable(dvs, "PORTCHANNEL_INTERFACE")["PortChannel001|40.0.0.0/31"] = {"NULL": "NULL"} - time.sleep(3) - - # Check Portchannel member in ASIC db that shouldn't been created before MACsec enabled - lagmtbl = swsscommon.Table(swsscommon.DBConnector(1, dvs.redis_sock, 0), "ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER") - lagms = lagmtbl.getKeys() - assert len(lagms) == 0 - - # Create MACsec session - port_name = "Ethernet0" - local_mac_address = "00-15-5D-78-FF-C1" - peer_mac_address = "00-15-5D-78-FF-C2" - macsec_port_identifier = 1 - macsec_port = "macsec_eth1" - sak = "0" * 32 - auth_key = "0" * 32 - packet_number = 1 - ssci = 1 - salt = "0" * 24 - - wpa = WPASupplicantMock(dvs) - inspector = MACsecInspector(dvs) - - self.init_macsec( - wpa, - port_name, - local_mac_address, - macsec_port_identifier) - self.establish_macsec( - wpa, - port_name, - local_mac_address, - peer_mac_address, - macsec_port_identifier, - 0, - sak, - packet_number, - auth_key, - ssci, - salt) - time.sleep(3) - - # Check Portchannel member in ASIC db that should been created after MACsec enabled - lagmtbl = swsscommon.Table(swsscommon.DBConnector(1, dvs.redis_sock, 0), "ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER") - lagms = lagmtbl.getKeys() - assert len(lagms) == 1 - - self.deinit_macsec( - wpa, - inspector, - port_name, - macsec_port, - local_mac_address, - peer_mac_address, - macsec_port_identifier, - 0) - - # remove port channel member - del ConfigTable(dvs, "PORTCHANNEL_INTERFACE")["PortChannel001"] - del ConfigTable(dvs, "PORTCHANNEL_INTERFACE")["PortChannel001|40.0.0.0/31"] - del ConfigTable(dvs, "PORTCHANNEL_MEMBER")["PortChannel001|Ethernet0"] - - # remove port channel - del ConfigTable(dvs, "PORTCHANNEL")["PortChannel001"] - - # Clear MACsec enabled on Ethernet0 - ConfigTable(dvs, "PORT")["Ethernet0"] = {"macsec" : ""} - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down -# before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_mclag_cfg.py b/tests/test_mclag_cfg.py deleted file mode 100644 index f93632bd37..0000000000 --- a/tests/test_mclag_cfg.py +++ /dev/null @@ -1,210 +0,0 @@ -# Common file to test all MCLAG related changes -from swsscommon import swsscommon -import time -import re -import json -import pytest -import platform -from distutils.version import StrictVersion - - -def delete_table_keys(db, table): - tbl = swsscommon.Table(db, table) - keys = tbl.getKeys() - for key in keys: - tbl.delete(key) - -#check table entry exits with this key -def check_table_exists(db, table, key): - error_info = [ ] - tbl = swsscommon.Table(db, table) - keys = tbl.getKeys() - if key not in keys: - error_info.append("The table with desired key %s not found" % key) - return False, error_info - return True, error_info - -#check table entry doesn't exits with this key -def check_table_doesnt_exists(db, table, key): - error_info = [ ] - tbl = swsscommon.Table(db, table) - keys = tbl.getKeys() - if key in keys: - error_info.append("unexcpected: The table with desired key %s is found" % key) - return False, error_info - return True, error_info - - -def create_mclag_domain(dvs, domain_id, source_ip, peer_ip, peer_link): - tbl = swsscommon.Table(dvs.cdb, "MCLAG_DOMAIN") - fvs = swsscommon.FieldValuePairs([("source_ip", source_ip), - ("peer_ip", peer_ip), - ("peer_link", peer_link)]) - tbl.set(domain_id, fvs) - time.sleep(1) - -def remove_mclag_domain(dvs, domain_id): - tbl = swsscommon.Table(dvs.cdb, "MCLAG_DOMAIN") - tbl._del(domain_id) - time.sleep(1) - -def add_mclag_domain_field(dvs, domain_id, field, value): - tbl = swsscommon.Table(dvs.cdb, "MCLAG_DOMAIN") - fvs = swsscommon.FieldValuePairs([(field, value)]) - tbl.set(domain_id, fvs) - time.sleep(1) - -def create_mclag_interface(dvs, domain_id, mclag_interface): - tbl = swsscommon.Table(dvs.cdb, "MCLAG_INTERFACE") - fvs = swsscommon.FieldValuePairs([("if_type", "PortChannel")]) - key_string = domain_id + "|" + mclag_interface - tbl.set(key_string, fvs) - time.sleep(1) - -def remove_mclag_interface(dvs, domain_id, mclag_interface): - tbl = swsscommon.Table(dvs.cdb, "MCLAG_INTERFACE") - key_string = domain_id + "|" + mclag_interface - tbl._del(key_string) - time.sleep(1) - -# Test MCLAG Configs -class TestMclagConfig(object): - CFG_MCLAG_DOMAIN_TABLE = "MCLAG_DOMAIN" - CFG_MCLAG_INTERFACE_TABLE = "MCLAG_INTERFACE" - - PORTCHANNEL1 = "PortChannel11" - PORTCHANNEL2 = "PortChannel50" - PORTCHANNEL3 = "PortChannel51" - - MCLAG_DOMAIN_ID = "4095" - MCLAG_SRC_IP = "10.5.1.1" - MCLAG_PEER_IP = "10.5.1.2" - MCLAG_PEER_LINK = PORTCHANNEL1 - - MCLAG_DOMAIN_2 = "111" - - MCLAG_SESS_TMOUT_VALID_LIST = ["3","3600"] - MCLAG_KA_VALID_LIST = ["1","60"] - - MCLAG_KA_INVALID_LIST = ["0","61"] - MCLAG_SESS_TMOUT_INVALID_LIST = ["0","3601"] - - MCLAG_INTERFACE1 = PORTCHANNEL2 - MCLAG_INTERFACE2 = PORTCHANNEL3 - - - # Testcase 1 Verify Configuration of MCLAG Domain with src, peer ip and peer link config gets updated in CONFIG_DB - @pytest.mark.dev_sanity - def test_mclag_cfg_domain_add(self, dvs, testlog): - dvs.setup_db() - - #cleanup existing entries - delete_table_keys(dvs.cdb, self.CFG_MCLAG_DOMAIN_TABLE) - delete_table_keys(dvs.cdb, self.CFG_MCLAG_INTERFACE_TABLE) - - create_mclag_domain(dvs, self.MCLAG_DOMAIN_ID, self.MCLAG_SRC_IP, self.MCLAG_PEER_IP, self.MCLAG_PEER_LINK) - time.sleep(2) - - #check whether domain cfg table contents are same as configured values - ok,error_info = dvs.all_table_entry_has(dvs.cdb, self.CFG_MCLAG_DOMAIN_TABLE, self.MCLAG_DOMAIN_ID, - [ - ("source_ip",self.MCLAG_SRC_IP), - ("peer_ip",self.MCLAG_PEER_IP), - ("peer_link",self.MCLAG_PEER_LINK) - ] - ) - assert ok,error_info - - - # Testcase 3 Verify Configuration of MCLAG Interface to existing domain - @pytest.mark.dev_sanity - def test_mclag_cfg_intf_add(self, dvs, testlog): - dvs.setup_db() - - create_mclag_interface(dvs, self.MCLAG_DOMAIN_ID, self.MCLAG_INTERFACE1) - time.sleep(2) - - #check whether mclag interface config is reflected - key_string = self.MCLAG_DOMAIN_ID + "|" + self.MCLAG_INTERFACE1 - ok,error_info = check_table_exists(dvs.cdb, self.CFG_MCLAG_INTERFACE_TABLE, key_string) - assert ok,error_info - - # Testcase 4 Verify remove and add mclag interface - @pytest.mark.dev_sanity - def test_mclag_cfg_intf_remove_and_add(self, dvs, testlog): - dvs.setup_db() - - remove_mclag_interface(dvs, self.MCLAG_DOMAIN_ID, self.MCLAG_INTERFACE1) - time.sleep(2) - - #check whether mclag interface is removed - key_string = self.MCLAG_DOMAIN_ID + "|" + self.MCLAG_INTERFACE1 - ok,error_info = check_table_doesnt_exists(dvs.cdb, self.CFG_MCLAG_INTERFACE_TABLE, key_string) - assert ok,error_info - - #add different mclag interface - create_mclag_interface(dvs, self.MCLAG_DOMAIN_ID, self.MCLAG_INTERFACE2) - time.sleep(2) - - #check whether new mclag interface is added - key_string = self.MCLAG_DOMAIN_ID + "|" + self.MCLAG_INTERFACE2 - ok,error_info = check_table_exists(dvs.cdb, self.CFG_MCLAG_INTERFACE_TABLE, key_string) - assert ok,error_info - - # Testcase 5 Verify Configuration of valid values for session timeout - @pytest.mark.dev_sanity - def test_mclag_cfg_session_timeout_valid_values(self, dvs, testlog): - dvs.setup_db() - - for value in self.MCLAG_SESS_TMOUT_VALID_LIST: - add_mclag_domain_field(dvs, self.MCLAG_DOMAIN_ID, "session_timeout", value) - - time.sleep(2) - - #check whether domain cfg table contents are same as configured values - ok,error_info = dvs.all_table_entry_has(dvs.cdb, self.CFG_MCLAG_DOMAIN_TABLE, self.MCLAG_DOMAIN_ID, - [ - ("source_ip",self.MCLAG_SRC_IP), - ("peer_ip",self.MCLAG_PEER_IP), - ("peer_link",self.MCLAG_PEER_LINK), - ("session_timeout",value) - ] - ) - assert ok,error_info - - # Testcase 6 Verify Configuration of valid values for KA timer - @pytest.mark.dev_sanity - def test_mclag_cfg_ka_valid_values(self, dvs, testlog): - dvs.setup_db() - - for value in self.MCLAG_KA_VALID_LIST: - add_mclag_domain_field(dvs, self.MCLAG_DOMAIN_ID, "keepalive_interval", value) - time.sleep(2) - #check whether domain cfg table contents are same as configured values - ok,error_info = dvs.all_table_entry_has(dvs.cdb, self.CFG_MCLAG_DOMAIN_TABLE, self.MCLAG_DOMAIN_ID, - [ - ("source_ip",self.MCLAG_SRC_IP), - ("peer_ip",self.MCLAG_PEER_IP), - ("peer_link",self.MCLAG_PEER_LINK), - ("keepalive_interval",value) - ] - ) - assert ok,error_info - - - # Testcase 7 Verify Deletion of MCLAG Domain - @pytest.mark.dev_sanity - def test_mclag_cfg_domain_del(self, dvs, testlog): - dvs.setup_db() - - remove_mclag_domain(dvs, self.MCLAG_DOMAIN_ID) - time.sleep(2) - - #check whether domain cfg table contents are same as configured values - ok, error_info = check_table_doesnt_exists(dvs.cdb, self.CFG_MCLAG_DOMAIN_TABLE, self.MCLAG_DOMAIN_ID) - assert ok,error_info - - #make sure mclag interface tables entries are also deleted when mclag domain is deleted - key_string = self.MCLAG_DOMAIN_ID - ok,error_info = check_table_doesnt_exists(dvs.cdb, self.CFG_MCLAG_INTERFACE_TABLE, key_string) - assert ok,error_info diff --git a/tests/test_mclag_fdb.py b/tests/test_mclag_fdb.py deleted file mode 100644 index 8252db8421..0000000000 --- a/tests/test_mclag_fdb.py +++ /dev/null @@ -1,587 +0,0 @@ -from swsscommon import swsscommon -import os -import sys -import time -import json -import pytest -from distutils.version import StrictVersion - -def create_entry(tbl, key, pairs): - fvs = swsscommon.FieldValuePairs(pairs) - tbl.set(key, fvs) - - time.sleep(1) - -def create_entry_tbl(db, table, key, pairs): - tbl = swsscommon.Table(db, table) - create_entry(tbl, key, pairs) - -def create_entry_pst(db, table, key, pairs): - tbl = swsscommon.ProducerStateTable(db, table) - create_entry(tbl, key, pairs) - -def delete_entry_tbl(db, table, key): - tbl = swsscommon.Table(db, table) - tbl._del(key) - -def delete_entry_pst(db, table, key): - tbl = swsscommon.ProducerStateTable(db, table) - tbl._del(key) - -def get_port_oid(dvs, port_name): - counters_db = swsscommon.DBConnector(swsscommon.COUNTERS_DB, dvs.redis_sock, 0) - port_map_tbl = swsscommon.Table(counters_db, 'COUNTERS_PORT_NAME_MAP') - for k in port_map_tbl.get('')[1]: - if k[0] == port_name: - return k[1] - return None - -def get_portchannel_oid(dvs, alias): - counters_db = swsscommon.DBConnector(swsscommon.COUNTERS_DB, dvs.redis_sock, 0) - lag_name_map_tbl = swsscommon.Table(counters_db, 'COUNTERS_LAG_NAME_MAP') - for k in lag_name_map_tbl.get('')[1]: - if k[0] == alias: - return k[1] - return None - -def get_bridge_port_oid(dvs, port_oid): - tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") - for key in tbl.getKeys(): - status, data = tbl.get(key) - assert status - values = dict(data) - if port_oid == values["SAI_BRIDGE_PORT_ATTR_PORT_ID"]: - return key - return None - -def create_port_channel(dvs, alias): - tbl = swsscommon.Table(dvs.cdb, "PORTCHANNEL") - fvs = swsscommon.FieldValuePairs([("admin_status", "up"), - ("mtu", "9100")]) - tbl.set(alias, fvs) - time.sleep(1) - -def remove_port_channel(dvs, alias): - tbl = swsscommon.Table(dvs.cdb, "PORTCHANNEL") - tbl._del(alias) - time.sleep(1) - -def add_port_channel_members(dvs, lag, members): - tbl = swsscommon.Table(dvs.cdb, "PORTCHANNEL_MEMBER") - fvs = swsscommon.FieldValuePairs([("NULL", "NULL")]) - for member in members: - tbl.set(lag + "|" + member, fvs) - time.sleep(1) - -def remove_port_channel_members(dvs, lag, members): - tbl = swsscommon.Table(dvs.cdb, "PORTCHANNEL_MEMBER") - for member in members: - tbl._del(lag + "|" + member) - time.sleep(1) - -def how_many_entries_exist(db, table): - tbl = swsscommon.Table(db, table) - return len(tbl.getKeys()) - -# Test-1 Verify basic config add - -@pytest.mark.dev_sanity -def test_mclagFdb_basic_config_add(dvs, testlog): - dvs.setup_db() - dvs.clear_fdb() - time.sleep(2) - - vlan_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - bp_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") - vm_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") - - # create PortChannel0005 - create_port_channel(dvs, "PortChannel0005") - - # add members to PortChannel0005 - add_port_channel_members(dvs, "PortChannel0005", ["Ethernet4"]) - - # create PortChannel0006 - create_port_channel(dvs, "PortChannel0006") - - # add members to PortChannel0006 - add_port_channel_members(dvs, "PortChannel0006", ["Ethernet8"]) - - # create PortChannel0008 - create_port_channel(dvs, "PortChannel0008") - - # add members to PortChannel0008 - add_port_channel_members(dvs, "PortChannel0008", ["Ethernet12"]) - - # create vlan - dvs.create_vlan("200") - - # Add vlan members - dvs.create_vlan_member("200", "PortChannel0005") - dvs.create_vlan_member("200", "PortChannel0006") - dvs.create_vlan_member("200", "PortChannel0008") - - # check that the vlan information was propagated - vlan_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - bp_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") - vm_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") - - assert vlan_after - vlan_before == 1, "The Vlan200 wasn't created" - assert bp_after - bp_before == 3, "The bridge port wasn't created" - assert vm_after - vm_before == 3, "The vlan member wasn't added" - -# Test-2 Remote Dynamic MAC Add - -@pytest.mark.dev_sanity -def test_mclagFdb_remote_dynamic_mac_add(dvs, testlog): - dvs.setup_db() - # create FDB entry in APP_DB MCLAG_FDB_TABLE - create_entry_pst( - dvs.pdb, - "MCLAG_FDB_TABLE", "Vlan200:3C:85:99:5E:00:01", - [ - ("port", "PortChannel0005"), - ("type", "dynamic"), - ] - ) - - # check that the FDB entry was inserted into ASIC DB - assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 1, "The MCLAG fdb entry not inserted to ASIC" - - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [("mac", "3C:85:99:5E:00:01"), ("bvid", str(dvs.getVlanOid("200")))], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_STATIC"), - ("SAI_FDB_ENTRY_ATTR_ALLOW_MAC_MOVE", "true")] - ) - - assert ok, str(extra) - -# Test-3 Remote Dynamic MAC Delete - -@pytest.mark.dev_sanity -def test_mclagFdb_remote_dynamic_mac_delete(dvs, testlog): - dvs.setup_db() - - delete_entry_pst( - dvs.pdb, - "MCLAG_FDB_TABLE", "Vlan200:3C:85:99:5E:00:01", - ) - - time.sleep(2) - # check that the FDB entry was deleted from ASIC DB - assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 0, "The MCLAG fdb entry not deleted" - - -# Test-4 Remote Static MAC Add - -@pytest.mark.dev_sanity -def test_mclagFdb_remote_static_mac_add(dvs, testlog): - dvs.setup_db() - - create_entry_pst( - dvs.pdb, - "MCLAG_FDB_TABLE", "Vlan200:3C:85:99:5E:00:01", - [ - ("port", "PortChannel0005"), - ("type", "static"), - ] - ) - - # check that the FDB entry was inserted into ASIC DB - assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 1, "The MCLAG static fdb entry not inserted to ASIC" - - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [("mac", "3C:85:99:5E:00:01"), ("bvid", str(dvs.getVlanOid("200")))], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_STATIC")] - ) - - assert ok, str(extra) - -# Test-5 Remote Static MAC Del - -@pytest.mark.dev_sanity -def test_mclagFdb_remote_static_mac_del(dvs, testlog): - dvs.setup_db() - - delete_entry_pst( - dvs.pdb, - "MCLAG_FDB_TABLE", "Vlan200:3C:85:99:5E:00:01", - ) - - time.sleep(2) - # check that the FDB entry was deleted from ASIC DB - assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 0, "The MCLAG static fdb entry not deleted" - - -# Test-6 Verify Remote to Local Move. - -@pytest.mark.dev_sanity -def test_mclagFdb_remote_to_local_mac_move(dvs, testlog): - dvs.setup_db() - - #Add remote MAC to MCLAG_FDB_TABLE on PortChannel0005 - create_entry_pst( - dvs.pdb, - "MCLAG_FDB_TABLE", "Vlan200:3C:85:99:5E:00:01", - [ - ("port", "PortChannel0005"), - ("type", "dynamic"), - ] - ) - - # check that the FDB entry inserted into ASIC DB - assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 1, "The MCLAG fdb entry not inserted to ASIC" - - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [("mac", "3C:85:99:5E:00:01"), ("bvid", str(dvs.getVlanOid("200")))], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_STATIC"), - ("SAI_FDB_ENTRY_ATTR_ALLOW_MAC_MOVE", "true")] - ) - - assert ok, str(extra) - - #Move MAC to PortChannel0008 on Local FDB_TABLE - create_entry_pst( - dvs.pdb, - "FDB_TABLE", "Vlan200:3C:85:99:5E:00:01", - [ - ("port", "PortChannel0008"), - ("type", "dynamic"), - ] - ) - - # check that the FDB entry was inserted into ASIC DB - assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 1, "The fdb entry not inserted to ASIC" - - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [("mac", "3C:85:99:5E:00:01"), ("bvid", str(dvs.getVlanOid("200")))], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_DYNAMIC")] - ) - - assert ok, str(extra) - -# Test-7 Verify Remote MAC del should not del local MAC after move - -@pytest.mark.dev_sanity -def test_mclagFdb_local_mac_move_del(dvs, testlog): - dvs.setup_db() - - #Cleanup the FDB from MCLAG_FDB_TABLE - delete_entry_pst( - dvs.pdb, - "MCLAG_FDB_TABLE", "Vlan200:3C:85:99:5E:00:01", - ) - - # Verify that the local FDB entry still inserted into ASIC DB - assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 1, "The fdb entry not inserted to ASIC" - - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [("mac", "3C:85:99:5E:00:01"), ("bvid", str(dvs.getVlanOid("200")))], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_DYNAMIC")] - ) - - assert ok, str(extra) - - - #delete the local FDB and Verify - delete_entry_pst( - dvs.pdb, - "FDB_TABLE", "Vlan200:3C:85:99:5E:00:01", - ) - - time.sleep(2) - # check that the FDB entry was deleted from ASIC DB - assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 0, "The fdb entry was not deleted" - - -# Test-8 Verify Local to Remote Move. - -@pytest.mark.dev_sanity -def test_mclagFdb_local_to_remote_move(dvs, testlog): - dvs.setup_db() - - #Add local MAC to FDB_TABLE on PortChannel0008 - create_entry_pst( - dvs.pdb, - "FDB_TABLE", "Vlan200:3C:85:99:5E:00:01", - [ - ("port", "PortChannel0008"), - ("type", "dynamic"), - ] - ) - - # check that the FDB entry was inserted into ASIC DB - assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 1, "The MCLAG fdb entry not inserted to ASIC" - - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [("mac", "3C:85:99:5E:00:01"), ("bvid", str(dvs.getVlanOid("200")))], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_DYNAMIC")] - ) - - assert ok, str(extra) - - #Move MAC to PortChannel0005 on Remote FDB_TABLE - create_entry_pst( - dvs.pdb, - "MCLAG_FDB_TABLE", "Vlan200:3C:85:99:5E:00:01", - [ - ("port", "PortChannel0005"), - ("type", "dynamic"), - ] - ) - - # check that the FDB entry was inserted into ASIC DB - assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 1, "The MCLAG fdb entry not inserted to ASIC" - - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [("mac", "3C:85:99:5E:00:01"), ("bvid", str(dvs.getVlanOid("200")))], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_STATIC"), - ("SAI_FDB_ENTRY_ATTR_ALLOW_MAC_MOVE", "true")] - ) - - assert ok, str(extra) - -# Test-9 Verify local MAC del should not del remote MAC after move - -@pytest.mark.dev_sanity -def test_mclagFdb_remote_move_del(dvs, testlog): - dvs.setup_db() - - #Cleanup the local FDB - delete_entry_pst( - dvs.pdb, - "FDB_TABLE", "Vlan200:3C:85:99:5E:00:01", - ) - - # check that the remote FDB entry still inserted into ASIC DB - assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 1, "The MCLAG fdb entry not inserted to ASIC" - - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [("mac", "3C:85:99:5E:00:01"), ("bvid", str(dvs.getVlanOid("200")))], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_STATIC"), - ("SAI_FDB_ENTRY_ATTR_ALLOW_MAC_MOVE", "true")] - ) - - assert ok, str(extra) - - #delete the remote FDB and Verify - delete_entry_pst( - dvs.pdb, - "MCLAG_FDB_TABLE", "Vlan200:3C:85:99:5E:00:01", - ) - - time.sleep(2) - # check that the FDB entry was deleted from ASIC DB - assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 0, "The fdb entry not deleted" - - - -# Test-10 Verify remote MAC move in remote node is updated locally. - -@pytest.mark.dev_sanity -def test_mclagFdb_remote_move_peer_node(dvs, testlog): - dvs.setup_db() - - #Add remote MAC to MCLAG_FDB_TABLE on PortChannel0005 - create_entry_pst( - dvs.pdb, - "MCLAG_FDB_TABLE", "Vlan200:3C:85:99:5E:00:01", - [ - ("port", "PortChannel0005"), - ("type", "dynamic"), - ] - ) - - # check that the FDB entry inserted into ASIC DB - assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 1, "The MCLAG fdb entry not inserted to ASIC" - - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [("mac", "3C:85:99:5E:00:01"), ("bvid", str(dvs.getVlanOid("200")))], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_STATIC"), - ("SAI_FDB_ENTRY_ATTR_ALLOW_MAC_MOVE", "true")] - ) - - assert ok, str(extra) - - # Move remote MAC in MCLAG_FDB_TABLE to PortChannel0006 - create_entry_pst( - dvs.pdb, - "MCLAG_FDB_TABLE", "Vlan200:3C:85:99:5E:00:01", - [ - ("port", "PortChannel0006"), - ("type", "dynamic"), - ] - ) - - # check that the FDB entry inserted into ASIC DB - assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 1, "The MCLAG fdb entry not inserted to ASIC" - - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [("mac", "3C:85:99:5E:00:01"), ("bvid", str(dvs.getVlanOid("200")))], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_STATIC"), - ("SAI_FDB_ENTRY_ATTR_ALLOW_MAC_MOVE", "true")] - ) - - assert ok, str(extra) - - #delete the remote FDB and Verify - delete_entry_pst( - dvs.pdb, - "MCLAG_FDB_TABLE", "Vlan200:3C:85:99:5E:00:01", - ) - - time.sleep(2) - # check that the FDB entry was deleted from ASIC DB - assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 0, "The fdb entry not deleted" - - -# Test-11 Verify remote dynamic MAC move rejection in presecense of local static MAC. - -@pytest.mark.dev_sanity -def test_mclagFdb_static_mac_dynamic_move_reject(dvs, testlog): - dvs.setup_db() - - #Add local MAC to FDB_TABLE on PortChannel0008 - create_entry_pst( - dvs.pdb, - "FDB_TABLE", "Vlan200:3C:85:99:5E:00:01", - [ - ("port", "PortChannel0008"), - ("type", "static"), - ] - ) - - # check that the static FDB entry was inserted into ASIC DB - assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 1, "The MCLAG fdb entry not inserted to ASIC" - - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [("mac", "3C:85:99:5E:00:01"), ("bvid", str(dvs.getVlanOid("200")))], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_STATIC")] - ) - - assert ok, str(extra) - - #Add remote MAC to MCLAG_FDB_TABLE on PortChannel0005 - create_entry_pst( - dvs.pdb, - "MCLAG_FDB_TABLE", "Vlan200:3C:85:99:5E:00:01", - [ - ("port", "PortChannel0005"), - ("type", "dynamic"), - ] - ) - - # check that still static FDB entry is inserted into ASIC DB - assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 1, "The MCLAG fdb entry not inserted to ASIC" - - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [("mac", "3C:85:99:5E:00:01"), ("bvid", str(dvs.getVlanOid("200")))], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_STATIC")] - ) - - assert ok, str(extra) - - delete_entry_pst( - dvs.pdb, - "FDB_TABLE", "Vlan200:3C:85:99:5E:00:01", - ) - - time.sleep(2) - # check that the FDB entry was deleted from ASIC DB - assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 0, "The MCLAG static fdb entry not deleted" - - delete_entry_pst( - dvs.pdb, - "MCLAG_FDB_TABLE", "Vlan200:3C:85:99:5E:00:01", - ) - -# Test-12 Verify Remote to Local Move. - -@pytest.mark.dev_sanity -def test_mclagFdb_remote_to_local_mac_move_ntf(dvs, testlog): - dvs.setup_db() - - #Add remote MAC to MCLAG_FDB_TABLE on PortChannel0005 - create_entry_pst( - dvs.pdb, - "MCLAG_FDB_TABLE", "Vlan200:3C:85:99:5E:00:01", - [ - ("port", "PortChannel0005"), - ("type", "dynamic"), - ] - ) - - # check that the FDB entry inserted into ASIC DB - assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 1, "The MCLAG fdb entry not inserted to ASIC" - - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [("mac", "3C:85:99:5E:00:01"), ("bvid", str(dvs.getVlanOid("200")))], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_STATIC"), - ("SAI_FDB_ENTRY_ATTR_ALLOW_MAC_MOVE", "true")] - ) - - assert ok, str(extra) - - mac = "3C:85:99:5E:00:01" - vlan_oid = dvs.getVlanOid("200") - switch_id = dvs.getSwitchOid() - port_oid = get_portchannel_oid(dvs, "PortChannel0008") - bp_port_oid = get_bridge_port_oid(dvs, port_oid) - - # send fdb_event SAI_FDB_EVENT_MOVE - ntf = swsscommon.NotificationProducer(dvs.adb, "NOTIFICATIONS") - fvp = swsscommon.FieldValuePairs() - ntf_data = "[{\"fdb_entry\":\"{\\\"bvid\\\":\\\""+vlan_oid+"\\\",\\\"mac\\\":\\\"3C:85:99:5E:00:01\\\",\\\"switch_id\\\":\\\""+switch_id+"\\\"}\",\"fdb_event\":\"SAI_FDB_EVENT_MOVE\",\"list\":[{\"id\":\"SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID\",\"value\":\""+bp_port_oid+"\"}]}]" - ntf.send("fdb_event", ntf_data, fvp) - - time.sleep(2) - - # check that the FDB entry was inserted into ASIC DB - assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 1, "The fdb entry not inserted to ASIC" - ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", - [("mac", "3C:85:99:5E:00:01"), ("bvid", str(dvs.getVlanOid("200")))], - [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_DYNAMIC"), - ("SAI_FDB_ENTRY_ATTR_ALLOW_MAC_MOVE", "false")] - ) - assert ok, str(extra) - - delete_entry_tbl( - dvs.sdb, - "FDB_TABLE", "Vlan200:3c:85:99:5e:00:01", - ) - - time.sleep(2) - - delete_entry_tbl( - dvs.adb, - "ASIC_STATE", "SAI_OBJECT_TYPE_FDB_ENTRY:{\"bvid\":\""+vlan_oid+"\",\"mac\":\"3C:85:99:5E:00:01\",\"switch_id\":\""+switch_id+"\"}" - ) - - # check that the FDB entry was deleted from ASIC DB - assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 0, "The MCLAG static fdb entry not deleted" - - delete_entry_pst( - dvs.pdb, - "MCLAG_FDB_TABLE", "Vlan200:3C:85:99:5E:00:01", - ) - -# Test-13 Verify cleanup of the basic config. - -@pytest.mark.dev_sanity -def test_mclagFdb_basic_config_del(dvs, testlog): - dvs.setup_db() - - dvs.remove_vlan_member("200", "PortChannel0005") - dvs.remove_vlan_member("200", "PortChannel0006") - dvs.remove_vlan_member("200", "PortChannel0008") - dvs.remove_vlan("200") - remove_port_channel_members(dvs, "PortChannel0005", - ["Ethernet4"]) - remove_port_channel_members(dvs, "PortChannel0006", - ["Ethernet8"]) - remove_port_channel_members(dvs, "PortChannel0008", - ["Ethernet12"]) - remove_port_channel(dvs, "PortChannel0005") - remove_port_channel(dvs, "PortChannel0006") - remove_port_channel(dvs, "PortChannel0008") - diff --git a/tests/test_mirror.py b/tests/test_mirror.py deleted file mode 100644 index f74ff6fa0d..0000000000 --- a/tests/test_mirror.py +++ /dev/null @@ -1,917 +0,0 @@ -# This test suite covers the functionality of mirror feature in SwSS -import distro -import pytest -import time - -from swsscommon import swsscommon -from distutils.version import StrictVersion - - -class TestMirror(object): - def setup_db(self, dvs): - self.pdb = swsscommon.DBConnector(0, dvs.redis_sock, 0) - self.adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - self.cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) - self.sdb = swsscommon.DBConnector(6, dvs.redis_sock, 0) - - def set_interface_status(self, dvs, interface, admin_status): - if interface.startswith("PortChannel"): - tbl_name = "PORTCHANNEL" - elif interface.startswith("Vlan"): - tbl_name = "VLAN" - else: - tbl_name = "PORT" - tbl = swsscommon.Table(self.cdb, tbl_name) - fvs = swsscommon.FieldValuePairs([("admin_status", "up")]) - tbl.set(interface, fvs) - time.sleep(1) - - # when using FRR, route cannot be inserted if the neighbor is not - # connected. thus it is mandatory to force the interface up manually - if interface.startswith("PortChannel"): - dvs.runcmd("bash -c 'echo " + ("1" if admin_status == "up" else "0") +\ - " > /sys/class/net/" + interface + "/carrier'") - - def add_ip_address(self, interface, ip): - if interface.startswith("PortChannel"): - tbl_name = "PORTCHANNEL_INTERFACE" - elif interface.startswith("Vlan"): - tbl_name = "VLAN_INTERFACE" - else: - tbl_name = "INTERFACE" - tbl = swsscommon.Table(self.cdb, tbl_name) - fvs = swsscommon.FieldValuePairs([("NULL", "NULL")]) - tbl.set(interface + "|" + ip, fvs) - tbl.set(interface, fvs) - time.sleep(1) - - def remove_ip_address(self, interface, ip): - if interface.startswith("PortChannel"): - tbl_name = "PORTCHANNEL_INTERFACE" - elif interface.startswith("Vlan"): - tbl_name = "VLAN_INTERFACE" - else: - tbl_name = "INTERFACE" - tbl = swsscommon.Table(self.cdb, tbl_name) - tbl._del(interface + "|" + ip) - tbl._del(interface) - time.sleep(1) - - def add_neighbor(self, interface, ip, mac): - tbl = swsscommon.ProducerStateTable(self.pdb, "NEIGH_TABLE") - fvs = swsscommon.FieldValuePairs([("neigh", mac), - ("family", "IPv4")]) - tbl.set(interface + ":" + ip, fvs) - time.sleep(1) - - def remove_neighbor(self, interface, ip): - tbl = swsscommon.ProducerStateTable(self.pdb, "NEIGH_TABLE") - tbl._del(interface + ":" + ip) - time.sleep(1) - - def add_route(self, dvs, prefix, nexthop): - dvs.runcmd("ip route add " + prefix + " via " + nexthop) - time.sleep(1) - - def remove_route(self, dvs, prefix): - dvs.runcmd("ip route del " + prefix) - time.sleep(1) - - def create_mirror_session(self, name, src, dst, gre, dscp, ttl, queue): - tbl = swsscommon.Table(self.cdb, "MIRROR_SESSION") - fvs = swsscommon.FieldValuePairs([("src_ip", src), - ("dst_ip", dst), - ("gre_type", gre), - ("dscp", dscp), - ("ttl", ttl), - ("queue", queue)]) - tbl.set(name, fvs) - time.sleep(1) - - def remove_mirror_session(self, name): - tbl = swsscommon.Table(self.cdb, "MIRROR_SESSION") - tbl._del(name) - time.sleep(1) - - def get_mirror_session_status(self, name): - return self.get_mirror_session_state(name)["status"] - - def get_mirror_session_state(self, name): - tbl = swsscommon.Table(self.sdb, "MIRROR_SESSION_TABLE") - (status, fvs) = tbl.get(name) - assert status == True - assert len(fvs) > 0 - return { fv[0]: fv[1] for fv in fvs } - - def check_syslog(self, dvs, marker, log, expected_cnt): - (ec, out) = dvs.runcmd(['sh', '-c', "awk \'/%s/,ENDFILE {print;}\' /var/log/syslog | grep \'%s\' | wc -l" % (marker, log)]) - assert out.strip() == str(expected_cnt) - - def test_MirrorAddRemove(self, dvs, testlog): - """ - This test covers the basic mirror session creation and removal operations - Operation flow: - 1. Create mirror session - The session remains inactive because no nexthop/neighbor exists - 2. Bring up port; assign IP; create neighbor; create route - The session remains inactive until the route is created - 3. Remove route; remove neighbor; remove IP; bring down port - The session becomes inactive again till the end - 4. Remove miror session - """ - self.setup_db(dvs) - - session = "TEST_SESSION" - - marker = dvs.add_log_marker() - # create mirror session - self.create_mirror_session(session, "1.1.1.1", "2.2.2.2", "0x6558", "8", "100", "0") - assert self.get_mirror_session_state(session)["status"] == "inactive" - self.check_syslog(dvs, marker, "Attached next hop observer .* for destination IP 2.2.2.2", 1) - - # bring up Ethernet16 - self.set_interface_status(dvs, "Ethernet16", "up") - assert self.get_mirror_session_state(session)["status"] == "inactive" - - # add IP address to Ethernet16 - self.add_ip_address("Ethernet16", "10.0.0.0/31") - assert self.get_mirror_session_state(session)["status"] == "inactive" - - # add neighbor to Ethernet16 - self.add_neighbor("Ethernet16", "10.0.0.1", "02:04:06:08:10:12") - assert self.get_mirror_session_state(session)["status"] == "inactive" - - # add route to mirror destination via 10.0.0.1 - self.add_route(dvs, "2.2.2.2", "10.0.0.1") - assert self.get_mirror_session_state(session)["status"] == "active" - assert self.get_mirror_session_state(session)["monitor_port"] == "Ethernet16" - assert self.get_mirror_session_state(session)["dst_mac"] == "02:04:06:08:10:12" - assert self.get_mirror_session_state(session)["route_prefix"] == "2.2.2.2/32" - - # check asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - mirror_entries = tbl.getKeys() - assert len(mirror_entries) == 1 - - (status, fvs) = tbl.get(mirror_entries[0]) - assert status == True - assert len(fvs) == 11 - for fv in fvs: - if fv[0] == "SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": - assert dvs.asicdb.portoidmap[fv[1]] == "Ethernet16" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_TYPE": - assert fv[1] == "SAI_MIRROR_SESSION_TYPE_ENHANCED_REMOTE" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_ERSPAN_ENCAPSULATION_TYPE": - assert fv[1] == "SAI_ERSPAN_ENCAPSULATION_TYPE_MIRROR_L3_GRE_TUNNEL" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_IPHDR_VERSION": - assert fv[1] == "4" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_TOS": - assert fv[1] == "32" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_TTL": - assert fv[1] == "100" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_SRC_IP_ADDRESS": - assert fv[1] == "1.1.1.1" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_DST_IP_ADDRESS": - assert fv[1] == "2.2.2.2" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_SRC_MAC_ADDRESS": - assert fv[1] == dvs.runcmd("bash -c \"ip link show eth0 | grep ether | awk '{print $2}'\"")[1].strip().upper() - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS": - assert fv[1] == "02:04:06:08:10:12" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_GRE_PROTOCOL_TYPE": - assert fv[1] == "25944" # 0x6558 - else: - assert False - - # remove route - self.remove_route(dvs, "2.2.2.2") - assert self.get_mirror_session_state(session)["status"] == "inactive" - - # remove neighbor - self.remove_neighbor("Ethernet16", "10.0.0.1") - assert self.get_mirror_session_state(session)["status"] == "inactive" - - # remove IP address - self.remove_ip_address("Ethernet16", "10.0.0.0/31") - assert self.get_mirror_session_state(session)["status"] == "inactive" - - # bring down Ethernet16 - self.set_interface_status(dvs, "Ethernet16", "down") - assert self.get_mirror_session_state(session)["status"] == "inactive" - - marker = dvs.add_log_marker() - # remove mirror session - self.remove_mirror_session(session) - self.check_syslog(dvs, marker, "Detached next hop observer for destination IP 2.2.2.2", 1) - - def create_vlan(self, dvs, vlan): - #dvs.runcmd("ip link del Bridge") - #dvs.runcmd("ip link add Bridge up type bridge") - tbl = swsscommon.Table(self.cdb, "VLAN") - fvs = swsscommon.FieldValuePairs([("vlanid", vlan)]) - tbl.set("Vlan" + vlan, fvs) - time.sleep(1) - - def remove_vlan(self, vlan): - tbl = swsscommon.Table(self.cdb, "VLAN") - tbl._del("Vlan" + vlan) - time.sleep(1) - - def create_vlan_member(self, vlan, interface): - tbl = swsscommon.Table(self.cdb, "VLAN_MEMBER") - fvs = swsscommon.FieldValuePairs([("tagging_mode", "untagged")]) - tbl.set("Vlan" + vlan + "|" + interface, fvs) - time.sleep(1) - - def remove_vlan_member(self, vlan, interface): - tbl = swsscommon.Table(self.cdb, "VLAN_MEMBER") - tbl._del("Vlan" + vlan + "|" + interface) - time.sleep(1) - - def create_fdb(self, vlan, mac, interface): - tbl = swsscommon.ProducerStateTable(self.pdb, "FDB_TABLE") - fvs = swsscommon.FieldValuePairs([("port", interface), - ("type", "dynamic")]) - tbl.set("Vlan" + vlan + ":" + mac, fvs) - time.sleep(1) - - def remove_fdb(self, vlan, mac): - tbl = swsscommon.ProducerStateTable(self.pdb, "FDB_TABLE") - tbl._del("Vlan" + vlan + ":" + mac) - time.sleep(1) - - - # Ignore testcase in Debian Jessie - # TODO: Remove this skip if Jessie support is no longer needed - @pytest.mark.skipif(StrictVersion(distro.linux_distribution()[1]) <= StrictVersion('8.9'), reason="Debian 8.9 or before has no support") - def test_MirrorToVlanAddRemove(self, dvs, testlog): - """ - This test covers basic mirror session creation and removal operation - with destination port sits in a VLAN - Opeartion flow: - 1. Create mirror session - 2. Create VLAN; assign IP; create neighbor; create FDB - The session should be up only at this time. - 3. Remove FDB; remove neighbor; remove IP; remove VLAN - 4. Remove mirror session - """ - self.setup_db(dvs) - - session = "TEST_SESSION" - - marker = dvs.add_log_marker() - # create mirror session - self.create_mirror_session(session, "5.5.5.5", "6.6.6.6", "0x6558", "8", "100", "0") - assert self.get_mirror_session_state(session)["status"] == "inactive" - self.check_syslog(dvs, marker, "Attached next hop observer .* for destination IP 6.6.6.6", 1) - - # create vlan; create vlan member - self.create_vlan(dvs, "6") - self.create_vlan_member("6", "Ethernet4") - - # bring up vlan and member - self.set_interface_status(dvs, "Vlan6", "up") - self.set_interface_status(dvs, "Ethernet4", "up") - - # add ip address to vlan 6 - self.add_ip_address("Vlan6", "6.6.6.0/24") - assert self.get_mirror_session_state(session)["status"] == "inactive" - - # create neighbor to vlan 6 - self.add_neighbor("Vlan6", "6.6.6.6", "66:66:66:66:66:66") - assert self.get_mirror_session_state(session)["status"] == "inactive" - - # create fdb entry to ethernet4 - self.create_fdb("6", "66-66-66-66-66-66", "Ethernet4") - assert self.get_mirror_session_state(session)["status"] == "active" - - # check asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - mirror_entries = tbl.getKeys() - assert len(mirror_entries) == 1 - - (status, fvs) = tbl.get(mirror_entries[0]) - assert status == True - assert len(fvs) == 16 - for fv in fvs: - if fv[0] == "SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": - assert dvs.asicdb.portoidmap[fv[1]] == "Ethernet4" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_TYPE": - assert fv[1] == "SAI_MIRROR_SESSION_TYPE_ENHANCED_REMOTE" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_ERSPAN_ENCAPSULATION_TYPE": - assert fv[1] == "SAI_ERSPAN_ENCAPSULATION_TYPE_MIRROR_L3_GRE_TUNNEL" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_IPHDR_VERSION": - assert fv[1] == "4" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_TOS": - assert fv[1] == "32" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_TTL": - assert fv[1] == "100" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_SRC_IP_ADDRESS": - assert fv[1] == "5.5.5.5" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_DST_IP_ADDRESS": - assert fv[1] == "6.6.6.6" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_SRC_MAC_ADDRESS": - assert fv[1] == dvs.runcmd("bash -c \"ip link show eth0 | grep ether | awk '{print $2}'\"")[1].strip().upper() - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS": - assert fv[1] == "66:66:66:66:66:66" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_GRE_PROTOCOL_TYPE": - assert fv[1] == "25944" # 0x6558 - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_VLAN_HEADER_VALID": - assert fv[1] == "true" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_VLAN_TPID": - assert fv[1] == "33024" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_VLAN_ID": - assert fv[1] == "6" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_VLAN_PRI": - assert fv[1] == "0" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_VLAN_CFI": - assert fv[1] == "0" - else: - assert False - - # remove fdb entry - self.remove_fdb("6", "66-66-66-66-66-66") - assert self.get_mirror_session_state(session)["status"] == "inactive" - - # remove neighbor - self.remove_neighbor("Vlan6", "6.6.6.6") - assert self.get_mirror_session_state(session)["status"] == "inactive" - - # remove ip address - self.remove_ip_address("Vlan6", "6.6.6.0/24") - assert self.get_mirror_session_state(session)["status"] == "inactive" - - # bring down vlan and member - self.set_interface_status(dvs, "Ethernet4", "down") - self.set_interface_status(dvs, "Vlan6", "down") - - # remove vlan member; remove vlan - self.remove_vlan_member("6", "Ethernet4") - self.remove_vlan("6") - - marker = dvs.add_log_marker() - # remove mirror session - self.remove_mirror_session(session) - self.check_syslog(dvs, marker, "Detached next hop observer for destination IP 6.6.6.6", 1) - - def create_port_channel(self, dvs, channel): - tbl = swsscommon.ProducerStateTable(self.pdb, "LAG_TABLE") - fvs = swsscommon.FieldValuePairs([("admin", "up"), ("mtu", "9100")]) - tbl.set("PortChannel" + channel, fvs) - dvs.runcmd("ip link add PortChannel" + channel + " type bond") - tbl = swsscommon.Table(self.sdb, "LAG_TABLE") - fvs = swsscommon.FieldValuePairs([("state", "ok")]) - tbl.set("PortChannel" + channel, fvs) - time.sleep(1) - - def remove_port_channel(self, dvs, channel): - tbl = swsscommon.ProducerStateTable(self.pdb, "LAG_TABLE") - tbl._del("PortChannel" + channel) - dvs.runcmd("ip link del PortChannel" + channel) - tbl = swsscommon.Table(self.sdb, "LAG_TABLE") - tbl._del("PortChannel" + channel) - time.sleep(1) - - def create_port_channel_member(self, channel, interface): - tbl = swsscommon.ProducerStateTable(self.pdb, "LAG_MEMBER_TABLE") - fvs = swsscommon.FieldValuePairs([("status", "enabled")]) - tbl.set("PortChannel" + channel + ":" + interface, fvs) - time.sleep(1) - - def remove_port_channel_member(self, channel, interface): - tbl = swsscommon.ProducerStateTable(self.pdb, "LAG_MEMBER_TABLE") - tbl._del("PortChannel" + channel + ":" + interface) - time.sleep(1) - - - def test_MirrorToLagAddRemove(self, dvs, testlog): - """ - This test covers basic mirror session creation and removal operations - with destination port sits in a LAG - Operation flow: - 1. Create mirror sesion - 2. Create LAG; assign IP; create directly connected neighbor - The session shoudl be up only at this time. - 3. Remove neighbor; remove IP; remove LAG - 4. Remove mirror session - - """ - self.setup_db(dvs) - - session = "TEST_SESSION" - - marker = dvs.add_log_marker() - # create mirror session - self.create_mirror_session(session, "10.10.10.10", "11.11.11.11", "0x6558", "8", "100", "0") - assert self.get_mirror_session_state(session)["status"] == "inactive" - self.check_syslog(dvs, marker, "Attached next hop observer .* for destination IP 11.11.11.11", 1) - - # create port channel; create port channel member - self.create_port_channel(dvs, "008") - self.create_port_channel_member("008", "Ethernet88") - - # bring up port channel and port channel member - self.set_interface_status(dvs, "PortChannel008", "up") - self.set_interface_status(dvs, "Ethernet88", "up") - - # add ip address to port channel 008 - self.add_ip_address("PortChannel008", "11.11.11.0/24") - assert self.get_mirror_session_state(session)["status"] == "inactive" - - # create neighbor to port channel 008 - self.add_neighbor("PortChannel008", "11.11.11.11", "88:88:88:88:88:88") - assert self.get_mirror_session_state(session)["status"] == "active" - - # check asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - assert len(tbl.getKeys()) == 1 - - (status, fvs) = tbl.get(tbl.getKeys()[0]) - assert status == True - for fv in fvs: - if fv[0] == "SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": - assert dvs.asicdb.portoidmap[fv[1]] == "Ethernet88" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS": - assert fv[1] == "88:88:88:88:88:88" - - # remove neighbor - self.remove_neighbor("PortChannel008", "11.11.11.11") - assert self.get_mirror_session_state(session)["status"] == "inactive" - - # remove ip address - self.remove_ip_address("PortChannel008", "11.11.11.0/24") - assert self.get_mirror_session_state(session)["status"] == "inactive" - - # bring down port channel and port channel member - self.set_interface_status(dvs, "PortChannel008", "down") - self.set_interface_status(dvs, "Ethernet88", "down") - - # remove port channel member; remove port channel - self.remove_port_channel_member("008", "Ethernet88") - self.remove_port_channel(dvs, "008") - - marker = dvs.add_log_marker() - # remove mirror session - self.remove_mirror_session(session) - self.check_syslog(dvs, marker, "Detached next hop observer for destination IP 11.11.11.11", 1) - - - # Ignore testcase in Debian Jessie - # TODO: Remove this skip if Jessie support is no longer needed - @pytest.mark.skipif(StrictVersion(distro.linux_distribution()[1]) <= StrictVersion('8.9'), reason="Debian 8.9 or before has no support") - def test_MirrorDestMoveVlan(self, dvs, testlog): - """ - This test tests mirror session destination move from non-VLAN to VLAN - and back to non-VLAN port - 1. Create mirror session - 2. Enable non-VLAN monitor port - 3. Create VLAN; move to VLAN without FDB entry - 4. Create FDB entry - 5. Remove FDB entry - 6. Remove VLAN; move to non-VLAN - 7. Disable non-VLAN monitor port - 8. Remove mirror session - """ - self.setup_db(dvs) - - session = "TEST_SESSION" - - # create mirror session - self.create_mirror_session(session, "7.7.7.7", "8.8.8.8", "0x6558", "8", "100", "0") - assert self.get_mirror_session_state(session)["status"] == "inactive" - - # bring up port; add ip; add neighbor; add route - self.set_interface_status(dvs, "Ethernet32", "up") - self.add_ip_address("Ethernet32", "80.0.0.0/31") - self.add_neighbor("Ethernet32", "80.0.0.1", "02:04:06:08:10:12") - self.add_route(dvs, "8.8.0.0/16", "80.0.0.1") - assert self.get_mirror_session_state(session)["status"] == "active" - - # check monitor port - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - assert len(tbl.getKeys()) == 1 - (status, fvs) = tbl.get(tbl.getKeys()[0]) - assert status == True - for fv in fvs: - if fv[0] == "SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": - assert dvs.asicdb.portoidmap[fv[1]] == "Ethernet32" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_VLAN_HEADER_VALID": - assert fv[1] == "false" - - # mirror session move round 1 - # create vlan; create vlan member; bring up vlan and member - self.create_vlan(dvs, "9") - self.create_vlan_member("9", "Ethernet48") - self.set_interface_status(dvs, "Vlan9", "up") - self.set_interface_status(dvs, "Ethernet48", "up") - assert self.get_mirror_session_state(session)["status"] == "active" - - # add ip address to vlan 9 - self.add_ip_address("Vlan9", "8.8.8.0/24") - assert self.get_mirror_session_state(session)["status"] == "inactive" - - # create neighbor to vlan 9 - self.add_neighbor("Vlan9", "8.8.8.8", "88:88:88:88:88:88") - assert self.get_mirror_session_state(session)["status"] == "inactive" - - # create fdb entry to ethernet48 - self.create_fdb("9", "88-88-88-88-88-88", "Ethernet48") - assert self.get_mirror_session_state(session)["status"] == "active" - - # check monitor port - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - assert len(tbl.getKeys()) == 1 - (status, fvs) = tbl.get(tbl.getKeys()[0]) - assert status == True - for fv in fvs: - if fv[0] == "SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": - assert dvs.asicdb.portoidmap[fv[1]] == "Ethernet48" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_VLAN_HEADER_VALID": - assert fv[1] == "true" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_VLAN_TPID": - assert fv[1] == "33024" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_VLAN_ID": - assert fv[1] == "9" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_VLAN_PRI": - assert fv[1] == "0" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_VLAN_CFI": - assert fv[1] == "0" - - # mirror session move round 2 - # remove fdb entry - self.remove_fdb("9", "88-88-88-88-88-88") - assert self.get_mirror_session_state(session)["status"] == "inactive" - - # remove neighbor - self.remove_neighbor("Vlan9", "8.8.8.8") - assert self.get_mirror_session_state(session)["status"] == "inactive" - - # remove ip address - self.remove_ip_address("Vlan9", "8.8.8.0/24") - assert self.get_mirror_session_state(session)["status"] == "active" - - # check monitor port - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - assert len(tbl.getKeys()) == 1 - (status, fvs) = tbl.get(tbl.getKeys()[0]) - assert status == True - for fv in fvs: - if fv[0] == "SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": - assert dvs.asicdb.portoidmap[fv[1]] == "Ethernet32" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_VLAN_HEADER_VALID": - assert fv[1] == "false" - - # bring down vlan and member; remove vlan member; remove vlan - self.set_interface_status(dvs, "Ethernet48", "down") - self.set_interface_status(dvs, "Vlan9", "down") - self.remove_vlan_member("9", "Ethernet48") - self.remove_vlan("9") - - # remove route; remove neighbor; remove ip; bring down port - self.remove_route(dvs, "8.8.8.0/24") - self.remove_neighbor("Ethernet32", "80.0.0.1") - self.remove_ip_address("Ethernet32", "80.0.0.0/31") - self.set_interface_status(dvs, "Ethernet32", "down") - - # remove mirror session - self.remove_mirror_session(session) - - - def test_MirrorDestMoveLag(self, dvs, testlog): - """ - This test tests mirror session destination move from non-LAG to LAG - and back to non-LAG port - 1. Create mirror session - 2. Enable non-LAG monitor port - 3. Create LAG; move to LAG with one member - 4. Remove LAG member - 5. Create LAG member - 6. Remove LAG; move to non-LAG - 7. Disable non-LAG monitor port - 8. Remove mirror session - """ - self.setup_db(dvs) - - session = "TEST_SESSION" - - # create mirror session - self.create_mirror_session(session, "12.12.12.12", "13.13.13.13", "0x6558", "8", "100", "0") - assert self.get_mirror_session_state(session)["status"] == "inactive" - - # bring up port; add ip; add neighbor; add route - self.set_interface_status(dvs, "Ethernet64", "up") - self.add_ip_address("Ethernet64", "100.0.0.0/31") - self.add_neighbor("Ethernet64", "100.0.0.1", "02:04:06:08:10:12") - self.add_route(dvs, "13.13.0.0/16", "100.0.0.1") - assert self.get_mirror_session_state(session)["status"] == "active" - - # check monitor port - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - assert len(tbl.getKeys()) == 1 - (status, fvs) = tbl.get(tbl.getKeys()[0]) - assert status == True - for fv in fvs: - if fv[0] == "SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": - assert dvs.asicdb.portoidmap[fv[1]] == "Ethernet64" - if fv[0] == "SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS": - assert fv[1] == "02:04:06:08:10:12" - - # mirror session move round 1 - # create port channel; create port channel member; bring up - self.create_port_channel(dvs, "080") - self.create_port_channel_member("080", "Ethernet32") - self.set_interface_status(dvs, "PortChannel080", "up") - self.set_interface_status(dvs, "Ethernet32", "up") - - # add ip address to port channel 080; create neighbor to port channel 080 - self.add_ip_address("PortChannel080", "200.0.0.0/31") - self.add_neighbor("PortChannel080", "200.0.0.1", "12:10:08:06:04:02") - assert self.get_mirror_session_state(session)["status"] == "active" - - # add route - self.add_route(dvs, "13.13.13.0/24", "200.0.0.1") - assert self.get_mirror_session_state(session)["status"] == "active" - - # check monitor port - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - assert len(tbl.getKeys()) == 1 - (status, fvs) = tbl.get(tbl.getKeys()[0]) - assert status == True - for fv in fvs: - if fv[0] == "SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": - assert dvs.asicdb.portoidmap[fv[1]] == "Ethernet32" - if fv[0] == "SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS": - assert fv[1] == "12:10:08:06:04:02" - - # mirror session move round 2 - # remove port channel member - self.remove_port_channel_member("080", "Ethernet32") - assert self.get_mirror_session_state(session)["status"] == "inactive" - - # mirror session move round 3 - # create port channel member - self.create_port_channel_member("080", "Ethernet32") - assert self.get_mirror_session_state(session)["status"] == "active" - - # check monitor port - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - assert len(tbl.getKeys()) == 1 - (status, fvs) = tbl.get(tbl.getKeys()[0]) - assert status == True - for fv in fvs: - if fv[0] == "SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": - assert dvs.asicdb.portoidmap[fv[1]] == "Ethernet32" - if fv[0] == "SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS": - assert fv[1] == "12:10:08:06:04:02" - - # mirror session move round 4 - # remove route - self.remove_route(dvs, "13.13.13.0/24") - assert self.get_mirror_session_state(session)["status"] == "active" - - port_oid = "" - # check monitor port - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - assert len(tbl.getKeys()) == 1 - (status, fvs) = tbl.get(tbl.getKeys()[0]) - assert status == True - for fv in fvs: - if fv[0] == "SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": - assert dvs.asicdb.portoidmap[fv[1]] == "Ethernet64" - if fv[0] == "SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS": - assert fv[1] == "02:04:06:08:10:12" - - # remove neighbor; remove ip address to port channel 080 - self.remove_neighbor("PortChannel080", "200.0.0.1") - self.remove_ip_address("PortChannel080", "200.0.0.0/31") - - # bring down; remove port channel member; remove port channel - self.set_interface_status(dvs, "Ethernet32", "down") - self.set_interface_status(dvs, "PortChannel080", "down") - self.remove_port_channel_member("080", "Ethernet32") - self.remove_port_channel(dvs, "080") - assert self.get_mirror_session_state(session)["status"] == "active" - - # remove route; remove neighbor; remove ip; bring down port - self.remove_route(dvs, "13.13.0.0/16") - self.remove_neighbor("Ethernet64", "100.0.0.1") - self.remove_ip_address("Ethernet64", "100.0.0.0/31") - self.set_interface_status(dvs, "Ethernet64", "down") - assert self.get_mirror_session_state(session)["status"] == "inactive" - - # remove mirror session - self.remove_mirror_session(session) - - - def create_acl_table(self, table, interfaces): - tbl = swsscommon.Table(self.cdb, "ACL_TABLE") - fvs = swsscommon.FieldValuePairs([("policy_desc", "mirror_test"), - ("type", "mirror"), - ("ports", ",".join(interfaces))]) - tbl.set(table, fvs) - time.sleep(1) - - def remove_acl_table(self, table): - tbl = swsscommon.Table(self.cdb, "ACL_TABLE") - tbl._del(table) - time.sleep(1) - - def create_mirror_acl_dscp_rule(self, table, rule, dscp, session, stage=None): - action_name = "mirror_action" - action_name_map = { - "ingress": "MIRROR_INGRESS_ACTION", - "egress": "MIRROR_EGRESS_ACTION" - } - if stage is not None: # else it should be treated as ingress by default in orchagent - assert stage in ('ingress', 'egress'), "invalid stage input {}".format(stage) - action_name = action_name_map[stage] - tbl = swsscommon.Table(self.cdb, "ACL_RULE") - fvs = swsscommon.FieldValuePairs([("priority", "1000"), - (action_name, session), - ("DSCP", dscp)]) - tbl.set(table + "|" + rule, fvs) - time.sleep(1) - - def remove_mirror_acl_dscp_rule(self, table, rule): - tbl = swsscommon.Table(self.cdb, "ACL_RULE") - tbl._del(table + "|" + rule) - time.sleep(1) - - def test_AclBindMirrorPerStage(self, dvs, testlog): - """ - This test configures mirror rules with specifying explicitely - the mirror action stage (ingress, egress) and verifies ASIC db - entry set with correct mirror action - """ - self.setup_db(dvs) - - session = "MIRROR_SESSION" - acl_table = "MIRROR_TABLE" - acl_rule = "MIRROR_RULE" - - # bring up port; assign ip; create neighbor; create route - self.set_interface_status(dvs, "Ethernet32", "up") - self.add_ip_address("Ethernet32", "20.0.0.0/31") - self.add_neighbor("Ethernet32", "20.0.0.1", "02:04:06:08:10:12") - self.add_route(dvs, "4.4.4.4", "20.0.0.1") - - # create mirror session - self.create_mirror_session(session, "3.3.3.3", "4.4.4.4", "0x6558", "8", "100", "0") - assert self.get_mirror_session_state(session)["status"] == "active" - - # assert mirror session in asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - assert len(tbl.getKeys()) == 1 - mirror_session_oid = tbl.getKeys()[0] - - # create acl table - self.create_acl_table(acl_table, ["Ethernet0", "Ethernet4"]) - - for stage, asic_attr in (("ingress", "SAI_ACL_ENTRY_ATTR_ACTION_MIRROR_INGRESS"), - ("egress", "SAI_ACL_ENTRY_ATTR_ACTION_MIRROR_EGRESS")): - # create acl rule with dscp value 48 - self.create_mirror_acl_dscp_rule(acl_table, acl_rule, "48", session, stage=stage) - - # assert acl rule is created - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") - rule_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_entries] - assert len(rule_entries) == 1 - - (status, fvs) = tbl.get(rule_entries[0]) - assert status == True - - asic_attr_found = False - for fv in fvs: - if fv[0] == asic_attr: - asic_attr_found = True - - assert asic_attr_found == True - - # remove acl rule - self.remove_mirror_acl_dscp_rule(acl_table, acl_rule) - - # remove acl table - self.remove_acl_table(acl_table) - - # remove mirror session - self.remove_mirror_session(session) - - # assert no mirror session in asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - assert len(tbl.getKeys()) == 0 - - # remove route; remove neighbor; remove ip; bring down port - self.remove_route(dvs, "4.4.4.4") - self.remove_neighbor("Ethernet32", "20.0.0.1") - self.remove_ip_address("Ethernet32", "20.0.0.0/31") - self.set_interface_status(dvs, "Ethernet32", "down") - - def _test_AclBindMirror(self, dvs, testlog, create_seq_test=False): - """ - This test tests ACL associated with mirror session with DSCP value - The DSCP value is tested on both with mask and without mask - """ - - session = "MIRROR_SESSION" - acl_table = "MIRROR_TABLE" - acl_rule = "MIRROR_RULE" - - # bring up port; assign ip; create neighbor; create route - self.set_interface_status(dvs, "Ethernet32", "up") - self.add_ip_address("Ethernet32", "20.0.0.0/31") - self.add_neighbor("Ethernet32", "20.0.0.1", "02:04:06:08:10:12") - if create_seq_test == False: - self.add_route(dvs, "4.4.4.4", "20.0.0.1") - - # create mirror session - self.create_mirror_session(session, "3.3.3.3", "4.4.4.4", "0x6558", "8", "100", "0") - assert self.get_mirror_session_state(session)["status"] == ("active" if create_seq_test == False else "inactive") - - # check mirror session in asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - assert len(tbl.getKeys()) == (1 if create_seq_test == False else 0) - if create_seq_test == False: - mirror_session_oid = tbl.getKeys()[0] - - # create acl table - self.create_acl_table(acl_table, ["Ethernet0", "Ethernet4"]) - - # create acl rule with dscp value 48 - self.create_mirror_acl_dscp_rule(acl_table, acl_rule, "48", session) - - # acl rule creation check - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") - rule_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_entries] - assert len(rule_entries) == (1 if create_seq_test == False else 0) - - if create_seq_test == True: - self.add_route(dvs, "4.4.4.4", "20.0.0.1") - - assert self.get_mirror_session_state(session)["status"] == "active" - - # assert mirror session in asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - assert len(tbl.getKeys()) == 1 - mirror_session_oid = tbl.getKeys()[0] - - # assert acl rule is created - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") - rule_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_entries] - assert len(rule_entries) == 1 - - (status, fvs) = tbl.get(rule_entries[0]) - assert status == True - for fv in fvs: - if fv[0] == "SAI_ACL_ENTRY_ATTR_FIELD_DSCP": - assert fv[1] == "48&mask:0x3f" - if fv[0] == "SAI_ACL_ENTRY_ATTR_ACTION_MIRROR_INGRESS": - assert fv[1] == "1:" + mirror_session_oid - - # remove acl rule - self.remove_mirror_acl_dscp_rule(acl_table, acl_rule) - - # create acl rule with dscp value 16/16 - self.create_mirror_acl_dscp_rule(acl_table, acl_rule, "16/16", session) - - # assert acl rule is created - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") - rule_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_entries] - assert len(rule_entries) == 1 - - (status, fvs) = tbl.get(rule_entries[0]) - assert status == True - for fv in fvs: - if fv[0] == "SAI_ACL_ENTRY_ATTR_FIELD_DSCP": - assert fv[1] == "16&mask:0x10" - if fv[0] == "SAI_ACL_ENTRY_ATTR_ACTION_MIRROR_INGRESS": - assert fv[1] == "1:" + mirror_session_oid - - # remove acl rule - self.remove_mirror_acl_dscp_rule(acl_table, acl_rule) - - # remove acl table - self.remove_acl_table(acl_table) - - # remove mirror session - self.remove_mirror_session(session) - - # assert no mirror session in asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - assert len(tbl.getKeys()) == 0 - - # remove route; remove neighbor; remove ip; bring down port - self.remove_route(dvs, "4.4.4.4") - self.remove_neighbor("Ethernet32", "20.0.0.1") - self.remove_ip_address("Ethernet32", "20.0.0.0/31") - self.set_interface_status(dvs, "Ethernet32", "down") - - def test_AclBindMirror(self, dvs, testlog): - self.setup_db(dvs) - - self._test_AclBindMirror(dvs, testlog) - self._test_AclBindMirror(dvs, testlog, create_seq_test=True) - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_mirror_ipv6_combined.py b/tests/test_mirror_ipv6_combined.py deleted file mode 100644 index e75f6af72d..0000000000 --- a/tests/test_mirror_ipv6_combined.py +++ /dev/null @@ -1,479 +0,0 @@ -# This test suite covers the functionality of mirror feature in SwSS -import time - -from swsscommon import swsscommon - -class TestMirror(object): - def setup_db(self, dvs): - self.pdb = swsscommon.DBConnector(0, dvs.redis_sock, 0) - self.adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - self.cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) - self.sdb = swsscommon.DBConnector(6, dvs.redis_sock, 0) - - def setup_mirrorv6_mode(self, mode): - tbl = swsscommon.Table(self.sdb, "SWITCH_CAPABILITY") - fvs = swsscommon.FieldValuePairs([("mirror_v6_table_mode", mode)]) - tbl.set("switch", fvs) - time.sleep(1) - - def set_interface_status(self, interface, admin_status): - if interface.startswith("PortChannel"): - tbl_name = "PORTCHANNEL" - elif interface.startswith("Vlan"): - tbl_name = "VLAN" - else: - tbl_name = "PORT" - tbl = swsscommon.Table(self.cdb, tbl_name) - fvs = swsscommon.FieldValuePairs([("admin_status", "up")]) - tbl.set(interface, fvs) - time.sleep(1) - - def add_ip_address(self, interface, ip): - if interface.startswith("PortChannel"): - tbl_name = "PORTCHANNEL_INTERFACE" - elif interface.startswith("Vlan"): - tbl_name = "VLAN_INTERFACE" - else: - tbl_name = "INTERFACE" - tbl = swsscommon.Table(self.cdb, tbl_name) - fvs = swsscommon.FieldValuePairs([("NULL", "NULL")]) - tbl.set(interface, fvs) - tbl.set(interface + "|" + ip, fvs) - time.sleep(1) - - def remove_ip_address(self, interface, ip): - if interface.startswith("PortChannel"): - tbl_name = "PORTCHANNEL_INTERFACE" - elif interface.startswith("Vlan"): - tbl_name = "VLAN_INTERFACE" - else: - tbl_name = "INTERFACE" - tbl = swsscommon.Table(self.cdb, tbl_name) - tbl._del(interface + "|" + ip) - tbl._del(interface) - time.sleep(1) - - def add_neighbor(self, interface, ip, mac): - tbl = swsscommon.ProducerStateTable(self.pdb, "NEIGH_TABLE") - fvs = swsscommon.FieldValuePairs([("neigh", mac), - ("family", "IPv4")]) - tbl.set(interface + ":" + ip, fvs) - time.sleep(1) - - def remove_neighbor(self, interface, ip): - tbl = swsscommon.ProducerStateTable(self.pdb, "NEIGH_TABLE") - tbl._del(interface + ":" + ip) - time.sleep(1) - - def add_route(self, dvs, prefix, nexthop): - dvs.runcmd("ip route add " + prefix + " via " + nexthop) - time.sleep(1) - - def remove_route(self, dvs, prefix): - dvs.runcmd("ip route del " + prefix) - time.sleep(1) - - def create_mirror_session(self, name, src, dst, gre, dscp, ttl, queue): - tbl = swsscommon.Table(self.cdb, "MIRROR_SESSION") - fvs = swsscommon.FieldValuePairs([("src_ip", src), - ("dst_ip", dst), - ("gre_type", gre), - ("dscp", dscp), - ("ttl", ttl), - ("queue", queue)]) - tbl.set(name, fvs) - time.sleep(1) - - def remove_mirror_session(self, name): - tbl = swsscommon.Table(self.cdb, "MIRROR_SESSION") - tbl._del(name) - time.sleep(1) - - def get_mirror_session_status(self, name): - return self.get_mirror_session_state(name)["status"] - - def get_mirror_session_state(self, name): - tbl = swsscommon.Table(self.sdb, "MIRROR_SESSION_TABLE") - (status, fvs) = tbl.get(name) - assert status == True - assert len(fvs) > 0 - return { fv[0]: fv[1] for fv in fvs } - - def create_acl_table(self, table, interfaces, type): - tbl = swsscommon.Table(self.cdb, "ACL_TABLE") - fvs = swsscommon.FieldValuePairs([("policy_desc", "mirror_test"), - ("type", type), - ("ports", ",".join(interfaces))]) - tbl.set(table, fvs) - time.sleep(1) - - def remove_acl_table(self, table): - tbl = swsscommon.Table(self.cdb, "ACL_TABLE") - tbl._del(table) - time.sleep(1) - - def create_mirror_acl_ipv4_rule(self, table, rule, session): - tbl = swsscommon.Table(self.cdb, "ACL_RULE") - fvs = swsscommon.FieldValuePairs([("priority", "1000"), - ("mirror_action", session), - ("SRC_IP", "10.0.0.0/32"), - ("DST_IP", "20.0.0.0/23")]) - tbl.set(table + "|" + rule, fvs) - time.sleep(1) - - def create_mirror_acl_ipv6_rule(self, table, rule, session): - tbl = swsscommon.Table(self.cdb, "ACL_RULE") - fvs = swsscommon.FieldValuePairs([("priority", "1000"), - ("mirror_action", session), - ("SRC_IPV6", "2777::0/64"), - ("DST_IPV6", "3666::0/128")]) - tbl.set(table + "|" + rule, fvs) - time.sleep(1) - - def remove_mirror_acl_rule(self, table, rule): - tbl = swsscommon.Table(self.cdb, "ACL_RULE") - tbl._del(table + "|" + rule) - time.sleep(1) - - def test_CombinedMirrorTableCreation(self, dvs, testlog): - self.setup_db(dvs) - - acl_table = "MIRROR_TABLE" - ports = ["Ethernet0", "Ethernet4"] - - # Create the table - self.create_acl_table(acl_table, ports, "MIRROR") - - # Check that the table has been created - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE") - table_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_tables] - assert len(table_entries) == 1 - - # Get the data from the table - table_id = table_entries[0] - status, attributes = tbl.get(table_id) - assert status - - # TODO: Refactor mirror table tests so that these attributes can be shared between tests for v4, v6, and - # dscp mirror tables. - expected_sai_attributes = [ - "SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE", - "SAI_ACL_TABLE_ATTR_FIELD_IP_PROTOCOL", - "SAI_ACL_TABLE_ATTR_FIELD_IPV6_NEXT_HEADER", - "SAI_ACL_TABLE_ATTR_FIELD_SRC_IP", - "SAI_ACL_TABLE_ATTR_FIELD_DST_IP", - "SAI_ACL_TABLE_ATTR_FIELD_ICMP_TYPE", - "SAI_ACL_TABLE_ATTR_FIELD_ICMP_CODE", - "SAI_ACL_TABLE_ATTR_FIELD_L4_SRC_PORT", - "SAI_ACL_TABLE_ATTR_FIELD_L4_DST_PORT", - "SAI_ACL_TABLE_ATTR_FIELD_TCP_FLAGS", - "SAI_ACL_TABLE_ATTR_FIELD_DSCP", - "SAI_ACL_TABLE_ATTR_FIELD_ETHER_TYPE", - "SAI_ACL_TABLE_ATTR_FIELD_OUTER_VLAN_ID", - "SAI_ACL_TABLE_ATTR_FIELD_IN_PORTS", - "SAI_ACL_TABLE_ATTR_FIELD_SRC_IPV6", - "SAI_ACL_TABLE_ATTR_FIELD_DST_IPV6", - "SAI_ACL_TABLE_ATTR_FIELD_ICMPV6_TYPE", - "SAI_ACL_TABLE_ATTR_FIELD_ICMPV6_CODE", - ] - - expected_sai_list_attributes = [ - "SAI_ACL_TABLE_ATTR_FIELD_ACL_RANGE_TYPE", - "SAI_ACL_TABLE_ATTR_ACL_BIND_POINT_TYPE_LIST" - ] - - # Check that all of the V6 table attributes have been populated - assert(len(attributes) == (len(expected_sai_attributes) + len(expected_sai_list_attributes) + 1)) - for attribute in attributes: - key = attribute[0] - value = attribute[1] - - if key in expected_sai_attributes: - assert value == "true" - elif key in expected_sai_list_attributes: - count = int(value[0:1]) - list_attrs = value[2:].split(',') - if key == "SAI_ACL_TABLE_ATTR_FIELD_ACL_RANGE_TYPE": - assert set(list_attrs) == set(["SAI_ACL_RANGE_TYPE_L4_DST_PORT_RANGE", "SAI_ACL_RANGE_TYPE_L4_SRC_PORT_RANGE"]) - elif key == "SAI_ACL_TABLE_ATTR_ACL_BIND_POINT_TYPE_LIST": - assert set(list_attrs) == set(["SAI_ACL_BIND_POINT_TYPE_PORT", "SAI_ACL_BIND_POINT_TYPE_LAG"]) - else: - print("Encountered unexpected range attribute on mirror table: {}".format(key)) - assert False - elif key == "SAI_ACL_TABLE_ATTR_ACL_STAGE": - assert value == "SAI_ACL_STAGE_INGRESS" - else: - print("Encountered unexpected attribute on mirror table: {}".format(key)) - assert False - - # Delete the table - self.remove_acl_table(acl_table) - - - # Test case - create a MIRROR table and a MIRRORV6 table in combined mode - # 0. predefine the VS capability: combined - # 1. create a mirror session - # 2. create two ACL tables that support both IPv4 and IPv6 - # 3. create two ACL rules with both IPv4 and IPv6 source and destination IP - # verify the ACL rules are created successfully - # 4. remove all the configurations - def test_AclBindMirrorV6Combined(self, dvs, testlog): - """ - This test verifies IPv6 rules cannot be inserted into MIRROR table - """ - self.setup_db(dvs) - - self.setup_mirrorv6_mode("combined") - - session = "MIRROR_SESSION" - acl_table = "MIRROR_TABLE" - acl_table_v6 = "MIRROR_TABLE_V6" - acl_rule_1 = "MIRROR_RULE_1" - acl_rule_2 = "MIRROR_RULE_2" - - # bring up port; assign ip; create neighbor; create route - self.set_interface_status("Ethernet32", "up") - self.add_ip_address("Ethernet32", "20.0.0.0/31") - self.add_neighbor("Ethernet32", "20.0.0.1", "02:04:06:08:10:12") - self.add_route(dvs, "4.4.4.4", "20.0.0.1") - - # create mirror session - self.create_mirror_session(session, "3.3.3.3", "4.4.4.4", "0x6558", "8", "100", "0") - assert self.get_mirror_session_state(session)["status"] == "active" - - # assert mirror session in asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - assert len(tbl.getKeys()) == 1 - mirror_session_oid = tbl.getKeys()[0] - - # create acl table ipv4 - self.create_acl_table(acl_table, ["Ethernet0", "Ethernet4"], "MIRROR") - - # assert acl table is created - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE") - table_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_tables] - assert len(table_entries) == 1 - - # create acl table ipv6 - self.create_acl_table(acl_table_v6, ["Ethernet0", "Ethernet4"], "MIRRORV6") - - # assert acl table is created - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE") - table_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_tables] - assert len(table_entries) == 1 - - table_id = table_entries[0] - - # create acl rule with IPv4 addresses - self.create_mirror_acl_ipv4_rule(acl_table, acl_rule_1, session) - - # assert acl rule ipv4 is created - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") - rule_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_entries] - assert len(rule_entries) == 1 - - rule_id_v4 = rule_entries[0] - - # assert acl rule is assocaited with table ipv4 - (status, fvs) = tbl.get(rule_id_v4) - assert status == True - for fv in fvs: - if fv[0] == "SAI_ACL_ENTRY_ATTR_TABLE_ID": - assert fv[1] == table_id - - # create acl rule with IPv6 addresses - self.create_mirror_acl_ipv6_rule(acl_table_v6, acl_rule_2, session) - - # assert acl rule ipv6 is created - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") - rule_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_entries] - assert len(rule_entries) == 2 - - rule_id_v6 = rule_entries[1] if rule_entries[0] == rule_id_v4 else rule_entries[0] - - # assert acl rule is associated with table ipv6 - (status, fvs) = tbl.get(rule_id_v6) - assert status == True - for fv in fvs: - if fv[0] == "SAI_ACL_ENTRY_ATTR_TABLE_ID": - assert fv[1] == table_id - - # remove acl rule - self.remove_mirror_acl_rule(acl_table, acl_rule_1) - self.remove_mirror_acl_rule(acl_table_v6, acl_rule_2) - - # remove acl table - self.remove_acl_table(acl_table) - self.remove_acl_table(acl_table_v6) - - # remove mirror session - self.remove_mirror_session(session) - - # assert no mirror session in asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - assert len(tbl.getKeys()) == 0 - - # remove route; remove neighbor; remove ip; bring down port - self.remove_route(dvs, "4.4.4.4") - self.remove_neighbor("Ethernet32", "20.0.0.1") - self.remove_ip_address("Ethernet32", "20.0.0.0/31") - self.set_interface_status("Ethernet32", "down") - - - # Test case - intervene rule creation in table creation - # 0. predefine the VS platform: mellanox platform - # 1. create a mirror session - # 2. create the ipv4 ACL table - # 3. create the ipv4 ACL rule - # 4. create the ipv6 ACL table - # 5. create the ipv6 ACL rule - # 6. verify two rules are inserted successfully - def test_AclBindMirrorV6Reorder1(self, dvs, testlog): - """ - This test verifies IPv6 rules cannot be inserted into MIRROR table - """ - self.setup_db(dvs) - - session = "MIRROR_SESSION" - acl_table = "MIRROR_TABLE" - acl_table_v6 = "MIRROR_TABLE_V6" - acl_rule_1 = "MIRROR_RULE_1" - acl_rule_2 = "MIRROR_RULE_2" - - # bring up port; assign ip; create neighbor; create route - self.set_interface_status("Ethernet32", "up") - self.add_ip_address("Ethernet32", "20.0.0.0/31") - self.add_neighbor("Ethernet32", "20.0.0.1", "02:04:06:08:10:12") - self.add_route(dvs, "4.4.4.4", "20.0.0.1") - - # create mirror session - self.create_mirror_session(session, "3.3.3.3", "4.4.4.4", "0x6558", "8", "100", "0") - assert self.get_mirror_session_state(session)["status"] == "active" - - # assert mirror session in asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - assert len(tbl.getKeys()) == 1 - mirror_session_oid = tbl.getKeys()[0] - - # create acl table ipv4 - self.create_acl_table(acl_table, ["Ethernet0", "Ethernet4"], "MIRROR") - - # create acl rule with IPv4 addresses - self.create_mirror_acl_ipv4_rule(acl_table, acl_rule_1, session) - - # create acl table ipv6 - self.create_acl_table(acl_table_v6, ["Ethernet0", "Ethernet4"], "MIRRORV6") - - # create acl rule with IPv6 addresses - self.create_mirror_acl_ipv6_rule(acl_table_v6, acl_rule_2, session) - - # assert acl rules are created - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") - rule_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_entries] - assert len(rule_entries) == 2 - - # remove acl rule - self.remove_mirror_acl_rule(acl_table, acl_rule_1) - self.remove_mirror_acl_rule(acl_table_v6, acl_rule_2) - - # remove acl table - self.remove_acl_table(acl_table) - self.remove_acl_table(acl_table_v6) - - # remove mirror session - self.remove_mirror_session(session) - - # assert no mirror session in asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - assert len(tbl.getKeys()) == 0 - - # remove route; remove neighbor; remove ip; bring down port - self.remove_route(dvs, "4.4.4.4") - self.remove_neighbor("Ethernet32", "20.0.0.1") - self.remove_ip_address("Ethernet32", "20.0.0.0/31") - self.set_interface_status("Ethernet32", "down") - - - # Test case - intervene rule creation in table creation - # 0. predefine the VS platform: mellanox platform - # 1. create a mirror session - # 2. create the ipv4 ACL table - # 3. create the ipv6 ACL rule - # 4. create the ipv6 ACL table - # 5. create the ipv4 ACL rule - # 6. verify two rules are inserted successfully - def test_AclBindMirrorV6Reorder2(self, dvs, testlog): - """ - This test verifies IPv6 rules cannot be inserted into MIRROR table - """ - self.setup_db(dvs) - - session = "MIRROR_SESSION" - acl_table = "MIRROR_TABLE" - acl_table_v6 = "MIRROR_TABLE_V6" - acl_rule_1 = "MIRROR_RULE_1" - acl_rule_2 = "MIRROR_RULE_2" - - # bring up port; assign ip; create neighbor; create route - self.set_interface_status("Ethernet32", "up") - self.add_ip_address("Ethernet32", "20.0.0.0/31") - self.add_neighbor("Ethernet32", "20.0.0.1", "02:04:06:08:10:12") - self.add_route(dvs, "4.4.4.4", "20.0.0.1") - - # create mirror session - self.create_mirror_session(session, "3.3.3.3", "4.4.4.4", "0x6558", "8", "100", "0") - assert self.get_mirror_session_state(session)["status"] == "active" - - # assert mirror session in asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - assert len(tbl.getKeys()) == 1 - mirror_session_oid = tbl.getKeys()[0] - - # create acl table ipv4 - self.create_acl_table(acl_table, ["Ethernet0", "Ethernet4"], "MIRROR") - - # create acl rule with IPv6 addresses - self.create_mirror_acl_ipv6_rule(acl_table_v6, acl_rule_2, session) - - # assert acl rule is not created - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") - rule_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_entries] - assert len(rule_entries) == 0 - - # create acl table ipv6 - self.create_acl_table(acl_table_v6, ["Ethernet0", "Ethernet4"], "MIRRORV6") - - # create acl rule with IPv4 addresses - self.create_mirror_acl_ipv4_rule(acl_table, acl_rule_1, session) - - # assert acl rules are created - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") - rule_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_entries] - assert len(rule_entries) == 2 - - # remove acl rule - self.remove_mirror_acl_rule(acl_table, acl_rule_1) - self.remove_mirror_acl_rule(acl_table_v6, acl_rule_2) - - # remove acl table - self.remove_acl_table(acl_table) - self.remove_acl_table(acl_table_v6) - - # remove mirror session - self.remove_mirror_session(session) - - # assert no mirror session in asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - assert len(tbl.getKeys()) == 0 - - # remove route; remove neighbor; remove ip; bring down port - self.remove_route(dvs, "4.4.4.4") - self.remove_neighbor("Ethernet32", "20.0.0.1") - self.remove_ip_address("Ethernet32", "20.0.0.0/31") - self.set_interface_status("Ethernet32", "down") - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_mirror_ipv6_separate.py b/tests/test_mirror_ipv6_separate.py deleted file mode 100644 index 6711c345c5..0000000000 --- a/tests/test_mirror_ipv6_separate.py +++ /dev/null @@ -1,670 +0,0 @@ -# This test suite covers the functionality of mirror feature in SwSS -import time - -from swsscommon import swsscommon - -DVS_ENV = ["HWSKU=Mellanox-SN2700"] - - -class TestMirror(object): - def setup_db(self, dvs): - self.pdb = swsscommon.DBConnector(0, dvs.redis_sock, 0) - self.adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - self.cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) - self.sdb = swsscommon.DBConnector(6, dvs.redis_sock, 0) - - def set_interface_status(self, interface, admin_status): - if interface.startswith("PortChannel"): - tbl_name = "PORTCHANNEL" - elif interface.startswith("Vlan"): - tbl_name = "VLAN" - else: - tbl_name = "PORT" - tbl = swsscommon.Table(self.cdb, tbl_name) - fvs = swsscommon.FieldValuePairs([("admin_status", "up")]) - tbl.set(interface, fvs) - time.sleep(1) - - def add_ip_address(self, interface, ip): - if interface.startswith("PortChannel"): - tbl_name = "PORTCHANNEL_INTERFACE" - elif interface.startswith("Vlan"): - tbl_name = "VLAN_INTERFACE" - else: - tbl_name = "INTERFACE" - tbl = swsscommon.Table(self.cdb, tbl_name) - fvs = swsscommon.FieldValuePairs([("NULL", "NULL")]) - tbl.set(interface, fvs) - tbl.set(interface + "|" + ip, fvs) - time.sleep(1) - - def remove_ip_address(self, interface, ip): - if interface.startswith("PortChannel"): - tbl_name = "PORTCHANNEL_INTERFACE" - elif interface.startswith("Vlan"): - tbl_name = "VLAN_INTERFACE" - else: - tbl_name = "INTERFACE" - tbl = swsscommon.Table(self.cdb, tbl_name) - tbl._del(interface + "|" + ip) - tbl._del(interface) - time.sleep(1) - - def add_neighbor(self, interface, ip, mac): - tbl = swsscommon.ProducerStateTable(self.pdb, "NEIGH_TABLE") - fvs = swsscommon.FieldValuePairs([("neigh", mac), - ("family", "IPv4")]) - tbl.set(interface + ":" + ip, fvs) - time.sleep(1) - - def remove_neighbor(self, interface, ip): - tbl = swsscommon.ProducerStateTable(self.pdb, "NEIGH_TABLE") - tbl._del(interface + ":" + ip) - time.sleep(1) - - def add_route(self, dvs, prefix, nexthop): - dvs.runcmd("ip route add " + prefix + " via " + nexthop) - time.sleep(1) - - def remove_route(self, dvs, prefix): - dvs.runcmd("ip route del " + prefix) - time.sleep(1) - - def create_mirror_session(self, name, src, dst, gre, dscp, ttl, queue): - tbl = swsscommon.Table(self.cdb, "MIRROR_SESSION") - fvs = swsscommon.FieldValuePairs([("src_ip", src), - ("dst_ip", dst), - ("gre_type", gre), - ("dscp", dscp), - ("ttl", ttl), - ("queue", queue)]) - tbl.set(name, fvs) - time.sleep(1) - - def remove_mirror_session(self, name): - tbl = swsscommon.Table(self.cdb, "MIRROR_SESSION") - tbl._del(name) - time.sleep(1) - - def get_mirror_session_status(self, name): - return self.get_mirror_session_state(name)["status"] - - def get_mirror_session_state(self, name): - tbl = swsscommon.Table(self.sdb, "MIRROR_SESSION_TABLE") - (status, fvs) = tbl.get(name) - assert status == True - assert len(fvs) > 0 - return { fv[0]: fv[1] for fv in fvs } - - def create_acl_table(self, table, interfaces, type, stage=None): - attrs = [("policy_desc", "mirror_test"), - ("type", type), - ("ports", ",".join(interfaces))] - if stage: - attrs.append(("stage", stage)) - - tbl = swsscommon.Table(self.cdb, "ACL_TABLE") - fvs = swsscommon.FieldValuePairs(attrs) - tbl.set(table, fvs) - time.sleep(1) - - def remove_acl_table(self, table): - tbl = swsscommon.Table(self.cdb, "ACL_TABLE") - tbl._del(table) - time.sleep(1) - - def create_mirror_acl_ipv4_rule(self, table, rule, session): - tbl = swsscommon.Table(self.cdb, "ACL_RULE") - fvs = swsscommon.FieldValuePairs([("priority", "1000"), - ("mirror_action", session), - ("SRC_IP", "10.0.0.0/32"), - ("DST_IP", "20.0.0.0/23")]) - tbl.set(table + "|" + rule, fvs) - time.sleep(1) - - def create_mirror_acl_ipv6_rule(self, table, rule, session): - tbl = swsscommon.Table(self.cdb, "ACL_RULE") - fvs = swsscommon.FieldValuePairs([("priority", "1000"), - ("mirror_action", session), - ("SRC_IPV6", "2777::0/64"), - ("DST_IPV6", "3666::0/128")]) - tbl.set(table + "|" + rule, fvs) - time.sleep(1) - - def remove_mirror_acl_rule(self, table, rule): - tbl = swsscommon.Table(self.cdb, "ACL_RULE") - tbl._del(table + "|" + rule) - time.sleep(1) - - def test_MirrorTableCreation(self, dvs, testlog): - self.setup_db(dvs) - - acl_table = "MIRROR_TABLE" - ports = ["Ethernet0", "Ethernet4"] - - # Create the table - self.create_acl_table(acl_table, ports, "MIRROR") - - # Check that the table has been created - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE") - table_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_tables] - assert len(table_entries) == 1 - - # Get the data from the table - table_id = table_entries[0] - status, attributes = tbl.get(table_id) - assert status - - # TODO: Refactor mirror table tests so that these attributes can be shared between tests for v4, v6, and - # dscp mirror tables. - expected_sai_attributes = [ - "SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE", - "SAI_ACL_TABLE_ATTR_FIELD_IP_PROTOCOL", - "SAI_ACL_TABLE_ATTR_FIELD_SRC_IP", - "SAI_ACL_TABLE_ATTR_FIELD_DST_IP", - "SAI_ACL_TABLE_ATTR_FIELD_ICMP_TYPE", - "SAI_ACL_TABLE_ATTR_FIELD_ICMP_CODE", - "SAI_ACL_TABLE_ATTR_FIELD_L4_SRC_PORT", - "SAI_ACL_TABLE_ATTR_FIELD_L4_DST_PORT", - "SAI_ACL_TABLE_ATTR_FIELD_TCP_FLAGS", - "SAI_ACL_TABLE_ATTR_FIELD_DSCP", - "SAI_ACL_TABLE_ATTR_FIELD_ETHER_TYPE", - "SAI_ACL_TABLE_ATTR_FIELD_OUTER_VLAN_ID", - "SAI_ACL_TABLE_ATTR_FIELD_IN_PORTS", - ] - - expected_sai_list_attributes = [ - "SAI_ACL_TABLE_ATTR_FIELD_ACL_RANGE_TYPE", - "SAI_ACL_TABLE_ATTR_ACL_BIND_POINT_TYPE_LIST" - ] - - # Check that all of the V6 table attributes have been populated - assert(len(attributes) == (len(expected_sai_attributes) + len(expected_sai_list_attributes) + 1)) - for attribute in attributes: - key = attribute[0] - value = attribute[1] - - if key in expected_sai_attributes: - assert value == "true" - elif key in expected_sai_list_attributes: - count = int(value[0:1]) - list_attrs = value[2:].split(',') - if key == "SAI_ACL_TABLE_ATTR_FIELD_ACL_RANGE_TYPE": - assert set(list_attrs) == set(["SAI_ACL_RANGE_TYPE_L4_DST_PORT_RANGE", "SAI_ACL_RANGE_TYPE_L4_SRC_PORT_RANGE"]) - elif key == "SAI_ACL_TABLE_ATTR_ACL_BIND_POINT_TYPE_LIST": - assert set(list_attrs) == set(["SAI_ACL_BIND_POINT_TYPE_PORT", "SAI_ACL_BIND_POINT_TYPE_LAG"]) - else: - print("Encountered unexpected range attribute on mirror table: {}".format(key)) - assert False - elif key == "SAI_ACL_TABLE_ATTR_ACL_STAGE": - assert value == "SAI_ACL_STAGE_INGRESS" - else: - print("Encountered unexpected attribute on mirror table: {}".format(key)) - assert False - - # Delete the table - self.remove_acl_table(acl_table) - - def test_MirrorV6TableCreation(self, dvs, testlog): - self.setup_db(dvs) - - acl_table_v6 = "MIRROR_TABLE_V6" - ports = ["Ethernet0", "Ethernet4"] - - # Create the V6 table - self.create_acl_table(acl_table_v6, ports, "MIRRORV6") - - # Check that the V6 table has been created - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE") - table_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_tables] - assert len(table_entries) == 1 - - # Get the data from the V6 table - v6_table_id = table_entries[0] - status, attributes = tbl.get(v6_table_id) - assert status - - # TODO: Refactor mirror table tests so that these attributes can be shared between tests for v4, v6, and - # dscp mirror tables. - expected_sai_attributes = [ - "SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE", - "SAI_ACL_TABLE_ATTR_FIELD_IPV6_NEXT_HEADER", - "SAI_ACL_TABLE_ATTR_FIELD_SRC_IPV6", - "SAI_ACL_TABLE_ATTR_FIELD_DST_IPV6", - "SAI_ACL_TABLE_ATTR_FIELD_ICMPV6_TYPE", - "SAI_ACL_TABLE_ATTR_FIELD_ICMPV6_CODE", - "SAI_ACL_TABLE_ATTR_FIELD_L4_SRC_PORT", - "SAI_ACL_TABLE_ATTR_FIELD_L4_DST_PORT", - "SAI_ACL_TABLE_ATTR_FIELD_TCP_FLAGS", - "SAI_ACL_TABLE_ATTR_FIELD_DSCP", - "SAI_ACL_TABLE_ATTR_FIELD_OUTER_VLAN_ID" - ] - - expected_sai_list_attributes = [ - "SAI_ACL_TABLE_ATTR_FIELD_ACL_RANGE_TYPE", - "SAI_ACL_TABLE_ATTR_ACL_BIND_POINT_TYPE_LIST" - ] - - # Check that all of the V6 table attributes have been populated - for attribute in attributes: - key = attribute[0] - value = attribute[1] - - if key in expected_sai_attributes: - assert value == "true" - elif key in expected_sai_list_attributes: - count = int(value[0:1]) - list_attrs = value[2:].split(',') - if key == "SAI_ACL_TABLE_ATTR_FIELD_ACL_RANGE_TYPE": - assert set(list_attrs) == set(["SAI_ACL_RANGE_TYPE_L4_DST_PORT_RANGE", "SAI_ACL_RANGE_TYPE_L4_SRC_PORT_RANGE"]) - elif key == "SAI_ACL_TABLE_ATTR_ACL_BIND_POINT_TYPE_LIST": - assert set(list_attrs) == set(["SAI_ACL_BIND_POINT_TYPE_PORT", "SAI_ACL_BIND_POINT_TYPE_LAG"]) - else: - print("Encountered unexpected range attribute on mirror table: {}".format(key)) - assert False - elif key == "SAI_ACL_TABLE_ATTR_ACL_STAGE": - assert value == "SAI_ACL_STAGE_INGRESS" - else: - print("Encountered unexpected attribute on mirror table: {}".format(key)) - assert False - - # Delete the V6 table - self.remove_acl_table(acl_table_v6) - - def test_CreateMirrorIngressAndEgress(self, dvs, testlog): - self.setup_db(dvs) - asic_db = dvs.get_asic_db() - - ingress_table = "INGRESS_TABLE" - duplicate_ingress_table = "INGRESS_TABLE_2" - ports = ["Ethernet0", "Ethernet4"] - - # Create the table - self.create_acl_table(ingress_table, ports, "MIRROR") - - # Check that the table has been created - table_ids = asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE", - len(asic_db.default_acl_tables) + 1) - table_entries = [oid for oid in table_ids if oid not in asic_db.default_acl_tables] - original_entry = table_entries[0] - - # Attempt to create another MIRROR table with ingress ACLs - self.create_acl_table(duplicate_ingress_table, ports, "MIRROR") - - # Check that there is still only one table, and that it is the original table - table_ids = asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE", - len(asic_db.default_acl_tables) + 1) - table_entries = [oid for oid in table_ids if oid not in asic_db.default_acl_tables] - assert table_entries[0] == original_entry - - egress_table = "EGRESS_TABLE" - duplicate_egress_table = "EGRESS_TABLE_2" - - # Create the egress table - self.create_acl_table(egress_table, ports, "MIRROR", "egress") - - # Check that there are two tables - asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE", - len(asic_db.default_acl_tables) + 2) - - # Attempt to create another MIRROR table with egress ACLs - self.create_acl_table(duplicate_egress_table, ports, "MIRROR", "egress") - - # Check that there are still only two tables - asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE", - len(asic_db.default_acl_tables) + 2) - - self.remove_acl_table(ingress_table) - self.remove_acl_table(egress_table) - self.remove_acl_table(duplicate_ingress_table) - self.remove_acl_table(duplicate_egress_table) - - asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE", len(asic_db.default_acl_tables)) - - # Test case - create a MIRROR table and a MIRRORV6 table in separated mode - # 0. predefine the VS platform: mellanox platform - # 1. create a mirror session - # 2. create two ACL tables that support IPv4 and IPv6 separatedly - # 3. create two ACL rules with both IPv4 and IPv6 source and destination IP - # verify the ACL rules are created successfully - # 4. remove all the configurations - def test_AclBindMirrorSeparated(self, dvs, testlog): - """ - This test verifies IPv6 rules cannot be inserted into MIRROR table - """ - self.setup_db(dvs) - - session = "MIRROR_SESSION" - acl_table = "MIRROR_TABLE" - acl_table_v6 = "MIRROR_TABLE_V6" - acl_rule_1 = "MIRROR_RULE_1" - acl_rule_2 = "MIRROR_RULE_2" - - # bring up port; assign ip; create neighbor; create route - self.set_interface_status("Ethernet32", "up") - self.add_ip_address("Ethernet32", "20.0.0.0/31") - self.add_neighbor("Ethernet32", "20.0.0.1", "02:04:06:08:10:12") - self.add_route(dvs, "4.4.4.4", "20.0.0.1") - - # create mirror session - self.create_mirror_session(session, "3.3.3.3", "4.4.4.4", "0x6558", "8", "100", "0") - assert self.get_mirror_session_state(session)["status"] == "active" - - # assert mirror session in asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - assert len(tbl.getKeys()) == 1 - mirror_session_oid = tbl.getKeys()[0] - - # create acl table ipv4 - self.create_acl_table(acl_table, ["Ethernet0", "Ethernet4"], "MIRROR") - - # assert acl table ipv4 is created - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE") - table_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_tables] - assert len(table_entries) == 1 - - table_id_v4 = table_entries[0] - - # create acl table ipv6 - self.create_acl_table(acl_table_v6, ["Ethernet0", "Ethernet4"], "MIRRORV6") - - # assert acl table ipv6 is created - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE") - table_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_tables] - assert len(table_entries) == 2 - - table_id_v6 = table_entries[1] if table_entries[0] == table_id_v4 else table_entries[0] - - # create acl rule with IPv4 addresses - self.create_mirror_acl_ipv4_rule(acl_table, acl_rule_1, session) - - # assert acl rule ipv4 is created - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") - rule_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_entries] - assert len(rule_entries) == 1 - - rule_id_v4 = rule_entries[0] - - # assert acl rule is assocaited with table ipv4 - (status, fvs) = tbl.get(rule_id_v4) - assert status == True - for fv in fvs: - if fv[0] == "SAI_ACL_ENTRY_ATTR_TABLE_ID": - assert fv[1] == table_id_v4 - - # create acl rule with IPv6 addresses - self.create_mirror_acl_ipv6_rule(acl_table_v6, acl_rule_2, session) - - # assert acl rule ipv6 is created - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") - rule_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_entries] - assert len(rule_entries) == 2 - - rule_id_v6 = rule_entries[1] if rule_entries[0] == rule_id_v4 else rule_entries[0] - - # assert acl rule is associated with table ipv6 - (status, fvs) = tbl.get(rule_id_v6) - assert status == True - for fv in fvs: - if fv[0] == "SAI_ACL_ENTRY_ATTR_TABLE_ID": - assert fv[1] == table_id_v6 - - # remove acl rule - self.remove_mirror_acl_rule(acl_table, acl_rule_1) - self.remove_mirror_acl_rule(acl_table_v6, acl_rule_2) - - # remove acl table - self.remove_acl_table(acl_table) - self.remove_acl_table(acl_table_v6) - - # remove mirror session - self.remove_mirror_session(session) - - # assert no mirror session in asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - assert len(tbl.getKeys()) == 0 - - # remove route; remove neighbor; remove ip; bring down port - self.remove_route(dvs, "4.4.4.4") - self.remove_neighbor("Ethernet32", "20.0.0.1") - self.remove_ip_address("Ethernet32", "20.0.0.0/31") - self.set_interface_status("Ethernet32", "down") - - # Test case - intervene rule creation in table creation - # 0. predefine the VS platform: mellanox platform - # 1. create a mirror session - # 2. create the ipv4 ACL table - # 3. create the ipv4 ACL rule - # 4. create the ipv6 ACL table - # 5. create the ipv6 ACL rule - # 6. verify two rules are inserted successfully - def test_AclBindMirrorV6Reorder1(self, dvs, testlog): - """ - This test verifies IPv6 rules cannot be inserted into MIRROR table - """ - self.setup_db(dvs) - - session = "MIRROR_SESSION" - acl_table = "MIRROR_TABLE" - acl_table_v6 = "MIRROR_TABLE_V6" - acl_rule_1 = "MIRROR_RULE_1" - acl_rule_2 = "MIRROR_RULE_2" - - # bring up port; assign ip; create neighbor; create route - self.set_interface_status("Ethernet32", "up") - self.add_ip_address("Ethernet32", "20.0.0.0/31") - self.add_neighbor("Ethernet32", "20.0.0.1", "02:04:06:08:10:12") - self.add_route(dvs, "4.4.4.4", "20.0.0.1") - - # create mirror session - self.create_mirror_session(session, "3.3.3.3", "4.4.4.4", "0x6558", "8", "100", "0") - assert self.get_mirror_session_state(session)["status"] == "active" - - # assert mirror session in asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - assert len(tbl.getKeys()) == 1 - mirror_session_oid = tbl.getKeys()[0] - - # create acl table ipv4 - self.create_acl_table(acl_table, ["Ethernet0", "Ethernet4"], "MIRROR") - - # create acl rule with IPv4 addresses - self.create_mirror_acl_ipv4_rule(acl_table, acl_rule_1, session) - - # create acl table ipv6 - self.create_acl_table(acl_table_v6, ["Ethernet0", "Ethernet4"], "MIRRORV6") - - # create acl rule with IPv6 addresses - self.create_mirror_acl_ipv6_rule(acl_table_v6, acl_rule_2, session) - - # assert acl rules are created - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") - rule_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_entries] - assert len(rule_entries) == 2 - - # remove acl rule - self.remove_mirror_acl_rule(acl_table, acl_rule_1) - self.remove_mirror_acl_rule(acl_table_v6, acl_rule_2) - - # remove acl table - self.remove_acl_table(acl_table) - self.remove_acl_table(acl_table_v6) - - # remove mirror session - self.remove_mirror_session(session) - - # assert no mirror session in asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - assert len(tbl.getKeys()) == 0 - - # remove route; remove neighbor; remove ip; bring down port - self.remove_route(dvs, "4.4.4.4") - self.remove_neighbor("Ethernet32", "20.0.0.1") - self.remove_ip_address("Ethernet32", "20.0.0.0/31") - self.set_interface_status("Ethernet32", "down") - - - # Test case - intervene rule creation in table creation - # 0. predefine the VS platform: mellanox platform - # 1. create a mirror session - # 2. create the ipv4 ACL table - # 3. create the ipv6 ACL rule - # 4. create the ipv6 ACL table - # 5. create the ipv4 ACL rule - # 6. verify two rules are inserted successfully - def test_AclBindMirrorV6Reorder2(self, dvs, testlog): - """ - This test verifies IPv6 rules cannot be inserted into MIRROR table - """ - self.setup_db(dvs) - - session = "MIRROR_SESSION" - acl_table = "MIRROR_TABLE" - acl_table_v6 = "MIRROR_TABLE_V6" - acl_rule_1 = "MIRROR_RULE_1" - acl_rule_2 = "MIRROR_RULE_2" - - # bring up port; assign ip; create neighbor; create route - self.set_interface_status("Ethernet32", "up") - self.add_ip_address("Ethernet32", "20.0.0.0/31") - self.add_neighbor("Ethernet32", "20.0.0.1", "02:04:06:08:10:12") - self.add_route(dvs, "4.4.4.4", "20.0.0.1") - - # create mirror session - self.create_mirror_session(session, "3.3.3.3", "4.4.4.4", "0x6558", "8", "100", "0") - assert self.get_mirror_session_state(session)["status"] == "active" - - # assert mirror session in asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - assert len(tbl.getKeys()) == 1 - mirror_session_oid = tbl.getKeys()[0] - - # create acl table ipv4 - self.create_acl_table(acl_table, ["Ethernet0", "Ethernet4"], "MIRROR") - - # create acl rule with IPv6 addresses - self.create_mirror_acl_ipv6_rule(acl_table_v6, acl_rule_2, session) - - # assert acl rule is not created - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") - rule_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_entries] - assert len(rule_entries) == 0 - - # create acl table ipv6 - self.create_acl_table(acl_table_v6, ["Ethernet0", "Ethernet4"], "MIRRORV6") - - # create acl rule with IPv4 addresses - self.create_mirror_acl_ipv4_rule(acl_table, acl_rule_1, session) - - # assert acl rules are created - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") - rule_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_entries] - assert len(rule_entries) == 2 - - # remove acl rule - self.remove_mirror_acl_rule(acl_table, acl_rule_1) - self.remove_mirror_acl_rule(acl_table_v6, acl_rule_2) - - # remove acl table - self.remove_acl_table(acl_table) - self.remove_acl_table(acl_table_v6) - - # remove mirror session - self.remove_mirror_session(session) - - # assert no mirror session in asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - assert len(tbl.getKeys()) == 0 - - # remove route; remove neighbor; remove ip; bring down port - self.remove_route(dvs, "4.4.4.4") - self.remove_neighbor("Ethernet32", "20.0.0.1") - self.remove_ip_address("Ethernet32", "20.0.0.0/31") - self.set_interface_status("Ethernet32", "down") - - - # Test case - create ACL rules associated with wrong table - # 0. predefine the VS platform: mellanox platform - # 1. create a mirror session - # 2. create the ipv4 ACL table - # 3. create the ipv6 ACL rule associated with ipv4 table - # 4. create the ipv6 ACL table - # 5. create the ipv4 ACL rule associated with ipv6 table - # 6. verify two rules are inserted successfully - def test_AclBindMirrorV6WrongConfig(self, dvs, testlog): - """ - This test verifies IPv6 rules cannot be inserted into MIRROR table - """ - self.setup_db(dvs) - - session = "MIRROR_SESSION" - acl_table = "MIRROR_TABLE" - acl_table_v6 = "MIRROR_TABLE_V6" - acl_rule_1 = "MIRROR_RULE_1" - acl_rule_2 = "MIRROR_RULE_2" - - # bring up port; assign ip; create neighbor; create route - self.set_interface_status("Ethernet32", "up") - self.add_ip_address("Ethernet32", "20.0.0.0/31") - self.add_neighbor("Ethernet32", "20.0.0.1", "02:04:06:08:10:12") - self.add_route(dvs, "4.4.4.4", "20.0.0.1") - - # create mirror session - self.create_mirror_session(session, "3.3.3.3", "4.4.4.4", "0x6558", "8", "100", "0") - assert self.get_mirror_session_state(session)["status"] == "active" - - # assert mirror session in asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - assert len(tbl.getKeys()) == 1 - mirror_session_oid = tbl.getKeys()[0] - - # create acl table ipv4 - self.create_acl_table(acl_table, ["Ethernet0", "Ethernet4"], "MIRROR") - - # create WRONG acl rule with IPv6 addresses - self.create_mirror_acl_ipv6_rule(acl_table, acl_rule_2, session) - - # assert acl rule is not created - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") - rule_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_entries] - assert len(rule_entries) == 0 - - # create acl table ipv6 - self.create_acl_table(acl_table_v6, ["Ethernet0", "Ethernet4"], "MIRRORV6") - - # create WRONG acl rule with IPv4 addresses - self.create_mirror_acl_ipv4_rule(acl_table_v6, acl_rule_1, session) - - # assert acl rules are created - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") - rule_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_entries] - assert len(rule_entries) == 0 - - # remove acl rule - self.remove_mirror_acl_rule(acl_table, acl_rule_1) - self.remove_mirror_acl_rule(acl_table_v6, acl_rule_2) - - # remove acl table - self.remove_acl_table(acl_table) - self.remove_acl_table(acl_table_v6) - - # remove mirror session - self.remove_mirror_session(session) - - # assert no mirror session in asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - assert len(tbl.getKeys()) == 0 - - # remove route; remove neighbor; remove ip; bring down port - self.remove_route(dvs, "4.4.4.4") - self.remove_neighbor("Ethernet32", "20.0.0.1") - self.remove_ip_address("Ethernet32", "20.0.0.0/31") - self.set_interface_status("Ethernet32", "down") - - - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_mirror_policer.py b/tests/test_mirror_policer.py deleted file mode 100644 index 2daf74d21f..0000000000 --- a/tests/test_mirror_policer.py +++ /dev/null @@ -1,246 +0,0 @@ -# This test suite covers the functionality of mirror feature in SwSS -import platform -import pytest -import time - -from swsscommon import swsscommon -from distutils.version import StrictVersion - - -class TestMirror(object): - def setup_db(self, dvs): - self.pdb = swsscommon.DBConnector(0, dvs.redis_sock, 0) - self.adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - self.cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) - self.sdb = swsscommon.DBConnector(6, dvs.redis_sock, 0) - - def set_port_status(self, port, admin_status): - tbl = swsscommon.Table(self.cdb, "PORT") - fvs = swsscommon.FieldValuePairs([("admin_status", "up")]) - tbl.set(port, fvs) - time.sleep(1) - - def add_ip_address(self, interface, ip): - tbl = swsscommon.Table(self.cdb, "INTERFACE") - fvs = swsscommon.FieldValuePairs([("NULL", "NULL")]) - tbl.set(interface, fvs) - tbl.set(interface + "|" + ip, fvs) - time.sleep(1) - - def remove_ip_address(self, interface, ip): - tbl = swsscommon.Table(self.cdb, "INTERFACE") - tbl._del(interface + "|" + ip) - tbl._del(interface) - time.sleep(1) - - def add_neighbor(self, interface, ip, mac): - tbl = swsscommon.ProducerStateTable(self.pdb, "NEIGH_TABLE") - fvs = swsscommon.FieldValuePairs([("neigh", mac), - ("family", "IPv4")]) - tbl.set(interface + ":" + ip, fvs) - time.sleep(1) - - def remove_neighbor(self, interface, ip): - tbl = swsscommon.ProducerStateTable(self.pdb, "NEIGH_TABLE") - tbl._del(interface + ":" + ip) - time.sleep(1) - - def add_route(self, dvs, prefix, nexthop): - dvs.runcmd("ip route add " + prefix + " via " + nexthop) - time.sleep(1) - - def remove_route(self, dvs, prefix): - dvs.runcmd("ip route del " + prefix) - time.sleep(1) - - def create_mirror_session(self, name, src, dst, gre, dscp, ttl, queue, policer): - tbl = swsscommon.Table(self.cdb, "MIRROR_SESSION") - fvs = swsscommon.FieldValuePairs([("src_ip", src), - ("dst_ip", dst), - ("gre_type", gre), - ("dscp", dscp), - ("ttl", ttl), - ("queue", queue), - ("policer", policer)]) - tbl.set(name, fvs) - time.sleep(1) - - def remove_mirror_session(self, name): - tbl = swsscommon.Table(self.cdb, "MIRROR_SESSION") - tbl._del(name) - time.sleep(1) - - def create_policer(self, name): - tbl = swsscommon.Table(self.cdb, "POLICER") - fvs = swsscommon.FieldValuePairs([("meter_type", "packets"), - ("mode", "sr_tcm"), - ("cir", "600"), - ("cbs", "600"), - ("red_packet_action", "drop")]) - tbl.set(name, fvs) - time.sleep(1) - - def remove_policer(self, name): - tbl = swsscommon.Table(self.cdb, "POLICER") - tbl._del(name) - time.sleep(1) - - def test_MirrorPolicer(self, dvs, testlog): - self.setup_db(dvs) - - session = "MIRROR_SESSION" - policer= "POLICER" - - # create policer - self.create_policer(policer) - - # create mirror session - self.create_mirror_session(session, "3.3.3.3", "2.2.2.2", "0x6558", "8", "100", "0", policer) - self.set_port_status("Ethernet16", "up") - self.add_ip_address("Ethernet16", "10.0.0.0/31") - self.add_neighbor("Ethernet16", "10.0.0.1", "02:04:06:08:10:12") - self.add_route(dvs, "2.2.2.2", "10.0.0.1") - - # check asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_POLICER") - policer_entries = [p for p in tbl.getKeys() if p not in dvs.asicdb.default_copp_policers] - assert len(policer_entries) == 1 - policer_oid = policer_entries[0] - - # check asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - mirror_entries = tbl.getKeys() - assert len(mirror_entries) == 1 - - (status, fvs) = tbl.get(mirror_entries[0]) - assert status == True - assert len(fvs) == 12 - for fv in fvs: - if fv[0] == "SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": - assert dvs.asicdb.portoidmap[fv[1]] == "Ethernet16" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_TYPE": - assert fv[1] == "SAI_MIRROR_SESSION_TYPE_ENHANCED_REMOTE" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_ERSPAN_ENCAPSULATION_TYPE": - assert fv[1] == "SAI_ERSPAN_ENCAPSULATION_TYPE_MIRROR_L3_GRE_TUNNEL" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_IPHDR_VERSION": - assert fv[1] == "4" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_TOS": - assert fv[1] == "32" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_TTL": - assert fv[1] == "100" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_SRC_IP_ADDRESS": - assert fv[1] == "3.3.3.3" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_DST_IP_ADDRESS": - assert fv[1] == "2.2.2.2" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_SRC_MAC_ADDRESS": - assert fv[1] == dvs.runcmd("bash -c \"ip link show eth0 | grep ether | awk '{print $2}'\"")[1].strip().upper() - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS": - assert fv[1] == "02:04:06:08:10:12" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_GRE_PROTOCOL_TYPE": - assert fv[1] == "25944" # 0x6558 - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_POLICER": - assert fv[1] == policer_oid - else: - assert False - - # remove mirror session - self.remove_route(dvs, "2.2.2.2") - self.remove_neighbor("Ethernet16", "10.0.0.1") - self.remove_ip_address("Ethernet16", "10.0.0.0/31") - self.set_port_status("Ethernet16", "down") - self.remove_mirror_session(session) - - # remove policer - self.remove_policer(policer) - - - def create_acl_table(self, table, interfaces): - tbl = swsscommon.Table(self.cdb, "ACL_TABLE") - fvs = swsscommon.FieldValuePairs([("policy_desc", "mirror_test"), - ("type", "mirror"), - ("ports", ",".join(interfaces))]) - tbl.set(table, fvs) - time.sleep(1) - - def remove_acl_table(self, table): - tbl = swsscommon.Table(self.cdb, "ACL_TABLE") - tbl._del(table) - time.sleep(1) - - def create_mirror_acl_dscp_rule(self, table, rule, dscp, session): - tbl = swsscommon.Table(self.cdb, "ACL_RULE") - fvs = swsscommon.FieldValuePairs([("priority", "1000"), - ("mirror_action", session), - ("DSCP", dscp)]) - tbl.set(table + "|" + rule, fvs) - time.sleep(1) - - def remove_mirror_acl_dscp_rule(self, table, rule): - tbl = swsscommon.Table(self.cdb, "ACL_RULE") - tbl._del(table + "|" + rule) - time.sleep(1) - - def test_MirrorPolicerWithAcl(self, dvs, testlog): - self.setup_db(dvs) - - session = "MIRROR_SESSION" - policer= "POLICER" - acl_table = "MIRROR_TABLE" - acl_rule = "MIRROR_RULE" - - # create policer - self.create_policer(policer) - - # create mirror session - self.create_mirror_session(session, "3.3.3.3", "2.2.2.2", "0x6558", "8", "100", "0", policer) - self.set_port_status("Ethernet16", "up") - self.add_ip_address("Ethernet16", "10.0.0.0/31") - self.add_neighbor("Ethernet16", "10.0.0.1", "02:04:06:08:10:12") - self.add_route(dvs, "2.2.2.2", "10.0.0.1") - - # check asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - mirror_entries = tbl.getKeys() - assert len(mirror_entries) == 1 - mirror_oid = mirror_entries[0] - - # create acl table - self.create_acl_table(acl_table, ["Ethernet0", "Ethernet4"]) - - # create acl rule with dscp value and mask - self.create_mirror_acl_dscp_rule(acl_table, acl_rule, "8/56", session) - - # assert acl rule is created - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") - rule_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_entries] - assert len(rule_entries) == 1 - - (status, fvs) = tbl.get(rule_entries[0]) - assert status == True - for fv in fvs: - if fv[0] == "SAI_ACL_ENTRY_ATTR_FIELD_DSCP": - assert fv[1] == "8&mask:0x38" - if fv[0] == "SAI_ACL_ENTRY_ATTR_ACTION_MIRROR_INGRESS": - assert fv[1] == "1:" + mirror_oid - - # remove acl rule - self.remove_mirror_acl_dscp_rule(acl_table, acl_rule) - - # remove acl table - self.remove_acl_table(acl_table) - - # remove mirror session - self.remove_route(dvs, "2.2.2.2") - self.remove_neighbor("Ethernet16", "10.0.0.1") - self.remove_ip_address("Ethernet16", "10.0.0.0/31") - self.set_port_status("Ethernet16", "down") - self.remove_mirror_session(session) - - # remove policer - self.remove_policer(policer) - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_mirror_port_erspan.py b/tests/test_mirror_port_erspan.py deleted file mode 100644 index 61c0a17cd3..0000000000 --- a/tests/test_mirror_port_erspan.py +++ /dev/null @@ -1,581 +0,0 @@ -# This test suite covers the functionality of mirror feature in SwSS -import pytest - -@pytest.mark.usefixtures("testlog") -@pytest.mark.usefixtures('dvs_vlan_manager') -@pytest.mark.usefixtures('dvs_lag_manager') -@pytest.mark.usefixtures('dvs_mirror_manager') - -class TestMirror(object): - def test_PortMirrorERSpanAddRemove(self, dvs, testlog): - """ - This test covers the basic ERSPANmirror session creation and removal operations - Operation flow: - 1. Create mirror session with source ports. - The session remains inactive because no nexthop/neighbor exists - 2. Bring up port; assign IP; create neighbor; create route - The session remains inactive until the route is created - 3. Verify that port mirror config is proper. - 4. Remove route; remove neighbor; remove IP; bring down port - The session becomes inactive again till the end - """ - dvs.setup_db() - pmap = dvs.counters_db.get_entry("COUNTERS_PORT_NAME_MAP", "") - pmap = dict(pmap) - - session = "TEST_SESSION" - src_ports = "Ethernet12" - src_asic_ports = ["Ethernet12"] - - # create mirror session - self.dvs_mirror.create_erspan_session(session, "1.1.1.1", "2.2.2.2", "0x6558", "8", "100", "0", None, src_ports) - self.dvs_mirror.verify_session_status(session, status="inactive") - - # bring up Ethernet16 - dvs.set_interface_status("Ethernet16", "up") - self.dvs_mirror.verify_session_status(session, status="inactive") - - # add IP address to Ethernet16 - dvs.add_ip_address("Ethernet16", "10.0.0.0/30") - self.dvs_mirror.verify_session_status(session, status="inactive") - - # add neighbor to Ethernet16 - dvs.add_neighbor("Ethernet16", "10.0.0.1", "02:04:06:08:10:12") - self.dvs_mirror.verify_session_status(session, status="inactive") - - # add another neighbor to Ethernet16 - dvs.add_neighbor("Ethernet16", "10.0.0.2", "02:04:06:08:10:13") - self.dvs_mirror.verify_session_status(session, status="inactive") - - # add route to mirror destination via 10.0.0.1 - dvs.add_route("2.2.2.2", "10.0.0.1") - src_mac = dvs.runcmd("bash -c \"ip link show eth0 | grep ether | awk '{print $2}'\"")[1].strip().upper() - expected_asic_db = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": pmap.get("Ethernet16"), - "SAI_MIRROR_SESSION_ATTR_TYPE": "SAI_MIRROR_SESSION_TYPE_ENHANCED_REMOTE", - "SAI_MIRROR_SESSION_ATTR_ERSPAN_ENCAPSULATION_TYPE": "SAI_ERSPAN_ENCAPSULATION_TYPE_MIRROR_L3_GRE_TUNNEL", - "SAI_MIRROR_SESSION_ATTR_IPHDR_VERSION": "4", - "SAI_MIRROR_SESSION_ATTR_TOS": "32", - "SAI_MIRROR_SESSION_ATTR_TTL": "100", - "SAI_MIRROR_SESSION_ATTR_SRC_IP_ADDRESS": "1.1.1.1", - "SAI_MIRROR_SESSION_ATTR_DST_IP_ADDRESS": "2.2.2.2", - "SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS": "02:04:06:08:10:12", - "SAI_MIRROR_SESSION_ATTR_SRC_MAC_ADDRESS": src_mac, - "SAI_MIRROR_SESSION_ATTR_GRE_PROTOCOL_TYPE": "25944"} - - expected_state_db = {"status": "active", - "monitor_port": "Ethernet16", - "dst_mac": "02:04:06:08:10:12", - "route_prefix": "2.2.2.2/32", - "next_hop_ip": "10.0.0.1@Ethernet16"} - - self.dvs_mirror.verify_session_status(session) - self.dvs_mirror.verify_session(dvs, session, asic_db=expected_asic_db, state_db=expected_state_db, src_ports=src_asic_ports, asic_size=11) - # change route to mirror destination via 10.0.0.2 - dvs.change_route("2.2.2.2", "10.0.0.2") - expected_asic_db = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": pmap.get("Ethernet16"), - "SAI_MIRROR_SESSION_ATTR_TYPE": "SAI_MIRROR_SESSION_TYPE_ENHANCED_REMOTE", - "SAI_MIRROR_SESSION_ATTR_ERSPAN_ENCAPSULATION_TYPE": "SAI_ERSPAN_ENCAPSULATION_TYPE_MIRROR_L3_GRE_TUNNEL", - "SAI_MIRROR_SESSION_ATTR_IPHDR_VERSION": "4", - "SAI_MIRROR_SESSION_ATTR_TOS": "32", - "SAI_MIRROR_SESSION_ATTR_TTL": "100", - "SAI_MIRROR_SESSION_ATTR_SRC_IP_ADDRESS": "1.1.1.1", - "SAI_MIRROR_SESSION_ATTR_DST_IP_ADDRESS": "2.2.2.2", - "SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS": "02:04:06:08:10:13", - "SAI_MIRROR_SESSION_ATTR_SRC_MAC_ADDRESS": src_mac, - "SAI_MIRROR_SESSION_ATTR_GRE_PROTOCOL_TYPE": "25944"} - - expected_state_db = {"status": "active", - "monitor_port": "Ethernet16", - "dst_mac": "02:04:06:08:10:13", - "route_prefix": "2.2.2.2/32", - "next_hop_ip": "10.0.0.2@Ethernet16"} - - self.dvs_mirror.verify_session_status(session) - self.dvs_mirror.verify_session(dvs, session, asic_db=expected_asic_db, state_db=expected_state_db, src_ports=src_asic_ports, asic_size=11) - - # remove route - dvs.remove_route("2.2.2.2") - self.dvs_mirror.verify_session_status(session, status="inactive") - - # remove neighbor - dvs.remove_neighbor("Ethernet16", "10.0.0.1") - self.dvs_mirror.verify_session_status(session, status="inactive") - dvs.remove_neighbor("Ethernet16", "10.0.0.2") - self.dvs_mirror.verify_session_status(session, status="inactive") - - # remove IP address - dvs.remove_ip_address("Ethernet16", "10.0.0.0/30") - self.dvs_mirror.verify_session_status(session, status="inactive") - - # bring down Ethernet16 - dvs.set_interface_status("Ethernet16", "down") - self.dvs_mirror.verify_session_status(session, status="inactive") - - # remove mirror session - self.dvs_mirror.remove_mirror_session(session) - self.dvs_mirror.verify_no_mirror() - - def test_PortMirrorToVlanAddRemove(self, dvs, testlog): - """ - This test covers basic mirror session creation and removal operation - with destination port sits in a VLAN - Opeartion flow: - 1. Create mirror session with source ports. - 2. Create VLAN; assign IP; create neighbor; create FDB - The session should be up only at this time. - verify source port mirror config. - 3. Remove FDB; remove neighbor; remove IP; remove VLAN - 4. Remove mirror session - """ - dvs.setup_db() - pmap = dvs.counters_db.get_entry("COUNTERS_PORT_NAME_MAP", "") - pmap = dict(pmap) - - session = "TEST_SESSION" - src_ports = "Ethernet12,Ethernet16" - src_asic_ports = ["Ethernet12", "Ethernet16"] - vlan_id = "10" - vlan = "Vlan10" - - # create mirror session - self.dvs_mirror.create_erspan_session(session, "5.5.5.5", "6.6.6.6", "0x6558", "8", "100", "0", None, src_ports, direction="TX") - self.dvs_mirror.verify_session_status(session, status="inactive") - - # create vlan; create vlan member - self.dvs_vlan.create_vlan(vlan_id) - self.dvs_vlan.create_vlan_member(vlan_id, "Ethernet4") - - # bring up vlan and member - dvs.set_interface_status(vlan, "up") - dvs.set_interface_status("Ethernet4", "up") - - # add ip address to vlan 6 - dvs.add_ip_address(vlan, "6.6.6.0/24") - self.dvs_mirror.verify_session_status(session, status="inactive") - - # create neighbor to vlan 6 - dvs.add_neighbor(vlan, "6.6.6.6", "66:66:66:66:66:66") - self.dvs_mirror.verify_session_status(session, status="inactive") - - # create fdb entry to ethernet4 - dvs.create_fdb(vlan_id, "66-66-66-66-66-66", "Ethernet4") - self.dvs_mirror.verify_session_status(session) - - src_mac = dvs.runcmd("bash -c \"ip link show eth0 | grep ether | awk '{print $2}'\"")[1].strip().upper() - expected_asic_db = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": pmap.get("Ethernet4"), - "SAI_MIRROR_SESSION_ATTR_TYPE": "SAI_MIRROR_SESSION_TYPE_ENHANCED_REMOTE", - "SAI_MIRROR_SESSION_ATTR_ERSPAN_ENCAPSULATION_TYPE": "SAI_ERSPAN_ENCAPSULATION_TYPE_MIRROR_L3_GRE_TUNNEL", - "SAI_MIRROR_SESSION_ATTR_IPHDR_VERSION": "4", - "SAI_MIRROR_SESSION_ATTR_TOS": "32", - "SAI_MIRROR_SESSION_ATTR_TTL": "100", - "SAI_MIRROR_SESSION_ATTR_SRC_IP_ADDRESS": "5.5.5.5", - "SAI_MIRROR_SESSION_ATTR_DST_IP_ADDRESS": "6.6.6.6", - "SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS": "66:66:66:66:66:66", - "SAI_MIRROR_SESSION_ATTR_SRC_MAC_ADDRESS": src_mac, - "SAI_MIRROR_SESSION_ATTR_GRE_PROTOCOL_TYPE": "25944", - "SAI_MIRROR_SESSION_ATTR_VLAN_HEADER_VALID": "true", - "SAI_MIRROR_SESSION_ATTR_VLAN_TPID": "33024", - "SAI_MIRROR_SESSION_ATTR_VLAN_ID": vlan_id, - "SAI_MIRROR_SESSION_ATTR_VLAN_PRI": "0", - "SAI_MIRROR_SESSION_ATTR_VLAN_CFI": "0"} - self.dvs_mirror.verify_session(dvs, session, asic_db=expected_asic_db, src_ports=src_asic_ports, asic_size=16, direction="TX") - - # remove fdb entry - dvs.remove_fdb(vlan_id, "66-66-66-66-66-66") - self.dvs_mirror.verify_session_status(session, status="inactive") - - # remove neighbor - dvs.remove_neighbor(vlan, "6.6.6.6") - self.dvs_mirror.verify_session_status(session, status="inactive") - - # remove ip address - dvs.remove_ip_address(vlan, "6.6.6.0/24") - self.dvs_mirror.verify_session_status(session, status="inactive") - - # bring down vlan and member - dvs.set_interface_status("Ethernet4", "down") - dvs.set_interface_status(vlan, "down") - - # remove vlan member; remove vlan - self.dvs_vlan.remove_vlan_member(vlan_id, "Ethernet4") - self.dvs_vlan.get_and_verify_vlan_member_ids(0) - self.dvs_vlan.remove_vlan(vlan_id) - - # remove mirror session - self.dvs_mirror.remove_mirror_session(session) - self.dvs_mirror.verify_no_mirror() - - def test_PortMirrorToLagAddRemove(self, dvs, testlog): - """ - This test covers basic mirror session creation and removal operations - with destination port sits in a LAG - Operation flow: - 1. Create mirror sesion with source ports, direction - 2. Create LAG; assign IP; create directly connected neighbor - The session shoudl be up only at this time. - 3. Remove neighbor; remove IP; remove LAG - 4. Remove mirror session - - """ - dvs.setup_db() - pmap = dvs.counters_db.get_entry("COUNTERS_PORT_NAME_MAP", "") - pmap = dict(pmap) - - session = "TEST_SESSION" - src_ports = "Ethernet0,Ethernet4" - src_asic_ports = ["Ethernet0", "Ethernet4"] - - # create mirror session - self.dvs_mirror.create_erspan_session(session, "10.10.10.10", "11.11.11.11", "0x6558", - "8", "100", "0", None, src_ports, "TX") - self.dvs_mirror.verify_session_status(session, status="inactive") - - # create port channel; create port channel member - self.dvs_lag.create_port_channel("008") - lag_entries = self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG", 1) - self.dvs_lag.create_port_channel_member("008", "Ethernet88") - - # Verify the LAG has been initialized properly - lag_member_entries = self.dvs_lag.get_and_verify_port_channel_members(1) - fvs = self.dvs_vlan.asic_db.wait_for_entry("ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER", lag_member_entries[0]) - assert len(fvs) == 4 - assert fvs.get("SAI_LAG_MEMBER_ATTR_LAG_ID") == lag_entries[0] - assert self.dvs_vlan.asic_db.port_to_id_map[fvs.get("SAI_LAG_MEMBER_ATTR_PORT_ID")] == "Ethernet88" - - # bring up port channel and port channel member - dvs.set_interface_status("PortChannel008", "up") - dvs.set_interface_status("Ethernet88", "up") - - # add ip address to port channel 008 - dvs.add_ip_address("PortChannel008", "11.11.11.0/24") - self.dvs_mirror.verify_session_status(session, status="inactive") - - # create neighbor to port channel 008 - dvs.add_neighbor("PortChannel008", "11.11.11.11", "88:88:88:88:88:88") - self.dvs_mirror.verify_session_status(session) - - # Check src_port state. - expected_asic_db = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": pmap.get("Ethernet88"), - "SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS": "88:88:88:88:88:88"} - - self.dvs_mirror.verify_session(dvs, session, asic_db=expected_asic_db, src_ports=src_asic_ports, direction="TX") - - # remove neighbor - dvs.remove_neighbor("PortChannel008", "11.11.11.11") - self.dvs_mirror.verify_session_status(session, status="inactive") - - # remove ip address - dvs.remove_ip_address("PortChannel008", "11.11.11.0/24") - self.dvs_mirror.verify_session_status(session, status="inactive") - - # bring down port channel and port channel member - dvs.set_interface_status("PortChannel008", "down") - dvs.set_interface_status("Ethernet88", "down") - - # remove port channel member; remove port channel - - self.dvs_lag.remove_port_channel_member("008", "Ethernet88") - self.dvs_lag.remove_port_channel("008") - - # remove mirror session - self.dvs_mirror.remove_mirror_session(session) - self.dvs_mirror.verify_no_mirror() - - def test_PortMirrorDestMoveVlan(self, dvs, testlog): - """ - This test tests mirror session destination move from non-VLAN to VLAN - and back to non-VLAN port - 1. Create mirror session - 2. Enable non-VLAN monitor port - 3. Create VLAN; move to VLAN without FDB entry - 4. Create FDB entry - 5. Remove FDB entry - 6. Remove VLAN; move to non-VLAN - 7. Disable non-VLAN monitor port - 8. Remove mirror session - """ - dvs.setup_db() - pmap = dvs.counters_db.get_entry("COUNTERS_PORT_NAME_MAP", "") - pmap = dict(pmap) - - session = "TEST_SESSION" - src_ports = "Ethernet0" - src_asic_ports = ["Ethernet0"] - - # create mirror session - self.dvs_mirror.create_erspan_session(session, "7.7.7.7", "8.8.8.8", "0x6558", "8", "100", "0", None, src_ports) - self.dvs_mirror.verify_session_status(session, status="inactive") - - # bring up port; add ip; add neighbor; add route - dvs.set_interface_status("Ethernet32", "up") - dvs.add_ip_address("Ethernet32", "80.0.0.0/31") - dvs.add_neighbor("Ethernet32", "80.0.0.1", "02:04:06:08:10:12") - dvs.add_route("8.8.0.0/16", "80.0.0.1") - - self.dvs_mirror.verify_session_status(session) - - # check monitor port - expected_asic_db = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": pmap.get("Ethernet32")} - self.dvs_mirror.verify_session(dvs, session, asic_db=expected_asic_db) - - # mirror session move round 1 - # create vlan; create vlan member; bring up vlan and member - self.dvs_vlan.create_vlan("9") - self.dvs_vlan.create_vlan_member("9", "Ethernet48") - dvs.set_interface_status("Vlan9", "up") - dvs.set_interface_status("Ethernet48", "up") - - self.dvs_mirror.verify_session_status(session) - - # add ip address to vlan 9 - dvs.add_ip_address("Vlan9", "8.8.8.0/24") - self.dvs_mirror.verify_session_status(session, status="inactive") - - # create neighbor to vlan 9 - dvs.add_neighbor("Vlan9", "8.8.8.8", "88:88:88:88:88:88") - self.dvs_mirror.verify_session_status(session, status="inactive") - - # create fdb entry to ethernet48 - dvs.create_fdb("9", "88-88-88-88-88-88", "Ethernet48") - self.dvs_mirror.verify_session_status(session) - - # check monitor port - expected_asic_db = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": pmap.get("Ethernet48"), - "SAI_MIRROR_SESSION_ATTR_VLAN_HEADER_VALID": "true", - "SAI_MIRROR_SESSION_ATTR_VLAN_TPID": "33024", - "SAI_MIRROR_SESSION_ATTR_VLAN_ID": "9", - "SAI_MIRROR_SESSION_ATTR_VLAN_PRI": "0", - "SAI_MIRROR_SESSION_ATTR_VLAN_CFI": "0"} - - self.dvs_mirror.verify_session(dvs, session, asic_db=expected_asic_db, src_ports=src_asic_ports) - - # mirror session move round 2 - # remove fdb entry - dvs.remove_fdb("9", "88-88-88-88-88-88") - self.dvs_mirror.verify_session_status(session, status="inactive") - - # remove neighbor - dvs.remove_neighbor("Vlan9", "8.8.8.8") - self.dvs_mirror.verify_session_status(session, status="inactive") - - # remove ip address - dvs.remove_ip_address("Vlan9", "8.8.8.0/24") - self.dvs_mirror.verify_session_status(session) - - expected_asic_db = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": pmap.get("Ethernet32")} - self.dvs_mirror.verify_session(dvs, session, asic_db=expected_asic_db) - - # bring down vlan and member; remove vlan member; remove vlan - dvs.set_interface_status("Ethernet48", "down") - dvs.set_interface_status("Vlan9", "down") - self.dvs_vlan.remove_vlan_member("9", "Ethernet48") - self.dvs_vlan.get_and_verify_vlan_member_ids(0) - self.dvs_vlan.remove_vlan("9") - - # remove route; remove neighbor; remove ip; bring down port - dvs.remove_route("8.8.8.0/24") - dvs.remove_neighbor("Ethernet32", "80.0.0.1") - dvs.remove_ip_address("Ethernet32", "80.0.0.0/31") - dvs.set_interface_status("Ethernet32", "down") - - # remove mirror session - self.dvs_mirror.remove_mirror_session(session) - self.dvs_mirror.verify_no_mirror() - - - def test_PortMirrorDestMoveLag(self, dvs, testlog): - """ - This test tests mirror session destination move from non-LAG to LAG - and back to non-LAG port - 1. Create mirror session with source ports. - 2. Enable non-LAG monitor port - 3. Create LAG; move to LAG with one member - 4. Remove LAG member - 5. Create LAG member - 6. Remove LAG; move to non-LAG - 7. Disable non-LAG monitor port - 8. Remove mirror session - """ - dvs.setup_db() - pmap = dvs.counters_db.get_entry("COUNTERS_PORT_NAME_MAP", "") - pmap = dict(pmap) - - session = "TEST_SESSION" - src_ports = "Ethernet0,Ethernet4" - src_asic_ports = ["Ethernet0", "Ethernet4"] - # create mirror session - self.dvs_mirror.create_erspan_session(session, "12.12.12.12", "13.13.13.13", "0x6558", "8", "100", "0", None, src_ports, direction="RX") - self.dvs_mirror.verify_session_status(session, status="inactive") - - # bring up port; add ip; add neighbor; add route - dvs.set_interface_status("Ethernet64", "up") - dvs.add_ip_address("Ethernet64", "100.0.0.0/31") - dvs.add_neighbor("Ethernet64", "100.0.0.1", "02:04:06:08:10:12") - dvs.add_route("13.13.0.0/16", "100.0.0.1") - self.dvs_mirror.verify_session_status(session) - - # check monitor port - expected_asic_db = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": pmap.get("Ethernet64"), - "SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS": "02:04:06:08:10:12"} - self.dvs_mirror.verify_session(dvs, session, asic_db=expected_asic_db, src_ports=src_asic_ports, direction="RX") - - # mirror session move round 1 - # create port channel; create port channel member; bring up - self.dvs_lag.create_port_channel("080") - self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG", 1) - self.dvs_lag.create_port_channel_member("080", "Ethernet32") - dvs.set_interface_status("PortChannel080", "up") - dvs.set_interface_status("Ethernet32", "up") - - # add ip address to port channel 080; create neighbor to port channel 080 - dvs.add_ip_address("PortChannel080", "200.0.0.0/31") - dvs.add_neighbor("PortChannel080", "200.0.0.1", "12:10:08:06:04:02") - self.dvs_mirror.verify_session_status(session) - - # add route - dvs.add_route("13.13.13.0/24", "200.0.0.1") - self.dvs_mirror.verify_session_status(session) - - expected_asic_db = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": pmap.get("Ethernet32"), - "SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS": "12:10:08:06:04:02"} - self.dvs_mirror.verify_session(dvs, session, asic_db=expected_asic_db, src_ports=src_asic_ports, direction="RX") - - # mirror session move round 2 - # remove port channel member - self.dvs_lag.remove_port_channel_member("080", "Ethernet32") - self.dvs_mirror.verify_session_status(session) - - # mirror session move round 3 - # create port channel member - self.dvs_lag.create_port_channel_member("080", "Ethernet32") - self.dvs_mirror.verify_session_status(session) - - # check monitor port - expected_asic_db = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": pmap.get("Ethernet32"), - "SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS": "12:10:08:06:04:02"} - self.dvs_mirror.verify_session(dvs, session, asic_db=expected_asic_db, src_ports=src_asic_ports, direction="RX") - - # mirror session move round 4 - # remove route - dvs.remove_route("13.13.13.0/24") - self.dvs_mirror.verify_session_status(session) - - # check monitor port - expected_asic_db = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": pmap.get("Ethernet64"), - "SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS": "02:04:06:08:10:12"} - self.dvs_mirror.verify_session(dvs, session, asic_db=expected_asic_db, src_ports=src_asic_ports, direction="RX") - - # remove neighbor; remove ip address to port channel 080 - dvs.remove_neighbor("PortChannel080", "200.0.0.1") - dvs.remove_ip_address("PortChannel080", "200.0.0.0/31") - - # bring down; remove port channel member; remove port channel - dvs.set_interface_status("Ethernet32", "down") - dvs.set_interface_status("PortChannel080", "down") - self.dvs_lag.remove_port_channel_member("080", "Ethernet32") - self.dvs_lag.remove_port_channel("080") - self.dvs_mirror.verify_session_status(session) - - - # remove route; remove neighbor; remove ip; bring down port - dvs.remove_route("13.13.0.0/16") - dvs.remove_neighbor("Ethernet64", "100.0.0.1") - dvs.remove_ip_address("Ethernet64", "100.0.0.0/31") - dvs.set_interface_status("Ethernet64", "down") - self.dvs_mirror.verify_session_status(session, status="inactive") - - - # remove mirror session - self.dvs_mirror.remove_mirror_session(session) - self.dvs_mirror.verify_no_mirror() - - def test_LAGMirrorToERSPANLagAddRemove(self, dvs, testlog): - """ - This test covers basic LAG mirror session creation and removal operations - with destination port sits in a LAG - Operation flow: - 1. Create source LAG - 2. configure mirror sesion with LAG as source port. - 3. Create destination LAG; assign IP; create directly connected neighbor - The session shoudl be up only at this time. - 4. Remove neighbor; remove IP; remove LAG - 5. Remove mirror session - - """ - dvs.setup_db() - pmap = dvs.counters_db.get_entry("COUNTERS_PORT_NAME_MAP", "") - pmap = dict(pmap) - - session = "TEST_SESSION" - src_port1="Ethernet0" - po_src_port="PortChannel001" - src_port2="Ethernet4" - src_ports = "PortChannel001,Ethernet8" - src_asic_ports = ["Ethernet0", "Ethernet4", "Ethernet8"] - - # create port channel; create port channel member - self.dvs_lag.create_port_channel("001") - self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG", 1) - self.dvs_lag.create_port_channel_member("001", src_port1) - self.dvs_lag.create_port_channel_member("001", src_port2) - - # bring up port channel and port channel member - dvs.set_interface_status(po_src_port, "up") - dvs.set_interface_status(src_port1, "up") - dvs.set_interface_status(src_port2, "up") - - # create mirror session - self.dvs_mirror.create_erspan_session(session, "10.10.10.10", "11.11.11.11", "0x6558", "8", "100", "0", None, src_ports) - self.dvs_mirror.verify_session_status(session, status="inactive") - - # create port channel; create port channel member - self.dvs_lag.create_port_channel("008") - self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG", 2) - self.dvs_lag.create_port_channel_member("008", "Ethernet88") - - # bring up port channel and port channel member - dvs.set_interface_status("PortChannel008", "up") - dvs.set_interface_status("Ethernet88", "up") - - # add ip address to port channel 008 - dvs.add_ip_address("PortChannel008", "11.11.11.0/24") - self.dvs_mirror.verify_session_status(session, status="inactive") - - # create neighbor to port channel 008 - dvs.add_neighbor("PortChannel008", "11.11.11.11", "88:88:88:88:88:88") - self.dvs_mirror.verify_session_status(session) - - # Check src_port state. - expected_asic_db = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": pmap.get("Ethernet88"), - "SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS": "88:88:88:88:88:88"} - - self.dvs_mirror.verify_session(dvs, session, asic_db=expected_asic_db, src_ports=src_asic_ports) - - # remove neighbor - dvs.remove_neighbor("PortChannel008", "11.11.11.11") - self.dvs_mirror.verify_session_status(session, status="inactive") - - # remove ip address - dvs.remove_ip_address("PortChannel008", "11.11.11.0/24") - self.dvs_mirror.verify_session_status(session, status="inactive") - # bring down port channel and port channel member - dvs.set_interface_status("PortChannel008", "down") - dvs.set_interface_status("Ethernet88", "down") - - # remove port channel member; remove port channel - self.dvs_lag.remove_port_channel_member("008", "Ethernet88") - self.dvs_lag.remove_port_channel("008") - self.dvs_lag.remove_port_channel_member("001", src_port1) - self.dvs_lag.remove_port_channel_member("001", src_port2) - self.dvs_lag.remove_port_channel("001") - - # remove mirror session - self.dvs_mirror.remove_mirror_session(session) - self.dvs_mirror.verify_no_mirror() - - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_mirror_port_span.py b/tests/test_mirror_port_span.py deleted file mode 100644 index 7c27eff85c..0000000000 --- a/tests/test_mirror_port_span.py +++ /dev/null @@ -1,525 +0,0 @@ -# This test suite covers the functionality of mirror feature in SwSS -import pytest - -@pytest.mark.usefixtures("testlog") -@pytest.mark.usefixtures('dvs_vlan_manager') -@pytest.mark.usefixtures('dvs_lag_manager') -@pytest.mark.usefixtures('dvs_mirror_manager') -@pytest.mark.usefixtures('dvs_policer_manager') -class TestMirror(object): - - def check_syslog(self, dvs, marker, log, expected_cnt): - (ec, out) = dvs.runcmd(['sh', '-c', "awk \'/%s/,ENDFILE {print;}\' /var/log/syslog | grep \'%s\' | wc -l" % (marker, log)]) - assert out.strip() == str(expected_cnt) - - - def test_PortMirrorQueue(self, dvs, testlog): - """ - This test covers valid and invalid values of the queue parameter. All sessions have source & dest port. - Operation flow: - 1. Create mirror session with queue 0, verify session becomes active and error not written to log. - 2. Create mirror session with queue max valid value, verify session becomes active and error not written to log. - 3. Create mirror session with queue max valid value + 1, verify session doesnt get created and error written to log. - Due to lag in table operations, verify_no_mirror is necessary at the end of each step, to ensure cleanup before next step. - Note that since orchagent caches max valid value during initialization, this test cannot simulate a value from SAI, e.g. - by calling setReadOnlyAttr, because orchagent has already completed initialization and would never read the simulated value. - Therefore, the default value must be used, MIRROR_SESSION_DEFAULT_NUM_TC which is defined in mirrororch.cpp as 255. - """ - - session = "TEST_SESSION" - dst_port = "Ethernet16" - src_ports = "Ethernet12" - - # Sub Test 1 - marker = dvs.add_log_marker() - self.dvs_mirror.create_span_session(session, dst_port, src_ports, direction="BOTH", queue="0") - self.dvs_mirror.verify_session_status(session) - self.dvs_mirror.remove_mirror_session(session) - self.dvs_mirror.verify_no_mirror() - self.check_syslog(dvs, marker, "Failed to get valid queue 0", 0) - - # Sub Test 2 - marker = dvs.add_log_marker() - self.dvs_mirror.create_span_session(session, dst_port, src_ports, direction="RX", queue="254") - self.dvs_mirror.verify_session_status(session) - self.dvs_mirror.remove_mirror_session(session) - self.dvs_mirror.verify_no_mirror() - self.check_syslog(dvs, marker, "Failed to get valid queue 254", 0) - - # Sub Test 3 - marker = dvs.add_log_marker() - self.dvs_mirror.create_span_session(session, dst_port, src_ports, direction="TX", queue="255") - self.dvs_mirror.verify_session_status(session, expected=0) - self.dvs_mirror.remove_mirror_session(session) - self.dvs_mirror.verify_no_mirror() - self.check_syslog(dvs, marker, "Failed to get valid queue 255", 1) - - - def test_PortMirrorAddRemove(self, dvs, testlog): - """ - This test covers the basic SPAN mirror session creation and removal operations - Operation flow: - 1. Create mirror session with only dst_port , verify session becomes active. - 2. Create mirror session with invalid dst_port, verify session doesnt get created. - 3. Create mirror session with invalid source port, verify session doesnt get created. - 4. Create mirror session with source port, verify session becomes active - 5. Create mirror session with Vlan as dst_port, verify session doesnt get created. - 6. Create mirror session with Vlan as source port, verify session doesnt get created. - """ - - pmap = dvs.counters_db.get_entry("COUNTERS_PORT_NAME_MAP", "") - pmap = dict(pmap) - - session = "TEST_SESSION" - dst_port = "Ethernet16" - - # Sub Test 1 - self.dvs_mirror.create_span_session(session, dst_port) - self.dvs_mirror.verify_session_status(session) - a = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": pmap.get("Ethernet16"), - "SAI_MIRROR_SESSION_ATTR_TYPE": "SAI_MIRROR_SESSION_TYPE_LOCAL"} - self.dvs_mirror.verify_session(dvs, session, asic_db=a) - self.dvs_mirror.remove_mirror_session(session) - - # Sub Test 2 - self.dvs_mirror.create_span_session(session, "Invalid") - self.dvs_mirror.verify_session_status(session, expected=0) - - # Sub Test 3 - self.dvs_mirror.create_span_session(session, dst_port, "Invalid", "RX") - self.dvs_mirror.verify_session_status(session, expected=0) - - # Sub Test 4 - # create mirror session with dst_port, src_port, direction - src_ports = "Ethernet12" - src_asic_ports = ["Ethernet12"] - self.dvs_mirror.create_span_session(session, dst_port, src_ports, "RX") - self.dvs_mirror.verify_session_status(session) - self.dvs_mirror.verify_session(dvs, session, asic_db=a, src_ports=src_asic_ports, direction = "RX") - self.dvs_mirror.remove_mirror_session(session) - self.dvs_mirror.verify_no_mirror() - - ## Sub Test 5 - self.dvs_vlan.create_vlan("10") - self.dvs_mirror.create_span_session(session, dst_port="Vlan10") - self.dvs_mirror.verify_session_status(session, expected=0) - - ## Sub Test 6 - self.dvs_mirror.create_span_session(session, dst_port, src_ports="Vlan10") - self.dvs_mirror.verify_session_status(session, expected=0) - self.dvs_mirror.remove_mirror_session(session) - self.dvs_mirror.verify_no_mirror() - self.dvs_vlan.remove_vlan("10") - self.dvs_vlan.get_and_verify_vlan_ids(0) - - - def test_PortMirrorMultiSpanAddRemove(self, dvs, testlog): - """ - This test covers the Multiple SPAN mirror session creation and removal operations - Operation flow: - 1. Create mirror session with multiple source ports, verify that session is active - 2. Create mirror session with multiple source with valid,invalid ports, session doesnt get created. - 3. Create mirror session with multiple source with invalid destination, session doesnt get created. - 4. Create two mirror sessions with multiple source ports. - 5. Verify session config in both sessions. - """ - - pmap = dvs.counters_db.get_entry("COUNTERS_PORT_NAME_MAP", "") - pmap = dict(pmap) - - session1 = "TEST_SESSION1" - session2 = "TEST_SESSION2" - dst_port1 = "Ethernet16" - dst_oid1 = pmap.get(dst_port1) - dst_port2 = "Ethernet20" - dst_oid2 = pmap.get(dst_port2) - - # Sub test 1 - src_ports = "Ethernet0,Ethernet4,Ethernet8" - src_asic_ports = ["Ethernet0","Ethernet4","Ethernet8"] - self.dvs_mirror.create_span_session(session1, dst_port1, src_ports) - a = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": dst_oid1, - "SAI_MIRROR_SESSION_ATTR_TYPE": "SAI_MIRROR_SESSION_TYPE_LOCAL"} - self.dvs_mirror.verify_session_status(session1) - self.dvs_mirror.verify_session(dvs, session1, asic_db=a, src_ports=src_asic_ports) - self.dvs_mirror.remove_mirror_session(session1) - self.dvs_mirror.verify_no_mirror() - - #Subtest 2 - - # create mirror session with valid and invalid ports. - src_ports = "Ethernet0,Invalid,Ethernet8" - self.dvs_mirror.create_span_session(session1, dst_port1, src_ports) - self.dvs_mirror.verify_session_status(session1, expected=0) - - # Subtest 3 - src_ports = "Ethernet0,Ethernet4,Ethernet8" - self.dvs_mirror.create_span_session(session1, "Invalid", src_ports) - self.dvs_mirror.verify_session_status(session1, expected=0) - - # create mirror session - src_ports1 = "Ethernet0,Ethernet4" - src_asic_ports1 = ["Ethernet0","Ethernet4"] - self.dvs_mirror.create_span_session(session1, dst_port1, src_ports1) - src_ports2 = "Ethernet8,Ethernet12" - src_asic_ports2 = ["Ethernet8","Ethernet12"] - self.dvs_mirror.create_span_session(session2, dst_port2, src_ports2) - - a1 = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": dst_oid1, - "SAI_MIRROR_SESSION_ATTR_TYPE": "SAI_MIRROR_SESSION_TYPE_LOCAL"} - a2 = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": dst_oid2, - "SAI_MIRROR_SESSION_ATTR_TYPE": "SAI_MIRROR_SESSION_TYPE_LOCAL"} - self.dvs_mirror.verify_session_status(session1, expected = 2) - self.dvs_mirror.verify_session_status(session2, expected = 2) - self.dvs_mirror.verify_session(dvs, session1, dst_oid=dst_oid1, asic_db=a1, src_ports=src_asic_ports1, expected = 2) - self.dvs_mirror.verify_session(dvs, session2, dst_oid=dst_oid2, asic_db=a2, src_ports=src_asic_ports2, expected = 2) - self.dvs_mirror.remove_mirror_session(session1) - self.dvs_mirror.remove_mirror_session(session2) - self.dvs_mirror.verify_no_mirror() - - def test_PortMirrorPolicerAddRemove(self, dvs, testlog): - """ - This test covers the basic SPAN mirror session creation and removal operations - Operation flow: - 1. Create mirror session with only dst_port and policer , verify session becomes active - 2. Create session with invalid policer, verify session doesnt get created. - 2. Create mirror with policer and multiple source ports, verify session config on all ports. - """ - pmap = dvs.counters_db.get_entry("COUNTERS_PORT_NAME_MAP", "") - pmap = dict(pmap) - session = "TEST_SESSION" - dst_port = "Ethernet16" - policer="POLICER" - - #Sub Test 1 - self.dvs_policer.create_policer(policer) - self.dvs_policer.verify_policer(policer) - self.dvs_mirror.create_span_session(session, dst_port, policer="POLICER") - self.dvs_mirror.verify_session_status(session) - a = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": pmap.get("Ethernet16"), - "SAI_MIRROR_SESSION_ATTR_TYPE": "SAI_MIRROR_SESSION_TYPE_LOCAL"} - self.dvs_mirror.verify_session(dvs, session, asic_db=a, policer="POLICER") - self.dvs_mirror.remove_mirror_session(session) - self.dvs_policer.remove_policer("POLICER") - self.dvs_policer.verify_no_policer() - self.dvs_mirror.verify_no_mirror() - - # Sub test 2 - src_ports = "Ethernet0,Ethernet4,Ethernet8" - src_asic_ports = ["Ethernet0","Ethernet4","Ethernet8"] - self.dvs_mirror.create_span_session(session, dst_port, src_ports, policer="POLICER") - self.dvs_mirror.verify_session_status(session, expected=0) - - # Sub test 3 - self.dvs_policer.create_policer(policer) - self.dvs_policer.verify_policer(policer) - self.dvs_mirror.create_span_session(session, dst_port, src_ports, policer="POLICER") - self.dvs_mirror.verify_session_status(session) - self.dvs_mirror.verify_session(dvs, session, asic_db=a, src_ports=src_asic_ports, policer="POLICER") - self.dvs_mirror.remove_mirror_session(session) - self.dvs_policer.remove_policer("POLICER") - self.dvs_policer.verify_no_policer() - self.dvs_mirror.verify_no_mirror() - - - def test_PortMultiMirrorPolicerAddRemove(self, dvs, testlog): - """ - This test covers the basic SPAN mirror session creation and removal operations - Operation flow: - 1. Create mirror session with multiple source with multiple policer. - 2. Verify port/policer/session config on all. - """ - pmap = dvs.counters_db.get_entry("COUNTERS_PORT_NAME_MAP", "") - pmap = dict(pmap) - - session1 = "TEST_SESSION1" - session2 = "TEST_SESSION2" - dst_port1 = "Ethernet16" - dst_oid1 = pmap.get(dst_port1) - dst_port2 = "Ethernet20" - dst_oid2 = pmap.get(dst_port2) - policer1 = "POLICER1" - policer2 = "POLICER2" - - #Sub Test 1 - self.dvs_policer.create_policer(policer1, cir="600") - self.dvs_policer.verify_policer(policer1) - self.dvs_policer.create_policer(policer2, cir="800") - self.dvs_policer.verify_policer(policer2, expected = 2) - - src_ports1 = "Ethernet0,Ethernet4" - src_asic_ports1 = ["Ethernet0","Ethernet4"] - self.dvs_mirror.create_span_session(session1, dst_port1, src_ports1, policer=policer1) - src_ports2 = "Ethernet8,Ethernet12" - src_asic_ports2 = ["Ethernet8","Ethernet12"] - self.dvs_mirror.create_span_session(session2, dst_port2, src_ports2, policer=policer2) - - a1 = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": dst_oid1, - "SAI_MIRROR_SESSION_ATTR_TYPE": "SAI_MIRROR_SESSION_TYPE_LOCAL"} - a2 = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": dst_oid2, - "SAI_MIRROR_SESSION_ATTR_TYPE": "SAI_MIRROR_SESSION_TYPE_LOCAL"} - self.dvs_mirror.verify_session_status(session1, expected = 2) - self.dvs_mirror.verify_session_status(session2, expected = 2) - self.dvs_mirror.verify_session(dvs, session1, dst_oid=dst_oid1, asic_db=a1, src_ports=src_asic_ports1, expected = 2, policer=policer1) - self.dvs_mirror.verify_session(dvs, session2, dst_oid=dst_oid2, asic_db=a2, src_ports=src_asic_ports2, expected = 2, policer=policer2) - self.dvs_mirror.remove_mirror_session(session1) - self.dvs_mirror.remove_mirror_session(session2) - self.dvs_policer.remove_policer(policer1) - self.dvs_policer.remove_policer(policer2) - self.dvs_policer.verify_no_policer() - self.dvs_mirror.verify_no_mirror() - - def test_LAGMirrorSpanAddRemove(self, dvs, testlog): - """ - This test covers the LAG mirror session creation and removal operations - Operation flow: - 1. Create port channel with 2 members. - 2. Create mirror session with LAG as source port. - 3. Verify that source ports have proper mirror config. - 4. Remove port from port-channel and verify mirror config is removed from the port. - 5. Remove second port and verify mirror config is removed. - """ - dvs.setup_db() - pmap = dvs.counters_db.get_entry("COUNTERS_PORT_NAME_MAP", "") - pmap = dict(pmap) - - session = "TEST_SESSION" - dst_port = "Ethernet16" - src_port1="Ethernet8" - src_port2="Ethernet4" - po_src_port="PortChannel008" - src_ports = "PortChannel008,Ethernet12" - src_asic_ports = ["Ethernet8", "Ethernet4", "Ethernet12"] - - # create port channel; create port channel member - self.dvs_lag.create_port_channel("008") - self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG", 1) - self.dvs_lag.create_port_channel_member("008", src_port1) - self.dvs_lag.create_port_channel_member("008", src_port2) - - # bring up port channel and port channel member - dvs.set_interface_status(po_src_port, "up") - dvs.set_interface_status(src_port1, "up") - dvs.set_interface_status(src_port2, "up") - - # Sub Test 1 - self.dvs_mirror.create_span_session(session, dst_port, src_ports) - self.dvs_mirror.verify_session_status(session) - - # verify asicdb - # Check src_port state. - expected_asic_db = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": pmap.get(dst_port), - "SAI_MIRROR_SESSION_ATTR_TYPE": "SAI_MIRROR_SESSION_TYPE_LOCAL"} - self.dvs_mirror.verify_session(dvs, session, asic_db=expected_asic_db, src_ports=src_asic_ports, asic_size=2) - - # Sub Test 2 - # remove port channel member; remove port channel - self.dvs_lag.remove_port_channel_member("008", src_port1) - src_asic_ports = ["Ethernet4", "Ethernet12"] - self.dvs_mirror.verify_session(dvs, session, asic_db=expected_asic_db, src_ports=src_asic_ports, asic_size=2) - self.dvs_lag.remove_port_channel_member("008", src_port2) - - self.dvs_lag.remove_port_channel("008") - self.dvs_mirror.remove_mirror_session(session) - self.dvs_mirror.verify_no_mirror() - - def test_PortMirrorPolicerWithAcl(self, dvs, dvs_acl, testlog): - """ - This test covers the port mirroring with policer and ACL configurations. - Operation flow: - 1. Create port mirror session with policer. - 2. Create ACL and configure mirror - 2. Verify mirror and ACL config is proper. - """ - dvs.setup_db() - session = "MIRROR_SESSION" - policer= "POLICER" - dst_port = "Ethernet16" - - # create policer - self.dvs_policer.create_policer(policer) - self.dvs_policer.verify_policer(policer) - - # create mirror session - self.dvs_mirror.create_span_session(session, dst_port, policer=policer) - self.dvs_mirror.verify_session_status(session) - - member_ids = dvs.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION", 1) - - # create acl table - bind_ports = ["Ethernet0", "Ethernet4"] - dvs_acl.create_acl_table("test", "mirror", bind_ports) - dvs_acl.verify_acl_table_count(1) - dvs_acl.verify_acl_table_groups(len(bind_ports)) - - config_qualifiers = {"DSCP": "8/56"} - - mirror_oid = "1:" + member_ids[0] - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_DSCP": dvs_acl.get_simple_qualifier_comparator("8&mask:0x38") - } - - dvs_acl.create_mirror_acl_rule("test", "mirror_rule", config_qualifiers, session) - dvs_acl.verify_mirror_acl_rule(expected_sai_qualifiers, mirror_oid) - - dvs_acl.remove_acl_rule("test", "mirror_rule") - dvs_acl.verify_no_acl_rules() - - dvs_acl.remove_acl_table("test") - dvs_acl.verify_acl_table_count(0) - - self.dvs_mirror.remove_mirror_session(session) - - self.dvs_policer.remove_policer(policer) - self.dvs_policer.verify_no_policer() - self.dvs_mirror.verify_no_mirror() - - def test_PortMirrorLAGPortSpanAddRemove(self, dvs, testlog): - """ - This test covers the LAG mirror session creation and removal operations - Operation flow: - 1. Create port channel with 2 members. - 2. Create mirror session with LAG and LAG port. session creation has to fail. - 3. Create mirror session with LAG and other LAG port. session creation has to fail - 4. Create mirror session with LAG and new port, session will become active. - 5. Verify all LAG and new port has session config. - 6. Remove one LAG member and verify that failing session works fine. - """ - dvs.setup_db() - pmap = dvs.counters_db.get_entry("COUNTERS_PORT_NAME_MAP", "") - pmap = dict(pmap) - - session = "TEST_SESSION" - dst_port = "Ethernet16" - src_port1="Ethernet8" - src_port2="Ethernet4" - po_src_port="PortChannel008" - - # create port channel; create port channel member - self.dvs_lag.create_port_channel("008") - self.dvs_lag.get_and_verify_port_channel(1) - self.dvs_lag.create_port_channel_member("008", src_port1) - self.dvs_lag.create_port_channel_member("008", src_port2) - self.dvs_lag.get_and_verify_port_channel_members(2) - - # bring up port channel and port channel member - dvs.set_interface_status(po_src_port, "up") - dvs.set_interface_status(src_port1, "up") - dvs.set_interface_status(src_port2, "up") - - # Sub Test 1 - src_ports = "PortChannel008,Ethernet8" - self.dvs_mirror.create_span_session(session, dst_port, src_ports) - self.dvs_mirror.verify_session_status(session, expected=0) - self.dvs_mirror.verify_session_status(session, status="inactive", expected = 0) - - # Sub Test 2 - src_ports = "PortChannel008,Ethernet4" - self.dvs_mirror.create_span_session(session, dst_port, src_ports) - self.dvs_mirror.verify_session_status(session, expected=0) - self.dvs_mirror.verify_session_status(session, status="inactive", expected=0) - - # Sub Test 3 - src_ports = "PortChannel008,Ethernet40" - src_asic_ports = ["Ethernet8", "Ethernet40", "Ethernet4"] - self.dvs_mirror.create_span_session(session, dst_port, src_ports) - self.dvs_mirror.verify_session_status(session, status="active") - - expected_asic_db = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": pmap.get(dst_port), - "SAI_MIRROR_SESSION_ATTR_TYPE": "SAI_MIRROR_SESSION_TYPE_LOCAL"} - self.dvs_mirror.verify_session(dvs, session, asic_db=expected_asic_db, src_ports=src_asic_ports, asic_size=2) - self.dvs_mirror.remove_mirror_session(session) - self.dvs_mirror.verify_no_mirror() - - # Sub Test 4 - self.dvs_lag.remove_port_channel_member("008", "Ethernet4") - self.dvs_lag.get_and_verify_port_channel_members(1) - src_ports = "PortChannel008,Ethernet40" - src_asic_ports = ["Ethernet8", "Ethernet40"] - self.dvs_mirror.create_span_session(session, dst_port, src_ports) - self.dvs_mirror.verify_session_status(session) - self.dvs_mirror.verify_session(dvs, session, src_ports=src_asic_ports) - - self.dvs_mirror.remove_mirror_session(session) - self.dvs_mirror.verify_no_mirror() - self.dvs_lag.remove_port_channel_member("008", "Ethernet8") - self.dvs_lag.get_and_verify_port_channel_members(0) - self.dvs_lag.remove_port_channel("008") - self.dvs_lag.get_and_verify_port_channel(0) - self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG", 0) - - - def test_PortLAGMirrorUpdateLAG(self, dvs, testlog): - """ - This test covers the LAG mirror session creation and removal operations - Operation flow: - 1. Create port channel with 2 members. - 2. Create mirror session with LAG and other port P1 - 3. Verify mirror session is active and ports have proper config - 4. Add port P1 to LAG and verify mirror config on all ports. - 5. Remove port P1 from LAG and verify mirror config on P1 is intact. - 6. Remove port from LAG and verify mirror config on other ports in intact. - """ - dvs.setup_db() - pmap = dvs.counters_db.get_entry("COUNTERS_PORT_NAME_MAP", "") - pmap = dict(pmap) - - session = "TEST_SESSION" - dst_port = "Ethernet16" - src_port1="Ethernet8" - src_port2="Ethernet4" - po_src_port="PortChannel008" - - # create port channel; create port channel member - self.dvs_lag.create_port_channel("008") - self.dvs_lag.get_and_verify_port_channel(1) - self.dvs_lag.create_port_channel_member("008", src_port1) - self.dvs_lag.create_port_channel_member("008", src_port2) - self.dvs_lag.get_and_verify_port_channel_members(2) - - # bring up port channel and port channel member - dvs.set_interface_status(po_src_port, "up") - dvs.set_interface_status(src_port1, "up") - dvs.set_interface_status(src_port2, "up") - - # Sub Test 1 - src_ports = "PortChannel008,Ethernet40" - src_asic_ports = ["Ethernet8", "Ethernet40", "Ethernet4"] - self.dvs_mirror.create_span_session(session, dst_port, src_ports) - self.dvs_mirror.verify_session_status(session, status="active") - - expected_asic_db = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": pmap.get(dst_port), - "SAI_MIRROR_SESSION_ATTR_TYPE": "SAI_MIRROR_SESSION_TYPE_LOCAL"} - self.dvs_mirror.verify_session(dvs, session, asic_db=expected_asic_db, src_ports=src_asic_ports, asic_size=2) - - - # Add source port Ethernet40 to LAG - self.dvs_lag.create_port_channel_member("008", "Ethernet40") - self.dvs_lag.get_and_verify_port_channel_members(3) - self.dvs_mirror.verify_session(dvs, session, src_ports=src_asic_ports) - - # Remove source port Ethernet40 from LAG - self.dvs_lag.remove_port_channel_member("008", "Ethernet40") - self.dvs_lag.get_and_verify_port_channel_members(2) - self.dvs_mirror.verify_session(dvs, session, src_ports=src_asic_ports) - - # Remove one port from LAG - self.dvs_lag.remove_port_channel_member("008", "Ethernet4") - self.dvs_lag.get_and_verify_port_channel_members(1) - src_asic_ports = ["Ethernet8"] - self.dvs_mirror.verify_session(dvs, session, src_ports=src_asic_ports) - - #cleanup - self.dvs_mirror.remove_mirror_session(session) - self.dvs_mirror.verify_no_mirror() - self.dvs_lag.remove_port_channel_member("008", "Ethernet8") - self.dvs_lag.get_and_verify_port_channel_members(0) - self.dvs_lag.remove_port_channel("008") - self.dvs_lag.get_and_verify_port_channel(0) - self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG", 0) - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_mpls.py b/tests/test_mpls.py deleted file mode 100644 index 0b553ebba2..0000000000 --- a/tests/test_mpls.py +++ /dev/null @@ -1,685 +0,0 @@ -import os -import re -import time -import json -import pytest - -from swsscommon import swsscommon -from dvslib.dvs_common import wait_for_result - -class TestMplsBase(object): - def mpls_appdb_mode(self): - # run in APP_DB mode unless using "fpmsyncd -l net" - return True - - def setup_db(self, dvs): - self.pdb = dvs.get_app_db() - self.adb = dvs.get_asic_db() - self.cdb = dvs.get_config_db() - - def set_admin_status(self, interface, status): - self.cdb.update_entry("PORT", interface, {"admin_status": status}) - - def create_l3_intf(self, interface): - self.cdb.create_entry("INTERFACE", interface, {"NULL": "NULL"}) - - def remove_l3_intf(self, interface): - self.cdb.delete_entry("INTERFACE", interface) - - def create_mpls_intf(self, interface): - self.cdb.create_entry("INTERFACE", interface, {"mpls": "enable"}) - - def remove_mpls_intf(self, interface): - self.cdb.delete_entry("INTERFACE", interface) - - def add_ip_address(self, interface, ip): - self.cdb.create_entry("INTERFACE", interface + "|" + ip, {"NULL": "NULL"}) - - def remove_ip_address(self, interface, ip): - self.cdb.delete_entry("INTERFACE", interface + "|" + ip) - - def create_route_entry(self, key, pairs): - tbl = swsscommon.ProducerStateTable(self.pdb.db_connection, "ROUTE_TABLE") - fvs = swsscommon.FieldValuePairs(list(pairs.items())) - tbl.set(key, fvs) - - def remove_route_entry(self, key): - tbl = swsscommon.ProducerStateTable(self.pdb.db_connection, "ROUTE_TABLE") - tbl._del(key) - - def check_route_entries(self, present, destinations): - def _access_function(): - route_entries = self.adb.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - route_destinations = [json.loads(route_entry)["dest"] - for route_entry in route_entries] - if present: - return (all(destination in route_destinations for destination in destinations), None) - else: - return (all(destination not in route_destinations for destination in destinations), None) - - wait_for_result(_access_function) - - def get_route_nexthop(self, prefix): - route_entries = self.adb.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - for route_entry in route_entries: - if json.loads(route_entry)["dest"] == prefix: - return self.adb.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY", route_entry).get("SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID") - return None - - def check_route_nexthop(self, prefix, nhtype, ip, ostype, labels): - def _access_function(): - nh = self.get_route_nexthop(prefix) - if not bool(nh): return (False, None) - fvs = self.adb.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP", nh) - # NH should be in NH Table - if not bool(fvs): return (False, None) - if fvs.get("SAI_NEXT_HOP_ATTR_TYPE") != nhtype: return (False, None) - if fvs.get("SAI_NEXT_HOP_ATTR_IP") != ip: return (False, None) - if nhtype != "SAI_NEXT_HOP_TYPE_MPLS": return (True, None) - if fvs.get("SAI_NEXT_HOP_ATTR_OUTSEG_TYPE") != ostype: return (False, None) - if fvs.get("SAI_NEXT_HOP_ATTR_LABELSTACK") != labels: return (False, None) - return (True, None) - - wait_for_result(_access_function) - - def check_route_nexthop_group(self, prefix, count): - def _access_function(): - nhg = self.get_route_nexthop(prefix) - if not bool(nhg): return (False, None) - fvs = self.adb.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP", nhg) - # NH should be in NHG Table - if not bool(fvs): return (False, None) - keys = self.adb.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER") - matched_nhgms = [] - for key in keys: - fvs = self.adb.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER", key) - if fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID"] == nhg: - matched_nhgms.append(key) - - if len(matched_nhgms) != count: return (False, None) - return (True, None) - - wait_for_result(_access_function) - - def create_inseg_entry(self, key, pairs): - tbl = swsscommon.ProducerStateTable(self.pdb.db_connection, "LABEL_ROUTE_TABLE") - fvs = swsscommon.FieldValuePairs(list(pairs.items())) - tbl.set(key, fvs) - - def remove_inseg_entry(self, key): - tbl = swsscommon.ProducerStateTable(self.pdb.db_connection, "LABEL_ROUTE_TABLE") - tbl._del(key) - - def check_inseg_entries(self, present, labels): - def _access_function(): - inseg_entries = self.adb.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_INSEG_ENTRY") - inseg_labels = [json.loads(inseg_entry)["label"] - for inseg_entry in inseg_entries] - if present: - return (all(label in inseg_labels for label in labels), None) - else: - return (all(label not in inseg_labels for label in labels), None) - - wait_for_result(_access_function) - - def get_inseg_nexthop(self, label): - inseg_entries = self.adb.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_INSEG_ENTRY") - for inseg_entry in inseg_entries: - if json.loads(inseg_entry)["label"] == label: - return self.adb.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_INSEG_ENTRY", inseg_entry).get("SAI_INSEG_ENTRY_ATTR_NEXT_HOP_ID") - return None - - def check_inseg_nexthop(self, label, nhtype, ip, ostype, labels): - def _access_function(): - nh = self.get_inseg_nexthop(label) - if not bool(nh): return (False, None) - fvs = self.adb.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP", nh) - # NH should be in NH Table - if not bool(fvs): return (False, None) - if fvs.get("SAI_NEXT_HOP_ATTR_TYPE") != nhtype: return (False, None) - if fvs.get("SAI_NEXT_HOP_ATTR_IP") != ip: return (False, None) - if nhtype != "SAI_NEXT_HOP_TYPE_MPLS": return (True, None) - if fvs.get("SAI_NEXT_HOP_ATTR_OUTSEG_TYPE") != ostype: return (False, None) - if fvs.get("SAI_NEXT_HOP_ATTR_LABELSTACK") != labels: return (False, None) - return (True, None) - - wait_for_result(_access_function) - - def check_inseg_nexthop_group(self, label, count): - def _access_function(): - nhg = self.get_inseg_nexthop(label) - if not bool(nhg): return (False, None) - fvs = self.adb.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP", nhg) - # NH should be in NHG Table - if not bool(fvs): return (False, None) - keys = self.adb.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER") - matched_nhgms = [] - for key in keys: - fvs = self.adb.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER", key) - if fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID"] == nhg: - matched_nhgms.append(key) - - if len(matched_nhgms) != count: return (False, None) - return (True, None) - - wait_for_result(_access_function) - - def check_nexthop(self, present, nhtype, ip, ostype, labels): - def _access_function(): - nhs = self.adb.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP") - for nh in nhs: - fvs = self.adb.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP", nh) - if fvs.get("SAI_NEXT_HOP_ATTR_TYPE") != nhtype: continue - if fvs.get("SAI_NEXT_HOP_ATTR_IP") != ip: continue - if nhtype == "SAI_NEXT_HOP_TYPE_IP": return (present, None) - if nhtype != "SAI_NEXT_HOP_TYPE_MPLS": continue - if fvs.get("SAI_NEXT_HOP_ATTR_OUTSEG_TYPE") != ostype: continue - if fvs.get("SAI_NEXT_HOP_ATTR_LABELSTACK") == labels: return (present, None) - return (not present, None) - - wait_for_result(_access_function) - - def check_nexthop_group(self, present, nhg): - def _access_function(): - fvs = self.adb.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP", nhg) - if bool(fvs): return (present, None) - return (not present, None) - - wait_for_result(_access_function) - - def clear_srv_config(self, dvs): - dvs.servers[0].runcmd("ip address flush dev eth0") - dvs.servers[1].runcmd("ip address flush dev eth0") - dvs.servers[2].runcmd("ip address flush dev eth0") - dvs.servers[3].runcmd("ip address flush dev eth0") - - def setup_mpls(self, dvs, resolve): - if not self.mpls_appdb_mode(): - dvs.runcmd("modprobe mpls_router") - dvs.runcmd("modprobe mpls_iptunnel") - dvs.runcmd("sysctl -w net.mpls.platform_labels=1000") - - self.setup_db(dvs) - - self.clear_srv_config(dvs) - - # create mpls interface - self.create_mpls_intf("Ethernet0") - self.create_mpls_intf("Ethernet4") - self.create_mpls_intf("Ethernet8") - - # set ip address - self.add_ip_address("Ethernet0", "10.0.0.0/31") - self.add_ip_address("Ethernet4", "10.0.0.2/31") - self.add_ip_address("Ethernet8", "10.0.0.4/31") - - # bring up interface - self.set_admin_status("Ethernet0", "up") - self.set_admin_status("Ethernet4", "up") - self.set_admin_status("Ethernet8", "up") - - # set ip address and default route - dvs.servers[0].runcmd("ip address add 10.0.0.1/31 dev eth0") - dvs.servers[0].runcmd("ip route add default via 10.0.0.0") - - dvs.servers[1].runcmd("ip address add 10.0.0.3/31 dev eth0") - dvs.servers[1].runcmd("ip route add default via 10.0.0.2") - - dvs.servers[2].runcmd("ip address add 10.0.0.5/31 dev eth0") - dvs.servers[2].runcmd("ip route add default via 10.0.0.4") - - # get neighbor and arp entry - if resolve: - dvs.servers[0].runcmd("ping -c 1 10.0.0.3") - dvs.servers[2].runcmd("ping -c 1 10.0.0.3") - - def teardown_mpls(self, dvs): - # remove ip address - self.remove_ip_address("Ethernet0", "10.0.0.0/31") - self.remove_ip_address("Ethernet4", "10.0.0.2/31") - self.remove_ip_address("Ethernet8", "10.0.0.4/31") - - # remove mpls interface - self.remove_mpls_intf("Ethernet0") - self.remove_mpls_intf("Ethernet4") - self.remove_mpls_intf("Ethernet8") - - self.set_admin_status("Ethernet0", "down") - self.set_admin_status("Ethernet4", "down") - self.set_admin_status("Ethernet8", "down") - - # remove ip address and default route - dvs.servers[0].runcmd("ip route del default dev eth0") - dvs.servers[0].runcmd("ip address del 10.0.0.1/31 dev eth0") - - dvs.servers[1].runcmd("ip route del default dev eth0") - dvs.servers[1].runcmd("ip address del 10.0.0.3/31 dev eth0") - - dvs.servers[2].runcmd("ip route del default dev eth0") - dvs.servers[2].runcmd("ip address del 10.0.0.5/31 dev eth0") - - if not self.mpls_appdb_mode(): - dvs.runcmd("rmmod mpls_iptunnel") - dvs.runcmd("rmmod mpls_router") - -class TestMplsRoute(TestMplsBase): - """ Functionality tests for mpls """ - def test_RouteAddRemoveIpRoutePush(self, dvs, testlog): - self.setup_mpls(dvs, True) - - # add route entry - prefix = "2.2.2.0/24" - if self.mpls_appdb_mode(): - fieldValues = {"nexthop": "10.0.0.1", "ifname": "Ethernet0", "mpls_nh": "push201"} - self.create_route_entry(prefix, fieldValues) - else: - # dvs.runcmd("ip route add 2.2.2.0/24 encap mpls 201 via inet 10.0.0.1 dev Ethernet0") - dvs.runcmd("vtysh -c \"configure terminal\" -c \"ip route 2.2.2.0/24 10.0.0.1 Ethernet0 label 201\"") - - # check application database - self.pdb.wait_for_entry("ROUTE_TABLE", prefix) - - # check ASIC route database - self.check_route_entries(True, [prefix]) - self.check_route_nexthop(prefix, "SAI_NEXT_HOP_TYPE_MPLS", "10.0.0.1", "SAI_OUTSEG_TYPE_PUSH", "1:201") - - # remove route entry - if self.mpls_appdb_mode(): - self.remove_route_entry(prefix) - else: - # dvs.runcmd("ip route del 2.2.2.0/24 encap mpls 201 via inet 10.0.0.1 dev Ethernet0") - dvs.runcmd("vtysh -c \"configure terminal\" -c \"no ip route 2.2.2.0/24 10.0.0.1 Ethernet0 label 201\"") - - # check application database - self.pdb.wait_for_deleted_entry("ROUTE_TABLE", prefix) - - # check ASIC route database - self.check_route_entries(False, [prefix]) - self.check_nexthop(False, "SAI_NEXT_HOP_TYPE_MPLS", "10.0.0.1", "SAI_OUTSEG_TYPE_PUSH", "1:201") - - self.teardown_mpls(dvs) - - def test_RouteAddRemoveMplsRouteSwap(self, dvs, testlog): - self.setup_mpls(dvs, True) - - # add route entry - label = "200" - if self.mpls_appdb_mode(): - fieldValues = {"nexthop": "10.0.0.1", "ifname": "Ethernet0", "mpls_nh": "swap201", "mpls_pop": "1"} - self.create_inseg_entry(label, fieldValues) - else: - # dvs.runcmd("ip -f mpls route add 200 as 201 via inet 10.0.0.1 dev Ethernet0") - dvs.runcmd("vtysh -c \"configure terminal\" -c \"mpls lsp 200 10.0.0.1 201\"") - - # check application database - self.pdb.wait_for_entry("LABEL_ROUTE_TABLE", label) - - # check ASIC inseg database - self.check_inseg_entries(True, [label]) - self.check_inseg_nexthop(label, "SAI_NEXT_HOP_TYPE_MPLS", "10.0.0.1", "SAI_OUTSEG_TYPE_SWAP", "1:201") - - # remove route entry - if self.mpls_appdb_mode(): - self.remove_inseg_entry(label) - else: - # dvs.runcmd("ip -f mpls route del 200 as 201 via inet 10.0.0.1 dev Ethernet0") - dvs.runcmd("vtysh -c \"configure terminal\" -c \"no mpls lsp 200 10.0.0.1 201\"") - - # check application database - self.pdb.wait_for_deleted_entry("LABEL_ROUTE_TABLE", label) - - # check ASIC inseg database - self.check_inseg_entries(False, [label]) - self.check_nexthop(False, "SAI_NEXT_HOP_TYPE_MPLS", "10.0.0.1", "SAI_OUTSEG_TYPE_SWAP", "1:201") - - self.teardown_mpls(dvs) - - def test_RouteAddRemoveMplsRouteImplicitNull(self, dvs, testlog): - self.setup_mpls(dvs, True) - - # add route entry - label = "200" - if self.mpls_appdb_mode(): - fieldValues = {"nexthop": "10.0.0.1", "ifname": "Ethernet0", "mpls_pop": "1"} - self.create_inseg_entry(label, fieldValues) - else: - # dvs.runcmd("ip -f mpls route add 200 via inet 10.0.0.1 dev Ethernet0") - dvs.runcmd("vtysh -c \"configure terminal\" -c \"mpls lsp 200 10.0.0.1 implicit-null\"") - - # check application database - self.pdb.wait_for_entry("LABEL_ROUTE_TABLE", label) - - # check ASIC inseg database - self.check_inseg_entries(True, [label]) - self.check_inseg_nexthop(label, "SAI_NEXT_HOP_TYPE_IP", "10.0.0.1", "", "") - - # remove route entry - if self.mpls_appdb_mode(): - self.remove_inseg_entry(label) - else: - # dvs.runcmd("ip -f mpls route del 200 via inet 10.0.0.1 dev Ethernet0") - dvs.runcmd("vtysh -c \"configure terminal\" -c \"no mpls lsp 200 10.0.0.1 implicit-null\"") - - # check application database - self.pdb.wait_for_deleted_entry("LABEL_ROUTE_TABLE", label) - - # check ASIC inseg database - self.check_inseg_entries(False, [label]) - # IP NHs are created by neighbor resolution and should still be present - self.check_nexthop(True, "SAI_NEXT_HOP_TYPE_IP", "10.0.0.1", "", "") - - self.teardown_mpls(dvs) - - def test_RouteAddRemoveMplsRouteExplicitNull(self, dvs, testlog): - self.setup_mpls(dvs, True) - - # add route entry - label = "200" - if self.mpls_appdb_mode(): - fieldValues = {"nexthop": "10.0.0.1", "ifname": "Ethernet0", "mpls_nh": "swap0", "mpls_pop": "1"} - self.create_inseg_entry(label, fieldValues) - else: - # dvs.runcmd("ip -f mpls route add 200 as 0 via inet 10.0.0.1 dev Ethernet0") - dvs.runcmd("vtysh -c \"configure terminal\" -c \"mpls lsp 200 10.0.0.1 explicit-null\"") - - # check application database - self.pdb.wait_for_entry("LABEL_ROUTE_TABLE", label) - - # check ASIC inseg database - self.check_inseg_entries(True, [label]) - self.check_inseg_nexthop(label, "SAI_NEXT_HOP_TYPE_MPLS", "10.0.0.1", "SAI_OUTSEG_TYPE_SWAP", "1:0") - - # remove route entry - if self.mpls_appdb_mode(): - self.remove_inseg_entry(label) - else: - # dvs.runcmd("ip -f mpls route del 200 as 0 via inet 10.0.0.1 dev Ethernet0") - dvs.runcmd("vtysh -c \"configure terminal\" -c \"no mpls lsp 200 10.0.0.1 explicit-null\"") - - # check application database - self.pdb.wait_for_deleted_entry("LABEL_ROUTE_TABLE", label) - - # check ASIC inseg database - self.check_inseg_entries(False, [label]) - self.check_nexthop(False, "SAI_NEXT_HOP_TYPE_MPLS", "10.0.0.1", "SAI_OUTSEG_TYPE_SWAP", "1:0") - - self.teardown_mpls(dvs) - - def test_RouteAddRemoveIpRoutePushNHG(self, dvs, testlog): - self.setup_mpls(dvs, True) - - # add route entry - prefix = "2.2.2.0/24" - if self.mpls_appdb_mode(): - fieldValues = {"nexthop": "10.0.0.1,10.0.0.5", "ifname": "Ethernet0,Ethernet8", "mpls_nh": "push200,push201"} - self.create_route_entry(prefix, fieldValues) - else: - dvs.runcmd("ip route add 2.2.2.0/24 nexthop encap mpls 200 via inet 10.0.0.1 dev Ethernet0 nexthop encap mpls 201 via inet 10.0.0.5 dev Ethernet8") - - # check application database - self.pdb.wait_for_entry("ROUTE_TABLE", prefix) - - # check ASIC route database - self.check_route_entries(True, [prefix]) - self.check_route_nexthop_group(prefix, 2) - self.check_nexthop(True, "SAI_NEXT_HOP_TYPE_MPLS", "10.0.0.1", "SAI_OUTSEG_TYPE_PUSH", "1:200") - self.check_nexthop(True, "SAI_NEXT_HOP_TYPE_MPLS", "10.0.0.5", "SAI_OUTSEG_TYPE_PUSH", "1:201") - nhg = self.get_route_nexthop(prefix) - - # remove route entry - if self.mpls_appdb_mode(): - self.remove_route_entry(prefix) - else: - dvs.runcmd("ip route del 2.2.2.0/24 nexthop encap mpls 200 via inet 10.0.0.1 dev Ethernet0 nexthop encap mpls 201 via inet 10.0.0.5 dev Ethernet8") - - # check application database - self.pdb.wait_for_deleted_entry("ROUTE_TABLE", prefix) - - # check ASIC route database - self.check_route_entries(False, [prefix]) - self.check_nexthop_group(False, nhg) - self.check_nexthop(False, "SAI_NEXT_HOP_TYPE_MPLS", "10.0.0.1", "SAI_OUTSEG_TYPE_PUSH", "1:200") - self.check_nexthop(False, "SAI_NEXT_HOP_TYPE_MPLS", "10.0.0.5", "SAI_OUTSEG_TYPE_PUSH", "1:201") - - self.teardown_mpls(dvs) - - def test_RouteAddRemoveMplsRouteSwapNHG(self, dvs, testlog): - self.setup_mpls(dvs, True) - - # add route entry - label = "200" - if self.mpls_appdb_mode(): - fieldValues = {"nexthop": "10.0.0.1,10.0.0.5", "ifname": "Ethernet0,Ethernet8", "mpls_nh": "swap201,swap202", "mpls_pop": "1"} - self.create_inseg_entry(label, fieldValues) - else: - dvs.runcmd("ip -f mpls route add 200 nexthop as 201 via inet 10.0.0.1 dev Ethernet0 nexthop as 202 via inet 10.0.0.5 dev Ethernet8") - - # check application database - self.pdb.wait_for_entry("LABEL_ROUTE_TABLE", label) - - # check ASIC inseg database - self.check_inseg_entries(True, [label]) - self.check_inseg_nexthop_group(label, 2) - self.check_nexthop(True, "SAI_NEXT_HOP_TYPE_MPLS", "10.0.0.1", "SAI_OUTSEG_TYPE_SWAP", "1:201") - self.check_nexthop(True, "SAI_NEXT_HOP_TYPE_MPLS", "10.0.0.5", "SAI_OUTSEG_TYPE_SWAP", "1:202") - nhg = self.get_inseg_nexthop(label) - - # remove route entry - if self.mpls_appdb_mode(): - self.remove_inseg_entry(label) - else: - dvs.runcmd("ip -f mpls route del 200 nexthop as 201 via inet 10.0.0.1 dev Ethernet0 nexthop as 202 via inet 10.0.0.5 dev Ethernet8") - - # check application database - self.pdb.wait_for_deleted_entry("LABEL_ROUTE_TABLE", label) - - # check ASIC inseg database - self.check_inseg_entries(False, [label]) - self.check_nexthop_group(False, nhg) - self.check_nexthop(False, "SAI_NEXT_HOP_TYPE_MPLS", "10.0.0.1", "SAI_OUTSEG_TYPE_SWAP", "1:201") - self.check_nexthop(False, "SAI_NEXT_HOP_TYPE_MPLS", "10.0.0.5", "SAI_OUTSEG_TYPE_SWAP", "1:202") - - self.teardown_mpls(dvs) - - def test_RouteAddRemoveMplsRoutePopNHG(self, dvs, testlog): - self.setup_mpls(dvs, True) - - # add route entry - label = "200" - if self.mpls_appdb_mode(): - fieldValues = {"nexthop": "10.0.0.1,10.0.0.5", "ifname": "Ethernet0,Ethernet8", "mpls_pop": "1"} - self.create_inseg_entry(label, fieldValues) - else: - dvs.runcmd("ip -f mpls route add 200 nexthop via inet 10.0.0.1 dev Ethernet0 nexthop via inet 10.0.0.5 dev Ethernet8") - - # check application database - self.pdb.wait_for_entry("LABEL_ROUTE_TABLE", label) - - # check ASIC inseg database - self.check_inseg_entries(True, [label]) - self.check_inseg_nexthop_group(label, 2) - self.check_nexthop(True, "SAI_NEXT_HOP_TYPE_IP", "10.0.0.1", "", "") - self.check_nexthop(True, "SAI_NEXT_HOP_TYPE_IP", "10.0.0.5", "", "") - nhg = self.get_inseg_nexthop(label) - - # remove route entry - if self.mpls_appdb_mode(): - self.remove_inseg_entry(label) - else: - dvs.runcmd("ip -f mpls route del 200 nexthop via inet 10.0.0.1 dev Ethernet0 nexthop via inet 10.0.0.5 dev Ethernet8") - - # check application database - self.pdb.wait_for_deleted_entry("LABEL_ROUTE_TABLE", label) - - # check ASIC inseg database - self.check_inseg_entries(False, [label]) - self.check_nexthop_group(False, nhg) - # IP NHs are created by neighbor resolution and should still be present - self.check_nexthop(True, "SAI_NEXT_HOP_TYPE_IP", "10.0.0.1", "", "") - self.check_nexthop(True, "SAI_NEXT_HOP_TYPE_IP", "10.0.0.5", "", "") - - self.teardown_mpls(dvs) - - def test_RouteAddRemoveIpRouteMixedNHG(self, dvs, testlog): - self.setup_mpls(dvs, True) - - # add route entry - prefix = "2.2.2.0/24" - if self.mpls_appdb_mode(): - fieldValues = {"nexthop": "10.0.0.1,10.0.0.5", "ifname": "Ethernet0,Ethernet8", "mpls_nh": "push200,na"} - self.create_route_entry(prefix, fieldValues) - else: - dvs.runcmd("ip route add 2.2.2.0/24 nexthop encap mpls 200 via inet 10.0.0.1 dev Ethernet0 nexthop via inet 10.0.0.5 dev Ethernet8") - - # check application database - self.pdb.wait_for_entry("ROUTE_TABLE", prefix) - - # check ASIC route database - self.check_route_entries(True, [prefix]) - self.check_route_nexthop_group(prefix, 2) - self.check_nexthop(True, "SAI_NEXT_HOP_TYPE_MPLS", "10.0.0.1", "SAI_OUTSEG_TYPE_PUSH", "1:200") - self.check_nexthop(True, "SAI_NEXT_HOP_TYPE_IP", "10.0.0.5", "", "") - nhg = self.get_route_nexthop(prefix) - - # remove route entry - if self.mpls_appdb_mode(): - self.remove_route_entry(prefix) - else: - dvs.runcmd("ip route del 2.2.2.0/24 nexthop encap mpls 200 via inet 10.0.0.1 dev Ethernet0 nexthop via inet 10.0.0.5 dev Ethernet8") - - # check application database - self.pdb.wait_for_deleted_entry("ROUTE_TABLE", prefix) - - # check ASIC route database - self.check_route_entries(False, [prefix]) - self.check_nexthop_group(False, nhg) - self.check_nexthop(False, "SAI_NEXT_HOP_TYPE_MPLS", "10.0.0.1", "SAI_OUTSEG_TYPE_SWAP", "1:200") - # IP NHs are created by neighbor resolution and should still be present - self.check_nexthop(True, "SAI_NEXT_HOP_TYPE_IP", "10.0.0.5", "", "") - - self.teardown_mpls(dvs) - - def test_RouteAddRemoveMplsRouteMixedNHG(self, dvs, testlog): - self.setup_mpls(dvs, True) - - # add route entry - label = "200" - if self.mpls_appdb_mode(): - fieldValues = {"nexthop": "10.0.0.1,10.0.0.5", "ifname": "Ethernet0,Ethernet8", "mpls_nh": "na,swap201", "mpls_pop": "1"} - self.create_inseg_entry(label, fieldValues) - else: - dvs.runcmd("ip -f mpls route add 200 nexthop via inet 10.0.0.1 dev Ethernet0 nexthop as 201 via inet 10.0.0.5 dev Ethernet8") - - # check application database - self.pdb.wait_for_entry("LABEL_ROUTE_TABLE", label) - - # check ASIC route database - self.check_inseg_entries(True, [label]) - self.check_inseg_nexthop_group(label, 2) - self.check_nexthop(True, "SAI_NEXT_HOP_TYPE_IP", "10.0.0.1", "", "") - self.check_nexthop(True, "SAI_NEXT_HOP_TYPE_MPLS", "10.0.0.5", "SAI_OUTSEG_TYPE_SWAP", "1:201") - nhg = self.get_inseg_nexthop(label) - - # remove inseg entry - if self.mpls_appdb_mode(): - self.remove_inseg_entry(label) - else: - dvs.runcmd("ip -f mpls route del 200 nexthop via inet 10.0.0.1 dev Ethernet0 nexthop as 201 via inet 10.0.0.5 dev Ethernet8") - - # check application database - self.pdb.wait_for_deleted_entry("LABEL_ROUTE_TABLE", label) - - # check ASIC route database - self.check_inseg_entries(False, [label]) - self.check_nexthop_group(False, nhg) - self.check_nexthop(False, "SAI_NEXT_HOP_TYPE_MPLS", "10.0.0.5", "SAI_OUTSEG_TYPE_SWAP", "1:201") - # IP NHs are created by neighbor resolution and should still be present - self.check_nexthop(True, "SAI_NEXT_HOP_TYPE_IP", "10.0.0.1", "", "") - - self.teardown_mpls(dvs) - - def test_RouteAddRemoveMplsRouteResolveNeigh(self, dvs, testlog): - if not self.mpls_appdb_mode(): - dvs.runcmd("modprobe mpls_router") - dvs.runcmd("modprobe mpls_iptunnel") - dvs.runcmd("sysctl -w net.mpls.platform_labels=1000") - - self.setup_db(dvs) - - self.clear_srv_config(dvs) - - # create mpls interface - self.create_mpls_intf("Ethernet0") - self.create_mpls_intf("Ethernet4") - - # set ip address - self.add_ip_address("Ethernet0", "10.0.0.0/31") - self.add_ip_address("Ethernet4", "10.0.0.2/31") - - # bring up interface - self.set_admin_status("Ethernet0", "up") - self.set_admin_status("Ethernet4", "up") - - # set ip address and default route - dvs.servers[0].runcmd("ip address add 10.0.0.1/31 dev eth0") - dvs.servers[0].runcmd("ip route add default via 10.0.0.0") - - dvs.servers[1].runcmd("ip address add 10.0.0.3/31 dev eth0") - dvs.servers[1].runcmd("ip route add default via 10.0.0.2") - time.sleep(2) - - # add route entries. The neighbor entries for 10.0.0.1 and 10.0.0.3 are not yet resolved, so will trigger an ARP request - label = "100" - label2 = "200" - if self.mpls_appdb_mode(): - fieldValues = {"nexthop": "10.0.0.1", "ifname": "Ethernet0", "mpls_nh": "swap101", "mpls_pop": "1"} - self.create_inseg_entry(label, fieldValues) - fieldValues = {"nexthop": "10.0.0.1,10.0.0.3", "ifname": "Ethernet0,Ethernet4", "mpls_nh": "swap201,swap202", "mpls_pop": "1"} - self.create_inseg_entry(label2, fieldValues) - else: - dvs.runcmd("ip -f mpls route add 100 nexthop as 101 via inet 10.0.0.1 dev Ethernet0") - dvs.runcmd("ip -f mpls route add 200 nexthop as 201 via inet 10.0.0.1 dev Ethernet0 nexthop as 202 via inet 10.0.0.3 dev Ethernet4") - - # check application database - self.pdb.wait_for_entry("LABEL_ROUTE_TABLE", label) - self.pdb.wait_for_entry("LABEL_ROUTE_TABLE", label2) - - # check neighbor got resolved and removed from NEIGH_RESOLVE_TABLE - self.pdb.wait_for_deleted_entry("NEIGH_RESOLVE_TABLE", "Ethernet0:10.0.0.1") - self.pdb.wait_for_deleted_entry("NEIGH_RESOLVE_TABLE", "Ethernet4:10.0.0.3") - - # check ASIC inseg database - self.check_inseg_entries(True, [label]) - self.check_inseg_nexthop(label, "SAI_NEXT_HOP_TYPE_MPLS", "10.0.0.1", "SAI_OUTSEG_TYPE_SWAP", "1:101") - self.check_inseg_entries(True, [label2]) - self.check_inseg_nexthop_group(label2, 2) - self.check_nexthop(True, "SAI_NEXT_HOP_TYPE_MPLS", "10.0.0.1", "SAI_OUTSEG_TYPE_SWAP", "1:201") - self.check_nexthop(True, "SAI_NEXT_HOP_TYPE_MPLS", "10.0.0.3", "SAI_OUTSEG_TYPE_SWAP", "1:202") - nhg = self.get_inseg_nexthop(label) - - # remove inseg entry - if self.mpls_appdb_mode(): - self.remove_inseg_entry(label) - self.remove_inseg_entry(label2) - else: - dvs.runcmd("ip -f mpls route del 100 nexthop as 101 via inet 10.0.0.1 dev Ethernet0") - dvs.runcmd("ip -f mpls route del 200 nexthop as 201 via inet 10.0.0.1 dev Ethernet0 nexthop as 202 via inet 10.0.0.3 dev Ethernet4") - - # check application database - self.pdb.wait_for_deleted_entry("LABEL_ROUTE_TABLE", label) - self.pdb.wait_for_deleted_entry("LABEL_ROUTE_TABLE", label2) - - # check ASIC route database - self.check_inseg_entries(False, [label]) - self.check_inseg_entries(False, [label2]) - self.check_nexthop_group(False, nhg) - self.check_nexthop(False, "SAI_NEXT_HOP_TYPE_MPLS", "10.0.0.1", "SAI_OUTSEG_TYPE_SWAP", "1:101") - self.check_nexthop(False, "SAI_NEXT_HOP_TYPE_MPLS", "10.0.0.1", "SAI_OUTSEG_TYPE_SWAP", "1:201") - self.check_nexthop(False, "SAI_NEXT_HOP_TYPE_MPLS", "10.0.0.3", "SAI_OUTSEG_TYPE_SWAP", "1:202") - - self.teardown_mpls(dvs) - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_mux.py b/tests/test_mux.py deleted file mode 100644 index 207ec6741b..0000000000 --- a/tests/test_mux.py +++ /dev/null @@ -1,1587 +0,0 @@ -import time -import pytest -import json -import itertools - -from ipaddress import ip_network, ip_address, IPv4Address -from swsscommon import swsscommon - -from mux_neigh_miss_tests import * - -def create_fvs(**kwargs): - return swsscommon.FieldValuePairs(list(kwargs.items())) - -tunnel_nh_id = 0 - -class TestMuxTunnelBase(): - APP_MUX_CABLE = "MUX_CABLE_TABLE" - APP_NEIGH_TABLE = "NEIGH_TABLE" - APP_ROUTE_TABLE = "ROUTE_TABLE" - APP_TUNNEL_DECAP_TABLE_NAME = "TUNNEL_DECAP_TABLE" - APP_TUNNEL_ROUTE_TABLE_NAME = "TUNNEL_ROUTE_TABLE" - ASIC_TUNNEL_TABLE = "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL" - ASIC_TUNNEL_TERM_ENTRIES = "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL_TERM_TABLE_ENTRY" - ASIC_RIF_TABLE = "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE" - ASIC_VRF_TABLE = "ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER" - ASIC_NEIGH_TABLE = "ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY" - ASIC_NEXTHOP_TABLE = "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP" - ASIC_NHG_MEMBER_TABLE = "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER" - ASIC_ROUTE_TABLE = "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY" - ASIC_FDB_TABLE = "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY" - ASIC_SWITCH_TABLE = "ASIC_STATE:SAI_OBJECT_TYPE_SWITCH" - CONFIG_MUX_CABLE = "MUX_CABLE" - CONFIG_PEER_SWITCH = "PEER_SWITCH" - STATE_FDB_TABLE = "FDB_TABLE" - MUX_TUNNEL_0 = "MuxTunnel0" - PEER_SWITCH_HOST = "peer_switch_hostname" - CONFIG_TUNNEL_TABLE_NAME = "TUNNEL" - ASIC_QOS_MAP_TABLE_KEY = "ASIC_STATE:SAI_OBJECT_TYPE_QOS_MAP" - TUNNEL_QOS_MAP_NAME = "AZURE_TUNNEL" - - SELF_IPV4 = "10.1.0.32" - PEER_IPV4 = "10.1.0.33" - SERV1_IPV4 = "192.168.0.100" - SERV1_IPV6 = "fc02:1000::100" - SERV1_SOC_IPV4 = "192.168.0.103" - SERV2_IPV4 = "192.168.0.101" - SERV2_IPV6 = "fc02:1000::101" - SERV3_IPV4 = "192.168.0.102" - SERV3_IPV6 = "fc02:1000::102" - NEIGH1_IPV4 = "192.168.0.200" - NEIGH1_IPV6 = "fc02:1000::200" - NEIGH2_IPV4 = "192.168.0.201" - NEIGH2_IPV6 = "fc02:1000::201" - NEIGH3_IPV4 = "192.168.0.202" - NEIGH3_IPV6 = "fc02:1000::202" - IPV4_MASK = "/32" - IPV6_MASK = "/128" - TUNNEL_NH_ID = 0 - ACL_PRIORITY = "999" - VLAN_1000 = "Vlan1000" - - PING_CMD = "timeout 0.5 ping -c1 -W1 -i0 -n -q {ip}" - - SAI_ROUTER_INTERFACE_ATTR_TYPE = "SAI_ROUTER_INTERFACE_ATTR_TYPE" - SAI_ROUTER_INTERFACE_TYPE_VLAN = "SAI_ROUTER_INTERFACE_TYPE_VLAN" - - DEFAULT_TUNNEL_PARAMS = { - "tunnel_type": "IPINIP", - "dst_ip": SELF_IPV4, - "dscp_mode": "pipe", - "ecn_mode": "standard", - "ttl_mode": "pipe", - "encap_tc_to_queue_map": TUNNEL_QOS_MAP_NAME, - "encap_tc_to_dscp_map": TUNNEL_QOS_MAP_NAME, - "decap_dscp_to_tc_map": TUNNEL_QOS_MAP_NAME, - "decap_tc_to_pg_map": TUNNEL_QOS_MAP_NAME - } - - DEFAULT_PEER_SWITCH_PARAMS = { - "address_ipv4": PEER_IPV4 - } - - ecn_modes_map = { - "standard" : "SAI_TUNNEL_DECAP_ECN_MODE_STANDARD", - "copy_from_outer": "SAI_TUNNEL_DECAP_ECN_MODE_COPY_FROM_OUTER" - } - - dscp_modes_map = { - "pipe" : "SAI_TUNNEL_DSCP_MODE_PIPE_MODEL", - "uniform" : "SAI_TUNNEL_DSCP_MODE_UNIFORM_MODEL" - } - - ttl_modes_map = { - "pipe" : "SAI_TUNNEL_TTL_MODE_PIPE_MODEL", - "uniform" : "SAI_TUNNEL_TTL_MODE_UNIFORM_MODEL" - } - - TC_TO_DSCP_MAP = {str(i):str(i) for i in range(0, 8)} - TC_TO_QUEUE_MAP = {str(i):str(i) for i in range(0, 8)} - DSCP_TO_TC_MAP = {str(i):str(1) for i in range(0, 64)} - TC_TO_PRIORITY_GROUP_MAP = {str(i):str(i) for i in range(0, 8)} - - def check_syslog(self, dvs, marker, err_log, expected_cnt): - (exitcode, num) = dvs.runcmd(['sh', '-c', "awk \'/%s/,ENDFILE {print;}\' /var/log/syslog | grep \"%s\" | wc -l" % (marker, err_log)]) - assert num.strip() >= str(expected_cnt) - - def create_vlan_interface(self, dvs): - confdb = dvs.get_config_db() - - fvs = {"vlanid": "1000"} - confdb.create_entry("VLAN", self.VLAN_1000, fvs) - - fvs = {"tagging_mode": "untagged"} - confdb.create_entry("VLAN_MEMBER", "Vlan1000|Ethernet0", fvs) - confdb.create_entry("VLAN_MEMBER", "Vlan1000|Ethernet4", fvs) - confdb.create_entry("VLAN_MEMBER", "Vlan1000|Ethernet8", fvs) - - fvs = {"NULL": "NULL"} - confdb.create_entry("VLAN_INTERFACE", self.VLAN_1000, fvs) - confdb.create_entry("VLAN_INTERFACE", "Vlan1000|192.168.0.1/24", fvs) - confdb.create_entry("VLAN_INTERFACE", "Vlan1000|fc02:1000::1/64", fvs) - - dvs.port_admin_set("Ethernet0", "up") - dvs.port_admin_set("Ethernet4", "up") - dvs.port_admin_set("Ethernet8", "up") - - def create_mux_cable(self, confdb): - fvs = { - "server_ipv4":self.SERV1_IPV4 + self.IPV4_MASK, - "server_ipv6":self.SERV1_IPV6 + self.IPV6_MASK, - "soc_ipv4": self.SERV1_SOC_IPV4 + self.IPV4_MASK, - "cable_type": "active-active" # "cable_type" is not used by orchagent, this is a dummy value - } - confdb.create_entry(self.CONFIG_MUX_CABLE, "Ethernet0", fvs) - - fvs = {"server_ipv4": self.SERV2_IPV4+self.IPV4_MASK, - "server_ipv6": self.SERV2_IPV6+self.IPV6_MASK} - confdb.create_entry(self.CONFIG_MUX_CABLE, "Ethernet4", fvs) - - fvs = {"server_ipv4": self.SERV3_IPV4+self.IPV4_MASK, - "server_ipv6": self.SERV3_IPV6+self.IPV6_MASK} - confdb.create_entry(self.CONFIG_MUX_CABLE, "Ethernet8", fvs) - - def set_mux_state(self, appdb, ifname, state_change): - - ps = swsscommon.ProducerStateTable(appdb, self.APP_MUX_CABLE) - - fvs = create_fvs(state=state_change) - - ps.set(ifname, fvs) - - time.sleep(1) - - def get_switch_oid(self, asicdb): - # Assumes only one switch is ever present - keys = asicdb.wait_for_n_keys(self.ASIC_SWITCH_TABLE, 1) - return keys[0] - - def get_vlan_rif_oid(self, asicdb): - # create_vlan_interface should be called before this method - # Assumes only one VLAN RIF is present - rifs = asicdb.get_keys(self.ASIC_RIF_TABLE) - - vlan_oid = '' - for rif_key in rifs: - entry = asicdb.get_entry(self.ASIC_RIF_TABLE, rif_key) - if entry[self.SAI_ROUTER_INTERFACE_ATTR_TYPE] == self.SAI_ROUTER_INTERFACE_TYPE_VLAN: - vlan_oid = rif_key - break - - return vlan_oid - - def get_nexthop_oid(self, asicdb, nexthop): - # gets nexthop oid - nexthop_keys = asicdb.get_keys(self.ASIC_NEXTHOP_TABLE) - - nexthop_oid = '' - for nexthop_key in nexthop_keys: - entry = asicdb.get_entry(self.ASIC_NEXTHOP_TABLE, nexthop_key) - if entry["SAI_NEXT_HOP_ATTR_IP"] == nexthop: - nexthop_oid = nexthop_key - break - - return nexthop_oid - - def get_route_nexthop_oid(self, route_key, asicdb): - # gets nexthop oid - entry = asicdb.get_entry(self.ASIC_ROUTE_TABLE, route_key) - assert 'SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID' in entry - - return entry['SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID'] - - def check_tunnel_route_in_app_db(self, dvs, destinations, expected=True): - appdb = dvs.get_app_db() - - if expected: - appdb.wait_for_matching_keys(self.APP_TUNNEL_ROUTE_TABLE_NAME, destinations) - else: - appdb.wait_for_deleted_keys(self.APP_TUNNEL_ROUTE_TABLE_NAME, destinations) - - def check_neigh_in_asic_db(self, asicdb, ip, expected=True): - rif_oid = self.get_vlan_rif_oid(asicdb) - switch_oid = self.get_switch_oid(asicdb) - neigh_key_map = { - "ip": ip, - "rif": rif_oid, - "switch_id": switch_oid - } - expected_key = json.dumps(neigh_key_map, sort_keys=True, separators=(',', ':')) - - if expected: - nbr_keys = asicdb.wait_for_matching_keys(self.ASIC_NEIGH_TABLE, [expected_key]) - - for key in nbr_keys: - if ip in key: - return key - - else: - asicdb.wait_for_deleted_keys(self.ASIC_NEIGH_TABLE, [expected_key]) - - return '' - - def check_tnl_nexthop_in_asic_db(self, asicdb, expected=1): - - global tunnel_nh_id - - nh = asicdb.wait_for_n_keys(self.ASIC_NEXTHOP_TABLE, expected) - - for key in nh: - fvs = asicdb.get_entry(self.ASIC_NEXTHOP_TABLE, key) - if fvs.get("SAI_NEXT_HOP_ATTR_TYPE") == "SAI_NEXT_HOP_TYPE_TUNNEL_ENCAP": - tunnel_nh_id = key - - assert tunnel_nh_id - - def check_nexthop_in_asic_db(self, asicdb, key, standby=False): - - fvs = asicdb.get_entry(self.ASIC_ROUTE_TABLE, key) - if not fvs: - assert False - - nhid = fvs.get("SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID") - if standby: - assert (nhid == tunnel_nh_id) - else: - assert (nhid != tunnel_nh_id) - - def check_nexthop_group_in_asic_db(self, asicdb, key, num_tnl_nh=0): - - fvs = asicdb.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY", key) - - nhg_id = fvs["SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID"] - - asicdb.wait_for_entry("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP", nhg_id) - - # Two NH group members are expected to be added - keys = asicdb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER", 2) - - count = 0 - - for k in keys: - fvs = asicdb.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER", k) - assert fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID"] == nhg_id - - # Count the number of Nexthop member pointing to tunnel - if fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID"] == tunnel_nh_id: - count += 1 - - assert num_tnl_nh == count - - def check_route_nexthop(self, dvs_route, asicdb, route, nexthop, tunnel=False): - route_key = dvs_route.check_asicdb_route_entries([route]) - route_nexthop_oid = self.get_route_nexthop_oid(route_key[0], asicdb) - - if tunnel: - assert route_nexthop_oid == nexthop - return - - nexthop_oid = self.get_nexthop_oid(asicdb, nexthop) - - assert route_nexthop_oid == nexthop_oid - - def add_neighbor(self, dvs, ip, mac): - if ip_address(ip).version == 6: - dvs.runcmd("ip -6 neigh replace " + ip + " lladdr " + mac + " dev Vlan1000") - else: - dvs.runcmd("ip -4 neigh replace " + ip + " lladdr " + mac + " dev Vlan1000") - - def del_neighbor(self, dvs, ip): - cmd = 'ip neigh del {} dev {}'.format(ip, self.VLAN_1000) - dvs.runcmd(cmd) - - def add_fdb(self, dvs, port, mac): - - appdb = dvs.get_app_db() - ps = swsscommon.ProducerStateTable(appdb.db_connection, "FDB_TABLE") - fvs = swsscommon.FieldValuePairs([("port", port), ("type", "dynamic")]) - - ps.set("Vlan1000:"+mac, fvs) - - time.sleep(1) - - def del_fdb(self, dvs, mac): - - appdb = dvs.get_app_db() - ps = swsscommon.ProducerStateTable(appdb.db_connection, "FDB_TABLE") - ps._del("Vlan1000:"+mac) - - time.sleep(1) - - def add_route(self, dvs, route, nexthops, ifaces=[]): - apdb = dvs.get_app_db() - if len(nexthops) > 1: - nexthop_str = ",".join(nexthops) - if len(ifaces) == 0: - ifaces = [self.VLAN_1000 for k in range(len(nexthops))] - iface_str = ",".join(ifaces) - else: - nexthop_str = str(nexthops[0]) - if len(ifaces) == 0: - iface_str = self.VLAN_1000 - else: - iface_str = ifaces[0] - - ps = swsscommon.ProducerStateTable(apdb.db_connection, self.APP_ROUTE_TABLE) - fvs = swsscommon.FieldValuePairs( - [ - ("nexthop", nexthop_str), - ("ifname", iface_str) - ] - ) - ps.set(route, fvs) - - def del_route(self, dvs, route): - apdb = dvs.get_app_db() - ps = swsscommon.ProducerStateTable(apdb.db_connection, self.APP_ROUTE_TABLE) - ps._del(route) - - def create_and_test_neighbor(self, confdb, appdb, asicdb, dvs, dvs_route): - - self.set_mux_state(appdb, "Ethernet0", "active") - self.set_mux_state(appdb, "Ethernet4", "standby") - - self.add_neighbor(dvs, self.SERV1_IPV4, "00:00:00:00:00:01") - srv1_v4 = self.check_neigh_in_asic_db(asicdb, self.SERV1_IPV4) - - self.add_neighbor(dvs, self.SERV1_IPV6, "00:00:00:00:00:01") - srv1_v6 = self.check_neigh_in_asic_db(asicdb, self.SERV1_IPV6) - - existing_keys = asicdb.get_keys(self.ASIC_NEIGH_TABLE) - - self.add_neighbor(dvs, self.SERV2_IPV4, "00:00:00:00:00:02") - self.add_neighbor(dvs, self.SERV2_IPV6, "00:00:00:00:00:02") - time.sleep(1) - - # In standby mode, the entry must not be added to Neigh table but Route - asicdb.wait_for_matching_keys(self.ASIC_NEIGH_TABLE, existing_keys) - dvs_route.check_asicdb_route_entries( - [self.SERV2_IPV4+self.IPV4_MASK, self.SERV2_IPV6+self.IPV6_MASK] - ) - - # The first standby route also creates as tunnel Nexthop - self.check_tnl_nexthop_in_asic_db(asicdb, 3) - - # Change state to Standby. This will delete Neigh and add Route - self.set_mux_state(appdb, "Ethernet0", "standby") - - asicdb.wait_for_deleted_entry(self.ASIC_NEIGH_TABLE, srv1_v4) - asicdb.wait_for_deleted_entry(self.ASIC_NEIGH_TABLE, srv1_v6) - dvs_route.check_asicdb_route_entries( - [self.SERV1_IPV4+self.IPV4_MASK, self.SERV1_IPV6+self.IPV6_MASK] - ) - - # Change state to Active. This will add Neigh and delete Route - self.set_mux_state(appdb, "Ethernet4", "active") - - dvs_route.check_asicdb_deleted_route_entries( - [self.SERV2_IPV4+self.IPV4_MASK, self.SERV2_IPV6+self.IPV6_MASK] - ) - self.check_neigh_in_asic_db(asicdb, self.SERV2_IPV4) - self.check_neigh_in_asic_db(asicdb, self.SERV2_IPV6) - - def create_and_test_soc(self, appdb, asicdb, dvs, dvs_route): - - self.set_mux_state(appdb, "Ethernet0", "active") - - self.add_fdb(dvs, "Ethernet0", "00-00-00-00-00-01") - self.add_neighbor(dvs, self.SERV1_SOC_IPV4, "00:00:00:00:00:01") - - time.sleep(1) - - srv1_soc_v4 = self.check_neigh_in_asic_db(asicdb, self.SERV1_SOC_IPV4) - self.check_tunnel_route_in_app_db(dvs, [self.SERV1_SOC_IPV4+self.IPV4_MASK], expected=False) - - self.set_mux_state(appdb, "Ethernet0", "standby") - - asicdb.wait_for_deleted_entry(self.ASIC_NEIGH_TABLE, srv1_soc_v4) - dvs_route.check_asicdb_route_entries( - [self.SERV1_SOC_IPV4+self.IPV4_MASK] - ) - self.check_tunnel_route_in_app_db(dvs, [self.SERV1_SOC_IPV4+self.IPV4_MASK], expected=False) - - marker = dvs.add_log_marker() - - self.set_mux_state(appdb, "Ethernet0", "active") - self.set_mux_state(appdb, "Ethernet0", "active") - self.check_syslog(dvs, marker, "Maintaining current MUX state", 1) - - self.set_mux_state(appdb, "Ethernet0", "init") - self.check_syslog(dvs, marker, "State transition from active to init is not-handled", 1) - - def create_and_test_fdb(self, appdb, asicdb, dvs, dvs_route): - - self.set_mux_state(appdb, "Ethernet0", "active") - self.set_mux_state(appdb, "Ethernet4", "standby") - - self.add_fdb(dvs, "Ethernet0", "00-00-00-00-00-11") - self.add_fdb(dvs, "Ethernet4", "00-00-00-00-00-12") - - ip_1 = "fc02:1000::10" - ip_2 = "fc02:1000::11" - - self.add_neighbor(dvs, ip_1, "00:00:00:00:00:11") - self.add_neighbor(dvs, ip_2, "00:00:00:00:00:12") - - # ip_1 is on Active Mux, hence added to Host table - self.check_neigh_in_asic_db(asicdb, ip_1) - - # ip_2 is on Standby Mux, hence added to Route table - dvs_route.check_asicdb_route_entries([ip_2+self.IPV6_MASK]) - - # Check ip_1 move to standby mux, should be pointing to tunnel - self.add_neighbor(dvs, ip_1, "00:00:00:00:00:12") - - # ip_1 moved to standby Mux, hence added to Route table - dvs_route.check_asicdb_route_entries([ip_1+self.IPV6_MASK]) - - # Check ip_2 move to active mux, should be host entry - self.add_neighbor(dvs, ip_2, "00:00:00:00:00:11") - - # ip_2 moved to active Mux, hence remove from Route table - dvs_route.check_asicdb_deleted_route_entries([ip_2+self.IPV6_MASK]) - self.check_neigh_in_asic_db(asicdb, ip_2) - - # Simulate FDB aging out test case - ip_3 = "192.168.0.200" - - self.add_neighbor(dvs, ip_3, "00:00:00:00:00:12") - - # ip_3 is added to standby mux - dvs_route.check_asicdb_route_entries([ip_3+self.IPV4_MASK]) - - # Simulate FDB age out - self.del_fdb(dvs, "00-00-00-00-00-12") - - # FDB ageout is not expected to change existing state of neighbor - dvs_route.check_asicdb_route_entries([ip_3+self.IPV4_MASK]) - - # Change to active - self.set_mux_state(appdb, "Ethernet4", "active") - dvs_route.check_asicdb_deleted_route_entries([ip_3+self.IPV4_MASK]) - - self.del_fdb(dvs, "00-00-00-00-00-11") - - def create_and_test_route(self, appdb, asicdb, dvs, dvs_route): - - self.set_mux_state(appdb, "Ethernet0", "active") - - rtprefix = "2.3.4.0/24" - - dvs.runcmd( - "vtysh -c \"configure terminal\" -c \"ip route " + rtprefix + - " " + self.SERV1_IPV4 + "\"" - ) - - pdb = dvs.get_app_db() - pdb.wait_for_entry("ROUTE_TABLE", rtprefix) - - rtkeys = dvs_route.check_asicdb_route_entries([rtprefix]) - - self.check_nexthop_in_asic_db(asicdb, rtkeys[0]) - - # Change Mux state to Standby and verify route pointing to Tunnel - self.set_mux_state(appdb, "Ethernet0", "standby") - - self.check_nexthop_in_asic_db(asicdb, rtkeys[0], True) - - # Change Mux state back to Active and verify route is not pointing to Tunnel - self.set_mux_state(appdb, "Ethernet0", "active") - - self.check_nexthop_in_asic_db(asicdb, rtkeys[0]) - - # Check route set flow and changing nexthop - self.set_mux_state(appdb, "Ethernet4", "active") - - ps = swsscommon.ProducerStateTable(pdb.db_connection, "ROUTE_TABLE") - fvs = swsscommon.FieldValuePairs([("nexthop", self.SERV2_IPV4), ("ifname", "Vlan1000")]) - ps.set(rtprefix, fvs) - - # Check if route was propagated to ASIC DB - rtkeys = dvs_route.check_asicdb_route_entries([rtprefix]) - - # Change Mux status for Ethernet0 and expect no change to replaced route - self.set_mux_state(appdb, "Ethernet0", "standby") - self.check_nexthop_in_asic_db(asicdb, rtkeys[0]) - - self.set_mux_state(appdb, "Ethernet4", "standby") - self.check_nexthop_in_asic_db(asicdb, rtkeys[0], True) - - # Delete the route - ps._del(rtprefix) - - self.set_mux_state(appdb, "Ethernet4", "active") - dvs_route.check_asicdb_deleted_route_entries([rtprefix]) - - dvs.runcmd( - "vtysh -c \"configure terminal\" -c \"no ip route " + rtprefix + - " " + self.SERV1_IPV4 + "\"" - ) - - def multi_nexthop_check(self, asicdb, dvs_route, route, nexthops, mux_states, non_mux_nexthop = None): - if isinstance(route, list): - route_copy = route.copy() - else: - route_copy = [route] - - for r in route_copy: - if non_mux_nexthop != None: - self.check_route_nexthop(dvs_route, asicdb, r, non_mux_nexthop) - continue - for i,state in enumerate(mux_states): - # Find first active mux port, and check that route points to that neighbor - if state == ACTIVE: - self.check_route_nexthop(dvs_route, asicdb, r, nexthops[i]) - break - else: - # If no active mux port, check that route points to tunnel - self.check_route_nexthop(dvs_route, asicdb, r, tunnel_nh_id, True) - - def multi_nexthop_test_create(self, appdb, asicdb, dvs, dvs_route, route, mux_ports, nexthops, non_mux_nexthop = None): - ''' - Tests the creation of a route with multiple nexthops in various combinations of initial mux state - ''' - init_mux_states = list(itertools.product([ACTIVE, STANDBY], repeat=len(mux_ports))) - - print("Test create route in various combos of mux nexthop states for route with multiple nexthops") - for states in init_mux_states: - print("Create route with mux ports: %s in states: %s" % (str(mux_ports), str(states))) - # Set mux states - for i,port in enumerate(mux_ports): - self.set_mux_state(appdb, port, states[i]) - - # Add route - if non_mux_nexthop != None: - self.add_route(dvs, route, nexthops + [non_mux_nexthop]) - else: - self.add_route(dvs, route, nexthops) - self.multi_nexthop_check(asicdb, dvs_route, route, nexthops, states, non_mux_nexthop) - - self.del_route(dvs, route) - - def multi_nexthop_test_fdb(self, appdb, asicdb, dvs, dvs_route, route, mux_ports, nexthops, macs): - ''' - Tests fbd updates for mux neighbors - ''' - init_mux_states = list(itertools.product([ACTIVE, STANDBY], repeat=len(mux_ports))) - - print("Test fdb update on route with multiple mux nexthops for various mux states") - for states in init_mux_states: - print("Testing fdb update in states: %s, for nexthops: %s" % (str(states), str(nexthops))) - - # Set mux states - for i,port in enumerate(mux_ports): - self.set_mux_state(appdb, port, states[i]) - - for i,nexthop in enumerate(nexthops): - print("Triggering fdb update for %s" % (nexthop)) - # only supports testing up to 9 nexhops at the moment - self.add_neighbor(dvs, nexthop, "00:aa:bb:cc:dd:0%d" % (i)) - self.multi_nexthop_check(asicdb, dvs_route, route, nexthops, states) - - # Reset fdb - self.add_neighbor(dvs, nexthop, macs[i]) - - def multi_nexthop_test_toggle(self, appdb, asicdb, dvs_route, route, mux_ports, nexthops, non_mux_nexthop=None): - ''' - Tests toggling mux state for a route with multiple nexthops - ''' - init_mux_states = list(list(tup) for tup in itertools.product([ACTIVE, STANDBY], repeat=len(mux_ports))) - - print("Test toggling mux state for route with multiple mux nexthops") - for states in init_mux_states: - print("Testing state change in states: %s, for nexthops: %s" % (str(states), str(nexthops))) - for i,port in enumerate(mux_ports): - if nexthops[i] == non_mux_nexthop: - continue - self.set_mux_state(appdb, port, states[i]) - - for toggle_index,toggle_port in enumerate(mux_ports): - if nexthops[toggle_index] == non_mux_nexthop: - continue - new_states = states.copy() - - print("Toggling %s from %s" % (toggle_port, states[toggle_index])) - - if states[toggle_index] == ACTIVE: - new_states[toggle_index] = STANDBY - self.set_mux_state(appdb, toggle_port, STANDBY) - self.multi_nexthop_check(asicdb, dvs_route, route, nexthops, new_states, non_mux_nexthop) - - new_states[toggle_index] = ACTIVE - self.set_mux_state(appdb, toggle_port, ACTIVE) - self.multi_nexthop_check(asicdb, dvs_route, route, nexthops, new_states, non_mux_nexthop) - else: - new_states[toggle_index] = ACTIVE - self.set_mux_state(appdb, toggle_port, ACTIVE) - self.multi_nexthop_check(asicdb, dvs_route, route, nexthops, new_states, non_mux_nexthop) - - new_states[toggle_index] = STANDBY - self.set_mux_state(appdb, toggle_port, STANDBY) - self.multi_nexthop_check(asicdb, dvs_route, route, nexthops, new_states, non_mux_nexthop) - - # Set everything back to active - for i,port in enumerate(mux_ports): - if nexthops[i] == non_mux_nexthop: - continue - self.set_mux_state(appdb, port, ACTIVE) - - def multi_nexthop_test_route_update_keep_size(self, appdb, asicdb, dvs, dvs_route, route, mux_ports, nexthops, new_nexthop, new_mux_port, nh_is_mux=True): - ''' - Tests route update for a route with multiple nexthops with same number of nexthops - - nh_is_mux: is True if new nexthop is a mux nexthop, False if not - ''' - # Add route - self.add_route(dvs, route, nexthops) - - print("Test route update for route with multiple mux nexthops") - for i,nexthop in enumerate(nexthops): - new_nexthops = nexthops.copy() - new_muxports = mux_ports.copy() - - print("Triggering route update %s to replace: %s with: %s" % (str(new_nexthops), str(nexthop), str(new_nexthop))) - new_nexthops[i] = new_nexthop - new_muxports[i] = new_mux_port - - if nh_is_mux: - # We need to sort the nexthops to match the way they will pe processed - new_nexthops.sort() - new_muxports.sort() - - self.add_route(dvs, route, new_nexthops) - - if nh_is_mux: - self.multi_nexthop_test_toggle(appdb, asicdb, dvs_route, route, new_muxports, new_nexthops) - else: - self.multi_nexthop_test_toggle(appdb, asicdb, dvs_route, route, new_muxports, new_nexthops, non_mux_nexthop=new_nexthop) - - # Reset route - self.add_route(dvs, route, nexthops) - - self.del_route(dvs, route) - - def multi_nexthop_test_route_update_increase_size(self, appdb, asicdb, dvs, dvs_route, route, mux_ports, nexthops, non_mux_nexthop=None): - ''' - Tests route update for a route with multiple nexthops increasing number of nexthops over time - ''' - print("Test route update for route with multiple mux nexthops") - for i,nexthop in enumerate(nexthops): - print("Triggering route update to add: %s. new route %s -> %s" % (str(nexthop), route, nexthops[:i+1])) - self.add_route(dvs, route, nexthops[:i+1]) - self.multi_nexthop_test_toggle(appdb, asicdb, dvs_route, route, mux_ports[:i+1], nexthops[:i+1]) - - # Add non_mux_nexthop to route list - if non_mux_nexthop != None: - print("Triggering route update to add non_mux: %s. new route %s -> %s" % (str(non_mux_nexthop), route, nexthops + [non_mux_nexthop])) - self.add_route(dvs, route, nexthops + [non_mux_nexthop]) - self.multi_nexthop_test_toggle(appdb, asicdb, dvs_route, route, mux_ports + [None], nexthops + [non_mux_nexthop], non_mux_nexthop=non_mux_nexthop) - - self.del_route(dvs, route) - - def multi_nexthop_test_route_update_decrease_size(self, appdb, asicdb, dvs, dvs_route, route, mux_ports, nexthops, non_mux_nexthop=None): - ''' - Tests route update for a route with multiple nexthops increasing number of nexthops over time - ''' - print("Test route update for route with multiple mux nexthops") - - if non_mux_nexthop != None: - print("Triggering route update to add non_mux: %s. new route %s -> %s" % (str(non_mux_nexthop), route, [non_mux_nexthop] + nexthops)) - self.add_route(dvs, route, [non_mux_nexthop] + nexthops) - self.multi_nexthop_test_toggle(appdb, asicdb, dvs_route, route, [None] + mux_ports, [non_mux_nexthop] + nexthops, non_mux_nexthop=non_mux_nexthop) - - for i,nexthop in enumerate(nexthops): - print("Triggering route update to remove: %s. new route %s -> %s" % (str(nexthop), route, nexthops[i:])) - self.add_route(dvs, route, nexthops[i:]) - self.multi_nexthop_test_toggle(appdb, asicdb, dvs_route, route, mux_ports[i:], nexthops[i:]) - - self.del_route(dvs, route) - - def multi_nexthop_test_neighbor_add(self, appdb, asicdb, dvs, dvs_route, route, mux_ports, nexthops, macs): - ''' - Tests adding neighbors for a route with multiple nexthops - ''' - print("Test adding neighbors for route with multiple mux nexthops") - for i,nexthop in enumerate(nexthops): - print("Triggering neighbor add for %s" % (nexthop)) - self.add_neighbor(dvs, nexthop, macs[i]) - self.multi_nexthop_test_toggle(appdb, asicdb, dvs_route, route, mux_ports, nexthops) - - def multi_nexthop_test_neighbor_del(self, appdb, asicdb, dvs, dvs_route, route, mux_ports, nexthops): - ''' - Tests deleting neighbors for a route with multiple nexthops - ''' - print("Test setting 0 mac neighbors for route with multiple mux nexthops") - for nexthop in nexthops: - print("Triggering neighbor del for %s" % (nexthop)) - self.add_neighbor(dvs, nexthop, "00:00:00:00:00:00") - self.multi_nexthop_test_toggle(appdb, asicdb, dvs_route, route, mux_ports, nexthops) - - def create_and_test_multi_nexthop_routes(self, dvs, dvs_route, appdb, macs, new_mac, asicdb): - ''' - Tests case where there are multiple nexthops tied to a route - If the nexthops are tied to a mux, then only the first active neighbor will be programmed - If not, the route should point to a regular ECMP group - ''' - - route_ipv4 = "2.3.4.0/24" - route_ipv6 = "2023::/64" - route_B_ipv4 = "2.3.5.0/24" - route_B_ipv6 = "2024::/64" - ipv4_nexthops = [self.SERV1_IPV4, self.SERV2_IPV4] - ipv6_nexthops = [self.SERV1_IPV6, self.SERV2_IPV6] - new_ipv4_nexthop = self.SERV3_IPV4 - new_ipv6_nexthop = self.SERV3_IPV6 - non_mux_ipv4 = "11.11.11.11" - non_mux_ipv6 = "2222::100" - non_mux_mac = "00:aa:aa:aa:aa:aa" - mux_ports = ["Ethernet0", "Ethernet4"] - new_mux_port = "Ethernet8" - - for i,mac in enumerate(macs): - self.add_neighbor(dvs, ipv4_nexthops[i], mac) - self.add_neighbor(dvs, ipv6_nexthops[i], mac) - - self.add_neighbor(dvs, new_ipv4_nexthop, new_mac) - self.add_neighbor(dvs, new_ipv6_nexthop, new_mac) - self.add_neighbor(dvs, non_mux_ipv4, non_mux_mac) - self.add_neighbor(dvs, non_mux_ipv6, non_mux_mac) - - for port in mux_ports: - self.set_mux_state(appdb, port, ACTIVE) - self.set_mux_state(appdb, new_mux_port, ACTIVE) - - try: - # These tests create route: - self.multi_nexthop_test_create(appdb, asicdb, dvs, dvs_route, route_ipv4, mux_ports, ipv4_nexthops) - self.multi_nexthop_test_create(appdb, asicdb, dvs, dvs_route, route_ipv6, mux_ports, ipv6_nexthops) - self.multi_nexthop_test_create(appdb, asicdb, dvs, dvs_route, route_ipv4, mux_ports, ipv4_nexthops, non_mux_ipv4) - self.multi_nexthop_test_create(appdb, asicdb, dvs, dvs_route, route_ipv6, mux_ports, ipv6_nexthops, non_mux_ipv6) - self.multi_nexthop_test_route_update_keep_size(appdb, asicdb, dvs, dvs_route, route_ipv4, mux_ports, ipv4_nexthops, new_ipv4_nexthop, new_mux_port) - self.multi_nexthop_test_route_update_keep_size(appdb, asicdb, dvs, dvs_route, route_ipv6, mux_ports, ipv6_nexthops, new_ipv6_nexthop, new_mux_port) - self.multi_nexthop_test_route_update_keep_size(appdb, asicdb, dvs, dvs_route, route_ipv4, mux_ports, ipv4_nexthops, non_mux_ipv4, None, nh_is_mux=False) - self.multi_nexthop_test_route_update_keep_size(appdb, asicdb, dvs, dvs_route, route_ipv6, mux_ports, ipv6_nexthops, non_mux_ipv6, None, nh_is_mux=False) - self.multi_nexthop_test_route_update_increase_size(appdb, asicdb, dvs, dvs_route, route_ipv4, mux_ports, ipv4_nexthops, non_mux_nexthop=non_mux_ipv4) - self.multi_nexthop_test_route_update_increase_size(appdb, asicdb, dvs, dvs_route, route_ipv6, mux_ports, ipv6_nexthops, non_mux_nexthop=non_mux_ipv6) - self.multi_nexthop_test_route_update_decrease_size(appdb, asicdb, dvs, dvs_route, route_ipv4, mux_ports, ipv4_nexthops, non_mux_nexthop=non_mux_ipv4) - self.multi_nexthop_test_route_update_decrease_size(appdb, asicdb, dvs, dvs_route, route_ipv6, mux_ports, ipv6_nexthops, non_mux_nexthop=non_mux_ipv6) - - # # These tests do not create route, so create beforehand: - self.add_route(dvs, route_ipv4, ipv4_nexthops) - self.add_route(dvs, route_ipv6, ipv6_nexthops) - self.add_route(dvs, route_B_ipv4, ipv4_nexthops) - self.add_route(dvs, route_B_ipv6, ipv6_nexthops) - - self.multi_nexthop_test_fdb(appdb, asicdb, dvs, dvs_route, [route_ipv4, route_B_ipv4], mux_ports, ipv4_nexthops, macs) - self.multi_nexthop_test_fdb(appdb, asicdb, dvs, dvs_route, [route_ipv6, route_B_ipv6], mux_ports, ipv6_nexthops, macs) - self.multi_nexthop_test_neighbor_add(appdb, asicdb, dvs, dvs_route, [route_ipv4, route_B_ipv4], mux_ports, ipv4_nexthops, macs) - self.multi_nexthop_test_neighbor_add(appdb, asicdb, dvs, dvs_route, [route_ipv6, route_B_ipv6], mux_ports, ipv6_nexthops, macs) - self.multi_nexthop_test_neighbor_del(appdb, asicdb, dvs, dvs_route, [route_ipv4, route_B_ipv4], mux_ports, ipv4_nexthops) - self.multi_nexthop_test_neighbor_del(appdb, asicdb, dvs, dvs_route, [route_ipv6, route_B_ipv6], mux_ports, ipv6_nexthops) - finally: - # Cleanup - self.del_route(dvs,route_ipv4) - self.del_route(dvs,route_B_ipv4) - self.del_route(dvs,route_ipv6) - self.del_route(dvs,route_B_ipv6) - for neighbor in ipv4_nexthops: - self.del_neighbor(dvs, neighbor) - for neighbor in ipv6_nexthops: - self.del_neighbor(dvs, neighbor) - self.del_neighbor(dvs, new_ipv4_nexthop) - self.del_neighbor(dvs, new_ipv6_nexthop) - - def create_and_test_NH_routes(self, appdb, asicdb, dvs, dvs_route, mac): - ''' - Tests case where neighbor is removed in standby and added in active with route - ''' - nh_route = "2.2.2.0/24" - nh_route_ipv6 = "2023::/64" - neigh_ip = self.SERV1_IPV4 - neigh_ipv6 = self.SERV1_IPV6 - apdb = dvs.get_app_db() - - # Setup - self.set_mux_state(appdb, "Ethernet0", "active") - self.add_neighbor(dvs, neigh_ip, mac) - self.add_neighbor(dvs, neigh_ipv6, mac) - dvs.runcmd( - "vtysh -c \"configure terminal\" -c \"ip route " + nh_route + - " " + neigh_ip + "\"" - ) - dvs.runcmd( - "vtysh -c \"configure terminal\" -c \"ipv6 route " + nh_route_ipv6 + - " " + neigh_ipv6 + "\"" - ) - apdb.wait_for_entry("ROUTE_TABLE", nh_route) - apdb.wait_for_entry("ROUTE_TABLE", nh_route_ipv6) - - rtkeys = dvs_route.check_asicdb_route_entries([nh_route]) - rtkeys_ipv6 = dvs_route.check_asicdb_route_entries([nh_route_ipv6]) - self.check_nexthop_in_asic_db(asicdb, rtkeys[0]) - self.check_nexthop_in_asic_db(asicdb, rtkeys_ipv6[0]) - - # Set state to standby and delete neighbor - self.set_mux_state(appdb, "Ethernet0", "standby") - self.check_nexthop_in_asic_db(asicdb, rtkeys[0], True) - self.check_nexthop_in_asic_db(asicdb, rtkeys_ipv6[0], True) - - self.del_neighbor(dvs, neigh_ip) - self.del_neighbor(dvs, neigh_ipv6) - apdb.wait_for_deleted_entry(self.APP_NEIGH_TABLE, neigh_ip) - apdb.wait_for_deleted_entry(self.APP_NEIGH_TABLE, neigh_ipv6) - asicdb.wait_for_deleted_entry(self.ASIC_NEIGH_TABLE, neigh_ip) - asicdb.wait_for_deleted_entry(self.ASIC_NEIGH_TABLE, neigh_ip) - - self.check_nexthop_in_asic_db(asicdb, rtkeys[0], True) - self.check_nexthop_in_asic_db(asicdb, rtkeys_ipv6[0], True) - - # Set state to active, learn neighbor again - self.set_mux_state(appdb, "Ethernet0", "active") - - self.add_neighbor(dvs, neigh_ip, mac) - self.add_neighbor(dvs, neigh_ipv6, mac) - self.check_neigh_in_asic_db(asicdb, neigh_ip) - self.check_neigh_in_asic_db(asicdb, neigh_ipv6) - - self.check_nexthop_in_asic_db(asicdb, rtkeys[0]) - self.check_nexthop_in_asic_db(asicdb, rtkeys_ipv6[0]) - dvs.runcmd( - "ip neigh flush " + neigh_ip - ) - dvs.runcmd( - "ip neigh flush " + neigh_ipv6 - ) - - # Cleanup - dvs.runcmd( - "vtysh -c \"configure terminal\" -c \"no ip route " + nh_route + - " " + neigh_ip + "\"" - ) - dvs.runcmd( - "vtysh -c \"configure terminal\" -c \"no ipv6 route " + nh_route_ipv6 + - " " + neigh_ipv6 + "\"" - ) - self.del_neighbor(dvs, neigh_ip) - self.del_neighbor(dvs, neigh_ipv6) - - def get_expected_sai_qualifiers(self, portlist, dvs_acl): - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_PRIORITY": self.ACL_PRIORITY, - "SAI_ACL_ENTRY_ATTR_FIELD_IN_PORTS": dvs_acl.get_port_list_comparator(portlist) - } - - return expected_sai_qualifiers - - def create_and_test_acl(self, appdb, dvs_acl): - - # Start with active, verify NO ACL rules exists - self.set_mux_state(appdb, "Ethernet0", "active") - self.set_mux_state(appdb, "Ethernet4", "active") - self.set_mux_state(appdb, "Ethernet8", "active") - - dvs_acl.verify_no_acl_rules() - - # Set mux port in active-active cable type, no ACL rules programmed - self.set_mux_state(appdb, "Ethernet0", "standby") - dvs_acl.verify_no_acl_rules() - - # Set one mux port to standby, verify ACL rule with inport bitmap (1 port) - self.set_mux_state(appdb, "Ethernet4", "standby") - sai_qualifier = self.get_expected_sai_qualifiers(["Ethernet4"], dvs_acl) - dvs_acl.verify_acl_rule(sai_qualifier, action="DROP", priority=self.ACL_PRIORITY) - - # Set two mux ports to standby, verify ACL rule with inport bitmap (2 ports) - self.set_mux_state(appdb, "Ethernet8", "standby") - sai_qualifier = self.get_expected_sai_qualifiers(["Ethernet4", "Ethernet8"], dvs_acl) - dvs_acl.verify_acl_rule(sai_qualifier, action="DROP", priority=self.ACL_PRIORITY) - - self.set_mux_state(appdb, "Ethernet0", "active") - sai_qualifier = self.get_expected_sai_qualifiers(["Ethernet4", "Ethernet8"], dvs_acl) - dvs_acl.verify_acl_rule(sai_qualifier, action="DROP", priority=self.ACL_PRIORITY) - - # Set one mux port to active, verify ACL rule with inport bitmap (1 port) - self.set_mux_state(appdb, "Ethernet4", "active") - sai_qualifier = self.get_expected_sai_qualifiers(["Ethernet8"], dvs_acl) - dvs_acl.verify_acl_rule(sai_qualifier, action="DROP", priority=self.ACL_PRIORITY) - - # Set last mux port to active, verify ACL rule is deleted - self.set_mux_state(appdb, "Ethernet8", "active") - dvs_acl.verify_no_acl_rules() - - # Set unknown state and verify the behavior as standby - self.set_mux_state(appdb, "Ethernet4", "unknown") - sai_qualifier = self.get_expected_sai_qualifiers(["Ethernet4"], dvs_acl) - dvs_acl.verify_acl_rule(sai_qualifier, action="DROP", priority=self.ACL_PRIORITY) - - # Verify change while setting unknown from active - self.set_mux_state(appdb, "Ethernet8", "unknown") - sai_qualifier = self.get_expected_sai_qualifiers(["Ethernet4", "Ethernet8"], dvs_acl) - dvs_acl.verify_acl_rule(sai_qualifier, action="DROP", priority=self.ACL_PRIORITY) - - self.set_mux_state(appdb, "Ethernet4", "active") - sai_qualifier = self.get_expected_sai_qualifiers(["Ethernet8"], dvs_acl) - dvs_acl.verify_acl_rule(sai_qualifier, action="DROP", priority=self.ACL_PRIORITY) - - self.set_mux_state(appdb, "Ethernet4", "standby") - sai_qualifier = self.get_expected_sai_qualifiers(["Ethernet4", "Ethernet8"], dvs_acl) - dvs_acl.verify_acl_rule(sai_qualifier, action="DROP", priority=self.ACL_PRIORITY) - - # Verify no change while setting unknown from standby - self.set_mux_state(appdb, "Ethernet4", "unknown") - sai_qualifier = self.get_expected_sai_qualifiers(["Ethernet4", "Ethernet8"], dvs_acl) - dvs_acl.verify_acl_rule(sai_qualifier, action="DROP", priority=self.ACL_PRIORITY) - - def create_and_test_metrics(self, appdb, statedb): - - # Set to active and test attributes for start and end time - self.set_mux_state(appdb, "Ethernet0", "active") - keys = statedb.get_keys("MUX_METRICS_TABLE") - assert len(keys) != 0 - - for key in keys: - if key != "Ethernet0": - continue - fvs = statedb.get_entry("MUX_METRICS_TABLE", key) - assert fvs != {} - - start = end = False - for f, _ in fvs.items(): - if f == "orch_switch_active_start": - start = True - elif f == "orch_switch_active_end": - end = True - - assert start - assert end - - # Set to standby and test attributes for start and end time - self.set_mux_state(appdb, "Ethernet0", "standby") - - keys = statedb.get_keys("MUX_METRICS_TABLE") - assert len(keys) != 0 - - for key in keys: - if key != "Ethernet0": - continue - fvs = statedb.get_entry("MUX_METRICS_TABLE", key) - assert fvs != {} - - start = end = False - for f, v in fvs.items(): - if f == "orch_switch_standby_start": - start = True - elif f == "orch_switch_standby_end": - end = True - - assert start - assert end - - def check_interface_exists_in_asicdb(self, asicdb, sai_oid): - asicdb.wait_for_entry(self.ASIC_RIF_TABLE, sai_oid) - return True - - def check_vr_exists_in_asicdb(self, asicdb, sai_oid): - asicdb.wait_for_entry(self.ASIC_VRF_TABLE, sai_oid) - return True - - def create_and_test_peer(self, asicdb, tc_to_dscp_map_oid=None, tc_to_queue_map_oid=None): - """ Create PEER entry verify all needed enties in ASIC DB exists """ - - # check asic db table - # There will be two tunnels, one P2MP and another P2P - tunnels = asicdb.wait_for_n_keys(self.ASIC_TUNNEL_TABLE, 2) - - p2p_obj = None - - for tunnel_sai_obj in tunnels: - fvs = asicdb.wait_for_entry(self.ASIC_TUNNEL_TABLE, tunnel_sai_obj) - - for field, value in fvs.items(): - if field == "SAI_TUNNEL_ATTR_TYPE": - assert value == "SAI_TUNNEL_TYPE_IPINIP" - if field == "SAI_TUNNEL_ATTR_PEER_MODE": - if value == "SAI_TUNNEL_PEER_MODE_P2P": - p2p_obj = tunnel_sai_obj - - assert p2p_obj != None - - fvs = asicdb.wait_for_entry(self.ASIC_TUNNEL_TABLE, p2p_obj) - - if tc_to_dscp_map_oid: - assert "SAI_TUNNEL_ATTR_ENCAP_QOS_TC_AND_COLOR_TO_DSCP_MAP" in fvs - if tc_to_queue_map_oid: - assert "SAI_TUNNEL_ATTR_ENCAP_QOS_TC_TO_QUEUE_MAP" in fvs - - for field, value in fvs.items(): - if field == "SAI_TUNNEL_ATTR_TYPE": - assert value == "SAI_TUNNEL_TYPE_IPINIP" - elif field == "SAI_TUNNEL_ATTR_ENCAP_SRC_IP": - assert value == self.SELF_IPV4 - elif field == "SAI_TUNNEL_ATTR_ENCAP_DST_IP": - assert value == self.PEER_IPV4 - elif field == "SAI_TUNNEL_ATTR_PEER_MODE": - assert value == "SAI_TUNNEL_PEER_MODE_P2P" - elif field == "SAI_TUNNEL_ATTR_OVERLAY_INTERFACE": - assert self.check_interface_exists_in_asicdb(asicdb, value) - elif field == "SAI_TUNNEL_ATTR_UNDERLAY_INTERFACE": - assert self.check_interface_exists_in_asicdb(asicdb, value) - elif field == "SAI_TUNNEL_ATTR_ENCAP_TTL_MODE": - assert value == "SAI_TUNNEL_TTL_MODE_PIPE_MODEL" - elif field == "SAI_TUNNEL_ATTR_DECAP_TTL_MODE": - assert value == "SAI_TUNNEL_TTL_MODE_PIPE_MODEL" - elif field == "SAI_TUNNEL_ATTR_LOOPBACK_PACKET_ACTION": - assert value == "SAI_PACKET_ACTION_DROP" - elif field == "SAI_TUNNEL_ATTR_ENCAP_QOS_TC_AND_COLOR_TO_DSCP_MAP": - assert value == tc_to_dscp_map_oid - elif field == "SAI_TUNNEL_ATTR_ENCAP_QOS_TC_TO_QUEUE_MAP": - assert value == tc_to_queue_map_oid - elif field == "SAI_TUNNEL_ATTR_ENCAP_DSCP_MODE": - assert value == "SAI_TUNNEL_DSCP_MODE_PIPE_MODEL" - elif field == "SAI_TUNNEL_ATTR_DECAP_DSCP_MODE": - assert value == "SAI_TUNNEL_DSCP_MODE_PIPE_MODEL" - else: - assert False, "Field %s is not tested" % field - - def check_tunnel_termination_entry_exists_in_asicdb(self, asicdb, tunnel_sai_oid, dst_ips, src_ip=None): - tunnel_term_entries = asicdb.wait_for_n_keys(self.ASIC_TUNNEL_TERM_ENTRIES, len(dst_ips)) - expected_term_type = "SAI_TUNNEL_TERM_TABLE_ENTRY_TYPE_P2P" if src_ip else "SAI_TUNNEL_TERM_TABLE_ENTRY_TYPE_P2MP" - expected_len = 6 if src_ip else 5 - for term_entry in tunnel_term_entries: - fvs = asicdb.get_entry(self.ASIC_TUNNEL_TERM_ENTRIES, term_entry) - - assert len(fvs) == expected_len - - for field, value in fvs.items(): - if field == "SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_VR_ID": - assert self.check_vr_exists_in_asicdb(asicdb, value) - elif field == "SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_TYPE": - assert value == expected_term_type - elif field == "SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_TUNNEL_TYPE": - assert value == "SAI_TUNNEL_TYPE_IPINIP" - elif field == "SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_ACTION_TUNNEL_ID": - assert value == tunnel_sai_oid - elif field == "SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_DST_IP": - assert value in dst_ips - elif field == "SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_SRC_IP" and src_ip: - assert value == src_ip - else: - assert False, "Field %s is not tested" % field - - def create_and_test_tunnel(self, db, asicdb, tunnel_name, tunnel_params): - """ Create tunnel and verify all needed enties in ASIC DB exists """ - - is_symmetric_tunnel = "src_ip" in tunnel_params - - # 6 parameters to check in case of decap tunnel - # + 1 (SAI_TUNNEL_ATTR_ENCAP_SRC_IP) in case of symmetric tunnel - expected_len = 7 if is_symmetric_tunnel else 6 - - if 'decap_tc_to_pg_map_id' in tunnel_params: - expected_len += 1 - decap_tc_to_pg_map_id = tunnel_params.pop('decap_tc_to_pg_map_id') - - if 'decap_dscp_to_tc_map_id' in tunnel_params: - expected_len += 1 - decap_dscp_to_tc_map_id = tunnel_params.pop('decap_dscp_to_tc_map_id') - - # check asic db table - tunnels = asicdb.wait_for_n_keys(self.ASIC_TUNNEL_TABLE, 1) - - tunnel_sai_obj = tunnels[0] - - fvs = asicdb.wait_for_entry(self.ASIC_TUNNEL_TABLE, tunnel_sai_obj) - - assert len(fvs) == expected_len - - expected_ecn_mode = self.ecn_modes_map[tunnel_params["ecn_mode"]] - expected_dscp_mode = self.dscp_modes_map[tunnel_params["dscp_mode"]] - expected_ttl_mode = self.ttl_modes_map[tunnel_params["ttl_mode"]] - - - for field, value in fvs.items(): - if field == "SAI_TUNNEL_ATTR_TYPE": - assert value == "SAI_TUNNEL_TYPE_IPINIP" - elif field == "SAI_TUNNEL_ATTR_ENCAP_SRC_IP": - assert value == tunnel_params["src_ip"] - elif field == "SAI_TUNNEL_ATTR_DECAP_ECN_MODE": - assert value == expected_ecn_mode - elif field == "SAI_TUNNEL_ATTR_DECAP_TTL_MODE": - assert value == expected_ttl_mode - elif field == "SAI_TUNNEL_ATTR_DECAP_DSCP_MODE": - assert value == expected_dscp_mode - elif field == "SAI_TUNNEL_ATTR_OVERLAY_INTERFACE": - assert self.check_interface_exists_in_asicdb(asicdb, value) - elif field == "SAI_TUNNEL_ATTR_UNDERLAY_INTERFACE": - assert self.check_interface_exists_in_asicdb(asicdb, value) - elif field == "SAI_TUNNEL_ATTR_DECAP_QOS_DSCP_TO_TC_MAP": - assert value == decap_dscp_to_tc_map_id - elif field == "SAI_TUNNEL_ATTR_DECAP_QOS_TC_TO_PRIORITY_GROUP_MAP": - assert value == decap_tc_to_pg_map_id - else: - assert False, "Field %s is not tested" % field - - - src_ip = tunnel_params['src_ip'] if 'src_ip' in tunnel_params else None - self.check_tunnel_termination_entry_exists_in_asicdb(asicdb, tunnel_sai_obj, tunnel_params["dst_ip"].split(","), src_ip) - - def remove_and_test_tunnel(self, db, asicdb, tunnel_name): - """ Removes tunnel and checks that ASIC db is clear""" - - tunnel_table = swsscommon.Table(asicdb, self.ASIC_TUNNEL_TABLE) - tunnel_term_table = swsscommon.Table(asicdb, self.ASIC_TUNNEL_TERM_ENTRIES) - tunnel_app_table = swsscommon.Table(asicdb, self.APP_TUNNEL_DECAP_TABLE_NAME) - - tunnels = tunnel_table.getKeys() - tunnel_sai_obj = tunnels[0] - - status, fvs = tunnel_table.get(tunnel_sai_obj) - - # get overlay loopback interface oid to check if it is deleted with the tunnel - overlay_infs_id = {f:v for f, v in fvs}["SAI_TUNNEL_ATTR_OVERLAY_INTERFACE"] - - ps = swsscommon.ProducerStateTable(db, self.APP_TUNNEL_DECAP_TABLE_NAME) - ps.set(tunnel_name, create_fvs(), 'DEL') - - # wait till config will be applied - time.sleep(1) - - assert len(tunnel_table.getKeys()) == 0 - assert len(tunnel_term_table.getKeys()) == 0 - assert len(tunnel_app_table.getKeys()) == 0 - assert not self.check_interface_exists_in_asicdb(asicdb, overlay_infs_id) - - def check_app_db_neigh_table( - self, appdb, intf, neigh_ip, - mac="00:00:00:00:00:00", expect_entry=True - ): - key = "{}:{}".format(intf, neigh_ip) - if isinstance(ip_address(neigh_ip), IPv4Address): - family = 'IPv4' - else: - family = 'IPv6' - - if expect_entry: - appdb.wait_for_matching_keys(self.APP_NEIGH_TABLE, [key]) - appdb.wait_for_field_match(self.APP_NEIGH_TABLE, key, {'family': family}) - appdb.wait_for_field_match(self.APP_NEIGH_TABLE, key, {'neigh': mac}) - else: - appdb.wait_for_deleted_keys(self.APP_NEIGH_TABLE, key) - def add_qos_map(self, configdb, asicdb, qos_map_type_name, qos_map_name, qos_map): - current_oids = asicdb.get_keys(self.ASIC_QOS_MAP_TABLE_KEY) - # Apply QoS map to config db - table = swsscommon.Table(configdb.db_connection, qos_map_type_name) - fvs = swsscommon.FieldValuePairs(list(qos_map.items())) - table.set(qos_map_name, fvs) - time.sleep(1) - - diff = set(asicdb.get_keys(self.ASIC_QOS_MAP_TABLE_KEY)) - set(current_oids) - assert len(diff) == 1 - oid = diff.pop() - return oid - - def remove_qos_map(self, configdb, qos_map_type_name, qos_map_oid): - """ Remove the testing qos map""" - table = swsscommon.Table(configdb.db_connection, qos_map_type_name) - table._del(qos_map_oid) - - def cleanup_left_over(self, db, asicdb): - """ Cleanup APP and ASIC tables """ - - tunnel_table = asicdb.get_keys(self.ASIC_TUNNEL_TABLE) - for key in tunnel_table: - asicdb.delete_entry(self.ASIC_TUNNEL_TABLE, key) - - tunnel_term_table = asicdb.get_keys(self.ASIC_TUNNEL_TERM_ENTRIES) - for key in tunnel_term_table: - asicdb.delete_entry(self.ASIC_TUNNEL_TERM_ENTRIES, key) - - tunnel_app_table = swsscommon.Table(db, self.APP_TUNNEL_DECAP_TABLE_NAME) - for key in tunnel_app_table.getKeys(): - tunnel_table._del(key) - - def ping_ip(self, dvs, ip): - dvs.runcmd(self.PING_CMD.format(ip=ip)) - - def check_neighbor_state( - self, dvs, dvs_route, neigh_ip, expect_route=True, - expect_neigh=False, expected_mac='00:00:00:00:00:00' - ): - """ - Checks the status of neighbor entries in APPL and ASIC DB - """ - if expect_route and expect_neigh: - pytest.fail('expect_routes and expect_neigh cannot both be True') - app_db = dvs.get_app_db() - asic_db = dvs.get_asic_db() - prefix = str(ip_network(neigh_ip)) - self.check_app_db_neigh_table( - app_db, self.VLAN_1000, neigh_ip, - mac=expected_mac, expect_entry=expect_route - ) - if expect_route: - self.check_tnl_nexthop_in_asic_db(asic_db) - routes = dvs_route.check_asicdb_route_entries([prefix]) - for route in routes: - self.check_nexthop_in_asic_db(asic_db, route, standby=expect_route) - else: - dvs_route.check_asicdb_deleted_route_entries([prefix]) - self.check_neigh_in_asic_db(asic_db, neigh_ip, expected=expect_neigh) - - def execute_action(self, action, dvs, test_info): - if action in (PING_SERV, PING_NEIGH): - self.ping_ip(dvs, test_info[IP]) - elif action in (ACTIVE, STANDBY): - app_db_connector = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - self.set_mux_state(app_db_connector, test_info[INTF], action) - elif action == RESOLVE_ENTRY: - self.add_neighbor(dvs, test_info[IP], test_info[MAC]) - elif action == DELETE_ENTRY: - self.del_neighbor(dvs, test_info[IP]) - else: - pytest.fail('Invalid test action {}'.format(action)) - - @pytest.fixture(scope='module') - def setup_vlan(self, dvs): - self.create_vlan_interface(dvs) - - @pytest.fixture(scope='module') - def setup_mux_cable(self, dvs): - config_db = dvs.get_config_db() - self.create_mux_cable(config_db) - - @pytest.fixture(scope='module') - def setup_tunnel(self, dvs): - app_db_connector = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - ps = swsscommon.ProducerStateTable(app_db_connector, self.APP_TUNNEL_DECAP_TABLE_NAME) - fvs = create_fvs(**self.DEFAULT_TUNNEL_PARAMS) - ps.set(self.MUX_TUNNEL_0, fvs) - - @pytest.fixture - def setup_peer_switch(self, dvs): - config_db = dvs.get_config_db() - config_db.create_entry( - self.CONFIG_PEER_SWITCH, - self.PEER_SWITCH_HOST, - self.DEFAULT_PEER_SWITCH_PARAMS - ) - - @pytest.fixture - def remove_peer_switch(self, dvs): - config_db = dvs.get_config_db() - config_db.delete_entry(self.CONFIG_PEER_SWITCH, self.PEER_SWITCH_HOST) - - @pytest.fixture(params=['IPv4', 'IPv6']) - def ip_version(self, request): - return request.param - - def clear_neighbors(self, dvs): - _, neighs_str = dvs.runcmd('ip neigh show all') - neighs = [entry.split()[0] for entry in neighs_str.split('\n')[:-1]] - - for neigh in neighs: - self.del_neighbor(dvs, neigh) - - @pytest.fixture - def neighbor_cleanup(self, dvs): - """ - Ensures that all kernel neighbors are removed before and after tests - """ - self.clear_neighbors(dvs) - yield - self.clear_neighbors(dvs) - - @pytest.fixture - def server_test_ips(self, ip_version): - if ip_version == 'IPv4': - return [self.SERV1_IPV4, self.SERV2_IPV4, self.SERV3_IPV4] - else: - return [self.SERV1_IPV6, self.SERV2_IPV6, self.SERV3_IPV6] - - @pytest.fixture - def neigh_test_ips(self, ip_version): - if ip_version == 'IPv4': - return [self.NEIGH1_IPV4, self.NEIGH2_IPV4, self.NEIGH3_IPV4] - else: - return [self.NEIGH1_IPV6, self.NEIGH2_IPV6, self.NEIGH3_IPV6] - - @pytest.fixture - def ips_for_test(self, server_test_ips, neigh_test_ips, neigh_miss_test_sequence): - # Assumes that each test sequence has at exactly one of - # PING_NEIGH OR PING_SERV as a step - for step in neigh_miss_test_sequence: - if step[TEST_ACTION] == PING_SERV: - return server_test_ips - if step[TEST_ACTION] == PING_NEIGH: - return neigh_test_ips - - # If we got here, the test sequence did not contain a ping command - pytest.fail('No ping command found in test sequence {}'.format(neigh_miss_test_sequence)) - - @pytest.fixture - def ip_to_intf_map(self, server_test_ips, neigh_test_ips): - map = { - server_test_ips[0]: 'Ethernet0', - server_test_ips[1]: 'Ethernet4', - server_test_ips[2]: 'Ethernet8', - neigh_test_ips[0]: 'Ethernet0', - neigh_test_ips[1]: 'Ethernet4', - neigh_test_ips[2]: 'Ethernet8' - } - return map - - @pytest.fixture( - params=NEIGH_MISS_TESTS, - ids=['->'.join([step[TEST_ACTION] for step in scenario]) - for scenario in NEIGH_MISS_TESTS] - ) - def neigh_miss_test_sequence(self, request): - return request.param - - @pytest.fixture - def intf_fdb_map(self, dvs, setup_vlan): - """ - Note: this fixture invokes the setup_vlan fixture so that - the interfaces are brought up before attempting to access FDB information - """ - state_db = dvs.get_state_db() - keys = state_db.get_keys(self.STATE_FDB_TABLE) - - fdb_map = {} - for key in keys: - entry = state_db.get_entry(self.STATE_FDB_TABLE, key) - mac = key.replace('{}:'.format(self.VLAN_1000), '') - port = entry['port'] - fdb_map[port] = mac - - return fdb_map - - -class TestMuxTunnel(TestMuxTunnelBase): - """ Tests for Mux tunnel creation and removal """ - @pytest.fixture(scope='class') - def setup(self, dvs): - db = dvs.get_config_db() - asicdb = dvs.get_asic_db() - - tc_to_dscp_map_oid = self.add_qos_map(db, asicdb, swsscommon.CFG_TC_TO_DSCP_MAP_TABLE_NAME, self.TUNNEL_QOS_MAP_NAME, self.TC_TO_DSCP_MAP) - tc_to_queue_map_oid = self.add_qos_map(db, asicdb, swsscommon.CFG_TC_TO_QUEUE_MAP_TABLE_NAME, self.TUNNEL_QOS_MAP_NAME, self.TC_TO_QUEUE_MAP) - - dscp_to_tc_map_oid = self.add_qos_map(db, asicdb, swsscommon.CFG_DSCP_TO_TC_MAP_TABLE_NAME, self.TUNNEL_QOS_MAP_NAME, self.DSCP_TO_TC_MAP) - tc_to_pg_map_oid = self.add_qos_map(db, asicdb, swsscommon.CFG_TC_TO_PRIORITY_GROUP_MAP_TABLE_NAME, self.TUNNEL_QOS_MAP_NAME, self.TC_TO_PRIORITY_GROUP_MAP) - - yield tc_to_dscp_map_oid, tc_to_queue_map_oid, dscp_to_tc_map_oid, tc_to_pg_map_oid - - self.remove_qos_map(db, swsscommon.CFG_TC_TO_DSCP_MAP_TABLE_NAME, tc_to_dscp_map_oid) - self.remove_qos_map(db, swsscommon.CFG_TC_TO_QUEUE_MAP_TABLE_NAME, tc_to_queue_map_oid) - self.remove_qos_map(db, swsscommon.CFG_DSCP_TO_TC_MAP_TABLE_NAME, dscp_to_tc_map_oid) - self.remove_qos_map(db, swsscommon.CFG_TC_TO_PRIORITY_GROUP_MAP_TABLE_NAME, tc_to_pg_map_oid) - - - def test_Tunnel(self, dvs, setup_tunnel, testlog, setup): - """ test IPv4 Mux tunnel creation """ - db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - asicdb = dvs.get_asic_db() - - #self.cleanup_left_over(db, asicdb) - _, _, dscp_to_tc_map_oid, tc_to_pg_map_oid = setup - tunnel_params = self.DEFAULT_TUNNEL_PARAMS - tunnel_params["decap_dscp_to_tc_map_id"] = dscp_to_tc_map_oid - tunnel_params["decap_tc_to_pg_map_id"] = tc_to_pg_map_oid - - # create tunnel IPv4 tunnel - self.create_and_test_tunnel(db, asicdb, self.MUX_TUNNEL_0, tunnel_params) - - def test_Peer(self, dvs, setup_peer_switch, setup_tunnel, setup, testlog): - - """ test IPv4 Mux tunnel creation """ - - asicdb = dvs.get_asic_db() - - encap_tc_to_dscp_map_id, encap_tc_to_queue_map_id, _, _ = setup - - self.create_and_test_peer(asicdb, encap_tc_to_dscp_map_id, encap_tc_to_queue_map_id) - - def test_Neighbor(self, dvs, dvs_route, setup_vlan, setup_mux_cable, testlog): - """ test Neighbor entries and mux state change """ - - confdb = dvs.get_config_db() - appdb = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - asicdb = dvs.get_asic_db() - - self.create_and_test_neighbor(confdb, appdb, asicdb, dvs, dvs_route) - - def test_Fdb(self, dvs, dvs_route, testlog): - """ test Fdb entries and mux state change """ - - appdb = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - asicdb = dvs.get_asic_db() - - self.create_and_test_fdb(appdb, asicdb, dvs, dvs_route) - - def test_Route(self, dvs, dvs_route, testlog): - """ test Route entries and mux state change """ - - appdb = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - asicdb = dvs.get_asic_db() - - self.create_and_test_route(appdb, asicdb, dvs, dvs_route) - - def test_NH(self, dvs, dvs_route, intf_fdb_map, setup, setup_mux_cable, - setup_peer_switch, setup_tunnel, testlog): - """ test NH routes and mux state change """ - appdb = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - asicdb = dvs.get_asic_db() - mac = intf_fdb_map["Ethernet0"] - - # get tunnel nexthop - self.check_tnl_nexthop_in_asic_db(asicdb, 5) - - self.create_and_test_NH_routes(appdb, asicdb, dvs, dvs_route, mac) - - def test_multi_nexthop(self, dvs, dvs_route, intf_fdb_map, neighbor_cleanup, testlog, setup): - appdb = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - asicdb = dvs.get_asic_db() - macs = [intf_fdb_map["Ethernet0"], intf_fdb_map["Ethernet4"]] - new_mac = intf_fdb_map["Ethernet8"] - - self.create_and_test_multi_nexthop_routes(dvs, dvs_route, appdb, macs, new_mac, asicdb) - - def test_acl(self, dvs, dvs_acl, testlog): - """ test acl and mux state change """ - - appdb = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - - try: - self.create_and_test_acl(appdb, dvs_acl) - finally: - self.set_mux_state(appdb, "Ethernet0", "active") - self.set_mux_state(appdb, "Ethernet4", "active") - self.set_mux_state(appdb, "Ethernet8", "active") - dvs_acl.verify_no_acl_rules() - - def test_mux_metrics(self, dvs, testlog): - """ test metrics for mux state change """ - - appdb = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - statedb = dvs.get_state_db() - - self.create_and_test_metrics(appdb, statedb) - - def test_neighbor_miss( - self, dvs, dvs_route, ips_for_test, neigh_miss_test_sequence, - ip_to_intf_map, intf_fdb_map, neighbor_cleanup, setup_vlan, - setup_mux_cable, setup_tunnel, setup_peer_switch, testlog - ): - ip = ips_for_test[0] - intf = ip_to_intf_map[ip] - mac = intf_fdb_map[intf] - test_info = { - IP: ip, - INTF: intf, - MAC: mac - } - - for step in neigh_miss_test_sequence: - self.execute_action(step[TEST_ACTION], dvs, test_info) - exp_result = step[EXPECTED_RESULT] - self.check_neighbor_state( - dvs, dvs_route, ip, - expect_route=exp_result[EXPECT_ROUTE], - expect_neigh=exp_result[EXPECT_NEIGH], - expected_mac=mac if exp_result[REAL_MAC] else '00:00:00:00:00:00' - ) - - def test_neighbor_miss_no_mux( - self, dvs, dvs_route, setup_vlan, setup_tunnel, setup, - setup_peer_switch, neighbor_cleanup, testlog - ): - config_db = dvs.get_config_db() - appdb = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - - test_ip = self.SERV1_SOC_IPV4 - self.ping_ip(dvs, test_ip) - - # no mux present, no standalone tunnel route installed - self.check_neighbor_state(dvs, dvs_route, test_ip, expect_route=False) - - # setup the mux - config_db = dvs.get_config_db() - self.create_mux_cable(config_db) - # tunnel route should be installed immediately after mux setup - self.check_neighbor_state(dvs, dvs_route, test_ip, expect_route=True) - - # set port state as standby - self.set_mux_state(appdb, "Ethernet0", "standby") - self.check_neighbor_state(dvs, dvs_route, test_ip, expect_route=True) - - # set port state as active - self.set_mux_state(appdb, "Ethernet0", "active") - self.check_neighbor_state(dvs, dvs_route, test_ip, expect_route=True) - - # clear the FAILED neighbor - self.clear_neighbors(dvs) - self.check_neighbor_state(dvs, dvs_route, test_ip, expect_route=False) - - def test_neighbor_miss_no_peer( - self, dvs, dvs_route, setup_vlan, setup_mux_cable, setup_tunnel, - remove_peer_switch, neighbor_cleanup, testlog - ): - """ - test neighbor miss with no peer switch configured - No new entries are expected in APPL_DB or ASIC_DB - """ - test_ips = [self.NEIGH3_IPV4, self.SERV3_IPV4, self.NEIGH1_IPV6, self.SERV1_IPV6] - - for ip in test_ips: - self.ping_ip(dvs, ip) - - for ip in test_ips: - self.check_neighbor_state(dvs, dvs_route, ip, expect_route=False) - - def test_soc_ip(self, dvs, dvs_route, setup_vlan, setup_mux_cable, testlog): - appdb = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - asicdb = dvs.get_asic_db() - - self.create_and_test_soc(appdb, asicdb, dvs, dvs_route) - - def test_warm_boot_mux_state( - self, dvs, dvs_route, setup_vlan, setup_mux_cable, setup_tunnel, - remove_peer_switch, neighbor_cleanup, testlog - ): - """ - test mux initialization during warm boot. - """ - appdb = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - apdb = dvs.get_app_db() - - self.set_mux_state(appdb, "Ethernet0", "active") - self.set_mux_state(appdb, "Ethernet4", "active") - self.set_mux_state(appdb, "Ethernet8", "standby") - - # Execute the warm reboot - dvs.runcmd("config warm_restart enable swss") - dvs.stop_swss() - dvs.start_swss() - - time.sleep(5) - - fvs = apdb.get_entry(self.APP_MUX_CABLE, "Ethernet0") - for key in fvs: - if key == "state": - assert fvs[key] == "active", "Ethernet0 Mux state is not active after warm boot, state: {}".format(fvs[key]) - - fvs = apdb.get_entry(self.APP_MUX_CABLE, "Ethernet4") - for key in fvs: - if key == "state": - assert fvs[key] == "active", "Ethernet4 Mux state is not active after warm boot, state: {}".format(fvs[key]) - - fvs = apdb.get_entry(self.APP_MUX_CABLE, "Ethernet8") - for key in fvs: - if key == "state": - assert fvs[key] == "standby", "Ethernet8 Mux state is not standby after warm boot, state: {}".format(fvs[key]) - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_nat.py b/tests/test_nat.py deleted file mode 100644 index 1c509e464f..0000000000 --- a/tests/test_nat.py +++ /dev/null @@ -1,431 +0,0 @@ -import time -import pytest - -from dvslib.dvs_common import wait_for_result - -L3_TABLE_TYPE = "L3" -L3_TABLE_NAME = "L3_TEST" -L3_BIND_PORTS = ["Ethernet0"] -L3_RULE_NAME = "L3_TEST_RULE" - -class TestNat(object): - def setup_db(self, dvs): - self.app_db = dvs.get_app_db() - self.asic_db = dvs.get_asic_db() - self.config_db = dvs.get_config_db() - - def set_interfaces(self, dvs): - dvs.interface_ip_add("Ethernet0", "67.66.65.1/24") - dvs.interface_ip_add("Ethernet4", "18.18.18.1/24") - dvs.port_admin_set("Ethernet0", "up") - dvs.port_admin_set("Etherent4", "up") - - dvs.servers[0].runcmd("ip link set down dev eth0") - dvs.servers[0].runcmd("ip link set up dev eth0") - dvs.servers[0].runcmd("ifconfig eth0 67.66.65.2/24") - dvs.servers[0].runcmd("ip route add default via 67.66.65.1") - - dvs.servers[1].runcmd("ip link set down dev eth0") - dvs.servers[1].runcmd("ip link set up dev eth0") - dvs.servers[1].runcmd("ifconfig eth0 18.18.18.2/24") - dvs.servers[1].runcmd("ip route add default via 18.18.18.1") - - dvs.set_nat_zone("Ethernet0", "1") - - time.sleep(1) - - def clear_interfaces(self, dvs): - dvs.servers[0].runcmd("ifconfig eth0 0.0.0.0") - dvs.servers[1].runcmd("ifconfig eth0 0.0.0.0") - - time.sleep(1) - - def test_NatGlobalTable(self, dvs, testlog): - # initialize - self.setup_db(dvs) - - # enable NAT feature - dvs.nat_mode_set("enabled") - dvs.nat_timeout_set("450") - dvs.nat_udp_timeout_set("360") - dvs.nat_tcp_timeout_set("900") - - # check NAT global values in appdb - self.app_db.wait_for_n_keys("NAT_GLOBAL_TABLE", 1) - - fvs = self.app_db.wait_for_entry("NAT_GLOBAL_TABLE", "Values") - - assert fvs == {"admin_mode": "enabled", "nat_timeout": "450", "nat_udp_timeout": "360", "nat_tcp_timeout": "900"} - - def test_NatInterfaceZone(self, dvs, testlog): - # initialize - self.setup_db(dvs) - self.set_interfaces(dvs) - - # check NAT zone is set for interface in app db - fvs = self.app_db.wait_for_entry("INTF_TABLE", "Ethernet0") - zone = False - for f, v in fvs.items(): - if f == "nat_zone" and v == '1': - zone = True - break - assert zone - - def test_AddNatStaticEntry(self, dvs, testlog): - # initialize - self.setup_db(dvs) - - # get neighbor and arp entry - dvs.servers[0].runcmd("ping -c 1 18.18.18.2") - - # add a static nat entry - dvs.add_nat_basic_entry("67.66.65.1", "18.18.18.2") - - # check the entry in the config db - self.config_db.wait_for_n_keys("STATIC_NAT", 1) - - fvs = self.config_db.wait_for_entry("STATIC_NAT", "67.66.65.1") - - assert fvs == {"local_ip": "18.18.18.2"} - - # check the entry in app db - self.app_db.wait_for_n_keys("NAT_TABLE", 2) - - fvs = self.app_db.wait_for_entry("NAT_TABLE", "67.66.65.1") - - assert fvs == { - "translated_ip": "18.18.18.2", - "nat_type": "dnat", - "entry_type": "static" - } - - #check the entry in asic db, 3 keys = SNAT, DNAT and DNAT_Pool - keys = self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_NAT_ENTRY", 3) - for key in keys: - if (key.find("dst_ip:67.66.65.1")) or (key.find("src_ip:18.18.18.2")): - assert True - else: - assert False - - def test_DelNatStaticEntry(self, dvs, testlog): - # initialize - self.setup_db(dvs) - - # delete a static nat entry - dvs.del_nat_basic_entry("67.66.65.1") - - # check the entry is no there in the config db - self.config_db.wait_for_n_keys("STATIC_NAT", 0) - - # check the entry is not there in app db - self.app_db.wait_for_n_keys("NAT_TABLE", 0) - - #check the entry is not there in asic db - self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_NAT_ENTRY", 0) - - def test_AddNaPtStaticEntry(self, dvs, testlog): - # initialize - self.setup_db(dvs) - - # get neighbor and arp entry - dvs.servers[0].runcmd("ping -c 1 18.18.18.2") - - # add a static nat entry - dvs.add_nat_udp_entry("67.66.65.1", "670", "18.18.18.2", "180") - - # check the entry in the config db - self.config_db.wait_for_n_keys("STATIC_NAPT", 1) - - fvs = self.config_db.wait_for_entry("STATIC_NAPT", "67.66.65.1|UDP|670") - - assert fvs == {"local_ip": "18.18.18.2", "local_port": "180"} - - # check the entry in app db - self.app_db.wait_for_n_keys("NAPT_TABLE:UDP", 2) - - fvs = self.app_db.wait_for_entry("NAPT_TABLE:UDP", "67.66.65.1:670") - - assert fvs == {"translated_ip": "18.18.18.2", "translated_l4_port": "180", "nat_type": "dnat", "entry_type": "static"} - - #check the entry in asic db, 3 keys = SNAT, DNAT and DNAT_Pool - keys = self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_NAT_ENTRY", 3) - for key in keys: - if (key.find("dst_ip:67.66.65.1")) and (key.find("key.l4_dst_port:670")): - assert True - if (key.find("src_ip:18.18.18.2")) or (key.find("key.l4_src_port:180")): - assert True - else: - assert False - - def test_DelNaPtStaticEntry(self, dvs, testlog): - # initialize - self.setup_db(dvs) - - # delete a static nat entry - dvs.del_nat_udp_entry("67.66.65.1", "670") - - # check the entry is no there in the config db - self.config_db.wait_for_n_keys("STATIC_NAPT", 0) - - # check the entry is not there in app db - self.app_db.wait_for_n_keys("NAPT_TABLE:UDP", 0) - - #check the entry is not there in asic db - self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_NAT_ENTRY", 0) - - @pytest.mark.skip(reason="Failing. Under investigation") - def test_AddTwiceNatEntry(self, dvs, testlog): - # initialize - self.setup_db(dvs) - - # get neighbor and arp entry - dvs.servers[0].runcmd("ping -c 1 18.18.18.2") - dvs.servers[1].runcmd("ping -c 1 67.66.65.2") - - # add a twice nat entry - dvs.add_twice_nat_basic_entry("67.66.65.2", "18.18.18.1", "snat", "9") - dvs.add_twice_nat_basic_entry("67.66.65.1", "18.18.18.2", "dnat", "9") - - # check the entry in the config db - self.config_db.wait_for_n_keys("STATIC_NAT", 2) - - fvs = self.config_db.wait_for_entry("STATIC_NAT", "67.66.65.1") - assert fvs == {"nat_type": "dnat", "twice_nat_id": "9", "local_ip": "18.18.18.2"} - - fvs = self.config_db.wait_for_entry("STATIC_NAT", "67.66.65.2") - assert fvs == {"nat_type": "snat", "twice_nat_id": "9", "local_ip": "18.18.18.1"} - - # check the entry in app db - self.app_db.wait_for_n_keys("NAT_TWICE_TABLE", 2) - - fvs = self.app_db.wait_for_entry("NAT_TWICE_TABLE", "67.66.65.2:67.66.65.1") - assert fvs == {"translated_src_ip": "18.18.18.1", "translated_dst_ip": "18.18.18.2", "entry_type": "static"} - - fvs = self.app_db.wait_for_entry("NAT_TWICE_TABLE", "18.18.18.2:18.18.18.1") - assert fvs == {"translated_src_ip": "67.66.65.1", "translated_dst_ip": "67.66.65.2", "entry_type": "static"} - - #check the entry in asic db, 4 keys = SNAT, DNAT and 2 DNAT_Pools - keys = self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_NAT_ENTRY", 4) - for key in keys: - if (key.find("dst_ip:18.18.18.1")) or (key.find("src_ip:18.18.18.2")): - assert True - else: - assert False - - def test_DelTwiceNatStaticEntry(self, dvs, testlog): - # initialize - self.setup_db(dvs) - - # delete a static nat entry - dvs.del_twice_nat_basic_entry("67.66.65.2") - dvs.del_twice_nat_basic_entry("67.66.65.1") - - # check the entry is no there in the config db - self.config_db.wait_for_n_keys("STATIC_NAT", 0) - - # check the entry is not there in app db - self.app_db.wait_for_n_keys("NAT_TWICE_TABLE", 0) - - #check the entry is not there in asic db - self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_NAT_ENTRY", 0) - - def test_AddTwiceNaPtEntry(self, dvs, testlog): - # initialize - self.setup_db(dvs) - - # get neighbor and arp entry - dvs.servers[0].runcmd("ping -c 1 18.18.18.2") - dvs.servers[1].runcmd("ping -c 1 67.66.65.2") - - # add a twice nat entry - dvs.add_twice_nat_udp_entry("67.66.65.2", "670", "18.18.18.1", "181", "snat", "7") - dvs.add_twice_nat_udp_entry("67.66.65.1", "660", "18.18.18.2", "182", "dnat", "7") - - # check the entry in the config db - self.config_db.wait_for_n_keys("STATIC_NAPT", 2) - - fvs = self.config_db.wait_for_entry("STATIC_NAPT", "67.66.65.1|UDP|660") - assert fvs == {"nat_type": "dnat", "local_ip": "18.18.18.2", "twice_nat_id": "7", "local_port": "182"} - - fvs = self.config_db.wait_for_entry("STATIC_NAPT", "67.66.65.2|UDP|670") - assert fvs == {"nat_type": "snat", "local_ip": "18.18.18.1", "twice_nat_id": "7", "local_port": "181"} - - # check the entry in app db - self.app_db.wait_for_n_keys("NAPT_TWICE_TABLE", 2) - - fvs = self.app_db.wait_for_entry("NAPT_TWICE_TABLE", "UDP:67.66.65.2:670:67.66.65.1:660") - assert fvs == {"translated_src_ip": "18.18.18.1", "translated_src_l4_port": "181", "translated_dst_ip": "18.18.18.2", "translated_dst_l4_port": "182", "entry_type": "static"} - - fvs = self.app_db.wait_for_entry("NAPT_TWICE_TABLE", "UDP:18.18.18.2:182:18.18.18.1:181") - assert fvs == {"translated_src_ip": "67.66.65.1", "translated_src_l4_port": "660", "translated_dst_ip": "67.66.65.2", "translated_dst_l4_port": "670", "entry_type": "static"} - - #check the entry in asic db, 4 keys = SNAT, DNAT and 2 DNAT_Pools - keys = self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_NAT_ENTRY", 4) - for key in keys: - if (key.find("src_ip:18.18.18.2")) or (key.find("l4_src_port:182")): - assert True - if (key.find("dst_ip:18.18.18.1")) or (key.find("l4_dst_port:181")): - assert True - else: - assert False - - def test_DelTwiceNaPtStaticEntry(self, dvs, testlog): - # initialize - self.setup_db(dvs) - - # delete a static nat entry - dvs.del_twice_nat_udp_entry("67.66.65.2", "670") - dvs.del_twice_nat_udp_entry("67.66.65.1", "660") - - # check the entry is not there in the config db - self.config_db.wait_for_n_keys("STATIC_NAPT", 0) - - # check the entry is not there in app db - self.app_db.wait_for_n_keys("NAPT_TWICE_TABLE", 0) - - #check the entry is not there in asic db - self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_NAT_ENTRY", 0) - - def test_VerifyConntrackTimeoutForNatEntry(self, dvs, testlog): - # get neighbor and arp entry - dvs.servers[0].runcmd("ping -c 1 18.18.18.2") - - # add a static nat entry - dvs.add_nat_basic_entry("67.66.65.1", "18.18.18.2") - - # check the conntrack timeout for static entry - def _check_conntrack_for_static_entry(): - output = dvs.runcmd("conntrack -j -L -s 18.18.18.2 -p udp -q 67.66.65.1") - if len(output) != 2: - return (False, None) - - conntrack_list = list(output[1].split(" ")) - - src_exists = "src=18.18.18.2" in conntrack_list - dst_exists = "dst=67.66.65.1" in conntrack_list - proto_exists = "udp" in conntrack_list - - if not src_exists or not dst_exists or not proto_exists: - return (False, None) - - proto_index = conntrack_list.index("udp") - - if int(conntrack_list[proto_index + 7]) > 432000 or int(conntrack_list[proto_index + 7]) < 431900: - return (False, None) - - return (True, None) - - wait_for_result(_check_conntrack_for_static_entry) - - # delete a static nat entry - dvs.del_nat_basic_entry("67.66.65.1") - - def test_DoNotNatAclAction(self, dvs_acl, testlog): - - # Creating the ACL Table - dvs_acl.create_acl_table(L3_TABLE_NAME, L3_TABLE_TYPE, L3_BIND_PORTS, stage="ingress") - - acl_table_id = dvs_acl.get_acl_table_ids(1)[0] - acl_table_group_ids = dvs_acl.get_acl_table_group_ids(len(L3_BIND_PORTS)) - - dvs_acl.verify_acl_table_group_members(acl_table_id, acl_table_group_ids, 1) - dvs_acl.verify_acl_table_port_binding(acl_table_id, L3_BIND_PORTS, 1) - - # Create a ACL Rule with "do_not_nat" packet action - config_qualifiers = {"SRC_IP": "14.1.0.1/32"} - dvs_acl.create_acl_rule(L3_TABLE_NAME, L3_RULE_NAME, config_qualifiers, action="DO_NOT_NAT", priority="97") - - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_SRC_IP": dvs_acl.get_simple_qualifier_comparator("14.1.0.1&mask:255.255.255.255") - } - - dvs_acl.verify_nat_acl_rule(expected_sai_qualifiers, priority="97") - - # Deleting the ACL Rule - dvs_acl.remove_acl_rule(L3_TABLE_NAME, L3_RULE_NAME) - dvs_acl.verify_no_acl_rules() - - # Deleting the ACL Table - dvs_acl.remove_acl_table(L3_TABLE_NAME) - dvs_acl.verify_acl_table_count(0) - - def test_CrmSnatAndDnatEntryUsedCount(self, dvs, testlog): - # initialize - self.setup_db(dvs) - - # get neighbor and arp entry - dvs.servers[0].runcmd("ping -c 1 18.18.18.2") - - # set pooling interval to 1 - dvs.crm_poll_set("1") - - dvs.setReadOnlyAttr('SAI_OBJECT_TYPE_SWITCH', 'SAI_SWITCH_ATTR_AVAILABLE_SNAT_ENTRY', '1000') - dvs.setReadOnlyAttr('SAI_OBJECT_TYPE_SWITCH', 'SAI_SWITCH_ATTR_AVAILABLE_DNAT_ENTRY', '1000') - - time.sleep(2) - - # get snat counters - used_snat_counter = dvs.getCrmCounterValue('STATS', 'crm_stats_snat_entry_used') - avail_snat_counter = dvs.getCrmCounterValue('STATS', 'crm_stats_snat_entry_available') - - # get dnat counters - used_dnat_counter = dvs.getCrmCounterValue('STATS', 'crm_stats_dnat_entry_used') - avail_dnat_counter = dvs.getCrmCounterValue('STATS', 'crm_stats_dnat_entry_available') - - # add a static nat entry - dvs.add_nat_basic_entry("67.66.65.1", "18.18.18.2") - - #check the entry in asic db, 3 keys = SNAT, DNAT and DNAT_Pool - keys = self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_NAT_ENTRY", 3) - for key in keys: - if (key.find("dst_ip:67.66.65.1")) or (key.find("src_ip:18.18.18.2")): - assert True - else: - assert False - - dvs.setReadOnlyAttr('SAI_OBJECT_TYPE_SWITCH', 'SAI_SWITCH_ATTR_AVAILABLE_SNAT_ENTRY', '999') - dvs.setReadOnlyAttr('SAI_OBJECT_TYPE_SWITCH', 'SAI_SWITCH_ATTR_AVAILABLE_DNAT_ENTRY', '999') - - time.sleep(2) - - # get snat counters - new_used_snat_counter = dvs.getCrmCounterValue('STATS', 'crm_stats_snat_entry_used') - new_avail_snat_counter = dvs.getCrmCounterValue('STATS', 'crm_stats_snat_entry_available') - - # get dnat counters - new_used_dnat_counter = dvs.getCrmCounterValue('STATS', 'crm_stats_dnat_entry_used') - new_avail_dnat_counter = dvs.getCrmCounterValue('STATS', 'crm_stats_dnat_entry_available') - - assert new_used_snat_counter - used_snat_counter == 1 - assert avail_snat_counter - new_avail_snat_counter == 1 - assert new_used_dnat_counter - used_dnat_counter == 1 - assert avail_dnat_counter - new_avail_dnat_counter == 1 - - # delete a static nat entry - dvs.del_nat_basic_entry("67.66.65.1") - - dvs.setReadOnlyAttr('SAI_OBJECT_TYPE_SWITCH', 'SAI_SWITCH_ATTR_AVAILABLE_SNAT_ENTRY', '1000') - dvs.setReadOnlyAttr('SAI_OBJECT_TYPE_SWITCH', 'SAI_SWITCH_ATTR_AVAILABLE_DNAT_ENTRY', '1000') - - time.sleep(2) - - # get snat counters - new_used_snat_counter = dvs.getCrmCounterValue('STATS', 'crm_stats_snat_entry_used') - new_avail_snat_counter = dvs.getCrmCounterValue('STATS', 'crm_stats_snat_entry_available') - - # get dnat counters - new_used_dnat_counter = dvs.getCrmCounterValue('STATS', 'crm_stats_dnat_entry_used') - new_avail_dnat_counter = dvs.getCrmCounterValue('STATS', 'crm_stats_dnat_entry_available') - - assert new_used_snat_counter == used_snat_counter - assert new_avail_snat_counter == avail_snat_counter - assert new_used_dnat_counter == used_dnat_counter - assert new_avail_dnat_counter == avail_dnat_counter - - # clear interfaces - self.clear_interfaces(dvs) - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_neighbor.py b/tests/test_neighbor.py deleted file mode 100644 index 59618c75ce..0000000000 --- a/tests/test_neighbor.py +++ /dev/null @@ -1,530 +0,0 @@ -import time -import json -import pytest - -from swsscommon import swsscommon - - -class TestNeighbor(object): - CONFIG_PEER_SWITCH = "PEER_SWITCH" - PEER_SWITCH_HOST = "peer_switch_hostname" - PEER_IPV4 = "10.1.0.33" - - DEFAULT_PEER_SWITCH_PARAMS = { - "address_ipv4": PEER_IPV4 - } - - def setup_db(self, dvs): - self.pdb = swsscommon.DBConnector(0, dvs.redis_sock, 0) - self.adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - self.cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) - - def set_admin_status(self, interface, status): - tbl = swsscommon.Table(self.cdb, "PORT") - fvs = swsscommon.FieldValuePairs([("admin_status", status)]) - tbl.set(interface, fvs) - time.sleep(1) - - def create_vrf(self, vrf_name): - tbl = swsscommon.Table(self.cdb, "VRF") - fvs = swsscommon.FieldValuePairs([('empty', 'empty')]) - tbl.set(vrf_name, fvs) - time.sleep(1) - - def remove_vrf(self, vrf_name): - tbl = swsscommon.Table(self.cdb, "VRF") - tbl._del(vrf_name) - time.sleep(1) - - def create_l3_intf(self, interface, vrf_name): - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") - initial_entries = set(tbl.getKeys()) - - tbl = swsscommon.Table(self.cdb, "INTERFACE") - if len(vrf_name) == 0: - fvs = swsscommon.FieldValuePairs([("NULL", "NULL")]) - else: - fvs = swsscommon.FieldValuePairs([("vrf_name", vrf_name)]) - tbl.set(interface, fvs) - time.sleep(1) - - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") - current_entries = set(tbl.getKeys()) - assert len(current_entries - initial_entries) == 1 - return list(current_entries - initial_entries)[0] - - def remove_l3_intf(self, interface): - tbl = swsscommon.Table(self.cdb, "INTERFACE") - tbl._del(interface) - time.sleep(1) - - def add_ip_address(self, interface, ip): - tbl = swsscommon.Table(self.cdb, "INTERFACE") - fvs = swsscommon.FieldValuePairs([("NULL", "NULL")]) - tbl.set(interface + "|" + ip, fvs) - time.sleep(2) # IPv6 netlink message needs longer time - - def remove_ip_address(self, interface, ip): - tbl = swsscommon.Table(self.cdb, "INTERFACE") - tbl._del(interface + "|" + ip) - time.sleep(1) - - def add_neighbor(self, interface, ip, mac): - tbl = swsscommon.Table(self.cdb, "NEIGH") - fvs = swsscommon.FieldValuePairs([("neigh", mac)]) - tbl.set(interface + "|" + ip, fvs) - time.sleep(1) - - def remove_neighbor(self, interface, ip): - tbl = swsscommon.Table(self.cdb, "NEIGH") - tbl._del(interface + "|" + ip) - time.sleep(1) - - def test_NeighborAddRemoveIpv6(self, dvs, testlog): - self.setup_db(dvs) - - # bring up interface - # NOTE: For IPv6, only when the interface is up will the netlink message - # get generated. - self.set_admin_status("Ethernet8", "up") - - # create interface and get rif_oid - rif_oid = self.create_l3_intf("Ethernet8", "") - - # assign IP to interface - self.add_ip_address("Ethernet8", "2000::1/64") - - # add neighbor - self.add_neighbor("Ethernet8", "2000::2", "00:01:02:03:04:05") - - # check application database - tbl = swsscommon.Table(self.pdb, "NEIGH_TABLE:Ethernet8") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 1 - assert intf_entries[0] == "2000::2" - (status, fvs) = tbl.get(intf_entries[0]) - assert status == True - assert len(fvs) == 2 - for fv in fvs: - if fv[0] == "neigh": - assert fv[1] == "00:01:02:03:04:05" - elif fv[0] == "family": - assert fv[1] == "IPv6" - else: - assert False - - # check ASIC neighbor database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 1 - route = json.loads(intf_entries[0]) - assert route["ip"] == "2000::2" - assert route["rif"] == rif_oid - - (status, fvs) = tbl.get(intf_entries[0]) - assert status == True - for fv in fvs: - if fv[0] == "SAI_NEIGHBOR_ENTRY_ATTR_DST_MAC_ADDRESS": - assert fv[1] == "00:01:02:03:04:05" - - # remove neighbor - self.remove_neighbor("Ethernet8", "2000::2") - - # remove IP from interface - self.remove_ip_address("Ethernet8", "2000::1/64") - - # remove interface - self.remove_l3_intf("Ethernet8") - - # bring down interface - self.set_admin_status("Ethernet8", "down") - - # check application database - tbl = swsscommon.Table(self.pdb, "NEIGH_TABLE:Ethernet8") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - # check ASIC neighbor database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - - def test_NeighborAddRemoveIpv4(self, dvs, testlog): - self.setup_db(dvs) - - # bring up interface - self.set_admin_status("Ethernet8", "up") - - # create interface and get rif_oid - rif_oid = self.create_l3_intf("Ethernet8", "") - - # assign IP to interface - self.add_ip_address("Ethernet8", "10.0.0.1/24") - - # add neighbor - self.add_neighbor("Ethernet8", "10.0.0.2", "00:01:02:03:04:05") - - # check application database - tbl = swsscommon.Table(self.pdb, "NEIGH_TABLE:Ethernet8") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 1 - assert intf_entries[0] == "10.0.0.2" - (status, fvs) = tbl.get(intf_entries[0]) - assert status == True - assert len(fvs) == 2 - for fv in fvs: - if fv[0] == "neigh": - assert fv[1] == "00:01:02:03:04:05" - elif fv[0] == "family": - assert fv[1] == "IPv4" - else: - assert False - - # check ASIC neighbor database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 1 - route = json.loads(intf_entries[0]) - assert route["ip"] == "10.0.0.2" - assert route["rif"] == rif_oid - - (status, fvs) = tbl.get(intf_entries[0]) - assert status == True - for fv in fvs: - if fv[0] == "SAI_NEIGHBOR_ENTRY_ATTR_DST_MAC_ADDRESS": - assert fv[1] == "00:01:02:03:04:05" - - # remove neighbor - self.remove_neighbor("Ethernet8", "10.0.0.2") - - # remove IP from interface - self.remove_ip_address("Ethernet8", "10.0.0.1/24") - - # remove interface - self.remove_l3_intf("Ethernet8") - - # bring down interface - self.set_admin_status("Ethernet8", "down") - - # check application database - tbl = swsscommon.Table(self.pdb, "NEIGH_TABLE:Ethernet8") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - # check ASIC neighbor database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - def test_NeighborAddRemoveIpv6WithVrf(self, dvs, testlog): - self.setup_db(dvs) - - for i in [0, 4]: - # record ASIC neighbor database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY") - old_neigh_entries = set(tbl.getKeys()) - - intf_name = "Ethernet" + str(i) - vrf_name = "Vrf_" + str(i) - - # bring up interface - self.set_admin_status(intf_name, "up") - - # create vrf - self.create_vrf(vrf_name) - - # create interface and get rif_oid - rif_oid = self.create_l3_intf(intf_name, vrf_name) - - # assign IP to interface - self.add_ip_address(intf_name, "2000::1/64") - - # add neighbor - self.add_neighbor(intf_name, "2000::2", "00:01:02:03:04:05") - - # check application database - tbl = swsscommon.Table(self.pdb, "NEIGH_TABLE:" + intf_name) - neigh_entries = tbl.getKeys() - assert len(neigh_entries) == 1 - assert neigh_entries[0] == "2000::2" - (status, fvs) = tbl.get(neigh_entries[0]) - assert status == True - assert len(fvs) == 2 - for fv in fvs: - if fv[0] == "neigh": - assert fv[1] == "00:01:02:03:04:05" - elif fv[0] == "family": - assert fv[1] == "IPv6" - else: - assert False - - # check ASIC neighbor interface database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY") - current_neigh_entries = set(tbl.getKeys()) - neigh_entries = list(current_neigh_entries - old_neigh_entries) - assert len(neigh_entries) == 1 - route = json.loads(neigh_entries[0]) - assert route["ip"] == "2000::2" - assert route["rif"] == rif_oid - - (status, fvs) = tbl.get(neigh_entries[0]) - assert status == True - for fv in fvs: - if fv[0] == "SAI_NEIGHBOR_ENTRY_ATTR_DST_MAC_ADDRESS": - assert fv[1] == "00:01:02:03:04:05" - - for i in [0, 4]: - # record ASIC neighbor database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY") - old_neigh_entries_cnt = len(tbl.getKeys()) - - intf_name = "Ethernet" + str(i) - vrf_name = "Vrf_" + str(i) - - # remove neighbor - self.remove_neighbor(intf_name, "2000::2") - - # remove IP from interface - self.remove_ip_address(intf_name, "2000::1/64") - - # remove interface - self.remove_l3_intf(intf_name) - - # remove vrf - self.remove_vrf(vrf_name) - - # bring down interface - self.set_admin_status(intf_name, "down") - - # check application database - tbl = swsscommon.Table(self.pdb, "NEIGH_TABLE:" + intf_name) - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - # check ASIC neighbor interface database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY") - current_neigh_entries_cnt = len(tbl.getKeys()) - dec_neigh_entries_cnt = (old_neigh_entries_cnt - current_neigh_entries_cnt) - assert dec_neigh_entries_cnt == 1 - - def test_NeighborAddRemoveIpv4WithVrf(self, dvs, testlog): - self.setup_db(dvs) - - for i in [0, 4]: - # record ASIC neighbor database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY") - old_neigh_entries = set(tbl.getKeys()) - - intf_name = "Ethernet" + str(i) - vrf_name = "Vrf_" + str(i) - - # bring up interface - self.set_admin_status(intf_name, "up") - - # create vrf - self.create_vrf(vrf_name) - - # create interface and get rif_oid - rif_oid = self.create_l3_intf(intf_name, vrf_name) - - # assign IP to interface - self.add_ip_address(intf_name, "10.0.0.1/24") - - # add neighbor - self.add_neighbor(intf_name, "10.0.0.2", "00:01:02:03:04:05") - - # check application database - tbl = swsscommon.Table(self.pdb, "NEIGH_TABLE:" + intf_name) - neigh_entries = tbl.getKeys() - assert len(neigh_entries) == 1 - assert neigh_entries[0] == "10.0.0.2" - (status, fvs) = tbl.get(neigh_entries[0]) - assert status == True - assert len(fvs) == 2 - for fv in fvs: - if fv[0] == "neigh": - assert fv[1] == "00:01:02:03:04:05" - elif fv[0] == "family": - assert fv[1] == "IPv4" - else: - assert False - - # check ASIC neighbor interface database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY") - current_neigh_entries = set(tbl.getKeys()) - neigh_entries = list(current_neigh_entries - old_neigh_entries) - assert len(neigh_entries) == 1 - route = json.loads(neigh_entries[0]) - assert route["ip"] == "10.0.0.2" - assert route["rif"] == rif_oid - - (status, fvs) = tbl.get(neigh_entries[0]) - assert status == True - for fv in fvs: - if fv[0] == "SAI_NEIGHBOR_ENTRY_ATTR_DST_MAC_ADDRESS": - assert fv[1] == "00:01:02:03:04:05" - - for i in [0, 4]: - # record ASIC neighbor database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY") - old_neigh_entries_cnt = len(tbl.getKeys()) - - intf_name = "Ethernet" + str(i) - vrf_name = "Vrf_" + str(i) - - # remove neighbor - self.remove_neighbor(intf_name, "10.0.0.2") - - # remove IP from interface - self.remove_ip_address(intf_name, "10.0.0.1/24") - - # remove interface - self.remove_l3_intf(intf_name) - - # remove vrf - self.remove_vrf(vrf_name) - - # bring down interface - self.set_admin_status(intf_name, "down") - - # check application database - tbl = swsscommon.Table(self.pdb, "NEIGH_TABLE:" + intf_name) - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - # check ASIC neighbor interface database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY") - current_neigh_entries_cnt = len(tbl.getKeys()) - dec_neigh_entries_cnt = (old_neigh_entries_cnt - current_neigh_entries_cnt) - assert dec_neigh_entries_cnt == 1 - - def test_FlushResolveNeighborIpv6(self, dvs, testlog): - appl_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - prod_state_tbl = swsscommon.ProducerStateTable(appl_db, swsscommon.APP_NEIGH_RESOLVE_TABLE_NAME) - fvs = swsscommon.FieldValuePairs([("mac", "52:54:00:25:06:E9")]) - - prod_state_tbl.set("Vlan2:2000:1::1", fvs) - time.sleep(2) - - (exitcode, output) = dvs.runcmd(['sh', '-c', "supervisorctl status nbrmgrd | awk '{print $2}'"]) - assert output == "RUNNING\n" - - def test_FlushResolveNeighborIpv4(self, dvs, testlog): - appl_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - prod_state_tbl = swsscommon.ProducerStateTable(appl_db, swsscommon.APP_NEIGH_RESOLVE_TABLE_NAME) - fvs = swsscommon.FieldValuePairs([("mac", "52:54:00:25:06:E9")]) - - prod_state_tbl.set("Vlan2:192.168.10.1", fvs) - time.sleep(2) - - (exitcode, output) = dvs.runcmd(['sh', '-c', "supervisorctl status nbrmgrd | awk '{print $2}'"]) - assert output == "RUNNING\n" - - def test_Ipv4LinkLocalNeighbor(self, dvs, testlog): - self.setup_db(dvs) - - # bring up interface - self.set_admin_status("Ethernet8", "up") - - # create interface - self.create_l3_intf("Ethernet8", "") - - # assign IP to interface - self.add_ip_address("Ethernet8", "10.0.0.1/24") - - # add neighbor - self.add_neighbor("Ethernet8", "169.254.0.0", "00:01:02:03:04:05") - - # check application database - tbl = swsscommon.Table(self.pdb, "NEIGH_TABLE:Ethernet8") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 1 - - # check ASIC neighbor database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 1 - - # remove neighbor - self.remove_neighbor("Ethernet8", "169.254.0.0") - - # remove IP from interface - self.remove_ip_address("Ethernet8", "10.0.0.1/24") - - # remove interface - self.remove_l3_intf("Ethernet8") - - # bring down interface - self.set_admin_status("Ethernet8", "down") - - # check application database - tbl = swsscommon.Table(self.pdb, "NEIGH_TABLE:Ethernet8") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - # check ASIC neighbor database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - def test_Ipv4LinkLocalNeighborWithDualToR(self, dvs, testlog, setup_peer_switch): - self.setup_db(dvs) - - # bring up interface - self.set_admin_status("Ethernet8", "up") - - # create interface - self.create_l3_intf("Ethernet8", "") - - # assign IP to interface - self.add_ip_address("Ethernet8", "10.0.0.1/24") - - # add neighbor - self.add_neighbor("Ethernet8", "169.254.0.0", "00:01:02:03:04:05") - - # check application database - tbl = swsscommon.Table(self.pdb, "NEIGH_TABLE:Ethernet8") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - # check ASIC neighbor database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - # remove neighbor - self.remove_neighbor("Ethernet8", "169.254.0.0") - - # remove IP from interface - self.remove_ip_address("Ethernet8", "10.0.0.1/24") - - # remove interface - self.remove_l3_intf("Ethernet8") - - # bring down interface - self.set_admin_status("Ethernet8", "down") - - # check application database - tbl = swsscommon.Table(self.pdb, "NEIGH_TABLE:Ethernet8") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - # check ASIC neighbor database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - @pytest.fixture - def setup_peer_switch(self, dvs): - config_db = dvs.get_config_db() - config_db.create_entry( - self.CONFIG_PEER_SWITCH, - self.PEER_SWITCH_HOST, - self.DEFAULT_PEER_SWITCH_PARAMS - ) - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_nhg.py b/tests/test_nhg.py deleted file mode 100644 index b9e125f760..0000000000 --- a/tests/test_nhg.py +++ /dev/null @@ -1,2409 +0,0 @@ -import os -import re -import sys -import time -import json -import pytest -import ipaddress - -from swsscommon import swsscommon - -class TestNextHopGroupBase(object): - ASIC_NHS_STR = "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP" - ASIC_NHG_STR = "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP" - ASIC_NHG_MAP_STR = "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MAP" - ASIC_NHGM_STR = ASIC_NHG_STR + "_MEMBER" - ASIC_RT_STR = "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY" - ASIC_INSEG_STR = "ASIC_STATE:SAI_OBJECT_TYPE_INSEG_ENTRY" - - def get_route_id(self, prefix): - for k in self.asic_db.get_keys(self.ASIC_RT_STR): - if json.loads(k)['dest'] == prefix: - return k - - return None - - def get_inseg_id(self, label): - for k in self.asic_db.get_keys(self.ASIC_INSEG_STR): - if json.loads(k)['label'] == label: - return k - - return None - - def get_nhg_id(self, nhg_index): - # Add a route with the given index, then retrieve the next hop group ID - # from that route - asic_rts_count = len(self.asic_db.get_keys(self.ASIC_RT_STR)) - - fvs = swsscommon.FieldValuePairs([('nexthop_group', nhg_index)]) - prefix = '255.255.255.255/24' - ps = swsscommon.ProducerStateTable(self.dvs.get_app_db().db_connection, swsscommon.APP_ROUTE_TABLE_NAME) - ps.set(prefix, fvs) - - # Assert the route is created - try: - self.asic_db.wait_for_n_keys(self.ASIC_RT_STR, asic_rts_count + 1) - except Exception as e: - ps._del(prefix) - return None - else: - # Get the route ID for the created route - rt_id = self.get_route_id(prefix) - assert rt_id != None - - # Get the NHGID - nhgid = self.asic_db.get_entry(self.ASIC_RT_STR, rt_id)["SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID"] - ps._del(prefix) - self.asic_db.wait_for_deleted_entry(self.ASIC_RT_STR, rt_id) - - return nhgid - - def get_nhgm_ids(self, nhg_index): - nhgid = self.get_nhg_id(nhg_index) - nhgms = [] - - for k in self.asic_db.get_keys(self.ASIC_NHGM_STR): - fvs = self.asic_db.get_entry(self.ASIC_NHGM_STR, k) - - # Sometimes some of the NHGMs have no fvs for some reason, so - # we skip those - try: - if fvs['SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID'] == nhgid: - nhgms.append(k) - except KeyError as e: - pass - - return nhgms - - def get_nhg_map_id(self, nhg_map_index): - nhg_ps = swsscommon.ProducerStateTable(self.app_db.db_connection, swsscommon.APP_NEXTHOP_GROUP_TABLE_NAME) - cbf_nhg_ps = swsscommon.ProducerStateTable(self.app_db.db_connection, - swsscommon.APP_CLASS_BASED_NEXT_HOP_GROUP_TABLE_NAME) - - asic_nhgs_count = len(self.asic_db.get_keys(self.ASIC_NHG_STR)) - - # Create a NHG - fvs = swsscommon.FieldValuePairs([('nexthop', '10.0.0.1'), ('ifname', 'Ethernet0')]) - nhg_ps.set('_testnhg', fvs) - fvs = swsscommon.FieldValuePairs([('nexthop_group', '_testnhg')]) - nhg_ps.set('testnhg', fvs) - - # Add a CBF NHG pointing to the given map - fvs = swsscommon.FieldValuePairs([('members', 'testnhg'), ('selection_map', nhg_map_index)]) - cbf_nhg_ps.set('testcbfnhg', fvs) - time.sleep(1) - - # If the CBF NHG can't be created, the provided NHG map index is invalid - try: - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, asic_nhgs_count + 2) - except Exception as e: - # Remove the added NHGs - cbf_nhg_ps._del('testcbfnhg') - nhg_ps._del('testnhg') - nhg_ps._del('_testnhg') - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, asic_nhgs_count) - return None - - # Get the CBF NHG ID - cbf_nhg_id = self.get_nhg_id('testcbfnhg') - assert cbf_nhg_id != None - - # Get the NHG map id - nhg_map_id = self.asic_db.get_entry(self.ASIC_NHG_STR, cbf_nhg_id)['SAI_NEXT_HOP_GROUP_ATTR_SELECTION_MAP'] - - # Remove the added NHGs - cbf_nhg_ps._del('testcbfnhg') - nhg_ps._del('testnhg') - nhg_ps._del('_testnhg') - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, asic_nhgs_count) - - return nhg_map_id - - def port_name(self, i): - return "Ethernet" + str(i * 4) - - def port_ip(self, i): - return "10.0.0." + str(i * 2) - - def port_ipprefix(self, i): - return self.port_ip(i) + "/31" - - def peer_ip(self, i): - return "10.0.0." + str(i * 2 + 1) - - def port_mac(self, i): - return "00:00:00:00:00:0" + str(i + 1) - - def config_intf(self, i): - fvs = {'NULL': 'NULL'} - - self.config_db.create_entry("INTERFACE", self.port_name(i), fvs) - self.config_db.create_entry("INTERFACE", "{}|{}".format(self.port_name(i), self.port_ipprefix(i)), fvs) - self.dvs.port_admin_set(self.port_name(i), "up") - self.dvs.runcmd("arp -s {} {}".format(self.peer_ip(i), self.port_mac(i))) - assert self.dvs.servers[i].runcmd("ip link set down dev eth0") == 0 - assert self.dvs.servers[i].runcmd("ip link set up dev eth0") == 0 - - def flap_intf(self, i, status): - assert status in ['up', 'down'] - - self.dvs.servers[i].runcmd("ip link set {} dev eth0".format(status)) == 0 - time.sleep(2) - fvs = self.dvs.get_app_db().get_entry("PORT_TABLE", "Ethernet%d" % (i * 4)) - assert bool(fvs) - assert fvs["oper_status"] == status - - # BFD utilities for static route BFD and ecmp acceleration -- begin - def get_exist_bfd_session(self): - return set(self.asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_BFD_SESSION")) - - def create_bfd_session(self, key, pairs): - tbl = swsscommon.ProducerStateTable(self.app_db.db_connection, "BFD_SESSION_TABLE") - fvs = swsscommon.FieldValuePairs(list(pairs.items())) - tbl.set(key, fvs) - - def remove_bfd_session(self, key): - tbl = swsscommon.ProducerStateTable(self.app_db.db_connection, "BFD_SESSION_TABLE") - tbl._del(key) - - def check_asic_bfd_session_value(self, key, expected_values): - fvs = self.asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_BFD_SESSION", key) - for k, v in expected_values.items(): - assert fvs[k] == v - - def check_state_bfd_session_value(self, key, expected_values): - fvs = self.state_db.get_entry("BFD_SESSION_TABLE", key) - for k, v in expected_values.items(): - assert fvs[k] == v - - def update_bfd_session_state(self, dvs, session, state): - bfd_sai_state = {"Admin_Down": "SAI_BFD_SESSION_STATE_ADMIN_DOWN", - "Down": "SAI_BFD_SESSION_STATE_DOWN", - "Init": "SAI_BFD_SESSION_STATE_INIT", - "Up": "SAI_BFD_SESSION_STATE_UP"} - - ntf = swsscommon.NotificationProducer(self.asic_db.db_connection, "NOTIFICATIONS") - fvp = swsscommon.FieldValuePairs() - ntf_data = "[{\"bfd_session_id\":\""+session+"\",\"session_state\":\""+bfd_sai_state[state]+"\"}]" - ntf.send("bfd_session_state_change", ntf_data, fvp) - # BFD utilities for static route BFD and ecmp acceleration -- end - - def init_test(self, dvs, num_intfs): - self.dvs = dvs - self.app_db = self.dvs.get_app_db() - self.asic_db = self.dvs.get_asic_db() - self.config_db = self.dvs.get_config_db() - self.state_db = self.dvs.get_state_db() - self.nhg_ps = swsscommon.ProducerStateTable(self.app_db.db_connection, swsscommon.APP_NEXTHOP_GROUP_TABLE_NAME) - self.rt_ps = swsscommon.ProducerStateTable(self.app_db.db_connection, swsscommon.APP_ROUTE_TABLE_NAME) - self.lr_ps = swsscommon.ProducerStateTable(self.app_db.db_connection, swsscommon.APP_LABEL_ROUTE_TABLE_NAME) - self.cbf_nhg_ps = swsscommon.ProducerStateTable(self.app_db.db_connection, swsscommon.APP_CLASS_BASED_NEXT_HOP_GROUP_TABLE_NAME) - self.fc_to_nhg_ps = swsscommon.ProducerStateTable(self.app_db.db_connection, swsscommon.APP_FC_TO_NHG_INDEX_MAP_TABLE_NAME) - self.switch_ps = swsscommon.ProducerStateTable(self.app_db.db_connection, swsscommon.APP_SWITCH_TABLE_NAME) - - # Set switch FC capability to 63 - self.dvs.setReadOnlyAttr('SAI_OBJECT_TYPE_SWITCH', 'SAI_SWITCH_ATTR_MAX_NUMBER_OF_FORWARDING_CLASSES', '63') - - for i in range(num_intfs): - self.config_intf(i) - - self.asic_nhgs_count = len(self.asic_db.get_keys(self.ASIC_NHG_STR)) - self.asic_nhgms_count = len(self.asic_db.get_keys(self.ASIC_NHGM_STR)) - self.asic_insgs_count = len(self.asic_db.get_keys(self.ASIC_INSEG_STR)) - self.asic_nhs_count = len(self.asic_db.get_keys(self.ASIC_NHS_STR)) - self.asic_rts_count = len(self.asic_db.get_keys(self.ASIC_RT_STR)) - self.asic_nhg_maps_count = len(self.asic_db.get_keys(self.ASIC_NHG_MAP_STR)) - - def nhg_exists(self, nhg_index): - return self.get_nhg_id(nhg_index) is not None - - def route_exists(self, rt_prefix): - return self.get_route_id(rt_prefix) is not None - - def nhg_map_exists(self, nhg_map_index): - return self.get_nhg_map_id(nhg_map_index) is not None - - def enable_ordered_ecmp(self): - switch_fvs = swsscommon.FieldValuePairs([('ordered_ecmp', 'true')]) - self.switch_ps.set('switch', switch_fvs) - self.state_db.wait_for_field_match("SWITCH_CAPABILITY", "switch", {"ORDERED_ECMP_CAPABLE": "true"}) - - def disble_ordered_ecmp(self): - switch_fvs = swsscommon.FieldValuePairs([('ordered_ecmp', 'false')]) - self.switch_ps.set('switch', switch_fvs) - self.state_db.wait_for_field_match("SWITCH_CAPABILITY", "switch", {"ORDERED_ECMP_CAPABLE": "false"}) - -class TestNhgExhaustBase(TestNextHopGroupBase): - MAX_ECMP_COUNT = 512 - MAX_PORT_COUNT = 10 - - def init_test(self, dvs): - super().init_test(dvs, self.MAX_PORT_COUNT) - self.r = 0 - - def gen_nhg_fvs(self, binary): - nexthop = [] - ifname = [] - - for i in range(self.MAX_PORT_COUNT): - if binary[i] == '1': - nexthop.append(self.peer_ip(i)) - ifname.append(self.port_name(i)) - - nexthop = ','.join(nexthop) - ifname = ','.join(ifname) - fvs = swsscommon.FieldValuePairs([("nexthop", nexthop), ("ifname", ifname)]) - - return fvs - - def gen_valid_binary(self): - while True: - self.r += 1 - binary = self.gen_valid_binary.fmt.format(self.r) - # We need at least 2 ports for a nexthop group - if binary.count('1') <= 1: - continue - return binary - gen_valid_binary.fmt = '{{0:0{}b}}'.format(MAX_PORT_COUNT) - - -class TestRotueOrchNhgExhaust(TestNhgExhaustBase): - def test_route_nhg_exhaust(self, dvs, testlog): - """ - Test the situation of exhausting ECMP group, assume SAI_SWITCH_ATTR_NUMBER_OF_ECMP_GROUPS is 512 - - In order to achieve that, we will config - 1. 9 ports - 2. 512 routes with different nexthop group - - See Also - -------- - SwitchStateBase::set_number_of_ecmp_groups() - https://github.com/Azure/sonic-sairedis/blob/master/vslib/src/SwitchStateBase.cpp - - """ - - # TODO: check ECMP 512 - - def gen_ipprefix(r): - """ Construct route like 2.X.X.0/24 """ - ip = ipaddress.IPv4Address(IP_INTEGER_BASE + r * 256) - ip = str(ip) - ipprefix = ip + "/24" - return ipprefix - - def asic_route_nhg_fvs(k): - fvs = self.asic_db.get_entry(self.ASIC_RT_STR, k) - if not fvs: - return None - - nhgid = fvs.get("SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID") - if nhgid is None: - return None - - fvs = self.asic_db.get_entry(self.ASIC_NHG_STR, nhgid) - return fvs - - if sys.version_info < (3, 0): - IP_INTEGER_BASE = int(ipaddress.IPv4Address(unicode("2.2.2.0"))) - else: - IP_INTEGER_BASE = int(ipaddress.IPv4Address(str("2.2.2.0"))) - - self.init_test(dvs) - - # Add first batch of routes with unique nexthop groups in AppDB - route_count = 0 - while route_count < self.MAX_ECMP_COUNT: - binary = self.gen_valid_binary() - fvs = self.gen_nhg_fvs(binary) - route_ipprefix = gen_ipprefix(route_count) - self.rt_ps.set(route_ipprefix, fvs) - route_count += 1 - - # Wait and check ASIC DB the count of nexthop groups used - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.MAX_ECMP_COUNT) - - # Wait and check ASIC DB the count of routes - self.asic_db.wait_for_n_keys(self.ASIC_RT_STR, self.asic_rts_count + self.MAX_ECMP_COUNT) - self.asic_rts_count += self.MAX_ECMP_COUNT - - # Add a route with labeled NHs - self.asic_nhs_count = len(self.asic_db.get_keys(self.ASIC_NHS_STR)) - route_ipprefix = gen_ipprefix(route_count) - fvs = swsscommon.FieldValuePairs([('nexthop', '10.0.0.1,10.0.0.3'), - ('mpls_nh', 'push1,push3'), - ('ifname', 'Ethernet0,Ethernet4')]) - self.rt_ps.set(route_ipprefix, fvs) - route_count += 1 - - # A temporary route should be created - self.asic_db.wait_for_n_keys(self.ASIC_RT_STR, self.asic_rts_count + 1) - - # A NH should be elected as the temporary NHG and it should be created - # as it doesn't exist. - self.asic_db.wait_for_n_keys(self.ASIC_NHS_STR, self.asic_nhs_count + 1) - - # Delete the route. The route and the added labeled NH should be - # removed. - self.rt_ps._del(route_ipprefix) - route_count -= 1 - self.asic_db.wait_for_n_keys(self.ASIC_RT_STR, self.asic_rts_count) - self.asic_db.wait_for_n_keys(self.ASIC_NHS_STR, self.asic_nhs_count) - - # Add second batch of routes with unique nexthop groups in AppDB - # Add more routes with new nexthop group in AppDBdd - route_ipprefix = gen_ipprefix(route_count) - base_ipprefix = route_ipprefix - base = route_count - route_count = 0 - while route_count < 10: - binary = self.gen_valid_binary() - fvs = self.gen_nhg_fvs(binary) - route_ipprefix = gen_ipprefix(base + route_count) - self.rt_ps.set(route_ipprefix, fvs) - route_count += 1 - last_ipprefix = route_ipprefix - - # Wait until we get expected routes and check ASIC DB on the count of nexthop groups used, and it should not increase - self.asic_db.wait_for_n_keys(self.ASIC_RT_STR, self.asic_rts_count + 10) - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.MAX_ECMP_COUNT) - - # Check the route points to next hop group - # Note: no need to wait here - k = self.get_route_id("2.2.2.0/24") - assert k is not None - fvs = asic_route_nhg_fvs(k) - assert fvs is not None - - # Check the second batch does not point to next hop group - k = self.get_route_id(base_ipprefix) - assert k is not None - fvs = asic_route_nhg_fvs(k) - assert not(fvs) - - # Remove first batch of routes with unique nexthop groups in AppDB - route_count = 0 - self.r = 0 - while route_count < self.MAX_ECMP_COUNT: - route_ipprefix = gen_ipprefix(route_count) - self.rt_ps._del(route_ipprefix) - route_count += 1 - self.asic_rts_count -= self.MAX_ECMP_COUNT - - # Wait and check the second batch points to next hop group - # Check ASIC DB on the count of nexthop groups used, and it should not increase or decrease - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, 10) - k = self.get_route_id(base_ipprefix) - assert k is not None - fvs = asic_route_nhg_fvs(k) - assert fvs is not None - k = self.get_route_id(last_ipprefix) - assert k is not None - fvs = asic_route_nhg_fvs(k) - assert fvs is not None - - # Cleanup - - # Remove second batch of routes - for i in range(10): - route_ipprefix = gen_ipprefix(self.MAX_ECMP_COUNT + i) - self.rt_ps._del(route_ipprefix) - - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, 0) - self.asic_db.wait_for_n_keys(self.ASIC_RT_STR, self.asic_rts_count) - - -class TestNhgOrchNhgExhaust(TestNhgExhaustBase): - - def init_test(self, dvs): - super().init_test(dvs) - - self.nhg_count = self.asic_nhgs_count - self.first_valid_nhg = self.nhg_count - self.asic_nhgs = {} - - # Add first batch of next hop groups to reach the NHG limit - while self.nhg_count < self.MAX_ECMP_COUNT: - binary = self.gen_valid_binary() - nhg_fvs = self.gen_nhg_fvs(binary) - nhg_index = self.gen_nhg_index(self.nhg_count) - self.nhg_ps.set(nhg_index, nhg_fvs) - - # Save the NHG index/ID pair - self.asic_nhgs[nhg_index] = self.get_nhg_id(nhg_index) - - # Increase the number of NHGs in ASIC DB - self.nhg_count += 1 - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.MAX_ECMP_COUNT) - - def gen_nhg_index(self, nhg_number): - return "group{}".format(nhg_number) - - def create_temp_nhg(self): - binary = self.gen_valid_binary() - nhg_fvs = self.gen_nhg_fvs(binary) - nhg_index = self.gen_nhg_index(self.nhg_count) - self.nhg_ps.set(nhg_index, nhg_fvs) - self.nhg_count += 1 - - return nhg_index, binary - - def delete_nhg(self): - del_nhg_index = self.gen_nhg_index(self.first_valid_nhg) - del_nhg_id = self.asic_nhgs[del_nhg_index] - - self.nhg_ps._del(del_nhg_index) - self.asic_nhgs.pop(del_nhg_index) - self.first_valid_nhg += 1 - - return del_nhg_id - - - def test_nhgorch_nhg_exhaust(self, dvs, testlog): - - # Test scenario: - # - create a NHG and assert a NHG object doesn't get added to ASIC DB - # - delete a NHG and assert the newly created one is created in ASIC DB and its SAI ID changed - def temporary_group_promotion_test(): - # Add a new next hop group - it should create a temporary one instead - prev_nhgs = self.asic_db.get_keys(self.ASIC_NHG_STR) - nhg_index, _ = self.create_temp_nhg() - - # Save the temporary NHG's SAI ID - time.sleep(1) - nhg_id = self.get_nhg_id(nhg_index) - - # Assert no new group has been added - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.MAX_ECMP_COUNT) - - # Assert the same NHGs are in ASIC DB - assert prev_nhgs == self.asic_db.get_keys(self.ASIC_NHG_STR) - - # Delete an existing next hop group - del_nhg_id = self.delete_nhg() - - # Wait for the key to be deleted - self.asic_db.wait_for_deleted_entry(self.ASIC_NHG_STR, del_nhg_id) - - # Wait for the temporary group to be promoted and replace the deleted - # NHG - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.MAX_ECMP_COUNT) - - # Assert the SAI ID of the previously temporary NHG has been updated - assert nhg_id != self.get_nhg_id(nhg_index) - - # Save the promoted NHG index/ID - self.asic_nhgs[nhg_index] = self.get_nhg_id(nhg_index) - - # Test scenario: - # - update an existing NHG and assert the update is performed - def group_update_test(): - # Update a group - binary = self.gen_valid_binary() - nhg_fvs = self.gen_nhg_fvs(binary) - nhg_index = self.gen_nhg_index(self.first_valid_nhg) - - # Save the previous members - prev_nhg_members = self.get_nhgm_ids(nhg_index) - self.nhg_ps.set(nhg_index, nhg_fvs) - - # Wait a second so the NHG members get updated - time.sleep(1) - - # Assert the group was updated by checking it's members - assert self.get_nhgm_ids(nhg_index) != prev_nhg_members - - # Test scenario: - # - create and delete a NHG while the ASIC DB is full and assert nothing changes - def create_delete_temporary_test(): - # Create a new temporary group - nhg_index, _ = self.create_temp_nhg() - time.sleep(1) - - # Delete the temporary group - self.nhg_ps._del(nhg_index) - - # Assert the NHG does not exist anymore - assert not self.nhg_exists(nhg_index) - - # Assert the number of groups is the same - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.MAX_ECMP_COUNT) - - # Test scenario: - # - create a temporary NHG - # - update the NHG with a different number of members - # - delete a NHG and assert the new one is added and it has the updated number of members - def update_temporary_group_test(): - # Create a new temporary group - nhg_index, binary = self.create_temp_nhg() - - # Save the number of group members - binary_count = binary.count('1') - - # Update the temporary group with a different number of members - while True: - binary = self.gen_valid_binary() - if binary.count('1') == binary_count: - continue - binary_count = binary.count('1') - break - nhg_fvs = self.gen_nhg_fvs(binary) - self.nhg_ps.set(nhg_index, nhg_fvs) - - # Delete a group - del_nhg_id = self.delete_nhg() - - # Wait for the group to be deleted - self.asic_db.wait_for_deleted_entry(self.ASIC_NHG_STR, del_nhg_id) - - # The temporary group should be promoted - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.MAX_ECMP_COUNT) - - # Save the promoted NHG index/ID - self.asic_nhgs[nhg_index] = self.get_nhg_id(nhg_index) - - # Assert it has the updated details by checking the number of members - assert len(self.get_nhgm_ids(nhg_index)) == binary_count - - # Test scenario: - # - create a route pointing to a NHG and assert it is added - # - create a temporary NHG and update the route to point to it, asserting the route's SAI NHG ID changes - # - update the temporary NHG to contain completely different members and assert the SAI ID changes - # - delete a NHG and assert the temporary NHG is promoted and its SAI ID also changes - def route_nhg_update_test(): - # Add a route - nhg_index = self.gen_nhg_index(self.first_valid_nhg) - rt_fvs = swsscommon.FieldValuePairs([('nexthop_group', nhg_index)]) - self.rt_ps.set('2.2.2.0/24', rt_fvs) - - # Assert the route is created - self.asic_db.wait_for_n_keys(self.ASIC_RT_STR, self.asic_rts_count + 1) - - # Save the previous NHG ID - prev_nhg_id = self.asic_nhgs[nhg_index] - - # Create a new temporary group - nhg_index, binary = self.create_temp_nhg() - - # Get the route ID - rt_id = self.get_route_id('2.2.2.0/24') - assert rt_id != None - - # Update the route to point to the temporary NHG - rt_fvs = swsscommon.FieldValuePairs([('nexthop_group', nhg_index)]) - self.rt_ps.set('2.2.2.0/24', rt_fvs) - - # Wait for the route to change its NHG ID - self.asic_db.wait_for_field_negative_match(self.ASIC_RT_STR, - rt_id, - {'SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID': prev_nhg_id}) - - # Save the new route NHG ID - prev_nhg_id = self.asic_db.get_entry(self.ASIC_RT_STR, rt_id)['SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID'] - - # Update the temporary NHG with one that has different NHs - - # Create a new binary that uses the other interfaces than the previous - # binary was using - new_binary = [] - - for i in range(len(binary)): - if binary[i] == '1': - new_binary.append('0') - else: - new_binary.append('1') - - binary = ''.join(new_binary) - assert binary.count('1') > 1 - - nhg_fvs = self.gen_nhg_fvs(binary) - self.nhg_ps.set(nhg_index, nhg_fvs) - - # The NHG ID of the route should change - self.asic_db.wait_for_field_negative_match(self.ASIC_RT_STR, - rt_id, - {'SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID': prev_nhg_id}) - - # Delete a NHG. - del_nhg_id = self.delete_nhg() - - # Wait for the NHG to be deleted - self.asic_db.wait_for_deleted_entry(self.ASIC_NHG_STR, del_nhg_id) - - # The temporary group should get promoted. - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.MAX_ECMP_COUNT) - - # Save the promoted NHG index/ID - self.asic_nhgs[nhg_index] = self.get_nhg_id(nhg_index) - - # Assert the NHGID of the route changed due to temporary group being - # promoted. - self.asic_db.wait_for_field_match(self.ASIC_RT_STR, - rt_id, - {'SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID': self.asic_nhgs[nhg_index]}) - - # Test scenario: - # - create a temporary NHG containing labeled NHs and assert a new NH is added to represent the group - # - delete a NHG and assert the temporary NHG is promoted and all its NHs are added - def labeled_nhg_temporary_promotion_test(): - # Create a next hop group that contains labeled NHs that do not exist - # in NeighOrch - self.asic_nhs_count = len(self.asic_db.get_keys(self.ASIC_NHS_STR)) - fvs = swsscommon.FieldValuePairs([('nexthop', '10.0.0.1,10.0.0.3'), - ('mpls_nh', 'push1,push3'), - ('ifname', 'Ethernet0,Ethernet4')]) - nhg_index = self.gen_nhg_index(self.nhg_count) - self.nhg_ps.set(nhg_index, fvs) - self.nhg_count += 1 - - # A temporary next hop should be elected to represent the group and - # thus a new labeled next hop should be created - self.asic_db.wait_for_n_keys(self.ASIC_NHS_STR, self.asic_nhs_count + 1) - - # Delete a next hop group - self.delete_nhg() - - # The group should be promoted and the other labeled NH should also get - # created - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.MAX_ECMP_COUNT) - self.asic_db.wait_for_n_keys(self.ASIC_NHS_STR, self.asic_nhs_count + 2) - - # Save the promoted NHG index/ID - self.asic_nhgs[nhg_index] = self.get_nhg_id(nhg_index) - - # Test scenario: - # - update route to own its NHG and assert no new NHG is added - # - remove a NHG and assert the temporary NHG is promoted and added to ASIC DB - def back_compatibility_test(): - # Update the route with a RouteOrch's owned NHG - binary = self.gen_valid_binary() - nhg_fvs = self.gen_nhg_fvs(binary) - self.rt_ps.set('2.2.2.0/24', nhg_fvs) - - # Assert no new group has been added - time.sleep(1) - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.MAX_ECMP_COUNT) - - # Delete a next hop group - del_nhg_id = self.delete_nhg() - self.asic_db.wait_for_deleted_entry(self.ASIC_NHG_STR, del_nhg_id) - - # The temporary group should be promoted - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.MAX_ECMP_COUNT) - - # Test scenario: - # - create a NHG with all NHs not existing and assert the NHG is not created - # - update the NHG to have valid NHs and assert a temporary NHG is created - # - update the NHG to all invalid NHs again and assert the update is not performed and thus it has the same SAI - # ID - # - delete the temporary NHG - def invalid_temporary_test(): - # Create a temporary NHG that contains only NHs that do not exist - nhg_fvs = swsscommon.FieldValuePairs([('nexthop', '10.0.0.21,10.0.0.23'), - ('ifname', 'Ethernet40,Ethernet44')]) - nhg_index = self.gen_nhg_index(self.nhg_count) - self.nhg_count += 1 - self.nhg_ps.set(nhg_index, nhg_fvs) - - # Assert the group is not created - time.sleep(1) - assert not self.nhg_exists(nhg_index) - - # Update the temporary NHG to a valid one - binary = self.gen_valid_binary() - nhg_fvs = self.gen_nhg_fvs(binary) - self.nhg_ps.set(nhg_index, nhg_fvs) - - # Assert the temporary group was updated and the group got created - nhg_id = self.get_nhg_id(nhg_index) - assert nhg_id is not None - - # Update the temporary NHG to an invalid one again - nhg_fvs = swsscommon.FieldValuePairs([('nexthop', '10.0.0.21,10.0.0.23'), - ('ifname', 'Ethernet40,Ethernet44')]) - self.nhg_ps.set(nhg_index, nhg_fvs) - - # The update should fail and the temporary NHG should still be pointing - # to the old valid NH - assert self.get_nhg_id(nhg_index) == nhg_id - - # Delete the temporary group - self.nhg_ps._del(nhg_index) - - self.init_test(dvs) - - temporary_group_promotion_test() - group_update_test() - create_delete_temporary_test() - update_temporary_group_test() - route_nhg_update_test() - labeled_nhg_temporary_promotion_test() - back_compatibility_test() - invalid_temporary_test() - - # Cleanup - - # Delete the route - self.rt_ps._del('2.2.2.0/24') - self.asic_db.wait_for_n_keys(self.ASIC_RT_STR, self.asic_rts_count) - - # Delete the next hop groups - for k in self.asic_nhgs: - self.nhg_ps._del(k) - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count) - - - def test_cbf_nhg_exhaust(self, dvs, testlog): - self.init_test(dvs) - - # Create an FC to NH index selection map - fvs = swsscommon.FieldValuePairs([('0', '0')]) - self.fc_to_nhg_ps.set('cbfnhgmap1', fvs) - self.asic_db.wait_for_n_keys(self.ASIC_NHG_MAP_STR, self.asic_nhg_maps_count + 1) - - # Create a CBF NHG group - it should fail - fvs = swsscommon.FieldValuePairs([('members', 'group2'), - ('selection_map', 'cbfnhgmap1')]) - self.cbf_nhg_ps.set('cbfgroup1', fvs) - time.sleep(1) - assert(not self.nhg_exists('cbfgroup1')) - - # Delete a NHG - del_nhg_id = self.delete_nhg() - self.asic_db.wait_for_deleted_entry(self.ASIC_NHG_STR, del_nhg_id) - - # The CBF NHG should be created - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.MAX_ECMP_COUNT) - assert(self.nhg_exists('cbfgroup1')) - nhg_id = self.get_nhg_id('cbfgroup1') - - # Create a temporary NHG - nhg_index, _ = self.create_temp_nhg() - - # Update the CBF NHG to contain the temporary NHG - fvs = swsscommon.FieldValuePairs([('members', nhg_index), - ('selection_map', 'cbfnhgmap1')]) - self.cbf_nhg_ps.set('cbfgroup1', fvs) - time.sleep(1) - nhgm_id = self.get_nhgm_ids('cbfgroup1')[0] - fvs = self.asic_db.get_entry(self.ASIC_NHGM_STR, nhgm_id) - assert(fvs['SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID'] != self.get_nhg_id('group2')) - - # Coverage testing: CbfNhgHandler::hasSameMembers() returns false - # - # Update the group while it has a temporary NHG to contain one more member. - # - # Update the group keeping the same number of members, but changing the fully fledged NHG with another one. - # - # Update the group reversing the order of the 2 members. - # - # Update the CBF NHG back to its original form to resume testing. - fvs = swsscommon.FieldValuePairs([('members', '{},group3'.format(nhg_index)), - ('selection_map', 'cbfnhgmap1')]) - self.cbf_nhg_ps.set('cbfgroup1', fvs) - time.sleep(1) - fvs = swsscommon.FieldValuePairs([('members', '{},group4'.format(nhg_index)), - ('selection_map', 'cbfnhgmap1')]) - self.cbf_nhg_ps.set('cbfgroup1', fvs) - time.sleep(1) - fvs = swsscommon.FieldValuePairs([('members', 'group4,{}'.format(nhg_index)), - ('selection_map', 'cbfnhgmap1')]) - self.cbf_nhg_ps.set('cbfgroup1', fvs) - time.sleep(1) - fvs = swsscommon.FieldValuePairs([('members', nhg_index), ('selection_map', 'cbfnhgmap1')]) - self.cbf_nhg_ps.set('cbfgroup1', fvs) - - # Delete a NHG - nh_id = self.get_nhg_id(nhg_index) - del_nhg_id = self.delete_nhg() - self.asic_db.wait_for_deleted_entry(self.ASIC_NHG_STR, del_nhg_id) - - # The NHG should be promoted and the CBF NHG member updated - nhgm_id = self.get_nhgm_ids('cbfgroup1')[0] - self.asic_db.wait_for_field_negative_match(self.ASIC_NHGM_STR, - nhgm_id, - {'SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID': nh_id}) - self.asic_nhgs[nhg_index] = self.get_nhg_id(nhg_index) - - # Create a couple more temporary NHGs - nhg_index1, _ = self.create_temp_nhg() - nhg_index2, _ = self.create_temp_nhg() - - # Update the CBF NHG to contain both of them as well - fvs = swsscommon.FieldValuePairs([('members', '{},{},{}'.format(nhg_index, nhg_index1, nhg_index2)), - ('selection_map', 'cbfnhgmap1')]) - self.cbf_nhg_ps.set('cbfgroup1', fvs) - - # The previous CBF NHG member should be deleted - self.asic_db.wait_for_deleted_entry(self.ASIC_NHGM_STR, nhgm_id) - - # Create an FC to NH index selection map - fvs = swsscommon.FieldValuePairs([('0', '0')]) - self.fc_to_nhg_ps.set('cbfnhgmap2', fvs) - self.asic_db.wait_for_n_keys(self.ASIC_NHG_MAP_STR, self.asic_nhg_maps_count + 2) - - # Update the selection map of the group - old_map = self.asic_db.get_entry(self.ASIC_NHG_STR, nhg_id)['SAI_NEXT_HOP_GROUP_ATTR_SELECTION_MAP'] - nhgm_ids = self.get_nhgm_ids('cbfgroup1') - members = {nhgm_id: self.asic_db.get_entry(self.ASIC_NHGM_STR, nhgm_id) for nhgm_id in nhgm_ids} - fvs = swsscommon.FieldValuePairs([('members', '{},{},{}'.format(nhg_index, nhg_index1, nhg_index2)), - ('selection_map', 'cbfnhgmap2')]) - self.cbf_nhg_ps.set('cbfgroup1', fvs) - - # Check that the map was updates, but the members weren't - self.asic_db.wait_for_field_negative_match(self.ASIC_NHG_STR, - nhg_id, - {'SAI_NEXT_HOP_GROUP_ATTR_SELECTION_MAP': old_map}) - values = {} - for nhgm_id in nhgm_ids: - fvs = self.asic_db.get_entry(self.ASIC_NHGM_STR, nhgm_id) - assert(members[nhgm_id] == fvs) - values[nhgm_id] = fvs['SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID'] - - # Gradually delete temporary NHGs and check that the NHG members are - # updated - for i in range(2): - # Delete a temporary NHG - del_nhg_id = self.delete_nhg() - self.asic_db.wait_for_deleted_entry(self.ASIC_NHG_STR, del_nhg_id) - time.sleep(1) - - # Sleep 1 second to allow CBF NHG to update its member NH ID - time.sleep(1) - - # Check that one of the temporary NHGs has been updated - diff_count = 0 - for nhgm_id, nh_id in values.items(): - fvs = self.asic_db.get_entry(self.ASIC_NHGM_STR, nhgm_id) - if nh_id != fvs['SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID']: - values[nhgm_id] = fvs['SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID'] - diff_count += 1 - assert(diff_count == 1) - - for index in [nhg_index1, nhg_index2]: - self.asic_nhgs[index] = self.get_nhg_id(index) - - # Create a temporary NHG - nhg_index, binary = self.create_temp_nhg() - - # Update the CBF NHG to point to the new NHG - nhgm_ids = self.get_nhgm_ids('cbfgroup1') - fvs = swsscommon.FieldValuePairs([('members', nhg_index), ('selection_map', 'cbfnhgmap1')]) - self.cbf_nhg_ps.set('cbfgroup1', fvs) - self.asic_db.wait_for_deleted_keys(self.ASIC_NHGM_STR, nhgm_ids) - - # Update the temporary NHG to force using a new designated NH - new_binary = [] - - for i in range(len(binary)): - if binary[i] == '1': - new_binary.append('0') - else: - new_binary.append('1') - - binary = ''.join(new_binary) - assert binary.count('1') > 1 - - nh_id = self.get_nhg_id(nhg_index) - nhg_fvs = self.gen_nhg_fvs(binary) - self.nhg_ps.set(nhg_index, nhg_fvs) - - # The CBF NHG member's NH attribute should be updated - nhgm_id = self.get_nhgm_ids('cbfgroup1')[0] - self.asic_db.wait_for_field_negative_match(self.ASIC_NHGM_STR, - nhgm_id, - {'SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID': nh_id}) - - # Delete a NHG - del_nhg_id = self.delete_nhg() - self.asic_db.wait_for_deleted_entry(self.ASIC_NHG_STR, del_nhg_id) - - # The temporary group should be promoted - nh_id = self.get_nhg_id(nhg_index) - self.asic_db.wait_for_field_match(self.ASIC_NHGM_STR, - nhgm_id, - {'SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID': nh_id}) - self.asic_nhgs[nhg_index] = nh_id - - # Delete the NHGs - self.cbf_nhg_ps._del('cbfgroup1') - for k in self.asic_nhgs: - self.nhg_ps._del(k) - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count) - - # Delete the NHG maps - self.fc_to_nhg_ps._del('cbfnhgmap1') - self.fc_to_nhg_ps._del('cbfnhgmap2') - self.asic_db.wait_for_n_keys(self.ASIC_NHG_MAP_STR, self.asic_nhg_maps_count) - -class TestNextHopGroup(TestNextHopGroupBase): - - @pytest.mark.parametrize('ordered_ecmp', ['false', 'true']) - def test_route_nhg(self, ordered_ecmp, dvs, dvs_route, testlog): - self.init_test(dvs, 3) - nhip_seqid_map = {"10.0.0.1" : "1", "10.0.0.3" : "2" , "10.0.0.5" : "3" } - - if ordered_ecmp == 'true': - self.enable_ordered_ecmp() - - rtprefix = "2.2.2.0/24" - - dvs_route.check_asicdb_deleted_route_entries([rtprefix]) - - # nexthop group without weight - fvs = swsscommon.FieldValuePairs([("nexthop","10.0.0.1,10.0.0.3,10.0.0.5"), - ("ifname", "Ethernet0,Ethernet4,Ethernet8")]) - self.rt_ps.set(rtprefix, fvs) - - # check if route was propagated to ASIC DB - rtkeys = dvs_route.check_asicdb_route_entries([rtprefix]) - - # assert the route points to next hop group - fvs = self.asic_db.get_entry(self.ASIC_RT_STR, rtkeys[0]) - - nhgid = fvs["SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID"] - - fvs = self.asic_db.get_entry(self.ASIC_NHG_STR, nhgid) - - assert bool(fvs) - - if ordered_ecmp == 'true': - assert fvs["SAI_NEXT_HOP_GROUP_ATTR_TYPE"] == "SAI_NEXT_HOP_GROUP_TYPE_DYNAMIC_ORDERED_ECMP" - else: - assert fvs["SAI_NEXT_HOP_GROUP_ATTR_TYPE"] == "SAI_NEXT_HOP_GROUP_TYPE_DYNAMIC_UNORDERED_ECMP" - - keys = self.asic_db.get_keys(self.ASIC_NHGM_STR) - - assert len(keys) == 3 - - for k in keys: - fvs = self.asic_db.get_entry(self.ASIC_NHGM_STR, k) - - assert fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID"] == nhgid - - # verify weight attributes not in asic db - assert fvs.get("SAI_NEXT_HOP_GROUP_MEMBER_ATTR_WEIGHT") is None - - if ordered_ecmp == "true": - nhid = fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID"] - nh_fvs = self.asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP", nhid) - assert nhip_seqid_map[nh_fvs["SAI_NEXT_HOP_ATTR_IP"]] == fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_SEQUENCE_ID"] - else: - assert fvs.get("SAI_NEXT_HOP_GROUP_MEMBER_ATTR_SEQUENCE_ID") is None - - # BFD: test validate/invalidate nexthop group member when bfd state changes -- begin - bfdSessions = self.get_exist_bfd_session() - # Create BFD session - fieldValues = {"local_addr": "10.0.0.2"} - self.create_bfd_session("default:default:10.0.0.3", fieldValues) - time.sleep(1) - - # Checked created BFD session in ASIC_DB - createdSessions = self.get_exist_bfd_session() - bfdSessions - assert len(createdSessions) == 1 - session = createdSessions.pop() - - expected_adb_values = { - "SAI_BFD_SESSION_ATTR_SRC_IP_ADDRESS": "10.0.0.2", - "SAI_BFD_SESSION_ATTR_DST_IP_ADDRESS": "10.0.0.3", - "SAI_BFD_SESSION_ATTR_TYPE": "SAI_BFD_SESSION_TYPE_ASYNC_ACTIVE", - "SAI_BFD_SESSION_ATTR_IPHDR_VERSION": "4" - } - self.check_asic_bfd_session_value(session, expected_adb_values) - - # Check STATE_DB entry related to the BFD session - expected_sdb_values = {"state": "Down", "type": "async_active", "local_addr" : "10.0.0.2"} - self.check_state_bfd_session_value("default|default|10.0.0.3", expected_sdb_values) - - # Send BFD session state notification to update BFD session state - self.update_bfd_session_state(dvs, session, "Down") - time.sleep(1) - # Confirm BFD session state in STATE_DB is updated as expected - expected_sdb_values["state"] = "Down" - self.check_state_bfd_session_value("default|default|10.0.0.3", expected_sdb_values) - - #check nexthop group member is removed - keys = self.asic_db.get_keys(self.ASIC_NHGM_STR) - assert len(keys) == 2 - - # Send BFD session state notification to update BFD session state - self.update_bfd_session_state(dvs, session, "Up") - time.sleep(1) - # Confirm BFD session state in STATE_DB is updated as expected - expected_sdb_values["state"] = "Up" - self.check_state_bfd_session_value("default|default|10.0.0.3", expected_sdb_values) - - #check nexthop group member is added back - keys = self.asic_db.get_keys(self.ASIC_NHGM_STR) - assert len(keys) == 3 - - # Remove the BFD session - self.remove_bfd_session("default:default:10.0.0.3") - self.asic_db.wait_for_deleted_entry("ASIC_STATE:SAI_OBJECT_TYPE_BFD_SESSION", session) - # BFD: test validate/invalidate nexthop group member when bfd state changes -- end - - # Remove route 2.2.2.0/24 - self.rt_ps._del(rtprefix) - - # Wait for route 2.2.2.0/24 to be removed - dvs_route.check_asicdb_deleted_route_entries([rtprefix]) - - # Negative test with nexthops with incomplete weight info - # To validate Order ECMP change the nexthop order - fvs = swsscommon.FieldValuePairs([("nexthop","10.0.0.5,10.0.0.1,10.0.0.3"), - ("ifname", "Ethernet8,Ethernet0,Ethernet4"), - ("weight", "10,30")]) - self.rt_ps.set(rtprefix, fvs) - - # check if route was propagated to ASIC DB - rtkeys = dvs_route.check_asicdb_route_entries([rtprefix]) - - # assert the route points to next hop group - fvs = self.asic_db.get_entry(self.ASIC_RT_STR, rtkeys[0]) - - nhgid = fvs["SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID"] - - fvs = self.asic_db.get_entry(self.ASIC_NHG_STR, nhgid) - - assert bool(fvs) - - keys = self.asic_db.get_keys(self.ASIC_NHGM_STR) - - assert len(keys) == 3 - - for k in keys: - fvs = self.asic_db.get_entry(self.ASIC_NHGM_STR, k) - - assert fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID"] == nhgid - - # verify weight attributes not in asic db - assert fvs.get("SAI_NEXT_HOP_GROUP_MEMBER_ATTR_WEIGHT") is None - - if ordered_ecmp == "true": - nhid = fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID"] - nh_fvs = self.asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP", nhid) - assert nhip_seqid_map[nh_fvs["SAI_NEXT_HOP_ATTR_IP"]] == fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_SEQUENCE_ID"] - else: - assert fvs.get("SAI_NEXT_HOP_GROUP_MEMBER_ATTR_SEQUENCE_ID") is None - - - # Remove route 2.2.2.0/24 - self.rt_ps._del(rtprefix) - - # Wait for route 2.2.2.0/24 to be removed - dvs_route.check_asicdb_deleted_route_entries([rtprefix]) - - fvs = swsscommon.FieldValuePairs([("nexthop","10.0.0.1,10.0.0.3,10.0.0.5"), - ("ifname", "Ethernet0,Ethernet4,Ethernet8"), - ("weight", "10,30,50")]) - self.rt_ps.set(rtprefix, fvs) - - # check if route was propagated to ASIC DB - rtkeys = dvs_route.check_asicdb_route_entries([rtprefix]) - - # assert the route points to next hop group - fvs = self.asic_db.get_entry(self.ASIC_RT_STR, rtkeys[0]) - - nhgid = fvs["SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID"] - - fvs = self.asic_db.get_entry(self.ASIC_NHG_STR, nhgid) - - assert bool(fvs) - - keys = self.asic_db.get_keys(self.ASIC_NHGM_STR) - - assert len(keys) == 3 - - for k in keys: - fvs = self.asic_db.get_entry(self.ASIC_NHGM_STR, k) - - assert fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID"] == nhgid - - # verify weight attributes in asic db - nhid = fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID"] - weight = fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_WEIGHT"] - - if ordered_ecmp == "true": - nhid = fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID"] - nh_fvs = self.asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP", nhid) - assert nhip_seqid_map[nh_fvs["SAI_NEXT_HOP_ATTR_IP"]] == fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_SEQUENCE_ID"] - else: - assert fvs.get("SAI_NEXT_HOP_GROUP_MEMBER_ATTR_SEQUENCE_ID") is None - - fvs = self.asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP", nhid) - nhip = fvs["SAI_NEXT_HOP_ATTR_IP"].split('.') - expected_weight = int(nhip[3]) * 10 - - assert int(weight) == expected_weight - - rtprefix2 = "3.3.3.0/24" - - fvs = swsscommon.FieldValuePairs([("nexthop","10.0.0.1,10.0.0.3,10.0.0.5"), - ("ifname", "Ethernet0,Ethernet4,Ethernet8"), - ("weight", "20,30,40")]) - self.rt_ps.set(rtprefix2, fvs) - - # wait for route to be programmed - time.sleep(1) - - keys = self.asic_db.get_keys(self.ASIC_NHG_STR) - - assert len(keys) == 2 - - keys = self.asic_db.get_keys(self.ASIC_NHGM_STR) - - assert len(keys) == 6 - - # Remove route 3.3.3.0/24 - self.rt_ps._del(rtprefix2) - - # Wait for route 3.3.3.0/24 to be removed - dvs_route.check_asicdb_deleted_route_entries([rtprefix2]) - - - # bring links down one-by-one - for i in [0, 1, 2]: - self.flap_intf(i, 'down') - - keys = self.asic_db.get_keys(self.ASIC_NHGM_STR) - - assert len(keys) == 2 - i - - # bring links up one-by-one - # Bring link up in random order to verify sequence id is as per order - for i, val in enumerate([2,1,0]): - self.flap_intf(i, 'up') - - keys = self.asic_db.get_keys(self.ASIC_NHGM_STR) - - assert len(keys) == i + 1 - - for k in keys: - fvs = self.asic_db.get_entry(self.ASIC_NHGM_STR, k) - assert fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID"] == nhgid - if ordered_ecmp == "true": - nhid = fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID"] - nh_fvs = self.asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP", nhid) - assert nhip_seqid_map[nh_fvs["SAI_NEXT_HOP_ATTR_IP"]] == fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_SEQUENCE_ID"] - else: - assert fvs.get("SAI_NEXT_HOP_GROUP_MEMBER_ATTR_SEQUENCE_ID") is None - - # Remove route 2.2.2.0/24 - self.rt_ps._del(rtprefix) - - # Wait for route 2.2.2.0/24 to be removed - dvs_route.check_asicdb_deleted_route_entries([rtprefix]) - - # Cleanup by disabling to get default behaviour - if ordered_ecmp == 'true': - self.disble_ordered_ecmp() - - def test_label_route_nhg(self, dvs, testlog): - self.init_test(dvs, 3) - - # add label route - fvs = swsscommon.FieldValuePairs([("nexthop","10.0.0.1,10.0.0.3,10.0.0.5"), - ("ifname", "Ethernet0,Ethernet4,Ethernet8")]) - self.lr_ps.set("10", fvs) - self.asic_db.wait_for_n_keys(self.ASIC_INSEG_STR, self.asic_insgs_count + 1) - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count + 1) - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count + 3) - - k = self.get_inseg_id('10') - assert k is not None - - # assert the route points to next hop group - fvs = self.asic_db.get_entry(self.ASIC_INSEG_STR, k) - nhgid = fvs["SAI_INSEG_ENTRY_ATTR_NEXT_HOP_ID"] - fvs = self.asic_db.get_entry(self.ASIC_NHG_STR, nhgid) - assert bool(fvs) - - keys = self.asic_db.get_keys(self.ASIC_NHGM_STR) - assert len(keys) == 3 - for k in keys: - fvs = self.asic_db.get_entry(self.ASIC_NHGM_STR, k) - assert fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID"] == nhgid - - # bring links down one-by-one - for i in [0, 1, 2]: - self.flap_intf(i, 'down') - keys = self.asic_db.get_keys(self.ASIC_NHGM_STR) - assert len(keys) == 2 - i - - # bring links up one-by-one - for i in [0, 1, 2]: - self.flap_intf(i, 'up') - keys = self.asic_db.get_keys(self.ASIC_NHGM_STR) - assert len(keys) == i + 1 - for k in keys: - fvs = self.asic_db.get_entry(self.ASIC_NHGM_STR, k) - assert fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID"] == nhgid - - # Remove label route 10 - self.lr_ps._del("10") - - # Wait for label route 10 to be removed - self.asic_db.wait_for_n_keys(self.ASIC_INSEG_STR, self.asic_insgs_count) - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count) - - def test_nhgorch_labeled_nhs(self, dvs, testlog): - # Test scenario: - # - create a NHG with all labeled and weighted NHs and assert 2 new NHs are created - # - create a NHG with an existing label and assert no new NHs are created - # - create a NHG with a new label and assert a new NH is created - # - remove the third NHG and assert the NH is deleted - # - delete the second group and assert no NH is deleted because it is still referenced by the first group - # - remove the weights from the first NHG and change the labels, leaving one NH unlabeled; assert one NH is - # deleted - # - delete the first NHG and perform cleanup - def mainline_labeled_nhs_test(): - # Add a group containing labeled weighted NHs - fvs = swsscommon.FieldValuePairs([('nexthop', '10.0.0.1,10.0.0.3'), - ('mpls_nh', 'push1,push3'), - ('ifname', 'Ethernet0,Ethernet4'), - ('weight', '2,4')]) - self.nhg_ps.set('group1', fvs) - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count + 1) - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count + 2) - - # NhgOrch should create two next hops for the labeled ones - self.asic_db.wait_for_n_keys(self.ASIC_NHS_STR, self.asic_nhs_count + 2) - - # Assert the weights are properly set - nhgm_ids = self.get_nhgm_ids('group1') - weights = [] - for k in nhgm_ids: - fvs = self.asic_db.get_entry(self.ASIC_NHGM_STR, k) - weights.append(fvs['SAI_NEXT_HOP_GROUP_MEMBER_ATTR_WEIGHT']) - assert set(weights) == set(['2', '4']) - - # Create a new single next hop with the same label - fvs = swsscommon.FieldValuePairs([('nexthop', '10.0.0.1'), - ('mpls_nh', 'push1'), - ('ifname', 'Ethernet0')]) - self.nhg_ps.set('group2', fvs) - - # No new next hop should be added - time.sleep(1) - assert len(self.asic_db.get_keys(self.ASIC_NHS_STR)) == self.asic_nhs_count + 2 - - # Create a new single next hop with a different label - fvs = swsscommon.FieldValuePairs([('nexthop', '10.0.0.1'), - ('mpls_nh', 'push2'), - ('ifname', 'Ethernet0')]) - self.nhg_ps.set('group3', fvs) - - # A new next hop should be added - self.asic_db.wait_for_n_keys(self.ASIC_NHS_STR, self.asic_nhs_count + 3) - - # Delete group3 - self.nhg_ps._del('group3') - - # Group3's NH should be deleted - self.asic_db.wait_for_n_keys(self.ASIC_NHS_STR, self.asic_nhs_count + 2) - - # Delete group2 - self.nhg_ps._del('group2') - - # The number of NHs should be the same as they are still referenced by - # group1 - time.sleep(1) - self.asic_db.wait_for_n_keys(self.ASIC_NHS_STR, self.asic_nhs_count + 2) - - # Update group1 with no weights and both labeled and unlabeled NHs - fvs = swsscommon.FieldValuePairs([('nexthop', '10.0.0.1,10.0.0.3'), - ('mpls_nh', 'push2,na'), - ('ifname', 'Ethernet0,Ethernet4')]) - self.nhg_ps.set('group1', fvs) - - # Group members should be replaced and one NH should get deleted - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count + 2) - self.asic_db.wait_for_n_keys(self.ASIC_NHS_STR, self.asic_nhs_count + 1) - - # Delete group1 - self.nhg_ps._del('group1') - - # Wait for the group and it's members to be deleted - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count) - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count) - - # The two next hops should also get deleted - self.asic_db.wait_for_n_keys(self.ASIC_NHS_STR, self.asic_nhs_count) - - # Test scenario: - # - create a route with labeled and weighted NHs and assert a NHG and 2 NHs are created - # - create a NHG with the same details as the one being used by the route and assert a NHG is created and no - # new NHs are added - # - update the NHG by changing the first NH's label and assert a new NH is created - # - remove the route and assert that only one (now unreferenced) NH is removed - # - remove the NHG and perform cleanup - def routeorch_nhgorch_interop_test(): - # Create a route with labeled NHs - fvs = swsscommon.FieldValuePairs([('nexthop', '10.0.0.1,10.0.0.3'), - ('mpls_nh', 'push1,push3'), - ('ifname', 'Ethernet0,Ethernet4'), - ('weight', '2,4')]) - self.rt_ps.set('2.2.2.0/24', fvs) - self.asic_db.wait_for_n_keys(self.ASIC_RT_STR, self.asic_rts_count + 1) - - # A NHG should be created - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count + 1) - - # Two new next hops should be created - self.asic_db.wait_for_n_keys(self.ASIC_NHS_STR, self.asic_nhs_count + 2) - - # Create a NHG with the same details - self.nhg_ps.set('group1', fvs) - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count + 2) - - # No new next hops should be created - assert len(self.asic_db.get_keys(self.ASIC_NHS_STR)) == self.asic_nhs_count + 2 - - # Update the group with a different NH - fvs = swsscommon.FieldValuePairs([('nexthop', '10.0.0.1,10.0.0.3'), - ('mpls_nh', 'push2,push3'), - ('ifname', 'Ethernet0,Ethernet4'), - ('weight', '2,4')]) - self.nhg_ps.set('group1', fvs) - - # A new next hop should be created - self.asic_db.wait_for_n_keys(self.ASIC_NHS_STR, self.asic_nhs_count + 3) - - # group1 should be updated and a new NHG shouldn't be created - time.sleep(1) - assert len(self.asic_db.get_keys(self.ASIC_NHG_STR)) == self.asic_nhgs_count + 2 - - # Remove the route - self.rt_ps._del('2.2.2.0/24') - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count + 1) - - # One NH should become unreferenced and should be deleted. The other - # one is still referenced by NhgOrch's owned NHG. - self.asic_db.wait_for_n_keys(self.ASIC_NHS_STR, self.asic_nhs_count + 2) - - # Remove the group - self.nhg_ps._del('group1') - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count) - - # Both new next hops should be deleted - self.asic_db.wait_for_n_keys(self.ASIC_NHS_STR, self.asic_nhs_count) - - self.init_test(dvs, 2) - - mainline_labeled_nhs_test() - routeorch_nhgorch_interop_test() - - def test_nhgorch_excp_group_cases(self, dvs, testlog): - # Test scenario: - # - remove a NHG that does not exist and assert the number of NHGs in ASIC DB remains the same - def remove_inexistent_nhg_test(): - # Remove a group that does not exist - self.nhg_ps._del("group1") - time.sleep(1) - assert len(self.asic_db.get_keys(self.ASIC_NHG_STR)) == self.asic_nhgs_count - - # Test scenario: - # - create a NHG with a member which does not exist and assert no NHG is created - # - update the NHG to contain all valid members and assert the NHG is created and it has 2 members - def nhg_members_validation_test(): - # Create a next hop group with a member that does not exist - should fail - fvs = swsscommon.FieldValuePairs([('nexthop', '10.0.0.1,10.0.0.3,10.0.0.63'), - ("ifname", "Ethernet0,Ethernet4,Ethernet124")]) - self.nhg_ps.set("group1", fvs) - time.sleep(1) - assert len(self.asic_db.get_keys(self.ASIC_NHG_STR)) == self.asic_nhgs_count - - # Issue an update for this next hop group that doesn't yet exist, - # which contains only valid NHs. This will overwrite the previous - # operation and create the group. - fvs = swsscommon.FieldValuePairs([('nexthop', '10.0.0.1,10.0.0.5'), - ("ifname", "Ethernet0,Ethernet8")]) - self.nhg_ps.set("group1", fvs) - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count + 1) - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count + 2) - - # Check the group has its two members - assert len(self.get_nhgm_ids('group1')) == 2 - - # Test scenario: - # - create a route pointing to the NHG created in `test_nhg_members_validation` and assert it is being created - # - remove the NHG and assert it fails as it is being referenced - # - create a new NHG and assert it and its members are being created - # - update the route to point to the new NHG and assert the first NHG is now deleted as it's not referenced - # anymore - def remove_referenced_nhg_test(): - # Add a route referencing the new group - fvs = swsscommon.FieldValuePairs([('nexthop_group', 'group1')]) - self.rt_ps.set('2.2.2.0/24', fvs) - self.asic_db.wait_for_n_keys(self.ASIC_RT_STR, self.asic_rts_count + 1) - - # Try removing the group while it still has references - should fail - self.nhg_ps._del('group1') - time.sleep(1) - assert len(self.asic_db.get_keys(self.ASIC_NHG_STR)) == self.asic_nhgs_count + 1 - - # Create a new group - fvs = swsscommon.FieldValuePairs([('nexthop', '10.0.0.1,10.0.0.3'), - ('ifname', 'Ethernet0,Ethernet4')]) - self.nhg_ps.set("group2", fvs) - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count + 2) - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count + 4) - - # Update the route to point to the new group - fvs = swsscommon.FieldValuePairs([('nexthop_group', 'group2')]) - self.rt_ps.set('2.2.2.0/24', fvs) - - # The first group should have got deleted - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count + 1) - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count + 2) - - # The route's group should have changed to the new one - assert self.asic_db.get_entry(self.ASIC_RT_STR, self.get_route_id('2.2.2.0/24'))['SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID'] == self.get_nhg_id('group2') - - # Test scenario: - # - update the route created in `test_remove_referenced_nhg` to own the NHG with the same details as the - # previous one and assert a new NHG and 2 new NHGMs are added - # - update the route to point back to the original NHG and assert the routeOrch's owned NHG is deleted - def routeorch_nhgorch_interop_test(): - rt_id = self.get_route_id('2.2.2.0/24') - assert rt_id is not None - - # Update the route with routeOrch's owned next hop group - nhgid = self.asic_db.get_entry(self.ASIC_RT_STR, rt_id)['SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID'] - fvs = swsscommon.FieldValuePairs([('nexthop', '10.0.0.1,10.0.0.3'), - ('ifname', 'Ethernet0,Ethernet4')]) - self.rt_ps.set('2.2.2.0/24', fvs) - - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count + 2) - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count + 4) - - # Assert the next hop group ID changed - time.sleep(1) - assert self.asic_db.get_entry(self.ASIC_RT_STR, rt_id)['SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID'] != nhgid - nhgid = self.asic_db.get_entry(self.ASIC_RT_STR, rt_id)['SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID'] - - # Update the route to point back to group2 - fvs = swsscommon.FieldValuePairs([('nexthop_group', 'group2')]) - self.rt_ps.set('2.2.2.0/24', fvs) - - # The routeOrch's owned next hop group should get deleted - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count + 1) - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count + 2) - - # Assert the route points back to group2 - assert self.asic_db.get_entry(self.ASIC_RT_STR, rt_id)['SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID'] != nhgid - - # Test scenario: - # - create a new NHG with the same details as the previous NHG and assert a new NHG and 2 new NHGMs are created - # - update the route to point to the new NHG and assert its SAI NHG ID changes - def identical_nhgs_test(): - rt_id = self.get_route_id('2.2.2.0/24') - assert rt_id is not None - - # Create a new group with the same members as group2 - nhgid = self.asic_db.get_entry(self.ASIC_RT_STR, rt_id)['SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID'] - fvs = swsscommon.FieldValuePairs([('nexthop', '10.0.0.1,10.0.0.3'), - ('ifname', 'Ethernet0,Ethernet4')]) - self.nhg_ps.set("group1", fvs) - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count + 2) - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count + 4) - - # Update the route to point to the new group - fvs = swsscommon.FieldValuePairs([('nexthop_group', 'group1')]) - self.rt_ps.set('2.2.2.0/24', fvs) - time.sleep(1) - - # Assert the next hop group ID changed - assert self.asic_db.get_entry(self.ASIC_RT_STR, rt_id)['SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID'] != nhgid - - # Test scenario: - # - create a route referencing a NHG that does not exist and assert it is not created - def create_route_inexistent_nhg_test(): - # Add a route with a NHG that does not exist - fvs = swsscommon.FieldValuePairs([('nexthop_group', 'group3')]) - self.rt_ps.set('2.2.3.0/24', fvs) - time.sleep(1) - assert self.get_route_id('2.2.3.0/24') is None - - # Remove the pending route - self.rt_ps._del('2.2.3.0/24') - - self.init_test(dvs, 3) - - remove_inexistent_nhg_test() - nhg_members_validation_test() - remove_referenced_nhg_test() - routeorch_nhgorch_interop_test() - identical_nhgs_test() - create_route_inexistent_nhg_test() - - # Cleanup - - # Remove the route - self.rt_ps._del('2.2.2.0/24') - self.asic_db.wait_for_n_keys(self.ASIC_RT_STR, self.asic_rts_count) - - # Remove the groups - self.nhg_ps._del('group1') - self.nhg_ps._del('group2') - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count) - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count) - - def test_nhgorch_nh_group(self, dvs, testlog): - # Test scenario: - # - create recursive nhg - rec_grp1 with two members - grp1 and grp2 only one of which exists - # - create singleton nhg grp2 and check if the rec_grp1 is updated with both the members - # - create a recursive nhg - rec_grp2 with another recursive nhg - rec_grp1 as member. Assert that the nhg is not created. - def create_recursive_nhg_test(): - # create next hop group in APPL DB - fvs = swsscommon.FieldValuePairs([('nexthop', '10.0.0.1'), ('ifname', 'Ethernet0')]) - self.nhg_ps.set("grp1", fvs) - - # create a recursive nexthop group with two members - fvs = swsscommon.FieldValuePairs([('nexthop_group', 'grp1,grp2')]) - self.nhg_ps.set("rec_grp1", fvs) - - # check if group was propagated to ASIC DB with the existing member - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count + 1) - assert self.nhg_exists('rec_grp1') - - # check if the existing member was propagated to ASIC DB - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count + 1) - assert len(self.get_nhgm_ids('rec_grp1')) == 1 - - # add another singleton nexthop group - grp2 - fvs = swsscommon.FieldValuePairs([('nexthop', '10.0.0.3'), ('ifname', 'Ethernet4')]) - self.nhg_ps.set("grp2", fvs) - - # check if both the members were propagated to ASIC DB - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count + 2) - assert len(self.get_nhgm_ids('rec_grp1')) == 2 - - # update the recursive nexthop group with another member not yet existing - fvs = swsscommon.FieldValuePairs([('nexthop_group', 'grp1,grp2,grp3')]) - self.nhg_ps.set("rec_grp1", fvs) - - # check if only two members were propagated to ASIC DB - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count + 2) - assert len(self.get_nhgm_ids('rec_grp1')) == 2 - - # add another singleton nexthop group - grp3 - fvs = swsscommon.FieldValuePairs([('nexthop', '10.0.0.5'), ('ifname', 'Ethernet8')]) - self.nhg_ps.set("grp3", fvs) - - # check if all members were propagated to ASIC DB - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count + 3) - assert len(self.get_nhgm_ids('rec_grp1')) == 3 - - # create a recursive nhg with another recursive nhg as member - fvs = swsscommon.FieldValuePairs([('nexthop_group', 'rec_grp1')]) - self.nhg_ps.set("rec_grp2", fvs) - - # check that the group was not propagated to ASIC DB - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count + 1) - assert not self.nhg_exists('rec_grp2') - - self.nhg_ps._del("rec_grp2") - self.nhg_ps._del("rec_grp1") - self.nhg_ps._del("grp1") - self.nhg_ps._del("grp2") - self.nhg_ps._del("grp3") - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count) - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count) - - # Test scenario: - # - create NHG 'group1' and assert it is being added to ASIC DB along with its members - def create_nhg_test(): - # create next hop group in APPL DB - fvs = swsscommon.FieldValuePairs([('nexthop', '10.0.0.1,10.0.0.3,10.0.0.5'), - ("ifname", "Ethernet0,Ethernet4,Ethernet8")]) - self.nhg_ps.set("group1", fvs) - - # check if group was propagated to ASIC DB - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count + 1) - assert self.nhg_exists('group1') - - # check if members were propagated to ASIC DB - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count + 3) - assert len(self.get_nhgm_ids('group1')) == 3 - - # Test scenario: - # - create a route pointing to `group1` and assert it is being added to ASIC DB and pointing to its SAI ID - # - delete the route and assert it is being removed - def create_route_nhg_test(): - # create route in APPL DB - fvs = swsscommon.FieldValuePairs([("nexthop_group", "group1")]) - self.rt_ps.set("2.2.2.0/24", fvs) - - # check if route was propagated to ASIC DB - self.asic_db.wait_for_n_keys(self.ASIC_RT_STR, self.asic_rts_count + 1) - - k = self.get_route_id('2.2.2.0/24') - assert k is not None - - # assert the route points to next hop group - fvs = self.asic_db.get_entry(self.ASIC_RT_STR, k) - assert fvs["SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID"] == self.get_nhg_id('group1') - - # Remove route 2.2.2.0/24 - self.rt_ps._del("2.2.2.0/24") - self.asic_db.wait_for_n_keys(self.ASIC_RT_STR, self.asic_rts_count) - - # Test scenario: - # - bring the links down one by one and assert the group1's members are subsequently removed and the group - # still exists - # - bring the liks up one by one and assert the group1's members are subsequently added back - def link_flap_test(): - # bring links down one-by-one - for i in [0, 1, 2]: - self.flap_intf(i, 'down') - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count + 2 - i) - assert len(self.get_nhgm_ids('group1')) == 2 - i - assert self.nhg_exists('group1') - - # bring links up one-by-one - for i in [0, 1, 2]: - self.flap_intf(i, 'up') - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count + i + 1) - assert len(self.get_nhgm_ids('group1')) == i + 1 - - # Test scenario: - # - bring a link down and assert a NHGM of `group1` is removed - # - create NHG `group2` which has a member pointing to the link being down and assert the group gets created - # but the member referencing the link is not added - # - update `group1` by removing a member while having another member referencing the link which is down and - # assert it'll only have a member added in ASIC DB - # - bring the link back up and assert the missing 2 members of `group1` and `group2` are added - # - remove `group2` and assert it and its members are removed - def validate_invalidate_group_member_test(): - # Bring an interface down - self.flap_intf(1, 'down') - - # One group member will get deleted - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count + 2) - - # Create a group that contains a NH that uses the down link - fvs = swsscommon.FieldValuePairs([('nexthop', '10.0.0.1,10.0.0.3'), - ("ifname", "Ethernet0,Ethernet4")]) - self.nhg_ps.set('group2', fvs) - - # The group should get created, but it will not contained the NH that - # has the link down - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count + 2) - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count + 3) - assert len(self.get_nhgm_ids('group2')) == 1 - - # Update the NHG with one interface down - fvs = swsscommon.FieldValuePairs([('nexthop', '10.0.0.3,10.0.0.1'), - ("ifname", "Ethernet4,Ethernet0")]) - self.nhg_ps.set("group1", fvs) - - # Wait for group members to update - the group will contain only the - # members that have their links up - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count + 2) - assert len(self.get_nhgm_ids('group1')) == 1 - - # Bring the interface up - self.flap_intf(1, 'up') - - # Check that the missing member of group1 and group2 is being added - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count + 4) - - # Remove group2 - self.nhg_ps._del('group2') - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count + 1) - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count + 2) - - # Test scenario: - # - create NHG `group2` with a NH that does not exist and assert it isn't created - # - update `group1` to contain the invalid NH and assert it remains only with the unremoved members - # - configure the invalid NH's interface and assert `group2` gets created and `group1`'s NH is added - # - delete `group` and assert it is being removed - def inexistent_group_member_test(): - # Create group2 with a NH that does not exist - fvs = swsscommon.FieldValuePairs([('nexthop', '10.0.0.3,10.0.0.63'), - ("ifname", "Ethernet4,Ethernet124")]) - self.nhg_ps.set("group2", fvs) - - # The groups should not be created - time.sleep(1) - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count + 1) - - # Update group1 with a NH that does not exist - fvs = swsscommon.FieldValuePairs([('nexthop', '10.0.0.3,10.0.0.63'), - ("ifname", "Ethernet4,Ethernet124")]) - self.nhg_ps.set("group1", fvs) - - # The update should fail, leaving group1 with only the unremoved - # members - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count + 1) - assert len(self.get_nhgm_ids('group1')) == 1 - - # Configure the missing NH's interface - self.config_intf(31) - - # A couple more routes will be added to ASIC DB - self.asic_rts_count += 2 - - # Group2 should get created and group1 should be updated - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count + 2) - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count + 4) - assert len(self.get_nhgm_ids('group1')) == 2 - assert len(self.get_nhgm_ids('group2')) == 2 - - # Delete group2 - self.nhg_ps._del('group2') - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count + 1) - - # Test scenario: - # - update `group1` to have 4 members and assert they are all added - # - update `group1` to have only 1 member and assert the other 3 are removed - # - update `group1` to have 2 members and assert a new one is added - def update_nhgm_count_test(): - # Update the NHG, adding two new members - fvs = swsscommon.FieldValuePairs([('nexthop', '10.0.0.1,10.0.0.3,10.0.0.5,10.0.0.7'), - ("ifname", "Ethernet0,Ethernet4,Ethernet8,Ethernet12")]) - self.nhg_ps.set("group1", fvs) - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count + 4) - assert len(self.get_nhgm_ids('group1')) == 4 - - # Update the group to one NH only - fvs = swsscommon.FieldValuePairs([('nexthop', '10.0.0.1'), ("ifname", "Ethernet0")]) - self.nhg_ps.set("group1", fvs) - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count) - assert len(self.get_nhgm_ids('group1')) == 0 - - # Update the group to 2 NHs - fvs = swsscommon.FieldValuePairs([('nexthop', '10.0.0.1,10.0.0.3'), ("ifname", "Ethernet0,Ethernet4")]) - self.nhg_ps.set("group1", fvs) - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count + 2) - assert len(self.get_nhgm_ids('group1')) == 2 - - self.init_test(dvs, 4) - - create_recursive_nhg_test() - create_nhg_test() - create_route_nhg_test() - link_flap_test() - validate_invalidate_group_member_test() - inexistent_group_member_test() - update_nhgm_count_test() - - # Cleanup - - # Remove group1 - self.nhg_ps._del("group1") - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count) - - def test_nhgorch_label_route(self, dvs, testlog): - self.init_test(dvs, 4) - - # create next hop group in APPL DB - fvs = swsscommon.FieldValuePairs([('nexthop', '10.0.0.1,10.0.0.3,10.0.0.5'), - ("ifname", "Ethernet0,Ethernet4,Ethernet8")]) - self.nhg_ps.set("group1", fvs) - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count + 1) - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count + 3) - - # create label route in APPL DB pointing to the NHG - fvs = swsscommon.FieldValuePairs([("nexthop_group", "group1")]) - self.lr_ps.set("20", fvs) - self.asic_db.wait_for_n_keys(self.ASIC_INSEG_STR, self.asic_insgs_count + 1) - - k = self.get_inseg_id('20') - assert k is not None - - # assert the route points to next hop group - fvs = self.asic_db.get_entry(self.ASIC_INSEG_STR, k) - assert fvs["SAI_INSEG_ENTRY_ATTR_NEXT_HOP_ID"] == self.get_nhg_id('group1') - - # Remove label route 20 - self.lr_ps._del("20") - self.asic_db.wait_for_n_keys(self.ASIC_INSEG_STR, self.asic_insgs_count) - - # Remove group1 - self.nhg_ps._del("group1") - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count) - -class TestCbfNextHopGroup(TestNextHopGroupBase): - MAX_NHG_MAP_COUNT = 512 - - def test_cbf_nhgorch(self, dvs, testlog): - - # Test scenario: - # - create two NHGs and a NHG map - # - create a CBF NHG and assert it has the expected details - # - delete the CBF NHG - def mainline_cbf_nhg_test(): - # Create two non-CBF NHGs - fvs = swsscommon.FieldValuePairs([('nexthop', '10.0.0.1,10.0.0.3,10.0.0.5'), - ("ifname", "Ethernet0,Ethernet4,Ethernet8")]) - self.nhg_ps.set("group1", fvs) - - fvs = swsscommon.FieldValuePairs([('nexthop', '10.0.0.1,10.0.0.3'), - ('ifname', 'Ethernet0,Ethernet4')]) - self.nhg_ps.set('group2', fvs) - - # Wait for the groups to appear in ASIC DB - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count + 2) - - # Create an FC to NH index selection map - nhg_map = [(str(i), '0' if i < 4 else '1') for i in range(8)] - fvs = swsscommon.FieldValuePairs(nhg_map) - self.fc_to_nhg_ps.set('cbfnhgmap1', fvs) - self.asic_db.wait_for_n_keys(self.ASIC_NHG_MAP_STR, self.asic_nhg_maps_count + 1) - - # Create a CBF NHG - fvs = swsscommon.FieldValuePairs([('members', 'group1,group2'), - ('selection_map', 'cbfnhgmap1')]) - self.cbf_nhg_ps.set('cbfgroup1', fvs) - - # Check if the group makes it to ASIC DB - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count + 3) - nhgid = self.get_nhg_id('cbfgroup1') - assert(nhgid != None) - fvs = self.asic_db.get_entry(self.ASIC_NHG_STR, nhgid) - assert(fvs['SAI_NEXT_HOP_GROUP_ATTR_TYPE'] == 'SAI_NEXT_HOP_GROUP_TYPE_CLASS_BASED') - - # Check if the next hop group members get created - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count + 7) - nhgm_ids = self.get_nhgm_ids('cbfgroup1') - assert(len(nhgm_ids) == 2) - nhg_ids = dict(zip([self.get_nhg_id(x) for x in ['group1', 'group2']], ['0', '1'])) - for nhgm_id in nhgm_ids: - fvs = self.asic_db.get_entry(self.ASIC_NHGM_STR, nhgm_id) - nh_id = fvs['SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID'] - assert(fvs['SAI_NEXT_HOP_GROUP_MEMBER_ATTR_INDEX'] == nhg_ids[nh_id]) - nhg_ids.pop(nh_id) - - # Delete the CBF next hop group - self.cbf_nhg_ps._del('cbfgroup1') - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count + 2) - - # Test scenario: - # - try creating invalid NHG maps and assert they're not being created - def data_validation_test(): - # Test the data validation - fv_values = [ - ('', 'cbfnhgmap1'), # empty members - ('group1,group2', ''), # non-existent selection map - ('group1,group1', 'cbfnhgmap1'), # non-unique members - ] - - for members, selection_map in fv_values: - fvs = swsscommon.FieldValuePairs([('members', members), - ('selection_map', selection_map)]) - self.cbf_nhg_ps.set('cbfgroup1', fvs) - time.sleep(1) - assert(len(self.asic_db.get_keys(self.ASIC_NHG_STR)) == self.asic_nhgs_count + 2) - - # Test scenario: - # - create a CBF NHG - # - try deleting one of its members and assert it fails as it is being referenced - # - update the group replacing the to-be-deleted member with another NHG and assert it is deleted - # - update the CBF NHG reordering the members and assert the new details match - def update_cbf_nhg_members_test(): - # Create a NHG with a single next hop - fvs = swsscommon.FieldValuePairs([('nexthop', '10.0.0.1'), ('ifname', 'Ethernet0')]) - self.nhg_ps.set("_group3", fvs) - fvs = swsscommon.FieldValuePairs([('nexthop_group','_group3')]) - self.nhg_ps.set("group3", fvs) - - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count + 3) - - # Create a CBF NHG - fvs = swsscommon.FieldValuePairs([('members', 'group1,group3'), - ('selection_map', 'cbfnhgmap1')]) - self.cbf_nhg_ps.set('cbfgroup1', fvs) - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count + 4) - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count + 8) - - # Remove group1 while being referenced - should not work - self.nhg_ps._del('group1') - time.sleep(1) - assert(self.nhg_exists('group1')) - - # Update the CBF NHG replacing group1 with group2 - nhgm_ids = self.get_nhgm_ids('cbfgroup1') - fvs = swsscommon.FieldValuePairs([('members', 'group2,group3'), - ('selection_map', 'cbfnhgmap1')]) - self.cbf_nhg_ps.set('cbfgroup1', fvs) - self.asic_db.wait_for_deleted_keys(self.ASIC_NHGM_STR, nhgm_ids) - # group1 should be deleted and the updated members added - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count + 3) - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count + 5) - - # Update the CBF NHG changing the order of the members - nhgm_ids = self.get_nhgm_ids('cbfgroup1') - fvs = swsscommon.FieldValuePairs([('members', 'group3,group2'), - ('selection_map', 'cbfnhgmap1')]) - self.cbf_nhg_ps.set('cbfgroup1', fvs) - self.asic_db.wait_for_deleted_keys(self.ASIC_NHGM_STR, nhgm_ids) - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count + 5) - assert(len(self.asic_db.get_keys(self.ASIC_NHG_STR)) == self.asic_nhgs_count + 3) - - indexes = { - self.get_nhg_id('group3'): '0', - self.get_nhg_id('group2'): '1' - } - nhgm_ids = self.get_nhgm_ids('cbfgroup1') - for nhgm_id in nhgm_ids: - fvs = self.asic_db.get_entry(self.ASIC_NHGM_STR, nhgm_id) - nh_id = fvs['SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID'] - assert(fvs['SAI_NEXT_HOP_GROUP_MEMBER_ATTR_INDEX'] == indexes[nh_id]) - indexes.pop(nh_id) - - # Test scenario: - # - update the selection map of the CBF NHG and assert it changes in ASIC DB - def update_cbf_nhg_map_test(): - # Create an FC to NH index selection map - fvs = swsscommon.FieldValuePairs([('0', '1'), ('1', '0')]) - self.fc_to_nhg_ps.set('cbfnhgmap2', fvs) - self.asic_db.wait_for_n_keys(self.ASIC_NHG_MAP_STR, self.asic_nhg_maps_count + 2) - - # Update the CBF NHG class map - nhg_id = self.get_nhg_id('cbfgroup1') - old_map = self.get_nhg_map_id('cbfnhgmap1') - fvs = swsscommon.FieldValuePairs([('members', 'group3,group2'), - ('selection_map', 'cbfnhgmap2')]) - self.cbf_nhg_ps.set('cbfgroup1', fvs) - self.asic_db.wait_for_field_negative_match(self.ASIC_NHG_STR, - nhg_id, - {'SAI_NEXT_HOP_GROUP_ATTR_SELECTION_MAP': old_map}) - assert(len(self.asic_db.get_keys(self.ASIC_NHG_STR)) == self.asic_nhgs_count + 3) - - # Test scenario: - # - create a route pointing to the CBF NHG - # - try deleting the CBF NHG and assert it fails as it is being referenced - # - delete the route and assert the CBF NHG also gets deleted - def delete_referenced_cbf_nhg_test(): - # Create a route pointing to the CBF NHG - fvs = swsscommon.FieldValuePairs([('nexthop_group', 'cbfgroup1')]) - self.lr_ps.set('10', fvs) - self.asic_db.wait_for_n_keys(self.ASIC_INSEG_STR, self.asic_insgs_count + 1) - - # Try deleting the CBF NHG - should not work - self.cbf_nhg_ps._del('cbfgroup1') - time.sleep(1) - assert(self.nhg_exists('cbfgroup1')) - - # Delete the label route - the CBF NHG should also get deleted - self.lr_ps._del('10') - self.asic_db.wait_for_n_keys(self.ASIC_INSEG_STR, self.asic_insgs_count) - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count + 2) - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count + 3) - - # Test scenario: - # - create a route pointing to a CBF NHG that doesn't exist and assert it isn't created - # - create the CBF NHG and assert the route also gets created - def create_route_inexistent_cbf_nhg_test(): - # Create a route pointing to a CBF NHG that does not yet exist - fvs = swsscommon.FieldValuePairs([('nexthop_group', 'cbfgroup1')]) - self.rt_ps.set('2.2.2.0/24', fvs) - time.sleep(1) - assert(not self.route_exists('2.2.2.0/24')) - - # Create the CBF NHG - fvs = swsscommon.FieldValuePairs([('members', 'group3,group2'), - ('selection_map', 'cbfnhgmap2')]) - self.cbf_nhg_ps.set('cbfgroup1', fvs) - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count + 3) - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count + 5) - self.asic_db.wait_for_n_keys(self.ASIC_RT_STR, self.asic_rts_count + 1) - - # Test scenario: - # - try deleting the CBF NHG and assert it fails as it is being referenced - # - update the CBF NHG - # - delete the route pointing to the CBF NHG and assert the CBF NHG doesn't get deleted - def update_deleting_cbf_nhg_test(): - # Try deleting the CBF group - self.cbf_nhg_ps._del('cbfgroup1') - time.sleep(1) - assert(self.nhg_exists('cbfgroup1')) - - # Update the CBF group - nhgm_ids = self.get_nhgm_ids('cbfgroup1') - fvs = swsscommon.FieldValuePairs([('members', 'group2,group3'), ('selection_map', 'cbfnhgmap1')]) - self.cbf_nhg_ps.set('cbfgroup1', fvs) - self.asic_db.wait_for_deleted_keys(self.ASIC_NHGM_STR, nhgm_ids) - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count + 5) - - # Delete the route - self.rt_ps._del('2.2.2.0/24') - self.asic_db.wait_for_n_keys(self.ASIC_RT_STR, self.asic_rts_count) - # The update should have overwritten the delete for CBF NHG - assert(self.nhg_exists('cbfgroup1')) - - # Test scenario: - # - try updating the CBF NHG with a member that doesn't exist and assert the CBF NHG's - # - create the missing NHG and assert the CBF NHG's member also gets created - def update_cbf_nhg_inexistent_member_test(): - # Create an FC to NH index selection map that references just 1 group member - fvs = swsscommon.FieldValuePairs([('0', '0')]) - self.fc_to_nhg_ps.set('cbfnhgmap4', fvs) - self.asic_db.wait_for_n_keys(self.ASIC_NHG_MAP_STR, self.asic_nhg_maps_count + 3) - - # Update the CBF NHG referencing an NHG that doesn't exist. In the end, create the NHG and - # make sure everything works fine. - fvs = swsscommon.FieldValuePairs([('members', 'group2'), ('selection_map', 'cbfnhgmap4')]) - self.cbf_nhg_ps.set('cbfgroup1', fvs) - time.sleep(1) - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count) - assert(len(self.asic_db.get_keys(self.ASIC_NHGM_STR)) == self.asic_nhgms_count) - fvs = swsscommon.FieldValuePairs([('nexthop', '10.0.0.1,10.0.0.3'), - ('ifname', 'Ethernet0,Ethernet4')]) - self.nhg_ps.set('group2', fvs) - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count + 2) - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count + 3) - - # Test scenario: - # - try updating the CBF NHG with a NHG map that doesn't exist and assert it does't change - # - create the missing NHG map and assert the selection map also gets updated - def update_cbf_nhg_inexistent_map_test(): - # Update the CBF NHG with an NHG map that doesn't exist, then update it with one that does exist. - nhg_id = self.get_nhg_id('cbfgroup1') - smap_id = self.asic_db.get_entry(self.ASIC_NHG_STR, nhg_id)['SAI_NEXT_HOP_GROUP_ATTR_SELECTION_MAP'] - fvs = swsscommon.FieldValuePairs([('members', 'group2'), ('selection_map', 'a')]) - self.cbf_nhg_ps.set('cbfgroup1', fvs) - time.sleep(1) - assert(self.asic_db.get_entry(self.ASIC_NHG_STR, nhg_id)['SAI_NEXT_HOP_GROUP_ATTR_SELECTION_MAP'] == smap_id) - fvs = swsscommon.FieldValuePairs([('members', 'group2'), ('selection_map', 'cbfnhgmap4')]) - self.cbf_nhg_ps.set('cbfgroup1', fvs) - - # Test scenario: - # - create a NHG that points to a map that refers to more members than the group has - def create_cbf_invalid_nhg_map_test(): - # Create an FC to NH index selection map that references 3 group members - fvs = swsscommon.FieldValuePairs([('0', '1'), ('1', '0'), ('2', '2')]) - self.fc_to_nhg_ps.set('cbfnhgmap3', fvs) - self.asic_db.wait_for_n_keys(self.ASIC_NHG_MAP_STR, self.asic_nhg_maps_count + 2) - - # Create a group that references this map. It doesn't get created. - fvs = swsscommon.FieldValuePairs([('members', 'group3,group2'), - ('selection_map', 'cbfnhgmap3')]) - self.cbf_nhg_ps.set('cbfgroup3', fvs) - time.sleep(1) - assert(not self.nhg_exists('cbfgroup3')) - - # Cleanup - self.cbf_nhg_ps._del('cbfgroup3') - - self.init_test(dvs, 4) - - mainline_cbf_nhg_test() - data_validation_test() - update_cbf_nhg_members_test() - update_cbf_nhg_map_test() - delete_referenced_cbf_nhg_test() - create_route_inexistent_cbf_nhg_test() - update_deleting_cbf_nhg_test() - create_cbf_invalid_nhg_map_test() - - # Delete the NHGs - self.cbf_nhg_ps._del('cbfgroup1') - self.nhg_ps._del('group2') - self.nhg_ps._del('group3') - self.nhg_ps._del('_group3') - - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count) - self.asic_db.wait_for_n_keys(self.ASIC_NHGM_STR, self.asic_nhgms_count) - - update_cbf_nhg_inexistent_member_test() - update_cbf_nhg_inexistent_map_test() - - # Coverage testing: Update the CBF NHG with a member that does not exist. - fvs = swsscommon.FieldValuePairs([('members', 'group3'), ('selection_map', 'cbfnhgmap2')]) - self.cbf_nhg_ps.set('cbfgroup1', fvs) - time.sleep(1) - - # Delete the NHGs - self.cbf_nhg_ps._del('cbfgroup1') - self.nhg_ps._del('group2') - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count) - - # Delete the NHG maps - self.fc_to_nhg_ps._del('cbfnhgmap1') - self.fc_to_nhg_ps._del('cbfnhgmap2') - self.fc_to_nhg_ps._del('cbfnhgmap3') - self.fc_to_nhg_ps._del('cbfnhgmap4') - self.asic_db.wait_for_n_keys(self.ASIC_NHG_MAP_STR, self.asic_nhg_maps_count) - - # Coverage testing: Delete inexistent CBF NHG - self.cbf_nhg_ps._del('cbfgroup1') - - def test_nhg_map(self, dvs, testlog): - - # Test scenario: - # - create a NHG map and assert the expected details - # - update the map - # - delete the map - def mainline_nhg_map_test(): - # Create two non-CBF NHGs - fvs = swsscommon.FieldValuePairs([('nexthop', '10.0.0.1,10.0.0.3,10.0.0.5'), - ("ifname", "Ethernet0,Ethernet4,Ethernet8")]) - self.nhg_ps.set("group1", fvs) - - fvs = swsscommon.FieldValuePairs([('nexthop', '10.0.0.1,10.0.0.3'), - ('ifname', 'Ethernet0,Ethernet4')]) - self.nhg_ps.set('group2', fvs) - - # Wait for the groups to appear in ASIC DB - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count + 2) - - # Create an FC to NH index map - fvs = swsscommon.FieldValuePairs([('0', '0')]) - self.fc_to_nhg_ps.set('cbfnhgmap1', fvs) - self.asic_db.wait_for_n_keys(self.ASIC_NHG_MAP_STR, self.asic_nhg_maps_count + 1) - - # Check the NHG map attributes - nhg_map_id = self.get_nhg_map_id('cbfnhgmap1') - assert nhg_map_id != None - - self.asic_db.wait_for_field_match(self.ASIC_NHG_MAP_STR, - nhg_map_id, - {'SAI_NEXT_HOP_GROUP_MAP_ATTR_TYPE': 'SAI_NEXT_HOP_GROUP_MAP_TYPE_FORWARDING_CLASS_TO_INDEX', - 'SAI_NEXT_HOP_GROUP_MAP_ATTR_MAP_TO_VALUE_LIST': '{\"count\":1,\"list\":[{\"key\":0,\"value\":0}]}'}) - - # Create a CBF next hop group - fvs = swsscommon.FieldValuePairs([('members', 'group1,group2'), - ('selection_map', 'cbfnhgmap1')]) - self.cbf_nhg_ps.set('cbfgroup1', fvs) - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count + 3) - - # Update the map. - fvs = swsscommon.FieldValuePairs([('0', '0'), ('1', '1')]) - self.fc_to_nhg_ps.set('cbfnhgmap1', fvs) - - self.asic_db.wait_for_field_match(self.ASIC_NHG_MAP_STR, - nhg_map_id, - {'SAI_NEXT_HOP_GROUP_MAP_ATTR_TYPE': 'SAI_NEXT_HOP_GROUP_MAP_TYPE_FORWARDING_CLASS_TO_INDEX', - 'SAI_NEXT_HOP_GROUP_MAP_ATTR_MAP_TO_VALUE_LIST': '{\"count\":2,\"list\":[{\"key\":1,\"value\":1},{\"key\":0,\"value\":0}]}'}) - - # Delete the group - self.cbf_nhg_ps._del('cbfgroup1') - self.nhg_ps._del("group1") - self.nhg_ps._del("group2") - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count) - - # Delete the map - self.fc_to_nhg_ps._del('cbfnhgmap1') - self.asic_db.wait_for_n_keys(self.ASIC_NHG_MAP_STR, self.asic_nhg_maps_count) - - # Test scenario: - # - try creating different NHG maps with invalid data and assert they don't get created - def data_validation_test(): - # Test validation errors - nhg_maps = [ - ('-1', '0'), # negative FC - ('63', '0'), # greater than max FC value - ('a', '0'), # non-integer FC - ('0', '-1'), # negative NH index - ('0', 'a'), # non-integer NH index - ] - - # Check that no such NHG map gets created - for nhg_map in nhg_maps: - fvs = swsscommon.FieldValuePairs([nhg_map]) - self.fc_to_nhg_ps.set('cbfnhgmap1', fvs) - time.sleep(1) - assert(not self.nhg_map_exists('cbfnhgmap1')) - - # Test scenario: - # - create two CBF NHG and a NHG map - # - try deleting the NHG map and assert it fails as it is being referenced - # - delete a CBF NHG and assert the NHG map is still not deleted as it's still being referenced - # - create a new NHG map and update the CBF NHG to point to it and assert the previous NHG map gets deleted - def delete_referenced_nhg_map_test(): - # Create two non-CBF NHGs - fvs = swsscommon.FieldValuePairs([('nexthop', '10.0.0.1,10.0.0.3,10.0.0.5'), - ("ifname", "Ethernet0,Ethernet4,Ethernet8")]) - self.nhg_ps.set("group1", fvs) - - fvs = swsscommon.FieldValuePairs([('nexthop', '10.0.0.1,10.0.0.3'), - ('ifname', 'Ethernet0,Ethernet4')]) - self.nhg_ps.set('group2', fvs) - - # Wait for the groups to appear in ASIC DB - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count + 2) - - # Create an FC to NH index map - fvs = swsscommon.FieldValuePairs([('0', '0')]) - self.fc_to_nhg_ps.set('cbfnhgmap1', fvs) - self.asic_db.wait_for_n_keys(self.ASIC_NHG_MAP_STR, self.asic_nhg_maps_count + 1) - - # Create a couple of CBF NHGs - for i in range(2): - fvs = swsscommon.FieldValuePairs([('members', 'group{}'.format(i + 1)), - ('selection_map', 'cbfnhgmap1')]) - self.cbf_nhg_ps.set('cbfgroup{}'.format(i), fvs) - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count + 4) - # Try deleting the NHG map. It should fail as it is referenced. - self.fc_to_nhg_ps._del('cbfnhgmap1') - time.sleep(1) - assert(self.nhg_map_exists('cbfnhgmap1')) - - # Delete a CBF NHG - self.cbf_nhg_ps._del('cbfgroup1') - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count + 3) - - # The NHG map is still referenced so shouldn't be deleted - assert(self.nhg_map_exists('cbfnhgmap1')) - - # Create a new FC to NH index map - fvs = swsscommon.FieldValuePairs([('0', '0')]) - self.fc_to_nhg_ps.set('cbfnhgmap2', fvs) - self.asic_db.wait_for_n_keys(self.ASIC_NHG_MAP_STR, self.asic_nhg_maps_count + 2) - - # Update the second CBF NHG to point to the new map - fvs = swsscommon.FieldValuePairs([('members', 'group1'), ('selection_map', 'cbfnhgmap2')]) - self.cbf_nhg_ps.set('cbfgroup0', fvs) - - # The NHG map is no longer referenced and should have been deleted - self.asic_db.wait_for_n_keys(self.ASIC_NHG_MAP_STR, self.asic_nhg_maps_count + 1) - - # Test scenario: - # - delete the NHG map and assert it fails as it's being referenced - # - update the NHG map and assert for the new details - # - delete the referencing CBF NHG and assert the NHG map isn't deleted as it was updated - # - delete the NHG map - def update_override_delete_test(): - # Delete the second NHG map. It fails as it is referenced. - self.fc_to_nhg_ps._del('cbfnhgmap2') - time.sleep(1) - assert(self.nhg_map_exists('cbfnhgmap2')) - - # Update the NHG map - nhg_map_id = self.get_nhg_map_id('cbfnhgmap2') - fvs = swsscommon.FieldValuePairs([('1', '0'), ('2', '0')]) - self.fc_to_nhg_ps.set('cbfnhgmap2', fvs) - self.asic_db.wait_for_field_match(self.ASIC_NHG_MAP_STR, - nhg_map_id, - {'SAI_NEXT_HOP_GROUP_MAP_ATTR_TYPE': 'SAI_NEXT_HOP_GROUP_MAP_TYPE_FORWARDING_CLASS_TO_INDEX', - 'SAI_NEXT_HOP_GROUP_MAP_ATTR_MAP_TO_VALUE_LIST': '{\"count\":2,\"list\":[{\"key\":2,\"value\":0},{\"key\":1,\"value\":0}]}'}) - - # Delete the second CBF NHG - self.cbf_nhg_ps._del('cbfgroup0') - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count + 2) - - # The NHG map should not be deleted as it was updated - time.sleep(1) - assert(self.nhg_map_exists('cbfnhgmap2')) - - # Delete the NHG map - self.fc_to_nhg_ps._del('cbfnhgmap2') - self.asic_db.wait_for_n_keys(self.ASIC_NHG_MAP_STR, self.asic_nhg_maps_count) - - # Test scenario: - # - fill the ASIC with NHG maps - # - try creating a new NHG map and assert it fails as the ASIC is full - # - delete a NHG map and assert the to-be-created one is actually created - def nhg_map_exhaust_test(): - # Create the maximum number of NHG maps allowed by the VS switch (512) - fvs = swsscommon.FieldValuePairs([('0', '0')]) - for i in range(512 - self.asic_nhg_maps_count): - nhg_maps.append('cbfnhgmap{}'.format(i)) - self.fc_to_nhg_ps.set('cbfnhgmap{}'.format(i), fvs) - self.asic_db.wait_for_n_keys(self.ASIC_NHG_MAP_STR, self.MAX_NHG_MAP_COUNT) - - # Try creating a new NHG map. It should fail as there is no more space. - nhg_maps.append('cbfnhgmap512') - self.fc_to_nhg_ps.set('cbfnhgmap512', fvs) - time.sleep(1) - assert(not self.nhg_map_exists('cbfnhgmap512')) - time.sleep(1) - - # Delete an existing NHG map. The pending NHG map should now be created - del_nhg_map_index = nhg_maps.pop(0) - del_nhg_map_id = self.get_nhg_map_id(del_nhg_map_index) - self.fc_to_nhg_ps._del(del_nhg_map_index) - self.asic_db.wait_for_deleted_entry(self.ASIC_NHG_MAP_STR, del_nhg_map_id) - self.asic_db.wait_for_n_keys(self.ASIC_NHG_MAP_STR, self.MAX_NHG_MAP_COUNT) - assert(self.nhg_map_exists('cbfnhgmap512')) - - # Test scenario: - # - create a NHG map while the ASIC is full - # - create a CBF NHG pointing to this NHG map and assert it isn't created - # - delete a NHG map and assert the new NHG map and the CBF NHG map is created - # - delete the CBF NHG - def create_cbf_nhg_inexistent_map_test(): - # Create a new NHG map. It should remain pending. - nhg_maps.append('cbfnhgmap513') - fvs = swsscommon.FieldValuePairs([('0', '0')]) - self.fc_to_nhg_ps.set('cbfnhgmap513', fvs) - - # Create a CBF NHG which should reference this NHG map. It should fail creating it. - fvs = swsscommon.FieldValuePairs([('members', 'group1'), ('selection_map', 'cbfnhgmap513')]) - self.cbf_nhg_ps.set('testcbfnhg', fvs) - time.sleep(1) - assert(not self.nhg_exists('testcbfnhg')) - - # Delete an existing NHG map. The new map and the CBF NHG should be created. - self.fc_to_nhg_ps._del(nhg_maps.pop(0)) - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count + 3) - self.asic_db.wait_for_n_keys(self.ASIC_NHG_MAP_STR, self.MAX_NHG_MAP_COUNT) - - self.cbf_nhg_ps._del('testcbfnhg') - - self.init_test(dvs, 4) - nhg_maps = [] - - mainline_nhg_map_test() - data_validation_test() - delete_referenced_nhg_map_test() - update_override_delete_test() - nhg_map_exhaust_test() - create_cbf_nhg_inexistent_map_test() - - # Cleanup - - # Delete the NHGs - for i in range(2): - self.nhg_ps._del('group{}'.format(i + 1)) - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count) - - # Delete all the NHG maps - while len(nhg_maps) > 0: - self.fc_to_nhg_ps._del(nhg_maps.pop()) - self.asic_db.wait_for_n_keys(self.ASIC_NHG_MAP_STR, self.asic_nhg_maps_count) - - # Test scenario: - # - Create a CBF NHG that has a member which is not yet synced. It shouldn't be synced. - # - Add the missing member and assert the CBF NHG is now synced. - def test_cbf_sync_before_member(self, dvs, testlog): - self.init_test(dvs, 2) - - # Create an FC to NH index selection map - nhg_map = [(str(i), '0' if i < 4 else '1') for i in range(8)] - fvs = swsscommon.FieldValuePairs(nhg_map) - self.fc_to_nhg_ps.set('cbfnhgmap1', fvs) - self.asic_db.wait_for_n_keys(self.ASIC_NHG_MAP_STR, self.asic_nhg_maps_count + 1) - - # Create a non-CBF NHG - fvs = swsscommon.FieldValuePairs([('nexthop', '10.0.0.1,10.0.0.3'), - ('ifname', 'Ethernet0,Ethernet4')]) - self.nhg_ps.set('group1', fvs) - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count + 1) - - # Create a CBF NHG with a member that doesn't currently exist. Nothing should happen - fvs = swsscommon.FieldValuePairs([('members', 'group1,group2'), - ('selection_map', 'cbfnhgmap1')]) - self.cbf_nhg_ps.set('cbfgroup1', fvs) - time.sleep(1) - assert(len(self.asic_db.get_keys(self.ASIC_NHG_STR)) == self.asic_nhgs_count + 1) - - # Create the missing non-CBF NHG. This and the CBF NHG should be created. - fvs = swsscommon.FieldValuePairs([('nexthop', '10.0.0.1,10.0.0.3'), - ("ifname", "Ethernet0,Ethernet4")]) - self.nhg_ps.set("group2", fvs) - self.asic_db.wait_for_n_keys(self.ASIC_NHG_STR, self.asic_nhgs_count + 3) - - # Cleanup - self.nhg_ps._del('cbfgroup1') - self.nhg_ps._del('group1') - self.nhg_ps._del('group2') - self.nhg_ps._del('cbfnhgmap1') - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_nvgre_tunnel.py b/tests/test_nvgre_tunnel.py deleted file mode 100644 index 90fe560141..0000000000 --- a/tests/test_nvgre_tunnel.py +++ /dev/null @@ -1,381 +0,0 @@ -import time -import json -import random -import time -import pytest - - -from swsscommon import swsscommon -from pprint import pprint - - -NVGRE_TUNNEL = 'NVGRE_TUNNEL' -NVGRE_TUNNEL_MAP = 'NVGRE_TUNNEL_MAP' - - -SAI_OBJECT_TYPE_TUNNEL = 'ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL' -SAI_OBJECT_TYPE_TUNNEL_MAP = 'ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL_MAP' -SAI_OBJECT_TYPE_TUNNEL_MAP_ENTRY = 'ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL_MAP_ENTRY' - - -def create_entry(tbl, key, pairs): - fvs = swsscommon.FieldValuePairs(pairs) - tbl.set(key, fvs) - time.sleep(1) - - -def create_entry_tbl(db, table, separator, key, pairs): - tbl = swsscommon.Table(db, table) - create_entry(tbl, key, pairs) - - -def delete_entry_tbl(db, table, key): - tbl = swsscommon.Table(db, table) - tbl._del(key) - time.sleep(1) - - -def get_all_created_entries(db, table, existed_entries): - tbl = swsscommon.Table(db, table) - entries = set(tbl.getKeys()) - new_entries = list(entries - existed_entries) - assert len(new_entries) >= 0, "DB entries was't created" - new_entries.sort() - return new_entries - - -def get_created_entries(db, table, existed_entries, count): - new_entries = get_all_created_entries(db, table, existed_entries) - assert len(new_entries) == count, "Wrong number of created entries." - return new_entries - - -def get_exist_entries(dvs, table): - db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - tbl = swsscommon.Table(db, table) - return set(tbl.getKeys()) - - -def get_created_entry(db, table, existed_entries): - tbl = swsscommon.Table(db, table) - entries = set(tbl.getKeys()) - new_entries = list(entries - existed_entries) - assert len(new_entries) == 1, "Wrong number of created entries." - return new_entries[0] - - -def how_many_entries_exist(db, table): - tbl = swsscommon.Table(db, table) - return len(tbl.getKeys()) - - -def get_lo(dvs): - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - - tbl = swsscommon.Table(asic_db, 'ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE') - - entries = tbl.getKeys() - lo_id = None - for entry in entries: - status, fvs = tbl.get(entry) - assert status, "Got an error when get a key" - for key, value in fvs: - if key == 'SAI_ROUTER_INTERFACE_ATTR_TYPE' and value == 'SAI_ROUTER_INTERFACE_TYPE_LOOPBACK': - lo_id = entry - break - else: - assert False, 'Don\'t found loopback id' - - return lo_id - - -def check_object(db, table, key, expected_attributes): - tbl = swsscommon.Table(db, table) - keys = tbl.getKeys() - assert key in keys, "The desired key is not presented" - - status, fvs = tbl.get(key) - assert status, "Got an error when get a key" - - assert len(fvs) == len(expected_attributes), "Unexpected number of attributes" - - attr_keys = {entry[0] for entry in fvs} - - for name, value in fvs: - assert expected_attributes[name] == value, "Wrong value %s for the attribute %s = %s" % \ - (value, name, expected_attributes[name]) - - -loopback_id = 0 - - -class NvgreTunnel(object): - tunnel_ids = set() - tunnel_map_ids = set() - tunnel_map_entry_ids = set() - tunnel_map_map = {} - tunnel = {} - - - def fetch_exist_entries(self, dvs): - self.tunnel_ids = get_exist_entries(dvs, SAI_OBJECT_TYPE_TUNNEL) - self.tunnel_map_ids = get_exist_entries(dvs, SAI_OBJECT_TYPE_TUNNEL_MAP) - self.tunnel_map_entry_ids = get_exist_entries(dvs, SAI_OBJECT_TYPE_TUNNEL_MAP_ENTRY) - - global loopback_id - if not loopback_id: - loopback_id = get_lo(dvs) - - - def create_nvgre_tunnel(self, dvs, tunnel_name, src_ip): - conf_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - - create_entry_tbl(conf_db, NVGRE_TUNNEL, '|', tunnel_name, [ ('src_ip', src_ip) ]) - time.sleep(1) - - - def check_nvgre_tunnel(self, dvs, tunnel_name, src_ip): - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - global loopback_id - - tunnel_id = get_created_entry(asic_db, SAI_OBJECT_TYPE_TUNNEL, self.tunnel_ids) - tunnel_map_ids = get_created_entries(asic_db, SAI_OBJECT_TYPE_TUNNEL_MAP, self.tunnel_map_ids, 4) - - assert how_many_entries_exist(asic_db, SAI_OBJECT_TYPE_TUNNEL_MAP) == (len(self.tunnel_map_ids) + 4), "The TUNNEL_MAP wasn't created" - assert how_many_entries_exist(asic_db, SAI_OBJECT_TYPE_TUNNEL_MAP_ENTRY) == len(self.tunnel_map_entry_ids), "The TUNNEL_MAP_ENTRY is created too early" - assert how_many_entries_exist(asic_db, SAI_OBJECT_TYPE_TUNNEL) == (len(self.tunnel_ids) + 1), "The TUNNEL wasn't created" - - check_object(asic_db, SAI_OBJECT_TYPE_TUNNEL_MAP, tunnel_map_ids[0], { 'SAI_TUNNEL_MAP_ATTR_TYPE': 'SAI_TUNNEL_MAP_TYPE_VLAN_ID_TO_VSID' }) - check_object(asic_db, SAI_OBJECT_TYPE_TUNNEL_MAP, tunnel_map_ids[1], { 'SAI_TUNNEL_MAP_ATTR_TYPE': 'SAI_TUNNEL_MAP_TYPE_BRIDGE_IF_TO_VSID' }) - check_object(asic_db, SAI_OBJECT_TYPE_TUNNEL_MAP, tunnel_map_ids[2], { 'SAI_TUNNEL_MAP_ATTR_TYPE': 'SAI_TUNNEL_MAP_TYPE_VSID_TO_VLAN_ID' }) - check_object(asic_db, SAI_OBJECT_TYPE_TUNNEL_MAP, tunnel_map_ids[3], { 'SAI_TUNNEL_MAP_ATTR_TYPE': 'SAI_TUNNEL_MAP_TYPE_VSID_TO_BRIDGE_IF' }) - - check_object(asic_db, SAI_OBJECT_TYPE_TUNNEL, tunnel_id, - { - 'SAI_TUNNEL_ATTR_TYPE': 'SAI_TUNNEL_TYPE_NVGRE', - 'SAI_TUNNEL_ATTR_UNDERLAY_INTERFACE': loopback_id, - 'SAI_TUNNEL_ATTR_DECAP_MAPPERS': f'2:{tunnel_map_ids[2]},{tunnel_map_ids[3]}', - 'SAI_TUNNEL_ATTR_ENCAP_MAPPERS': f'2:{tunnel_map_ids[0]},{tunnel_map_ids[1]}', - 'SAI_TUNNEL_ATTR_ENCAP_SRC_IP': src_ip - } - ) - - self.tunnel_map_ids.update(tunnel_map_ids) - self.tunnel_ids.add(tunnel_id) - self.tunnel_map_map[tunnel_name] = tunnel_map_ids - self.tunnel[tunnel_name] = tunnel_id - - - def check_invalid_nvgre_tunnel(self, dvs): - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - - assert how_many_entries_exist(asic_db, SAI_OBJECT_TYPE_TUNNEL) == len(self.tunnel_ids), "Invalid TUNNEL was created" - assert how_many_entries_exist(asic_db, SAI_OBJECT_TYPE_TUNNEL_MAP) == len(self.tunnel_map_ids), "Invalid TUNNEL_MAP was created" - - - def remove_nvgre_tunnel(self, dvs, tunnel_name): - conf_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - - delete_entry_tbl(conf_db, NVGRE_TUNNEL, tunnel_name) - time.sleep(1) - - - def check_remove_nvgre_tunnel(self, dvs, tunnel_name): - self.fetch_exist_entries(dvs) - self.tunnel.pop(tunnel_name, None) - self.tunnel_map_map.pop(tunnel_name, None) - - - def create_nvgre_tunnel_map_entry(self, dvs, tunnel_name, tunnel_map_entry_name, vlan_id, vsid): - conf_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - - create_entry_tbl( - conf_db, - NVGRE_TUNNEL_MAP, '|', f'{tunnel_name}|{tunnel_map_entry_name}', - [ - ('vsid', vsid), - ('vlan_id', f'Vlan{vlan_id}'), - ], - ) - time.sleep(1) - - - def check_nvgre_tunnel_map_entry(self, dvs, tunnel_name, vlan_id, vsid): - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - - if (self.tunnel_map_map.get(tunnel_name) is None): - tunnel_map_ids = get_created_entries(asic_db, SAI_OBJECT_TYPE_TUNNEL_MAP, self.tunnel_map_ids, 4) - else: - tunnel_map_ids = self.tunnel_map_map[tunnel_name] - - tunnel_map_entry_id = get_created_entries(asic_db, SAI_OBJECT_TYPE_TUNNEL_MAP_ENTRY, self.tunnel_map_entry_ids, 1) - - assert how_many_entries_exist(asic_db, SAI_OBJECT_TYPE_TUNNEL_MAP_ENTRY) == (len(self.tunnel_map_entry_ids) + 1), "The TUNNEL_MAP_ENTRY is created too early" - - check_object(asic_db, SAI_OBJECT_TYPE_TUNNEL_MAP_ENTRY, tunnel_map_entry_id[0], - { - 'SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE': 'SAI_TUNNEL_MAP_TYPE_VSID_TO_VLAN_ID', - 'SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP': tunnel_map_ids[2], - 'SAI_TUNNEL_MAP_ENTRY_ATTR_VSID_ID_KEY': vsid, - 'SAI_TUNNEL_MAP_ENTRY_ATTR_VLAN_ID_VALUE': vlan_id, - } - ) - - self.tunnel_map_entry_ids.update(tunnel_map_entry_id) - - - def check_invalid_nvgre_tunnel_map_entry(self, dvs): - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - - assert how_many_entries_exist(asic_db, SAI_OBJECT_TYPE_TUNNEL_MAP_ENTRY) == len(self.tunnel_map_entry_ids), "Invalid TUNNEL_MAP_ENTRY was created" - - - def remove_nvgre_tunnel_map_entry(self, dvs, tunnel_name, tunnel_map_entry_name): - conf_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - - delete_entry_tbl(conf_db, NVGRE_TUNNEL_MAP, f'{tunnel_name}|{tunnel_map_entry_name}') - time.sleep(1) - - - def check_remove_nvgre_tunnel_map_entry(self, dvs): - self.fetch_exist_entries(dvs) - - -@pytest.mark.usefixtures('dvs_vlan_manager') -class TestNvgreTunnel(object): - - def get_nvgre_tunnel_obj(self): - return NvgreTunnel() - - - def test_nvgre_create_tunnel_map_entry(self, dvs, testlog): - try: - tunnel_name = 'tunnel_1' - tunnel_map_entry_name = 'entry_1' - src_ip = '10.0.0.1' - vlan_id = '500' - vsid = '850' - - nvgre_obj = self.get_nvgre_tunnel_obj() - nvgre_obj.fetch_exist_entries(dvs) - - self.dvs_vlan.create_vlan(vlan_id) - - nvgre_obj.create_nvgre_tunnel(dvs, tunnel_name, src_ip) - nvgre_obj.check_nvgre_tunnel(dvs, tunnel_name, src_ip) - - nvgre_obj.create_nvgre_tunnel_map_entry(dvs, tunnel_name, tunnel_map_entry_name, vlan_id, vsid) - nvgre_obj.check_nvgre_tunnel_map_entry(dvs, tunnel_name, vlan_id, vsid) - finally: - nvgre_obj.remove_nvgre_tunnel_map_entry(dvs, tunnel_name, tunnel_map_entry_name) - nvgre_obj.check_remove_nvgre_tunnel_map_entry(dvs) - - nvgre_obj.remove_nvgre_tunnel(dvs, tunnel_name) - nvgre_obj.check_remove_nvgre_tunnel(dvs, tunnel_name) - - self.dvs_vlan.remove_vlan(vlan_id) - - - def test_multiple_nvgre_tunnels_entries(self, dvs, testlog): - try: - tunnel_name_1 = 'tunnel_1' - tunnel_name_2 = 'tunnel_2' - tunnel_name_3 = 'tunnel_3' - entry_1 = 'entry_1' - entry_2 = 'entry_2' - entry_3 = 'entry_3' - entry_4 = 'entry_4' - - nvgre_obj = self.get_nvgre_tunnel_obj() - nvgre_obj.fetch_exist_entries(dvs) - - self.dvs_vlan.create_vlan('501') - self.dvs_vlan.create_vlan('502') - self.dvs_vlan.create_vlan('503') - self.dvs_vlan.create_vlan('504') - - nvgre_obj.create_nvgre_tunnel(dvs, tunnel_name_1, '10.0.0.1') - nvgre_obj.check_nvgre_tunnel(dvs, tunnel_name_1, '10.0.0.1') - - nvgre_obj.create_nvgre_tunnel_map_entry(dvs, tunnel_name_1, entry_1, '501', '801') - nvgre_obj.check_nvgre_tunnel_map_entry(dvs, tunnel_name_1, '501', '801') - - nvgre_obj.create_nvgre_tunnel(dvs, tunnel_name_2, '10.0.0.2') - nvgre_obj.check_nvgre_tunnel(dvs, tunnel_name_2, '10.0.0.2') - - nvgre_obj.create_nvgre_tunnel_map_entry(dvs, tunnel_name_2, entry_2, '502', '802') - nvgre_obj.check_nvgre_tunnel_map_entry(dvs, tunnel_name_2, '502', '802') - - nvgre_obj.create_nvgre_tunnel(dvs, tunnel_name_3, '10.0.0.3') - nvgre_obj.check_nvgre_tunnel(dvs, tunnel_name_3, '10.0.0.3') - - nvgre_obj.create_nvgre_tunnel_map_entry(dvs, tunnel_name_3, entry_3, '503', '803') - nvgre_obj.check_nvgre_tunnel_map_entry(dvs, tunnel_name_3, '503', '803') - - nvgre_obj.create_nvgre_tunnel_map_entry(dvs, tunnel_name_3, entry_4, '504', '804') - nvgre_obj.check_nvgre_tunnel_map_entry(dvs, tunnel_name_3, '504', '804') - finally: - nvgre_obj.remove_nvgre_tunnel_map_entry(dvs, tunnel_name_1, entry_1) - nvgre_obj.check_remove_nvgre_tunnel_map_entry(dvs) - - nvgre_obj.remove_nvgre_tunnel(dvs, tunnel_name_1) - nvgre_obj.check_remove_nvgre_tunnel(dvs, tunnel_name_1) - - nvgre_obj.remove_nvgre_tunnel_map_entry(dvs, tunnel_name_2, entry_2) - nvgre_obj.check_remove_nvgre_tunnel_map_entry(dvs) - - nvgre_obj.remove_nvgre_tunnel(dvs, tunnel_name_2) - nvgre_obj.check_remove_nvgre_tunnel(dvs, tunnel_name_2) - - nvgre_obj.remove_nvgre_tunnel_map_entry(dvs, tunnel_name_3, entry_3) - nvgre_obj.check_remove_nvgre_tunnel_map_entry(dvs) - - nvgre_obj.remove_nvgre_tunnel_map_entry(dvs, tunnel_name_3, entry_4) - nvgre_obj.check_remove_nvgre_tunnel_map_entry(dvs) - - nvgre_obj.remove_nvgre_tunnel(dvs, tunnel_name_3) - nvgre_obj.check_remove_nvgre_tunnel(dvs, tunnel_name_3) - - self.dvs_vlan.remove_vlan('501') - self.dvs_vlan.remove_vlan('502') - self.dvs_vlan.remove_vlan('503') - self.dvs_vlan.remove_vlan('504') - - - def test_invalid_nvgre_tunnel(self, dvs, testlog): - nvgre_obj = self.get_nvgre_tunnel_obj() - nvgre_obj.fetch_exist_entries(dvs) - - nvgre_obj.create_nvgre_tunnel(dvs, 'tunnel_1', '1111.1111.1111.1111') - nvgre_obj.check_invalid_nvgre_tunnel(dvs) - - - def test_invalid_nvgre_tunnel_map_entry(self, dvs, testlog): - try: - tunnel_name = 'tunnel_1' - tunnel_map_entry_name = 'entry_1' - src_ip = '10.0.0.1' - vlan_id = '500' - vsid = 'INVALID' - - nvgre_obj = self.get_nvgre_tunnel_obj() - nvgre_obj.fetch_exist_entries(dvs) - - self.dvs_vlan.create_vlan(vlan_id) - - nvgre_obj.create_nvgre_tunnel(dvs, tunnel_name, src_ip) - nvgre_obj.check_nvgre_tunnel(dvs, tunnel_name, src_ip) - - nvgre_obj.create_nvgre_tunnel_map_entry(dvs, tunnel_name, tunnel_map_entry_name, vlan_id, vsid) - nvgre_obj.check_invalid_nvgre_tunnel_map_entry(dvs) - finally: - nvgre_obj.remove_nvgre_tunnel(dvs, tunnel_name) - nvgre_obj.check_remove_nvgre_tunnel(dvs, tunnel_name) - - self.dvs_vlan.remove_vlan(vlan_id) - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_pbh.py b/tests/test_pbh.py deleted file mode 100644 index 65401a3ea9..0000000000 --- a/tests/test_pbh.py +++ /dev/null @@ -1,1023 +0,0 @@ -import pytest -import logging - -import test_flex_counters as flex_counter_module - - -PBH_HASH_FIELD_NAME = "inner_ip_proto" -PBH_HASH_FIELD_HASH_FIELD = "INNER_IP_PROTOCOL" -PBH_HASH_FIELD_SEQUENCE_ID = "1" - -PBH_HASH_NAME = "inner_v4_hash" -PBH_HASH_HASH_FIELD_LIST = ["inner_ip_proto"] - -PBH_RULE_NAME = "nvgre" -PBH_RULE_PRIORITY = "1" -PBH_RULE_ETHER_TYPE = "0x0800" -PBH_RULE_IP_PROTOCOL = "0x2f" -PBH_RULE_GRE_KEY = "0x2500/0xffffff00" -PBH_RULE_INNER_ETHER_TYPE = "0x86dd" -PBH_RULE_HASH = "inner_v4_hash" - -PBH_TABLE_NAME = "pbh_table" -PBH_TABLE_INTERFACE_LIST = ["Ethernet0", "Ethernet4"] -PBH_TABLE_DESCRIPTION = "NVGRE and VxLAN" - - -logging.basicConfig(level=logging.INFO) -pbhlogger = logging.getLogger(__name__) - - -@pytest.fixture(autouse=True, scope="class") -def dvs_api(request, dvs_pbh, dvs_acl): - # Fixtures are created when first requested by a test, and are destroyed based on their scope - if request.cls is None: - yield - return - pbhlogger.info("Initialize DVS API: PBH, ACL") - request.cls.dvs_pbh = dvs_pbh - request.cls.dvs_acl = dvs_acl - yield - pbhlogger.info("Deinitialize DVS API: PBH, ACL") - del request.cls.dvs_pbh - del request.cls.dvs_acl - - -@pytest.mark.usefixtures("dvs_lag_manager") -class TestPbhInterfaceBinding: - def test_PbhTablePortBinding(self, testlog): - try: - port_list = ["Ethernet0", "Ethernet4"] - - pbhlogger.info("Create PBH table: {}".format(PBH_TABLE_NAME)) - self.dvs_pbh.create_pbh_table( - table_name=PBH_TABLE_NAME, - interface_list=port_list, - description=PBH_TABLE_DESCRIPTION - ) - self.dvs_acl.verify_acl_table_count(1) - - pbhlogger.info("Validate PBH table port binding: {}".format(",".join(port_list))) - acl_table_id = self.dvs_acl.get_acl_table_ids(1)[0] - acl_table_group_ids = self.dvs_acl.get_acl_table_group_ids(len(port_list)) - - self.dvs_acl.verify_acl_table_group_members(acl_table_id, acl_table_group_ids, 1) - self.dvs_acl.verify_acl_table_port_binding(acl_table_id, port_list, 1) - finally: - pbhlogger.info("Remove PBH table: {}".format(PBH_TABLE_NAME)) - self.dvs_pbh.remove_pbh_table(PBH_TABLE_NAME) - self.dvs_acl.verify_acl_table_count(0) - - def test_PbhTablePortChannelBinding(self, testlog): - try: - # PortChannel0001 - pbhlogger.info("Create LAG: PortChannel0001") - self.dvs_lag.create_port_channel("0001") - self.dvs_lag.get_and_verify_port_channel(1) - - pbhlogger.info("Create LAG member: Ethernet120") - self.dvs_lag.create_port_channel_member("0001", "Ethernet120") - self.dvs_lag.get_and_verify_port_channel_members(1) - - # PortChannel0002 - pbhlogger.info("Create LAG: PortChannel0002") - self.dvs_lag.create_port_channel("0002") - self.dvs_lag.get_and_verify_port_channel(2) - - pbhlogger.info("Create LAG member: Ethernet124") - self.dvs_lag.create_port_channel_member("0002", "Ethernet124") - self.dvs_lag.get_and_verify_port_channel_members(2) - - # PBH table - portchannel_list = ["PortChannel0001", "PortChannel0002"] - - pbhlogger.info("Create PBH table: {}".format(PBH_TABLE_NAME)) - self.dvs_pbh.create_pbh_table( - table_name=PBH_TABLE_NAME, - interface_list=portchannel_list, - description=PBH_TABLE_DESCRIPTION - ) - self.dvs_acl.verify_acl_table_count(1) - - pbhlogger.info("Validate PBH table LAG binding: {}".format(",".join(portchannel_list))) - acl_table_id = self.dvs_acl.get_acl_table_ids(1)[0] - acl_table_group_ids = self.dvs_acl.get_acl_table_group_ids(len(portchannel_list)) - - self.dvs_acl.verify_acl_table_group_members(acl_table_id, acl_table_group_ids, 1) - self.dvs_acl.verify_acl_table_portchannel_binding(acl_table_id, portchannel_list, 1) - finally: - # PBH table - pbhlogger.info("Remove PBH table: {}".format(PBH_TABLE_NAME)) - self.dvs_pbh.remove_pbh_table(PBH_TABLE_NAME) - self.dvs_acl.verify_acl_table_count(0) - - # PortChannel0001 - pbhlogger.info("Remove LAG member: Ethernet120") - self.dvs_lag.remove_port_channel_member("0001", "Ethernet120") - self.dvs_lag.get_and_verify_port_channel_members(1) - - pbhlogger.info("Remove LAG: PortChannel0001") - self.dvs_lag.remove_port_channel("0001") - self.dvs_lag.get_and_verify_port_channel(1) - - # PortChannel0002 - pbhlogger.info("Remove LAG member: Ethernet124") - self.dvs_lag.remove_port_channel_member("0002", "Ethernet124") - self.dvs_lag.get_and_verify_port_channel_members(0) - - pbhlogger.info("Remove LAG: PortChannel0002") - self.dvs_lag.remove_port_channel("0002") - self.dvs_lag.get_and_verify_port_channel(0) - - -@pytest.mark.usefixtures("dvs_hash_manager") -class TestPbhBasicFlows: - def test_PbhHashFieldCreationDeletion(self, testlog): - try: - pbhlogger.info("Create PBH hash field: {}".format(PBH_HASH_FIELD_NAME)) - self.dvs_pbh.create_pbh_hash_field( - hash_field_name=PBH_HASH_FIELD_NAME, - hash_field=PBH_HASH_FIELD_HASH_FIELD, - sequence_id=PBH_HASH_FIELD_SEQUENCE_ID - ) - self.dvs_pbh.verify_pbh_hash_field_count(1) - finally: - pbhlogger.info("Remove PBH hash field: {}".format(PBH_HASH_FIELD_NAME)) - self.dvs_pbh.remove_pbh_hash_field(PBH_HASH_FIELD_NAME) - self.dvs_pbh.verify_pbh_hash_field_count(0) - - def test_PbhHashCreationDeletion(self, testlog): - try: - # PBH hash field - pbhlogger.info("Create PBH hash field: {}".format(PBH_HASH_FIELD_NAME)) - self.dvs_pbh.create_pbh_hash_field( - hash_field_name=PBH_HASH_FIELD_NAME, - hash_field=PBH_HASH_FIELD_HASH_FIELD, - sequence_id=PBH_HASH_FIELD_SEQUENCE_ID - ) - self.dvs_pbh.verify_pbh_hash_field_count(1) - - # PBH hash - pbhlogger.info("Create PBH hash: {}".format(PBH_HASH_NAME)) - self.dvs_pbh.create_pbh_hash( - hash_name=PBH_HASH_NAME, - hash_field_list=PBH_HASH_HASH_FIELD_LIST - ) - self.dvs_hash.verify_hash_count(1) - finally: - # PBH hash - pbhlogger.info("Remove PBH hash: {}".format(PBH_HASH_NAME)) - self.dvs_pbh.remove_pbh_hash(PBH_HASH_NAME) - self.dvs_hash.verify_hash_count(0) - - # PBH hash field - pbhlogger.info("Remove PBH hash field: {}".format(PBH_HASH_FIELD_NAME)) - self.dvs_pbh.remove_pbh_hash_field(PBH_HASH_FIELD_NAME) - self.dvs_pbh.verify_pbh_hash_field_count(0) - - def test_PbhTableCreationDeletion(self, testlog): - try: - pbhlogger.info("Create PBH table: {}".format(PBH_TABLE_NAME)) - self.dvs_pbh.create_pbh_table( - table_name=PBH_TABLE_NAME, - interface_list=PBH_TABLE_INTERFACE_LIST, - description=PBH_TABLE_DESCRIPTION - ) - self.dvs_acl.verify_acl_table_count(1) - finally: - pbhlogger.info("Remove PBH table: {}".format(PBH_TABLE_NAME)) - self.dvs_pbh.remove_pbh_table(PBH_TABLE_NAME) - self.dvs_acl.verify_acl_table_count(0) - - def test_PbhRuleCreationDeletion(self, testlog): - try: - # PBH hash field - pbhlogger.info("Create PBH hash field: {}".format(PBH_HASH_FIELD_NAME)) - self.dvs_pbh.create_pbh_hash_field( - hash_field_name=PBH_HASH_FIELD_NAME, - hash_field=PBH_HASH_FIELD_HASH_FIELD, - sequence_id=PBH_HASH_FIELD_SEQUENCE_ID - ) - self.dvs_pbh.verify_pbh_hash_field_count(1) - - # PBH hash - pbhlogger.info("Create PBH hash: {}".format(PBH_HASH_NAME)) - self.dvs_pbh.create_pbh_hash( - hash_name=PBH_HASH_NAME, - hash_field_list=PBH_HASH_HASH_FIELD_LIST - ) - self.dvs_hash.verify_hash_count(1) - - # PBH table - pbhlogger.info("Create PBH table: {}".format(PBH_TABLE_NAME)) - self.dvs_pbh.create_pbh_table( - table_name=PBH_TABLE_NAME, - interface_list=PBH_TABLE_INTERFACE_LIST, - description=PBH_TABLE_DESCRIPTION - ) - self.dvs_acl.verify_acl_table_count(1) - - # PBH rule - attr_dict = { - "ether_type": PBH_RULE_ETHER_TYPE, - "ip_protocol": PBH_RULE_IP_PROTOCOL, - "gre_key": PBH_RULE_GRE_KEY, - "inner_ether_type": PBH_RULE_INNER_ETHER_TYPE - } - - pbhlogger.info("Create PBH rule: {}".format(PBH_RULE_NAME)) - self.dvs_pbh.create_pbh_rule( - table_name=PBH_TABLE_NAME, - rule_name=PBH_RULE_NAME, - priority=PBH_RULE_PRIORITY, - qualifiers=attr_dict, - hash_name=PBH_RULE_HASH - ) - self.dvs_acl.verify_acl_rule_count(1) - finally: - # PBH rule - pbhlogger.info("Remove PBH rule: {}".format(PBH_RULE_NAME)) - self.dvs_pbh.remove_pbh_rule(PBH_TABLE_NAME, PBH_RULE_NAME) - self.dvs_acl.verify_acl_rule_count(0) - - # PBH table - pbhlogger.info("Remove PBH table: {}".format(PBH_TABLE_NAME)) - self.dvs_pbh.remove_pbh_table(PBH_TABLE_NAME) - self.dvs_acl.verify_acl_table_count(0) - - # PBH hash - pbhlogger.info("Remove PBH hash: {}".format(PBH_HASH_NAME)) - self.dvs_pbh.remove_pbh_hash(PBH_HASH_NAME) - self.dvs_hash.verify_hash_count(0) - - # PBH hash field - pbhlogger.info("Remove PBH hash field: {}".format(PBH_HASH_FIELD_NAME)) - self.dvs_pbh.remove_pbh_hash_field(PBH_HASH_FIELD_NAME) - self.dvs_pbh.verify_pbh_hash_field_count(0) - - -@pytest.mark.usefixtures("dvs_hash_manager") -class TestPbhBasicEditFlows: - def test_PbhRuleUpdate(self, testlog): - try: - # PBH hash field - pbhlogger.info("Create PBH hash field: {}".format(PBH_HASH_FIELD_NAME)) - self.dvs_pbh.create_pbh_hash_field( - hash_field_name=PBH_HASH_FIELD_NAME, - hash_field=PBH_HASH_FIELD_HASH_FIELD, - sequence_id=PBH_HASH_FIELD_SEQUENCE_ID - ) - self.dvs_pbh.verify_pbh_hash_field_count(1) - - # PBH hash - pbhlogger.info("Create PBH hash: {}".format(PBH_HASH_NAME)) - self.dvs_pbh.create_pbh_hash( - hash_name=PBH_HASH_NAME, - hash_field_list=PBH_HASH_HASH_FIELD_LIST - ) - self.dvs_hash.verify_hash_count(1) - - # PBH table - pbhlogger.info("Create PBH table: {}".format(PBH_TABLE_NAME)) - self.dvs_pbh.create_pbh_table( - table_name=PBH_TABLE_NAME, - interface_list=PBH_TABLE_INTERFACE_LIST, - description=PBH_TABLE_DESCRIPTION - ) - self.dvs_acl.verify_acl_table_count(1) - - # PBH rule - attr_dict = { - "ether_type": PBH_RULE_ETHER_TYPE, - "ip_protocol": PBH_RULE_IP_PROTOCOL, - "gre_key": PBH_RULE_GRE_KEY, - "inner_ether_type": PBH_RULE_INNER_ETHER_TYPE - } - - pbhlogger.info("Create PBH rule: {}".format(PBH_RULE_NAME)) - self.dvs_pbh.create_pbh_rule( - table_name=PBH_TABLE_NAME, - rule_name=PBH_RULE_NAME, - priority=PBH_RULE_PRIORITY, - qualifiers=attr_dict, - hash_name=PBH_RULE_HASH - ) - self.dvs_acl.verify_acl_rule_count(1) - - attr_dict = { - "ether_type": "0x86dd", - "ipv6_next_header": "0x2f", - "inner_ether_type": "0x0800" - } - - pbhlogger.info("Update PBH rule: {}".format(PBH_RULE_NAME)) - self.dvs_pbh.update_pbh_rule( - table_name=PBH_TABLE_NAME, - rule_name=PBH_RULE_NAME, - priority="100", - qualifiers=attr_dict, - hash_name=PBH_RULE_HASH, - packet_action="SET_LAG_HASH", - flow_counter="ENABLED" - ) - - hash_id = self.dvs_hash.get_hash_ids(1)[0] - counter_id = self.dvs_acl.get_acl_counter_ids(1)[0] - - sai_attr_dict = { - "SAI_ACL_ENTRY_ATTR_PRIORITY": self.dvs_acl.get_simple_qualifier_comparator("100"), - "SAI_ACL_ENTRY_ATTR_FIELD_ETHER_TYPE": self.dvs_acl.get_simple_qualifier_comparator("34525&mask:0xffff"), - "SAI_ACL_ENTRY_ATTR_FIELD_IP_PROTOCOL": self.dvs_acl.get_simple_qualifier_comparator("disabled"), - "SAI_ACL_ENTRY_ATTR_FIELD_IPV6_NEXT_HEADER": self.dvs_acl.get_simple_qualifier_comparator("47&mask:0xff"), - "SAI_ACL_ENTRY_ATTR_FIELD_GRE_KEY": self.dvs_acl.get_simple_qualifier_comparator("disabled"), - "SAI_ACL_ENTRY_ATTR_FIELD_INNER_ETHER_TYPE": self.dvs_acl.get_simple_qualifier_comparator("2048&mask:0xffff"), - "SAI_ACL_ENTRY_ATTR_ACTION_SET_ECMP_HASH_ID": self.dvs_acl.get_simple_qualifier_comparator("disabled"), - "SAI_ACL_ENTRY_ATTR_ACTION_SET_LAG_HASH_ID": self.dvs_acl.get_simple_qualifier_comparator(hash_id), - "SAI_ACL_ENTRY_ATTR_ACTION_COUNTER": self.dvs_acl.get_simple_qualifier_comparator(counter_id) - } - - self.dvs_acl.verify_acl_rule_generic( - sai_qualifiers=sai_attr_dict - ) - - finally: - # PBH rule - pbhlogger.info("Remove PBH rule: {}".format(PBH_RULE_NAME)) - self.dvs_pbh.remove_pbh_rule(PBH_TABLE_NAME, PBH_RULE_NAME) - self.dvs_acl.verify_acl_rule_count(0) - - # PBH table - pbhlogger.info("Remove PBH table: {}".format(PBH_TABLE_NAME)) - self.dvs_pbh.remove_pbh_table(PBH_TABLE_NAME) - self.dvs_acl.verify_acl_table_count(0) - - # PBH hash - pbhlogger.info("Remove PBH hash: {}".format(PBH_HASH_NAME)) - self.dvs_pbh.remove_pbh_hash(PBH_HASH_NAME) - self.dvs_hash.verify_hash_count(0) - - # PBH hash field - pbhlogger.info("Remove PBH hash field: {}".format(PBH_HASH_FIELD_NAME)) - self.dvs_pbh.remove_pbh_hash_field(PBH_HASH_FIELD_NAME) - self.dvs_pbh.verify_pbh_hash_field_count(0) - - - def test_PbhRuleUpdateFlowCounter(self, dvs, testlog): - try: - # PBH hash field - pbhlogger.info("Create PBH hash field: {}".format(PBH_HASH_FIELD_NAME)) - self.dvs_pbh.create_pbh_hash_field( - hash_field_name=PBH_HASH_FIELD_NAME, - hash_field=PBH_HASH_FIELD_HASH_FIELD, - sequence_id=PBH_HASH_FIELD_SEQUENCE_ID - ) - self.dvs_pbh.verify_pbh_hash_field_count(1) - - # PBH hash - pbhlogger.info("Create PBH hash: {}".format(PBH_HASH_NAME)) - self.dvs_pbh.create_pbh_hash( - hash_name=PBH_HASH_NAME, - hash_field_list=PBH_HASH_HASH_FIELD_LIST - ) - self.dvs_hash.verify_hash_count(1) - - # PBH table - pbhlogger.info("Create PBH table: {}".format(PBH_TABLE_NAME)) - self.dvs_pbh.create_pbh_table( - table_name=PBH_TABLE_NAME, - interface_list=PBH_TABLE_INTERFACE_LIST, - description=PBH_TABLE_DESCRIPTION - ) - self.dvs_acl.verify_acl_table_count(1) - - # Prepare ACL FLEX Counter environment - meta_data = flex_counter_module.counter_group_meta['acl_counter'] - counter_key = meta_data['key'] - counter_stat = meta_data['group_name'] - counter_map = meta_data['name_map'] - - test_flex_counters = flex_counter_module.TestFlexCounters() - test_flex_counters.setup_dbs(dvs) - test_flex_counters.verify_no_flex_counters_tables(counter_stat) - - # PBH rule - pbhlogger.info("Create PBH rule: {}".format(PBH_RULE_NAME)) - - attr_dict = { - "ether_type": PBH_RULE_ETHER_TYPE, - "ip_protocol": PBH_RULE_IP_PROTOCOL, - "gre_key": PBH_RULE_GRE_KEY, - "inner_ether_type": PBH_RULE_INNER_ETHER_TYPE - } - - self.dvs_pbh.create_pbh_rule( - table_name=PBH_TABLE_NAME, - rule_name=PBH_RULE_NAME, - priority=PBH_RULE_PRIORITY, - qualifiers=attr_dict, - hash_name=PBH_RULE_HASH, - packet_action="SET_ECMP_HASH", - flow_counter="ENABLED" - ) - self.dvs_acl.verify_acl_rule_count(1) - self.dvs_acl.get_acl_counter_ids(1) - - pbhlogger.info("Enable a ACL FLEX counter") - test_flex_counters.set_flex_counter_group_status(counter_key, counter_map) - test_flex_counters.set_flex_counter_group_interval(counter_key, counter_stat, '1000') - test_flex_counters.verify_flex_counters_populated(counter_map, counter_stat) - - pbhlogger.info("Disable a flow counter for PBH rule: {}".format(PBH_RULE_NAME)) - self.dvs_pbh.update_pbh_rule( - table_name=PBH_TABLE_NAME, - rule_name=PBH_RULE_NAME, - priority=PBH_RULE_PRIORITY, - qualifiers=attr_dict, - hash_name=PBH_RULE_HASH, - packet_action="SET_ECMP_HASH", - flow_counter="DISABLED" - ) - self.dvs_acl.get_acl_counter_ids(0) - - pbhlogger.info("Enable a flow counter for PBH rule: {}".format(PBH_RULE_NAME)) - self.dvs_pbh.update_pbh_rule( - table_name=PBH_TABLE_NAME, - rule_name=PBH_RULE_NAME, - priority=PBH_RULE_PRIORITY, - qualifiers=attr_dict, - hash_name=PBH_RULE_HASH, - packet_action="SET_ECMP_HASH", - flow_counter="ENABLED" - ) - self.dvs_acl.get_acl_counter_ids(1) - - finally: - # PBH rule - pbhlogger.info("Remove PBH rule: {}".format(PBH_RULE_NAME)) - self.dvs_pbh.remove_pbh_rule(PBH_TABLE_NAME, PBH_RULE_NAME) - self.dvs_acl.verify_acl_rule_count(0) - - # PBH table - pbhlogger.info("Remove PBH table: {}".format(PBH_TABLE_NAME)) - self.dvs_pbh.remove_pbh_table(PBH_TABLE_NAME) - self.dvs_acl.verify_acl_table_count(0) - - # PBH hash - pbhlogger.info("Remove PBH hash: {}".format(PBH_HASH_NAME)) - self.dvs_pbh.remove_pbh_hash(PBH_HASH_NAME) - self.dvs_hash.verify_hash_count(0) - - # PBH hash field - pbhlogger.info("Remove PBH hash field: {}".format(PBH_HASH_FIELD_NAME)) - self.dvs_pbh.remove_pbh_hash_field(PBH_HASH_FIELD_NAME) - self.dvs_pbh.verify_pbh_hash_field_count(0) - - # ACL FLEX counter - pbhlogger.info("Disable ACL FLEX counter") - test_flex_counters.post_trap_flow_counter_test(meta_data) - - -@pytest.mark.usefixtures("dvs_hash_manager") -@pytest.mark.usefixtures("dvs_lag_manager") -class TestPbhExtendedFlows: - class PbhRefCountHelper(object): - def __init__(self): - self.hashFieldCount = 0 - self.hashCount = 0 - self.ruleCount = 0 - self.tableCount = 0 - - def incPbhHashFieldCount(self): - self.hashFieldCount += 1 - - def decPbhHashFieldCount(self): - self.hashFieldCount -= 1 - - def getPbhHashFieldCount(self): - return self.hashFieldCount - - def incPbhHashCount(self): - self.hashCount += 1 - - def decPbhHashCount(self): - self.hashCount -= 1 - - def getPbhHashCount(self): - return self.hashCount - - def incPbhRuleCount(self): - self.ruleCount += 1 - - def decPbhRuleCount(self): - self.ruleCount -= 1 - - def getPbhRuleCount(self): - return self.ruleCount - - def incPbhTableCount(self): - self.tableCount += 1 - - def decPbhTableCount(self): - self.tableCount -= 1 - - def getPbhTableCount(self): - return self.tableCount - - class LagRefCountHelper(object): - def __init__(self): - self.lagCount = 0 - self.lagMemberCount = 0 - - def incLagCount(self): - self.lagCount += 1 - - def decLagCount(self): - self.lagCount -= 1 - - def getLagCount(self): - return self.lagCount - - def incLagMemberCount(self): - self.lagMemberCount += 1 - - def decLagMemberCount(self): - self.lagMemberCount -= 1 - - def getLagMemberCount(self): - return self.lagMemberCount - - def strip_prefix(self, s, p): - return s[len(p):] if s.startswith(p) else s - - def create_basic_lag(self, meta_dict, lag_ref_count): - lag_id = self.strip_prefix(meta_dict["name"], "PortChannel") - - pbhlogger.info("Create LAG: {}".format(meta_dict["name"])) - self.dvs_lag.create_port_channel(lag_id) - lag_ref_count.incLagCount() - self.dvs_lag.get_and_verify_port_channel(lag_ref_count.getLagCount()) - - pbhlogger.info("Create LAG member: {}".format(meta_dict["member"])) - self.dvs_lag.create_port_channel_member(lag_id, meta_dict["member"]) - lag_ref_count.incLagMemberCount() - self.dvs_lag.get_and_verify_port_channel_members(lag_ref_count.getLagMemberCount()) - - def remove_basic_lag(self, meta_dict, lag_ref_count): - lag_id = self.strip_prefix(meta_dict["name"], "PortChannel") - - pbhlogger.info("Remove LAG member: {}".format(meta_dict["member"])) - self.dvs_lag.remove_port_channel_member(lag_id, meta_dict["member"]) - lag_ref_count.decLagMemberCount() - self.dvs_lag.get_and_verify_port_channel_members(lag_ref_count.getLagMemberCount()) - - pbhlogger.info("Remove LAG: {}".format(meta_dict["name"])) - self.dvs_lag.remove_port_channel(lag_id) - lag_ref_count.decLagCount() - self.dvs_lag.get_and_verify_port_channel(lag_ref_count.getLagCount()) - - def create_hash_field(self, meta_dict, pbh_ref_count): - pbhlogger.info("Create PBH hash field: {}".format(meta_dict["name"])) - self.dvs_pbh.create_pbh_hash_field( - hash_field_name=meta_dict["name"], - hash_field=meta_dict["hash_field"], - ip_mask=meta_dict["ip_mask"] if "ip_mask" in meta_dict else None, - sequence_id=meta_dict["sequence_id"] - ) - pbh_ref_count.incPbhHashFieldCount() - self.dvs_pbh.verify_pbh_hash_field_count(pbh_ref_count.getPbhHashFieldCount()) - - def remove_hash_field(self, meta_dict, pbh_ref_count): - pbhlogger.info("Remove PBH hash field: {}".format(meta_dict["name"])) - self.dvs_pbh.remove_pbh_hash_field(meta_dict["name"]) - pbh_ref_count.decPbhHashFieldCount() - self.dvs_pbh.verify_pbh_hash_field_count(pbh_ref_count.getPbhHashFieldCount()) - - def create_hash(self, meta_dict, pbh_ref_count): - pbhlogger.info("Create PBH hash: {}".format(meta_dict["name"])) - self.dvs_pbh.create_pbh_hash( - hash_name=meta_dict["name"], - hash_field_list=meta_dict["hash_field_list"] - ) - pbh_ref_count.incPbhHashCount() - self.dvs_hash.verify_hash_count(pbh_ref_count.getPbhHashCount()) - - def remove_hash(self, meta_dict, pbh_ref_count): - pbhlogger.info("Remove PBH hash: {}".format(meta_dict["name"])) - self.dvs_pbh.remove_pbh_hash(meta_dict["name"]) - pbh_ref_count.decPbhHashCount() - self.dvs_hash.verify_hash_count(pbh_ref_count.getPbhHashCount()) - - def create_table(self, meta_dict, pbh_ref_count): - pbhlogger.info("Create PBH table: {}".format(meta_dict["name"])) - self.dvs_pbh.create_pbh_table( - table_name=meta_dict["name"], - interface_list=meta_dict["interface_list"], - description=meta_dict["description"] - ) - pbh_ref_count.incPbhTableCount() - self.dvs_acl.verify_acl_table_count(pbh_ref_count.getPbhTableCount()) - - def remove_table(self, meta_dict, pbh_ref_count): - pbhlogger.info("Remove PBH table: {}".format(meta_dict["name"])) - self.dvs_pbh.remove_pbh_table(meta_dict["name"]) - pbh_ref_count.decPbhTableCount() - self.dvs_acl.verify_acl_table_count(pbh_ref_count.getPbhTableCount()) - - def create_rule(self, meta_dict, attr_dict, pbh_ref_count): - pbhlogger.info("Create PBH rule: {}".format(meta_dict["name"])) - self.dvs_pbh.create_pbh_rule( - table_name=meta_dict["table"], - rule_name=meta_dict["name"], - priority=meta_dict["priority"], - qualifiers=attr_dict, - hash_name=meta_dict["hash"], - packet_action=meta_dict["packet_action"] if "packet_action" in meta_dict else None, - flow_counter=meta_dict["flow_counter"] if "flow_counter" in meta_dict else None - ) - pbh_ref_count.incPbhRuleCount() - self.dvs_acl.verify_acl_rule_count(pbh_ref_count.getPbhRuleCount()) - - def remove_rule(self, meta_dict, pbh_ref_count): - pbhlogger.info("Remove PBH rule: {}".format(meta_dict["name"])) - self.dvs_pbh.remove_pbh_rule(meta_dict["table"], meta_dict["name"]) - pbh_ref_count.decPbhRuleCount() - self.dvs_acl.verify_acl_rule_count(pbh_ref_count.getPbhRuleCount()) - - @pytest.fixture(autouse=True) - def pbh_ref_count(self): - pbhlogger.info("Create PBH reference count helper") - yield self.PbhRefCountHelper() - pbhlogger.info("Remove PBH reference count helper") - - @pytest.fixture(autouse=True) - def lag_ref_count(self): - pbhlogger.info("Create LAG reference count helper") - yield self.LagRefCountHelper() - pbhlogger.info("Remove LAG reference count helper") - - @pytest.fixture(autouse=True) - def pbh_port_channel_0001(self, lag_ref_count): - try: - meta_dict = { - "name": "PortChannel0001", - "member": "Ethernet120" - } - self.create_basic_lag(meta_dict, lag_ref_count) - yield meta_dict - finally: - self.remove_basic_lag(meta_dict, lag_ref_count) - - @pytest.fixture(autouse=True) - def pbh_port_channel_0002(self, lag_ref_count): - try: - meta_dict = { - "name": "PortChannel0002", - "member": "Ethernet124" - } - self.create_basic_lag(meta_dict, lag_ref_count) - yield meta_dict - finally: - self.remove_basic_lag(meta_dict, lag_ref_count) - - @pytest.fixture - def pbh_inner_ip_proto(self, pbh_ref_count): - try: - meta_dict = { - "name": "inner_ip_proto", - "hash_field": "INNER_IP_PROTOCOL", - "sequence_id": "1" - } - self.create_hash_field(meta_dict, pbh_ref_count) - yield meta_dict - finally: - self.remove_hash_field(meta_dict, pbh_ref_count) - - @pytest.fixture - def pbh_inner_l4_dst_port(self, pbh_ref_count): - try: - meta_dict = { - "name": "inner_l4_dst_port", - "hash_field": "INNER_L4_DST_PORT", - "sequence_id": "2" - } - self.create_hash_field(meta_dict, pbh_ref_count) - yield meta_dict - finally: - self.remove_hash_field(meta_dict, pbh_ref_count) - - @pytest.fixture - def pbh_inner_l4_src_port(self, pbh_ref_count): - try: - meta_dict = { - "name": "inner_l4_src_port", - "hash_field": "INNER_L4_SRC_PORT", - "sequence_id": "2" - } - self.create_hash_field(meta_dict, pbh_ref_count) - yield meta_dict - finally: - self.remove_hash_field(meta_dict, pbh_ref_count) - - @pytest.fixture - def pbh_inner_dst_ipv4(self, pbh_ref_count): - try: - meta_dict = { - "name": "inner_dst_ipv4", - "hash_field": "INNER_DST_IPV4", - "ip_mask": "255.0.0.0", - "sequence_id": "3" - } - self.create_hash_field(meta_dict, pbh_ref_count) - yield meta_dict - finally: - self.remove_hash_field(meta_dict, pbh_ref_count) - - @pytest.fixture - def pbh_inner_src_ipv4(self, pbh_ref_count): - try: - meta_dict = { - "name": "inner_src_ipv4", - "hash_field": "INNER_SRC_IPV4", - "ip_mask": "0.0.0.255", - "sequence_id": "3" - } - self.create_hash_field(meta_dict, pbh_ref_count) - yield meta_dict - finally: - self.remove_hash_field(meta_dict, pbh_ref_count) - - @pytest.fixture - def pbh_inner_dst_ipv6(self, pbh_ref_count): - try: - meta_dict = { - "name": "inner_dst_ipv6", - "hash_field": "INNER_DST_IPV6", - "ip_mask": "ffff::", - "sequence_id": "4" - } - self.create_hash_field(meta_dict, pbh_ref_count) - yield meta_dict - finally: - self.remove_hash_field(meta_dict, pbh_ref_count) - - @pytest.fixture - def pbh_inner_src_ipv6(self, pbh_ref_count): - try: - meta_dict = { - "name": "inner_src_ipv6", - "hash_field": "INNER_SRC_IPV6", - "ip_mask": "::ffff", - "sequence_id": "4" - } - self.create_hash_field(meta_dict, pbh_ref_count) - yield meta_dict - finally: - self.remove_hash_field(meta_dict, pbh_ref_count) - - @pytest.fixture - def pbh_inner_v4( - self, - pbh_ref_count, - pbh_inner_ip_proto, - pbh_inner_l4_dst_port, - pbh_inner_l4_src_port, - pbh_inner_dst_ipv4, - pbh_inner_src_ipv4 - ): - try: - meta_dict = { - "name": "inner_v4_hash", - "hash_field_list": [ - pbh_inner_ip_proto["name"], - pbh_inner_l4_dst_port["name"], - pbh_inner_l4_src_port["name"], - pbh_inner_dst_ipv4["name"], - pbh_inner_src_ipv4["name"] - ] - } - self.create_hash(meta_dict, pbh_ref_count) - yield meta_dict - finally: - self.remove_hash(meta_dict, pbh_ref_count) - - @pytest.fixture - def pbh_inner_v6( - self, - pbh_ref_count, - pbh_inner_ip_proto, - pbh_inner_l4_dst_port, - pbh_inner_l4_src_port, - pbh_inner_dst_ipv6, - pbh_inner_src_ipv6 - ): - try: - meta_dict = { - "name": "inner_v6_hash", - "hash_field_list": [ - pbh_inner_ip_proto["name"], - pbh_inner_l4_dst_port["name"], - pbh_inner_l4_src_port["name"], - pbh_inner_dst_ipv6["name"], - pbh_inner_src_ipv6["name"] - ] - } - self.create_hash(meta_dict, pbh_ref_count) - yield meta_dict - finally: - self.remove_hash(meta_dict, pbh_ref_count) - - @pytest.fixture - def pbh_table( - self, - pbh_ref_count, - pbh_port_channel_0001, - pbh_port_channel_0002 - ): - try: - meta_dict = { - "name": "pbh_table", - "interface_list": [ - "Ethernet0", - "Ethernet4", - pbh_port_channel_0001["name"], - pbh_port_channel_0002["name"] - ], - "description": "NVGRE and VxLAN" - } - self.create_table(meta_dict, pbh_ref_count) - yield meta_dict - finally: - self.remove_table(meta_dict, pbh_ref_count) - - @pytest.fixture - def pbh_nvgre( - self, - pbh_ref_count, - pbh_table, - pbh_inner_v6 - ): - try: - meta_dict = { - "table": pbh_table["name"], - "name": "nvgre", - "priority": "1", - "ether_type": "0x0800", - "ip_protocol": "0x2f", - "gre_key": "0x2500/0xffffff00", - "inner_ether_type": "0x86dd", - "hash": pbh_inner_v6["name"], - "packet_action": "SET_ECMP_HASH", - "flow_counter": "DISABLED" - } - attr_dict = { - "gre_key": meta_dict["gre_key"], - "inner_ether_type": meta_dict["inner_ether_type"] - } - self.create_rule(meta_dict, attr_dict, pbh_ref_count) - yield meta_dict - finally: - self.remove_rule(meta_dict, pbh_ref_count) - - @pytest.fixture - def pbh_vxlan( - self, - pbh_ref_count, - pbh_table, - pbh_inner_v4 - ): - try: - meta_dict = { - "table": pbh_table["name"], - "name": "vxlan", - "priority": "2", - "ether_type": "0x0800", - "ip_protocol": "0x11", - "l4_dst_port": "0x12b5", - "inner_ether_type": "0x0800", - "hash": pbh_inner_v4["name"], - "packet_action": "SET_LAG_HASH", - "flow_counter": "ENABLED" - } - attr_dict = { - "ip_protocol": meta_dict["ip_protocol"], - "l4_dst_port": meta_dict["l4_dst_port"], - "inner_ether_type": meta_dict["inner_ether_type"] - } - self.create_rule(meta_dict, attr_dict, pbh_ref_count) - yield meta_dict - finally: - self.remove_rule(meta_dict, pbh_ref_count) - - def test_PbhNvgreVxlanConfiguration(self, testlog, pbh_nvgre, pbh_vxlan): - pass - - -@pytest.mark.usefixtures("dvs_hash_manager") -class TestPbhDependencyFlows: - def test_PbhHashCreationDeletionWithDependencies(self, testlog): - try: - # PBH hash - pbhlogger.info("Create PBH hash: {}".format(PBH_HASH_NAME)) - self.dvs_pbh.create_pbh_hash( - hash_name=PBH_HASH_NAME, - hash_field_list=PBH_HASH_HASH_FIELD_LIST - ) - self.dvs_hash.verify_hash_count(0) - - # PBH hash field - pbhlogger.info("Create PBH hash field: {}".format(PBH_HASH_FIELD_NAME)) - self.dvs_pbh.create_pbh_hash_field( - hash_field_name=PBH_HASH_FIELD_NAME, - hash_field=PBH_HASH_FIELD_HASH_FIELD, - sequence_id=PBH_HASH_FIELD_SEQUENCE_ID - ) - self.dvs_pbh.verify_pbh_hash_field_count(1) - self.dvs_hash.verify_hash_count(1) - finally: - # PBH hash field - pbhlogger.info("Remove PBH hash field: {}".format(PBH_HASH_FIELD_NAME)) - self.dvs_pbh.remove_pbh_hash_field(PBH_HASH_FIELD_NAME) - self.dvs_pbh.verify_pbh_hash_field_count(1) - - # PBH hash - pbhlogger.info("Remove PBH hash: {}".format(PBH_HASH_NAME)) - self.dvs_pbh.remove_pbh_hash(PBH_HASH_NAME) - self.dvs_hash.verify_hash_count(0) - self.dvs_pbh.verify_pbh_hash_field_count(0) - - def test_PbhRuleCreationDeletionWithDependencies(self, testlog): - try: - # PBH hash - pbhlogger.info("Create PBH hash: {}".format(PBH_HASH_NAME)) - self.dvs_pbh.create_pbh_hash( - hash_name=PBH_HASH_NAME, - hash_field_list=PBH_HASH_HASH_FIELD_LIST - ) - self.dvs_hash.verify_hash_count(0) - - # PBH hash field - pbhlogger.info("Create PBH hash field: {}".format(PBH_HASH_FIELD_NAME)) - self.dvs_pbh.create_pbh_hash_field( - hash_field_name=PBH_HASH_FIELD_NAME, - hash_field=PBH_HASH_FIELD_HASH_FIELD, - sequence_id=PBH_HASH_FIELD_SEQUENCE_ID - ) - self.dvs_pbh.verify_pbh_hash_field_count(1) - self.dvs_hash.verify_hash_count(1) - - # PBH rule - attr_dict = { - "ether_type": PBH_RULE_ETHER_TYPE, - "ip_protocol": PBH_RULE_IP_PROTOCOL, - "gre_key": PBH_RULE_GRE_KEY, - "inner_ether_type": PBH_RULE_INNER_ETHER_TYPE - } - - pbhlogger.info("Create PBH rule: {}".format(PBH_RULE_NAME)) - self.dvs_pbh.create_pbh_rule( - table_name=PBH_TABLE_NAME, - rule_name=PBH_RULE_NAME, - priority=PBH_RULE_PRIORITY, - qualifiers=attr_dict, - hash_name=PBH_RULE_HASH - ) - self.dvs_acl.verify_acl_rule_count(0) - - # PBH table - pbhlogger.info("Create PBH table: {}".format(PBH_TABLE_NAME)) - self.dvs_pbh.create_pbh_table( - table_name=PBH_TABLE_NAME, - interface_list=PBH_TABLE_INTERFACE_LIST, - description=PBH_TABLE_DESCRIPTION - ) - self.dvs_acl.verify_acl_table_count(1) - self.dvs_acl.verify_acl_rule_count(1) - - finally: - # PBH table - pbhlogger.info("Remove PBH table: {}".format(PBH_TABLE_NAME)) - self.dvs_pbh.remove_pbh_table(PBH_TABLE_NAME) - self.dvs_acl.verify_acl_table_count(1) - - # PBH rule - pbhlogger.info("Remove PBH rule: {}".format(PBH_RULE_NAME)) - self.dvs_pbh.remove_pbh_rule(PBH_TABLE_NAME, PBH_RULE_NAME) - self.dvs_acl.verify_acl_rule_count(0) - self.dvs_acl.verify_acl_table_count(0) - - # PBH hash field - pbhlogger.info("Remove PBH hash field: {}".format(PBH_HASH_FIELD_NAME)) - self.dvs_pbh.remove_pbh_hash_field(PBH_HASH_FIELD_NAME) - self.dvs_pbh.verify_pbh_hash_field_count(1) - - # PBH hash - pbhlogger.info("Remove PBH hash: {}".format(PBH_HASH_NAME)) - self.dvs_pbh.remove_pbh_hash(PBH_HASH_NAME) - self.dvs_hash.verify_hash_count(0) - self.dvs_pbh.verify_pbh_hash_field_count(0) - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_pfc.py b/tests/test_pfc.py deleted file mode 100644 index 9bd5c41f0a..0000000000 --- a/tests/test_pfc.py +++ /dev/null @@ -1,136 +0,0 @@ -import time -import pytest - -from swsscommon import swsscommon - -def getBitMaskStr(bits): - - mask = 0 - - for b in bits: - mask = mask | 1 << b - - return str(mask) - - -def setPortPfc(dvs, port_name, pfc_queues): - - cfg_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - - port_qos_tbl = swsscommon.Table(cfg_db, 'PORT_QOS_MAP') - fvs = swsscommon.FieldValuePairs([('pfc_enable', ",".join(str(q) for q in pfc_queues))]) - port_qos_tbl.set(port_name, fvs) - - time.sleep(1) - - -def setPortPfcAsym(dvs, port_name, pfc_asym): - - cfg_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - - port_tbl = swsscommon.Table(cfg_db, 'PORT') - fvs = swsscommon.FieldValuePairs([('pfc_asym', pfc_asym)]) - port_tbl.set(port_name, fvs) - - time.sleep(1) - - -def getPortOid(dvs, port_name): - - cnt_db = swsscommon.DBConnector(swsscommon.COUNTERS_DB, dvs.redis_sock, 0) - port_map_tbl = swsscommon.Table(cnt_db, 'COUNTERS_PORT_NAME_MAP') - - for k in port_map_tbl.get('')[1]: - if k[0] == port_name: - return k[1] - - return '' - - -def getPortAttr(dvs, port_oid, port_attr): - - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - port_tbl = swsscommon.Table(asic_db, 'ASIC_STATE:SAI_OBJECT_TYPE_PORT:{0}'.format(port_oid)) - - for k in port_tbl.get('')[1]: - if k[0] == port_attr: - return k[1] - - return '' - - -class TestPfc(object): - def test_PfcAsymmetric(self, dvs, testlog): - - port_name = 'Ethernet0' - pfc_queues = [ 3, 4 ] - - # Configure default PFC - setPortPfc(dvs, port_name, pfc_queues) - - # Get SAI object ID for the interface - port_oid = getPortOid(dvs, port_name) - - # Verify default PFC is set to configured value - pfc = getPortAttr(dvs, port_oid, 'SAI_PORT_ATTR_PRIORITY_FLOW_CONTROL') - assert pfc == getBitMaskStr(pfc_queues) - - # Enable asymmetric PFC - setPortPfcAsym(dvs, port_name, 'on') - - # Verify PFC mode is set to 'SEPARATE' - pfc_mode = getPortAttr(dvs, port_oid, 'SAI_PORT_ATTR_PRIORITY_FLOW_CONTROL_MODE') - assert pfc_mode == 'SAI_PORT_PRIORITY_FLOW_CONTROL_MODE_SEPARATE' - - # Verify TX PFC is set to previous PFC value - pfc_tx = getPortAttr(dvs, port_oid, 'SAI_PORT_ATTR_PRIORITY_FLOW_CONTROL_TX') - assert pfc_tx == pfc - - # Verify RX PFC is set to 0xFF (255) - pfc_rx = getPortAttr(dvs, port_oid, 'SAI_PORT_ATTR_PRIORITY_FLOW_CONTROL_RX') - assert pfc_rx == '255' - - # Disable asymmetric PFC - setPortPfcAsym(dvs, port_name, 'off') - - # Verify PFC mode is set to 'COMBINED' - pfc_mode = getPortAttr(dvs, port_oid, 'SAI_PORT_ATTR_PRIORITY_FLOW_CONTROL_MODE') - assert pfc_mode == 'SAI_PORT_PRIORITY_FLOW_CONTROL_MODE_COMBINED' - - # Verify PFC is set to TX PFC value - pfc = getPortAttr(dvs, port_oid, 'SAI_PORT_ATTR_PRIORITY_FLOW_CONTROL') - assert pfc == pfc_tx - - def test_PfcUnconfig(self, dvs, testlog): - - port_name = 'Ethernet0' - pfc_queues = [ 3, 4 ] - - # Configure default PFC - setPortPfc(dvs, port_name, pfc_queues) - - # Get SAI object ID for the interface - port_oid = getPortOid(dvs, port_name) - - # Verify default PFC is set to configured value - pfc = getPortAttr(dvs, port_oid, 'SAI_PORT_ATTR_PRIORITY_FLOW_CONTROL') - assert pfc == getBitMaskStr(pfc_queues) - - # Configure PFC on single TC - pfc_queues = [ 3 ] - setPortPfc(dvs, port_name, pfc_queues) - # Verify default PFC is set to configured value - pfc = getPortAttr(dvs, port_oid, 'SAI_PORT_ATTR_PRIORITY_FLOW_CONTROL') - assert pfc == getBitMaskStr(pfc_queues) - - # Disable PFC on last TC - pfc_queues = [ ] - setPortPfc(dvs, port_name, pfc_queues) - # Verify default PFC is set to configured value - pfc = getPortAttr(dvs, port_oid, 'SAI_PORT_ATTR_PRIORITY_FLOW_CONTROL') - assert pfc == getBitMaskStr(pfc_queues) - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_pfcwd.py b/tests/test_pfcwd.py deleted file mode 100644 index c88b6f6e96..0000000000 --- a/tests/test_pfcwd.py +++ /dev/null @@ -1,302 +0,0 @@ -import redis -import time -import os -import pytest -import re -import json -from swsscommon import swsscommon - -PFCWD_TABLE_NAME = "DROP_TEST_TABLE" -PFCWD_TABLE_TYPE = "DROP" -PFCWD_TC = ["3", "4"] -PFCWD_RULE_NAME_1 = "DROP_TEST_RULE_1" -PFCWD_RULE_NAME_2 = "DROP_TEST_RULE_2" - -class TestPfcWd: - def test_PfcWdAclCreationDeletion(self, dvs, dvs_acl, testlog): - try: - dvs_acl.create_acl_table(PFCWD_TABLE_NAME, PFCWD_TABLE_TYPE, ["Ethernet0","Ethernet8", "Ethernet16", "Ethernet24"], stage="ingress") - - config_qualifiers = { - "TC" : PFCWD_TC[0], - "IN_PORTS": "Ethernet0" - } - - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_TC" : dvs_acl.get_simple_qualifier_comparator("3&mask:0xff"), - "SAI_ACL_ENTRY_ATTR_FIELD_IN_PORTS": dvs_acl.get_port_list_comparator(["Ethernet0"]) - } - - dvs_acl.create_acl_rule(PFCWD_TABLE_NAME, PFCWD_RULE_NAME_1, config_qualifiers, action="DROP") - time.sleep(5) - dvs_acl.verify_acl_rule(expected_sai_qualifiers, action="DROP") - - config_qualifiers = { - "TC" : PFCWD_TC[0], - "IN_PORTS": "Ethernet0,Ethernet16" - } - - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_TC" : dvs_acl.get_simple_qualifier_comparator("3&mask:0xff"), - "SAI_ACL_ENTRY_ATTR_FIELD_IN_PORTS": dvs_acl.get_port_list_comparator(["Ethernet0","Ethernet16"]) - } - - dvs_acl.update_acl_rule(PFCWD_TABLE_NAME, PFCWD_RULE_NAME_1, config_qualifiers, action="DROP") - time.sleep(5) - dvs_acl.verify_acl_rule(expected_sai_qualifiers, action="DROP") - dvs_acl.remove_acl_rule(PFCWD_TABLE_NAME, PFCWD_RULE_NAME_1) - - config_qualifiers = { - "TC" : PFCWD_TC[1], - "IN_PORTS": "Ethernet8" - } - - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_TC" : dvs_acl.get_simple_qualifier_comparator("4&mask:0xff"), - "SAI_ACL_ENTRY_ATTR_FIELD_IN_PORTS": dvs_acl.get_port_list_comparator(["Ethernet8"]), - } - - dvs_acl.create_acl_rule(PFCWD_TABLE_NAME, PFCWD_RULE_NAME_2, config_qualifiers, action="DROP") - time.sleep(5) - dvs_acl.verify_acl_rule(expected_sai_qualifiers, action="DROP") - - config_qualifiers = { - "TC" : PFCWD_TC[1], - "IN_PORTS": "Ethernet8,Ethernet24" - } - - expected_sai_qualifiers = { - "SAI_ACL_ENTRY_ATTR_FIELD_TC" : dvs_acl.get_simple_qualifier_comparator("4&mask:0xff"), - "SAI_ACL_ENTRY_ATTR_FIELD_IN_PORTS": dvs_acl.get_port_list_comparator(["Ethernet8","Ethernet24"]), - } - - dvs_acl.update_acl_rule(PFCWD_TABLE_NAME, PFCWD_RULE_NAME_2, config_qualifiers, action="DROP") - time.sleep(5) - dvs_acl.verify_acl_rule(expected_sai_qualifiers, action="DROP") - dvs_acl.remove_acl_rule(PFCWD_TABLE_NAME, PFCWD_RULE_NAME_2) - - finally: - dvs_acl.remove_acl_table(PFCWD_TABLE_NAME) - - -class TestPfcwdFunc(object): - @pytest.fixture - def setup_teardown_test(self, dvs): - self.get_db_handle(dvs) - - self.test_ports = ["Ethernet0"] - - self.setup_test(dvs) - self.get_port_oids() - self.get_queue_oids() - - yield - - self.teardown_test(dvs) - - def setup_test(self, dvs): - # get original cable len for test ports - fvs = self.config_db.get_entry("CABLE_LENGTH", "AZURE") - self.orig_cable_len = dict() - for port in self.test_ports: - self.orig_cable_len[port] = fvs[port] - # set cable len to non zero value. if port is down, default cable len is 0 - self.set_cable_len(port, "5m") - # startup port - dvs.port_admin_set(port, "up") - - # enable pfcwd - self.set_flex_counter_status("PFCWD", "enable") - # enable queue so that queue oids are generated - self.set_flex_counter_status("QUEUE", "enable") - - def teardown_test(self, dvs): - # disable pfcwd - self.set_flex_counter_status("PFCWD", "disable") - # disable queue - self.set_flex_counter_status("QUEUE", "disable") - - for port in self.test_ports: - if self.orig_cable_len: - self.set_cable_len(port, self.orig_cable_len[port]) - # shutdown port - dvs.port_admin_set(port, "down") - - def get_db_handle(self, dvs): - self.app_db = dvs.get_app_db() - self.asic_db = dvs.get_asic_db() - self.config_db = dvs.get_config_db() - self.counters_db = dvs.get_counters_db() - - def set_flex_counter_status(self, key, state): - fvs = {'FLEX_COUNTER_STATUS': state} - self.config_db.update_entry("FLEX_COUNTER_TABLE", key, fvs) - time.sleep(1) - - def get_queue_oids(self): - self.queue_oids = self.counters_db.get_entry("COUNTERS_QUEUE_NAME_MAP", "") - - def get_port_oids(self): - self.port_oids = self.counters_db.get_entry("COUNTERS_PORT_NAME_MAP", "") - - def _get_bitmask(self, queues): - mask = 0 - if queues is not None: - for queue in queues: - mask = mask | 1 << queue - - return str(mask) - - def set_ports_pfc(self, status='enable', pfc_queues=[3,4]): - keyname = 'pfcwd_sw_enable' - for port in self.test_ports: - if 'enable' in status: - queues = ",".join([str(q) for q in pfc_queues]) - fvs = {keyname: queues, 'pfc_enable': queues} - self.config_db.create_entry("PORT_QOS_MAP", port, fvs) - else: - self.config_db.delete_entry("PORT_QOS_MAP", port) - - def set_cable_len(self, port_name, cable_len): - fvs = {port_name: cable_len} - self.config_db.update_entry("CABLE_LEN", "AZURE", fvs) - - def start_pfcwd_on_ports(self, poll_interval="200", detection_time="200", restoration_time="200", action="drop"): - pfcwd_info = {"POLL_INTERVAL": poll_interval} - self.config_db.update_entry("PFC_WD", "GLOBAL", pfcwd_info) - - pfcwd_info = {"action": action, - "detection_time" : detection_time, - "restoration_time": restoration_time - } - for port in self.test_ports: - self.config_db.update_entry("PFC_WD", port, pfcwd_info) - - def stop_pfcwd_on_ports(self): - for port in self.test_ports: - self.config_db.delete_entry("PFC_WD", port) - - def verify_ports_pfc(self, queues=None): - mask = self._get_bitmask(queues) - fvs = {"SAI_PORT_ATTR_PRIORITY_FLOW_CONTROL" : mask} - for port in self.test_ports: - self.asic_db.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", self.port_oids[port], fvs) - - def verify_pfcwd_state(self, queues, state="stormed"): - fvs = {"PFC_WD_STATUS": state} - for port in self.test_ports: - for queue in queues: - queue_name = port + ":" + str(queue) - self.counters_db.wait_for_field_match("COUNTERS", self.queue_oids[queue_name], fvs) - - def verify_pfcwd_counters(self, queues, restore="0"): - fvs = {"PFC_WD_QUEUE_STATS_DEADLOCK_DETECTED" : "1", - "PFC_WD_QUEUE_STATS_DEADLOCK_RESTORED" : restore - } - for port in self.test_ports: - for queue in queues: - queue_name = port + ":" + str(queue) - self.counters_db.wait_for_field_match("COUNTERS", self.queue_oids[queue_name], fvs) - - def reset_pfcwd_counters(self, queues): - fvs = {"PFC_WD_QUEUE_STATS_DEADLOCK_DETECTED" : "0", - "PFC_WD_QUEUE_STATS_DEADLOCK_RESTORED" : "0" - } - for port in self.test_ports: - for queue in queues: - queue_name = port + ":" + str(queue) - self.counters_db.update_entry("COUNTERS", self.queue_oids[queue_name], fvs) - - def set_storm_state(self, queues, state="enabled"): - fvs = {"DEBUG_STORM": state} - for port in self.test_ports: - for queue in queues: - queue_name = port + ":" + str(queue) - self.counters_db.update_entry("COUNTERS", self.queue_oids[queue_name], fvs) - - def test_pfcwd_software_single_queue(self, dvs, setup_teardown_test): - try: - # enable PFC on queues - test_queues = [3, 4] - self.set_ports_pfc(pfc_queues=test_queues) - - # verify in asic db - self.verify_ports_pfc(test_queues) - - # start pfcwd - self.start_pfcwd_on_ports() - - # start pfc storm - storm_queue = [3] - self.set_storm_state(storm_queue) - - # verify pfcwd is triggered - self.verify_pfcwd_state(storm_queue) - - # verify pfcwd counters - self.verify_pfcwd_counters(storm_queue) - - # verify if queue is disabled - self.verify_ports_pfc(queues=[4]) - - # stop storm - self.set_storm_state(storm_queue, state="disabled") - - # verify pfcwd state is restored - self.verify_pfcwd_state(storm_queue, state="operational") - - # verify pfcwd counters - self.verify_pfcwd_counters(storm_queue, restore="1") - - # verify if queue is enabled - self.verify_ports_pfc(test_queues) - - finally: - self.reset_pfcwd_counters(storm_queue) - self.stop_pfcwd_on_ports() - - def test_pfcwd_software_multi_queue(self, dvs, setup_teardown_test): - try: - # enable PFC on queues - test_queues = [3, 4] - self.set_ports_pfc(pfc_queues=test_queues) - - # verify in asic db - self.verify_ports_pfc(test_queues) - - # start pfcwd - self.start_pfcwd_on_ports() - - # start pfc storm - self.set_storm_state(test_queues) - - # verify pfcwd is triggered - self.verify_pfcwd_state(test_queues) - - # verify pfcwd counters - self.verify_pfcwd_counters(test_queues) - - # verify if queue is disabled. Expected mask is 0 - self.verify_ports_pfc() - - # stop storm - self.set_storm_state(test_queues, state="disabled") - - # verify pfcwd state is restored - self.verify_pfcwd_state(test_queues, state="operational") - - # verify pfcwd counters - self.verify_pfcwd_counters(test_queues, restore="1") - - # verify if queue is enabled - self.verify_ports_pfc(test_queues) - - finally: - self.reset_pfcwd_counters(test_queues) - self.stop_pfcwd_on_ports() - -# -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_pg_drop_counter.py b/tests/test_pg_drop_counter.py deleted file mode 100644 index 6d97af5f5c..0000000000 --- a/tests/test_pg_drop_counter.py +++ /dev/null @@ -1,94 +0,0 @@ -import os -import re -import time -import json -import redis - -from swsscommon import swsscommon - -pg_drop_attr = "SAI_INGRESS_PRIORITY_GROUP_STAT_DROPPED_PACKETS" - -class TestPGDropCounter(object): - DEFAULT_POLL_INTERVAL = 10 - pgs = {} - - def setup_dbs(self, dvs): - self.asic_db = dvs.get_asic_db() - self.counters_db = dvs.get_counters_db() - self.config_db = dvs.get_config_db() - self.flex_db = dvs.get_flex_db() - - def set_counter(self, dvs, obj_type, obj_id, attr, val): - - db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - ntf = swsscommon.NotificationProducer(db, "SAI_VS_UNITTEST_CHANNEL") - - r = redis.Redis(unix_socket_path=dvs.redis_sock, db=swsscommon.ASIC_DB, - encoding="utf-8", decode_responses=True) - rid = r.hget("VIDTORID", obj_id) - - assert rid is not None - - fvp = swsscommon.FieldValuePairs([(attr, val)]) - key = rid - - # explicit convert unicode string to str for python2 - ntf.send("set_stats", str(key), fvp) - - def populate_asic(self, dvs, val): - for obj_id in self.pgs: - self.set_counter(dvs, "SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP", obj_id, pg_drop_attr, val) - - def verify_value(self, dvs, obj_ids, entry_name, expected_value): - counters_db = swsscommon.DBConnector(swsscommon.COUNTERS_DB, dvs.redis_sock, 0) - table = swsscommon.Table(counters_db, "COUNTERS") - - for obj_id in obj_ids: - ret = table.get(obj_id) - - status = ret[0] - assert status - keyvalues = ret[1] - found = False - for key, value in keyvalues: - if key == entry_name: - assert value == expected_value, "Saved value not the same as expected" - found = True - assert found, "entry name %s not found" % (entry_name) - - def set_up_flex_counter(self): - fc_status_enable = {"FLEX_COUNTER_STATUS": "enable"} - self.config_db.create_entry("FLEX_COUNTER_TABLE", "PG_DROP", fc_status_enable) - self.config_db.create_entry("FLEX_COUNTER_TABLE", "PG_WATERMARK", fc_status_enable) - # Wait for DB's to populate by orchagent - time.sleep(2) - - def clear_flex_counter(self): - for pg in self.pgs: - self.flex_db.delete_entry("FLEX_COUNTER_TABLE", "PG_DROP_STAT_COUNTER:{}".format(pg)) - - self.config_db.delete_entry("FLEX_COUNTER_TABLE", "PG_DROP") - self.config_db.delete_entry("FLEX_COUNTER_TABLE", "PG_WATERMARK") - - def test_pg_drop_counters(self, dvs): - self.setup_dbs(dvs) - self.set_up_flex_counter() - # Get all configured counters OID's - self.pgs = self.counters_db.db_connection.hgetall("COUNTERS_PG_NAME_MAP").values() - assert self.pgs is not None and len(self.pgs) > 0 - - try: - self.populate_asic(dvs, "0") - time.sleep(self.DEFAULT_POLL_INTERVAL) - self.verify_value(dvs, self.pgs, pg_drop_attr, "0") - - self.populate_asic(dvs, "100") - time.sleep(self.DEFAULT_POLL_INTERVAL) - self.verify_value(dvs, self.pgs, pg_drop_attr, "100") - - self.populate_asic(dvs, "123") - time.sleep(self.DEFAULT_POLL_INTERVAL) - self.verify_value(dvs, self.pgs, pg_drop_attr, "123") - finally: - self.clear_flex_counter() - diff --git a/tests/test_policer.py b/tests/test_policer.py deleted file mode 100644 index 4df4f9c15c..0000000000 --- a/tests/test_policer.py +++ /dev/null @@ -1,80 +0,0 @@ -import platform -import pytest -import time - -from swsscommon import swsscommon - - -class TestPolicer(object): - def test_PolicerBasic(self, dvs, testlog): - dvs.setup_db() - policer = "POLICER" - - # create policer - tbl = swsscommon.Table(dvs.cdb, "POLICER") - fvs = swsscommon.FieldValuePairs([("meter_type", "packets"), - ("mode", "sr_tcm"), - ("cir", "600"), - ("cbs", "600"), - ("red_packet_action", "drop")]) - tbl.set(policer, fvs) - time.sleep(1) - - # check asic database - tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_POLICER") - policer_entries = [p for p in tbl.getKeys() if p not in dvs.asicdb.default_copp_policers] - assert len(policer_entries) == 1 - - (status, fvs) = tbl.get(policer_entries[0]) - assert status == True - assert len(fvs) == 5 - for fv in fvs: - if fv[0] == "SAI_POLICER_ATTR_CBS": - assert fv[1] == "600" - if fv[0] == "SAI_POLICER_ATTR_CIR": - assert fv[1] == "600" - if fv[0] == "SAI_POLICER_ATTR_RED_PACKET_ACTION": - assert fv[1] == "SAI_PACKET_ACTION_DROP" - if fv[0] == "SAI_POLICER_ATTR_MODE": - assert fv[1] == "SAI_POLICER_MODE_SR_TCM" - if fv[0] == "SAI_POLICER_ATTR_METER_TYPE": - assert fv[1] == "SAI_METER_TYPE_PACKETS" - - # update cir - tbl = swsscommon.Table(dvs.cdb, "POLICER") - fvs = swsscommon.FieldValuePairs([("cir", "800")]) - tbl.set(policer, fvs) - time.sleep(1) - - # check asic database - tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_POLICER") - (status, fvs) = tbl.get(policer_entries[0]) - assert status == True - assert len(fvs) == 5 - for fv in fvs: - if fv[0] == "SAI_POLICER_ATTR_CBS": - assert fv[1] == "600" - if fv[0] == "SAI_POLICER_ATTR_CIR": - assert fv[1] == "800" # updated - if fv[0] == "SAI_POLICER_ATTR_RED_PACKET_ACTION": - assert fv[1] == "SAI_PACKET_ACTION_DROP" - if fv[0] == "SAI_POLICER_ATTR_MODE": - assert fv[1] == "SAI_POLICER_MODE_SR_TCM" - if fv[0] == "SAI_POLICER_ATTR_METER_TYPE": - assert fv[1] == "SAI_METER_TYPE_PACKETS" - - # remove policer - tbl = swsscommon.Table(dvs.cdb, "POLICER") - tbl._del(policer) - time.sleep(1) - - # check asic database - tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_POLICER") - policer_entries = [p for p in tbl.getKeys() if p not in dvs.asicdb.default_copp_policers] - assert len(policer_entries) == 0 - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_port.py b/tests/test_port.py deleted file mode 100644 index 3853a61ffe..0000000000 --- a/tests/test_port.py +++ /dev/null @@ -1,312 +0,0 @@ -import time -import os -import pytest - -from swsscommon import swsscommon - - -class TestPort(object): - def test_PortTpid(self, dvs, testlog): - pdb = swsscommon.DBConnector(0, dvs.redis_sock, 0) - adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) - - # set TPID to port - cdb_port_tbl = swsscommon.Table(cdb, "PORT") - fvs = swsscommon.FieldValuePairs([("tpid", "0x9200")]) - cdb_port_tbl.set("Ethernet8", fvs) - time.sleep(1) - - # check application database - pdb_port_tbl = swsscommon.Table(pdb, "PORT_TABLE") - (status, fvs) = pdb_port_tbl.get("Ethernet8") - assert status == True - for fv in fvs: - if fv[0] == "tpid": - tpid = fv[1] - assert tpid == "0x9200" - - # Check ASIC DB - atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_PORT") - # get TPID and validate it to be 0x9200 (37376) - (status, fvs) = atbl.get(dvs.asicdb.portnamemap["Ethernet8"]) - assert status == True - asic_tpid = "0" - - for fv in fvs: - if fv[0] == "SAI_PORT_ATTR_TPID": - asic_tpid = fv[1] - - assert asic_tpid == "37376" - - def test_PortMtu(self, dvs, testlog): - pdb = swsscommon.DBConnector(0, dvs.redis_sock, 0) - adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) - - # set MTU to port - tbl = swsscommon.Table(cdb, "PORT") - fvs = swsscommon.FieldValuePairs([("MTU", "9100")]) - tbl.set("Ethernet8", fvs) - time.sleep(1) - - # check application database - tbl = swsscommon.Table(pdb, "PORT_TABLE") - (status, fvs) = tbl.get("Ethernet8") - assert status == True - for fv in fvs: - if fv[0] == "mtu": - assert fv[1] == "9100" - - def test_PortNotification(self, dvs, testlog): - dvs.port_admin_set("Ethernet0", "up") - dvs.interface_ip_add("Ethernet0", "10.0.0.0/31") - - dvs.port_admin_set("Ethernet4", "up") - dvs.interface_ip_add("Ethernet4", "10.0.0.2/31") - - dvs.servers[0].runcmd("ip link set down dev eth0") == 0 - - time.sleep(1) - - db = swsscommon.DBConnector(0, dvs.redis_sock, 0) - - tbl = swsscommon.Table(db, "PORT_TABLE") - - (status, fvs) = tbl.get("Ethernet0") - - assert status == True - - oper_status = "unknown" - - for v in fvs: - if v[0] == "oper_status": - oper_status = v[1] - break - - assert oper_status == "down" - - dvs.servers[0].runcmd("ip link set up dev eth0") == 0 - - time.sleep(1) - - (status, fvs) = tbl.get("Ethernet0") - - assert status == True - - oper_status = "unknown" - - for v in fvs: - if v[0] == "oper_status": - oper_status = v[1] - break - - assert oper_status == "up" - - def test_PortFecForce(self, dvs, testlog): - db = swsscommon.DBConnector(0, dvs.redis_sock, 0) - adb = dvs.get_asic_db() - - ptbl = swsscommon.ProducerStateTable(db, "PORT_TABLE") - - # set fec - fvs = swsscommon.FieldValuePairs([("fec","none")]) - ptbl.set("Ethernet0", fvs) - fvs = swsscommon.FieldValuePairs([("fec","rs")]) - ptbl.set("Ethernet4", fvs) - - # validate if fec none is pushed to asic db when set first time - port_oid = adb.port_name_map["Ethernet0"] - expected_fields = {"SAI_PORT_ATTR_FEC_MODE":"SAI_PORT_FEC_MODE_NONE"} - adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) - - # validate if fec rs is pushed to asic db when set first time - port_oid = adb.port_name_map["Ethernet4"] - expected_fields = {"SAI_PORT_ATTR_FEC_MODE":"SAI_PORT_FEC_MODE_RS"} - adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) - - def test_PortFec(self, dvs, testlog): - dvs.port_admin_set("Ethernet0", "up") - dvs.interface_ip_add("Ethernet0", "10.0.0.0/31") - - dvs.port_admin_set("Ethernet4", "up") - dvs.interface_ip_add("Ethernet4", "10.0.0.2/31") - - dvs.servers[0].runcmd("ip link set down dev eth0") == 0 - - time.sleep(1) - - db = swsscommon.DBConnector(0, dvs.redis_sock, 0) - adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - - tbl = swsscommon.Table(db, "PORT_TABLE") - ptbl = swsscommon.ProducerStateTable(db, "PORT_TABLE") - atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_PORT") - - (status, fvs) = tbl.get("Ethernet0") - - assert status == True - - oper_status = "unknown" - - for v in fvs: - if v[0] == "oper_status": - oper_status = v[1] - break - - assert oper_status == "down" - - dvs.servers[0].runcmd("ip link set up dev eth0") == 0 - - time.sleep(1) - - (status, fvs) = tbl.get("Ethernet0") - - assert status == True - - oper_status = "unknown" - - for v in fvs: - if v[0] == "oper_status": - oper_status = v[1] - break - - assert oper_status == "up" - - # set fec - fvs = swsscommon.FieldValuePairs([("fec","rs"), ("speed", "1000")]) - ptbl.set("Ethernet0", fvs) - - time.sleep(1) - - # get fec - (status, fvs) = atbl.get(dvs.asicdb.portnamemap["Ethernet0"]) - assert status == True - - for fv in fvs: - if fv[0] == "SAI_PORT_ATTR_FEC_MODE": - assert fv[1] == "SAI_PORT_FEC_MODE_RS" - assert fv[0] != "SAI_PORT_ATTR_AUTO_NEG_FEC_MODE_OVERRIDE" - - def test_PortPreemp(self, dvs, testlog): - - pre_name = 'preemphasis' - pre_val = [0x1234,0x2345,0x3456,0x4567] - pre_val_str = str(hex(pre_val[0])) + "," + str(hex(pre_val[1]))+ "," + \ - str(hex(pre_val[2]))+ "," + str(hex(pre_val[3])) - - pre_val_asic = '4:' + str(pre_val[0]) + "," + str(pre_val[1]) + "," + \ - str(pre_val[2]) + "," + str(pre_val[3]) - fvs = swsscommon.FieldValuePairs([(pre_name, pre_val_str)]) - db = swsscommon.DBConnector(0, dvs.redis_sock, 0) - adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - - tbl = swsscommon.Table(db, "PORT_TABLE") - ptbl = swsscommon.ProducerStateTable(db, "PORT_TABLE") - atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_PORT") - - ptbl.set("Ethernet0", fvs) - - - time.sleep(1) - - # get fec - (status, fvs) = atbl.get(dvs.asicdb.portnamemap["Ethernet0"]) - assert status == True - - for fv in fvs: - if fv[0] == "SAI_PORT_ATTR_SERDES_PREEMPHASIS": - assert fv[1] == pre_val_asic - - def test_PortIdriver(self, dvs, testlog): - - idrv_name = 'idriver' - idrv_val = [0x1,0x1,0x2,0x2] - idrv_val_str = str(hex(idrv_val[0])) + "," + str(hex(idrv_val[1]))+ "," + \ - str(hex(idrv_val[2]))+ "," + str(hex(idrv_val[3])) - - idrv_val_asic = '4:' + str(idrv_val[0]) + "," + str(idrv_val[1]) + "," + \ - str(idrv_val[2]) + "," + str(idrv_val[3]) - fvs = swsscommon.FieldValuePairs([(idrv_name, idrv_val_str)]) - db = swsscommon.DBConnector(0, dvs.redis_sock, 0) - adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - - tbl = swsscommon.Table(db, "PORT_TABLE") - ptbl = swsscommon.ProducerStateTable(db, "PORT_TABLE") - atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_PORT") - - ptbl.set("Ethernet0", fvs) - - - time.sleep(1) - - # get fec - (status, fvs) = atbl.get(dvs.asicdb.portnamemap["Ethernet0"]) - assert status == True - - for fv in fvs: - if fv[0] == "SAI_PORT_ATTR_SERDES_IDRIVER": - assert fv[1] == idrv_val_asic - - def test_PortIpredriver(self, dvs, testlog): - - ipre_name = 'ipredriver' - ipre_val = [0x2,0x3,0x4,0x5] - ipre_val_str = str(hex(ipre_val[0])) + "," + str(hex(ipre_val[1]))+ "," + \ - str(hex(ipre_val[2]))+ "," + str(hex(ipre_val[3])) - - ipre_val_asic = '4:' + str(ipre_val[0]) + "," + str(ipre_val[1]) + "," + \ - str(ipre_val[2]) + "," + str(ipre_val[3]) - fvs = swsscommon.FieldValuePairs([(ipre_name, ipre_val_str)]) - db = swsscommon.DBConnector(0, dvs.redis_sock, 0) - adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - - tbl = swsscommon.Table(db, "PORT_TABLE") - ptbl = swsscommon.ProducerStateTable(db, "PORT_TABLE") - atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_PORT") - - ptbl.set("Ethernet0", fvs) - - - time.sleep(1) - - # get fec - (status, fvs) = atbl.get(dvs.asicdb.portnamemap["Ethernet0"]) - assert status == True - - for fv in fvs: - if fv[0] == "SAI_PORT_ATTR_SERDES_IPREDRIVER": - assert fv[1] == ipre_val_asic - - def test_PortHostif(self, dvs): - adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_HOSTIF") - host_intfs = atbl.getKeys() - for intf in host_intfs: - status, fvs = atbl.get(intf) - assert status, "Error getting value for key" - attributes = dict(fvs) - hostif_queue = attributes.get("SAI_HOSTIF_ATTR_QUEUE") - assert hostif_queue == "7" - - def test_PortHostTxSignalSet(self, dvs, testlog): - adb = dvs.get_asic_db() - statedb = dvs.get_state_db() - - transceiver_info_tbl = swsscommon.Table(statedb.db_connection, "TRANSCEIVER_INFO") - fvs = swsscommon.FieldValuePairs([("supported_max_tx_power","N/A")]) - transceiver_info_tbl.set("Ethernet0", fvs) - - port_oid = adb.port_name_map["Ethernet0"] - expected_fields = {"SAI_PORT_ATTR_HOST_TX_SIGNAL_ENABLE":"true"} - adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) - - transceiver_info_tbl.hdel("Ethernet0", "supported_max_tx_power") - expected_fields = {"SAI_PORT_ATTR_HOST_TX_SIGNAL_ENABLE":"false"} - adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_port_add_remove.py b/tests/test_port_add_remove.py deleted file mode 100644 index 54cd6599c9..0000000000 --- a/tests/test_port_add_remove.py +++ /dev/null @@ -1,525 +0,0 @@ -import pytest -import time -import buffer_model -from dvslib.dvs_common import PollingConfig - -# the port to be removed and add -PORT_A = "Ethernet64" -PORT_B = "Ethernet68" - -""" -DELETE_CREATE_ITERATIONS defines the number of iteration of delete and create to ports, -we add different timeouts between delete/create to catch potential race condition that can lead to system crush - -Add \ Remove of Buffers can be done only when the model is dynamic. -""" -DELETE_CREATE_ITERATIONS = 10 - -@pytest.yield_fixture -def dynamic_buffer(dvs): - buffer_model.enable_dynamic_buffer(dvs.get_config_db(), dvs.runcmd) - yield - buffer_model.disable_dynamic_buffer(dvs.get_config_db(), dvs.runcmd) - - -@pytest.mark.usefixtures('dvs_port_manager') -@pytest.mark.usefixtures("dynamic_buffer") -class TestPortAddRemove(object): - - def set_mmu(self,dvs): - state_db = dvs.get_state_db() - # set mmu size - fvs = {"mmu_size": "12766208"} - state_db.create_entry("BUFFER_MAX_PARAM_TABLE", "global", fvs) - - - def test_remove_add_remove_port_with_buffer_cfg(self, dvs, testlog): - config_db = dvs.get_config_db() - asic_db = dvs.get_asic_db() - state_db = dvs.get_state_db() - app_db = dvs.get_app_db() - - # set mmu size - self.set_mmu(dvs) - - # Startup interface - dvs.port_admin_set(PORT_A, 'up') - - # get port info - port_info = config_db.get_entry("PORT", PORT_A) - - # get the number of ports before removal - num_of_ports = len(asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_PORT")) - - # remove buffer pg cfg for the port (record the buffer pgs before removing them) - pgs = config_db.get_keys('BUFFER_PG') - buffer_pgs = {} - for key in pgs: - if PORT_A in key: - buffer_pgs[key] = config_db.get_entry('BUFFER_PG', key) - config_db.delete_entry('BUFFER_PG', key) - app_db.wait_for_deleted_entry("BUFFER_PG_TABLE", key) - - # modify buffer queue entry to egress_lossless_profile instead of egress_lossy_profile - config_db.update_entry("BUFFER_QUEUE", "%s|0-2"%PORT_A, {"profile": "egress_lossless_profile"}) - - # remove buffer queue cfg for the port - queues = config_db.get_keys('BUFFER_QUEUE') - buffer_queues = {} - for key in queues: - if PORT_A in key: - buffer_queues[key] = config_db.get_entry('BUFFER_QUEUE', key) - config_db.delete_entry('BUFFER_QUEUE', key) - app_db.wait_for_deleted_entry('BUFFER_QUEUE_TABLE', key) - - # Shutdown interface - dvs.port_admin_set(PORT_A, 'down') - - # try to remove this port - config_db.delete_entry('PORT', PORT_A) - num = asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_PORT", - num_of_ports-1, - polling_config = PollingConfig(polling_interval = 1, timeout = 5.00, strict = True)) - - # verify that the port was removed properly since all buffer configuration was removed also - assert len(num) == num_of_ports - 1 - - # set back the port - config_db.update_entry("PORT", PORT_A, port_info) - - # verify that the port has been readded - num = asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_PORT", - num_of_ports, - polling_config = PollingConfig(polling_interval = 1, timeout = 5.00, strict = True)) - - assert len(num) == num_of_ports - - # re-add buffer pg and queue cfg to the port - for key, pg in buffer_pgs.items(): - config_db.update_entry("BUFFER_PG", key, pg) - - for key, queue in buffer_queues.items(): - config_db.update_entry("BUFFER_QUEUE", key, queue) - - time.sleep(5) - - # Remove the port with buffer configuration - config_db.delete_entry('PORT', PORT_A) - num = asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_PORT", - num_of_ports-1, - polling_config = PollingConfig(polling_interval = 1, timeout = 5.00, strict = False)) - - # verify that the port wasn't removed since we still have buffer cfg - assert len(num) == num_of_ports - - # Remove buffer pgs - for key in buffer_pgs.keys(): - config_db.delete_entry('BUFFER_PG', key) - app_db.wait_for_deleted_entry("BUFFER_PG_TABLE", key) - - num = asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_PORT", - num_of_ports-1, - polling_config = PollingConfig(polling_interval = 1, timeout = 5.00, strict = False)) - - # verify that the port wasn't removed since we still have buffer cfg - assert len(num) == num_of_ports - - # Remove buffer queue - for key in buffer_queues.keys(): - config_db.delete_entry('BUFFER_QUEUE', key) - app_db.wait_for_deleted_entry('BUFFER_QUEUE_TABLE', key) - - num = asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_PORT", - num_of_ports-1, - polling_config = PollingConfig(polling_interval = 1, timeout = 5.00, strict = True)) - - # verify that the port wasn't removed since we still have buffer cfg - assert len(num) == num_of_ports - 1 - - # set back the port as it is required for next test - config_db.update_entry("PORT", PORT_A, port_info) - - - - @pytest.mark.parametrize("scenario", ["one_port", "all_ports"]) - def test_add_remove_all_the_ports(self, dvs, testlog, scenario): - config_db = dvs.get_config_db() - state_db = dvs.get_state_db() - asic_db = dvs.get_asic_db() - app_db = dvs.get_app_db() - - # set mmu size - self.set_mmu(dvs) - - # get the number of ports before removal - num_of_ports = len(asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_PORT")) - - # remove buffer pg cfg for the port - if scenario == "all_ports": - ports = config_db.get_keys('PORT') - elif scenario == "one_port": - ports = [PORT_A] - else: - assert False - - # delete all PGs and QUEUEs from the relevant ports - pgs = config_db.get_keys('BUFFER_PG') - queues = config_db.get_keys('BUFFER_QUEUE') - - for port in ports: - for key in pgs: - if port in key: - config_db.delete_entry('BUFFER_PG', key) - app_db.wait_for_deleted_entry('BUFFER_PG_TABLE', key) - - for key in queues: - if port in key: - config_db.delete_entry('BUFFER_QUEUE', key) - app_db.wait_for_deleted_entry('BUFFER_QUEUE_TABLE', key) - - ports_info = {} - - for key in ports: - # read port info and save it - ports_info[key] = config_db.get_entry("PORT", key) - - - for i in range(DELETE_CREATE_ITERATIONS): - # remove ports - for key in ports: - config_db.delete_entry('PORT',key) - app_db.wait_for_deleted_entry("PORT_TABLE", key) - - # verify remove port - num = asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_PORT", - num_of_ports-len(ports)) - - assert len(num) == num_of_ports-len(ports) - - # add port - """ - DELETE_CREATE_ITERATIONS defines the number of iteration of delete and create to ports, - we add different timeouts between delete/create to catch potential race condition that can lead to system crush. - """ - time.sleep(i%3) - for key in ports: - config_db.update_entry("PORT", key, ports_info[key]) - app_db.wait_for_entry('PORT_TABLE',key) - - # verify add port - num = asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_PORT", - num_of_ports) - - assert len(num) == num_of_ports - - time.sleep((i%2)+1) - - # run ping - dvs.setup_db() - - dvs.create_vlan("6") - dvs.create_vlan_member("6", PORT_A) - dvs.create_vlan_member("6", PORT_B) - - port_entry_a = state_db.get_entry("PORT_TABLE",PORT_A) - port_entry_b = state_db.get_entry("PORT_TABLE",PORT_B) - port_admin_a = port_entry_a['admin_status'] - port_admin_b = port_entry_b['admin_status'] - - dvs.set_interface_status("Vlan6", "up") - dvs.add_ip_address("Vlan6", "6.6.6.1/24") - dvs.set_interface_status(PORT_A, "up") - dvs.set_interface_status(PORT_B, "up") - - dvs.servers[16].runcmd("ifconfig eth0 6.6.6.6/24 up") - dvs.servers[16].runcmd("ip route add default via 6.6.6.1") - dvs.servers[17].runcmd("ifconfig eth0 6.6.6.7/24 up") - dvs.servers[17].runcmd("ip route add default via 6.6.6.1") - - time.sleep(2) - - rc = dvs.servers[16].runcmd("ping -c 1 6.6.6.7") - assert rc == 0 - - rc = dvs.servers[17].runcmd("ping -c 1 6.6.6.6") - assert rc == 0 - - dvs.set_interface_status(PORT_A, port_admin_a) - dvs.set_interface_status(PORT_B, port_admin_b) - dvs.remove_vlan_member("6", PORT_A) - dvs.remove_vlan_member("6", PORT_B) - dvs.remove_ip_address("Vlan6", "6.6.6.1/24") - dvs.remove_vlan("6") - - -@pytest.mark.usefixtures("dynamic_buffer") -@pytest.mark.usefixtures("dvs_port_manager") -class TestPortAddRemoveDup(object): - def test_add_remove_with_dup_lanes(self, testlog, dvs): - config_db = dvs.get_config_db() - app_db = dvs.get_app_db() - state_db = dvs.get_state_db() - - # set mmu size - fvs = {"mmu_size": "12766208"} - state_db.create_entry("BUFFER_MAX_PARAM_TABLE", "global", fvs) - - # get port count - port_count = len(self.dvs_port.get_port_ids()) - - # get port info - port_info = config_db.get_entry("PORT", PORT_A) - - # remove buffer pg cfg for the port - pgs = config_db.get_keys("BUFFER_PG") - buffer_pgs = {} - for key in pgs: - if PORT_A in key: - buffer_pgs[key] = config_db.get_entry("BUFFER_PG", key) - config_db.delete_entry("BUFFER_PG", key) - app_db.wait_for_deleted_entry("BUFFER_PG_TABLE", key.replace(config_db.separator, app_db.separator)) - - # remove buffer queue cfg for the port - queues = config_db.get_keys("BUFFER_QUEUE") - buffer_queues = {} - for key in queues: - if PORT_A in key: - buffer_queues[key] = config_db.get_entry("BUFFER_QUEUE", key) - config_db.delete_entry("BUFFER_QUEUE", key) - app_db.wait_for_deleted_entry("BUFFER_QUEUE_TABLE", key.replace(config_db.separator, app_db.separator)) - - # shutdown port - dvs.port_admin_set(PORT_A, "down") - - # remove port - self.dvs_port.remove_port_generic(PORT_A) - self.dvs_port.verify_port_count(port_count-1) - - # make port config with duplicate lanes - dup_lanes = port_info["lanes"] - dup_lanes += ",{}".format(port_info["lanes"].split(",")[-1]) - - # add port - self.dvs_port.create_port_generic(PORT_A, dup_lanes, port_info["speed"]) - self.dvs_port.verify_port_count(port_count) - - # shutdown port - dvs.port_admin_set(PORT_A, "down") - - # remove port - self.dvs_port.remove_port_generic(PORT_A) - self.dvs_port.verify_port_count(port_count-1) - - # make port config - port_lanes = port_info.pop("lanes") - port_speed = port_info.pop("speed") - - # re-add port - self.dvs_port.create_port_generic(PORT_A, port_lanes, port_speed, port_info) - self.dvs_port.verify_port_count(port_count) - - # re-add buffer pg and queue cfg to the port - for key, pg in buffer_pgs.items(): - config_db.update_entry("BUFFER_PG", key, pg) - app_db.wait_for_entry("BUFFER_PG_TABLE", key.replace(config_db.separator, app_db.separator)) - - for key, queue in buffer_queues.items(): - config_db.update_entry("BUFFER_QUEUE", key, queue) - app_db.wait_for_entry("BUFFER_QUEUE_TABLE", key.replace(config_db.separator, app_db.separator)) - - -@pytest.mark.usefixtures("dvs_port_manager") -class TestPortAddRemoveInvalidMandatoryParam(object): - @pytest.mark.parametrize( - "port,lanes,speed", [ - pytest.param("Ethernet1000", "", "10000", id="empty-lanes-list"), - pytest.param("Ethernet1004", "1004,x,1006,1007", "10000", id="invalid-lanes-list"), - pytest.param("Ethernet1008", "1008,1009,1010,1011", "", id="empty-speed"), - pytest.param("Ethernet1012", "1012,1013,1014,1015", "invalid", id="invalid-speed"), - pytest.param("Ethernet1016", "1016,1017,1018,1019", "0", id="out-of-range-speed") - ] - ) - def test_add_remove_neg(self, testlog, port, lanes, speed): - # get port count - port_asicdb_count = len(self.dvs_port.get_port_ids(dbid=self.dvs_port.ASIC_DB)) - port_appdb_count = len(self.dvs_port.get_port_ids(dbid=self.dvs_port.APPL_DB)) - - # add port - self.dvs_port.create_port_generic(port, lanes, speed) - self.dvs_port.verify_port_count(port_appdb_count+1, self.dvs_port.APPL_DB) - self.dvs_port.verify_port_count(port_asicdb_count, self.dvs_port.ASIC_DB) - - # remove port - self.dvs_port.remove_port_generic(port) - self.dvs_port.verify_port_count(port_appdb_count, self.dvs_port.APPL_DB) - self.dvs_port.verify_port_count(port_asicdb_count, self.dvs_port.ASIC_DB) - - -@pytest.mark.usefixtures("dvs_port_manager") -class TestPortAddRemoveInvalidSerdesParam(object): - @pytest.fixture(scope="class") - def port_attr(self): - meta_dict = { - "port": "Ethernet1000", - "lanes": "1000,1001,1002,1003", - "speed": "100000", - "port_asicdb_count": len(self.dvs_port.get_port_ids(dbid=self.dvs_port.ASIC_DB)), - "port_appdb_count": len(self.dvs_port.get_port_ids(dbid=self.dvs_port.APPL_DB)) - } - yield meta_dict - - def verify_add_remove(self, attr, qualifiers): - # add port - self.dvs_port.create_port_generic(attr["port"], attr["lanes"], attr["speed"], qualifiers) - self.dvs_port.verify_port_count(attr["port_appdb_count"]+1, self.dvs_port.APPL_DB) - self.dvs_port.verify_port_count(attr["port_asicdb_count"], self.dvs_port.ASIC_DB) - - # remove port - self.dvs_port.remove_port_generic(attr["port"]) - self.dvs_port.verify_port_count(attr["port_appdb_count"], self.dvs_port.APPL_DB) - self.dvs_port.verify_port_count(attr["port_asicdb_count"], self.dvs_port.ASIC_DB) - - @pytest.mark.parametrize( - "serdes", [ - pytest.param("preemphasis", id="preemphasis"), - pytest.param("idriver", id="idriver"), - pytest.param("ipredriver", id="ipredriver"), - pytest.param("pre1", id="pre1"), - pytest.param("pre2", id="pre2"), - pytest.param("pre3", id="pre3"), - pytest.param("main", id="main"), - pytest.param("post1", id="post1"), - pytest.param("post2", id="post2"), - pytest.param("post3", id="post3"), - pytest.param("attn", id="attn") - ] - ) - def test_add_remove_neg(self, testlog, port_attr, serdes): - qualifiers = { serdes: "" } - self.verify_add_remove(port_attr, qualifiers) - - qualifiers = { serdes: "invalid" } - self.verify_add_remove(port_attr, qualifiers) - - -@pytest.mark.usefixtures("dvs_port_manager") -class TestPortAddRemoveInvalidParam(object): - def verify_add_remove(self, qualifiers): - port = "Ethernet1000" - lanes = "1000,1001,1002,1003" - speed = "100000" - - # get port count - port_asicdb_count = len(self.dvs_port.get_port_ids(dbid=self.dvs_port.ASIC_DB)) - port_appdb_count = len(self.dvs_port.get_port_ids(dbid=self.dvs_port.APPL_DB)) - - # add port - self.dvs_port.create_port_generic(port, lanes, speed, qualifiers) - self.dvs_port.verify_port_count(port_appdb_count+1, self.dvs_port.APPL_DB) - self.dvs_port.verify_port_count(port_asicdb_count, self.dvs_port.ASIC_DB) - - # remove port - self.dvs_port.remove_port_generic(port) - self.dvs_port.verify_port_count(port_appdb_count, self.dvs_port.APPL_DB) - self.dvs_port.verify_port_count(port_asicdb_count, self.dvs_port.ASIC_DB) - - def test_add_remove_neg_alias(self, testlog): - qualifiers = { "alias": "" } - self.verify_add_remove(qualifiers) - - def test_add_remove_neg_index(self, testlog): - qualifiers = { "index": "" } - self.verify_add_remove(qualifiers) - - qualifiers = { "index": "invalid" } - self.verify_add_remove(qualifiers) - - def test_add_remove_neg_autoneg(self, testlog): - qualifiers = { "autoneg": "" } - self.verify_add_remove(qualifiers) - - qualifiers = { "autoneg": "invalid" } - self.verify_add_remove(qualifiers) - - def test_add_remove_neg_adv_speeds(self, testlog): - qualifiers = { "adv_speeds": "" } - self.verify_add_remove(qualifiers) - - qualifiers = { "adv_speeds": "0" } - self.verify_add_remove(qualifiers) - - qualifiers = { "adv_speeds": "invalid" } - self.verify_add_remove(qualifiers) - - def test_add_remove_neg_interface_type(self, testlog): - qualifiers = { "interface_type": "" } - self.verify_add_remove(qualifiers) - - qualifiers = { "interface_type": "invalid" } - self.verify_add_remove(qualifiers) - - def test_add_remove_neg_adv_interface_types(self, testlog): - qualifiers = { "adv_interface_types": "" } - self.verify_add_remove(qualifiers) - - qualifiers = { "adv_interface_types": "invalid" } - self.verify_add_remove(qualifiers) - - def test_add_remove_neg_fec(self, testlog): - qualifiers = { "fec": "" } - self.verify_add_remove(qualifiers) - - qualifiers = { "fec": "invalid" } - self.verify_add_remove(qualifiers) - - def test_add_remove_neg_mtu(self, testlog): - qualifiers = { "mtu": "" } - self.verify_add_remove(qualifiers) - - qualifiers = { "mtu": "0" } - self.verify_add_remove(qualifiers) - - qualifiers = { "mtu": "invalid" } - self.verify_add_remove(qualifiers) - - def test_add_remove_neg_tpid(self, testlog): - qualifiers = { "tpid": "" } - self.verify_add_remove(qualifiers) - - qualifiers = { "tpid": "invalid" } - self.verify_add_remove(qualifiers) - - def test_add_remove_neg_pfc_asym(self, testlog): - qualifiers = { "pfc_asym": "" } - self.verify_add_remove(qualifiers) - - qualifiers = { "pfc_asym": "invalid" } - self.verify_add_remove(qualifiers) - - def test_add_remove_neg_learn_mode(self, testlog): - qualifiers = { "learn_mode": "" } - self.verify_add_remove(qualifiers) - - qualifiers = { "learn_mode": "invalid" } - self.verify_add_remove(qualifiers) - - def test_add_remove_neg_link_training(self, testlog): - qualifiers = { "link_training": "" } - self.verify_add_remove(qualifiers) - - qualifiers = { "link_training": "invalid" } - self.verify_add_remove(qualifiers) - - def test_add_remove_neg_role(self, testlog): - qualifiers = { "role": "" } - self.verify_add_remove(qualifiers) - - qualifiers = { "role": "invalid" } - self.verify_add_remove(qualifiers) - - def test_add_remove_neg_admin_status(self, testlog): - qualifiers = { "admin_status": "" } - self.verify_add_remove(qualifiers) - - qualifiers = { "admin_status": "invalid" } - self.verify_add_remove(qualifiers) diff --git a/tests/test_port_an.py b/tests/test_port_an.py deleted file mode 100644 index 5356d2e837..0000000000 --- a/tests/test_port_an.py +++ /dev/null @@ -1,359 +0,0 @@ -import time -import os -import pytest - -from swsscommon import swsscommon - - -class TestPortAutoNeg(object): - def test_PortAutoNegForce(self, dvs, testlog): - - db = swsscommon.DBConnector(0, dvs.redis_sock, 0) - adb = dvs.get_asic_db() - - tbl = swsscommon.ProducerStateTable(db, "PORT_TABLE") - fvs = swsscommon.FieldValuePairs([("autoneg","off")]) - tbl.set("Ethernet0", fvs) - - tbl = swsscommon.ProducerStateTable(db, "PORT_TABLE") - fvs = swsscommon.FieldValuePairs([("autoneg","on"), ("speed", "1000")]) - tbl.set("Ethernet4", fvs) - - # validate if autoneg false is pushed to asic db when set first time - port_oid = adb.port_name_map["Ethernet0"] - expected_fields = {"SAI_PORT_ATTR_AUTO_NEG_MODE":"false"} - adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) - - # validate if autoneg true is pushed to asic db when set first time - port_oid = adb.port_name_map["Ethernet4"] - expected_fields = {"SAI_PORT_ATTR_AUTO_NEG_MODE":"true"} - adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) - - def test_PortAutoNegCold(self, dvs, testlog): - db = swsscommon.DBConnector(0, dvs.redis_sock, 0) - - tbl = swsscommon.ProducerStateTable(db, "PORT_TABLE") - - # set autoneg = true and adv_speeds = 1000 - fvs = swsscommon.FieldValuePairs([("autoneg","on"), ("adv_speeds", "1000")]) - - tbl.set("Ethernet0", fvs) - - time.sleep(1) - - adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - - atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_PORT") - (status, fvs) = atbl.get(dvs.asicdb.portnamemap["Ethernet0"]) - assert status == True - - assert "SAI_PORT_ATTR_AUTO_NEG_MODE" in [fv[0] for fv in fvs] - assert "SAI_PORT_ATTR_ADVERTISED_SPEED" in [fv[0] for fv in fvs] - for fv in fvs: - if fv[0] == "SAI_PORT_ATTR_AUTO_NEG_MODE": - assert fv[1] == "true" - elif fv[0] == "SAI_PORT_ATTR_ADVERTISED_SPEED": - assert fv[1] == "1:1000" - - # set adv_speeds = 100,1000 - fvs = swsscommon.FieldValuePairs([("adv_speeds", "100,1000")]) - - tbl.set("Ethernet0", fvs) - - time.sleep(1) - - (status, fvs) = atbl.get(dvs.asicdb.portnamemap["Ethernet0"]) - assert status == True - - assert "SAI_PORT_ATTR_AUTO_NEG_MODE" in [fv[0] for fv in fvs] - assert "SAI_PORT_ATTR_ADVERTISED_SPEED" in [fv[0] for fv in fvs] - for fv in fvs: - if fv[0] == "SAI_PORT_ATTR_AUTO_NEG_MODE": - assert fv[1] == "true" - elif fv[0] == "SAI_PORT_ATTR_ADVERTISED_SPEED": - assert fv[1] == "2:100,1000" - - # set adv_interface_types = CR2 - fvs = swsscommon.FieldValuePairs([("adv_interface_types", "CR2")]) - - tbl.set("Ethernet0", fvs) - - time.sleep(1) - - (status, fvs) = atbl.get(dvs.asicdb.portnamemap["Ethernet0"]) - assert status == True - - assert "SAI_PORT_ATTR_AUTO_NEG_MODE" in [fv[0] for fv in fvs] - assert "SAI_PORT_ATTR_ADVERTISED_SPEED" in [fv[0] for fv in fvs] - assert "SAI_PORT_ATTR_ADVERTISED_INTERFACE_TYPE" in [fv[0] for fv in fvs] - for fv in fvs: - if fv[0] == "SAI_PORT_ATTR_AUTO_NEG_MODE": - assert fv[1] == "true" - elif fv[0] == "SAI_PORT_ATTR_ADVERTISED_SPEED": - assert fv[1] == "2:100,1000" - elif fv[0] == "SAI_PORT_ATTR_ADVERTISED_INTERFACE_TYPE": - assert fv[1] == "1:SAI_PORT_INTERFACE_TYPE_CR2" - - # set adv_interface_types = CR2,CR4 - fvs = swsscommon.FieldValuePairs([("adv_interface_types", "CR2,CR4")]) - - tbl.set("Ethernet0", fvs) - - time.sleep(1) - - (status, fvs) = atbl.get(dvs.asicdb.portnamemap["Ethernet0"]) - assert status == True - - assert "SAI_PORT_ATTR_AUTO_NEG_MODE" in [fv[0] for fv in fvs] - assert "SAI_PORT_ATTR_ADVERTISED_SPEED" in [fv[0] for fv in fvs] - assert "SAI_PORT_ATTR_ADVERTISED_INTERFACE_TYPE" in [fv[0] for fv in fvs] - for fv in fvs: - if fv[0] == "SAI_PORT_ATTR_AUTO_NEG_MODE": - assert fv[1] == "true" - elif fv[0] == "SAI_PORT_ATTR_ADVERTISED_SPEED": - assert fv[1] == "2:100,1000" - elif fv[0] == "SAI_PORT_ATTR_ADVERTISED_INTERFACE_TYPE": - assert fv[1] == "2:SAI_PORT_INTERFACE_TYPE_CR2,SAI_PORT_INTERFACE_TYPE_CR4" - - # change autoneg to false - fvs = swsscommon.FieldValuePairs([("autoneg","off"), ("speed", "100")]) - - tbl.set("Ethernet0", fvs) - - time.sleep(1) - - (status, fvs) = atbl.get(dvs.asicdb.portnamemap["Ethernet0"]) - assert status == True - - assert "SAI_PORT_ATTR_AUTO_NEG_MODE" in [fv[0] for fv in fvs] - assert "SAI_PORT_ATTR_ADVERTISED_SPEED" in [fv[0] for fv in fvs] - assert "SAI_PORT_ATTR_ADVERTISED_INTERFACE_TYPE" in [fv[0] for fv in fvs] - assert "SAI_PORT_ATTR_SPEED" in [fv[0] for fv in fvs] - for fv in fvs: - if fv[0] == "SAI_PORT_ATTR_AUTO_NEG_MODE": - assert fv[1] == "false" - elif fv[0] == "SAI_PORT_ATTR_ADVERTISED_SPEED": - assert fv[1] == "2:100,1000" - elif fv[0] == "SAI_PORT_ATTR_SPEED": - assert fv[1] == "100" - elif fv[0] == "SAI_PORT_ATTR_ADVERTISED_INTERFACE_TYPE": - assert fv[1] == "2:SAI_PORT_INTERFACE_TYPE_CR2,SAI_PORT_INTERFACE_TYPE_CR4" - - # set speed = 1000 - fvs = swsscommon.FieldValuePairs([("speed", "1000")]) - - tbl.set("Ethernet0", fvs) - - time.sleep(1) - - (status, fvs) = atbl.get(dvs.asicdb.portnamemap["Ethernet0"]) - assert status == True - - assert "SAI_PORT_ATTR_AUTO_NEG_MODE" in [fv[0] for fv in fvs] - assert "SAI_PORT_ATTR_ADVERTISED_SPEED" in [fv[0] for fv in fvs] - assert "SAI_PORT_ATTR_ADVERTISED_INTERFACE_TYPE" in [fv[0] for fv in fvs] - assert "SAI_PORT_ATTR_SPEED" in [fv[0] for fv in fvs] - for fv in fvs: - if fv[0] == "SAI_PORT_ATTR_AUTO_NEG_MODE": - assert fv[1] == "false" - elif fv[0] == "SAI_PORT_ATTR_ADVERTISED_SPEED": - assert fv[1] == "2:100,1000" - elif fv[0] == "SAI_PORT_ATTR_SPEED": - assert fv[1] == "1000" - elif fv[0] == "SAI_PORT_ATTR_ADVERTISED_INTERFACE_TYPE": - assert fv[1] == "2:SAI_PORT_INTERFACE_TYPE_CR2,SAI_PORT_INTERFACE_TYPE_CR4" - - # set interface_type = CR4 - fvs = swsscommon.FieldValuePairs([("interface_type", "CR4")]) - tbl.set("Ethernet0", fvs) - - time.sleep(1) - - (status, fvs) = atbl.get(dvs.asicdb.portnamemap["Ethernet0"]) - assert status == True - - assert "SAI_PORT_ATTR_AUTO_NEG_MODE" in [fv[0] for fv in fvs] - assert "SAI_PORT_ATTR_ADVERTISED_SPEED" in [fv[0] for fv in fvs] - assert "SAI_PORT_ATTR_ADVERTISED_INTERFACE_TYPE" in [fv[0] for fv in fvs] - assert "SAI_PORT_ATTR_SPEED" in [fv[0] for fv in fvs] - assert "SAI_PORT_ATTR_INTERFACE_TYPE" in [fv[0] for fv in fvs] - for fv in fvs: - if fv[0] == "SAI_PORT_ATTR_AUTO_NEG_MODE": - assert fv[1] == "false" - elif fv[0] == "SAI_PORT_ATTR_ADVERTISED_SPEED": - assert fv[1] == "2:100,1000" - elif fv[0] == "SAI_PORT_ATTR_SPEED": - assert fv[1] == "1000" - elif fv[0] == "SAI_PORT_ATTR_ADVERTISED_INTERFACE_TYPE": - assert fv[1] == "2:SAI_PORT_INTERFACE_TYPE_CR2,SAI_PORT_INTERFACE_TYPE_CR4" - elif fv[0] == "SAI_PORT_ATTR_INTERFACE_TYPE": - assert fv[1] == "SAI_PORT_INTERFACE_TYPE_CR4" - - # set interface_type = CR2 - fvs = swsscommon.FieldValuePairs([("interface_type", "CR2")]) - tbl.set("Ethernet0", fvs) - - time.sleep(1) - - (status, fvs) = atbl.get(dvs.asicdb.portnamemap["Ethernet0"]) - assert status == True - - assert "SAI_PORT_ATTR_AUTO_NEG_MODE" in [fv[0] for fv in fvs] - assert "SAI_PORT_ATTR_ADVERTISED_SPEED" in [fv[0] for fv in fvs] - assert "SAI_PORT_ATTR_ADVERTISED_INTERFACE_TYPE" in [fv[0] for fv in fvs] - assert "SAI_PORT_ATTR_SPEED" in [fv[0] for fv in fvs] - assert "SAI_PORT_ATTR_INTERFACE_TYPE" in [fv[0] for fv in fvs] - for fv in fvs: - if fv[0] == "SAI_PORT_ATTR_AUTO_NEG_MODE": - assert fv[1] == "false" - elif fv[0] == "SAI_PORT_ATTR_ADVERTISED_SPEED": - assert fv[1] == "2:100,1000" - elif fv[0] == "SAI_PORT_ATTR_SPEED": - assert fv[1] == "1000" - elif fv[0] == "SAI_PORT_ATTR_ADVERTISED_INTERFACE_TYPE": - assert fv[1] == "2:SAI_PORT_INTERFACE_TYPE_CR2,SAI_PORT_INTERFACE_TYPE_CR4" - elif fv[0] == "SAI_PORT_ATTR_INTERFACE_TYPE": - assert fv[1] == "SAI_PORT_INTERFACE_TYPE_CR2" - - def test_PortAutoNegWarm(self, dvs, testlog): - - db = swsscommon.DBConnector(0, dvs.redis_sock, 0) - cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) - sdb = swsscommon.DBConnector(6, dvs.redis_sock, 0) - - tbl = swsscommon.ProducerStateTable(db, "PORT_TABLE") - ctbl = swsscommon.Table(cdb, "PORT") - stbl = swsscommon.Table(sdb, "PORT_TABLE") - - # set autoneg = true and speed = 1000 - fvs = swsscommon.FieldValuePairs([("autoneg","on"), - ("adv_speeds", "100,1000"), - ("adv_interface_types", "CR2,CR4")]) - ctbl.set("Ethernet0", fvs) - - time.sleep(1) - - adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - - atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_PORT") - (status, fvs) = atbl.get(dvs.asicdb.portnamemap["Ethernet0"]) - assert status == True - - assert "SAI_PORT_ATTR_AUTO_NEG_MODE" in [fv[0] for fv in fvs] - assert "SAI_PORT_ATTR_ADVERTISED_SPEED" in [fv[0] for fv in fvs] - assert "SAI_PORT_ATTR_ADVERTISED_INTERFACE_TYPE" in [fv[0] for fv in fvs] - for fv in fvs: - if fv[0] == "SAI_PORT_ATTR_AUTO_NEG_MODE": - assert fv[1] == "true" - elif fv[0] == "SAI_PORT_ATTR_ADVERTISED_SPEED": - assert fv[1] == "2:100,1000" - elif fv[0] == "SAI_PORT_ATTR_ADVERTISED_INTERFACE_TYPE": - assert fv[1] == "2:SAI_PORT_INTERFACE_TYPE_CR2,SAI_PORT_INTERFACE_TYPE_CR4" - - # set admin up - cfvs = swsscommon.FieldValuePairs([("admin_status", "up")]) - ctbl.set("Ethernet0", cfvs) - - - dvs.warm_restart_swss("true") - - # freeze orchagent for warm restart - (exitcode, result) = dvs.runcmd("/usr/bin/orchagent_restart_check", include_stderr=False) - assert result == "RESTARTCHECK succeeded\n" - time.sleep(2) - - try: - # restart orchagent - # clean port state - dvs.stop_swss() - ports = stbl.getKeys() - for port in ports: - stbl._del(port) - dvs.start_swss() - time.sleep(2) - - # check ASIC DB after warm restart - (status, fvs) = atbl.get(dvs.asicdb.portnamemap["Ethernet0"]) - assert status == True - - assert "SAI_PORT_ATTR_AUTO_NEG_MODE" in [fv[0] for fv in fvs] - assert "SAI_PORT_ATTR_ADVERTISED_SPEED" in [fv[0] for fv in fvs] - assert "SAI_PORT_ATTR_ADVERTISED_INTERFACE_TYPE" in [fv[0] for fv in fvs] - for fv in fvs: - if fv[0] == "SAI_PORT_ATTR_AUTO_NEG_MODE": - assert fv[1] == "true" - elif fv[0] == "SAI_PORT_ATTR_ADVERTISED_SPEED": - assert fv[1] == "2:100,1000" - elif fv[0] == "SAI_PORT_ATTR_ADVERTISED_INTERFACE_TYPE": - assert fv[1] == "2:SAI_PORT_INTERFACE_TYPE_CR2,SAI_PORT_INTERFACE_TYPE_CR4" - - finally: - # disable warm restart - dvs.warm_restart_swss("disable") - # slow down crm polling - dvs.crm_poll_set("10000") - - def test_PortAutoNegRemoteAdvSpeeds(self, dvs, testlog): - - cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) - sdb = swsscommon.DBConnector(6, dvs.redis_sock, 0) - - ctbl = swsscommon.Table(cdb, "PORT") - stbl = swsscommon.Table(sdb, "PORT_TABLE") - - # set autoneg = true and admin_status = up - fvs = swsscommon.FieldValuePairs([("autoneg","on"),("admin_status","up")]) - ctbl.set("Ethernet0", fvs) - - time.sleep(10) - - (status, fvs) = stbl.get("Ethernet0") - assert status == True - assert "rmt_adv_speeds" in [fv[0] for fv in fvs] - - def test_PortAdvWithoutAutoneg(self, dvs, testlog): - - db = swsscommon.DBConnector(0, dvs.redis_sock, 0) - cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) - sdb = swsscommon.DBConnector(6, dvs.redis_sock, 0) - - tbl = swsscommon.ProducerStateTable(db, "PORT_TABLE") - ctbl = swsscommon.Table(cdb, "PORT") - stbl = swsscommon.Table(sdb, "PORT_TABLE") - - # set autoneg = off - fvs = swsscommon.FieldValuePairs([("autoneg", "off")]) - ctbl.set("Ethernet0", fvs) - - time.sleep(1) - fvs = swsscommon.FieldValuePairs([("adv_speeds", "100,1000"), - ("adv_interface_types", "CR2,CR4")]) - ctbl.set("Ethernet0", fvs) - - time.sleep(1) - - adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - - atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_PORT") - (status, fvs) = atbl.get(dvs.asicdb.portnamemap["Ethernet0"]) - assert status == True - - assert "SAI_PORT_ATTR_AUTO_NEG_MODE" in [fv[0] for fv in fvs] - assert "SAI_PORT_ATTR_ADVERTISED_SPEED" in [fv[0] for fv in fvs] - assert "SAI_PORT_ATTR_ADVERTISED_INTERFACE_TYPE" in [fv[0] for fv in fvs] - for fv in fvs: - if fv[0] == "SAI_PORT_ATTR_AUTO_NEG_MODE": - assert fv[1] == "false" - elif fv[0] == "SAI_PORT_ATTR_ADVERTISED_SPEED": - assert fv[1] == "2:100,1000" - elif fv[0] == "SAI_PORT_ATTR_ADVERTISED_INTERFACE_TYPE": - assert fv[1] == "2:SAI_PORT_INTERFACE_TYPE_CR2,SAI_PORT_INTERFACE_TYPE_CR4" - - # set admin up - cfvs = swsscommon.FieldValuePairs([("admin_status", "up")]) - ctbl.set("Ethernet0", cfvs) - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_port_buffer_rel.py b/tests/test_port_buffer_rel.py deleted file mode 100644 index 144259fa8e..0000000000 --- a/tests/test_port_buffer_rel.py +++ /dev/null @@ -1,42 +0,0 @@ -import time -import pytest - -from swsscommon import swsscommon - - -# The test check that the ports will be up, when the admin state is UP by conf db. -class TestPortBuffer(object): - def test_PortsAreUpAfterBuffers(self, dvs, testlog): - num_ports = 32 - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - conf_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - - conf_port_table = swsscommon.Table(conf_db, "PORT") - asic_port_table = swsscommon.Table(asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_PORT") - - # enable all ports - fvs = swsscommon.FieldValuePairs([("admin_status", "up")]) - for i in range(0, num_ports): - conf_port_table.set("Ethernet%d" % (i*4), fvs) - - time.sleep(5) - - # check that the ports are enabled in ASIC - asic_port_records = asic_port_table.getKeys() - assert len(asic_port_records) == (num_ports + 1), "Number of port records doesn't match number of ports" # +CPU port - num_set = 0 - for k in asic_port_records: - status, fvs = asic_port_table.get(k) - assert status, "Got an error when get a key" - for fv in fvs: - if fv[0] == "SAI_PORT_ATTR_ADMIN_STATE": - assert fv[1] == "true", "The port isn't UP as expected" - num_set += 1 - # make sure that state is set for all "num_ports" ports - assert num_set == num_ports, "Not all ports are up" - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_port_config.py b/tests/test_port_config.py deleted file mode 100644 index b6f51e4e86..0000000000 --- a/tests/test_port_config.py +++ /dev/null @@ -1,235 +0,0 @@ -import redis -import time -import os -import pytest - -from swsscommon import swsscommon -from dvslib.dvs_common import wait_for_result, PollingConfig - - -@pytest.fixture -def port_config(request, dvs): - file_name = "/usr/share/sonic/hwsku/port_config.ini" - dvs.runcmd("cp %s %s.bak" % (file_name, file_name)) - yield file_name - dvs.runcmd("mv %s.bak %s" % (file_name, file_name)) - - -class TestPortConfig(object): - - def getPortName(self, dvs, port_vid): - cnt_db = swsscommon.DBConnector(swsscommon.COUNTERS_DB, dvs.redis_sock, 0) - port_map = swsscommon.Table(cnt_db, 'COUNTERS_PORT_NAME_MAP') - - for k in port_map.get('')[1]: - if k[1] == port_vid: - return k[0] - - return '' - - - def getPortOid(self, dvs, port_name): - cnt_r = redis.Redis(unix_socket_path=dvs.redis_sock, db=swsscommon.COUNTERS_DB, - encoding="utf-8", decode_responses=True) - return cnt_r.hget("COUNTERS_PORT_NAME_MAP", port_name); - - - def getVIDfromRID(self, dvs, port_rid): - asic_r = redis.Redis(unix_socket_path=dvs.redis_sock, db=swsscommon.ASIC_DB, - encoding="utf-8", decode_responses=True) - return asic_r.hget("RIDTOVID", port_rid); - - def test_port_hw_lane(self, dvs): - - app_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - app_db_ptbl = swsscommon.Table(app_db, "PORT_TABLE") - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - asic_db_lanes_tbl = swsscommon.Table(asic_db, "LANES") - - lanes = asic_db_lanes_tbl.get('')[1] - num_lanes = len(lanes) - for lane in lanes: - lane_num = lane[0]; - port_rid = lane[1]; - port_vid = self.getVIDfromRID(dvs, port_rid) - port_name = self.getPortName(dvs, port_vid) - (status, fvs) = app_db_ptbl.get(port_name) - assert status == True - for fv in fvs: - if fv[0] == "lanes": - assert str(lane_num) in list(fv[1].split(",")) - - def test_port_breakout(self, dvs, port_config): - - # Breakout the port from 1 to 4 - ''' - "Ethernet0": { - "alias": "fortyGigE0/0", - "index": "0", - "lanes": "25,26,27,28", - "speed": "40000" - }, - - to: - "Ethernet0": { - "alias": "tenGigE0", - "index": "0", - "lanes": "25", - "speed": "10000" - }, - - "Ethernet1": { - "alias": "tenGigE1", - "index": "0", - "lanes": "26", - "speed": "10000" - }, - - "Ethernet2": { - "alias": "tenGigE2", - "index": "0", - "lanes": "27", - "speed": "10000" - }, - - "Ethernet3": { - "alias": "tenGigE3", - "index": "0", - "lanes": "28", - "speed": "10000" - }, - ''' - # Get port config from configDB - conf_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - portTbl = swsscommon.Table(conf_db, swsscommon.CFG_PORT_TABLE_NAME) - - chg_port = "Ethernet0" - - keys = portTbl.getKeys() - assert chg_port in keys - - (status, fvs) = portTbl.get(chg_port) - assert(status == True) - - for fv in fvs: - if fv[0] == "index": - new_index = fv[1] - if fv[0] == "lanes": - new_lanes = fv[1].split(",") - - # Stop swss before modifing the configDB - dvs.stop_swss() - time.sleep(1) - - # breakout the port in configDB - portTbl._del(chg_port) - - new_ports = ["Ethernet0","Ethernet1","Ethernet2","Ethernet3"] - new_speed = "10000" - new_alias = ["tenGigE0", "tenGigE1", "tenGigE2", "tenGigE3"] - - for i in range (0 ,4): - fvs = swsscommon.FieldValuePairs([("alias", new_alias[i]), - ("lanes", new_lanes[i]), - ("speed", new_speed), - ("index", new_index)]) - - portTbl.set(new_ports[i], fvs) - - # start to apply new port_config.ini - dvs.start_swss() - time.sleep(5) - - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - - for i in range(0,4): - port_name = 'Ethernet{0}'.format(i) - port_oid = self.getPortOid(dvs, port_name) - port_tbl = swsscommon.Table(asic_db, 'ASIC_STATE:SAI_OBJECT_TYPE_PORT:{0}'.format(port_oid)) - hw_lane_value = None - - for k in port_tbl.get('')[1]: - if k[0] == "SAI_PORT_ATTR_HW_LANE_LIST": - hw_lane_value = k[1] - - assert hw_lane_value, "Can't get hw_lane list" - assert hw_lane_value == "1:%s" % (new_lanes[i]) - - @pytest.mark.skip(reason="Failing. Under investigation") - def test_recirc_port(self, dvs): - - # Get port config from configDB - cfg_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - cfg_port_tbl = swsscommon.Table(cfg_db, swsscommon.CFG_PORT_TABLE_NAME) - - indexes = [] - lanes = [] - keys = cfg_port_tbl.getKeys() - for port in keys: - (status, fvs) = cfg_port_tbl.get(port) - assert(status == True) - - for fv in fvs: - if fv[0] == "index": - indexes.append(int(fv[1])) - if fv[0] == "lanes": - lanes.extend([int(lane) for lane in fv[1].split(",")]) - - # Stop swss before modifing the configDB - dvs.stop_swss() - time.sleep(1) - - recirc_port_lane_base = max(lanes) + 1 - recirc_port_index_base = max(indexes) + 1 - - # Add recirc ports to port config in configDB - recirc_port_lane_name_map = {} - for i in range(2): - name = alias = "Ethernet-Rec%s" % i - fvs = swsscommon.FieldValuePairs([("role", "Rec" if i % 2 == 0 else "Inb"), - ("alias", alias), - ("lanes", str(recirc_port_lane_base + i)), - ("speed", "10000"), - ("index", str(recirc_port_index_base + i))]) - cfg_port_tbl.set(name, fvs) - - # Start swss - dvs.start_swss() - time.sleep(5) - - polling_config = PollingConfig(polling_interval=0.1, timeout=15, strict=True) - - # Verify recirc ports in port table in applDB - for i in range(2): - name = alias = "Ethernet-Rec%s" % i - dvs.get_app_db().wait_for_field_match(swsscommon.APP_PORT_TABLE_NAME, name, - {"role" : "Rec" if i % 2 == 0 else "Inb", - "alias" : name, - "lanes" : str(recirc_port_lane_base + i), - "speed" : "10000", - "index" : str(recirc_port_index_base + i) }, - polling_config=polling_config) - - # Verify recirc port lanes in asicDB - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - asic_db_lanes_tbl = swsscommon.Table(asic_db, "LANES") - - def _access_function(): - lanes = asic_db_lanes_tbl.get('')[1] - if len(lanes) == 0: - return (False, None) - - recirc_port_lanes = [recirc_port_lane_base, recirc_port_lane_base + 1] - for lane in lanes: - lane_num = int(lane[0]) - if int(lane_num) in recirc_port_lanes: - recirc_port_lanes.remove( lane_num ) - return (not recirc_port_lanes, None) - wait_for_result(_access_function, polling_config=polling_config) - - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_port_dpb.py b/tests/test_port_dpb.py deleted file mode 100644 index 3fb74de8b1..0000000000 --- a/tests/test_port_dpb.py +++ /dev/null @@ -1,105 +0,0 @@ -from swsscommon import swsscommon -import redis -import time -import os -import pytest -from pytest import * -import json -import re -from port_dpb import DPB - -speed100G = 100000 -speed50G = 50000 -speed40G = 40000 -speed25G = 25000 -speed10G = 10000 -maxPorts = 128 -maxRootPorts = 32 -maxBreakOut = 4 - -@pytest.mark.usefixtures('dpb_setup_fixture') -class TestPortDPB(object): - - ''' - |-------------------------------------------------- - | | 1X100G | 1X40G | 4X10G | 4X25G | 2X50G | - |-------------------------------------------------- - | 1X100G | NA | P | P | P | P | - |-------------------------------------------------- - | 1X40G | P | NA | P | P | | - |-------------------------------------------------- - | 4X10G | P | P | NA | P | | - |-------------------------------------------------- - | 4X25G | P | P | P | NA | | - |-------------------------------------------------- - | 2X50G | P | | | | NA | - |-------------------------------------------------- - NA --> Not Applicable - P --> Pass - F --> Fail - Empty --> Not Tested - ''' - - def test_port_breakout_one(self, dvs): - dpb = DPB() - dpb.breakout(dvs, "Ethernet0", maxBreakOut) - #print "**** 1X40G --> 4X10G passed ****" - dpb.change_speed_and_verify(dvs, ["Ethernet0", "Ethernet1", "Ethernet2", "Ethernet3"], speed25G) - #print "**** 4X10G --> 4X25G passed ****" - dpb.change_speed_and_verify(dvs, ["Ethernet0", "Ethernet1", "Ethernet2", "Ethernet3"], speed10G) - #print "**** 4X25G --> 4X10G passed ****" - dpb.breakin(dvs, ["Ethernet0", "Ethernet1", "Ethernet2", "Ethernet3"]) - #print "**** 4X10G --> 1X40G passed ****" - dpb.change_speed_and_verify(dvs, ["Ethernet0"], speed100G) - #print "**** 1X40G --> 1X100G passed ****" - dpb.breakout(dvs, "Ethernet0", maxBreakOut) - #print "**** 1X100G --> 4X25G passed ****" - dpb.change_speed_and_verify(dvs, ["Ethernet0", "Ethernet1", "Ethernet2", "Ethernet3"], speed10G) - #print "**** 4X25G --> 4X10G passed ****" - dpb.change_speed_and_verify(dvs, ["Ethernet0", "Ethernet1", "Ethernet2", "Ethernet3"], speed25G) - #print "**** 4X10G --> 4X25G passed ****" - dpb.breakin(dvs, ["Ethernet0", "Ethernet1", "Ethernet2", "Ethernet3"]) - #print "**** 4X25G --> 1X100G passed ****" - dpb.breakout(dvs, "Ethernet0", maxBreakOut//2) - #print "**** 1X100G --> 2X50G passed ****" - dpb.breakin(dvs, ["Ethernet0", "Ethernet2"]) - #print "**** 2X50G --> 1X100G passed ****" - dpb.change_speed_and_verify(dvs, ["Ethernet0"], speed40G) - #print "**** 1X100G --> 1X40G passed ****" - - def test_port_breakout_multiple(self, dvs): - dpb = DPB() - port_names = ["Ethernet0", "Ethernet12", "Ethernet64", "Ethernet112"] - for pname in port_names: - dpb.breakout(dvs, pname, maxBreakOut) - dpb.breakin(dvs, ["Ethernet0", "Ethernet1", "Ethernet2", "Ethernet3"]) - dpb.breakin(dvs, ["Ethernet12", "Ethernet13", "Ethernet14", "Ethernet15"]) - dpb.breakin(dvs, ["Ethernet64", "Ethernet65", "Ethernet66", "Ethernet67"]) - dpb.breakin(dvs, ["Ethernet112", "Ethernet113", "Ethernet114", "Ethernet115"]) - - @pytest.mark.skip("breakout_all takes too long to execute") - def test_port_breakout_all(self, dvs): - dpb = DPB() - port_names = [] - for i in range(maxRootPorts): - pname = "Ethernet" + str(i*maxBreakOut) - port_names.append(pname) - - for pname in port_names: - dpb.breakout(dvs, pname, maxBreakOut) - - child_port_names = [] - for i in range(maxPorts): - cpname = "Ethernet" + str(i) - child_port_names.append(cpname) - - for i in range(32): - start = i*maxBreakOut - end = start+maxBreakOut - dpb.breakin(dvs, child_port_names[start:end]) - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_port_dpb_acl.py b/tests/test_port_dpb_acl.py deleted file mode 100644 index f22c304a19..0000000000 --- a/tests/test_port_dpb_acl.py +++ /dev/null @@ -1,190 +0,0 @@ -import pytest - -from port_dpb import DPB - -maxPorts = 32 -maxBreakout = 4 -maxRootPorts = maxPorts/maxBreakout -maxAclTables = 16 - - -@pytest.mark.usefixtures('dpb_setup_fixture') -class TestPortDPBAcl(object): - def test_acl_table_empty_port_list(self, dvs_acl): - # Create ACL table "test" and bind it to Ethernet0 - bind_ports = [] - dvs_acl.create_acl_table("test", "L3", bind_ports) - dvs_acl.verify_acl_table_count(1) - dvs_acl.verify_acl_table_groups(0) - - bind_ports = ["Ethernet0"] - dvs_acl.update_acl_table_port_list("test", bind_ports) - - # Verify table, group, and member have been created - dvs_acl.verify_acl_table_count(1) - dvs_acl.verify_acl_table_groups(1) - acl_table_ids = dvs_acl.get_acl_table_ids(1) - dvs_acl.verify_acl_table_port_binding(acl_table_ids[0], bind_ports, 1) - - bind_ports = [] - dvs_acl.update_acl_table_port_list("test", bind_ports) - dvs_acl.verify_acl_table_count(1) - dvs_acl.verify_acl_table_groups(0) - - def test_one_port_two_acl_tables(self, dvs_acl): - # Create ACL table "test" and bind it to Ethernet0 - bind_ports = ["Ethernet0"] - dvs_acl.create_acl_table("test", "L3", bind_ports) - dvs_acl.verify_acl_table_count(1) - dvs_acl.verify_acl_table_groups(1) - acl_table_ids = dvs_acl.get_acl_table_ids(1) - dvs_acl.verify_acl_table_port_binding(acl_table_ids[0], bind_ports, 1) - - # Create ACL table "test1" and bind it to Ethernet0 - bind_ports = ["Ethernet0"] - dvs_acl.create_acl_table("test1", "L3", bind_ports) - dvs_acl.verify_acl_table_count(2) - dvs_acl.verify_acl_table_groups(1) - acl_table_ids = dvs_acl.get_acl_table_ids(2) - dvs_acl.verify_acl_table_port_binding(acl_table_ids[0], bind_ports, 2) - dvs_acl.verify_acl_table_port_binding(acl_table_ids[1], bind_ports, 2) - - # Delete ACL tables - dvs_acl.remove_acl_table("test") - dvs_acl.verify_acl_table_count(1) - dvs_acl.verify_acl_table_groups(1) - - dvs_acl.remove_acl_table("test1") - dvs_acl.verify_acl_table_count(0) - dvs_acl.verify_acl_table_groups(0) - - def test_one_acl_table_many_ports(self, dvs, dvs_acl): - # Create ACL table and bind it to Ethernet0 and Ethernet4 - bind_ports = ["Ethernet0", "Ethernet4"] - dvs_acl.create_acl_table("test", "L3", bind_ports) - dvs_acl.verify_acl_table_count(1) - dvs_acl.verify_acl_table_groups(2) - acl_table_ids = dvs_acl.get_acl_table_ids(1) - dvs_acl.verify_acl_table_port_binding(acl_table_ids[0], bind_ports, 1) - - # Update bind list and verify - bind_ports = ["Ethernet4"] - dvs_acl.update_acl_table_port_list("test", bind_ports) - dvs_acl.verify_acl_table_groups(1) - acl_table_ids = dvs_acl.get_acl_table_ids(1) - dvs_acl.verify_acl_table_port_binding(acl_table_ids[0], bind_ports, 1) - - # Breakout Ethernet0 - dpb = DPB() - dpb.breakout(dvs, "Ethernet0", maxBreakout) - - # Update bind list and verify - bind_ports = ["Ethernet0", "Ethernet1", "Ethernet2", "Ethernet3", "Ethernet4"] - dvs_acl.update_acl_table_port_list("test", bind_ports) - dvs_acl.verify_acl_table_groups(5) - dvs_acl.verify_acl_table_port_binding(acl_table_ids[0], bind_ports, 1) - - # Update bind list and verify - bind_ports = ["Ethernet4"] - dvs_acl.update_acl_table_port_list("test", bind_ports) - dvs_acl.verify_acl_table_groups(1) - dvs_acl.verify_acl_table_port_binding(acl_table_ids[0], bind_ports, 1) - - # Breakin Ethernet0, 1, 2, 3 - dpb.breakin(dvs, ["Ethernet0", "Ethernet1", "Ethernet2", "Ethernet3"]) - - # Update bind list and verify - bind_ports = ["Ethernet0", "Ethernet4"] - dvs_acl.update_acl_table_port_list("test", bind_ports) - dvs_acl.verify_acl_table_groups(2) - dvs_acl.verify_acl_table_port_binding(acl_table_ids[0], bind_ports, 1) - - # Delete ACL table - dvs_acl.remove_acl_table("test") - dvs_acl.verify_acl_table_groups(0) - - def test_one_port_many_acl_tables(self, dvs, dvs_acl): - # Create 4 ACL tables and bind them to Ethernet0 - bind_ports = ["Ethernet0"] - acl_tables = ["test1", "test2", "test3", "test4"] - for acl_tbl in acl_tables: - dvs_acl.create_acl_table(acl_tbl, "L3", bind_ports) - - dvs_acl.verify_acl_table_count(len(acl_tables)) - dvs_acl.verify_acl_table_groups(len(bind_ports)) - acl_table_ids = dvs_acl.get_acl_table_ids(len(acl_tables)) - for acl_tbl_id in acl_table_ids: - dvs_acl.verify_acl_table_port_binding(acl_tbl_id, bind_ports, len(acl_tables)) - - # Update bind list and verify - bind_ports = [] - for acl_tbl in acl_tables: - dvs_acl.update_acl_table_port_list(acl_tbl, bind_ports) - - dvs_acl.verify_acl_table_groups(0) - - # Breakout Ethernet0 - dpb = DPB() - dpb.breakout(dvs, "Ethernet0", maxBreakout) - - # Breakin Ethernet0, 1, 2, 3 - dpb.breakin(dvs, ["Ethernet0", "Ethernet1", "Ethernet2", "Ethernet3"]) - - for acl_tbl in acl_tables: - dvs_acl.remove_acl_table(acl_tbl) - - def test_many_ports_many_acl_tables(self, dvs, dvs_acl): - # Prepare ACL table names - aclTableNames = [] - for i in range(maxAclTables): - aclTableNames.append("aclTable" + str(i+1)) - - # Prepare all port names - portNames = [] - for i in range(maxPorts): - portNames.append("Ethernet" + str(i)) - - # Prepare root port names - rootPortNames = [] - for i in range(0, maxPorts, maxBreakout): - rootPortNames.append("Ethernet" + str(i)) - - # Create ACL tables and bind root ports - for aclTable in aclTableNames: - dvs_acl.create_acl_table(aclTable, "L3", rootPortNames) - dvs_acl.verify_acl_table_groups(maxRootPorts) - - # Remove the dependency on all root ports by - # unbinding them from all ACL tables. - bind_ports = [] - for aclTable in aclTableNames: - dvs_acl.update_acl_table_port_list(aclTable, bind_ports) - dvs_acl.verify_acl_table_groups(0) - - # Breakout all root ports - dpb = DPB() - for pName in rootPortNames: - dpb.breakout(dvs, pName, maxBreakout) - - # Add all ports to aclTable1 - dvs_acl.update_acl_table_port_list(aclTableNames[0], portNames) - dvs_acl.verify_acl_table_groups(maxPorts) - - # Remove all ports from aclTable1 - bind_ports = [] - dvs_acl.update_acl_table_port_list(aclTableNames[0], bind_ports) - dvs_acl.verify_acl_table_groups(0) - - # Breakin all ports - for i in range(0, maxPorts, maxBreakout): - dpb.breakin(dvs, portNames[i:i+maxBreakout]) - - for aclTable in aclTableNames: - dvs_acl.remove_acl_table(aclTable) - dvs_acl.verify_acl_table_count(0) - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_port_dpb_lag.py b/tests/test_port_dpb_lag.py deleted file mode 100644 index 54d90ebc1a..0000000000 --- a/tests/test_port_dpb_lag.py +++ /dev/null @@ -1,84 +0,0 @@ -import time -import pytest -from port_dpb import Port -from port_dpb import DPB -from swsscommon import swsscommon - -@pytest.mark.usefixtures('dpb_setup_fixture') -@pytest.mark.usefixtures('dvs_lag_manager') -class TestPortDPBLag(object): - def check_syslog(self, dvs, marker, log, expected_cnt): - (exitcode, num) = dvs.runcmd(['sh', '-c', "awk \'/%s/,ENDFILE {print;}\' /var/log/syslog | grep \"%s\" | wc -l" % (marker, log)]) - assert num.strip() >= str(expected_cnt) - - def create_port_channel(self, dvs, channel): - tbl = swsscommon.ProducerStateTable(dvs.pdb, "LAG_TABLE") - fvs = swsscommon.FieldValuePairs([("admin", "up"), ("mtu", "9100")]) - tbl.set("PortChannel" + channel, fvs) - time.sleep(1) - - def remove_port_channel(self, dvs, channel): - tbl = swsscommon.ProducerStateTable(dvs.pdb, "LAG_TABLE") - tbl._del("PortChannel" + channel) - time.sleep(1) - - def create_port_channel_member(self, dvs, channel, interface): - tbl = swsscommon.ProducerStateTable(dvs.pdb, "LAG_MEMBER_TABLE") - fvs = swsscommon.FieldValuePairs([("status", "enabled")]) - tbl.set("PortChannel" + channel + ":" + interface, fvs) - time.sleep(1) - - def remove_port_channel_member(self, dvs, channel, interface): - tbl = swsscommon.ProducerStateTable(dvs.pdb, "LAG_MEMBER_TABLE") - tbl._del("PortChannel" + channel + ":" + interface) - time.sleep(1) - - def test_dependency(self, dvs): - dvs.setup_db() - lag = "0001" - p = Port(dvs, "Ethernet0") - p.sync_from_config_db() - - # 1. Create PortChannel0001. - self.create_port_channel(dvs, lag) - - # 2. Add Ethernet0 to PortChannel0001. - self.create_port_channel_member(dvs, lag, p.get_name()) - time.sleep(2) - - # 3. Add log marker to syslog - marker = dvs.add_log_marker() - - # 4. Delete Ethernet0 from config DB. - p.delete_from_config_db() - time.sleep(2) - - # 5. Verify that we are waiting in portsorch for the port - # to be removed from LAG, by looking at the log - self.check_syslog(dvs, marker, "Unable to remove port Ethernet0: ref count 1", 1) - - # 6. Also verify that port is still present in ASIC DB. - assert(p.exists_in_asic_db() == True) - - # 7. Remove port from LAG - self.remove_port_channel_member(dvs, lag, p.get_name()) - - # 8. Verify that port is removed from ASIC DB - assert(p.not_exists_in_asic_db() == True) - - # 9. Re-create port Ethernet0 and verify that it is - # present in CONFIG, APPL, and ASIC DBs - p.write_to_config_db() - p.verify_config_db() - p.verify_app_db() - p.verify_asic_db() - - # 10. Remove PortChannel0001 and verify that its removed. - self.remove_port_channel(dvs, lag) - self.dvs_lag.get_and_verify_port_channel(0) - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_port_dpb_system.py b/tests/test_port_dpb_system.py deleted file mode 100644 index 18afcd1a0f..0000000000 --- a/tests/test_port_dpb_system.py +++ /dev/null @@ -1,867 +0,0 @@ -import pytest -import json -from port_dpb import Port -from port_dpb import DPB -from dvslib.dvs_common import wait_for_result, PollingConfig - -ARP_FLUSH_POLLING = PollingConfig(polling_interval=0.01, timeout=10, strict=True) -ROUTE_CHECK_POLLING = PollingConfig(polling_interval=0.01, timeout=5, strict=True) -""" -Below prefix should be same as the one specified for Ethernet8 -in port_breakout_config_db.json in sonic-buildimage/platform/vs/docker-sonic-vs/ -""" -Ethernet8_IP = "10.0.0.8/31" -Ethernet8_IPME = "10.0.0.8/32" - -@pytest.mark.usefixtures('dpb_setup_fixture') -@pytest.mark.usefixtures('dvs_vlan_manager') -class TestPortDPBSystem(object): - - def create_l3_intf(self, dvs, interface, vrf_name): - dvs_asic_db = dvs.get_asic_db() - initial_entries = set(dvs_asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE")) - - if interface.startswith("PortChannel"): - tbl_name = "PORTCHANNEL_INTERFACE" - elif interface.startswith("Vlan"): - tbl_name = "VLAN_INTERFACE" - elif interface.startswith("Loopback"): - tbl_name = "LOOPBACK_INTERFACE" - else: - tbl_name = "INTERFACE" - - if len(vrf_name) == 0: - fvs = {'NULL':'NULL'} - else: - fvs = {'vrf_name':vrf_name} - dvs.get_config_db().create_entry(tbl_name, interface, fvs) - - dvs_asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE", len(initial_entries)+1) - current_entries = set(dvs_asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE")) - assert len(current_entries - initial_entries) == 1 - return list(current_entries - initial_entries)[0] - - def remove_l3_intf(self, dvs, interface): - if interface.startswith("PortChannel"): - tbl_name = "PORTCHANNEL_INTERFACE" - elif interface.startswith("Vlan"): - tbl_name = "VLAN_INTERFACE" - elif interface.startswith("Loopback"): - tbl_name = "LOOPBACK_INTERFACE" - else: - tbl_name = "INTERFACE" - - dvs.get_config_db().delete_entry(tbl_name, interface) - - def add_ip_address(self, dvs, interface, ip): - if interface.startswith("PortChannel"): - tbl_name = "PORTCHANNEL_INTERFACE" - elif interface.startswith("Vlan"): - tbl_name = "VLAN_INTERFACE" - elif interface.startswith("Loopback"): - tbl_name = "LOOPBACK_INTERFACE" - else: - tbl_name = "INTERFACE" - - dvs.get_config_db().create_entry(tbl_name, interface+'|'+ip, {'NULL':'NULL'}) - - def remove_ip_address(self, dvs, interface, ip): - if interface.startswith("PortChannel"): - tbl_name = "PORTCHANNEL_INTERFACE" - elif interface.startswith("Vlan"): - tbl_name = "VLAN_INTERFACE" - elif interface.startswith("Loopback"): - tbl_name = "LOOPBACK_INTERFACE" - else: - tbl_name = "INTERFACE" - - dvs.get_config_db().delete_entry(tbl_name, interface+'|'+ip) - - def clear_srv_config(self, dvs): - dvs.servers[0].runcmd("ip address flush dev eth0") - dvs.servers[1].runcmd("ip address flush dev eth0") - dvs.servers[2].runcmd("ip address flush dev eth0") - dvs.servers[3].runcmd("ip address flush dev eth0") - - def set_admin_status(self, dvs, interface, status): - dvs_cfg_db = dvs.get_config_db() - if interface.startswith("PortChannel"): - tbl_name = "PORTCHANNEL" - elif interface.startswith("Vlan"): - tbl_name = "VLAN" - else: - tbl_name = "PORT" - dvs_cfg_db.create_entry(tbl_name, interface, {'admin_status':status}) - - def verify_only_ports_exist(self, dvs, port_names): - all_port_names = ["Ethernet0", "Ethernet1", "Ethernet2", "Ethernet3"] - for port_name in all_port_names: - p = Port(dvs, port_name) - if port_name in port_names: - assert(p.exists_in_config_db() == True) - assert(p.exists_in_app_db() == True) - assert(p.exists_in_asic_db() == True) - else: - assert(p.exists_in_config_db() == False) - assert(p.exists_in_app_db() == False) - assert(p.exists_in_asic_db() == False) - - ''' - |----------------------------------------------------------------------------------------------------- - | | 1X40G | 1X100G | 4X10G | 4X25G | 2X50G | 2x25G(2)+1x50G(2) | 1x50G(2)+2x25G(2) | - |----------------------------------------------------------------------------------------------------- - | 1X40G | NA | | | | | | | - |----------------------------------------------------------------------------------------------------- - | 1X100G | | NA | | P | P | P | P | - |----------------------------------------------------------------------------------------------------- - | 4X10G | | | NA | | | | | - |----------------------------------------------------------------------------------------------------- - | 4X25G | | P | | NA | P | P | P | - |----------------------------------------------------------------------------------------------------- - | 2X50G | | P | | P | NA | P | P | - |----------------------------------------------------------------------------------------------------- - | 2x25G(2)+1x50G(2) | | P | | P | P | NA | P | - |----------------------------------------------------------------------------------------------------- - | 1x50G(2)+2x25G(2) | | P | | P | P | P | NA | - |----------------------------------------------------------------------------------------------------- - - NA --> Not Applicable - P --> Pass - F --> Fail - Empty --> Not Tested - ''' - @pytest.mark.parametrize('root_port, breakout_mode', [ - ('Ethernet0', '2x50G'), - ('Ethernet0', '4x25G[10G]'), - ('Ethernet0', '2x50G'), - ('Ethernet0', '2x25G(2)+1x50G(2)'), - ('Ethernet0', '2x50G'), - ('Ethernet0', '1x50G(2)+2x25G(2)'), - ('Ethernet0', '2x50G'), - ('Ethernet0', '1x100G[40G]'), - ('Ethernet0', '4x25G[10G]'), - ('Ethernet0', '2x25G(2)+1x50G(2)'), - ('Ethernet0', '4x25G[10G]'), - ('Ethernet0', '1x50G(2)+2x25G(2)'), - ('Ethernet0', '4x25G[10G]'), - ('Ethernet0', '1x100G[40G]'), - ('Ethernet0', '2x25G(2)+1x50G(2)'), - ('Ethernet0', '1x50G(2)+2x25G(2)'), - ('Ethernet0', '2x25G(2)+1x50G(2)'), - ('Ethernet0', '1x100G[40G]'), - ('Ethernet0', '1x50G(2)+2x25G(2)'), - ('Ethernet0', '1x100G[40G]') - ], scope="function") - @pytest.mark.skip(reason="This test is not stable enough") - def test_port_breakout_simple(self, dvs, root_port, breakout_mode): - dvs.setup_db() - dpb = DPB() - - dvs.change_port_breakout_mode(root_port, breakout_mode) - dpb.verify_port_breakout_mode(dvs, root_port, breakout_mode) - expected_ports = dpb.get_child_ports(root_port, breakout_mode) - self.verify_only_ports_exist(dvs, expected_ports) - - @pytest.mark.skip(reason="This test is not stable enough") - def test_port_breakout_with_vlan(self, dvs): - dvs.setup_db() - dpb = DPB() - - portName = "Ethernet0" - vlanID = "100" - breakoutMode1 = "1x100G[40G]" - breakoutMode2 = "4x25G[10G]" - breakoutOption = "-f" #Force breakout by deleting dependencies - - # Create VLAN - self.dvs_vlan.create_vlan(vlanID) - - # Verify VLAN is created - self.dvs_vlan.get_and_verify_vlan_ids(1) - - # Add port to VLAN - self.dvs_vlan.create_vlan_member(vlanID, portName) - - # Verify VLAN member is created - self.dvs_vlan.get_and_verify_vlan_member_ids(1) - - # Breakout port from 1x100G[40G] --> 4x25G[10G] - dpb.verify_port_breakout_mode(dvs, "Ethernet0", breakoutMode1) - dvs.change_port_breakout_mode("Ethernet0", breakoutMode2, breakoutOption) - - # Verify DPB is successful - dpb.verify_port_breakout_mode(dvs, "Ethernet0", breakoutMode2) - - # Verify port is removed from VLAN - self.dvs_vlan.get_and_verify_vlan_member_ids(0) - - # Delete VLAN - self.dvs_vlan.remove_vlan(vlanID) - - # Verify VLAN is deleted - self.dvs_vlan.get_and_verify_vlan_ids(0) - - # Breakout port from 4x25G[10G] --> 1x100G[40G] - dvs.change_port_breakout_mode("Ethernet0", breakoutMode1) - - # Verify DPB is successful - dpb.verify_port_breakout_mode(dvs, "Ethernet0", breakoutMode1) - - @pytest.mark.skip(reason="This test is not stable enough") - def test_port_breakout_with_acl(self, dvs, dvs_acl): - dvs.setup_db() - dpb = DPB() - - # Create ACL table "test" and bind it to Ethernet0 - bind_ports = ["Ethernet0"] - dvs_acl.create_acl_table("test", "L3", bind_ports) - - # Verify ACL table is created - dvs_acl.verify_acl_table_count(1) - - # Verify that ACL group OID is created. - # Just FYI: Usually one ACL group OID is created per port, - # even when port is bound to multiple ACL tables - dvs_acl.verify_acl_table_groups(1) - - # Verify that port is correctly bound to table by looking into - # ACL member table, which binds ACL group OID of a port and - # ACL table OID. - acl_table_ids = dvs_acl.get_acl_table_ids(1) - dvs_acl.verify_acl_table_port_binding(acl_table_ids[0], bind_ports, 1) - - # Verify current breakout mode, perform breakout without force dependency - # delete option - dpb.verify_port_breakout_mode(dvs, "Ethernet0", "1x100G[40G]") - dvs.change_port_breakout_mode("Ethernet0", "4x25G[10G]") - - # Verify that breakout did NOT succeed - dpb.verify_port_breakout_mode(dvs, "Ethernet0", "1x100G[40G]") - - # Do breakout with force option, and verify that it succeeds - dvs.change_port_breakout_mode("Ethernet0", "4x25G[10G]", "-f") - dpb.verify_port_breakout_mode(dvs, "Ethernet0", "4x25G[10G]") - - # Verify port is removed from ACL table - dvs_acl.verify_acl_table_count(1) - dvs_acl.verify_acl_table_groups(0) - - # Verify child ports are created. - self.verify_only_ports_exist(dvs, ["Ethernet0", "Ethernet1", "Ethernet2", "Ethernet3"]) - - # Move back to 1x100G[40G] mode and verify current mode - dvs.change_port_breakout_mode("Ethernet0", "1x100G[40G]", "-f") - dpb.verify_port_breakout_mode(dvs, "Ethernet0", "1x100G[40G]") - - # Remove ACL table and verify the same - dvs_acl.remove_acl_table("test") - dvs_acl.verify_acl_table_count(0) - - @pytest.mark.skip("DEBUG: When we have more than one child ports, operation status of all does NOT go down") - def test_cli_command_with_force_option(self, dvs, dvs_acl): - dvs.setup_db() - dpb = DPB() - - portGroup = ["Ethernet0", "Ethernet1", "Ethernet2", "Ethernet3"] - rootPortName = portGroup[0] - vlanID = "100" - aclTableName = "DPB_ACL_TBL_1" - breakoutMode1x = "1x100G[40G]" - breakoutMode2x = "2x50G" - breakoutMode4x = "4x25G[10G]" - breakoutOption = "-f" #Force breakout by deleting dependencies - - # Breakout port with no dependency using "-f" option - dvs.change_port_breakout_mode(rootPortName, breakoutMode4x, breakoutOption) - dpb.verify_port_breakout_mode(dvs, rootPortName, breakoutMode4x) - dvs.change_port_breakout_mode(rootPortName, breakoutMode1x, breakoutOption) - dpb.verify_port_breakout_mode(dvs, rootPortName, breakoutMode1x) - - # Breakout port with VLAN and ACL dependency - - # Create ACL table and bind port - dvs_acl.verify_acl_table_groups(0) - bind_ports = [] - bind_ports.append(rootPortName) - dvs_acl.create_acl_table(aclTableName, "L3", bind_ports) - dvs_acl.verify_acl_table_groups(1) - - # Create VLAN and add port to VLAN - self.dvs_vlan.create_vlan(vlanID) - self.dvs_vlan.create_vlan_member(vlanID, rootPortName) - self.dvs_vlan.get_and_verify_vlan_member_ids(1) - - # Breakout port and make sure it succeeds and associations are removed - dpb.verify_port_breakout_mode(dvs, rootPortName, breakoutMode1x) - dvs.change_port_breakout_mode(rootPortName, breakoutMode4x, breakoutOption) - dpb.verify_port_breakout_mode(dvs, rootPortName, breakoutMode4x) - dvs_acl.verify_acl_table_groups(0) - self.dvs_vlan.get_and_verify_vlan_member_ids(0) - - # Add all ports to ACL and VLAN tables - dvs_acl.update_acl_table_port_list(aclTableName, portGroup) - for p in portGroup: - self.dvs_vlan.create_vlan_member(vlanID, p) - dvs_acl.verify_acl_table_groups(len(portGroup)) - self.dvs_vlan.get_and_verify_vlan_member_ids(len(portGroup)) - - # Breakout with "-f" option and ensure it succeeds and associations are removed - dvs.change_port_breakout_mode(rootPortName, breakoutMode1x, breakoutOption) - dpb.verify_port_breakout_mode(dvs, rootPortName, breakoutMode1x) - dvs_acl.verify_acl_table_groups(0) - self.dvs_vlan.get_and_verify_vlan_member_ids(0) - - # Cleanup - - # Remove ACL and VLAN tables - dvs_acl.remove_acl_table(aclTableName) - self.dvs_vlan.remove_vlan(vlanID) - - # Verify cleanup - dvs_acl.verify_acl_table_count(0) - self.dvs_vlan.get_and_verify_vlan_ids(0) - - # check ASIC router interface database - # one loopback router interface - dvs.get_asic_db().wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE", 1) - - # Bring up port - self.set_admin_status(dvs, "Ethernet8", "up") - - # Create L3 interface - self.create_l3_intf(dvs, "Ethernet8", ""); - - # Configure IPv4 address on Ethernet8 - self.add_ip_address(dvs, "Ethernet8", Ethernet8_IP) - - # one loopback router interface and one port based router interface - dvs.get_asic_db().wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE", 2) - - def _check_route_present(): - routes = dvs.get_asic_db().get_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - subnet_found = False - ip2me_found = False - for route in routes: - rt = json.loads(route) - if rt["dest"] == Ethernet8_IP: - subnet_found = True - if rt["dest"] == Ethernet8_IPME: - ip2me_found = True - - return ((subnet_found and ip2me_found), routes) - # check ASIC route database - status, result = wait_for_result(_check_route_present, ROUTE_CHECK_POLLING) - assert status == True - - # Breakout Ethernet8 WITH "-f" option and ensure cleanup happened - dpb.verify_port_breakout_mode(dvs, "Ethernet8", breakoutMode1x) - dvs.change_port_breakout_mode("Ethernet8", breakoutMode2x, breakoutOption) - dpb.verify_port_breakout_mode(dvs, "Ethernet8", breakoutMode2x) - - # check ASIC router interface database - # one loopback router interface - dvs.get_asic_db().wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE", 1) - - def _check_route_absent(): - routes = dvs.get_asic_db().get_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - for route in routes: - rt = json.loads(route) - if rt["dest"] == Ethernet8_IP or \ - rt["dest"] == Ethernet8_IPME: - return (False, route) - return (True, routes) - # check ASIC database - status, result = wait_for_result(_check_route_absent, ROUTE_CHECK_POLLING) - assert status == True - - dpb.verify_port_breakout_mode(dvs, "Ethernet8", breakoutMode2x) - dvs.change_port_breakout_mode("Ethernet8", breakoutMode1x) - dpb.verify_port_breakout_mode(dvs, "Ethernet8", breakoutMode1x) - - @pytest.mark.skip("DEBUG: When we have more than one child ports, operation status of all does NOT go down") - def test_cli_command_with_load_port_breakout_config_option(self, dvs, dvs_acl): - dvs.setup_db() - dpb = DPB() - - # Note below definitions are dependent on port_breakout_config_db.json - # That is vlanIDs, aclTableNames are all should match with - # VLANs and ACL tables in port_breakout_config_db.json - portGroup = ["Ethernet0", "Ethernet1", "Ethernet2", "Ethernet3"] - rootPortName = portGroup[0] - vlanIDs = ["100", "101"] - aclTableNames = ["DPB_ACL_TBL_1", "DPB_ACL_TBL_2"] - breakoutMode1x = "1x100G[40G]" - breakoutMode2x = "2x50G" - breakoutMode4x = "4x25G[10G]" - breakoutOption = "-l" - - # Lets create ACL and VLAN tables - bind_ports = [] - for aclTableName in aclTableNames: - dvs_acl.create_acl_table(aclTableName, "L3", bind_ports) - for vlanID in vlanIDs: - self.dvs_vlan.create_vlan(vlanID) - - # Breakout port and expect that newly created ports are - # automatically added to VLANs and ACL tables as per - # port_breakout_config_db.json - dvs_acl.verify_acl_table_groups(0) - self.dvs_vlan.get_and_verify_vlan_member_ids(0) - dpb.verify_port_breakout_mode(dvs, rootPortName, breakoutMode1x) - dvs.change_port_breakout_mode(rootPortName, breakoutMode4x, breakoutOption) - dpb.verify_port_breakout_mode(dvs, rootPortName, breakoutMode4x) - dvs_acl.verify_acl_table_groups(len(portGroup)) - self.dvs_vlan.get_and_verify_vlan_member_ids(len(portGroup)) - - # Breakout port and expect that root port remains in VLAN and ACL tables - dpb.verify_port_breakout_mode(dvs, rootPortName, breakoutMode4x) - dvs.change_port_breakout_mode(rootPortName, breakoutMode1x, breakoutOption + " -f") - dpb.verify_port_breakout_mode(dvs, rootPortName, breakoutMode1x) - dvs_acl.verify_acl_table_groups(1) - self.dvs_vlan.get_and_verify_vlan_member_ids(1) - - # Breakout port with "-f" and WITHOUT "-l" and expect that - # breakout succeeds and root port gets removed from - # VLAN and ACL table - dpb.verify_port_breakout_mode(dvs, rootPortName, breakoutMode1x) - dvs.change_port_breakout_mode(rootPortName, breakoutMode4x, "-f") - dpb.verify_port_breakout_mode(dvs, rootPortName, breakoutMode4x) - dvs_acl.verify_acl_table_groups(0) - self.dvs_vlan.get_and_verify_vlan_member_ids(0) - - #-------------------------------------------------------------------- - # Exercise port group spanned across different VLAN and ACl table | - #-------------------------------------------------------------------- - portGroup = ["Ethernet4", "Ethernet5", "Ethernet6", "Ethernet7"] - rootPortName = portGroup[0] - breakoutMode2x = "2x50G" - - # Breakout port and expect that newly created ports are - # automatically added to VLANs and ACL tables as per - # port_breakout_config_db.json - dvs_acl.verify_acl_table_groups(0) - self.dvs_vlan.get_and_verify_vlan_member_ids(0) - dpb.verify_port_breakout_mode(dvs, rootPortName, breakoutMode1x) - dvs.change_port_breakout_mode(rootPortName, breakoutMode4x, breakoutOption) - dpb.verify_port_breakout_mode(dvs, rootPortName, breakoutMode4x) - dvs_acl.verify_acl_table_groups(len(portGroup)) - self.dvs_vlan.get_and_verify_vlan_member_ids(len(portGroup)) - - # Breakout port and expect that Ethernet4 and Ethernet6 remain in - # ACL and VLAN where as Ethernet5 and Ethernet7 get removed from - # ACL and VLAN table - dpb.verify_port_breakout_mode(dvs, rootPortName, breakoutMode4x) - dvs.change_port_breakout_mode(rootPortName, breakoutMode2x, breakoutOption + " -f") - dpb.verify_port_breakout_mode(dvs, rootPortName, breakoutMode2x) - dvs_acl.verify_acl_table_groups(2) - self.dvs_vlan.get_and_verify_vlan_member_ids(2) - - # Breakout again and verify that only root port (Ethernet4) remains in - # in VLAN and ACL and Ethernet6 gets removed. - dpb.verify_port_breakout_mode(dvs, rootPortName, breakoutMode2x) - dvs.change_port_breakout_mode(rootPortName, breakoutMode1x, breakoutOption + " -f") - dpb.verify_port_breakout_mode(dvs, rootPortName, breakoutMode1x) - dvs_acl.verify_acl_table_groups(1) - self.dvs_vlan.get_and_verify_vlan_member_ids(1) - - # Breakout port without "-l" option and ensure that root port - # gets removed from VLAN and ACL - dpb.verify_port_breakout_mode(dvs, rootPortName, breakoutMode1x) - dvs.change_port_breakout_mode(rootPortName, breakoutMode2x, "-f") - dpb.verify_port_breakout_mode(dvs, rootPortName, breakoutMode2x) - dvs_acl.verify_acl_table_groups(0) - self.dvs_vlan.get_and_verify_vlan_member_ids(0) - - #Cleanup - - # Move both Ethernet0 and Ethernet4 back to default mode - dvs.change_port_breakout_mode("Ethernet0", breakoutMode1x) - dpb.verify_port_breakout_mode(dvs, "Ethernet0", breakoutMode1x) - dvs.change_port_breakout_mode("Ethernet4", breakoutMode1x) - dpb.verify_port_breakout_mode(dvs, "Ethernet4", breakoutMode1x) - - # Delete VLANs and ACL tables - bind_ports = [] - for aclTableName in aclTableNames: - dvs_acl.remove_acl_table(aclTableName) - for vlanID in vlanIDs: - self.dvs_vlan.remove_vlan(vlanID) - - # Verify cleanup - dvs_acl.verify_acl_table_count(0) - self.dvs_vlan.get_and_verify_vlan_ids(0) - - ##### Interface dependency test ############ - - # check ASIC router interface database - # one loopback router interface - dvs.get_asic_db().wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE", 1) - - # Breakout Ethernet8 WITH "-l" option and ensure - # ip address gets configured as per port_breakout_config_db.json - dpb.verify_port_breakout_mode(dvs, "Ethernet8", breakoutMode1x) - dvs.change_port_breakout_mode("Ethernet8", breakoutMode2x, breakoutOption) - dpb.verify_port_breakout_mode(dvs, "Ethernet8", breakoutMode2x) - - # one loopback router interface and one port based router interface - dvs.get_asic_db().wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE", 2) - - def _check_route_present(): - routes = dvs.get_asic_db().get_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - subnet_found = False - ip2me_found = False - for route in routes: - rt = json.loads(route) - if rt["dest"] == Ethernet8_IP: - subnet_found = True - if rt["dest"] == Ethernet8_IPME: - ip2me_found = True - - return ((subnet_found and ip2me_found), routes) - # check ASIC route database - status, result = wait_for_result(_check_route_present, ROUTE_CHECK_POLLING) - assert status == True - - # Breakout Ethernet8 WITH "-f" option and ensure cleanup happened - dpb.verify_port_breakout_mode(dvs, "Ethernet8", breakoutMode2x) - dvs.change_port_breakout_mode("Ethernet8", breakoutMode1x, "-f") - dpb.verify_port_breakout_mode(dvs, "Ethernet8", breakoutMode1x) - - # check ASIC router interface database - # one loopback router interface - dvs.get_asic_db().wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE", 1) - - def _check_route_absent(): - routes = dvs.get_asic_db().get_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - for route in routes: - rt = json.loads(route) - if rt["dest"] == Ethernet8_IP or \ - rt["dest"] == Ethernet8_IPME: - return (False, route) - return (True, routes) - # check ASIC database - status, result = wait_for_result(_check_route_absent, ROUTE_CHECK_POLLING) - assert status == True - - @pytest.mark.skip(reason="This test is not stable enough") - def test_cli_command_negative(self, dvs, dvs_acl): - dvs.setup_db() - dpb = DPB() - - portGroup = ["Ethernet0", "Ethernet1", "Ethernet2", "Ethernet3"] - rootPortName = portGroup[0] - vlanIDs = ["100", "101"] - aclTableNames = ["DPB_ACL_TBL_1", "DPB_ACL_TBL_2"] - breakoutMode1x = "1x100G[40G]" - breakoutMode4x = "4x25G[10G]" - - # Create only one ACL table and one VLAN table - bind_ports = [] - dvs_acl.create_acl_table(aclTableNames[0], "L3", bind_ports) - self.dvs_vlan.create_vlan(vlanIDs[0]) - - # Add root port to ACL and VLAN tables - bind_ports = [] - bind_ports.append(rootPortName) - dvs_acl.update_acl_table_port_list(aclTableNames[0], bind_ports) - self.dvs_vlan.create_vlan_member(vlanIDs[0], rootPortName) - - # Breakout port WITHOUT "-f" option when dependencies exist - # TBD: Verify the list of dependencies returned by CLI command - dvs_acl.verify_acl_table_groups(1) - self.dvs_vlan.get_and_verify_vlan_member_ids(1) - dpb.verify_port_breakout_mode(dvs, rootPortName, breakoutMode1x) - dvs.change_port_breakout_mode(rootPortName, breakoutMode4x) - dpb.verify_port_breakout_mode(dvs, rootPortName, breakoutMode1x) - dvs_acl.verify_acl_table_groups(1) - self.dvs_vlan.get_and_verify_vlan_member_ids(1) - - # Breakout port WITH "-f" option, and WITHOUT "-l" option - dpb.verify_port_breakout_mode(dvs, rootPortName, breakoutMode1x) - dvs.change_port_breakout_mode(rootPortName, breakoutMode4x, "-f") - dpb.verify_port_breakout_mode(dvs, rootPortName, breakoutMode4x) - dvs_acl.verify_acl_table_groups(0) - self.dvs_vlan.get_and_verify_vlan_member_ids(0) - - # Delete VLAN table, ensure breakout WITH "-l" fails - self.dvs_vlan.remove_vlan(vlanIDs[0]) - self.dvs_vlan.get_and_verify_vlan_ids(0) - dpb.verify_port_breakout_mode(dvs, rootPortName, breakoutMode4x) - dvs.change_port_breakout_mode(rootPortName, breakoutMode1x, "-l") - dpb.verify_port_breakout_mode(dvs, rootPortName, breakoutMode4x) - dvs_acl.verify_acl_table_groups(0) - self.dvs_vlan.get_and_verify_vlan_member_ids(0) - - # Delete ACL table, Add back VLAN table and - # ensure breakout WITH "-l" fails - dvs_acl.remove_acl_table(aclTableNames[0]) - dvs_acl.verify_acl_table_count(0) - self.dvs_vlan.create_vlan(vlanIDs[0]) - dpb.verify_port_breakout_mode(dvs, rootPortName, breakoutMode4x) - dvs.change_port_breakout_mode(rootPortName, breakoutMode1x, "-l") - dpb.verify_port_breakout_mode(dvs, rootPortName, breakoutMode4x) - dvs_acl.verify_acl_table_groups(0) - self.dvs_vlan.get_and_verify_vlan_member_ids(0) - - # Create both ACL tables (as per port_breakout_config_db.json, - # Ethernet0 is in both ACL tables and one VLAN table) - # and ensure, breakout succeeds - bind_ports = [] - dvs_acl.create_acl_table(aclTableNames[0], "L3", bind_ports) - dvs_acl.create_acl_table(aclTableNames[1], "L3", bind_ports) - dpb.verify_port_breakout_mode(dvs, rootPortName, breakoutMode4x) - dvs.change_port_breakout_mode(rootPortName, breakoutMode1x, "-l") - dpb.verify_port_breakout_mode(dvs, rootPortName, breakoutMode1x) - dvs_acl.verify_acl_table_groups(1) - self.dvs_vlan.get_and_verify_vlan_member_ids(1) - - # Delete ACL and VLAN tables - self.dvs_vlan.remove_vlan_member(vlanIDs[0], rootPortName) - self.dvs_vlan.remove_vlan(vlanIDs[0]) - dvs_acl.remove_acl_table(aclTableNames[0]) - dvs_acl.remove_acl_table(aclTableNames[1]) - - # TBD: Provide "-l" option without port_breakout_config_db.json file - - # Verify cleanup - dvs_acl.verify_acl_table_count(0) - self.dvs_vlan.get_and_verify_vlan_ids(0) - - @pytest.mark.skip(reason="This test is not stable enough") - def test_dpb_arp_flush(self, dvs): - dvs.setup_db() - dvs_asic_db = dvs.get_asic_db() - dpb = DPB() - - portName = "Ethernet0" - vrfName = "" - ipAddress = "10.0.0.0/31" - srv0MAC = "00:00:00:00:01:11" - - self.clear_srv_config(dvs) - - # Create l3 interface - rif_oid = self.create_l3_intf(dvs, portName, vrfName) - - # set ip address - self.add_ip_address(dvs, portName, ipAddress) - - # bring up interface - self.set_admin_status(dvs, portName, "up") - - # Set IP address and default route - cmd = "ip link set eth0 address " + srv0MAC - dvs.servers[0].runcmd(cmd) - dvs.servers[0].runcmd("ip address add 10.0.0.1/31 dev eth0") - dvs.servers[0].runcmd("ip route add default via 10.0.0.0") - - # Get neighbor and ARP entry - dvs.servers[0].runcmd("ping -c 3 10.0.0.0") - - intf_entries = dvs_asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY", 1) - route = json.loads(intf_entries[0]) - assert route["ip"] == "10.0.0.1" - assert route["rif"] == rif_oid - dvs_asic_db.wait_for_exact_match("ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY", \ - intf_entries[0], \ - {"SAI_NEIGHBOR_ENTRY_ATTR_DST_MAC_ADDRESS":srv0MAC}) - - # Breakout port and make sure NEIGHBOR entry is removed - dpb.verify_port_breakout_mode(dvs, "Ethernet0", "1x100G[40G]") - dvs.change_port_breakout_mode("Ethernet0", "4x25G[10G]", "-f") - dpb.verify_port_breakout_mode(dvs, "Ethernet0", "4x25G[10G]") - - #Verify ARP/Neighbor entry is removed - dvs_asic_db.wait_for_deleted_entry("ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY", \ - intf_entries[0], ARP_FLUSH_POLLING) - - dvs.change_port_breakout_mode("Ethernet0", "1x100G[40G]") - dpb.verify_port_breakout_mode(dvs, "Ethernet0", "1x100G[40G]") - - @pytest.mark.skip(reason="This test is not stable enough") - def test_dpb_arp_flush_vlan(self, dvs): - dvs.setup_db() - dvs_asic_db = dvs.get_asic_db() - dpb = DPB() - - self.clear_srv_config(dvs) - vlanID = "100" - portName = "Ethernet0" - vlanName = "Vlan" + str(vlanID) - vrfName = "" - ipAddress = "10.0.0.0/31" - srv0MAC = "00:00:00:00:01:11" - - self.dvs_vlan.create_vlan(vlanID) - - self.dvs_vlan.create_vlan_member(vlanID, portName) - - # bring up interface - self.set_admin_status(dvs, portName, "up") - self.set_admin_status(dvs, vlanName, "up") - - # create vlan interface - rif_oid = self.create_l3_intf(dvs, vlanName, vrfName) - - # assign IP to interface - self.add_ip_address(dvs, vlanName, ipAddress) - - # Set IP address and default route - cmd = "ip link set eth0 address " + srv0MAC - dvs.servers[0].runcmd(cmd) - dvs.servers[0].runcmd("ip address add 10.0.0.1/31 dev eth0") - dvs.servers[0].runcmd("ip route add default via 10.0.0.0") - - # Get neighbor and ARP entry - dvs.servers[0].runcmd("ping -c 1 10.0.0.0") - - intf_entries = dvs_asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY", 1) - route = json.loads(intf_entries[0]) - assert route["ip"] == "10.0.0.1" - assert route["rif"] == rif_oid - dvs_asic_db.wait_for_exact_match("ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY", \ - intf_entries[0], \ - {"SAI_NEIGHBOR_ENTRY_ATTR_DST_MAC_ADDRESS":srv0MAC}) - - # Breakout port and make sure NEIGHBOR entry is removed - dpb.verify_port_breakout_mode(dvs, "Ethernet0", "1x100G[40G]") - dvs.change_port_breakout_mode("Ethernet0", "4x25G[10G]", "-f") - dpb.verify_port_breakout_mode(dvs, "Ethernet0", "4x25G[10G]") - - #Verify ARP/Neighbor entry is removed - dvs_asic_db.wait_for_deleted_entry("ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY", \ - intf_entries[0], ARP_FLUSH_POLLING) - - dvs.change_port_breakout_mode("Ethernet0", "1x100G[40G]") - dpb.verify_port_breakout_mode(dvs, "Ethernet0", "1x100G[40G]") - - # Remove IP from interface, and then remove interface - self.remove_ip_address(dvs, vlanName, ipAddress) - self.remove_l3_intf(dvs, vlanName) - - # Remove VLAN(note that member was removed during port breakout) - self.dvs_vlan.remove_vlan(vlanID) - - @pytest.mark.skip(reason="This test is not stable enough") - def test_dpb_arp_flush_on_port_oper_shut(self, dvs): - dvs.setup_db() - dvs_asic_db = dvs.get_asic_db() - dpb = DPB() - - self.clear_srv_config(dvs) - vlanID = "100" - portName = "Ethernet0" - vlanName = "Vlan" + str(vlanID) - vrfName = "" - ipAddress = "10.0.0.0/31" - srv0MAC = "00:00:00:00:01:11" - - self.dvs_vlan.create_vlan(vlanID) - - self.dvs_vlan.create_vlan_member(vlanID, portName) - - # bring up interface - self.set_admin_status(dvs, portName, "up") - self.set_admin_status(dvs, vlanName, "up") - - # create vlan interface - rif_oid = self.create_l3_intf(dvs, vlanName, vrfName) - - # assign IP to interface - self.add_ip_address(dvs, vlanName, ipAddress) - - # Set IP address and default route - cmd = "ip link set eth0 address " + srv0MAC - dvs.servers[0].runcmd(cmd) - dvs.servers[0].runcmd("ip address add 10.0.0.1/31 dev eth0") - dvs.servers[0].runcmd("ip route add default via 10.0.0.0") - - # Get neighbor and ARP entry - dvs.servers[0].runcmd("ping -c 3 10.0.0.0") - - intf_entries = dvs_asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY", 1) - route = json.loads(intf_entries[0]) - assert route["ip"] == "10.0.0.1" - assert route["rif"] == rif_oid - dvs_asic_db.wait_for_exact_match("ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY", \ - intf_entries[0], \ - {"SAI_NEIGHBOR_ENTRY_ATTR_DST_MAC_ADDRESS":srv0MAC}) - - # Bring link operation state down - self.set_admin_status(dvs, portName, "down") - dvs.servers[0].runcmd("ip link set dev eth0 down") - - #Verify ARP/Neighbor entry is removed - dvs_asic_db.wait_for_deleted_entry("ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY", \ - intf_entries[0], ARP_FLUSH_POLLING) - - # Bring link operation state up - self.set_admin_status(dvs, portName, "up") - dvs.servers[0].runcmd("ip link set dev eth0 up") - - # Remove IP from interface, and then remove interface - self.remove_ip_address(dvs, vlanName, ipAddress) - self.remove_l3_intf(dvs, vlanName) - - # Remove VLAN member and VLAN - self.dvs_vlan.remove_vlan_member(vlanID, portName) - self.dvs_vlan.remove_vlan(vlanID) - - @pytest.mark.skip(reason="This test is not stable enough") - def test_dpb_arp_flush_on_vlan_member_remove(self, dvs): - dvs.setup_db() - dvs_asic_db = dvs.get_asic_db() - dpb = DPB() - - self.clear_srv_config(dvs) - vlanID = "100" - portName = "Ethernet0" - vlanName = "Vlan" + str(vlanID) - vrfName = "" - ipAddress = "10.0.0.0/31" - srv0MAC = "00:00:00:00:01:11" - - self.dvs_vlan.create_vlan(vlanID) - - self.dvs_vlan.create_vlan_member(vlanID, portName) - - # bring up interface - self.set_admin_status(dvs, portName, "up") - self.set_admin_status(dvs, vlanName, "up") - - # create vlan interface - rif_oid = self.create_l3_intf(dvs, vlanName, vrfName) - - # assign IP to interface - self.add_ip_address(dvs, vlanName, ipAddress) - - # Set IP address and default route - cmd = "ip link set eth0 address " + srv0MAC - dvs.servers[0].runcmd(cmd) - dvs.servers[0].runcmd("ip address add 10.0.0.1/31 dev eth0") - dvs.servers[0].runcmd("ip route add default via 10.0.0.0") - - # Get neighbor and ARP entry - dvs.servers[0].runcmd("ping -c 1 10.0.0.0") - - intf_entries = dvs_asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY", 1) - route = json.loads(intf_entries[0]) - assert route["ip"] == "10.0.0.1" - assert route["rif"] == rif_oid - dvs_asic_db.wait_for_exact_match("ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY", \ - intf_entries[0], \ - {"SAI_NEIGHBOR_ENTRY_ATTR_DST_MAC_ADDRESS":srv0MAC}) - - # Remove port from VLAN - self.dvs_vlan.remove_vlan_member(vlanID, portName) - - #Verify ARP/Neighbor entry is removed - dvs_asic_db.wait_for_deleted_entry("ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY", \ - intf_entries[0], ARP_FLUSH_POLLING) - - # Remove IP from interface, and then remove interface - self.remove_ip_address(dvs, vlanName, ipAddress) - self.remove_l3_intf(dvs, vlanName) - - # Remove VLAN - self.dvs_vlan.remove_vlan(vlanID) diff --git a/tests/test_port_dpb_vlan.py b/tests/test_port_dpb_vlan.py deleted file mode 100644 index e6f89beb1a..0000000000 --- a/tests/test_port_dpb_vlan.py +++ /dev/null @@ -1,248 +0,0 @@ -import time -import pytest -from port_dpb import Port -from port_dpb import DPB - -@pytest.mark.usefixtures('dpb_setup_fixture') -@pytest.mark.usefixtures('dvs_vlan_manager') -class TestPortDPBVlan(object): - def check_syslog(self, dvs, marker, log, expected_cnt): - (exitcode, num) = dvs.runcmd(['sh', '-c', "awk \'/%s/,ENDFILE {print;}\' /var/log/syslog | grep \"%s\" | wc -l" % (marker, log)]) - assert num.strip() >= str(expected_cnt) - - def test_dependency(self, dvs): - vlan = "100" - p = Port(dvs, "Ethernet0") - p.sync_from_config_db() - - # 1. Create VLAN100 - self.dvs_vlan.create_vlan(vlan) - - # 2. Add Ethernet0 to VLAN100 - self.dvs_vlan.create_vlan_member(vlan, p.get_name()) - - # 3. Add log marker to syslog - marker = dvs.add_log_marker() - - # 4. Delete Ethernet0 from config DB. Sleep for 2 seconds. - p.delete_from_config_db() - time.sleep(2) - - # 5. Verify that we are waiting in portsorch for the port - # to be removed from VLAN, by looking at the log - self.check_syslog(dvs, marker, "Cannot remove port as bridge port OID is present", 1) - - # 6. Also verify that port is still present in ASIC DB. - assert(p.exists_in_asic_db() == True) - - # 7. Remove port from VLAN - self.dvs_vlan.remove_vlan_member(vlan, p.get_name()) - - # 8. Verify that port is removed from ASIC DB - assert(p.not_exists_in_asic_db() == True) - - # 9. Re-create port Ethernet0 and verify that it is - # present in CONFIG, APPL, and ASIC DBs - p.write_to_config_db() - p.verify_config_db() - p.verify_app_db() - p.verify_asic_db() - - # 10. Remove VLAN100 and verify that its removed. - self.dvs_vlan.remove_vlan(vlan) - self.dvs_vlan.get_and_verify_vlan_ids(0) - - @pytest.mark.skip(reason="Failing. Under investigation") - def test_one_port_one_vlan(self, dvs): - dpb = DPB() - vlan = "100" - - # 1. Create VLAN100 and add Ethernet0 as member - self.dvs_vlan.create_vlan(vlan) - self.dvs_vlan.create_vlan_member(vlan, "Ethernet0") - self.dvs_vlan.get_and_verify_vlan_member_ids(1) - - # 2. Delete Ethernet0 from config DB. Verify that its deleted - # CONFIG and APPL DB and its still present in ASIC DB - p = Port(dvs, "Ethernet0") - p.sync_from_config_db() - p.delete_from_config_db() - assert(p.exists_in_config_db() == False) - assert(p.exists_in_app_db() == False) - assert(p.exists_in_asic_db() == True) - - # 3. Verify that Ethernet0 gets deleted from ASIC DB once - # its removed from VLAN100. - self.dvs_vlan.remove_vlan_member(vlan, "Ethernet0") - self.dvs_vlan.get_and_verify_vlan_member_ids(0) - assert(p.not_exists_in_asic_db() == True) - - # 4. To simulate port breakout, 1x100G --> 4x25G, create 4 ports - dpb.create_child_ports(dvs, p, 4) - - # 5. Add all 4 ports to VLAN100 - port_names = ["Ethernet0", "Ethernet1", "Ethernet2", "Ethernet3"] - vlan_member_count = 0 - for pname in port_names: - self.dvs_vlan.create_vlan_member(vlan, pname) - vlan_member_count = vlan_member_count + 1 - self.dvs_vlan.get_and_verify_vlan_member_ids(vlan_member_count) - - # 6. Delete 4 ports from CONFIG DB. Verify that they are all deleted - # from CONFIG and APPL DB but still present in ASIC DB - child_ports = [] - for pname in port_names: - cp = Port(dvs, pname) - cp.sync_from_config_db() - cp.delete_from_config_db() - assert(cp.exists_in_config_db() == False) - assert(cp.exists_in_app_db() == False) - assert(cp.exists_in_asic_db() == True) - child_ports.append(cp) - - # 7. Remove all 4 ports from VLAN100 and verify that they all get - # deleted from ASIC DB - for cp in child_ports: - self.dvs_vlan.remove_vlan_member(vlan, cp.get_name()) - vlan_member_count = vlan_member_count - 1 - self.dvs_vlan.get_and_verify_vlan_member_ids(vlan_member_count) - assert(cp.not_exists_in_asic_db() == True) - - # 8. Re-create Ethernet0 and verify that its created all 3 DBs - p.write_to_config_db() - p.verify_config_db() - p.verify_app_db() - p.verify_asic_db() - - # 9. Remove VLAN100 and verify the same - self.dvs_vlan.remove_vlan(vlan) - self.dvs_vlan.get_and_verify_vlan_ids(0) - - @pytest.mark.skip(reason="Failing. Under investigation") - def test_one_port_multiple_vlan(self, dvs): - - dpb = DPB() - vlans = ["100", "101", "102"] - - # 1. Create 3 VLANs - for vlan in vlans: - self.dvs_vlan.create_vlan(vlan) - - # 2. Add Ethernet0 to all 3 VLANs and verify - for vlan in vlans: - self.dvs_vlan.create_vlan_member(vlan, "Ethernet0") - self.dvs_vlan.get_and_verify_vlan_member_ids(len(vlans)) - - # 3. Delete Ethernet0 from CONFIG DB. Verify that it is deleted - # from CONFIG and APPl DB, whereas still present in ASIC DB. - p = Port(dvs, "Ethernet0") - p.sync_from_config_db() - p.delete_from_config_db() - assert(p.exists_in_config_db() == False) - assert(p.exists_in_app_db() == False) - assert(p.exists_in_asic_db() == True) - - # 4. Remove Ethernet0 from one of the VLANs and verify that - # its still present in ASIC DB - self.dvs_vlan.remove_vlan_member(vlans[0], "Ethernet0") - self.dvs_vlan.get_and_verify_vlan_member_ids(len(vlans)-1) - assert(p.exists_in_asic_db() == True) - - # 5. Remove Ethernet0 from one more VLAN and verify that - # its still present in ASIC DB - self.dvs_vlan.remove_vlan_member(vlans[1], "Ethernet0") - self.dvs_vlan.get_and_verify_vlan_member_ids(len(vlans)-2) - assert(p.exists_in_asic_db() == True) - - # 6. Remove Ethernet0 from last VLAN as well and verify that - # its deleted from ASIC DB - self.dvs_vlan.remove_vlan_member(vlans[2], "Ethernet0") - self.dvs_vlan.get_and_verify_vlan_member_ids(0) - assert(p.not_exists_in_asic_db() == True) - - # 7. To Simulate 1x40G --> 4x10G, create 4 ports - dpb.create_child_ports(dvs, p, 4) - - # 8. To Simulate 4x10G --> 1x40G, delete all 4 ports and re-create Ethernet0 - port_names = ["Ethernet0", "Ethernet1", "Ethernet2", "Ethernet3"] - for pname in port_names: - cp = Port(dvs, pname) - cp.sync_from_config_db() - cp.delete_from_config_db() - assert(cp.exists_in_config_db() == False) - assert(cp.exists_in_app_db() == False) - assert(cp.not_exists_in_asic_db() == True) - - p.write_to_config_db() - p.verify_config_db() - p.verify_app_db() - p.verify_asic_db() - - # 9. Remove all 3 VLANs and verify the same - self.dvs_vlan.remove_vlan("100") - self.dvs_vlan.remove_vlan("101") - self.dvs_vlan.remove_vlan("102") - self.dvs_vlan.get_and_verify_vlan_ids(0) - - @pytest.mark.skip(reason="Failing. Under investigation") - def test_all_port_10_vlans(self, dvs): - num_vlans = 10 - start_vlan = 100 - num_ports = 32 - port_names = [] - vlan_names = [] - - dvs.setup_db() - for i in range(num_ports): - port_names.append("Ethernet" + str(i*4)) - - for i in range(num_vlans): - vlan_names.append(str(start_vlan + i)) - - # 1. Create 10 VLANs - for vlan_name in vlan_names: - self.dvs_vlan.create_vlan(vlan_name) - - # 2. Add all 32 ports to all 10 VLANs - for port_name in port_names: - for vlan_name in vlan_names: - self.dvs_vlan.create_vlan_member(vlan_name, port_name, tagging_mode = "tagged") - self.dvs_vlan.get_and_verify_vlan_member_ids(num_ports*num_vlans) - - # 3. Do the following for each port - # 3.1. Delete port from CONFIG DB and verify that its deleted from - # CONFIG DB and APPL DB but not from ASIC DB. - # 3.2. Remove the port from all 10 VLANs and verify that it - # gets deleted from ASIC DB - ports = [] - for port_name in port_names: - p = Port(dvs, port_name) - ports.append(p) - p.sync_from_config_db() - p.delete_from_config_db() - assert(p.exists_in_config_db() == False) - assert(p.exists_in_app_db() == False) - assert(p.exists_in_asic_db() == True) - for vlan_name in vlan_names: - self.dvs_vlan.remove_vlan_member(vlan_name, port_name) - - self.dvs_vlan.get_and_verify_vlan_member_ids((num_ports*num_vlans)-(len(ports)*num_vlans)) - assert(p.not_exists_in_asic_db() == True) - - # 4. Re-create all ports and verify the same - for p in ports: - p.write_to_config_db() - p.verify_config_db() - p.verify_app_db() - p.verify_asic_db() - - # 5. Remove all VLANs and verify the same - for vlan_name in vlan_names: - self.dvs_vlan.remove_vlan(vlan_name) - self.dvs_vlan.get_and_verify_vlan_ids(0) - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_port_fec_override.py b/tests/test_port_fec_override.py deleted file mode 100644 index 08d960116d..0000000000 --- a/tests/test_port_fec_override.py +++ /dev/null @@ -1,46 +0,0 @@ -import time -import os -import pytest - -from swsscommon import swsscommon - -DVS_ENV = ["HWSKU=Mellanox-SN2700"] - -class TestPort(object): - def test_PortFecOverride(self, dvs, testlog): - db = swsscommon.DBConnector(0, dvs.redis_sock, 0) - adb = dvs.get_asic_db() - - ptbl = swsscommon.ProducerStateTable(db, "PORT_TABLE") - - # set fec - fvs = swsscommon.FieldValuePairs([("fec","auto")]) - ptbl.set("Ethernet0", fvs) - fvs = swsscommon.FieldValuePairs([("fec","rs")]) - ptbl.set("Ethernet4", fvs) - - # validate if fec none is pushed to asic db when set first time - port_oid = adb.port_name_map["Ethernet0"] - expected_fields = {"SAI_PORT_ATTR_FEC_MODE":"SAI_PORT_FEC_MODE_NONE", "SAI_PORT_ATTR_AUTO_NEG_FEC_MODE_OVERRIDE":"false"} - adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) - - # validate if fec rs is pushed to asic db when set first time - port_oid = adb.port_name_map["Ethernet4"] - expected_fields = {"SAI_PORT_ATTR_FEC_MODE":"SAI_PORT_FEC_MODE_RS", "SAI_PORT_ATTR_AUTO_NEG_FEC_MODE_OVERRIDE":"true"} - adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) - - fvs = swsscommon.FieldValuePairs([("fec","none")]) - ptbl.set("Ethernet0", fvs) - ptbl.set("Ethernet4", fvs) - port_oid = adb.port_name_map["Ethernet0"] - expected_fields = {"SAI_PORT_ATTR_FEC_MODE":"SAI_PORT_FEC_MODE_NONE", "SAI_PORT_ATTR_AUTO_NEG_FEC_MODE_OVERRIDE":"true"} - adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) - port_oid = adb.port_name_map["Ethernet4"] - expected_fields = {"SAI_PORT_ATTR_FEC_MODE":"SAI_PORT_FEC_MODE_NONE", "SAI_PORT_ATTR_AUTO_NEG_FEC_MODE_OVERRIDE":"true"} - adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_port_lt.py b/tests/test_port_lt.py deleted file mode 100644 index 0da6abb071..0000000000 --- a/tests/test_port_lt.py +++ /dev/null @@ -1,139 +0,0 @@ -import time -import os -import pytest - -from swsscommon import swsscommon - - -class TestPortLinkTraining(object): - def test_PortLinkTrainingForce(self, dvs, testlog): - - db = swsscommon.DBConnector(0, dvs.redis_sock, 0) - adb = dvs.get_asic_db() - - tbl = swsscommon.ProducerStateTable(db, "PORT_TABLE") - fvs = swsscommon.FieldValuePairs([("link_training","off")]) - tbl.set("Ethernet0", fvs) - - tbl = swsscommon.ProducerStateTable(db, "PORT_TABLE") - fvs = swsscommon.FieldValuePairs([("link_training","on")]) - tbl.set("Ethernet4", fvs) - - # validate if link_training false is pushed to asic db when set first time - port_oid = adb.port_name_map["Ethernet0"] - expected_fields = {"SAI_PORT_ATTR_LINK_TRAINING_ENABLE":"false"} - adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) - - # validate if link_training true is pushed to asic db when set first time - port_oid = adb.port_name_map["Ethernet4"] - expected_fields = {"SAI_PORT_ATTR_LINK_TRAINING_ENABLE":"true"} - adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) - - def test_PortLinkTrainingCold(self, dvs, testlog): - db = swsscommon.DBConnector(0, dvs.redis_sock, 0) - - tbl = swsscommon.ProducerStateTable(db, "PORT_TABLE") - - # set link_training = true - fvs = swsscommon.FieldValuePairs([("link_training","on")]) - - tbl.set("Ethernet0", fvs) - - time.sleep(1) - - adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - - atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_PORT") - (status, fvs) = atbl.get(dvs.asicdb.portnamemap["Ethernet0"]) - assert status == True - - assert "SAI_PORT_ATTR_LINK_TRAINING_ENABLE" in [fv[0] for fv in fvs] - for fv in fvs: - if fv[0] == "SAI_PORT_ATTR_LINK_TRAINING_ENABLE": - assert fv[1] == "true" - - # change link_training to false - fvs = swsscommon.FieldValuePairs([("link_training","off")]) - - tbl.set("Ethernet0", fvs) - - time.sleep(1) - - (status, fvs) = atbl.get(dvs.asicdb.portnamemap["Ethernet0"]) - assert status == True - - assert "SAI_PORT_ATTR_LINK_TRAINING_ENABLE" in [fv[0] for fv in fvs] - for fv in fvs: - if fv[0] == "SAI_PORT_ATTR_LINK_TRAINING_ENABLE": - assert fv[1] == "false" - - def test_PortLinkTrainingWarm(self, dvs, testlog): - - db = swsscommon.DBConnector(0, dvs.redis_sock, 0) - cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) - sdb = swsscommon.DBConnector(6, dvs.redis_sock, 0) - - tbl = swsscommon.ProducerStateTable(db, "PORT_TABLE") - ctbl = swsscommon.Table(cdb, "PORT") - stbl = swsscommon.Table(sdb, "PORT_TABLE") - - # set link_training = true - fvs = swsscommon.FieldValuePairs([("link_training","on")]) - ctbl.set("Ethernet0", fvs) - - time.sleep(1) - - adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - - atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_PORT") - (status, fvs) = atbl.get(dvs.asicdb.portnamemap["Ethernet0"]) - assert status == True - - assert "SAI_PORT_ATTR_LINK_TRAINING_ENABLE" in [fv[0] for fv in fvs] - for fv in fvs: - if fv[0] == "SAI_PORT_ATTR_AUTO_NEG_MODE": - assert fv[1] == "true" - - # set admin up - cfvs = swsscommon.FieldValuePairs([("admin_status", "up")]) - ctbl.set("Ethernet0", cfvs) - - # enable warm restart - (exitcode, result) = dvs.runcmd("config warm_restart enable swss") - assert exitcode == 0 - - # freeze orchagent for warm restart - (exitcode, result) = dvs.runcmd("/usr/bin/orchagent_restart_check", include_stderr=False) - assert result == "RESTARTCHECK succeeded\n" - time.sleep(2) - - try: - # restart orchagent - # clean port state - dvs.stop_swss() - ports = stbl.getKeys() - for port in ports: - stbl._del(port) - dvs.start_swss() - time.sleep(2) - - # check ASIC DB after warm restart - (status, fvs) = atbl.get(dvs.asicdb.portnamemap["Ethernet0"]) - assert status == True - - assert "SAI_PORT_ATTR_LINK_TRAINING_ENABLE" in [fv[0] for fv in fvs] - for fv in fvs: - if fv[0] == "SAI_PORT_ATTR_LINK_TRAINING_ENABLE": - assert fv[1] == "true" - - finally: - # disable warm restart - dvs.runcmd("config warm_restart disable swss") - # slow down crm polling - dvs.runcmd("crm config polling interval 10000") - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_port_mac_learn.py b/tests/test_port_mac_learn.py deleted file mode 100644 index 32c01ab050..0000000000 --- a/tests/test_port_mac_learn.py +++ /dev/null @@ -1,189 +0,0 @@ -import time -import os -import pytest - -from swsscommon import swsscommon - - -class TestPortMacLearn(object): - def setup_db(self, dvs): - self.pdb = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - self.adb = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - self.cdb = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - self.cntdb = swsscommon.DBConnector(swsscommon.COUNTERS_DB, dvs.redis_sock, 0) - - def get_learn_mode_map(self): - learn_mode_map = { "drop": "SAI_BRIDGE_PORT_FDB_LEARNING_MODE_DROP", - "disable": "SAI_BRIDGE_PORT_FDB_LEARNING_MODE_DISABLE", - "hardware": "SAI_BRIDGE_PORT_FDB_LEARNING_MODE_HW", - "cpu_trap": "SAI_BRIDGE_PORT_FDB_LEARNING_MODE_CPU_TRAP", - "cpu_log": "SAI_BRIDGE_PORT_FDB_LEARNING_MODE_CPU_LOG", - "notification": "SAI_BRIDGE_PORT_FDB_LEARNING_MODE_FDB_NOTIFICATION"} - return learn_mode_map - - def get_port_oid(self, port_name): - port_map_tbl = swsscommon.Table(self.cntdb, 'COUNTERS_PORT_NAME_MAP') - for k in port_map_tbl.get('')[1]: - if k[0] == port_name: - return k[1] - return None - - def get_bridge_port_oid(self, port_oid): - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") - for key in tbl.getKeys(): - status, data = tbl.get(key) - assert status - values = dict(data) - if port_oid == values["SAI_BRIDGE_PORT_ATTR_PORT_ID"]: - return key - return None - - def check_learn_mode_in_appdb(self, table, interface, learn_mode): - (status, fvs) = table.get(interface) - assert status == True - for fv in fvs: - if fv[0] == "learn_mode": - if fv[1] == learn_mode: - return True - return False - - def check_learn_mode_in_asicdb(self, interface_oid, learn_mode): - # Get bridge port oid - bridge_port_oid = self.get_bridge_port_oid(interface_oid) - assert bridge_port_oid is not None - - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") - (status, fvs) = tbl.get(bridge_port_oid) - assert status == True - values = dict(fvs) - if values["SAI_BRIDGE_PORT_ATTR_FDB_LEARNING_MODE"] == learn_mode: - return True - else: - return False - - def test_PortMacLearnMode(self, dvs, testlog): - self.setup_db(dvs) - - # create vlan - tbl = swsscommon.Table(self.cdb, "VLAN") - fvs = swsscommon.FieldValuePairs([("vlanid", "2")]) - tbl.set("Vlan2", fvs) - time.sleep(1) - - # create vlan member entry in application db - tbl = swsscommon.Table(self.cdb, "VLAN_MEMBER") - fvs = swsscommon.FieldValuePairs([("tagging_mode", "untagged")]) - tbl.set("Vlan2|Ethernet8", fvs) - time.sleep(1) - - # get port oid - port_oid = self.get_port_oid("Ethernet8") - assert port_oid is not None - - # check asicdb before setting mac learn mode; The default learn_mode value is SAI_BRIDGE_PORT_FDB_LEARNING_MODE_HW. - status = self.check_learn_mode_in_asicdb(port_oid, "SAI_BRIDGE_PORT_FDB_LEARNING_MODE_HW") - assert status == True - - learn_mode_map = self.get_learn_mode_map() - for key, value in learn_mode_map.items(): - # set MAC learn mode to port - tbl = swsscommon.Table(self.cdb, "PORT") - fvs = swsscommon.FieldValuePairs([("learn_mode", key)]) - tbl.set("Ethernet8", fvs) - time.sleep(1) - - # check application database - tbl = swsscommon.Table(self.pdb, "PORT_TABLE") - status = self.check_learn_mode_in_appdb(tbl, "Ethernet8", key) - assert status == True - - # check ASIC bridge port database - status = self.check_learn_mode_in_asicdb(port_oid, value) - assert status == True - - # set default learn mode for Ethernet8 - tbl = swsscommon.Table(self.cdb, "PORT") - fvs = swsscommon.FieldValuePairs([("learn_mode", "hardware")]) - tbl.set("Ethernet8", fvs) - time.sleep(1) - - # remove vlan member - tbl = swsscommon.Table(self.cdb, "VLAN_MEMBER") - tbl._del("Vlan2|Ethernet8") - time.sleep(1) - - # remove vlan - tbl = swsscommon.Table(self.cdb, "VLAN") - tbl._del("Vlan2") - time.sleep(1) - - def test_PortchannelMacLearnMode(self, dvs, testlog): - self.setup_db(dvs) - - #create portchannel - tbl = swsscommon.Table(self.cdb, "PORTCHANNEL") - fvs = swsscommon.FieldValuePairs([("admin_status", "up"), - ("mtu", "9100")]) - tbl.set("PortChannel001", fvs) - time.sleep(1) - - # create vlan - tbl = swsscommon.Table(self.cdb, "VLAN") - fvs = swsscommon.FieldValuePairs([("vlanid", "3")]) - tbl.set("Vlan3", fvs) - time.sleep(1) - - # create vlan member entry in application db - tbl = swsscommon.Table(self.cdb, "VLAN_MEMBER") - fvs = swsscommon.FieldValuePairs([("tagging_mode", "untagged")]) - tbl.set("Vlan3|PortChannel001", fvs) - time.sleep(1) - - # get PortChannel oid; When sonic-swss pr885 is complete, you can get oid directly from COUNTERS_LAG_NAME_MAP, which would be better. - lag_tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_LAG") - lag_entries = lag_tbl.getKeys() - # At this point there should be only one lag in the system, which is PortChannel001. - assert len(lag_entries) == 1 - lag_oid = lag_entries[0] - - # check asicdb before setting mac learn mode; The default learn_mode value is SAI_BRIDGE_PORT_FDB_LEARNING_MODE_HW. - status = self.check_learn_mode_in_asicdb(lag_oid, "SAI_BRIDGE_PORT_FDB_LEARNING_MODE_HW") - assert status == True - - learn_mode_map = self.get_learn_mode_map() - for key, value in learn_mode_map.items(): - # set mac learn mode to PortChannel - tbl = swsscommon.Table(self.cdb, "PORTCHANNEL") - fvs = swsscommon.FieldValuePairs([("learn_mode", key)]) - tbl.set("PortChannel001", fvs) - time.sleep(1) - - # check application database - tbl = swsscommon.Table(self.pdb, "LAG_TABLE") - status = self.check_learn_mode_in_appdb(tbl, "PortChannel001", key) - assert status == True - - # check ASIC bridge port database - status = self.check_learn_mode_in_asicdb(lag_oid, value) - assert status == True - - # remove vlan member - tbl = swsscommon.Table(self.cdb, "VLAN_MEMBER") - tbl._del("Vlan3|PortChannel001") - time.sleep(1) - - # create vlan - tbl = swsscommon.Table(self.cdb, "VLAN") - tbl._del("Vlan3") - time.sleep(1) - - # remove PortChannel - tbl = swsscommon.Table(self.cdb, "PORTCHANNEL") - tbl._del("PortChannel001") - time.sleep(1) - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_portchannel.py b/tests/test_portchannel.py deleted file mode 100644 index 0a922e6936..0000000000 --- a/tests/test_portchannel.py +++ /dev/null @@ -1,470 +0,0 @@ -import pytest -import time -import re -import json -import itertools - -from swsscommon import swsscommon - - -@pytest.mark.usefixtures('dvs_lag_manager') -class TestPortchannel(object): - def test_Portchannel(self, dvs, testlog): - - # create port channel - db = swsscommon.DBConnector(0, dvs.redis_sock, 0) - ps = swsscommon.ProducerStateTable(db, "LAG_TABLE") - fvs = swsscommon.FieldValuePairs([("admin", "up"), ("mtu", "1500")]) - - ps.set("PortChannel0001", fvs) - - # create port channel member - ps = swsscommon.ProducerStateTable(db, "LAG_MEMBER_TABLE") - fvs = swsscommon.FieldValuePairs([("status", "enabled")]) - - ps.set("PortChannel0001:Ethernet0", fvs) - - time.sleep(1) - - # check asic db - asicdb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - - lagtbl = swsscommon.Table(asicdb, "ASIC_STATE:SAI_OBJECT_TYPE_LAG") - lags = lagtbl.getKeys() - assert len(lags) == 1 - - lagmtbl = swsscommon.Table(asicdb, "ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER") - lagms = lagmtbl.getKeys() - assert len(lagms) == 1 - - (status, fvs) = lagmtbl.get(lagms[0]) - fvs = dict(fvs) - assert status - assert "SAI_LAG_MEMBER_ATTR_LAG_ID" in fvs - assert fvs.pop("SAI_LAG_MEMBER_ATTR_LAG_ID") == lags[0] - assert "SAI_LAG_MEMBER_ATTR_PORT_ID" in fvs - assert dvs.asicdb.portoidmap[fvs.pop("SAI_LAG_MEMBER_ATTR_PORT_ID")] == "Ethernet0" - assert "SAI_LAG_MEMBER_ATTR_INGRESS_DISABLE" in fvs - assert fvs.pop("SAI_LAG_MEMBER_ATTR_INGRESS_DISABLE") == "false" - assert "SAI_LAG_MEMBER_ATTR_EGRESS_DISABLE" in fvs - assert fvs.pop("SAI_LAG_MEMBER_ATTR_EGRESS_DISABLE") == "false" - assert not fvs - - ps = swsscommon.ProducerStateTable(db, "LAG_MEMBER_TABLE") - fvs = swsscommon.FieldValuePairs([("status", "disabled")]) - - ps.set("PortChannel0001:Ethernet0", fvs) - - time.sleep(1) - - lagmtbl = swsscommon.Table(asicdb, "ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER") - lagms = lagmtbl.getKeys() - assert len(lagms) == 1 - - (status, fvs) = lagmtbl.get(lagms[0]) - fvs = dict(fvs) - assert status - assert "SAI_LAG_MEMBER_ATTR_LAG_ID" in fvs - assert fvs.pop("SAI_LAG_MEMBER_ATTR_LAG_ID") == lags[0] - assert "SAI_LAG_MEMBER_ATTR_PORT_ID" in fvs - assert dvs.asicdb.portoidmap[fvs.pop("SAI_LAG_MEMBER_ATTR_PORT_ID")] == "Ethernet0" - assert "SAI_LAG_MEMBER_ATTR_INGRESS_DISABLE" in fvs - assert fvs.pop("SAI_LAG_MEMBER_ATTR_INGRESS_DISABLE") == "true" - assert "SAI_LAG_MEMBER_ATTR_EGRESS_DISABLE" in fvs - assert fvs.pop("SAI_LAG_MEMBER_ATTR_EGRESS_DISABLE") == "true" - assert not fvs - - # remove port channel member - ps = swsscommon.ProducerStateTable(db, "LAG_MEMBER_TABLE") - ps._del("PortChannel0001:Ethernet0") - - # remove port channel - ps = swsscommon.ProducerStateTable(db, "LAG_TABLE") - ps._del("PortChannel0001") - - time.sleep(1) - - # check asic db - lags = lagtbl.getKeys() - assert len(lags) == 0 - - lagms = lagmtbl.getKeys() - assert len(lagms) == 0 - - @pytest.mark.parametrize("fast_rate", [False, True]) - def test_Portchannel_fast_rate(self, dvs, testlog, fast_rate): - po_id = "0003" - po_member = "Ethernet16" - - # Create PortChannel - self.dvs_lag.create_port_channel(po_id, fast_rate=fast_rate) - self.dvs_lag.get_and_verify_port_channel(1) - - # Add member to PortChannel - self.dvs_lag.create_port_channel_member(po_id, po_member) - self.dvs_lag.get_and_verify_port_channel_members(1) - - # test fast rate configuration - self.dvs_lag.get_and_verify_port_channel_fast_rate(po_id, fast_rate) - - # remove PortChannel - self.dvs_lag.create_port_channel_member(po_id, po_member) - self.dvs_lag.remove_port_channel(po_id) - self.dvs_lag.get_and_verify_port_channel(0) - - - def test_Portchannel_lacpkey(self, dvs, testlog): - portchannelNamesAuto = [("PortChannel001", "Ethernet0", 1001), - ("PortChannel002", "Ethernet4", 1002), - ("PortChannel2", "Ethernet8", 12), - ("PortChannel000", "Ethernet12", 1000)] - - portchannelNames = [("PortChannel0003", "Ethernet16", 0), - ("PortChannel0004", "Ethernet20", 0), - ("PortChannel0005", "Ethernet24", 564)] - - self.cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) - - # Create PortChannels - tbl = swsscommon.Table(self.cdb, "PORTCHANNEL") - fvs = swsscommon.FieldValuePairs( - [("admin_status", "up"), ("mtu", "9100"), ("oper_status", "up"), ("lacp_key", "auto")]) - - for portchannel in portchannelNamesAuto: - tbl.set(portchannel[0], fvs) - - fvs_no_lacp_key = swsscommon.FieldValuePairs( - [("admin_status", "up"), ("mtu", "9100"), ("oper_status", "up")]) - tbl.set(portchannelNames[0][0], fvs_no_lacp_key) - - fvs_empty_lacp_key = swsscommon.FieldValuePairs( - [("admin_status", "up"), ("mtu", "9100"), ("oper_status", "up"), ("lacp_key", "")]) - tbl.set(portchannelNames[1][0], fvs_empty_lacp_key) - - fvs_set_number_lacp_key = swsscommon.FieldValuePairs( - [("admin_status", "up"), ("mtu", "9100"), ("oper_status", "up"), ("lacp_key", "564")]) - tbl.set(portchannelNames[2][0], fvs_set_number_lacp_key) - time.sleep(1) - - # Add members to PortChannels - tbl = swsscommon.Table(self.cdb, "PORTCHANNEL_MEMBER") - fvs = swsscommon.FieldValuePairs([("NULL", "NULL")]) - - for portchannel in itertools.chain(portchannelNames, portchannelNamesAuto): - tbl.set(portchannel[0] + "|" + portchannel[1], fvs) - time.sleep(1) - - # TESTS here that LACP key is valid and equls to the expected LACP key - # The expected LACP key in the number at the end of the Port-Channel name with a prefix '1' - for portchannel in itertools.chain(portchannelNames, portchannelNamesAuto): - (exit_code, output) = dvs.runcmd("teamdctl " + portchannel[0] + " state dump") - port_state_dump = json.loads(output) - lacp_key = port_state_dump["ports"][portchannel[1]]["runner"]["actor_lacpdu_info"]["key"] - assert lacp_key == portchannel[2] - - # remove PortChannel members - tbl = swsscommon.Table(self.cdb, "PORTCHANNEL_MEMBER") - for portchannel in itertools.chain(portchannelNames, portchannelNamesAuto): - tbl._del(portchannel[0] + "|" + portchannel[1]) - time.sleep(1) - - # remove PortChannel - tbl = swsscommon.Table(self.cdb, "PORTCHANNEL") - for portchannel in itertools.chain(portchannelNames, portchannelNamesAuto): - tbl._del(portchannel[0]) - time.sleep(1) - - def test_Portchannel_oper_down(self, dvs, testlog): - - self.adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - self.cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) - self.pdb = swsscommon.DBConnector(0, dvs.redis_sock, 0) - - # Create 4 PortChannels - tbl = swsscommon.Table(self.cdb, "PORTCHANNEL") - fvs = swsscommon.FieldValuePairs([("admin_status", "up"),("mtu", "9100"),("oper_status", "up")]) - - tbl.set("PortChannel001", fvs) - time.sleep(1) - tbl.set("PortChannel002", fvs) - time.sleep(1) - tbl.set("PortChannel003", fvs) - time.sleep(1) - tbl.set("PortChannel004", fvs) - time.sleep(1) - - tbl = swsscommon.Table(self.cdb, "PORTCHANNEL_MEMBER") - fvs = swsscommon.FieldValuePairs([("NULL", "NULL")]) - tbl.set("PortChannel001|Ethernet0", fvs) - time.sleep(1) - tbl.set("PortChannel002|Ethernet4", fvs) - time.sleep(1) - tbl.set("PortChannel003|Ethernet8", fvs) - time.sleep(1) - tbl.set("PortChannel004|Ethernet12", fvs) - time.sleep(1) - - tbl = swsscommon.Table(self.cdb, "PORTCHANNEL_INTERFACE") - fvs = swsscommon.FieldValuePairs([("NULL", "NULL")]) - tbl.set("PortChannel001", fvs) - tbl.set("PortChannel001|40.0.0.0/31", fvs) - time.sleep(1) - tbl.set("PortChannel002", fvs) - tbl.set("PortChannel002|40.0.0.2/31", fvs) - time.sleep(1) - tbl.set("PortChannel003", fvs) - tbl.set("PortChannel003|40.0.0.4/31", fvs) - time.sleep(1) - tbl.set("PortChannel004", fvs) - tbl.set("PortChannel004|40.0.0.6/31", fvs) - time.sleep(1) - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:PortChannel001") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 1 - assert intf_entries[0] == "40.0.0.0/31" - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:PortChannel002") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 1 - assert intf_entries[0] == "40.0.0.2/31" - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:PortChannel003") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 1 - assert intf_entries[0] == "40.0.0.4/31" - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:PortChannel004") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 1 - assert intf_entries[0] == "40.0.0.6/31" - - # set oper_status for PortChannels - ps = swsscommon.ProducerStateTable(self.pdb, "LAG_TABLE") - fvs = swsscommon.FieldValuePairs([("admin_status", "up"),("mtu", "9100"),("oper_status", "up")]) - ps.set("PortChannel001", fvs) - ps.set("PortChannel002", fvs) - ps.set("PortChannel003", fvs) - ps.set("PortChannel004", fvs) - time.sleep(1) - - dvs.runcmd("arp -s 40.0.0.1 00:00:00:00:00:01") - time.sleep(1) - dvs.runcmd("arp -s 40.0.0.3 00:00:00:00:00:03") - time.sleep(1) - dvs.runcmd("arp -s 40.0.0.5 00:00:00:00:00:05") - time.sleep(1) - dvs.runcmd("arp -s 40.0.0.7 00:00:00:00:00:07") - time.sleep(1) - - ps = swsscommon.ProducerStateTable(self.pdb, "ROUTE_TABLE") - fvs = swsscommon.FieldValuePairs([("nexthop","40.0.0.1,40.0.0.3,40.0.0.5,40.0.0.7"), - ("ifname", "PortChannel001,PortChannel002,PortChannel003,PortChannel004")]) - ps.set("2.2.2.0/24", fvs) - time.sleep(1) - - # check if route has propagated to ASIC DB - re_tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - - found_route = False - for key in re_tbl.getKeys(): - route = json.loads(key) - if route["dest"] == "2.2.2.0/24": - found_route = True - break - - assert found_route - - # check if route points to next hop group - nhg_tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP") - (status, fvs) = re_tbl.get(key) - for v in fvs: - if v[0] == "SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID": - nhg_id = v[1] - - (status, fvs) = nhg_tbl.get(nhg_id) - assert status - - # check if next hop group consists of 4 members - nhg_member_tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER") - keys = nhg_member_tbl.getKeys() - assert len(keys) == 4 - - for key in keys: - (status, fvs) = nhg_member_tbl.get(key) - for v in fvs: - if v[0] == "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID": - assert v[1] == nhg_id - - # bring PortChannel down - dvs.servers[0].runcmd("ip link set down dev eth0") - time.sleep(1) - ps = swsscommon.ProducerStateTable(self.pdb, "LAG_TABLE") - fvs = swsscommon.FieldValuePairs([("admin_status", "up"),("mtu", "9100"),("oper_status", "down")]) - ps.set("PortChannel001", fvs) - time.sleep(1) - - # check if next hop group consists of 3 member - keys = nhg_member_tbl.getKeys() - assert len(keys) == 3 - - # remove route entry - ps = swsscommon.ProducerStateTable(self.pdb, "ROUTE_TABLE") - ps._del("2.2.2.0/24") - time.sleep(1) - - # remove IP address - tbl = swsscommon.Table(self.cdb, "PORTCHANNEL_INTERFACE") - tbl._del("PortChannel001|40.0.0.0/31") - tbl._del("PortChannel002|40.0.0.2/31") - tbl._del("PortChannel003|40.0.0.4/31") - tbl._del("PortChannel004|40.0.0.6/31") - time.sleep(1) - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:PortChannel001") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:PortChannel002") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:PortChannel003") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - tbl = swsscommon.Table(self.pdb, "INTF_TABLE:PortChannel004") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - # remove router interfaces - tbl = swsscommon.Table(self.cdb, "PORTCHANNEL_INTERFACE") - tbl._del("PortChannel001") - tbl._del("PortChannel002") - tbl._del("PortChannel003") - tbl._del("PortChannel004") - time.sleep(1) - - # check application database - tbl = swsscommon.Table(self.pdb, "INTF_TABLE") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 - - # remove PortChannel members - tbl = swsscommon.Table(self.cdb, "PORTCHANNEL_MEMBER") - tbl._del("PortChannel001|Ethernet0") - tbl._del("PortChannel002|Ethernet4") - tbl._del("PortChannel003|Ethernet8") - tbl._del("PortChannel004|Ethernet12") - time.sleep(1) - - # remove PortChannel - tbl = swsscommon.Table(self.cdb, "PORTCHANNEL") - tbl._del("PortChannel001") - tbl._del("PortChannel002") - tbl._del("PortChannel003") - tbl._del("PortChannel004") - time.sleep(1) - - # Restore eth0 up - dvs.servers[0].runcmd("ip link set up dev eth0") - time.sleep(1) - - def test_Portchannel_tpid(self, dvs, testlog): - adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) - pdb = swsscommon.DBConnector(0, dvs.redis_sock, 0) - - # Create PortChannel - tbl = swsscommon.Table(cdb, "PORTCHANNEL") - fvs = swsscommon.FieldValuePairs([("admin_status", "up"),("mtu", "9100"),("tpid", "0x9200")]) - - tbl.set("PortChannel002", fvs) - time.sleep(1) - - # set oper_status for PortChannels - ps = swsscommon.ProducerStateTable(pdb, "LAG_TABLE") - fvs = swsscommon.FieldValuePairs([("admin_status", "up"),("mtu", "9100"),("tpid", "0x9200"),("oper_status", "up")]) - ps.set("PortChannel002", fvs) - time.sleep(1) - - # Check ASIC DB - # get TPID and validate it to be 0x9200 (37376) - atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_LAG") - lag = atbl.getKeys()[0] - (status, fvs) = atbl.get(lag) - assert status == True - asic_tpid = "0" - - for fv in fvs: - if fv[0] == "SAI_LAG_ATTR_TPID": - asic_tpid = fv[1] - - assert asic_tpid == "37376" - - # remove port channel - tbl = swsscommon.Table(cdb, "PORTCHANNEL") - tbl._del("PortChannel0002") - time.sleep(1) - - def test_portchannel_member_netdev_oper_status(self, dvs, testlog): - config_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - state_db = swsscommon.DBConnector(swsscommon.STATE_DB, dvs.redis_sock, 0) - app_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - - # create port-channel - tbl = swsscommon.Table(config_db, "PORTCHANNEL") - fvs = swsscommon.FieldValuePairs([("admin_status", "up"),("mtu", "9100"),("oper_status", "up")]) - tbl.set("PortChannel111", fvs) - - # set port-channel oper status - tbl = swsscommon.ProducerStateTable(app_db, "LAG_TABLE") - fvs = swsscommon.FieldValuePairs([("admin_status", "up"),("mtu", "9100"),("oper_status", "up")]) - tbl.set("PortChannel111", fvs) - - # add members to port-channel - tbl = swsscommon.Table(config_db, "PORTCHANNEL_MEMBER") - fvs = swsscommon.FieldValuePairs([("NULL", "NULL")]) - tbl.set("PortChannel111|Ethernet0", fvs) - tbl.set("PortChannel111|Ethernet4", fvs) - - # wait for port-channel netdev creation - time.sleep(1) - - # set netdev oper status - (exitcode, _) = dvs.runcmd("ip link set up dev Ethernet0") - assert exitcode == 0, "ip link set failed" - - (exitcode, _) = dvs.runcmd("ip link set up dev Ethernet4") - assert exitcode == 0, "ip link set failed" - - (exitcode, _) = dvs.runcmd("ip link set dev PortChannel111 carrier on") - assert exitcode == 0, "ip link set failed" - - # verify port-channel members netdev oper status - tbl = swsscommon.Table(state_db, "PORT_TABLE") - status, fvs = tbl.get("Ethernet0") - assert status is True - fvs = dict(fvs) - assert fvs['netdev_oper_status'] == 'up' - - status, fvs = tbl.get("Ethernet4") - assert status is True - fvs = dict(fvs) - assert fvs['netdev_oper_status'] == 'up' - - # remove port-channel members - tbl = swsscommon.Table(config_db, "PORTCHANNEL_MEMBER") - tbl._del("PortChannel111|Ethernet0") - tbl._del("PortChannel111|Ethernet4") - - # remove port-channel - tbl = swsscommon.Table(config_db, "PORTCHANNEL") - tbl._del("PortChannel111") - - # wait for port-channel deletion - time.sleep(1) - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_qos_map.py b/tests/test_qos_map.py deleted file mode 100644 index 905b0dacaa..0000000000 --- a/tests/test_qos_map.py +++ /dev/null @@ -1,627 +0,0 @@ -import json -import time - -from swsscommon import swsscommon - -CFG_TC_TO_DSCP_MAP_TABLE_NAME = "TC_TO_DSCP_MAP" -CFG_TC_TO_DSCP_MAP_KEY = "AZURE" -TC_TO_DSCP_MAP = { - "0": "20", - "1": "16", - "2": "5", - "3": "43", - "4": "34", - "5": "52", - "6": "61", - "7": "17", -} - -CFG_TC_TO_DOT1P_MAP_TABLE_NAME = "TC_TO_DOT1P_MAP" -CFG_TC_TO_DOT1P_MAP_KEY = "AZURE" -TC_TO_DOT1P_MAP = { - "0": "0", - "1": "6", - "2": "5", - "3": "3", - "4": "4", - "5": "2", - "6": "1", - "7": "7", -} - -CFG_DOT1P_TO_TC_MAP_TABLE_NAME = "DOT1P_TO_TC_MAP" -CFG_DOT1P_TO_TC_MAP_KEY = "AZURE" -DOT1P_TO_TC_MAP = { - "0": "0", - "1": "6", - "2": "5", - "3": "3", - "4": "4", - "5": "2", - "6": "1", - "7": "7", -} - -CFG_MPLS_TC_TO_TC_MAP_TABLE_NAME = "MPLS_TC_TO_TC_MAP" -CFG_MPLS_TC_TO_TC_MAP_KEY = "AZURE_MPLS_TC" -MPLS_TC_TO_TC_MAP = { - "0": "0", - "1": "4", - "2": "1", - "3": "3", - "4": "5", - "5": "2", - "6": "7", - "7": "6", -} - -CFG_PORT_QOS_MAP_TABLE_NAME = "PORT_QOS_MAP" -CFG_PORT_QOS_DOT1P_MAP_FIELD = "dot1p_to_tc_map" -CFG_PORT_QOS_MPLS_TC_MAP_FIELD = "mpls_tc_to_tc_map" -CFG_PORT_QOS_TC_DOT1P_MAP_FIELD = "tc_to_dot1p_map" -CFG_PORT_QOS_TC_DSCP_MAP_FIELD = "tc_to_dscp_map" -CFG_PORT_TABLE_NAME = "PORT" - -#Tests for TC-to-DSCP qos map configuration -class TestTcDscp(object): - def connect_dbs(self, dvs): - self.asic_db = swsscommon.DBConnector(1, dvs.redis_sock, 0) - self.config_db = swsscommon.DBConnector(4, dvs.redis_sock, 0) - - def create_tc_dscp_profile(self): - tbl = swsscommon.Table(self.config_db, CFG_TC_TO_DSCP_MAP_TABLE_NAME) - fvs = swsscommon.FieldValuePairs(list(TC_TO_DSCP_MAP.items())) - tbl.set(CFG_TC_TO_DSCP_MAP_KEY, fvs) - time.sleep(1) - - def find_tc_dscp_profile(self): - found = False - tc_dscp_map_raw = None - tbl = swsscommon.Table(self.asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_QOS_MAP") - keys = tbl.getKeys() - for key in keys: - (status, fvs) = tbl.get(key) - assert status == True - - for fv in fvs: - if fv[0] == "SAI_QOS_MAP_ATTR_MAP_TO_VALUE_LIST": - tc_dscp_map_raw = fv[1] - elif fv[0] == "SAI_QOS_MAP_ATTR_TYPE" and fv[1] == "SAI_QOS_MAP_TYPE_TC_AND_COLOR_TO_DSCP": - found = True - - if found: - break - - assert found == True - - return (key, tc_dscp_map_raw) - - def apply_tc_dscp_profile_on_all_ports(self): - tbl = swsscommon.Table(self.config_db, CFG_PORT_QOS_MAP_TABLE_NAME) - fvs = swsscommon.FieldValuePairs([(CFG_PORT_QOS_TC_DSCP_MAP_FIELD, CFG_TC_TO_DSCP_MAP_KEY)]) - ports = swsscommon.Table(self.config_db, CFG_PORT_TABLE_NAME).getKeys() - for port in ports: - tbl.set(port, fvs) - - time.sleep(1) - - - def test_tc_dscp_cfg(self, dvs): - self.connect_dbs(dvs) - self.create_tc_dscp_profile() - _, tc_dscp_map_raw = self.find_tc_dscp_profile() - - tc_dscp_map = json.loads(tc_dscp_map_raw) - for tc2dscp in tc_dscp_map['list']: - tc_val = str(tc2dscp['key']['tc']) - dscp_val = str(tc2dscp['value']['dscp']) - assert dscp_val == TC_TO_DSCP_MAP[tc_val] - - def test_port_tc_dscp(self, dvs): - self.connect_dbs(dvs) - self.create_tc_dscp_profile() - oid, _ = self.find_tc_dscp_profile() - - self.apply_tc_dscp_profile_on_all_ports() - - cnt = 0 - tbl = swsscommon.Table(self.asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_PORT") - keys = tbl.getKeys() - for key in keys: - (status, fvs) = tbl.get(key) - assert status == True - - for fv in fvs: - if fv[0] == "SAI_PORT_ATTR_QOS_TC_AND_COLOR_TO_DSCP_MAP": - cnt += 1 - assert fv[1] == oid - - port_cnt = len(swsscommon.Table(self.config_db, CFG_PORT_TABLE_NAME).getKeys()) - assert port_cnt == cnt - - -#Tests for TC-to-Dot1p qos map configuration -class TestTcDot1p(object): - def connect_dbs(self, dvs): - self.asic_db = swsscommon.DBConnector(1, dvs.redis_sock, 0) - self.config_db = swsscommon.DBConnector(4, dvs.redis_sock, 0) - - def create_tc_dot1p_profile(self): - tbl = swsscommon.Table(self.config_db, CFG_TC_TO_DOT1P_MAP_TABLE_NAME) - fvs = swsscommon.FieldValuePairs(list(TC_TO_DOT1P_MAP.items())) - tbl.set(CFG_TC_TO_DOT1P_MAP_KEY, fvs) - time.sleep(1) - - def find_tc_dot1p_profile(self): - found = False - tc_dot1p_map_raw = None - tbl = swsscommon.Table(self.asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_QOS_MAP") - keys = tbl.getKeys() - for key in keys: - (status, fvs) = tbl.get(key) - assert status == True - - for fv in fvs: - if fv[0] == "SAI_QOS_MAP_ATTR_MAP_TO_VALUE_LIST": - tc_dot1p_map_raw = fv[1] - elif fv[0] == "SAI_QOS_MAP_ATTR_TYPE" and fv[1] == "SAI_QOS_MAP_TYPE_TC_AND_COLOR_TO_DOT1P": - found = True - - if found: - break - - assert found == True - - return (key, tc_dot1p_map_raw) - - def apply_tc_dot1p_profile_on_all_ports(self): - tbl = swsscommon.Table(self.config_db, CFG_PORT_QOS_MAP_TABLE_NAME) - fvs = swsscommon.FieldValuePairs([(CFG_PORT_QOS_TC_DOT1P_MAP_FIELD, CFG_TC_TO_DOT1P_MAP_KEY)]) - ports = swsscommon.Table(self.config_db, CFG_PORT_TABLE_NAME).getKeys() - for port in ports: - tbl.set(port, fvs) - - time.sleep(1) - - - def test_tc_dot1p_cfg(self, dvs): - self.connect_dbs(dvs) - self.create_tc_dot1p_profile() - _, tc_dot1p_map_raw = self.find_tc_dot1p_profile() - - tc_dot1p_map = json.loads(tc_dot1p_map_raw) - for tc2dot1p in tc_dot1p_map['list']: - tc_val = str(tc2dot1p['key']['tc']) - dot1p_val = str(tc2dot1p['value']['dot1p']) - assert dot1p_val == TC_TO_DOT1P_MAP[tc_val] - - def test_port_tc_dot1p(self, dvs): - self.connect_dbs(dvs) - self.create_tc_dot1p_profile() - oid, _ = self.find_tc_dot1p_profile() - - self.apply_tc_dot1p_profile_on_all_ports() - - cnt = 0 - tbl = swsscommon.Table(self.asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_PORT") - keys = tbl.getKeys() - for key in keys: - (status, fvs) = tbl.get(key) - assert status == True - - for fv in fvs: - if fv[0] == "SAI_PORT_ATTR_QOS_TC_AND_COLOR_TO_DOT1P_MAP": - cnt += 1 - assert fv[1] == oid - - port_cnt = len(swsscommon.Table(self.config_db, CFG_PORT_TABLE_NAME).getKeys()) - assert port_cnt == cnt - -#Tests for Dot1p-to-TC qos map configuration -class TestDot1p(object): - def connect_dbs(self, dvs): - self.asic_db = swsscommon.DBConnector(1, dvs.redis_sock, 0) - self.config_db = swsscommon.DBConnector(4, dvs.redis_sock, 0) - - - def create_dot1p_profile(self): - tbl = swsscommon.Table(self.config_db, CFG_DOT1P_TO_TC_MAP_TABLE_NAME) - fvs = swsscommon.FieldValuePairs(list(DOT1P_TO_TC_MAP.items())) - tbl.set(CFG_DOT1P_TO_TC_MAP_KEY, fvs) - time.sleep(1) - - def find_dot1p_profile(self): - found = False - dot1p_tc_map_raw = None - tbl = swsscommon.Table(self.asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_QOS_MAP") - keys = tbl.getKeys() - for key in keys: - (status, fvs) = tbl.get(key) - assert status == True - - for fv in fvs: - if fv[0] == "SAI_QOS_MAP_ATTR_MAP_TO_VALUE_LIST": - dot1p_tc_map_raw = fv[1] - elif fv[0] == "SAI_QOS_MAP_ATTR_TYPE" and fv[1] == "SAI_QOS_MAP_TYPE_DOT1P_TO_TC": - found = True - - if found: - break - - assert found == True - - return (key, dot1p_tc_map_raw) - - - def apply_dot1p_profile_on_all_ports(self): - tbl = swsscommon.Table(self.config_db, CFG_PORT_QOS_MAP_TABLE_NAME) - fvs = swsscommon.FieldValuePairs([(CFG_PORT_QOS_DOT1P_MAP_FIELD, CFG_DOT1P_TO_TC_MAP_KEY)]) - ports = swsscommon.Table(self.config_db, CFG_PORT_TABLE_NAME).getKeys() - for port in ports: - tbl.set(port, fvs) - - time.sleep(1) - - - def test_dot1p_cfg(self, dvs): - self.connect_dbs(dvs) - self.create_dot1p_profile() - _, dot1p_tc_map_raw = self.find_dot1p_profile() - - dot1p_tc_map = json.loads(dot1p_tc_map_raw) - for dot1p2tc in dot1p_tc_map['list']: - dot1p = str(dot1p2tc['key']['dot1p']) - tc = str(dot1p2tc['value']['tc']) - assert tc == DOT1P_TO_TC_MAP[dot1p] - - - def test_port_dot1p(self, dvs): - self.connect_dbs(dvs) - self.create_dot1p_profile() - oid, _ = self.find_dot1p_profile() - - self.apply_dot1p_profile_on_all_ports() - - cnt = 0 - tbl = swsscommon.Table(self.asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_PORT") - keys = tbl.getKeys() - for key in keys: - (status, fvs) = tbl.get(key) - assert status == True - - for fv in fvs: - if fv[0] == "SAI_PORT_ATTR_QOS_DOT1P_TO_TC_MAP": - cnt += 1 - assert fv[1] == oid - - port_cnt = len(swsscommon.Table(self.config_db, CFG_PORT_TABLE_NAME).getKeys()) - assert port_cnt == cnt - -class TestCbf(object): - ASIC_QOS_MAP_STR = "ASIC_STATE:SAI_OBJECT_TYPE_QOS_MAP" - ASIC_PORT_STR = "ASIC_STATE:SAI_OBJECT_TYPE_PORT" - - def init_test(self, dvs): - self.dvs = dvs - self.asic_db = dvs.get_asic_db() - self.config_db = dvs.get_config_db() - self.asic_qos_map_ids = self.asic_db.get_keys(self.ASIC_QOS_MAP_STR) - self.asic_qos_map_count = len(self.asic_qos_map_ids) - self.dscp_ps = swsscommon.Table(self.config_db.db_connection, swsscommon.CFG_DSCP_TO_FC_MAP_TABLE_NAME) - self.exp_ps = swsscommon.Table(self.config_db.db_connection, swsscommon.CFG_EXP_TO_FC_MAP_TABLE_NAME) - - # Set switch FC capability to 63 - dvs.setReadOnlyAttr('SAI_OBJECT_TYPE_SWITCH', 'SAI_SWITCH_ATTR_MAX_NUMBER_OF_FORWARDING_CLASSES', '63') - - def get_qos_id(self): - diff = set(self.asic_db.get_keys(self.ASIC_QOS_MAP_STR)) - set(self.asic_qos_map_ids) - assert len(diff) <= 1 - return None if len(diff) == 0 else diff.pop() - - def test_dscp_to_fc(self, dvs): - self.init_test(dvs) - - # Create a DSCP_TO_FC map - dscp_map = [(str(i), str(i)) for i in range(0, 63)] - self.dscp_ps.set("AZURE", swsscommon.FieldValuePairs(dscp_map)) - - self.asic_db.wait_for_n_keys(self.ASIC_QOS_MAP_STR, self.asic_qos_map_count + 1) - - # Get the DSCP map ID - dscp_map_id = self.get_qos_id() - assert(dscp_map_id is not None) - - # Assert the expected values - fvs = self.asic_db.get_entry(self.ASIC_QOS_MAP_STR, dscp_map_id) - assert(fvs.get("SAI_QOS_MAP_ATTR_TYPE") == "SAI_QOS_MAP_TYPE_DSCP_TO_FORWARDING_CLASS") - - # Modify the map - dscp_map = [(str(i), '0') for i in range(0, 63)] - self.dscp_ps.set("AZURE", swsscommon.FieldValuePairs(dscp_map)) - time.sleep(1) - - # Assert the expected values - fvs = self.asic_db.get_entry(self.ASIC_QOS_MAP_STR, dscp_map_id) - sai_dscp_map = json.loads(fvs.get("SAI_QOS_MAP_ATTR_MAP_TO_VALUE_LIST")) - - for dscp2fc in sai_dscp_map['list']: - fc = str(dscp2fc['value']['fc']) - assert fc == '0' - - # Delete the map - self.dscp_ps._del("AZURE") - self.asic_db.wait_for_deleted_entry(self.ASIC_QOS_MAP_STR, dscp_map_id) - - # Test validation - maps = [ - ('-1', '0'), # negative DSCP - ('64', '0'), # DSCP greater than max value - ('0', '-1'), # negative FC - ('0', '63'), # FC greater than max value - ('a', '0'), # non-integer DSCP - ('0', 'a'), # non-integet FC - ] - - for fvs in maps: - self.dscp_ps.set('AZURE', swsscommon.FieldValuePairs([fvs])) - time.sleep(1) - assert(self.asic_qos_map_count == len(self.asic_db.get_keys('ASIC_STATE:SAI_OBJECT_TYPE_QOS_MAP'))) - self.dscp_ps._del("AZURE") - - # Delete a map that does not exist. Nothing should happen - self.dscp_ps._del("AZURE") - time.sleep(1) - assert(len(self.asic_db.get_keys(self.ASIC_QOS_MAP_STR)) == self.asic_qos_map_count) - - def test_exp_to_fc(self, dvs): - self.init_test(dvs) - - # Create a EXP_TO_FC map - exp_map = [(str(i), str(i)) for i in range(0, 8)] - self.exp_ps.set("AZURE", swsscommon.FieldValuePairs(exp_map)) - - self.asic_db.wait_for_n_keys(self.ASIC_QOS_MAP_STR, self.asic_qos_map_count + 1) - - # Get the EXP map ID - exp_map_id = self.get_qos_id() - - # Assert the expected values - fvs = self.asic_db.get_entry(self.ASIC_QOS_MAP_STR, exp_map_id) - assert(fvs.get("SAI_QOS_MAP_ATTR_TYPE") == "SAI_QOS_MAP_TYPE_MPLS_EXP_TO_FORWARDING_CLASS") - - # Modify the map - exp_map = [(str(i), '0') for i in range(0, 8)] - self.exp_ps.set("AZURE", swsscommon.FieldValuePairs(exp_map)) - time.sleep(1) - - # Assert the expected values - fvs = self.asic_db.get_entry(self.ASIC_QOS_MAP_STR, exp_map_id) - sai_exp_map = json.loads(fvs.get("SAI_QOS_MAP_ATTR_MAP_TO_VALUE_LIST")) - - for exp2fc in sai_exp_map['list']: - fc = str(exp2fc['value']['fc']) - assert fc == '0' - - # Delete the map - self.exp_ps._del("AZURE") - self.asic_db.wait_for_deleted_entry(self.ASIC_QOS_MAP_STR, exp_map_id) - - # Test validation - maps = [ - ('-1', '0'), # negative EXP - ('8', '0'), # EXP greater than max value - ('0', '-1'), # negative FC - ('0', '63'), # FC greater than max value - ('a', '0'), # non-integer EXP - ('0', 'a'), # non-integet FC - ] - - for fvs in maps: - self.exp_ps.set('AZURE', swsscommon.FieldValuePairs([fvs])) - time.sleep(1) - assert(self.asic_qos_map_count == len(self.asic_db.get_keys('ASIC_STATE:SAI_OBJECT_TYPE_QOS_MAP'))) - self.exp_ps._del("AZURE") - - # Update the map with valid values - exp_map = [(str(i), str(i + 10)) for i in range(0, 8)] - self.exp_ps.set('AZURE', swsscommon.FieldValuePairs(exp_map)) - self.asic_db.wait_for_n_keys(self.ASIC_QOS_MAP_STR, self.asic_qos_map_count + 1) - - # Delete the map - exp_map_id = self.get_qos_id() - self.exp_ps._del("AZURE") - self.asic_db.wait_for_deleted_entry(self.ASIC_QOS_MAP_STR, exp_map_id) - - # Delete a map that does not exist. Nothing should happen - self.exp_ps._del("AZURE") - time.sleep(1) - assert(len(self.asic_db.get_keys(self.ASIC_QOS_MAP_STR)) == self.asic_qos_map_count) - - def test_per_port_cbf_binding(self, dvs): - self.init_test(dvs) - - # Create a DSCP_TO_FC map - dscp_map = [(str(i), str(i)) for i in range(0, 63)] - self.dscp_ps.set("AZURE", swsscommon.FieldValuePairs(dscp_map)) - self.asic_db.wait_for_n_keys(self.ASIC_QOS_MAP_STR, self.asic_qos_map_count + 1) - dscp_map_id = self.get_qos_id() - self.asic_qos_map_ids = self.asic_db.get_keys(self.ASIC_QOS_MAP_STR) - - # Create a EXP_TO_FC map - exp_map = [(str(i), str(i)) for i in range(0, 8)] - self.exp_ps.set("AZURE", swsscommon.FieldValuePairs(exp_map)) - self.asic_db.wait_for_n_keys(self.ASIC_QOS_MAP_STR, self.asic_qos_map_count + 2) - exp_map_id = self.get_qos_id() - - tbl = swsscommon.Table(self.config_db.db_connection, swsscommon.CFG_PORT_QOS_MAP_TABLE_NAME) - fvs = swsscommon.FieldValuePairs([('dscp_to_fc_map', "AZURE"), - ('exp_to_fc_map', "AZURE")]) - keys = self.config_db.get_keys(swsscommon.CFG_PORT_TABLE_NAME) - for key in keys: - tbl.set(key, fvs) - time.sleep(1) - - dscp_cnt = 0 - exp_cnt = 0 - for key in self.asic_db.get_keys(self.ASIC_PORT_STR): - fvs = self.asic_db.get_entry(self.ASIC_PORT_STR, key) - if 'SAI_PORT_ATTR_QOS_DSCP_TO_FORWARDING_CLASS_MAP' in fvs: - assert fvs['SAI_PORT_ATTR_QOS_DSCP_TO_FORWARDING_CLASS_MAP'] == dscp_map_id - dscp_cnt += 1 - if 'SAI_PORT_ATTR_QOS_MPLS_EXP_TO_FORWARDING_CLASS_MAP' in fvs: - assert fvs['SAI_PORT_ATTR_QOS_MPLS_EXP_TO_FORWARDING_CLASS_MAP'] == exp_map_id - exp_cnt += 1 - assert dscp_cnt == exp_cnt == len(keys) - -class TestMplsTc(object): - def connect_dbs(self, dvs): - self.asic_db = swsscommon.DBConnector(1, dvs.redis_sock, 0) - self.config_db = swsscommon.DBConnector(4, dvs.redis_sock, 0) - - - def create_mpls_tc_profile(self): - tbl = swsscommon.Table(self.config_db, CFG_MPLS_TC_TO_TC_MAP_TABLE_NAME) - fvs = swsscommon.FieldValuePairs(list(MPLS_TC_TO_TC_MAP.items())) - tbl.set(CFG_MPLS_TC_TO_TC_MAP_KEY, fvs) - time.sleep(1) - - - def find_mpls_tc_profile(self): - found = False - mpls_tc_tc_map_raw = None - tbl = swsscommon.Table(self.asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_QOS_MAP") - keys = tbl.getKeys() - for key in keys: - (status, fvs) = tbl.get(key) - assert status == True - - for fv in fvs: - if fv[0] == "SAI_QOS_MAP_ATTR_MAP_TO_VALUE_LIST": - mpls_tc_tc_map_raw = fv[1] - elif fv[0] == "SAI_QOS_MAP_ATTR_TYPE" and fv[1] == "SAI_QOS_MAP_TYPE_MPLS_EXP_TO_TC": - found = True - - if found: - break - - assert found == True - - return (key, mpls_tc_tc_map_raw) - - - def apply_mpls_tc_profile_on_all_ports(self): - tbl = swsscommon.Table(self.config_db, CFG_PORT_QOS_MAP_TABLE_NAME) - fvs = swsscommon.FieldValuePairs([(CFG_PORT_QOS_MPLS_TC_MAP_FIELD, CFG_MPLS_TC_TO_TC_MAP_KEY)]) - ports = swsscommon.Table(self.config_db, CFG_PORT_TABLE_NAME).getKeys() - for port in ports: - tbl.set(port, fvs) - - time.sleep(1) - - - def test_mpls_tc_cfg(self, dvs): - self.connect_dbs(dvs) - self.create_mpls_tc_profile() - _, mpls_tc_tc_map_raw = self.find_mpls_tc_profile() - - mpls_tc_tc_map = json.loads(mpls_tc_tc_map_raw) - for mplstc2tc in mpls_tc_tc_map['list']: - mpls_tc = str(mplstc2tc['key']['mpls_exp']) - tc = str(mplstc2tc['value']['tc']) - assert tc == MPLS_TC_TO_TC_MAP[mpls_tc] - - - def test_port_mpls_tc(self, dvs): - self.connect_dbs(dvs) - self.create_mpls_tc_profile() - oid, _ = self.find_mpls_tc_profile() - - self.apply_mpls_tc_profile_on_all_ports() - - cnt = 0 - tbl = swsscommon.Table(self.asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_PORT") - keys = tbl.getKeys() - for key in keys: - (status, fvs) = tbl.get(key) - assert status == True - - for fv in fvs: - if fv[0] == "SAI_PORT_ATTR_QOS_MPLS_EXP_TO_TC_MAP": - cnt += 1 - assert fv[1] == oid - - port_cnt = len(swsscommon.Table(self.config_db, CFG_PORT_TABLE_NAME).getKeys()) - assert port_cnt == cnt - -class TestDscpToTcMap(object): - ASIC_QOS_MAP_STR = "ASIC_STATE:SAI_OBJECT_TYPE_QOS_MAP" - ASIC_PORT_STR = "ASIC_STATE:SAI_OBJECT_TYPE_PORT" - ASIC_SWITCH_STR = "ASIC_STATE:SAI_OBJECT_TYPE_SWITCH" - - def init_test(self, dvs): - dvs.setup_db() - self.asic_db = dvs.get_asic_db() - self.config_db = dvs.get_config_db() - self.asic_qos_map_ids = self.asic_db.get_keys(self.ASIC_QOS_MAP_STR) - self.asic_qos_map_count = len(self.asic_qos_map_ids) - self.dscp_to_tc_table = swsscommon.Table(self.config_db.db_connection, swsscommon.CFG_DSCP_TO_TC_MAP_TABLE_NAME) - self.port_qos_table = swsscommon.Table(self.config_db.db_connection, swsscommon.CFG_PORT_QOS_MAP_TABLE_NAME) - - def get_qos_id(self): - diff = set(self.asic_db.get_keys(self.ASIC_QOS_MAP_STR)) - set(self.asic_qos_map_ids) - assert len(diff) <= 1 - return None if len(diff) == 0 else diff.pop() - - def test_dscp_to_tc_map_applied_to_switch(self, dvs): - self.init_test(dvs) - dscp_to_tc_map_id = None - created_new_map = False - try: - existing_map = self.dscp_to_tc_table.getKeys() - if "AZURE" not in existing_map: - # Create a DSCP_TO_TC map - dscp_to_tc_map = [(str(i), str(i)) for i in range(0, 63)] - self.dscp_to_tc_table.set("AZURE", swsscommon.FieldValuePairs(dscp_to_tc_map)) - - self.asic_db.wait_for_n_keys(self.ASIC_QOS_MAP_STR, self.asic_qos_map_count + 1) - - # Get the DSCP_TO_TC map ID - dscp_to_tc_map_id = self.get_qos_id() - assert(dscp_to_tc_map_id is not None) - - # Assert the expected values - fvs = self.asic_db.get_entry(self.ASIC_QOS_MAP_STR, dscp_to_tc_map_id) - assert(fvs.get("SAI_QOS_MAP_ATTR_TYPE") == "SAI_QOS_MAP_TYPE_DSCP_TO_TC") - created_new_map = True - else: - for id in self.asic_qos_map_ids: - fvs = self.asic_db.get_entry(self.ASIC_QOS_MAP_STR, id) - if fvs.get("SAI_QOS_MAP_ATTR_TYPE") == "SAI_QOS_MAP_TYPE_DSCP_TO_TC": - dscp_to_tc_map_id = id - break - switch_oid = dvs.getSwitchOid() - - # Insert switch level map entry - self.port_qos_table.set("global", [("dscp_to_tc_map", "AZURE")]) - time.sleep(1) - - # Check the switch level DSCP_TO_TC_MAP is applied - fvs = self.asic_db.get_entry(self.ASIC_SWITCH_STR, switch_oid) - assert(fvs.get("SAI_SWITCH_ATTR_QOS_DSCP_TO_TC_MAP") == dscp_to_tc_map_id) - - # Remove the global level DSCP_TO_TC_MAP - self.port_qos_table._del("global") - time.sleep(1) - - # Check the global level DSCP_TO_TC_MAP is set to SAI_ - fvs = self.asic_db.get_entry(self.ASIC_SWITCH_STR, switch_oid) - assert(fvs.get("SAI_SWITCH_ATTR_QOS_DSCP_TO_TC_MAP") == "oid:0x0") - finally: - if created_new_map: - self.dscp_to_tc_table._del("AZURE") - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_route.py b/tests/test_route.py deleted file mode 100644 index dfa6d04cc4..0000000000 --- a/tests/test_route.py +++ /dev/null @@ -1,1119 +0,0 @@ -import os -import re -import time -import json -import pytest - -from swsscommon import swsscommon -from dvslib.dvs_common import wait_for_result - -class TestRouteBase(object): - def setup_db(self, dvs): - self.pdb = dvs.get_app_db() - self.adb = dvs.get_asic_db() - self.cdb = dvs.get_config_db() - self.sdb = dvs.get_state_db() - - def set_admin_status(self, interface, status): - self.cdb.update_entry("PORT", interface, {"admin_status": status}) - - def create_vrf(self, vrf_name): - initial_entries = set(self.adb.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER")) - - self.cdb.create_entry("VRF", vrf_name, {"empty": "empty"}) - self.adb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER", len(initial_entries) + 1) - - current_entries = set(self.adb.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER")) - assert len(current_entries - initial_entries) == 1 - return list(current_entries - initial_entries)[0] - - def remove_vrf(self, vrf_name): - self.cdb.delete_entry("VRF", vrf_name) - - def create_l3_intf(self, interface, vrf_name): - if len(vrf_name) == 0: - self.cdb.create_entry("INTERFACE", interface, {"NULL": "NULL"}) - else: - self.cdb.create_entry("INTERFACE", interface, {"vrf_name": vrf_name}) - - def remove_l3_intf(self, interface): - self.cdb.delete_entry("INTERFACE", interface) - - def add_ip_address(self, interface, ip): - self.cdb.create_entry("INTERFACE", interface + "|" + ip, {"NULL": "NULL"}) - - def remove_ip_address(self, interface, ip): - self.cdb.delete_entry("INTERFACE", interface + "|" + ip) - - def create_route_entry(self, key, pairs): - tbl = swsscommon.ProducerStateTable(self.pdb.db_connection, "ROUTE_TABLE") - fvs = swsscommon.FieldValuePairs(list(pairs.items())) - tbl.set(key, fvs) - - def remove_route_entry(self, key): - tbl = swsscommon.ProducerStateTable(self.pdb.db_connection, "ROUTE_TABLE") - tbl._del(key) - - def check_route_entries(self, destinations): - def _access_function(): - route_entries = self.adb.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - route_destinations = [json.loads(route_entry)["dest"] - for route_entry in route_entries] - return (all(destination in route_destinations for destination in destinations), None) - - wait_for_result(_access_function) - - def check_route_state(self, prefix, value): - found = False - - route_entries = self.sdb.get_keys("ROUTE_TABLE") - for key in route_entries: - if key != prefix: - continue - found = True - fvs = self.sdb.get_entry("ROUTE_TABLE", key) - - assert fvs != {} - - for f,v in fvs.items(): - if f == "state": - assert v == value - assert found - - def get_asic_db_key(self, destination): - route_entries = self.adb.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - for route_entry in route_entries: - if json.loads(route_entry)["dest"] == destination: - return route_entry - return None - - def check_route_entries_with_vrf(self, destinations, vrf_oids): - def _access_function(): - route_entries = self.adb.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - route_destination_vrf = [(json.loads(route_entry)["dest"], json.loads(route_entry)["vr"]) - for route_entry in route_entries] - return (all((destination, vrf_oid) in route_destination_vrf - for destination, vrf_oid in zip(destinations, vrf_oids)), None) - - wait_for_result(_access_function) - - def check_route_entries_nexthop(self, destinations, vrf_oids, nexthops): - def _access_function_nexthop(): - nexthop_entries = self.adb.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP") - nexthop_oids = dict([(self.adb.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP", key)["SAI_NEXT_HOP_ATTR_IP"], key) - for key in nexthop_entries]) - return (all(nexthop in nexthop_oids for nexthop in nexthops), nexthop_oids) - - status, nexthop_oids = wait_for_result(_access_function_nexthop) - - def _access_function_route_nexthop(): - route_entries = self.adb.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - route_destination_nexthop = dict([((json.loads(route_entry)["dest"], json.loads(route_entry)["vr"]), - self.adb.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY", route_entry).get("SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID")) - for route_entry in route_entries]) - return (all(route_destination_nexthop.get((destination, vrf_oid)) == nexthop_oids.get(nexthop) - for destination, vrf_oid, nexthop in zip(destinations, vrf_oids, nexthops)), None) - - wait_for_result(_access_function_route_nexthop) - - def check_deleted_route_entries(self, destinations): - def _access_function(): - route_entries = self.adb.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - route_destinations = [json.loads(route_entry)["dest"] for route_entry in route_entries] - return (all(destination not in route_destinations for destination in destinations), None) - - wait_for_result(_access_function) - - def clear_srv_config(self, dvs): - dvs.servers[0].runcmd("ip address flush dev eth0") - dvs.servers[1].runcmd("ip address flush dev eth0") - dvs.servers[2].runcmd("ip address flush dev eth0") - dvs.servers[3].runcmd("ip address flush dev eth0") - -class TestRoute(TestRouteBase): - """ Functionality tests for route """ - def test_RouteAddRemoveIpv4Route(self, dvs, testlog): - self.setup_db(dvs) - - self.clear_srv_config(dvs) - - # create l3 interface - self.create_l3_intf("Ethernet0", "") - self.create_l3_intf("Ethernet4", "") - - # check STATE route database, initial state shall be "na" - self.check_route_state("0.0.0.0/0", "na") - - # set ip address - self.add_ip_address("Ethernet0", "10.0.0.0/31") - self.add_ip_address("Ethernet4", "10.0.0.2/31") - - # bring up interface - self.set_admin_status("Ethernet0", "up") - self.set_admin_status("Ethernet4", "up") - - # set ip address and default route - dvs.servers[0].runcmd("ip address add 10.0.0.1/31 dev eth0") - dvs.servers[0].runcmd("ip route add default via 10.0.0.0") - - dvs.servers[1].runcmd("ip address add 10.0.0.3/31 dev eth0") - dvs.servers[1].runcmd("ip route add default via 10.0.0.2") - - # get neighbor and arp entry - dvs.servers[0].runcmd("ping -c 1 10.0.0.3") - - # add route entry - dvs.runcmd("vtysh -c \"configure terminal\" -c \"ip route 2.2.2.0/24 10.0.0.1\"") - - # add default route entry - fieldValues = {"nexthop": "10.0.0.1", "ifname": "Ethernet0"} - self.create_route_entry("0.0.0.0/0", fieldValues) - - # check application database - self.pdb.wait_for_entry("ROUTE_TABLE", "2.2.2.0/24") - - # check ASIC route database - self.check_route_entries(["2.2.2.0/24"]) - - # check STATE route database - self.check_route_state("0.0.0.0/0", "ok") - - # remove route entry - dvs.runcmd("vtysh -c \"configure terminal\" -c \"no ip route 2.2.2.0/24 10.0.0.1\"") - - # remove default route entry - self.remove_route_entry("0.0.0.0/0") - - # check application database - self.pdb.wait_for_deleted_entry("ROUTE_TABLE", "2.2.2.0/24") - - # check ASIC route database - self.check_deleted_route_entries(["2.2.2.0/24"]) - - # remove ip address - self.remove_ip_address("Ethernet0", "10.0.0.0/31") - self.remove_ip_address("Ethernet4", "10.0.0.2/31") - - # remove l3 interface - self.remove_l3_intf("Ethernet0") - self.remove_l3_intf("Ethernet4") - - self.set_admin_status("Ethernet0", "down") - self.set_admin_status("Ethernet4", "down") - - # check STATE route database, state set to "na" after deleting the default route - self.check_route_state("0.0.0.0/0", "na") - - # remove ip address and default route - dvs.servers[0].runcmd("ip route del default dev eth0") - dvs.servers[0].runcmd("ip address del 10.0.0.1/31 dev eth0") - - dvs.servers[1].runcmd("ip route del default dev eth0") - dvs.servers[1].runcmd("ip address del 10.0.0.3/31 dev eth0") - - def test_RouteAddRemoveIpv6Route(self, dvs, testlog): - self.setup_db(dvs) - - # create l3 interface - self.create_l3_intf("Ethernet0", "") - self.create_l3_intf("Ethernet4", "") - - # check STATE route database, initial state shall be "na" - self.check_route_state("::/0", "na") - - # bring up interface - self.set_admin_status("Ethernet0", "up") - self.set_admin_status("Ethernet4", "up") - - # set ip address - self.add_ip_address("Ethernet0", "2000::1/64") - self.add_ip_address("Ethernet4", "2001::1/64") - dvs.runcmd("sysctl -w net.ipv6.conf.all.forwarding=1") - - # set ip address and default route - dvs.servers[0].runcmd("ip -6 address add 2000::2/64 dev eth0") - dvs.servers[0].runcmd("ip -6 route add default via 2000::1") - - dvs.servers[1].runcmd("ip -6 address add 2001::2/64 dev eth0") - dvs.servers[1].runcmd("ip -6 route add default via 2001::1") - time.sleep(2) - - # get neighbor entry - dvs.servers[0].runcmd("ping -6 -c 1 2001::2") - - # add route entry - dvs.runcmd("vtysh -c \"configure terminal\" -c \"ipv6 route 3000::0/64 2000::2\"") - - # add default route entry - fieldValues = {"nexthop": "2000::2", "ifname": "Ethernet0"} - self.create_route_entry("::/0", fieldValues) - - # check application database - self.pdb.wait_for_entry("ROUTE_TABLE", "3000::/64") - - # check ASIC route database - self.check_route_entries(["3000::/64"]) - - # check STATE route database - self.check_route_state("::/0", "ok") - - # remove route entry - dvs.runcmd("vtysh -c \"configure terminal\" -c \"no ipv6 route 3000::0/64 2000::2\"") - - # remove default route entry - self.remove_route_entry("::/0") - - # check application database - self.pdb.wait_for_deleted_entry("ROUTE_TABLE", "3000::/64") - - # check ASIC route database - self.check_deleted_route_entries(["3000::/64"]) - - # remove ip address - self.remove_ip_address("Ethernet0", "2000::1/64") - self.remove_ip_address("Ethernet4", "2001::1/64") - - # remove l3 interface - self.remove_l3_intf("Ethernet0") - self.remove_l3_intf("Ethernet4") - - self.set_admin_status("Ethernet0", "down") - self.set_admin_status("Ethernet4", "down") - - # check STATE route database, state set to "na" after deleting the default route - self.check_route_state("::/0", "na") - - # remove ip address and default route - dvs.servers[0].runcmd("ip -6 route del default dev eth0") - dvs.servers[0].runcmd("ip -6 address del 2000::2/64 dev eth0") - - dvs.servers[1].runcmd("ip -6 route del default dev eth0") - dvs.servers[1].runcmd("ip -6 address del 2001::2/64 dev eth0") - - def test_RouteAddRemoveIpv4RouteResolveNeigh(self, dvs, testlog): - self.setup_db(dvs) - - self.clear_srv_config(dvs) - - # create l3 interface - self.create_l3_intf("Ethernet0", "") - self.create_l3_intf("Ethernet4", "") - - # set ip address - self.add_ip_address("Ethernet0", "10.0.0.0/31") - self.add_ip_address("Ethernet4", "10.0.0.2/31") - - # bring up interface - self.set_admin_status("Ethernet0", "up") - self.set_admin_status("Ethernet4", "up") - - # set ip address and default route - dvs.servers[0].runcmd("ip address add 10.0.0.1/31 dev eth0") - dvs.servers[0].runcmd("ip route add default via 10.0.0.0") - - dvs.servers[1].runcmd("ip address add 10.0.0.3/31 dev eth0") - dvs.servers[1].runcmd("ip route add default via 10.0.0.2") - time.sleep(2) - - # add route entry -- single nexthop - dvs.runcmd("vtysh -c \"configure terminal\" -c \"ip route 2.2.2.0/24 10.0.0.1\"") - - # add route entry -- multiple nexthop - dvs.runcmd("vtysh -c \"configure terminal\" -c \"ip route 3.3.3.0/24 10.0.0.1\"") - dvs.runcmd("vtysh -c \"configure terminal\" -c \"ip route 3.3.3.0/24 10.0.0.3\"") - - # check application database - self.pdb.wait_for_entry("ROUTE_TABLE", "2.2.2.0/24") - self.pdb.wait_for_entry("ROUTE_TABLE", "3.3.3.0/24") - - # check neighbor got resolved and removed from NEIGH_RESOLVE_TABLE - self.pdb.wait_for_deleted_entry("NEIGH_RESOLVE_TABLE", "Ethernet0:10.0.0.1") - self.pdb.wait_for_deleted_entry("NEIGH_RESOLVE_TABLE", "Ethernet4:10.0.0.3") - - # check ASIC route database - self.check_route_entries(["2.2.2.0/24", "3.3.3.0/24"]) - - # remove route entry - dvs.runcmd("vtysh -c \"configure terminal\" -c \"no ip route 2.2.2.0/24 10.0.0.1\"") - dvs.runcmd("vtysh -c \"configure terminal\" -c \"no ip route 3.3.3.0/24 10.0.0.1\"") - dvs.runcmd("vtysh -c \"configure terminal\" -c \"no ip route 3.3.3.0/24 10.0.0.3\"") - - # check application database - self.pdb.wait_for_deleted_entry("ROUTE_TABLE", "2.2.2.0/24") - self.pdb.wait_for_deleted_entry("ROUTE_TABLE", "3.3.3.0/24") - - # check ASIC route database - self.check_deleted_route_entries(["2.2.2.0/24", "3.3.3.0/24"]) - - # remove ip address - self.remove_ip_address("Ethernet0", "10.0.0.0/31") - self.remove_ip_address("Ethernet4", "10.0.0.2/31") - - # remove l3 interface - self.remove_l3_intf("Ethernet0") - self.remove_l3_intf("Ethernet4") - - self.set_admin_status("Ethernet0", "down") - self.set_admin_status("Ethernet4", "down") - - # remove ip address and default route - dvs.servers[0].runcmd("ip route del default dev eth0") - dvs.servers[0].runcmd("ip address del 10.0.0.1/31 dev eth0") - - dvs.servers[1].runcmd("ip route del default dev eth0") - dvs.servers[1].runcmd("ip address del 10.0.0.3/31 dev eth0") - - def test_RouteAddRemoveIpv6RouteResolveNeigh(self, dvs, testlog): - self.setup_db(dvs) - - # create l3 interface - self.create_l3_intf("Ethernet0", "") - self.create_l3_intf("Ethernet4", "") - - # bring up interface - self.set_admin_status("Ethernet0", "up") - self.set_admin_status("Ethernet4", "up") - - # set ip address - self.add_ip_address("Ethernet0", "2000::1/64") - self.add_ip_address("Ethernet4", "2001::1/64") - dvs.runcmd("sysctl -w net.ipv6.conf.all.forwarding=1") - - # set ip address and default route - dvs.servers[0].runcmd("ip -6 address add 2000::2/64 dev eth0") - dvs.servers[0].runcmd("ip -6 route add default via 2000::1") - - dvs.servers[1].runcmd("ip -6 address add 2001::2/64 dev eth0") - dvs.servers[1].runcmd("ip -6 route add default via 2001::1") - time.sleep(2) - - # add route entry -- single nexthop - dvs.runcmd("vtysh -c \"configure terminal\" -c \"ipv6 route 3000::0/64 2000::2\"") - - # add route entry -- multiple nexthop - dvs.runcmd("vtysh -c \"configure terminal\" -c \"ipv6 route 4000::0/64 2000::2\"") - dvs.runcmd("vtysh -c \"configure terminal\" -c \"ipv6 route 4000::0/64 2001::2\"") - - # check application database - self.pdb.wait_for_entry("ROUTE_TABLE", "3000::/64") - self.pdb.wait_for_entry("ROUTE_TABLE", "4000::/64") - - # check neighbor got resolved and removed from NEIGH_RESOLVE_TABLE - self.pdb.wait_for_deleted_entry("NEIGH_RESOLVE_TABLE", "Ethernet0:2000::2") - self.pdb.wait_for_deleted_entry("NEIGH_RESOLVE_TABLE", "Ethernet4:2001::2") - - # check ASIC route database - self.check_route_entries(["3000::/64", "4000::/64"]) - - # remove route entry - dvs.runcmd("vtysh -c \"configure terminal\" -c \"no ipv6 route 3000::0/64 2000::2\"") - dvs.runcmd("vtysh -c \"configure terminal\" -c \"no ipv6 route 4000::0/64 2000::2\"") - dvs.runcmd("vtysh -c \"configure terminal\" -c \"no ipv6 route 4000::0/64 2001::2\"") - - # check application database - self.pdb.wait_for_deleted_entry("ROUTE_TABLE", "3000::/64") - self.pdb.wait_for_deleted_entry("ROUTE_TABLE", "4000::/64") - - # check ASIC route database - self.check_deleted_route_entries(["3000::/64", "4000::/64"]) - - # remove ip address - self.remove_ip_address("Ethernet0", "2000::1/64") - self.remove_ip_address("Ethernet4", "2001::1/64") - - # remove l3 interface - self.remove_l3_intf("Ethernet0") - self.remove_l3_intf("Ethernet4") - - self.set_admin_status("Ethernet0", "down") - self.set_admin_status("Ethernet4", "down") - - # remove ip address and default route - dvs.servers[0].runcmd("ip -6 route del default dev eth0") - dvs.servers[0].runcmd("ip -6 address del 2000::2/64 dev eth0") - - dvs.servers[1].runcmd("ip -6 route del default dev eth0") - dvs.servers[1].runcmd("ip -6 address del 2001::2/64 dev eth0") - - def test_RouteAddRemoveIpv4RouteUnresolvedNeigh(self, dvs, testlog): - self.setup_db(dvs) - - self.clear_srv_config(dvs) - - # create l3 interface - self.create_l3_intf("Ethernet0", "") - self.create_l3_intf("Ethernet4", "") - - # set ip address - self.add_ip_address("Ethernet0", "10.0.0.0/31") - self.add_ip_address("Ethernet4", "10.0.0.2/31") - - # bring up interface - self.set_admin_status("Ethernet0", "up") - self.set_admin_status("Ethernet4", "up") - - # add route entry -- single nexthop - dvs.runcmd("vtysh -c \"configure terminal\" -c \"ip route 2.2.2.0/24 10.0.0.1\"") - - # add route entry -- multiple nexthop - dvs.runcmd("vtysh -c \"configure terminal\" -c \"ip route 3.3.3.0/24 10.0.0.1\"") - dvs.runcmd("vtysh -c \"configure terminal\" -c \"ip route 3.3.3.0/24 10.0.0.3\"") - - # check application database - self.pdb.wait_for_entry("ROUTE_TABLE", "2.2.2.0/24") - self.pdb.wait_for_entry("ROUTE_TABLE", "3.3.3.0/24") - - # check for unresolved neighbor entries - self.pdb.wait_for_entry("NEIGH_RESOLVE_TABLE", "Ethernet0:10.0.0.1") - self.pdb.wait_for_entry("NEIGH_RESOLVE_TABLE", "Ethernet4:10.0.0.3") - - # check routes does not show up in ASIC_DB - self.check_deleted_route_entries(["2.2.2.0/24", "3.3.3.0/24"]) - - # set ip address and default route - dvs.servers[0].runcmd("ip address add 10.0.0.1/31 dev eth0") - dvs.servers[0].runcmd("ip route add default via 10.0.0.0") - - dvs.servers[1].runcmd("ip address add 10.0.0.3/31 dev eth0") - dvs.servers[1].runcmd("ip route add default via 10.0.0.2") - time.sleep(2) - - # check application database - self.pdb.wait_for_entry("ROUTE_TABLE", "2.2.2.0/24") - self.pdb.wait_for_entry("ROUTE_TABLE", "3.3.3.0/24") - - # check neighbor got resolved and removed from NEIGH_RESOLVE_TABLE - self.pdb.wait_for_deleted_entry("NEIGH_RESOLVE_TABLE", "Ethernet0:10.0.0.1") - self.pdb.wait_for_deleted_entry("NEIGH_RESOLVE_TABLE", "Ethernet4:10.0.0.3") - - # check ASIC route database - self.check_route_entries(["2.2.2.0/24", "3.3.3.0/24"]) - - # remove route entry - dvs.runcmd("vtysh -c \"configure terminal\" -c \"no ip route 2.2.2.0/24 10.0.0.1\"") - dvs.runcmd("vtysh -c \"configure terminal\" -c \"no ip route 3.3.3.0/24 10.0.0.1\"") - dvs.runcmd("vtysh -c \"configure terminal\" -c \"no ip route 3.3.3.0/24 10.0.0.3\"") - - # check application database - self.pdb.wait_for_deleted_entry("ROUTE_TABLE", "2.2.2.0/24") - self.pdb.wait_for_deleted_entry("ROUTE_TABLE", "3.3.3.0/24") - - # check ASIC route database - self.check_deleted_route_entries(["2.2.2.0/24", "3.3.3.0/24"]) - - # remove ip address - self.remove_ip_address("Ethernet0", "10.0.0.0/31") - self.remove_ip_address("Ethernet4", "10.0.0.2/31") - - # remove l3 interface - self.remove_l3_intf("Ethernet0") - self.remove_l3_intf("Ethernet4") - - self.set_admin_status("Ethernet0", "down") - self.set_admin_status("Ethernet4", "down") - - # remove ip address and default route - dvs.servers[0].runcmd("ip route del default dev eth0") - dvs.servers[0].runcmd("ip address del 10.0.0.1/31 dev eth0") - - dvs.servers[1].runcmd("ip route del default dev eth0") - dvs.servers[1].runcmd("ip address del 10.0.0.3/31 dev eth0") - - def test_RouteAddRemoveIpv6RouteUnresolvedNeigh(self, dvs, testlog): - self.setup_db(dvs) - - # create l3 interface - self.create_l3_intf("Ethernet0", "") - self.create_l3_intf("Ethernet4", "") - - # bring up interface - self.set_admin_status("Ethernet0", "up") - self.set_admin_status("Ethernet4", "up") - - # set ip address - self.add_ip_address("Ethernet0", "2000::1/64") - self.add_ip_address("Ethernet4", "2001::1/64") - dvs.runcmd("sysctl -w net.ipv6.conf.all.forwarding=1") - - # add route entry -- single nexthop - dvs.runcmd("vtysh -c \"configure terminal\" -c \"ipv6 route 3000::0/64 2000::2\"") - - # add route entry -- multiple nexthop - dvs.runcmd("vtysh -c \"configure terminal\" -c \"ipv6 route 4000::0/64 2000::2\"") - dvs.runcmd("vtysh -c \"configure terminal\" -c \"ipv6 route 4000::0/64 2001::2\"") - - # check application database - self.pdb.wait_for_entry("ROUTE_TABLE", "3000::/64") - self.pdb.wait_for_entry("ROUTE_TABLE", "4000::/64") - - # check for unresolved neighbor entries - self.pdb.wait_for_entry("NEIGH_RESOLVE_TABLE", "Ethernet0:2000::2") - self.pdb.wait_for_entry("NEIGH_RESOLVE_TABLE", "Ethernet4:2001::2") - - # check routes does not show up in ASIC_DB - self.check_deleted_route_entries(["3000::/64", "4000::/64"]) - - # set ip address and default route - dvs.servers[0].runcmd("ip -6 address add 2000::2/64 dev eth0") - dvs.servers[0].runcmd("ip -6 route add default via 2000::1") - - dvs.servers[1].runcmd("ip -6 address add 2001::2/64 dev eth0") - dvs.servers[1].runcmd("ip -6 route add default via 2001::1") - time.sleep(5) - - dvs.servers[0].runcmd("ping -6 -c 1 2001::2") - - # check application database - self.pdb.wait_for_entry("ROUTE_TABLE", "3000::/64") - self.pdb.wait_for_entry("ROUTE_TABLE", "4000::/64") - - # check neighbor got resolved and removed from NEIGH_RESOLVE_TABLE - self.pdb.wait_for_deleted_entry("NEIGH_RESOLVE_TABLE", "Ethernet0:2000::2") - self.pdb.wait_for_deleted_entry("NEIGH_RESOLVE_TABLE", "Ethernet4:2001::2") - - # check ASIC route database - self.check_route_entries(["3000::/64", "4000::/64"]) - - # remove route entry - dvs.runcmd("vtysh -c \"configure terminal\" -c \"no ipv6 route 3000::0/64 2000::2\"") - dvs.runcmd("vtysh -c \"configure terminal\" -c \"no ipv6 route 4000::0/64 2000::2\"") - dvs.runcmd("vtysh -c \"configure terminal\" -c \"no ipv6 route 4000::0/64 2001::2\"") - - # check application database - self.pdb.wait_for_deleted_entry("ROUTE_TABLE", "3000::/64") - self.pdb.wait_for_deleted_entry("ROUTE_TABLE", "4000::/64") - - # check ASIC route database - self.check_deleted_route_entries(["3000::/64", "4000::/64"]) - - # remove ip address - self.remove_ip_address("Ethernet0", "2000::1/64") - self.remove_ip_address("Ethernet4", "2001::1/64") - - # remove l3 interface - self.remove_l3_intf("Ethernet0") - self.remove_l3_intf("Ethernet4") - - self.set_admin_status("Ethernet0", "down") - self.set_admin_status("Ethernet4", "down") - - # remove ip address and default route - dvs.servers[0].runcmd("ip -6 route del default dev eth0") - dvs.servers[0].runcmd("ip -6 address del 2000::2/64 dev eth0") - - dvs.servers[1].runcmd("ip -6 route del default dev eth0") - dvs.servers[1].runcmd("ip -6 address del 2001::2/64 dev eth0") - - @pytest.mark.skip(reason="Failing. Under investigation") - def test_RouteAddRemoveIpv4RouteWithVrf(self, dvs, testlog): - self.setup_db(dvs) - - # create vrf - vrf_1_oid = self.create_vrf("Vrf_1") - vrf_2_oid = self.create_vrf("Vrf_2") - - # create l3 interface - self.create_l3_intf("Ethernet0", "Vrf_1") - self.create_l3_intf("Ethernet4", "Vrf_1") - self.create_l3_intf("Ethernet8", "Vrf_2") - self.create_l3_intf("Ethernet12", "Vrf_2") - - # set ip address - self.add_ip_address("Ethernet0", "10.0.0.0/31") - self.add_ip_address("Ethernet4", "10.0.0.2/31") - self.add_ip_address("Ethernet8", "10.0.0.0/31") - self.add_ip_address("Ethernet12", "10.0.0.2/31") - - # bring up interface - self.set_admin_status("Ethernet0", "up") - self.set_admin_status("Ethernet4", "up") - self.set_admin_status("Ethernet8", "up") - self.set_admin_status("Ethernet12", "up") - - # set ip address and default route - dvs.servers[0].runcmd("ip address add 10.0.0.1/31 dev eth0") - dvs.servers[0].runcmd("ip route add default via 10.0.0.0") - - dvs.servers[1].runcmd("ip address add 10.0.0.3/31 dev eth0") - dvs.servers[1].runcmd("ip route add default via 10.0.0.2") - - dvs.servers[2].runcmd("ip address add 10.0.0.1/31 dev eth0") - dvs.servers[2].runcmd("ip route add default via 10.0.0.0") - - dvs.servers[3].runcmd("ip address add 10.0.0.3/31 dev eth0") - dvs.servers[3].runcmd("ip route add default via 10.0.0.2") - - # get neighbor entry - dvs.servers[0].runcmd("ping -c 1 10.0.0.3") - dvs.servers[2].runcmd("ping -c 1 10.0.0.3") - - # add route - dvs.runcmd("vtysh -c \"configure terminal\" -c \"ip route 2.2.2.0/24 10.0.0.1 vrf Vrf_1\"") - dvs.runcmd("vtysh -c \"configure terminal\" -c \"ip route 3.3.3.0/24 10.0.0.1 vrf Vrf_2\"") - - # check application database - self.pdb.wait_for_entry("ROUTE_TABLE:Vrf_1", "2.2.2.0/24") - self.pdb.wait_for_entry("ROUTE_TABLE:Vrf_2", "3.3.3.0/24") - - # check ASIC route database - self.check_route_entries_with_vrf(["2.2.2.0/24", "3.3.3.0/24"], [vrf_1_oid, vrf_2_oid]) - - # remove route - dvs.runcmd("vtysh -c \"configure terminal\" -c \"no ip route 2.2.2.0/24 10.0.0.1 vrf Vrf_1\"") - dvs.runcmd("vtysh -c \"configure terminal\" -c \"no ip route 3.3.3.0/24 10.0.0.1 vrf Vrf_2\"") - - # check application database - self.pdb.wait_for_deleted_entry("ROUTE_TABLE:Vrf_1", "2.2.2.0/24") - self.pdb.wait_for_deleted_entry("ROUTE_TABLE:Vrf_2", "3.3.3.0/24") - - # check ASIC route database - self.check_deleted_route_entries(["2.2.2.0/24", "3.3.3.0/24"]) - - # remove ip address - self.remove_ip_address("Ethernet0", "10.0.0.0/31") - self.remove_ip_address("Ethernet4", "10.0.0.2/31") - self.remove_ip_address("Ethernet8", "10.0.0.0/31") - self.remove_ip_address("Ethernet12", "10.0.0.2/31") - - # remove l3 interface - self.remove_l3_intf("Ethernet0") - self.remove_l3_intf("Ethernet4") - self.remove_l3_intf("Ethernet8") - self.remove_l3_intf("Ethernet12") - - self.set_admin_status("Ethernet0", "down") - self.set_admin_status("Ethernet4", "down") - self.set_admin_status("Ethernet8", "down") - self.set_admin_status("Ethernet12", "down") - - # remove vrf - self.remove_vrf("Vrf_1") - self.remove_vrf("Vrf_2") - - # remove ip address and default route - dvs.servers[0].runcmd("ip route del default dev eth0") - dvs.servers[0].runcmd("ip address del 10.0.0.1/31 dev eth0") - dvs.servers[1].runcmd("ip route del default dev eth0") - dvs.servers[1].runcmd("ip address del 10.0.0.3/31 dev eth0") - dvs.servers[2].runcmd("ip route del default dev eth0") - dvs.servers[2].runcmd("ip address del 10.0.0.1/31 dev eth0") - dvs.servers[3].runcmd("ip route del default dev eth0") - dvs.servers[3].runcmd("ip address del 10.0.0.3/31 dev eth0") - - @pytest.mark.skip(reason="FRR 7.5 issue https://github.com/Azure/sonic-buildimage/issues/6359") - def test_RouteAddRemoveIpv6RouteWithVrf(self, dvs, testlog): - self.setup_db(dvs) - - # create vrf - vrf_1_oid = self.create_vrf("Vrf_1") - vrf_2_oid = self.create_vrf("Vrf_2") - - # create l3 interface - self.create_l3_intf("Ethernet0", "Vrf_1") - self.create_l3_intf("Ethernet4", "Vrf_1") - self.create_l3_intf("Ethernet8", "Vrf_2") - self.create_l3_intf("Ethernet12", "Vrf_2") - - # bring up interface - self.set_admin_status("Ethernet0", "up") - self.set_admin_status("Ethernet4", "up") - self.set_admin_status("Ethernet8", "up") - self.set_admin_status("Ethernet12", "up") - - # set ip address - self.add_ip_address("Ethernet0", "2000::1/64") - self.add_ip_address("Ethernet4", "2001::1/64") - self.add_ip_address("Ethernet8", "2000::1/64") - self.add_ip_address("Ethernet12", "2001::1/64") - - dvs.runcmd("sysctl -w net.ipv6.conf.all.forwarding=1") - - # set ip address and default route - dvs.servers[0].runcmd("ip -6 address add 2000::2/64 dev eth0") - dvs.servers[0].runcmd("ip -6 route add default via 2000::1") - dvs.servers[1].runcmd("ip -6 address add 2001::2/64 dev eth0") - dvs.servers[1].runcmd("ip -6 route add default via 2001::1") - dvs.servers[2].runcmd("ip -6 address add 2000::2/64 dev eth0") - dvs.servers[2].runcmd("ip -6 route add default via 2000::1") - dvs.servers[3].runcmd("ip -6 address add 2001::2/64 dev eth0") - dvs.servers[3].runcmd("ip -6 route add default via 2001::1") - time.sleep(2) - - # get neighbor entry - dvs.servers[0].runcmd("ping -6 -c 1 2001::2") - dvs.servers[2].runcmd("ping -6 -c 1 2001::2") - - # add route - dvs.runcmd("vtysh -c \"configure terminal\" -c \"ipv6 route 3000::0/64 2000::2 vrf Vrf_1\"") - dvs.runcmd("vtysh -c \"configure terminal\" -c \"ipv6 route 4000::0/64 2000::2 vrf Vrf_2\"") - - # check application database - self.pdb.wait_for_entry("ROUTE_TABLE:Vrf_1", "3000::/64") - self.pdb.wait_for_entry("ROUTE_TABLE:Vrf_2", "4000::/64") - - # check ASIC route database - self.check_route_entries_with_vrf(["3000::/64", "4000::/64"], [vrf_1_oid, vrf_2_oid]) - - # remove route - dvs.runcmd("vtysh -c \"configure terminal\" -c \"no ipv6 route 3000::0/64 2000::2 vrf Vrf_1\"") - dvs.runcmd("vtysh -c \"configure terminal\" -c \"no ipv6 route 4000::0/64 2000::2 vrf Vrf_2\"") - - # check application database - self.pdb.wait_for_deleted_entry("ROUTE_TABLE:Vrf_1", "3000::/64") - self.pdb.wait_for_deleted_entry("ROUTE_TABLE:Vrf_2", "4000::/64") - - # check ASIC route database - self.check_deleted_route_entries(["3000::/64", "4000::/64"]) - - # remove ip address - self.remove_ip_address("Ethernet0", "2000::1/64") - self.remove_ip_address("Ethernet4", "2001::1/64") - self.remove_ip_address("Ethernet8", "2000::1/64") - self.remove_ip_address("Ethernet12", "2001::1/64") - - # remove l3 interface - self.remove_l3_intf("Ethernet0") - self.remove_l3_intf("Ethernet4") - self.remove_l3_intf("Ethernet8") - self.remove_l3_intf("Ethernet12") - - # bring down interface - self.set_admin_status("Ethernet0", "down") - self.set_admin_status("Ethernet4", "down") - self.set_admin_status("Ethernet8", "down") - self.set_admin_status("Ethernet12", "down") - - # remove vrf - self.remove_vrf("Vrf_1") - self.remove_vrf("Vrf_2") - - # remove ip address and default route - dvs.servers[0].runcmd("ip -6 route del default dev eth0") - dvs.servers[0].runcmd("ip -6 address del 2000::2/64 dev eth0") - dvs.servers[1].runcmd("ip -6 route del default dev eth0") - dvs.servers[1].runcmd("ip -6 address del 2001::2/64 dev eth0") - dvs.servers[2].runcmd("ip -6 route del default dev eth0") - dvs.servers[2].runcmd("ip -6 address del 2000::2/64 dev eth0") - dvs.servers[3].runcmd("ip -6 route del default dev eth0") - dvs.servers[3].runcmd("ip -6 address del 2001::2/64 dev eth0") - - @pytest.mark.skip(reason="FRR 7.5 issue https://github.com/Azure/sonic-buildimage/issues/6359") - def test_RouteAndNexthopInDifferentVrf(self, dvs, testlog): - self.setup_db(dvs) - - # create vrf - vrf_1_oid = self.create_vrf("Vrf_1") - vrf_2_oid = self.create_vrf("Vrf_2") - - # create l3 interface - self.create_l3_intf("Ethernet0", "Vrf_1") - self.create_l3_intf("Ethernet4", "Vrf_1") - self.create_l3_intf("Ethernet8", "Vrf_2") - self.create_l3_intf("Ethernet12", "Vrf_2") - - # set ip address - self.add_ip_address("Ethernet0", "10.0.0.1/24") - self.add_ip_address("Ethernet4", "10.0.1.1/24") - self.add_ip_address("Ethernet8", "20.0.0.1/24") - self.add_ip_address("Ethernet12", "20.0.1.1/24") - - # bring up interface - self.set_admin_status("Ethernet0", "up") - self.set_admin_status("Ethernet4", "up") - self.set_admin_status("Ethernet8", "up") - self.set_admin_status("Ethernet12", "up") - - # set ip address and default route - dvs.servers[0].runcmd("ip address add 10.0.0.2/24 dev eth0") - dvs.servers[0].runcmd("ip route add default via 10.0.0.1") - - dvs.servers[1].runcmd("ip address add 10.0.1.2/24 dev eth0") - dvs.servers[1].runcmd("ip route add default via 10.0.1.1") - - dvs.servers[2].runcmd("ip address add 20.0.0.2/24 dev eth0") - dvs.servers[2].runcmd("ip route add default via 20.0.0.1") - - dvs.servers[3].runcmd("ip address add 20.0.1.2/24 dev eth0") - dvs.servers[3].runcmd("ip route add default via 20.0.1.1") - - # get neighbor entry - dvs.servers[0].runcmd("ping -c 1 10.0.1.2") - dvs.servers[2].runcmd("ping -c 1 20.0.1.2") - - # add route - dvs.runcmd("vtysh -c \"configure terminal\" -c \"ip route 20.0.1.2/32 20.0.1.2 vrf Vrf_1 nexthop-vrf Vrf_2\"") - dvs.runcmd("vtysh -c \"configure terminal\" -c \"ip route 10.0.0.2/32 10.0.0.2 vrf Vrf_2 nexthop-vrf Vrf_1\"") - - # check application database - self.pdb.wait_for_entry("ROUTE_TABLE:Vrf_1", "20.0.1.2") - self.pdb.wait_for_entry("ROUTE_TABLE:Vrf_2", "10.0.0.2") - - # check ASIC neighbor interface database - self.check_route_entries_nexthop(["10.0.0.2/32", "20.0.1.2/32"], [vrf_2_oid, vrf_1_oid], ["10.0.0.2", "20.0.1.2"]) - - # Ping should work - ping_stats = dvs.servers[0].runcmd("ping -c 1 20.0.1.2") - assert ping_stats == 0 - - # remove route - dvs.runcmd("vtysh -c \"configure terminal\" -c \"no ip route 20.0.1.2/32 20.0.1.2 vrf Vrf_1 nexthop-vrf Vrf_2\"") - dvs.runcmd("vtysh -c \"configure terminal\" -c \"no ip route 10.0.0.2/32 10.0.0.2 vrf Vrf_2 nexthop-vrf Vrf_1\"") - - # check application database - self.pdb.wait_for_deleted_entry("ROUTE_TABLE:Vrf_1", "20.0.1.2") - self.pdb.wait_for_deleted_entry("ROUTE_TABLE:Vrf_2", "10.0.0.2") - - # check ASIC route database - self.check_deleted_route_entries(["10.0.0.2/32", "20.0.1.2/32"]) - - # remove ip address - self.remove_ip_address("Ethernet0", "10.0.0.1/24") - self.remove_ip_address("Ethernet4", "10.0.1.1/24") - self.remove_ip_address("Ethernet8", "20.0.0.1/24") - self.remove_ip_address("Ethernet12", "20.0.1.1/24") - - # remove l3 interface - self.remove_l3_intf("Ethernet0") - self.remove_l3_intf("Ethernet4") - self.remove_l3_intf("Ethernet8") - self.remove_l3_intf("Ethernet12") - - self.set_admin_status("Ethernet0", "down") - self.set_admin_status("Ethernet4", "down") - self.set_admin_status("Ethernet8", "down") - self.set_admin_status("Ethernet12", "down") - - # remove vrf - self.remove_vrf("Vrf_1") - self.remove_vrf("Vrf_2") - - # remove ip address and default route - dvs.servers[0].runcmd("ip route del default dev eth0") - dvs.servers[0].runcmd("ip address del 10.0.0.2/24 dev eth0") - dvs.servers[1].runcmd("ip route del default dev eth0") - dvs.servers[1].runcmd("ip address del 10.0.1.2/24 dev eth0") - dvs.servers[2].runcmd("ip route del default dev eth0") - dvs.servers[2].runcmd("ip address del 20.0.0.2/24 dev eth0") - dvs.servers[3].runcmd("ip route del default dev eth0") - dvs.servers[3].runcmd("ip address del 20.0.1.2/24 dev eth0") - - def test_RouteAddRemoveIpv4BlackholeRoute(self, dvs, testlog): - self.setup_db(dvs) - - self.clear_srv_config(dvs) - - # add route entry - dvs.runcmd("vtysh -c \"configure terminal\" -c \"ip route 2.2.2.0/24 blackhole\"") - - # check application database - self.pdb.wait_for_entry("ROUTE_TABLE", "2.2.2.0/24") - - # check ASIC route database - self.check_route_entries(["2.2.2.0/24"]) - key = self.get_asic_db_key("2.2.2.0/24") - assert key - fvs = self.adb.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY", key) - assert fvs.get("SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION") == "SAI_PACKET_ACTION_DROP" - - # remove route entry - dvs.runcmd("vtysh -c \"configure terminal\" -c \"no ip route 2.2.2.0/24 blackhole\"") - - # check application database - self.pdb.wait_for_deleted_entry("ROUTE_TABLE", "2.2.2.0/24") - - # check ASIC route database - self.check_deleted_route_entries(["2.2.2.0/24"]) - - def test_RouteAddRemoveIpv6BlackholeRoute(self, dvs, testlog): - self.setup_db(dvs) - - self.clear_srv_config(dvs) - - # add route entry - dvs.runcmd("vtysh -c \"configure terminal\" -c \"ipv6 route 3000::0/64 blackhole\"") - - # check application database - self.pdb.wait_for_entry("ROUTE_TABLE", "3000::/64") - - # check ASIC route database - self.check_route_entries(["3000::/64"]) - key = self.get_asic_db_key("3000::/64") - assert key - fvs = self.adb.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY", key) - assert fvs.get("SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION") == "SAI_PACKET_ACTION_DROP" - - # remove route entry - dvs.runcmd("vtysh -c \"configure terminal\" -c \"no ipv6 route 3000::0/64 blackhole\"") - - # check application database - self.pdb.wait_for_deleted_entry("ROUTE_TABLE", "3000::/64") - - # check ASIC route database - self.check_deleted_route_entries(["3000::/64"]) - -class TestRoutePerf(TestRouteBase): - """ Performance tests for route """ - def test_PerfAddRemoveRoute(self, dvs, testlog): - self.setup_db(dvs) - self.clear_srv_config(dvs) - numRoutes = 5000 # number of routes to add/remove - - # generate ip prefixes of routes - prefixes = [] - for i in range(numRoutes): - prefixes.append("%d.%d.%d.%d/%d" % (100 + int(i / 256 ** 2), int(i / 256), i % 256, 0, 24)) - - # create l3 interface - self.create_l3_intf("Ethernet0", "") - self.create_l3_intf("Ethernet4", "") - - # set ip address - self.add_ip_address("Ethernet0", "10.0.0.0/31") - self.add_ip_address("Ethernet4", "10.0.0.2/31") - - # bring up interface - self.set_admin_status("Ethernet0", "up") - self.set_admin_status("Ethernet4", "up") - - # set ip address and default route - dvs.servers[0].runcmd("ip address add 10.0.0.1/31 dev eth0") - dvs.servers[0].runcmd("ip route add default via 10.0.0.0") - - dvs.servers[1].runcmd("ip address add 10.0.0.3/31 dev eth0") - dvs.servers[1].runcmd("ip route add default via 10.0.0.2") - time.sleep(2) - - fieldValues = [{"nexthop": "10.0.0.1", "ifname": "Ethernet0"}, {"nexthop": "10.0.0.3", "ifname": "Ethernet4"}] - - # get neighbor and arp entry - dvs.servers[0].runcmd("ping -c 1 10.0.0.3") - dvs.servers[1].runcmd("ping -c 1 10.0.0.1") - time.sleep(2) - - # get number of routes before adding new routes - startNumRoutes = len(self.adb.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY")) - - # add route entries - timeStart = time.time() - for i in range(numRoutes): - self.create_route_entry(prefixes[i], fieldValues[i % 2]) - - # wait until all routes are added into ASIC database - self.adb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY", startNumRoutes + numRoutes) # default timeout is 5 seconds - print("Time to add %d routes is %.2f seconds. " % (numRoutes, time.time() - timeStart)) - - # confirm all routes are added - self.check_route_entries(prefixes) - - # remove route entries - timeStart = time.time() - for i in range(numRoutes): - self.remove_route_entry(prefixes[i]) - - # wait until all routes are removed from ASIC database - self.adb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY", startNumRoutes) # default timeout is 5 seconds - print("Time to remove %d routes is %.2f seconds. " % (numRoutes, time.time() - timeStart)) - - # confirm all routes are removed - self.check_deleted_route_entries(prefixes) - - # remove ip address - self.remove_ip_address("Ethernet0", "10.0.0.0/31") - self.remove_ip_address("Ethernet4", "10.0.0.2/31") - - # remove l3 interface - self.remove_l3_intf("Ethernet0") - self.remove_l3_intf("Ethernet4") - - self.set_admin_status("Ethernet0", "down") - self.set_admin_status("Ethernet4", "down") - - # remove ip address and default route - dvs.servers[0].runcmd("ip route del default dev eth0") - dvs.servers[0].runcmd("ip address del 10.0.0.1/31 dev eth0") - - dvs.servers[1].runcmd("ip route del default dev eth0") - dvs.servers[1].runcmd("ip address del 10.0.0.3/31 dev eth0") - -class TestFpmSyncResponse(TestRouteBase): - @pytest.fixture - def setup(self, dvs): - self.setup_db(dvs) - - # create l3 interface - self.create_l3_intf("Ethernet0", "") - # set ip address - self.add_ip_address("Ethernet0", "10.0.0.0/31") - # bring up interface - self.set_admin_status("Ethernet0", "up") - - # set ip address and default route - dvs.servers[0].runcmd("ip address add 10.0.0.1/31 dev eth0") - dvs.servers[0].runcmd("ip route add default via 10.0.0.0") - - dvs.runcmd("ping -c 1 10.0.0.1") - - yield - - # remove ip address and default route - dvs.servers[0].runcmd("ip route del default dev eth0") - dvs.servers[0].runcmd("ip address del 10.0.0.1/31 dev eth0") - - # bring interface down - self.set_admin_status("Ethernet0", "down") - # remove ip address - self.remove_ip_address("Ethernet0", "10.0.0.0/31") - # remove l3 interface - self.remove_l3_intf("Ethernet0") - - def is_offloaded(self, dvs, route): - rc, output = dvs.runcmd(f"vtysh -c 'show ip route {route} json'") - assert rc == 0 - - route_entry = json.loads(output) - return bool(route_entry[route][0].get('offloaded')) - - @pytest.mark.xfail(reason="Requires VS docker update in https://github.com/sonic-net/sonic-buildimage/pull/12853") - @pytest.mark.parametrize("suppress_state", ["enabled", "disabled"]) - def test_offload(self, suppress_state, setup, dvs): - route = "1.1.1.0/24" - - # enable route suppression - rc, _ = dvs.runcmd(f"config suppress-fib-pending {suppress_state}") - assert rc == 0, "Failed to configure suppress-fib-pending" - - time.sleep(5) - - try: - rc, _ = dvs.runcmd("bash -c 'kill -SIGSTOP $(pidof orchagent)'") - assert rc == 0, "Failed to suspend orchagent" - - rc, _ = dvs.runcmd(f"ip route add {route} via 10.0.0.1 proto bgp") - assert rc == 0, "Failed to configure route" - - time.sleep(5) - - if suppress_state == 'disabled': - assert self.is_offloaded(dvs,route), f"{route} is expected to be offloaded (suppression is {suppress_state})" - return - - assert not self.is_offloaded(dvs, route), f"{route} is expected to be not offloaded (suppression is {suppress_state})" - - rc, _ = dvs.runcmd("bash -c 'kill -SIGCONT $(pidof orchagent)'") - assert rc == 0, "Failed to resume orchagent" - - def check_offloaded(): - return (self.is_offloaded(dvs, route), None) - - wait_for_result(check_offloaded, failure_message=f"{route} is expected to be offloaded after orchagent resume") - finally: - dvs.runcmd("bash -c 'kill -SIGCONT $(pidof orchagent)'") - dvs.runcmd(f"ip route del {route}") - - # make sure route suppression is disabled - dvs.runcmd("config suppress-fib-pending disabled") - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_setro.py b/tests/test_setro.py deleted file mode 100644 index d049a62981..0000000000 --- a/tests/test_setro.py +++ /dev/null @@ -1,52 +0,0 @@ -import time -import json -import redis -import pytest - -from pprint import pprint -from swsscommon import swsscommon - - -class TestSetRo(object): - def test_SetReadOnlyAttribute(self, dvs, testlog): - - db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - - tbl = swsscommon.Table(db, "ASIC_STATE:SAI_OBJECT_TYPE_SWITCH") - - keys = tbl.getKeys() - - assert len(keys) == 1 - - swVid = keys[0] - - r = redis.Redis(unix_socket_path=dvs.redis_sock, db=swsscommon.ASIC_DB, - encoding="utf-8", decode_responses=True) - - swRid = r.hget("VIDTORID", swVid) - - assert swRid is not None - - ntf = swsscommon.NotificationProducer(db, "SAI_VS_UNITTEST_CHANNEL") - - fvp = swsscommon.FieldValuePairs() - - ntf.send("enable_unittests", "true", fvp) - - fvp = swsscommon.FieldValuePairs([('SAI_SWITCH_ATTR_PORT_MAX_MTU', '42')]) - - key = "SAI_OBJECT_TYPE_SWITCH:" + swRid - - print(key) - - # explicit convert unicode string to str for python2 - ntf.send("set_ro", str(key), fvp) - - # make action on appdb so orchagent will get RO value - # read asic db to see if orchagent behaved correctly - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_sflow.py b/tests/test_sflow.py deleted file mode 100644 index 25e3a8eaf9..0000000000 --- a/tests/test_sflow.py +++ /dev/null @@ -1,347 +0,0 @@ -import time -from swsscommon import swsscommon - -class TestSflow: - speed_rate_table = { - "400000": "400000", - "200000": "200000", - "100000": "100000", - "50000": "50000", - "40000": "40000", - "25000": "25000", - "10000": "10000", - "1000": "1000" - } - - def setup_sflow(self, dvs): - self.adb = dvs.get_asic_db() - self.cdb = dvs.get_config_db() - - self.cdb.create_entry("SFLOW", "global", {"admin_state": "up"}) - - def test_defaultGlobal(self, dvs, testlog): - self.setup_sflow(dvs) - - # Verify that the session is up - port_oid = self.adb.port_name_map["Ethernet0"] - expected_fields = {"SAI_PORT_ATTR_INGRESS_SAMPLEPACKET_ENABLE": "oid:0x0"} - fvs = self.adb.wait_for_field_negative_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) - - sample_session = fvs["SAI_PORT_ATTR_INGRESS_SAMPLEPACKET_ENABLE"] - speed = fvs["SAI_PORT_ATTR_SPEED"] - - rate = self.speed_rate_table.get(speed, None) - assert rate - - expected_fields = {"SAI_SAMPLEPACKET_ATTR_SAMPLE_RATE": rate} - self.adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_SAMPLEPACKET", sample_session, expected_fields) - - self.cdb.update_entry("SFLOW", "global", {"admin_state": "down"}) - expected_fields = {"SAI_PORT_ATTR_INGRESS_SAMPLEPACKET_ENABLE": "oid:0x0"} - self.adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) - - def test_globalAll(self, dvs, testlog): - self.setup_sflow(dvs) - - # Verify that the session is up first - port_oid = self.adb.port_name_map["Ethernet0"] - expected_fields = {"SAI_PORT_ATTR_INGRESS_SAMPLEPACKET_ENABLE": "oid:0x0"} - self.adb.wait_for_field_negative_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) - - # Then shut down the session - self.cdb.update_entry("SFLOW_SESSION", "all", {"admin_state": "down"}) - expected_fields = {"SAI_PORT_ATTR_INGRESS_SAMPLEPACKET_ENABLE": "oid:0x0"} - self.adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) - - self.cdb.update_entry("SFLOW_SESSION", "all", {"admin_state": "up"}) - self.adb.wait_for_field_negative_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) - - self.cdb.delete_entry("SFLOW_SESSION", "all") - self.adb.wait_for_field_negative_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) - - def test_InterfaceSet(self, dvs, testlog): - self.setup_sflow(dvs) - - # Get the global session info as a baseline - port_oid = self.adb.port_name_map["Ethernet0"] - expected_fields = ["SAI_PORT_ATTR_INGRESS_SAMPLEPACKET_ENABLE"] - fvs = self.adb.wait_for_fields("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) - global_session = fvs["SAI_PORT_ATTR_INGRESS_SAMPLEPACKET_ENABLE"] - - # Then create the interface session - session_params = {"admin_state": "up", "sample_rate": "1000"} - self.cdb.create_entry("SFLOW_SESSION", "Ethernet0", session_params) - - # Verify that the new interface session has been created and is different from the global one - port_oid = self.adb.port_name_map["Ethernet0"] - expected_fields = {"SAI_PORT_ATTR_INGRESS_SAMPLEPACKET_ENABLE": global_session} - fvs = self.adb.wait_for_field_negative_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) - - sample_session = fvs["SAI_PORT_ATTR_INGRESS_SAMPLEPACKET_ENABLE"] - - expected_fields = {"SAI_SAMPLEPACKET_ATTR_SAMPLE_RATE": "1000"} - self.adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_SAMPLEPACKET", sample_session, expected_fields) - - self.cdb.create_entry("SFLOW_SESSION", "all", {"admin_state": "down"}) - - expected_fields = {"SAI_PORT_ATTR_INGRESS_SAMPLEPACKET_ENABLE": "oid:0x0"} - self.adb.wait_for_field_negative_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) - - self.cdb.create_entry("SFLOW", "global", {"admin_state": "down"}) - self.adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) - - self.cdb.delete_entry("SFLOW_SESSION", "all") - self.cdb.delete_entry("SFLOW_SESSION", "Ethernet0") - - def test_defaultRate(self, dvs, testlog): - self.setup_sflow(dvs) - - session_params = {"admin_state": "up"} - self.cdb.create_entry("SFLOW_SESSION", "Ethernet4", session_params) - - port_oid = self.adb.port_name_map["Ethernet4"] - expected_fields = {"SAI_PORT_ATTR_INGRESS_SAMPLEPACKET_ENABLE": "oid:0x0"} - fvs = self.adb.wait_for_field_negative_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) - - sample_session = fvs["SAI_PORT_ATTR_INGRESS_SAMPLEPACKET_ENABLE"] - speed = fvs["SAI_PORT_ATTR_SPEED"] - - rate = self.speed_rate_table.get(speed, None) - assert rate - - expected_fields = {"SAI_SAMPLEPACKET_ATTR_SAMPLE_RATE": rate} - self.adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_SAMPLEPACKET", sample_session, expected_fields) - - self.cdb.delete_entry("SFLOW_SESSION", "Ethernet4") - - def test_ConfigDel(self, dvs, testlog): - self.setup_sflow(dvs) - - session_params = {"admin_state": "up", "sample_rate": "1000"} - self.cdb.create_entry("SFLOW_SESSION_TABLE", "Ethernet0", session_params) - - self.cdb.delete_entry("SFLOW_SESSION_TABLE", "Ethernet0") - - port_oid = self.adb.port_name_map["Ethernet0"] - expected_fields = {"SAI_PORT_ATTR_INGRESS_SAMPLEPACKET_ENABLE": "oid:0x0"} - fvs = self.adb.wait_for_field_negative_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) - - sample_session = fvs["SAI_PORT_ATTR_INGRESS_SAMPLEPACKET_ENABLE"] - speed = fvs["SAI_PORT_ATTR_SPEED"] - - rate = self.speed_rate_table.get(speed, None) - assert rate - - expected_fields = {"SAI_SAMPLEPACKET_ATTR_SAMPLE_RATE": rate} - self.adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_SAMPLEPACKET", sample_session, expected_fields) - - def test_SamplingRatePortCfgUpdate(self, dvs, testlog): - ''' - This test checks if the SflowMgr updates the sampling rate - 1) When the Speed is Updated on the port and no local configuration has been given on the port - Eg: - config sflow enable - config interface speed Ethernet0 25000 (Let's suppose Original Speed for Ethernet0 is 100G) - show sflow interface | grep Ethernet0 (Should see a sampling rate of 25000 not 100000) - ''' - self.setup_sflow(dvs) - appldb = dvs.get_app_db() - self.cdb.update_entry("PORT", "Ethernet0", {'speed' : "25000"}) - expected_fields = {"sample_rate": self.speed_rate_table["25000"]} - appldb.wait_for_field_match("SFLOW_SESSION_TABLE", "Ethernet0", expected_fields) - - - def test_SamplingRateManualUpdate(self, dvs, testlog): - ''' - This test checks if the SflowMgr updates the sampling rate - 1) When the Cfg Sflow Table is updated with sampling rate by the user, this rate should not be impacted by Port Speed Changes - Eg: - config sflow enable - config sflow interface sample-rate Ethernet4 256 - config interface Ethernet0 speed 25000 (Original Speed for Ethernet0 is 100G) - show sflow interface | grep Ethernet0 (Should see a sampling rate of 256 not 100000 or 25000 - ''' - self.setup_sflow(dvs) - appldb = dvs.get_app_db() - - session_params = {"admin_state": "up", "sample_rate": "256"} - self.cdb.create_entry("SFLOW_SESSION", "Ethernet4", session_params) - self.cdb.wait_for_field_match("SFLOW_SESSION", "Ethernet4", session_params) - appldb.wait_for_field_match("SFLOW_SESSION_TABLE", "Ethernet4", {"sample_rate": "256"}) - - self.cdb.update_entry("PORT", "Ethernet4", {'speed' : "25000"}) - # The Check here is about the original value not getting changed. - # If some bug was to appear, let's give it some time to get noticed - time.sleep(1) - appldb.wait_for_field_match("SFLOW_SESSION_TABLE", "Ethernet4", {"sample_rate": "256"}) - - def test_InterfaceDisableAllUpdate(self, dvs, testlog): - ''' - This test checks if the SflowMgr updates sflow session table in APPL_DB when user has not configured the admin_status. - Steps to verify the issue: - 1) Enable sflow globally - 2) Configure sample rate for Ethernet0 - 3) Configure sample rate for Ethernet4 - 4) verify whether sample rates are reflected in the Ethernet0 & Ethernet4 interfaces - 5) Execute sflow disable all command to disable all interfaces - 6) Verify whether all interfaces are disabled (without the fix, interfaces were shown with admin up with configured rate, - this is not expected). - ''' - self.setup_sflow(dvs) - - appldb = dvs.get_app_db() - # create the interface session - session_params = {"sample_rate": "256"} - self.cdb.create_entry("SFLOW_SESSION", "Ethernet0", session_params) - expected_fields = {"sample_rate": "256"} - appldb.wait_for_field_match("SFLOW_SESSION_TABLE", "Ethernet0", expected_fields) - - session_params = {"sample_rate": "512"} - self.cdb.create_entry("SFLOW_SESSION", "Ethernet4", session_params) - expected_fields = {"sample_rate": "512"} - appldb.wait_for_field_match("SFLOW_SESSION_TABLE", "Ethernet4", expected_fields) - - session_params = {"admin_state": "down"} - self.cdb.create_entry("SFLOW_SESSION", "all", session_params) - # Wait for the APPL_DB from sflowmgrd - expected_fields = {} - appldb.wait_for_field_match("SFLOW_SESSION_TABLE", "Ethernet0", expected_fields) - appldb.wait_for_field_match("SFLOW_SESSION_TABLE", "Ethernet4", expected_fields) - - self.cdb.delete_entry("SFLOW_SESSION", "all") - self.cdb.delete_entry("SFLOW_SESSION", "Ethernet0") - self.cdb.delete_entry("SFLOW_SESSION", "Ethernet4") - - def test_InterfaceDefaultSampleRate(self, dvs, testlog): - ''' - This test checks if the SflowMgr updates sflow session table in APPL_DB with default rate. - Steps to verify the issue: - 1) Enable sflow globally - 2) Configure sample rate for Ethernet0 - 3) Verify whether sample rate is reflected in the Ethernet0 interfaces - 4) Remove sample rate for Ethernet0 - 5) Verify whether sample rate of Ethernet0 interface moved to default sample rate - ''' - self.setup_sflow(dvs) - - port_oid = self.adb.port_name_map["Ethernet0"] - expected_fields = {"SAI_PORT_ATTR_INGRESS_SAMPLEPACKET_ENABLE": "oid:0x0"} - fvs = self.adb.wait_for_field_negative_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) - speed = fvs["SAI_PORT_ATTR_SPEED"] - rate = self.speed_rate_table.get(speed, None) - assert rate - - appldb = dvs.get_app_db() - # create the interface session - session_params = {"sample_rate": "256"} - self.cdb.create_entry("SFLOW_SESSION", "Ethernet0", session_params) - expected_fields = {"admin_state": "up", "sample_rate": "256"} - appldb.wait_for_field_match("SFLOW_SESSION_TABLE", "Ethernet0", expected_fields) - - cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) - tbl = swsscommon.Table(cdb, "SFLOW_SESSION") - tbl.hdel("Ethernet0","sample_rate") - - expected_fields = {"admin_state": "up", "sample_rate": rate} - appldb.wait_for_field_match("SFLOW_SESSION_TABLE", "Ethernet0", expected_fields) - - self.cdb.delete_entry("SFLOW_SESSION", "Ethernet0") - - def test_Teardown(self, dvs, testlog): - self.setup_sflow(dvs) - - self.cdb.delete_entry("SFLOW", "global") - self.adb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_SAMPLEPACKET", 0) - - def test_globalSetSampleDir(self, dvs, testlog): - self.setup_sflow(dvs) - - # Verify that the session is up first - port_oid = self.adb.port_name_map["Ethernet0"] - expected_fields = {"SAI_PORT_ATTR_INGRESS_SAMPLEPACKET_ENABLE": "oid:0x0"} - expected_fields_egr = {"SAI_PORT_ATTR_EGRESS_SAMPLEPACKET_ENABLE": "oid:0x0"} - - self.adb.wait_for_field_negative_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) - - self.cdb.update_entry("SFLOW", "global", {"sample_direction": "both"}) - self.adb.wait_for_field_negative_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) - self.adb.wait_for_field_negative_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields_egr) - - self.cdb.update_entry("SFLOW", "global", {"sample_direction": "tx"}) - self.adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) - self.adb.wait_for_field_negative_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields_egr) - - self.cdb.delete_entry("SFLOW", "global") - self.adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) - self.adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields_egr) - - def test_globalAllSetDir(self, dvs, testlog): - self.setup_sflow(dvs) - # Verify that the session is up first - port_oid = self.adb.port_name_map["Ethernet0"] - self.cdb.update_entry("SFLOW_SESSION", "all", {"sample_direction": "both"}) - expected_fields = {"SAI_PORT_ATTR_INGRESS_SAMPLEPACKET_ENABLE": "oid:0x0"} - expected_fields_egr = {"SAI_PORT_ATTR_EGRESS_SAMPLEPACKET_ENABLE": "oid:0x0"} - self.adb.wait_for_field_negative_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) - self.adb.wait_for_field_negative_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields_egr) - - self.cdb.update_entry("SFLOW_SESSION", "all", {"sample_direction": "tx"}) - self.adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) - self.adb.wait_for_field_negative_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields_egr) - - self.cdb.delete_entry("SFLOW", "global") - self.adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) - self.adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields_egr) - - def test_InterfaceSetDir(self, dvs, testlog): - self.setup_sflow(dvs) - - # Get the global session info as a baseline - port_oid = self.adb.port_name_map["Ethernet0"] - expected_fields = ["SAI_PORT_ATTR_INGRESS_SAMPLEPACKET_ENABLE"] - fvs = self.adb.wait_for_fields("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) - global_session = fvs["SAI_PORT_ATTR_INGRESS_SAMPLEPACKET_ENABLE"] - - # Then create the interface session - session_params = {"admin_state": "up", "sample_rate": "1000", "sample_direction": "both"} - self.cdb.create_entry("SFLOW_SESSION", "Ethernet0", session_params) - - # Verify that the new interface session has been created and is different from the global one - port_oid = self.adb.port_name_map["Ethernet0"] - expected_fields = {"SAI_PORT_ATTR_INGRESS_SAMPLEPACKET_ENABLE": global_session} - fvs = self.adb.wait_for_field_negative_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) - - expected_fields_egr = {"SAI_PORT_ATTR_EGRESS_SAMPLEPACKET_ENABLE": global_session} - fvs = self.adb.wait_for_field_negative_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields_egr) - - local_ing_session = fvs["SAI_PORT_ATTR_INGRESS_SAMPLEPACKET_ENABLE"] - local_egr_session = fvs["SAI_PORT_ATTR_EGRESS_SAMPLEPACKET_ENABLE"] - - self.cdb.update_entry("SFLOW_SESSION", "Ethernet0", {"sample_direction": "tx"}) - - expected_fields = {"SAI_PORT_ATTR_INGRESS_SAMPLEPACKET_ENABLE": "oid:0x0"} - expected_fields_egr = {"SAI_PORT_ATTR_EGRESS_SAMPLEPACKET_ENABLE": local_egr_session} - fvs = self.adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) - fvs = self.adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields_egr) - - self.cdb.update_entry("SFLOW_SESSION", "Ethernet0", {"sample_direction": "rx"}) - - expected_fields = {"SAI_PORT_ATTR_INGRESS_SAMPLEPACKET_ENABLE": local_ing_session} - expected_fields_egr = {"SAI_PORT_ATTR_EGRESS_SAMPLEPACKET_ENABLE": "oid:0x0"} - fvs = self.adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) - fvs = self.adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields_egr) - - # interface config higher precedence then global/all. Changing all sample-dir should not affect existing interface config - self.cdb.create_entry("SFLOW_SESSION", "all", {"admin_state": "up", "sample_direction": "both"}) - fvs = self.adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) - fvs = self.adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields_egr) - - # interface delete will set fallback to all (sample-direction) if enabled. - self.cdb.delete_entry("SFLOW_SESSION", "Ethernet0") - fvs = self.adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, {"SAI_PORT_ATTR_INGRESS_SAMPLEPACKET_ENABLE": local_ing_session}) - fvs = self.adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, {"SAI_PORT_ATTR_INGRESS_SAMPLEPACKET_ENABLE": local_egr_session}) - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_speed.py b/tests/test_speed.py deleted file mode 100644 index bf44685989..0000000000 --- a/tests/test_speed.py +++ /dev/null @@ -1,82 +0,0 @@ -"""test_speed.py verifies that speed is set on interfaces and buffer manager behavies correctly on speed change.""" -import pytest - - -class TestSpeedSet: - # FIXME: This value should probably not be hardcoded since the persistent container can - # specify a dynamic number of ports now. - NUM_PORTS = 32 - - @pytest.mark.skip(reason="Failing. Under investigation") - def test_SpeedAndBufferSet(self, dvs, testlog): - configured_speed_list = [] - speed_list = ["10000", "25000", "40000", "50000", "100000"] - - # buffers_config.j2 is used for the test and defines 3 static profiles and 1 dynamic profile: - # "ingress_lossy_profile" - # "egress_lossless_profile" - # "egress_lossy_profile" - # "pg_lossless_40000_300m_profile" - num_buffer_profiles = 4 - - cdb = dvs.get_config_db() - adb = dvs.get_asic_db() - - # Get speed from the first port we hit in ASIC DB port walk, and - # assume that its the initial configured speed for all ports, and - # as new port configuration file i.e. 'platform.json' guarantees - # 100G as initial port speed for all ports and the dynamic buffer - # profile has already been created for it. - asic_port_records = adb.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_PORT") - for k in asic_port_records: - fvs = adb.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_PORT", k) - if "SAI_PORT_ATTR_SPEED" in fvs.keys(): - configured_speed_list.append(fvs["SAI_PORT_ATTR_SPEED"]) - break - - if configured_speed_list: - break - - # Check if the buffer profiles make it to Config DB - cdb.wait_for_n_keys("BUFFER_PROFILE", num_buffer_profiles) - - # Check if they make it to the ASIC - adb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_BUFFER_PROFILE", num_buffer_profiles) - - for speed in speed_list: - # Set same speed on all ports - for i in range(0, self.NUM_PORTS): - cdb.update_entry("PORT", "Ethernet{}".format(i * 4), {"speed": speed}) - - # Check that the speed was set for all "NUM_PORTS" ports - asic_port_records = adb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_PORT", self.NUM_PORTS + 1) # +1 CPU Port - for port in [port for port in asic_port_records if port in adb.port_name_map.values()]: - adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port, {"SAI_PORT_ATTR_SPEED": speed}) - - # Check number of created profiles - if speed not in configured_speed_list: - num_buffer_profiles += 1 # New speed should add new PG profile - configured_speed_list.append(speed) - - current_buffer_profiles = cdb.wait_for_n_keys("BUFFER_PROFILE", num_buffer_profiles) - # Make sure the same number of profiles are created on the ASIC - adb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_BUFFER_PROFILE", num_buffer_profiles) - - # Check new profile name - expected_new_profile_name = "pg_lossless_{}_300m_profile".format(speed) - assert expected_new_profile_name in current_buffer_profiles - - # Check correct profile is set for all ports - pg_tables = cdb.get_keys("BUFFER_PG") - for i in range(0, self.NUM_PORTS): - expected_pg_table = "Ethernet{}|3-4".format(i * 4) - assert expected_pg_table in pg_tables - - expected_fields = {"profile": expected_new_profile_name} - cdb.wait_for_field_match("BUFFER_PG", expected_pg_table, expected_fields) - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_srv6.py b/tests/test_srv6.py deleted file mode 100644 index 3ce19421b0..0000000000 --- a/tests/test_srv6.py +++ /dev/null @@ -1,633 +0,0 @@ -import os -import re -import time -import json -import pytest - -from swsscommon import swsscommon -from dvslib.dvs_common import wait_for_result - -def get_exist_entries(db, table): - tbl = swsscommon.Table(db, table) - return set(tbl.getKeys()) - -def get_created_entry(db, table, existed_entries): - tbl = swsscommon.Table(db, table) - entries = set(tbl.getKeys()) - new_entries = list(entries - existed_entries) - assert len(new_entries) == 1, "Wrong number of created entries." - return new_entries[0] - -class TestSrv6Mysid(object): - def setup_db(self, dvs): - self.pdb = dvs.get_app_db() - self.adb = dvs.get_asic_db() - self.cdb = dvs.get_config_db() - - def create_vrf(self, vrf_name): - table = "ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER" - existed_entries = get_exist_entries(self.adb.db_connection, table) - - self.cdb.create_entry("VRF", vrf_name, {"empty": "empty"}) - - self.adb.wait_for_n_keys(table, len(existed_entries) + 1) - return get_created_entry(self.adb.db_connection, table, existed_entries) - - def remove_vrf(self, vrf_name): - self.cdb.delete_entry("VRF", vrf_name) - - def add_ip_address(self, interface, ip): - self.cdb.create_entry("INTERFACE", interface + "|" + ip, {"NULL": "NULL"}) - - def remove_ip_address(self, interface, ip): - self.cdb.delete_entry("INTERFACE", interface + "|" + ip) - - def add_neighbor(self, interface, ip, mac, family): - table = "ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY" - existed_entries = get_exist_entries(self.adb.db_connection, table) - - tbl = swsscommon.ProducerStateTable(self.pdb.db_connection, "NEIGH_TABLE") - fvs = swsscommon.FieldValuePairs([("neigh", mac), - ("family", family)]) - tbl.set(interface + ":" + ip, fvs) - - self.adb.wait_for_n_keys(table, len(existed_entries) + 1) - return get_created_entry(self.adb.db_connection, table, existed_entries) - - def remove_neighbor(self, interface, ip): - tbl = swsscommon.ProducerStateTable(self.pdb.db_connection, "NEIGH_TABLE") - tbl._del(interface + ":" + ip) - time.sleep(1) - - def create_mysid(self, mysid, fvs): - table = "ASIC_STATE:SAI_OBJECT_TYPE_MY_SID_ENTRY" - existed_entries = get_exist_entries(self.adb.db_connection, table) - - tbl = swsscommon.ProducerStateTable(self.pdb.db_connection, "SRV6_MY_SID_TABLE") - tbl.set(mysid, fvs) - - self.adb.wait_for_n_keys(table, len(existed_entries) + 1) - return get_created_entry(self.adb.db_connection, table, existed_entries) - - def remove_mysid(self, mysid): - tbl = swsscommon.ProducerStateTable(self.pdb.db_connection, "SRV6_MY_SID_TABLE") - tbl._del(mysid) - - def create_l3_intf(self, interface, vrf_name): - table = "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE" - existed_entries = get_exist_entries(self.adb.db_connection, table) - - if len(vrf_name) == 0: - self.cdb.create_entry("INTERFACE", interface, {"NULL": "NULL"}) - else: - self.cdb.create_entry("INTERFACE", interface, {"vrf_name": vrf_name}) - - self.adb.wait_for_n_keys(table, len(existed_entries) + 1) - return get_created_entry(self.adb.db_connection, table, existed_entries) - - def remove_l3_intf(self, interface): - self.cdb.delete_entry("INTERFACE", interface) - - def get_nexthop_id(self, ip_address): - next_hop_entries = get_exist_entries(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP") - tbl = swsscommon.Table(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP") - for next_hop_entry in next_hop_entries: - (status, fvs) = tbl.get(next_hop_entry) - - assert status == True - assert len(fvs) == 3 - - for fv in fvs: - if fv[0] == "SAI_NEXT_HOP_ATTR_IP" and fv[1] == ip_address: - return next_hop_entry - - return None - - def set_interface_status(self, dvs, interface, admin_status): - tbl_name = "PORT" - tbl = swsscommon.Table(self.cdb.db_connection, tbl_name) - fvs = swsscommon.FieldValuePairs([("admin_status", "up")]) - tbl.set(interface, fvs) - time.sleep(1) - - def test_mysid(self, dvs, testlog): - self.setup_db(dvs) - - # create MySID entries - mysid1='16:8:8:8:baba:2001:10::' - mysid2='16:8:8:8:baba:2001:20::' - mysid3='16:8:8:8:fcbb:bb01:800::' - mysid4='16:8:8:8:baba:2001:40::' - mysid5='32:16:16:0:fc00:0:1:e000::' - mysid6='32:16:16:0:fc00:0:1:e001::' - mysid7='32:16:16:0:fc00:0:1:e002::' - mysid8='32:16:16:0:fc00:0:1:e003::' - mysid9='32:16:16:0:fc00:0:1:e004::' - mysid10='32:16:16:0:fc00:0:1:e005::' - - # create MySID END - fvs = swsscommon.FieldValuePairs([('action', 'end')]) - key = self.create_mysid(mysid1, fvs) - - # check ASIC MySID database - mysid = json.loads(key) - assert mysid["sid"] == "baba:2001:10::" - tbl = swsscommon.Table(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_MY_SID_ENTRY") - (status, fvs) = tbl.get(key) - assert status == True - for fv in fvs: - if fv[0] == "SAI_MY_SID_ENTRY_ATTR_ENDPOINT_BEHAVIOR": - assert fv[1] == "SAI_MY_SID_ENTRY_ENDPOINT_BEHAVIOR_E" - - # create vrf - vrf_id = self.create_vrf("VrfDt46") - - # create MySID END.DT46 - fvs = swsscommon.FieldValuePairs([('action', 'end.dt46'), ('vrf', 'VrfDt46')]) - key = self.create_mysid(mysid2, fvs) - - # check ASIC MySID database - mysid = json.loads(key) - assert mysid["sid"] == "baba:2001:20::" - tbl = swsscommon.Table(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_MY_SID_ENTRY") - (status, fvs) = tbl.get(key) - assert status == True - for fv in fvs: - if fv[0] == "SAI_MY_SID_ENTRY_ATTR_VRF": - assert fv[1] == vrf_id - elif fv[0] == "SAI_MY_SID_ENTRY_ATTR_ENDPOINT_BEHAVIOR": - assert fv[1] == "SAI_MY_SID_ENTRY_ENDPOINT_BEHAVIOR_DT46" - - # create MySID uN - fvs = swsscommon.FieldValuePairs([('action', 'un')]) - key = self.create_mysid(mysid3, fvs) - - # check ASIC MySID database - mysid = json.loads(key) - assert mysid["sid"] == "fcbb:bb01:800::" - tbl = swsscommon.Table(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_MY_SID_ENTRY") - (status, fvs) = tbl.get(key) - assert status == True - for fv in fvs: - if fv[0] == "SAI_MY_SID_ENTRY_ATTR_ENDPOINT_BEHAVIOR": - assert fv[1] == "SAI_MY_SID_ENTRY_ENDPOINT_BEHAVIOR_UN" - elif fv[0] == "SAI_MY_SID_ENTRY_ATTR_ENDPOINT_BEHAVIOR_FLAVOR": - assert fv[1] == "SAI_MY_SID_ENTRY_ENDPOINT_BEHAVIOR_FLAVOR_PSP_AND_USD" - - # create MySID END.DT4 with default vrf - fvs = swsscommon.FieldValuePairs([('action', 'end.dt4'), ('vrf', 'default')]) - key = self.create_mysid(mysid4, fvs) - - # check ASIC MySID database - mysid = json.loads(key) - assert mysid["sid"] == "baba:2001:40::" - tbl = swsscommon.Table(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_MY_SID_ENTRY") - (status, fvs) = tbl.get(key) - assert status == True - for fv in fvs: - if fv[0] == "SAI_MY_SID_ENTRY_ATTR_VRF": - assert True - elif fv[0] == "SAI_MY_SID_ENTRY_ATTR_ENDPOINT_BEHAVIOR": - assert fv[1] == "SAI_MY_SID_ENTRY_ENDPOINT_BEHAVIOR_DT4" - - # create interface - self.create_l3_intf("Ethernet104", "") - - # Assign IP to interface - self.add_ip_address("Ethernet104", "2001::2/126") - self.add_ip_address("Ethernet104", "192.0.2.2/30") - - # create neighbor - self.add_neighbor("Ethernet104", "2001::1", "00:00:00:01:02:04", "IPv6") - self.add_neighbor("Ethernet104", "192.0.2.1", "00:00:00:01:02:05", "IPv4") - - # get nexthops - next_hop_entries = get_exist_entries(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP") - assert len(next_hop_entries) == 2 - - tbl = swsscommon.Table(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP") - for next_hop_entry in next_hop_entries: - (status, fvs) = tbl.get(next_hop_entry) - - assert status == True - assert len(fvs) == 3 - - for fv in fvs: - if fv[0] == "SAI_NEXT_HOP_ATTR_IP": - if fv[1] == "2001::1": - next_hop_ipv6_id = next_hop_entry - elif fv[1] == "192.0.2.1": - next_hop_ipv4_id = next_hop_entry - else: - assert False, "Nexthop IP %s not expected" % fv[1] - - assert next_hop_ipv6_id is not None - assert next_hop_ipv4_id is not None - - # create MySID END.X - fvs = swsscommon.FieldValuePairs([('action', 'end.x'), ('adj', '2001::1')]) - key = self.create_mysid(mysid5, fvs) - - # check ASIC MySID database - mysid = json.loads(key) - assert mysid["sid"] == "fc00:0:1:e000::" - tbl = swsscommon.Table(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_MY_SID_ENTRY") - (status, fvs) = tbl.get(key) - assert status == True - for fv in fvs: - if fv[0] == "SAI_MY_SID_ENTRY_ATTR_NEXT_HOP_ID": - assert fv[1] == next_hop_ipv6_id - if fv[0] == "SAI_MY_SID_ENTRY_ATTR_ENDPOINT_BEHAVIOR": - assert fv[1] == "SAI_MY_SID_ENTRY_ENDPOINT_BEHAVIOR_X" - elif fv[0] == "SAI_MY_SID_ENTRY_ATTR_ENDPOINT_BEHAVIOR_FLAVOR": - assert fv[1] == "SAI_MY_SID_ENTRY_ENDPOINT_BEHAVIOR_FLAVOR_PSP_AND_USD" - - # create MySID END.DX4 - fvs = swsscommon.FieldValuePairs([('action', 'end.dx4'), ('adj', '192.0.2.1')]) - key = self.create_mysid(mysid6, fvs) - - # check ASIC MySID database - mysid = json.loads(key) - assert mysid["sid"] == "fc00:0:1:e001::" - tbl = swsscommon.Table(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_MY_SID_ENTRY") - (status, fvs) = tbl.get(key) - assert status == True - for fv in fvs: - if fv[0] == "SAI_MY_SID_ENTRY_ATTR_NEXT_HOP_ID": - assert fv[1] == next_hop_ipv4_id - if fv[0] == "SAI_MY_SID_ENTRY_ATTR_ENDPOINT_BEHAVIOR": - assert fv[1] == "SAI_MY_SID_ENTRY_ENDPOINT_BEHAVIOR_DX4" - elif fv[0] == "SAI_MY_SID_ENTRY_ATTR_ENDPOINT_BEHAVIOR_FLAVOR": - assert fv[1] == "SAI_MY_SID_ENTRY_ENDPOINT_BEHAVIOR_FLAVOR_PSP_AND_USD" - - # create MySID END.DX6 - fvs = swsscommon.FieldValuePairs([('action', 'end.dx6'), ('adj', '2001::1')]) - key = self.create_mysid(mysid7, fvs) - - # check ASIC MySID database - mysid = json.loads(key) - assert mysid["sid"] == "fc00:0:1:e002::" - tbl = swsscommon.Table(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_MY_SID_ENTRY") - (status, fvs) = tbl.get(key) - assert status == True - for fv in fvs: - if fv[0] == "SAI_MY_SID_ENTRY_ATTR_NEXT_HOP_ID": - assert fv[1] == next_hop_ipv6_id - if fv[0] == "SAI_MY_SID_ENTRY_ATTR_ENDPOINT_BEHAVIOR": - assert fv[1] == "SAI_MY_SID_ENTRY_ENDPOINT_BEHAVIOR_DX6" - elif fv[0] == "SAI_MY_SID_ENTRY_ATTR_ENDPOINT_BEHAVIOR_FLAVOR": - assert fv[1] == "SAI_MY_SID_ENTRY_ENDPOINT_BEHAVIOR_FLAVOR_PSP_AND_USD" - - # create MySID uA - fvs = swsscommon.FieldValuePairs([('action', 'ua'), ('adj', '2001::1')]) - key = self.create_mysid(mysid8, fvs) - - # check ASIC MySID database - mysid = json.loads(key) - assert mysid["sid"] == "fc00:0:1:e003::" - tbl = swsscommon.Table(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_MY_SID_ENTRY") - (status, fvs) = tbl.get(key) - assert status == True - for fv in fvs: - if fv[0] == "SAI_MY_SID_ENTRY_ATTR_NEXT_HOP_ID": - assert fv[1] == next_hop_ipv6_id - if fv[0] == "SAI_MY_SID_ENTRY_ATTR_ENDPOINT_BEHAVIOR": - assert fv[1] == "SAI_MY_SID_ENTRY_ENDPOINT_BEHAVIOR_UA" - elif fv[0] == "SAI_MY_SID_ENTRY_ATTR_ENDPOINT_BEHAVIOR_FLAVOR": - assert fv[1] == "SAI_MY_SID_ENTRY_ENDPOINT_BEHAVIOR_FLAVOR_PSP_AND_USD" - - # create MySID uDX4 - fvs = swsscommon.FieldValuePairs([('action', 'udx4'), ('adj', '192.0.2.1')]) - key = self.create_mysid(mysid9, fvs) - - # check ASIC MySID database - mysid = json.loads(key) - assert mysid["sid"] == "fc00:0:1:e004::" - tbl = swsscommon.Table(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_MY_SID_ENTRY") - (status, fvs) = tbl.get(key) - assert status == True - for fv in fvs: - if fv[0] == "SAI_MY_SID_ENTRY_ATTR_NEXT_HOP_ID": - assert fv[1] == next_hop_ipv4_id - if fv[0] == "SAI_MY_SID_ENTRY_ATTR_ENDPOINT_BEHAVIOR": - assert fv[1] == "SAI_MY_SID_ENTRY_ENDPOINT_BEHAVIOR_DX4" - elif fv[0] == "SAI_MY_SID_ENTRY_ATTR_ENDPOINT_BEHAVIOR_FLAVOR": - assert fv[1] == "SAI_MY_SID_ENTRY_ENDPOINT_BEHAVIOR_FLAVOR_PSP_AND_USD" - - # create MySID END.DX6 - fvs = swsscommon.FieldValuePairs([('action', 'udx6'), ('adj', '2001::1')]) - key = self.create_mysid(mysid10, fvs) - - # check ASIC MySID database - mysid = json.loads(key) - assert mysid["sid"] == "fc00:0:1:e005::" - tbl = swsscommon.Table(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_MY_SID_ENTRY") - (status, fvs) = tbl.get(key) - assert status == True - for fv in fvs: - if fv[0] == "SAI_MY_SID_ENTRY_ATTR_NEXT_HOP_ID": - assert fv[1] == next_hop_ipv6_id - if fv[0] == "SAI_MY_SID_ENTRY_ATTR_ENDPOINT_BEHAVIOR": - assert fv[1] == "SAI_MY_SID_ENTRY_ENDPOINT_BEHAVIOR_DX6" - elif fv[0] == "SAI_MY_SID_ENTRY_ATTR_ENDPOINT_BEHAVIOR_FLAVOR": - assert fv[1] == "SAI_MY_SID_ENTRY_ENDPOINT_BEHAVIOR_FLAVOR_PSP_AND_USD" - - # delete MySID - self.remove_mysid(mysid1) - self.remove_mysid(mysid2) - self.remove_mysid(mysid3) - self.remove_mysid(mysid4) - self.remove_mysid(mysid5) - self.remove_mysid(mysid6) - self.remove_mysid(mysid7) - self.remove_mysid(mysid8) - self.remove_mysid(mysid9) - self.remove_mysid(mysid10) - - # remove vrf - self.remove_vrf("VrfDt46") - - # remove nexthop - self.remove_neighbor("Ethernet104", "2001::1") - self.remove_neighbor("Ethernet104", "192.0.2.1") - - # Reemove IP from interface - self.remove_ip_address("Ethernet104", "2001::2/126") - self.remove_ip_address("Ethernet104", "192.0.2.2/30") - - self.remove_l3_intf("Ethernet104") - - def test_mysid_l3adj(self, dvs, testlog): - self.setup_db(dvs) - - # create MySID entries - mysid1='32:16:16:0:fc00:0:1:e000::' - - # create interface - self.create_l3_intf("Ethernet104", "") - - # assign IP to interface - self.add_ip_address("Ethernet104", "2001::2/64") - - time.sleep(3) - - # bring up Ethernet104 - self.set_interface_status(dvs, "Ethernet104", "up") - - time.sleep(3) - - # save the initial number of entries in MySID table - initial_my_sid_entries = get_exist_entries(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_MY_SID_ENTRY") - - # save the initial number of entries in Nexthop table - initial_next_hop_entries = get_exist_entries(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP") - - # create MySID END.X, neighbor does not exist yet - fvs = swsscommon.FieldValuePairs([('action', 'end.x'), ('adj', '2001::1')]) - tbl = swsscommon.ProducerStateTable(self.pdb.db_connection, "SRV6_MY_SID_TABLE") - tbl.set(mysid1, fvs) - - time.sleep(2) - - # check the current number of entries in MySID table - # since the neighbor does not exist yet, we expect the SID has not been installed (i.e., we - # expect the same number of MySID entries as before) - exist_my_sid_entries = get_exist_entries(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_MY_SID_ENTRY") - assert len(exist_my_sid_entries) == len(initial_my_sid_entries) - - # now, let's create the neighbor - self.add_neighbor("Ethernet104", "2001::1", "00:00:00:01:02:04", "IPv6") - - # verify that the nexthop is created in the ASIC (i.e., we have the previous number of next hop entries + 1) - self.adb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP", len(initial_next_hop_entries) + 1) - - # get the new nexthop and nexthop ID, which will be used later to verify the MySID entry - next_hop_entry = get_created_entry(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP", initial_next_hop_entries) - assert next_hop_entry is not None - next_hop_id = self.get_nexthop_id("2001::1") - assert next_hop_id is not None - - # now the neighbor has been created in the ASIC, we expect the MySID entry to be created in the ASIC as well - self.adb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_MY_SID_ENTRY", len(initial_my_sid_entries) + 1) - my_sid_entry = get_created_entry(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_MY_SID_ENTRY", initial_my_sid_entries) - assert my_sid_entry is not None - - # check ASIC MySID database and verify the SID - mysid = json.loads(my_sid_entry) - assert mysid is not None - assert mysid["sid"] == "fc00:0:1:e000::" - tbl = swsscommon.Table(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_MY_SID_ENTRY") - (status, fvs) = tbl.get(my_sid_entry) - assert status == True - for fv in fvs: - if fv[0] == "SAI_MY_SID_ENTRY_ATTR_NEXT_HOP_ID": - assert fv[1] == next_hop_id - if fv[0] == "SAI_MY_SID_ENTRY_ATTR_ENDPOINT_BEHAVIOR": - assert fv[1] == "SAI_MY_SID_ENTRY_ENDPOINT_BEHAVIOR_X" - elif fv[0] == "SAI_MY_SID_ENTRY_ATTR_ENDPOINT_BEHAVIOR_FLAVOR": - assert fv[1] == "SAI_MY_SID_ENTRY_ENDPOINT_BEHAVIOR_FLAVOR_PSP_AND_USD" - - # remove neighbor - self.remove_neighbor("Ethernet104", "2001::1") - - # delete MySID - self.remove_mysid(mysid1) - - # # verify that the nexthop has been removed from the ASIC - self.adb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP", len(initial_next_hop_entries)) - - # check the current number of entries in MySID table - # since the MySID has been removed, we expect the SID has been removed from the ASIC as well - exist_my_sid_entries = get_exist_entries(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_MY_SID_ENTRY") - assert len(exist_my_sid_entries) == len(initial_my_sid_entries) - - # remove IP from interface - self.remove_ip_address("Ethernet104", "2001::2/64") - - # remove interface - self.remove_l3_intf("Ethernet104") - -class TestSrv6(object): - def setup_db(self, dvs): - self.pdb = dvs.get_app_db() - self.adb = dvs.get_asic_db() - self.cdb = dvs.get_config_db() - - def create_sidlist(self, segname, ips, type=None): - table = "ASIC_STATE:SAI_OBJECT_TYPE_SRV6_SIDLIST" - existed_entries = get_exist_entries(self.adb.db_connection, table) - - if type is None: - fvs=swsscommon.FieldValuePairs([('path', ips)]) - else: - fvs=swsscommon.FieldValuePairs([('path', ips), ('type', type)]) - segtbl = swsscommon.ProducerStateTable(self.pdb.db_connection, "SRV6_SID_LIST_TABLE") - segtbl.set(segname, fvs) - - self.adb.wait_for_n_keys(table, len(existed_entries) + 1) - return get_created_entry(self.adb.db_connection, table, existed_entries) - - def remove_sidlist(self, segname): - segtbl = swsscommon.ProducerStateTable(self.pdb.db_connection, "SRV6_SID_LIST_TABLE") - segtbl._del(segname) - - def create_srv6_route(self, routeip,segname,segsrc): - table = "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY" - existed_entries = get_exist_entries(self.adb.db_connection, table) - - fvs=swsscommon.FieldValuePairs([('seg_src',segsrc),('segment',segname)]) - routetbl = swsscommon.ProducerStateTable(self.pdb.db_connection, "ROUTE_TABLE") - routetbl.set(routeip,fvs) - - self.adb.wait_for_n_keys(table, len(existed_entries) + 1) - return get_created_entry(self.adb.db_connection, table, existed_entries) - - def remove_srv6_route(self, routeip): - routetbl = swsscommon.ProducerStateTable(self.pdb.db_connection, "ROUTE_TABLE") - routetbl._del(routeip) - - def check_deleted_route_entries(self, destinations): - def _access_function(): - route_entries = self.adb.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - route_destinations = [json.loads(route_entry)["dest"] for route_entry in route_entries] - return (all(destination not in route_destinations for destination in destinations), None) - - wait_for_result(_access_function) - - def add_neighbor(self, interface, ip, mac): - fvs=swsscommon.FieldValuePairs([("neigh", mac)]) - neightbl = swsscommon.Table(self.cdb.db_connection, "NEIGH") - neightbl.set(interface + "|" +ip, fvs) - time.sleep(1) - - def remove_neighbor(self, interface,ip): - neightbl = swsscommon.Table(self.cdb.db_connection, "NEIGH") - neightbl._del(interface + "|" + ip) - time.sleep(1) - - def test_srv6(self, dvs, testlog): - self.setup_db(dvs) - dvs.setup_db() - - # save exist asic db entries - tunnel_entries = get_exist_entries(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL") - nexthop_entries = get_exist_entries(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP") - route_entries = get_exist_entries(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - - - # bring up interfacee - dvs.set_interface_status("Ethernet104", "up") - dvs.set_interface_status("Ethernet112", "up") - dvs.set_interface_status("Ethernet120", "up") - - # add neighbors - self.add_neighbor("Ethernet104", "baba:2001:10::", "00:00:00:01:02:01") - self.add_neighbor("Ethernet112", "baba:2002:10::", "00:00:00:01:02:02") - self.add_neighbor("Ethernet120", "baba:2003:10::", "00:00:00:01:02:03") - - # create seg lists - sidlist_id = self.create_sidlist('seg1', 'baba:2001:10::,baba:2001:20::') - - # check ASIC SAI_OBJECT_TYPE_SRV6_SIDLIST database - tbl = swsscommon.Table(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_SRV6_SIDLIST") - (status, fvs) = tbl.get(sidlist_id) - assert status == True - for fv in fvs: - if fv[0] == "SAI_SRV6_SIDLIST_ATTR_SEGMENT_LIST": - assert fv[1] == "2:baba:2001:10::,baba:2001:20::" - elif fv[0] == "SAI_SRV6_SIDLIST_ATTR_TYPE": - assert fv[1] == "SAI_SRV6_SIDLIST_TYPE_ENCAPS_RED" - - - # create v4 route with single sidlists - route_key = self.create_srv6_route('20.20.20.20/32','seg1','1001:2000::1') - nexthop_id = get_created_entry(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP", nexthop_entries) - tunnel_id = get_created_entry(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL", tunnel_entries) - - # check ASIC SAI_OBJECT_TYPE_ROUTE_ENTRY database - tbl = swsscommon.Table(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - (status, fvs) = tbl.get(route_key) - assert status == True - for fv in fvs: - if fv[0] == "SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID": - assert fv[1] == nexthop_id - - # check ASIC SAI_OBJECT_TYPE_NEXT_HOP database - tbl = swsscommon.Table(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP") - (status, fvs) = tbl.get(nexthop_id) - assert status == True - for fv in fvs: - if fv[0] == "SAI_NEXT_HOP_ATTR_SRV6_SIDLIST_ID": - assert fv[1] == sidlist_id - elif fv[0] == "SAI_NEXT_HOP_ATTR_TUNNEL_ID": - assert fv[1] == tunnel_id - - # check ASIC SAI_OBJECT_TYPE_TUNNEL database - tbl = swsscommon.Table(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL") - (status, fvs) = tbl.get(tunnel_id) - assert status == True - for fv in fvs: - if fv[0] == "SAI_TUNNEL_ATTR_TYPE": - assert fv[1] == "SAI_TUNNEL_TYPE_SRV6" - elif fv[0] == "SAI_TUNNEL_ATTR_ENCAP_SRC_IP": - assert fv[1] == "1001:2000::1" - - - # create 2nd seg lists - sidlist_id = self.create_sidlist('seg2', 'baba:2002:10::,baba:2002:20::', 'insert.red') - - # check ASIC SAI_OBJECT_TYPE_SRV6_SIDLIST database - tbl = swsscommon.Table(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_SRV6_SIDLIST") - (status, fvs) = tbl.get(sidlist_id) - assert status == True - for fv in fvs: - if fv[0] == "SAI_SRV6_SIDLIST_ATTR_SEGMENT_LIST": - assert fv[1] == "2:baba:2002:10::,baba:2002:20::" - elif fv[0] == "SAI_SRV6_SIDLIST_ATTR_TYPE": - assert fv[1] == "SAI_SRV6_SIDLIST_TYPE_INSERT_RED" - - # create 3rd seg lists with unsupported or wrong naming of sid list type, for this case, it will use default type: ENCAPS_RED - sidlist_id = self.create_sidlist('seg3', 'baba:2003:10::,baba:2003:20::', 'reduced') - - # check ASIC SAI_OBJECT_TYPE_SRV6_SIDLIST database - tbl = swsscommon.Table(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_SRV6_SIDLIST") - (status, fvs) = tbl.get(sidlist_id) - assert status == True - for fv in fvs: - if fv[0] == "SAI_SRV6_SIDLIST_ATTR_SEGMENT_LIST": - assert fv[1] == "2:baba:2003:10::,baba:2003:20::" - elif fv[0] == "SAI_SRV6_SIDLIST_ATTR_TYPE": - assert fv[1] == "SAI_SRV6_SIDLIST_TYPE_ENCAPS_RED" - - # create 2nd v4 route with single sidlists - self.create_srv6_route('20.20.20.21/32','seg2','1001:2000::1') - # create 3rd v4 route with single sidlists - self.create_srv6_route('20.20.20.22/32','seg3','1001:2000::1') - - # remove routes - self.remove_srv6_route('20.20.20.20/32') - self.check_deleted_route_entries('20.20.20.20/32') - self.remove_srv6_route('20.20.20.21/32') - self.check_deleted_route_entries('20.20.20.21/32') - self.remove_srv6_route('20.20.20.22/32') - self.check_deleted_route_entries('20.20.20.22/32') - - # remove sid lists - self.remove_sidlist('seg1') - self.remove_sidlist('seg2') - self.remove_sidlist('seg3') - - # remove neighbors - self.remove_neighbor("Ethernet104", "baba:2001:10::") - self.remove_neighbor("Ethernet112", "baba:2002:10::") - self.remove_neighbor("Ethernet120", "baba:2003:10::") - - # check if asic db entries are all restored - assert tunnel_entries == get_exist_entries(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL") - assert nexthop_entries == get_exist_entries(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP") - assert route_entries == get_exist_entries(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_storm_control.py b/tests/test_storm_control.py deleted file mode 100644 index ec4da04917..0000000000 --- a/tests/test_storm_control.py +++ /dev/null @@ -1,316 +0,0 @@ -from swsscommon import swsscommon -import os -import sys -import time -import json -from distutils.version import StrictVersion -import pytest - -class TestStormControl(object): - def setup_db(self,dvs): - self.pdb = swsscommon.DBConnector(0, dvs.redis_sock, 0) - self.adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - self.cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) - self.sdb = swsscommon.DBConnector(6, dvs.redis_sock, 0) - dvs.runcmd(['sh', '-c', "echo 0 > /var/log/syslog"]) - - def create_port_channel(self, dvs, lag_name): - dvs.runcmd("config portchannel add " + lag_name) - time.sleep(1) - - def delete_port_channel(self, dvs, lag_name): - dvs.runcmd("config portchannel del " + lag_name) - time.sleep(1) - - def add_port_channel_member(self, dvs, lag_name, member): - dvs.runcmd("config portchannel member add "+ lag_name + " "+ member) - time.sleep(1) - - def remove_port_channel_member(self, dvs, lag_name, member): - dvs.runcmd("config portchannel member del "+ lag_name + " "+ member) - time.sleep(1) - - def create_vlan(self, dvs, vlan): - dvs.runcmd("config vlan add " + vlan) - time.sleep(1) - - def delete_vlan(self, dvs, vlan): - dvs.runcmd("config vlan del " + vlan) - time.sleep(1) - - def add_vlan_member(self, dvs, vlan, interface): - dvs.runcmd("config vlan member add " + vlan + " " + interface) - time.sleep(1) - - def remove_vlan_member(self, dvs, vlan, interface): - dvs.runcmd("config vlan member del " + vlan + " " + interface) - time.sleep(1) - - def add_storm_session(self, if_name, storm_type, kbps_value): - tbl = swsscommon.Table(self.cdb, "PORT_STORM_CONTROL") - fvs = swsscommon.FieldValuePairs([("kbps", str(kbps_value))]) - key = if_name + "|" + storm_type - tbl.set(key,fvs) - time.sleep(1) - - def delete_storm_session(self, if_name, storm_type): - tbl = swsscommon.Table(self.cdb, "PORT_STORM_CONTROL") - key = if_name + "|" + storm_type - tbl._del(key) - time.sleep(1) - - def test_bcast_storm(self,dvs,testlog): - self.setup_db(dvs) - - if_name = "Ethernet0" - storm_type = "broadcast" - #User input is Kbps - #Orchagent converts the value to CIR as below and programs the ASIC DB - #kbps_value * 1000 / 8 - kbps_value = 1000000 - self.add_storm_control_on_interface(dvs,if_name,storm_type,kbps_value) - self.del_storm_control(dvs,if_name,storm_type) - - def del_storm_control(self, dvs, if_name, storm_type): - self.setup_db(dvs) - port_oid = dvs.asicdb.portnamemap[if_name] - atbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_PORT") - status, fvs = atbl.get(dvs.asicdb.portnamemap[if_name]) - assert status == True - - storm_type_port_attr = self.get_port_attr_for_storm_type(storm_type) - - policer_oid = 0 - for fv in fvs: - if fv[0] == storm_type_port_attr: - policer_oid = fv[1] - - self.delete_storm_session(if_name, storm_type) - tbl = swsscommon.Table(self.cdb, "PORT_STORM_CONTROL") - (status,fvs) = tbl.get(if_name+"|"+storm_type) - assert status == False - - atbl = swsscommon.Table(self.adb,"ASIC_STATE:SAI_OBJECT_TYPE_PORT") - status, fvs = atbl.get(dvs.asicdb.portnamemap[if_name]) - assert status == True - - for fv in fvs: - if fv[0] == storm_type_port_attr: - assert fv[1] == "oid:0x0" - - if policer_oid != 0: - atbl = swsscommon.Table(self.adb,"ASIC_STATE:SAI_OBJECT_TYPE_POLICER") - status, fvs = atbl.get(policer_oid) - assert status == False - - def test_uucast_storm(self,dvs,testlog): - self.setup_db(dvs) - - if_name = "Ethernet0" - storm_type = "unknown-unicast" - #User input is Kbps - #Orchagent converts the value to CIR as below and programs the ASIC DB - #kbps_value * 1000 / 8 - kbps_value = 1000000 - - self.add_storm_control_on_interface(dvs,if_name,storm_type,kbps_value) - self.del_storm_control(dvs,if_name,storm_type) - - def test_umcast_storm(self,dvs,testlog): - self.setup_db(dvs) - - if_name = "Ethernet0" - storm_type = "unknown-multicast" - #User input is Kbps - #Orchagent converts the value to CIR as below and programs the ASIC DB - #kbps_value * 1000 / 8 - kbps_value = 1000000 - - self.add_storm_control_on_interface(dvs,if_name,storm_type,kbps_value) - self.del_storm_control(dvs,if_name,storm_type) - - def get_port_attr_for_storm_type(self,storm_type): - port_attr = "" - if storm_type == "broadcast": - port_attr = "SAI_PORT_ATTR_BROADCAST_STORM_CONTROL_POLICER_ID" - elif storm_type == "unknown-unicast": - port_attr = "SAI_PORT_ATTR_FLOOD_STORM_CONTROL_POLICER_ID" - elif storm_type == "unknown-multicast": - port_attr = "SAI_PORT_ATTR_MULTICAST_STORM_CONTROL_POLICER_ID" - - return port_attr - - def check_storm_control_on_interface(self,dvs,if_name,storm_type,kbps_value): - print ("interface {} storm_type {} kbps {}".format(if_name,storm_type, kbps_value)) - tbl = swsscommon.Table(self.cdb,"PORT_STORM_CONTROL") - (status,fvs) = tbl.get(if_name+"|"+storm_type) - - assert status == True - assert len(fvs) > 0 - - port_oid = dvs.asicdb.portnamemap[if_name] - - atbl = swsscommon.Table(self.adb,"ASIC_STATE:SAI_OBJECT_TYPE_PORT") - status, fvs = atbl.get(dvs.asicdb.portnamemap[if_name]) - assert status == True - - policer_oid = 0 - - storm_type_port_attr = self.get_port_attr_for_storm_type(storm_type) - - for fv in fvs: - if fv[0] == storm_type_port_attr: - assert fv[1] != "oid:0x0" - policer_oid = fv[1] - - if policer_oid != 0: - atbl = swsscommon.Table(self.adb,"ASIC_STATE:SAI_OBJECT_TYPE_POLICER") - status, fvs = atbl.get(policer_oid) - assert status == True - - bps = 0 - - for fv in fvs: - if fv[0] == "SAI_POLICER_ATTR_CIR": - bps = fv[1] - - #Retrieved value of bps from ASIC_DB is converted back to user input kbps - kbps = int(int(bps) / int(1000) * 8) - print ("Kbps value {}".format(kbps)) - - assert str(kbps) == str(kbps_value) - - - def add_storm_control_on_interface(self,dvs,if_name,storm_type,kbps_value): - print ("interface {} storm_type {} kbps {}".format(if_name,storm_type,kbps_value)) - self.add_storm_session(if_name, storm_type, kbps_value) - self.check_storm_control_on_interface(dvs,if_name,storm_type,kbps_value) - - def test_add_storm_all_interfaces(self,dvs,testlog): - self.setup_db(dvs) - - tbl = swsscommon.Table(self.cdb,"PORT") - for key in tbl.getKeys(): - self.add_storm_control_on_interface(dvs,key,"broadcast",1000000) - self.add_storm_control_on_interface(dvs,key,"unknown-unicast",2000000) - self.add_storm_control_on_interface(dvs,key,"unknown-multicast",3000000) - self.del_storm_control(dvs,key,"broadcast") - self.del_storm_control(dvs,key,"unknown-unicast") - self.del_storm_control(dvs,key,"unknown-multicast") - - def test_warm_restart_all_interfaces(self,dvs,testlog): - self.setup_db(dvs) - - tbl = swsscommon.Table(self.cdb,"PORT") - for key in tbl.getKeys(): - self.add_storm_control_on_interface(dvs,key,"broadcast",1000000) - self.add_storm_control_on_interface(dvs,key,"unknown-unicast",2000000) - self.add_storm_control_on_interface(dvs,key,"unknown-multicast",3000000) - #dvs.runcmd("config save -y") - # enable warm restart - dvs.warm_restart_swss("true") - - # freeze orchagent for warm restart - (exitcode, result) = dvs.runcmd("/usr/bin/orchagent_restart_check", include_stderr=False) - assert result == "RESTARTCHECK succeeded\n" - time.sleep(2) - - dvs.stop_swss() - time.sleep(10) - dvs.start_swss() - time.sleep(10) - - for key in tbl.getKeys(): - self.check_storm_control_on_interface(dvs,key,"broadcast",1000000) - self.check_storm_control_on_interface(dvs,key,"unknown-unicast",2000000) - self.check_storm_control_on_interface(dvs,key,"unknown-multicast",3000000) - self.del_storm_control(dvs,key,"broadcast") - self.del_storm_control(dvs,key,"unknown-unicast") - self.del_storm_control(dvs,key,"unknown-multicast") - # disable warm restart - dvs.warm_restart_swss("false") - - def test_add_storm_lag_interface(self,dvs,testlog): - self.setup_db(dvs) - lag_name = "PortChannel10" - member_interface = "Ethernet0" - kbps_value = 1000000 - storm_list = ["broadcast","unknown-unicast","unknown-multicast"] - kbps_value_list = [1000000,2000000,3000000] - - #Create LAG interface and add member - self.create_port_channel(dvs,lag_name) - self.add_port_channel_member(dvs,lag_name,member_interface) - - #click CLI verification - #for storm_type in storm_list: - # dvs.runcmd("config interface storm-control add "+lag_name+" "+storm_type+" "+str(kbps_value)) - # tbl = swsscommon.Table(self.cdb,"PORT_STORM_CONTROL") - # (status,fvs) = tbl.get(lag_name+"|"+storm_type) - # assert status == False - # assert len(fvs) == 0 - - #Orchagent verification - storm_list_db = ["broadcast","unknown-unicast","unknown-multicast"] - for storm_type,kbps_value in zip(storm_list_db,kbps_value_list): - #Cleanup syslog - dvs.runcmd(['sh', '-c', "echo 0 > /var/log/syslog"]) - time.sleep(1) - print ("storm type: {} kbps value: {}".format(storm_type,kbps_value)) - #Add storm entry to config DB directly - self.add_storm_session(lag_name,storm_type,kbps_value) - tbl = swsscommon.Table(self.cdb,"PORT_STORM_CONTROL") - (status,fvs) = tbl.get(lag_name+"|"+storm_type) - assert status == True - assert len(fvs) > 0 - time.sleep(1) - #grep for error message in syslog - (exitcode,num) = dvs.runcmd(['sh', '-c', 'cat /var/log/syslog | grep -i "handlePortStormControlTable: {}: Unsupported / Invalid interface PortChannel10"'.format(storm_type)]) - time.sleep(1) - assert exitcode == 0 - self.delete_storm_session(lag_name, storm_type) - self.remove_port_channel_member(dvs,lag_name,member_interface) - self.delete_port_channel(dvs,lag_name) - - def test_add_storm_vlan_interface(self,dvs,testlog): - self.setup_db(dvs) - vlan_id = 99 - member_interface = "Ethernet4" - kbps_value = 1000000 - storm_list = ["broadcast","unknown-unicast","unknown-multicast"] - kbps_value_list = [1000000,2000000,3000000] - vlan_name = "Vlan"+str(vlan_id) - - #Create VLAN interface and add member - self.create_vlan(dvs,str(vlan_id)) - self.add_vlan_member(dvs,str(vlan_id),member_interface) - - #click CLI verification - #for storm_type in storm_list: - # dvs.runcmd("config interface storm-control add Vlan"+str(vlan_id)+" "+storm_type+" "+str(kbps_value)) - # tbl = swsscommon.Table(self.cdb,"PORT_STORM_CONTROL") - # (status,fvs) = tbl.get("Vlan"+str(vlan_id)+"|"+storm_type) - # assert status == False - # assert len(fvs) == 0 - - #Orchagent verification - storm_list_db = ["broadcast","unknown-unicast","unknown-multicast"] - for storm_type,kbps_value in zip(storm_list_db,kbps_value_list): - #Cleanup syslog - dvs.runcmd(['sh', '-c', "echo 0 > /var/log/syslog"]) - time.sleep(1) - print ("storm type: {} kbps value: {}".format(storm_type,kbps_value)) - #Add storm entry to config DB directly - self.add_storm_session(vlan_name,storm_type,kbps_value) - tbl = swsscommon.Table(self.cdb,"PORT_STORM_CONTROL") - (status,fvs) = tbl.get(vlan_name+"|"+storm_type) - assert status == True - assert len(fvs) > 0 - time.sleep(1) - #grep for error message in syslog - (exitcode,num) = dvs.runcmd(['sh', '-c', 'cat /var/log/syslog | grep -i "handlePortStormControlTable: {}: Unsupported / Invalid interface {}"'.format(storm_type,vlan_name)]) - time.sleep(1) - assert exitcode == 0 - self.delete_storm_session(vlan_name, storm_type) - self.remove_vlan_member(dvs,str(vlan_id),member_interface) - self.delete_vlan(dvs,str(vlan_id)) diff --git a/tests/test_sub_port_intf.py b/tests/test_sub_port_intf.py deleted file mode 100644 index ec76ec13bb..0000000000 --- a/tests/test_sub_port_intf.py +++ /dev/null @@ -1,1621 +0,0 @@ -import json -import time - -from dvslib.dvs_common import wait_for_result -from swsscommon import swsscommon - -DEFAULT_MTU = "9100" - -CFG_VLAN_SUB_INTF_TABLE_NAME = "VLAN_SUB_INTERFACE" -CFG_PORT_TABLE_NAME = "PORT" -CFG_LAG_TABLE_NAME = "PORTCHANNEL" -CFG_LAG_MEMBER_TABLE_NAME = "PORTCHANNEL_MEMBER" -CFG_VRF_TABLE_NAME = "VRF" -CFG_VXLAN_TUNNEL_TABLE_NAME = "VXLAN_TUNNEL" -CFG_VNET_TABLE_NAME = "VNET" - -STATE_PORT_TABLE_NAME = "PORT_TABLE" -STATE_LAG_TABLE_NAME = "LAG_TABLE" -STATE_INTERFACE_TABLE_NAME = "INTERFACE_TABLE" - -APP_INTF_TABLE_NAME = "INTF_TABLE" -APP_ROUTE_TABLE_NAME = "ROUTE_TABLE" -APP_PORT_TABLE_NAME = "PORT_TABLE" -APP_LAG_TABLE_NAME = "LAG_TABLE" -APP_VNET_TABLE_NAME = "VNET_TABLE" - -ASIC_RIF_TABLE = "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE" -ASIC_ROUTE_ENTRY_TABLE = "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY" -ASIC_NEXT_HOP_TABLE = "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP" -ASIC_NEXT_HOP_GROUP_TABLE = "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP" -ASIC_NEXT_HOP_GROUP_MEMBER_TABLE = "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER" -ASIC_LAG_MEMBER_TABLE = "ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER" -ASIC_HOSTIF_TABLE = "ASIC_STATE:SAI_OBJECT_TYPE_HOSTIF" -ASIC_VIRTUAL_ROUTER_TABLE = "ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER" -ASIC_PORT_TABLE = "ASIC_STATE:SAI_OBJECT_TYPE_PORT" -ASIC_LAG_TABLE = "ASIC_STATE:SAI_OBJECT_TYPE_LAG" -ASIC_TUNNEL_TABLE = "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL" - -ADMIN_STATUS = "admin_status" -VRF_NAME = "vrf_name" -VNET_NAME = "vnet_name" -SRC_IP = "src_ip" -VXLAN_TUNNEL = "vxlan_tunnel" -VNI = "vni" -PEER_LIST = "peer_list" - -ETHERNET_PREFIX = "Ethernet" -SUBINTF_LAG_PREFIX = "Po" -LAG_PREFIX = "PortChannel" -VRF_PREFIX = "Vrf" -VNET_PREFIX = "Vnet" - -VLAN_SUB_INTERFACE_SEPARATOR = "." -APPL_DB_SEPARATOR = ":" - -ETHERNET_PORT_DEFAULT_MTU = "1500" - - -class TestSubPortIntf(object): - SUB_PORT_INTERFACE_UNDER_TEST = "Ethernet64.10" - LAG_SUB_PORT_INTERFACE_UNDER_TEST = "PortChannel1.20" - LAG_MEMBERS_UNDER_TEST = ["Ethernet68", "Ethernet72"] - - IPV4_ADDR_UNDER_TEST = "10.0.0.33/31" - IPV4_TOME_UNDER_TEST = "10.0.0.33/32" - IPV4_SUBNET_UNDER_TEST = "10.0.0.32/31" - - IPV6_ADDR_UNDER_TEST = "fc00::41/126" - IPV6_TOME_UNDER_TEST = "fc00::41/128" - IPV6_SUBNET_UNDER_TEST = "fc00::40/126" - - VRF_UNDER_TEST = "Vrf0" - - TUNNEL_UNDER_TEST = "Tunnel1" - VTEP_IP_UNDER_TEST = "1.1.1.1" - VNET_UNDER_TEST = "Vnet1000" - VNI_UNDER_TEST = "1000" - - def connect_dbs(self, dvs): - self.app_db = dvs.get_app_db() - self.asic_db = dvs.get_asic_db() - self.config_db = dvs.get_config_db() - self.state_db = dvs.get_state_db() - dvs.setup_db() - - self.default_vrf_oid = self.get_default_vrf_oid() - - phy_port = self.SUB_PORT_INTERFACE_UNDER_TEST.split(VLAN_SUB_INTERFACE_SEPARATOR)[0] - - self.port_fvs = {} - self.port_fvs[phy_port] = self.app_db.get_entry(APP_PORT_TABLE_NAME, phy_port) - - self.buf_pg_fvs = {} - for key in self.config_db.get_keys("BUFFER_PG"): - if phy_port in key: - self.buf_pg_fvs[key] = self.config_db.get_entry("BUFFER_PG", key) - - self.buf_q_fvs = {} - for key in self.config_db.get_keys("BUFFER_QUEUE"): - if phy_port in key: - self.buf_q_fvs[key] = self.config_db.get_entry("BUFFER_QUEUE", key) - - def get_subintf_longname(self, port_name): - if port_name is None: - return None - sub_intf_sep_idx = port_name.find(VLAN_SUB_INTERFACE_SEPARATOR) - if sub_intf_sep_idx == -1: - return str(port_name) - parent_intf = port_name[:sub_intf_sep_idx] - sub_intf_idx = port_name[(sub_intf_sep_idx+1):] - if port_name.startswith("Eth"): - if port_name.startswith("Ethernet"): - intf_index=port_name[len("Ethernet"):sub_intf_sep_idx] - else: - intf_index=port_name[len("Eth"):sub_intf_sep_idx] - return "Ethernet"+intf_index+VLAN_SUB_INTERFACE_SEPARATOR+sub_intf_idx - elif port_name.startswith("Po"): - if port_name.startswith("PortChannel"): - intf_index=port_name[len("PortChannel"):sub_intf_sep_idx] - else: - intf_index=port_name[len("Po"):sub_intf_sep_idx] - return "PortChannel"+intf_index+VLAN_SUB_INTERFACE_SEPARATOR+sub_intf_idx - else: - return str(port_name) - - def get_port_longname(self, port_name): - if port_name is None: - return None - - if VLAN_SUB_INTERFACE_SEPARATOR in port_name: - return self.get_subintf_longname(port_name) - else: - if port_name.startswith("Eth"): - if port_name.startswith("Ethernet"): - return port_name - intf_index=port_name[len("Eth"):len(port_name)] - return "Ethernet"+intf_index - elif port_name.startswith("Po"): - if port_name.startswith("PortChannel"): - return port_name - intf_index=port_name[len("Po"):len(port_name)] - return "PortChannel"+intf_index - else: - return port_name - - def get_parent_port(self, port_name): - port = self.get_port_longname(port_name) - idx = port.find(VLAN_SUB_INTERFACE_SEPARATOR) - parent_port = "" - if port.startswith(ETHERNET_PREFIX): - parent_port = port[:idx] - else: - assert port.startswith(SUBINTF_LAG_PREFIX) - parent_port = port[:idx] - return parent_port - - def get_parent_port_index(self, port_name): - port_name = self.get_port_longname(port_name) - if port_name.startswith(ETHERNET_PREFIX): - idx = int(port_name[len(ETHERNET_PREFIX):]) - else: - assert port_name.startswith(LAG_PREFIX) - idx = int(port_name[len(LAG_PREFIX):]) - return idx - - def set_parent_port_oper_status(self, dvs, port_name, status): - if port_name.startswith(ETHERNET_PREFIX): - srv_idx = self.get_parent_port_index(port_name) // 4 - dvs.servers[srv_idx].runcmd("ip link set dev eth0 " + status) - else: - assert port_name.startswith(SUBINTF_LAG_PREFIX) - dvs.runcmd("bash -c 'echo " + ("1" if status == "up" else "0") + - " > /sys/class/net/" + port_name + "/carrier'") - time.sleep(1) - - def set_parent_port_admin_status(self, dvs, port_name, status): - fvs = {ADMIN_STATUS: status} - - if port_name.startswith(ETHERNET_PREFIX): - tbl_name = CFG_PORT_TABLE_NAME - else: - assert port_name.startswith(SUBINTF_LAG_PREFIX) - tbl_name = CFG_LAG_TABLE_NAME - self.config_db.create_entry(tbl_name, port_name, fvs) - time.sleep(1) - - if status == "up": - if port_name.startswith(ETHERNET_PREFIX): - self.set_parent_port_oper_status(dvs, port_name, "down") - self.set_parent_port_oper_status(dvs, port_name, "up") - else: - self.set_parent_port_oper_status(dvs, port_name, "up") - - def create_vxlan_tunnel(self, tunnel_name, vtep_ip): - fvs = { - SRC_IP: vtep_ip, - } - self.config_db.create_entry(CFG_VXLAN_TUNNEL_TABLE_NAME, tunnel_name, fvs) - - def create_vnet(self, vnet_name, tunnel_name, vni, peer_list=""): - fvs = { - VXLAN_TUNNEL: tunnel_name, - VNI: vni, - PEER_LIST: peer_list, - } - self.config_db.create_entry(CFG_VNET_TABLE_NAME, vnet_name, fvs) - - def create_vrf(self, vrf_name): - if vrf_name.startswith(VRF_PREFIX): - self.config_db.create_entry(CFG_VRF_TABLE_NAME, vrf_name, {"NULL": "NULL"}) - else: - assert vrf_name.startswith(VNET_PREFIX) - self.create_vxlan_tunnel(self.TUNNEL_UNDER_TEST, self.VTEP_IP_UNDER_TEST) - self.create_vnet(vrf_name, self.TUNNEL_UNDER_TEST, self.VNI_UNDER_TEST) - - def is_short_name(self, port_name): - idx = port_name.find(VLAN_SUB_INTERFACE_SEPARATOR) - parent_port = port_name[:idx] - is_short = False - if parent_port.startswith("Eth"): - if parent_port.startswith(ETHERNET_PREFIX): - is_short = False - else: - is_short = True - elif parent_port.startswith("Po"): - if parent_port.startswith("PortChannel"): - is_short = False - else: - is_short = True - return is_short - - def create_sub_port_intf_profile(self, sub_port_intf_name, vrf_name=None): - fvs = {ADMIN_STATUS: "up"} - idx = sub_port_intf_name.find(VLAN_SUB_INTERFACE_SEPARATOR) - sub_port_idx = sub_port_intf_name[(idx+1):] - if self.is_short_name(sub_port_intf_name) == True: - fvs["vlan"] = sub_port_idx - if vrf_name: - fvs[VRF_NAME if vrf_name.startswith(VRF_PREFIX) else VNET_NAME] = vrf_name - - self.config_db.create_entry(CFG_VLAN_SUB_INTF_TABLE_NAME, sub_port_intf_name, fvs) - - def create_phy_port_appl_db(self, dvs, port_name): - assert port_name in self.port_fvs - - hostif_cnt = len(self.asic_db.get_keys(ASIC_HOSTIF_TABLE)) - - fvs = swsscommon.FieldValuePairs(list(self.port_fvs[port_name].items())) - tbl = swsscommon.ProducerStateTable(self.app_db.db_connection, APP_PORT_TABLE_NAME) - tbl.set(port_name, fvs) - - self.asic_db.wait_for_n_keys(ASIC_HOSTIF_TABLE, hostif_cnt + 1) - dvs.asicdb._generate_oid_to_interface_mapping() - - for key, fvs in self.buf_pg_fvs.items(): - if port_name in key: - self.config_db.create_entry("BUFFER_PG", key, fvs) - - for key, fvs in self.buf_q_fvs.items(): - if port_name in key: - self.config_db.create_entry("BUFFER_QUEUE", key, fvs) - - def add_lag_members(self, lag, members): - fvs = {"NULL": "NULL"} - - for member in members: - key = "{}|{}".format(lag, member) - self.config_db.create_entry(CFG_LAG_MEMBER_TABLE_NAME, key, fvs) - - def create_sub_port_intf_profile_appl_db(self, sub_port_intf_name, admin_status, vrf_name=None): - substrs = sub_port_intf_name.split(VLAN_SUB_INTERFACE_SEPARATOR) - parent_port = self.get_parent_port(sub_port_intf_name) - vlan_id = substrs[1] - pairs = [ - (ADMIN_STATUS, admin_status), - ("vlan", vlan_id), - ("mtu", "0"), - ] - if vrf_name: - pairs.append((VRF_NAME if vrf_name.startswith(VRF_PREFIX) else VNET_NAME, vrf_name)) - fvs = swsscommon.FieldValuePairs(pairs) - - tbl = swsscommon.ProducerStateTable(self.app_db.db_connection, APP_INTF_TABLE_NAME) - tbl.set(sub_port_intf_name, fvs) - - def add_sub_port_intf_ip_addr(self, sub_port_intf_name, ip_addr): - fvs = {"NULL": "NULL"} - - key = "{}|{}".format(sub_port_intf_name, ip_addr) - self.config_db.create_entry(CFG_VLAN_SUB_INTF_TABLE_NAME, key, fvs) - - def add_sub_port_intf_ip_addr_appl_db(self, sub_port_intf_name, ip_addr): - pairs = [ - ("scope", "global"), - ("family", "IPv4" if "." in ip_addr else "IPv6"), - ] - fvs = swsscommon.FieldValuePairs(pairs) - - tbl = swsscommon.ProducerStateTable(self.app_db.db_connection, APP_INTF_TABLE_NAME) - tbl.set(sub_port_intf_name + APPL_DB_SEPARATOR + ip_addr, fvs) - - def add_route_appl_db(self, ip_prefix, nhop_ips, ifnames, vrf_name=None): - fvs = swsscommon.FieldValuePairs([("nexthop", ",".join(nhop_ips)), ("ifname", ",".join(ifnames))]) - - tbl = swsscommon.ProducerStateTable(self.app_db.db_connection, APP_ROUTE_TABLE_NAME) - tbl.set(vrf_name + APPL_DB_SEPARATOR + ip_prefix if vrf_name else ip_prefix, fvs) - - def set_sub_port_intf_admin_status(self, sub_port_intf_name, status): - fvs = {ADMIN_STATUS: status} - - self.config_db.create_entry(CFG_VLAN_SUB_INTF_TABLE_NAME, sub_port_intf_name, fvs) - - def remove_vxlan_tunnel(self, tunnel_name): - self.config_db.delete_entry(CFG_VXLAN_TUNNEL_TABLE_NAME, tunnel_name) - - def remove_vnet(self, vnet_name): - self.config_db.delete_entry(CFG_VNET_TABLE_NAME, vnet_name) - - def remove_vrf(self, vrf_name): - if vrf_name.startswith(VRF_PREFIX): - self.config_db.delete_entry(CFG_VRF_TABLE_NAME, vrf_name) - else: - assert vrf_name.startswith(VNET_PREFIX) - self.remove_vnet(vrf_name) - - def check_vrf_removal(self, vrf_oid): - self.asic_db.wait_for_deleted_keys(ASIC_VIRTUAL_ROUTER_TABLE, [vrf_oid]) - - def remove_parent_port_appl_db(self, port_name): - if port_name.startswith(ETHERNET_PREFIX): - tbl_name = APP_PORT_TABLE_NAME - - for key in self.buf_pg_fvs: - if port_name in key: - self.config_db.delete_entry("BUFFER_PG", key) - - for key in self.buf_q_fvs: - if port_name in key: - self.config_db.delete_entry("BUFFER_QUEUE", key) - else: - assert port_name.startswith(SUBINTF_LAG_PREFIX) - tbl_name = APP_LAG_TABLE_NAME - tbl = swsscommon.ProducerStateTable(self.app_db.db_connection, tbl_name) - tbl._del(port_name) - - def remove_lag(self, lag): - self.config_db.delete_entry(CFG_LAG_TABLE_NAME, lag) - - def check_lag_removal(self, lag_oid): - self.asic_db.wait_for_deleted_keys(ASIC_LAG_TABLE, [lag_oid]) - - def remove_lag_members(self, lag, members): - for member in members: - key = "{}|{}".format(lag, member) - self.config_db.delete_entry(CFG_LAG_MEMBER_TABLE_NAME, key) - - def remove_sub_port_intf_profile(self, sub_port_intf_name): - self.config_db.delete_entry(CFG_VLAN_SUB_INTF_TABLE_NAME, sub_port_intf_name) - - def check_sub_port_intf_profile_removal(self, rif_oid): - self.asic_db.wait_for_deleted_keys(ASIC_RIF_TABLE, [rif_oid]) - - def remove_sub_port_intf_profile_appl_db(self, sub_port_intf_name): - tbl = swsscommon.ProducerStateTable(self.app_db.db_connection, APP_INTF_TABLE_NAME) - tbl._del(sub_port_intf_name) - - def remove_sub_port_intf_ip_addr(self, sub_port_intf_name, ip_addr): - key = "{}|{}".format(sub_port_intf_name, ip_addr) - self.config_db.delete_entry(CFG_VLAN_SUB_INTF_TABLE_NAME, key) - - def check_sub_port_intf_ip_addr_removal(self, sub_port_intf_name, ip_addrs): - interfaces = ["{}:{}".format(sub_port_intf_name, addr) for addr in ip_addrs] - self.app_db.wait_for_deleted_keys(APP_INTF_TABLE_NAME, interfaces) - - def remove_sub_port_intf_ip_addr_appl_db(self, sub_port_intf_name, ip_addr): - tbl = swsscommon.ProducerStateTable(self.app_db.db_connection, APP_INTF_TABLE_NAME) - tbl._del(sub_port_intf_name + APPL_DB_SEPARATOR + ip_addr) - - def remove_route_appl_db(self, ip_prefix, vrf_name=None): - tbl = swsscommon.ProducerStateTable(self.app_db.db_connection, APP_ROUTE_TABLE_NAME) - tbl._del(vrf_name + APPL_DB_SEPARATOR + ip_prefix if vrf_name else ip_prefix) - - def get_oids(self, table): - return self.asic_db.get_keys(table) - - def get_newly_created_oid(self, table, old_oids): - new_oids = self.asic_db.wait_for_n_keys(table, len(old_oids) + 1) - oid = [ids for ids in new_oids if ids not in old_oids] - return oid[0] - - def get_default_vrf_oid(self): - oids = self.get_oids(ASIC_VIRTUAL_ROUTER_TABLE) - assert len(oids) == 1, "Wrong # of default vrfs: %d, expected #: 1." % (len(oids)) - return oids[0] - - def get_ip_prefix_nhg_oid(self, ip_prefix, vrf_oid=None): - if vrf_oid is None: - vrf_oid = self.default_vrf_oid - - def _access_function(): - route_entry_found = False - - raw_route_entry_keys = self.asic_db.get_keys(ASIC_ROUTE_ENTRY_TABLE) - for raw_route_entry_key in raw_route_entry_keys: - route_entry_key = json.loads(raw_route_entry_key) - if route_entry_key["dest"] == ip_prefix: - route_entry_found = True - assert route_entry_key["vr"] == vrf_oid - break - - return (route_entry_found, raw_route_entry_key) - - (route_entry_found, raw_route_entry_key) = wait_for_result(_access_function) - - fvs = self.asic_db.get_entry(ASIC_ROUTE_ENTRY_TABLE, raw_route_entry_key) - - nhg_oid = fvs.get("SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID", "") - assert nhg_oid != "" - assert nhg_oid != "oid:0x0" - - return nhg_oid - - def check_sub_port_intf_key_existence(self, db, table_name, key): - db.wait_for_matching_keys(table_name, [key]) - - def check_sub_port_intf_fvs(self, db, table_name, key, fv_dict): - db.wait_for_field_match(table_name, key, fv_dict) - - def check_sub_port_intf_route_entries(self, vrf_oid=None, check_ipv6=True): - expected_dests = [self.IPV4_TOME_UNDER_TEST, - self.IPV4_SUBNET_UNDER_TEST, - self.IPV6_TOME_UNDER_TEST, - self.IPV6_SUBNET_UNDER_TEST] - if not check_ipv6: - expected_dests.pop() - expected_dests.pop() - if vrf_oid is None: - vrf_oid = self.default_vrf_oid - expected_vrf_oids = [vrf_oid, - vrf_oid, - vrf_oid, - vrf_oid] - if not check_ipv6: - expected_vrf_oids.pop() - expected_vrf_oids.pop() - - def _access_function(): - raw_route_entries = self.asic_db.get_keys(ASIC_ROUTE_ENTRY_TABLE) - route_dest_vrf_oids = [(json.loads(raw_route_entry)["dest"], json.loads(raw_route_entry)["vr"]) - for raw_route_entry in raw_route_entries] - return (all((dest, vrf_oid) in route_dest_vrf_oids for dest, vrf_oid in zip(expected_dests, expected_vrf_oids)), None) - - wait_for_result(_access_function) - - def check_sub_port_intf_vrf_bind_kernel(self, dvs, port_name, vrf_name): - (ec, out) = dvs.runcmd(['bash', '-c', "ip link show {} | grep {}".format(port_name, vrf_name)]) - assert ec == 0 - assert vrf_name in out - - def check_sub_port_intf_vrf_nobind_kernel(self, dvs, port_name, vrf_name=None): - if vrf_name is not None: - (ec, out) = dvs.runcmd(['bash', '-c', "ip link show {} | grep {}".format(port_name, vrf_name)]) - assert ec == 1 - assert vrf_name not in out - - (ec, out) = dvs.runcmd(['bash', '-c', "ip link show {} | grep master".format(port_name)]) - assert ec == 1 - assert "master" not in out - - def check_sub_port_intf_removal_kernel(self, dvs, port_name): - (ec, out) = dvs.runcmd(['bash', '-c', "ip link show {}".format(port_name)]) - assert ec == 1 - assert port_name in out - assert "does not exist" in out - - def check_sub_port_intf_key_removal(self, db, table_name, key): - db.wait_for_deleted_keys(table_name, [key]) - - def check_sub_port_intf_route_entries_removal(self, removed_route_entries): - def _access_function(): - raw_route_entries = self.asic_db.get_keys(ASIC_ROUTE_ENTRY_TABLE) - status = all(str(json.loads(raw_route_entry)["dest"]) - not in removed_route_entries - for raw_route_entry in raw_route_entries) - return (status, None) - - wait_for_result(_access_function) - - def _test_sub_port_intf_creation(self, dvs, sub_port_intf_name, vrf_name=None): - substrs = sub_port_intf_name.split(VLAN_SUB_INTERFACE_SEPARATOR) - parent_port = self.get_parent_port(sub_port_intf_name) - vlan_id = substrs[1] - if parent_port.startswith(ETHERNET_PREFIX): - state_tbl_name = STATE_PORT_TABLE_NAME - phy_ports = [parent_port] - parent_port_oid = dvs.asicdb.portnamemap[parent_port] - else: - assert parent_port.startswith(SUBINTF_LAG_PREFIX) - state_tbl_name = STATE_LAG_TABLE_NAME - phy_ports = self.LAG_MEMBERS_UNDER_TEST - old_lag_oids = self.get_oids(ASIC_LAG_TABLE) - - vrf_oid = self.default_vrf_oid - old_rif_oids = self.get_oids(ASIC_RIF_TABLE) - - self.set_parent_port_admin_status(dvs, parent_port, "up") - if parent_port.startswith(SUBINTF_LAG_PREFIX): - parent_port_oid = self.get_newly_created_oid(ASIC_LAG_TABLE, old_lag_oids) - # Add lag members to test physical port host interface vlan tag attribute - self.add_lag_members(parent_port, self.LAG_MEMBERS_UNDER_TEST) - self.asic_db.wait_for_n_keys(ASIC_LAG_MEMBER_TABLE, len(self.LAG_MEMBERS_UNDER_TEST)) - if vrf_name: - self.create_vrf(vrf_name) - vrf_oid = self.get_newly_created_oid(ASIC_VIRTUAL_ROUTER_TABLE, [vrf_oid]) - self.create_sub_port_intf_profile(sub_port_intf_name, vrf_name) - - # Verify that sub port interface state ok is pushed to STATE_DB by Intfmgrd - fv_dict = { - "state": "ok", - } - self.check_sub_port_intf_fvs(self.state_db, state_tbl_name, sub_port_intf_name, fv_dict) - - # Verify vrf name sub port interface bound to in STATE_DB INTERFACE_TABLE - fv_dict = { - "vrf": vrf_name if vrf_name else "", - } - self.check_sub_port_intf_fvs(self.state_db, STATE_INTERFACE_TABLE_NAME, sub_port_intf_name, fv_dict) - - # If bound to non-default vrf, verify sub port interface vrf binding in linux kernel, - # and parent port not bound to vrf - if vrf_name: - self.check_sub_port_intf_vrf_bind_kernel(dvs, sub_port_intf_name, vrf_name) - self.check_sub_port_intf_vrf_nobind_kernel(dvs, parent_port, vrf_name) - - # Verify that sub port interface configuration is synced to APPL_DB INTF_TABLE by Intfmgrd - fv_dict = { - ADMIN_STATUS: "up", - } - if vrf_name: - fv_dict[VRF_NAME if vrf_name.startswith(VRF_PREFIX) else VNET_NAME] = vrf_name - self.check_sub_port_intf_fvs(self.app_db, APP_INTF_TABLE_NAME, sub_port_intf_name, fv_dict) - - # Verify that a sub port router interface entry is created in ASIC_DB - fv_dict = { - "SAI_ROUTER_INTERFACE_ATTR_TYPE": "SAI_ROUTER_INTERFACE_TYPE_SUB_PORT", - "SAI_ROUTER_INTERFACE_ATTR_OUTER_VLAN_ID": "{}".format(vlan_id), - "SAI_ROUTER_INTERFACE_ATTR_ADMIN_V4_STATE": "true", - "SAI_ROUTER_INTERFACE_ATTR_ADMIN_V6_STATE": "true", - "SAI_ROUTER_INTERFACE_ATTR_MTU": DEFAULT_MTU, - "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": vrf_oid, - "SAI_ROUTER_INTERFACE_ATTR_PORT_ID": parent_port_oid, - } - rif_oid = self.get_newly_created_oid(ASIC_RIF_TABLE, old_rif_oids) - self.check_sub_port_intf_fvs(self.asic_db, ASIC_RIF_TABLE, rif_oid, fv_dict) - - # Verify physical port host interface vlan tag attribute - fv_dict = { - "SAI_HOSTIF_ATTR_VLAN_TAG": "SAI_HOSTIF_VLAN_TAG_KEEP", - } - for phy_port in phy_ports: - hostif_oid = dvs.asicdb.hostifnamemap[phy_port] - self.check_sub_port_intf_fvs(self.asic_db, ASIC_HOSTIF_TABLE, hostif_oid, fv_dict) - - # Remove a sub port interface - self.remove_sub_port_intf_profile(sub_port_intf_name) - self.check_sub_port_intf_profile_removal(rif_oid) - - # Remove vrf if created - if vrf_name: - self.remove_vrf(vrf_name) - self.check_vrf_removal(vrf_oid) - if vrf_name.startswith(VNET_PREFIX): - self.remove_vxlan_tunnel(self.TUNNEL_UNDER_TEST) - self.app_db.wait_for_n_keys(ASIC_TUNNEL_TABLE, 0) - - if parent_port.startswith(SUBINTF_LAG_PREFIX): - # Remove lag members from lag parent port - self.remove_lag_members(parent_port, self.LAG_MEMBERS_UNDER_TEST) - self.asic_db.wait_for_n_keys(ASIC_LAG_MEMBER_TABLE, 0) - - # Remove lag - self.remove_lag(parent_port) - self.check_lag_removal(parent_port_oid) - - def test_sub_port_intf_creation(self, dvs): - self.connect_dbs(dvs) - - self._test_sub_port_intf_creation(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST) - self._test_sub_port_intf_creation(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST) - - self._test_sub_port_intf_creation(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, self.VRF_UNDER_TEST) - self._test_sub_port_intf_creation(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, self.VRF_UNDER_TEST) - - self._test_sub_port_intf_creation(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, self.VNET_UNDER_TEST) - self._test_sub_port_intf_creation(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, self.VNET_UNDER_TEST) - - def _test_sub_port_intf_add_ip_addrs(self, dvs, sub_port_intf_name, vrf_name=None): - substrs = sub_port_intf_name.split(VLAN_SUB_INTERFACE_SEPARATOR) - parent_port = self.get_parent_port(sub_port_intf_name) - - vrf_oid = self.default_vrf_oid - old_rif_oids = self.get_oids(ASIC_RIF_TABLE) - - self.set_parent_port_admin_status(dvs, parent_port, "up") - if vrf_name: - self.create_vrf(vrf_name) - vrf_oid = self.get_newly_created_oid(ASIC_VIRTUAL_ROUTER_TABLE, [vrf_oid]) - self.create_sub_port_intf_profile(sub_port_intf_name, vrf_name) - - self.add_sub_port_intf_ip_addr(sub_port_intf_name, self.IPV4_ADDR_UNDER_TEST) - if vrf_name is None or not vrf_name.startswith(VNET_PREFIX): - self.add_sub_port_intf_ip_addr(sub_port_intf_name, self.IPV6_ADDR_UNDER_TEST) - - rif_oid = self.get_newly_created_oid(ASIC_RIF_TABLE, old_rif_oids) - - # Verify that ip address state ok is pushed to STATE_DB INTERFACE_TABLE by Intfmgrd - fv_dict = { - "state": "ok", - } - self.check_sub_port_intf_fvs(self.state_db, STATE_INTERFACE_TABLE_NAME, - sub_port_intf_name + "|" + self.IPV4_ADDR_UNDER_TEST, fv_dict) - if vrf_name is None or not vrf_name.startswith(VNET_PREFIX): - self.check_sub_port_intf_fvs(self.state_db, STATE_INTERFACE_TABLE_NAME, - sub_port_intf_name + "|" + self.IPV6_ADDR_UNDER_TEST, fv_dict) - - # Verify that ip address configuration is synced to APPL_DB INTF_TABLE by Intfmgrd - fv_dict = { - "scope": "global", - "family": "IPv4", - } - self.check_sub_port_intf_fvs(self.app_db, APP_INTF_TABLE_NAME, - sub_port_intf_name + ":" + self.IPV4_ADDR_UNDER_TEST, fv_dict) - if vrf_name is None or not vrf_name.startswith(VNET_PREFIX): - fv_dict["family"] = "IPv6" - self.check_sub_port_intf_fvs(self.app_db, APP_INTF_TABLE_NAME, - sub_port_intf_name + ":" + self.IPV6_ADDR_UNDER_TEST, fv_dict) - - # Verify that an IPv4 ip2me route entry is created in ASIC_DB - # Verify that an IPv4 subnet route entry is created in ASIC_DB - # Verify that an IPv6 ip2me route entry is created in ASIC_DB for non-vnet case - # Verify that an IPv6 subnet route entry is created in ASIC_DB for non-vnet case - self.check_sub_port_intf_route_entries(vrf_oid, check_ipv6=True if vrf_name is None or not vrf_name.startswith(VNET_PREFIX) else False) - - # Remove IP addresses - ip_addrs = [ - self.IPV4_ADDR_UNDER_TEST, - ] - self.remove_sub_port_intf_ip_addr(sub_port_intf_name, self.IPV4_ADDR_UNDER_TEST) - if vrf_name is None or not vrf_name.startswith(VNET_PREFIX): - ip_addrs.append(self.IPV6_ADDR_UNDER_TEST) - self.remove_sub_port_intf_ip_addr(sub_port_intf_name, self.IPV6_ADDR_UNDER_TEST) - self.check_sub_port_intf_ip_addr_removal(sub_port_intf_name, ip_addrs) - - # Remove a sub port interface - self.remove_sub_port_intf_profile(sub_port_intf_name) - self.check_sub_port_intf_profile_removal(rif_oid) - - # Remove vrf if created - if vrf_name: - self.remove_vrf(vrf_name) - self.check_vrf_removal(vrf_oid) - if vrf_name.startswith(VNET_PREFIX): - self.remove_vxlan_tunnel(self.TUNNEL_UNDER_TEST) - self.app_db.wait_for_n_keys(ASIC_TUNNEL_TABLE, 0) - - # Remove lag - if parent_port.startswith(SUBINTF_LAG_PREFIX): - self.remove_lag(parent_port) - self.asic_db.wait_for_n_keys(ASIC_LAG_TABLE, 0) - - def test_sub_port_intf_add_ip_addrs(self, dvs): - self.connect_dbs(dvs) - - self._test_sub_port_intf_add_ip_addrs(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST) - self._test_sub_port_intf_add_ip_addrs(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST) - - self._test_sub_port_intf_add_ip_addrs(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, self.VRF_UNDER_TEST) - self._test_sub_port_intf_add_ip_addrs(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, self.VRF_UNDER_TEST) - - self._test_sub_port_intf_add_ip_addrs(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, self.VNET_UNDER_TEST) - self._test_sub_port_intf_add_ip_addrs(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, self.VNET_UNDER_TEST) - - def _test_sub_port_intf_appl_db_proc_seq(self, dvs, sub_port_intf_name, admin_up, vrf_name=None): - substrs = sub_port_intf_name.split(VLAN_SUB_INTERFACE_SEPARATOR) - parent_port = self.get_parent_port(sub_port_intf_name) - vlan_id = substrs[1] - - vrf_oid = self.default_vrf_oid - old_rif_oids = self.get_oids(ASIC_RIF_TABLE) - old_lag_oids = self.get_oids(ASIC_LAG_TABLE) - - self.set_parent_port_admin_status(dvs, parent_port, "up") - if parent_port.startswith(ETHERNET_PREFIX): - parent_port_oid = dvs.asicdb.portnamemap[parent_port] - else: - assert parent_port.startswith(SUBINTF_LAG_PREFIX) - parent_port_oid = self.get_newly_created_oid(ASIC_LAG_TABLE, old_lag_oids) - if vrf_name: - self.create_vrf(vrf_name) - vrf_oid = self.get_newly_created_oid(ASIC_VIRTUAL_ROUTER_TABLE, [vrf_oid]) - - # Create ip address configuration in APPL_DB before creating configuration for sub port interface itself - self.add_sub_port_intf_ip_addr_appl_db(sub_port_intf_name, self.IPV4_ADDR_UNDER_TEST) - if vrf_name is None or not vrf_name.startswith(VNET_PREFIX): - self.add_sub_port_intf_ip_addr_appl_db(sub_port_intf_name, self.IPV6_ADDR_UNDER_TEST) - time.sleep(2) - - # Create sub port interface configuration in APPL_DB - self.create_sub_port_intf_profile_appl_db(sub_port_intf_name, "up" if admin_up == True else "down", vrf_name) - - # Verify that a sub port router interface entry is created in ASIC_DB - fv_dict = { - "SAI_ROUTER_INTERFACE_ATTR_TYPE": "SAI_ROUTER_INTERFACE_TYPE_SUB_PORT", - "SAI_ROUTER_INTERFACE_ATTR_OUTER_VLAN_ID": "{}".format(vlan_id), - "SAI_ROUTER_INTERFACE_ATTR_ADMIN_V4_STATE": "true" if admin_up == True else "false", - "SAI_ROUTER_INTERFACE_ATTR_ADMIN_V6_STATE": "true" if admin_up == True else "false", - "SAI_ROUTER_INTERFACE_ATTR_MTU": DEFAULT_MTU, - "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": vrf_oid, - "SAI_ROUTER_INTERFACE_ATTR_PORT_ID": parent_port_oid, - } - rif_oid = self.get_newly_created_oid(ASIC_RIF_TABLE, old_rif_oids) - self.check_sub_port_intf_fvs(self.asic_db, ASIC_RIF_TABLE, rif_oid, fv_dict) - - # Remove ip addresses from APPL_DB - self.remove_sub_port_intf_ip_addr_appl_db(sub_port_intf_name, self.IPV4_ADDR_UNDER_TEST) - if vrf_name is None or not vrf_name.startswith(VNET_PREFIX): - self.remove_sub_port_intf_ip_addr_appl_db(sub_port_intf_name, self.IPV6_ADDR_UNDER_TEST) - - # Remove sub port interface from APPL_DB - self.remove_sub_port_intf_profile_appl_db(sub_port_intf_name) - self.check_sub_port_intf_profile_removal(rif_oid) - - # Remove vrf if created - if vrf_name: - self.remove_vrf(vrf_name) - self.check_vrf_removal(vrf_oid) - if vrf_name.startswith(VNET_PREFIX): - self.remove_vxlan_tunnel(self.TUNNEL_UNDER_TEST) - self.app_db.wait_for_n_keys(ASIC_TUNNEL_TABLE, 0) - - # Remove lag - if parent_port.startswith(SUBINTF_LAG_PREFIX): - self.remove_lag(parent_port) - self.check_lag_removal(parent_port_oid) - - def test_sub_port_intf_appl_db_proc_seq(self, dvs): - self.connect_dbs(dvs) - - self._test_sub_port_intf_appl_db_proc_seq(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, admin_up=True) - self._test_sub_port_intf_appl_db_proc_seq(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, admin_up=False) - - self._test_sub_port_intf_appl_db_proc_seq(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, admin_up=True) - self._test_sub_port_intf_appl_db_proc_seq(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, admin_up=False) - - self._test_sub_port_intf_appl_db_proc_seq(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, admin_up=True, vrf_name=self.VRF_UNDER_TEST) - self._test_sub_port_intf_appl_db_proc_seq(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, admin_up=False, vrf_name=self.VRF_UNDER_TEST) - - self._test_sub_port_intf_appl_db_proc_seq(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, admin_up=True, vrf_name=self.VRF_UNDER_TEST) - self._test_sub_port_intf_appl_db_proc_seq(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, admin_up=False, vrf_name=self.VRF_UNDER_TEST) - - self._test_sub_port_intf_appl_db_proc_seq(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, admin_up=True, vrf_name=self.VNET_UNDER_TEST) - self._test_sub_port_intf_appl_db_proc_seq(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, admin_up=False, vrf_name=self.VNET_UNDER_TEST) - - self._test_sub_port_intf_appl_db_proc_seq(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, admin_up=True, vrf_name=self.VNET_UNDER_TEST) - self._test_sub_port_intf_appl_db_proc_seq(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, admin_up=False, vrf_name=self.VNET_UNDER_TEST) - - def _test_sub_port_intf_admin_status_change(self, dvs, sub_port_intf_name, vrf_name=None, defer_parent_adminup=False): - substrs = sub_port_intf_name.split(VLAN_SUB_INTERFACE_SEPARATOR) - parent_port = substrs[0] - parent_port = self.get_parent_port(sub_port_intf_name) - - vrf_oid = self.default_vrf_oid - old_rif_oids = self.get_oids(ASIC_RIF_TABLE) - - if defer_parent_adminup: - self.set_parent_port_admin_status(dvs, parent_port, "down") - _, oa_pid = dvs.runcmd("pgrep orchagent") - oa_pid = oa_pid.strip() - # This is to block orchagent daemon in order to simulate the scenario that - # there are a large number of items pending in orchagent's m_toSync queue - dvs.runcmd("kill -s SIGSTOP {}".format(oa_pid)) - - self.set_parent_port_admin_status(dvs, parent_port, "up") - - if vrf_name: - self.create_vrf(vrf_name) - vrf_oid = self.get_newly_created_oid(ASIC_VIRTUAL_ROUTER_TABLE, [vrf_oid]) - self.create_sub_port_intf_profile(sub_port_intf_name, vrf_name) - - self.add_sub_port_intf_ip_addr(sub_port_intf_name, self.IPV4_ADDR_UNDER_TEST) - if vrf_name is None or not vrf_name.startswith(VNET_PREFIX): - self.add_sub_port_intf_ip_addr(sub_port_intf_name, self.IPV6_ADDR_UNDER_TEST) - - if defer_parent_adminup: - dvs.runcmd("kill -s SIGCONT {}".format(oa_pid)) - time.sleep(1) - - fv_dict = { - ADMIN_STATUS: "up", - } - if vrf_name: - fv_dict[VRF_NAME if vrf_name.startswith(VRF_PREFIX) else VNET_NAME] = vrf_name - self.check_sub_port_intf_fvs(self.app_db, APP_INTF_TABLE_NAME, sub_port_intf_name, fv_dict) - - fv_dict = { - "SAI_ROUTER_INTERFACE_ATTR_ADMIN_V4_STATE": "true", - "SAI_ROUTER_INTERFACE_ATTR_ADMIN_V6_STATE": "true", - "SAI_ROUTER_INTERFACE_ATTR_MTU": DEFAULT_MTU, - "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": vrf_oid, - } - rif_oid = self.get_newly_created_oid(ASIC_RIF_TABLE, old_rif_oids) - self.check_sub_port_intf_fvs(self.asic_db, ASIC_RIF_TABLE, rif_oid, fv_dict) - - # Change sub port interface admin status to down - self.set_sub_port_intf_admin_status(sub_port_intf_name, "down") - - # Verify that sub port interface admin status change is synced to APP_DB by Intfmgrd - fv_dict = { - ADMIN_STATUS: "down", - } - if vrf_name: - fv_dict[VRF_NAME if vrf_name.startswith(VRF_PREFIX) else VNET_NAME] = vrf_name - self.check_sub_port_intf_fvs(self.app_db, APP_INTF_TABLE_NAME, sub_port_intf_name, fv_dict) - - # Verify that sub port router interface entry in ASIC_DB has the updated admin status - fv_dict = { - "SAI_ROUTER_INTERFACE_ATTR_ADMIN_V4_STATE": "false", - "SAI_ROUTER_INTERFACE_ATTR_ADMIN_V6_STATE": "false", - "SAI_ROUTER_INTERFACE_ATTR_MTU": DEFAULT_MTU, - "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": vrf_oid, - } - rif_oid = self.get_newly_created_oid(ASIC_RIF_TABLE, old_rif_oids) - self.check_sub_port_intf_fvs(self.asic_db, ASIC_RIF_TABLE, rif_oid, fv_dict) - - # Change sub port interface admin status to up - self.set_sub_port_intf_admin_status(sub_port_intf_name, "up") - - # Verify that sub port interface admin status change is synced to APP_DB by Intfmgrd - fv_dict = { - ADMIN_STATUS: "up", - } - if vrf_name: - fv_dict[VRF_NAME if vrf_name.startswith(VRF_PREFIX) else VNET_NAME] = vrf_name - self.check_sub_port_intf_fvs(self.app_db, APP_INTF_TABLE_NAME, sub_port_intf_name, fv_dict) - - # Verify that sub port router interface entry in ASIC_DB has the updated admin status - fv_dict = { - "SAI_ROUTER_INTERFACE_ATTR_ADMIN_V4_STATE": "true", - "SAI_ROUTER_INTERFACE_ATTR_ADMIN_V6_STATE": "true", - "SAI_ROUTER_INTERFACE_ATTR_MTU": DEFAULT_MTU, - "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": vrf_oid, - } - rif_oid = self.get_newly_created_oid(ASIC_RIF_TABLE, old_rif_oids) - self.check_sub_port_intf_fvs(self.asic_db, ASIC_RIF_TABLE, rif_oid, fv_dict) - - # Remove IP addresses - ip_addrs = [ - self.IPV4_ADDR_UNDER_TEST, - ] - self.remove_sub_port_intf_ip_addr(sub_port_intf_name, self.IPV4_ADDR_UNDER_TEST) - if vrf_name is None or not vrf_name.startswith(VNET_PREFIX): - ip_addrs.append(self.IPV6_ADDR_UNDER_TEST) - self.remove_sub_port_intf_ip_addr(sub_port_intf_name, self.IPV6_ADDR_UNDER_TEST) - self.check_sub_port_intf_ip_addr_removal(sub_port_intf_name, ip_addrs) - - # Remove a sub port interface - self.remove_sub_port_intf_profile(sub_port_intf_name) - self.check_sub_port_intf_profile_removal(rif_oid) - - # Remove vrf if created - if vrf_name: - self.remove_vrf(vrf_name) - self.check_vrf_removal(vrf_oid) - if vrf_name.startswith(VNET_PREFIX): - self.remove_vxlan_tunnel(self.TUNNEL_UNDER_TEST) - self.app_db.wait_for_n_keys(ASIC_TUNNEL_TABLE, 0) - - # Remove lag - if parent_port.startswith(SUBINTF_LAG_PREFIX): - self.remove_lag(parent_port) - self.asic_db.wait_for_n_keys(ASIC_LAG_TABLE, 0) - - def test_sub_port_intf_admin_status_change(self, dvs): - self.connect_dbs(dvs) - - self._test_sub_port_intf_admin_status_change(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST) - self._test_sub_port_intf_admin_status_change(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST) - self._test_sub_port_intf_admin_status_change(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, defer_parent_adminup=True) - - self._test_sub_port_intf_admin_status_change(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, self.VRF_UNDER_TEST) - self._test_sub_port_intf_admin_status_change(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, self.VRF_UNDER_TEST) - - self._test_sub_port_intf_admin_status_change(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, self.VNET_UNDER_TEST) - self._test_sub_port_intf_admin_status_change(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, self.VNET_UNDER_TEST) - - def _test_sub_port_intf_remove_ip_addrs(self, dvs, sub_port_intf_name, vrf_name=None): - substrs = sub_port_intf_name.split(VLAN_SUB_INTERFACE_SEPARATOR) - parent_port = substrs[0] - parent_port = self.get_parent_port(sub_port_intf_name) - - old_rif_oids = self.get_oids(ASIC_RIF_TABLE) - - self.set_parent_port_admin_status(dvs, parent_port, "up") - if vrf_name: - self.create_vrf(vrf_name) - self.asic_db.wait_for_n_keys(ASIC_VIRTUAL_ROUTER_TABLE, 2) - self.create_sub_port_intf_profile(sub_port_intf_name, vrf_name) - - self.add_sub_port_intf_ip_addr(sub_port_intf_name, self.IPV4_ADDR_UNDER_TEST) - if vrf_name is None or not vrf_name.startswith(VNET_PREFIX): - self.add_sub_port_intf_ip_addr(sub_port_intf_name, self.IPV6_ADDR_UNDER_TEST) - - rif_oid = self.get_newly_created_oid(ASIC_RIF_TABLE, old_rif_oids) - - # Remove IPv4 address - self.remove_sub_port_intf_ip_addr(sub_port_intf_name, self.IPV4_ADDR_UNDER_TEST) - - # Verify that IPv4 address state ok is removed from STATE_DB INTERFACE_TABLE by Intfmgrd - self.check_sub_port_intf_key_removal(self.state_db, STATE_INTERFACE_TABLE_NAME, - sub_port_intf_name + "|" + self.IPV4_ADDR_UNDER_TEST) - - # Verify that IPv4 address configuration is removed from APPL_DB INTF_TABLE by Intfmgrd - self.check_sub_port_intf_key_removal(self.app_db, APP_INTF_TABLE_NAME, - sub_port_intf_name + ":" + self.IPV4_ADDR_UNDER_TEST) - - # Verify that IPv4 subnet route entry is removed from ASIC_DB - # Verify that IPv4 ip2me route entry is removed from ASIC_DB - removed_route_entries = set([self.IPV4_TOME_UNDER_TEST, self.IPV4_SUBNET_UNDER_TEST]) - self.check_sub_port_intf_route_entries_removal(removed_route_entries) - - # Remove IPv6 address for non-vnet cases - if vrf_name is None or not vrf_name.startswith(VNET_PREFIX): - self.remove_sub_port_intf_ip_addr(sub_port_intf_name, self.IPV6_ADDR_UNDER_TEST) - - # Verify that IPv6 address state ok is removed from STATE_DB INTERFACE_TABLE by Intfmgrd - self.check_sub_port_intf_key_removal(self.state_db, STATE_INTERFACE_TABLE_NAME, - sub_port_intf_name + "|" + self.IPV6_ADDR_UNDER_TEST) - - # Verify that IPv6 address configuration is removed from APPL_DB INTF_TABLE by Intfmgrd - self.check_sub_port_intf_key_removal(self.app_db, APP_INTF_TABLE_NAME, - sub_port_intf_name + ":" + self.IPV6_ADDR_UNDER_TEST) - - # Verify that IPv6 subnet route entry is removed from ASIC_DB - # Verify that IPv6 ip2me route entry is removed from ASIC_DB - removed_route_entries.update([self.IPV6_TOME_UNDER_TEST, self.IPV6_SUBNET_UNDER_TEST]) - self.check_sub_port_intf_route_entries_removal(removed_route_entries) - - # Verify that sub port router interface entry still exists in ASIC_DB - self.check_sub_port_intf_key_existence(self.asic_db, ASIC_RIF_TABLE, rif_oid) - - # Remove a sub port interface - self.remove_sub_port_intf_profile(sub_port_intf_name) - self.check_sub_port_intf_profile_removal(rif_oid) - - # Remove vrf if created - if vrf_name: - self.remove_vrf(vrf_name) - self.asic_db.wait_for_n_keys(ASIC_VIRTUAL_ROUTER_TABLE, 1) - if vrf_name.startswith(VNET_PREFIX): - self.remove_vxlan_tunnel(self.TUNNEL_UNDER_TEST) - self.app_db.wait_for_n_keys(ASIC_TUNNEL_TABLE, 0) - - # Remove lag - if parent_port.startswith(SUBINTF_LAG_PREFIX): - self.remove_lag(parent_port) - self.asic_db.wait_for_n_keys(ASIC_LAG_TABLE, 0) - - def test_sub_port_intf_remove_ip_addrs(self, dvs): - self.connect_dbs(dvs) - - self._test_sub_port_intf_remove_ip_addrs(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST) - self._test_sub_port_intf_remove_ip_addrs(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST) - - self._test_sub_port_intf_remove_ip_addrs(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, self.VRF_UNDER_TEST) - self._test_sub_port_intf_remove_ip_addrs(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, self.VRF_UNDER_TEST) - - self._test_sub_port_intf_remove_ip_addrs(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, self.VNET_UNDER_TEST) - self._test_sub_port_intf_remove_ip_addrs(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, self.VNET_UNDER_TEST) - - def _test_sub_port_intf_removal(self, dvs, sub_port_intf_name, removal_seq_test=False, vrf_name=None): - substrs = sub_port_intf_name.split(VLAN_SUB_INTERFACE_SEPARATOR) - parent_port = substrs[0] - parent_port = self.get_parent_port(sub_port_intf_name) - vlan_id = substrs[1] - if parent_port.startswith(ETHERNET_PREFIX): - state_tbl_name = STATE_PORT_TABLE_NAME - phy_ports = [parent_port] - parent_port_oid = dvs.asicdb.portnamemap[parent_port] - asic_tbl_name = ASIC_PORT_TABLE - else: - assert parent_port.startswith(SUBINTF_LAG_PREFIX) - state_tbl_name = STATE_LAG_TABLE_NAME - phy_ports = self.LAG_MEMBERS_UNDER_TEST - old_lag_oids = self.get_oids(ASIC_LAG_TABLE) - asic_tbl_name = ASIC_LAG_TABLE - - vrf_oid = self.default_vrf_oid - old_rif_oids = self.get_oids(ASIC_RIF_TABLE) - - self.set_parent_port_admin_status(dvs, parent_port, "up") - if parent_port.startswith(SUBINTF_LAG_PREFIX): - parent_port_oid = self.get_newly_created_oid(ASIC_LAG_TABLE, old_lag_oids) - if removal_seq_test == False: - # Add lag members to test physical port host interface vlan tag attribute - self.add_lag_members(parent_port, self.LAG_MEMBERS_UNDER_TEST) - self.asic_db.wait_for_n_keys(ASIC_LAG_MEMBER_TABLE, len(self.LAG_MEMBERS_UNDER_TEST)) - if vrf_name: - self.create_vrf(vrf_name) - vrf_oid = self.get_newly_created_oid(ASIC_VIRTUAL_ROUTER_TABLE, [vrf_oid]) - self.create_sub_port_intf_profile(sub_port_intf_name, vrf_name) - - self.add_sub_port_intf_ip_addr(sub_port_intf_name, self.IPV4_ADDR_UNDER_TEST) - if vrf_name is None or not vrf_name.startswith(VNET_PREFIX): - self.add_sub_port_intf_ip_addr(sub_port_intf_name, self.IPV6_ADDR_UNDER_TEST) - - fv_dict = { - "state": "ok", - } - self.check_sub_port_intf_fvs(self.state_db, state_tbl_name, sub_port_intf_name, fv_dict) - - fv_dict = { - "vrf": vrf_name if vrf_name else "", - } - self.check_sub_port_intf_fvs(self.state_db, STATE_INTERFACE_TABLE_NAME, sub_port_intf_name, fv_dict) - - if vrf_name: - self.check_sub_port_intf_vrf_bind_kernel(dvs, sub_port_intf_name, vrf_name) - self.check_sub_port_intf_vrf_nobind_kernel(dvs, parent_port, vrf_name) - - fv_dict = { - ADMIN_STATUS: "up", - } - if vrf_name: - fv_dict[VRF_NAME if vrf_name.startswith(VRF_PREFIX) else VNET_NAME] = vrf_name - self.check_sub_port_intf_fvs(self.app_db, APP_INTF_TABLE_NAME, sub_port_intf_name, fv_dict) - - if removal_seq_test == True: - obj_cnt = len(self.asic_db.get_keys(asic_tbl_name)) - # Remove parent port before removing sub port interface - self.remove_parent_port_appl_db(parent_port) - time.sleep(2) - - # Verify parent port persists in ASIC_DB - self.asic_db.wait_for_n_keys(asic_tbl_name, obj_cnt) - - # Remove a sub port interface before removing sub port interface IP addresses - self.remove_sub_port_intf_profile(sub_port_intf_name) - time.sleep(2) - - # Verify that sub port interface state ok persists in STATE_DB - fv_dict = { - "state": "ok", - } - self.check_sub_port_intf_fvs(self.state_db, state_tbl_name, sub_port_intf_name, fv_dict) - # Verify vrf name sub port interface bound to persists in STATE_DB INTERFACE_TABLE - fv_dict = { - "vrf": vrf_name if vrf_name else "", - } - self.check_sub_port_intf_fvs(self.state_db, STATE_INTERFACE_TABLE_NAME, sub_port_intf_name, fv_dict) - # If bound to non-default vrf, verify sub port interface vrf binding in linux kernel, - # and parent port not bound to vrf - if vrf_name: - self.check_sub_port_intf_vrf_bind_kernel(dvs, sub_port_intf_name, vrf_name) - self.check_sub_port_intf_vrf_nobind_kernel(dvs, parent_port, vrf_name) - # Verify that sub port interface configuration persists in APPL_DB INTF_TABLE - fv_dict = { - ADMIN_STATUS: "up", - } - if vrf_name: - fv_dict[VRF_NAME if vrf_name.startswith(VRF_PREFIX) else VNET_NAME] = vrf_name - self.check_sub_port_intf_fvs(self.app_db, APP_INTF_TABLE_NAME, sub_port_intf_name, fv_dict) - - # Verify that a sub port router interface entry persists in ASIC_DB - fv_dict = { - "SAI_ROUTER_INTERFACE_ATTR_TYPE": "SAI_ROUTER_INTERFACE_TYPE_SUB_PORT", - "SAI_ROUTER_INTERFACE_ATTR_OUTER_VLAN_ID": "{}".format(vlan_id), - "SAI_ROUTER_INTERFACE_ATTR_ADMIN_V4_STATE": "true", - "SAI_ROUTER_INTERFACE_ATTR_ADMIN_V6_STATE": "true", - "SAI_ROUTER_INTERFACE_ATTR_MTU": DEFAULT_MTU, - "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": vrf_oid, - "SAI_ROUTER_INTERFACE_ATTR_PORT_ID": parent_port_oid, - } - rif_oid = self.get_newly_created_oid(ASIC_RIF_TABLE, old_rif_oids) - #If subintf mtu deleted, it inherits from parent - if vrf_name == self.VRF_UNDER_TEST or vrf_name == self.VNET_UNDER_TEST: - if parent_port.startswith(ETHERNET_PREFIX): - fv_dict["SAI_ROUTER_INTERFACE_ATTR_MTU"] = ETHERNET_PORT_DEFAULT_MTU - self.check_sub_port_intf_fvs(self.asic_db, ASIC_RIF_TABLE, rif_oid, fv_dict) - else: - rif_oid = self.get_newly_created_oid(ASIC_RIF_TABLE, old_rif_oids) - - # Remove IP addresses - ip_addrs = [ - self.IPV4_ADDR_UNDER_TEST, - ] - self.remove_sub_port_intf_ip_addr(sub_port_intf_name, self.IPV4_ADDR_UNDER_TEST) - if vrf_name is None or not vrf_name.startswith(VNET_PREFIX): - ip_addrs.append(self.IPV6_ADDR_UNDER_TEST) - self.remove_sub_port_intf_ip_addr(sub_port_intf_name, self.IPV6_ADDR_UNDER_TEST) - self.check_sub_port_intf_ip_addr_removal(sub_port_intf_name, ip_addrs) - - if removal_seq_test == False: - # Remove a sub port interface - self.remove_sub_port_intf_profile(sub_port_intf_name) - self.check_sub_port_intf_profile_removal(rif_oid) - - # Verify that sub port interface state ok is removed from STATE_DB by Intfmgrd - self.check_sub_port_intf_key_removal(self.state_db, state_tbl_name, sub_port_intf_name) - - # Verify sub port interface not exist in linux kernel - self.check_sub_port_intf_removal_kernel(dvs, sub_port_intf_name) - # If bound to non-default vrf, verify parent port not bound to vrf - if vrf_name: - self.check_sub_port_intf_vrf_nobind_kernel(dvs, parent_port, vrf_name) - - # Verify vrf name sub port interface bound to is removed from STATE_DB INTERFACE_TABLE - self.check_sub_port_intf_key_removal(self.state_db, STATE_INTERFACE_TABLE_NAME, sub_port_intf_name) - - # Verify that sub port interface configuration is removed from APP_DB by Intfmgrd - self.check_sub_port_intf_key_removal(self.app_db, APP_INTF_TABLE_NAME, sub_port_intf_name) - - # Verify that sub port router interface entry is removed from ASIC_DB - self.check_sub_port_intf_key_removal(self.asic_db, ASIC_RIF_TABLE, rif_oid) - - if removal_seq_test == True: - # Verify that parent port is removed from ASIC_DB - self.asic_db.wait_for_n_keys(asic_tbl_name, obj_cnt - 1) - else: - # Verify physical port host interface vlan tag attribute - fv_dict = { - "SAI_HOSTIF_ATTR_VLAN_TAG": "SAI_HOSTIF_VLAN_TAG_STRIP", - } - for phy_port in phy_ports: - hostif_oid = dvs.asicdb.hostifnamemap[phy_port] - self.check_sub_port_intf_fvs(self.asic_db, ASIC_HOSTIF_TABLE, hostif_oid, fv_dict) - - # Remove vrf if created - if vrf_name: - self.remove_vrf(vrf_name) - self.asic_db.wait_for_n_keys(ASIC_VIRTUAL_ROUTER_TABLE, 1) - if vrf_name.startswith(VNET_PREFIX): - self.remove_vxlan_tunnel(self.TUNNEL_UNDER_TEST) - self.app_db.wait_for_n_keys(ASIC_TUNNEL_TABLE, 0) - - if parent_port.startswith(ETHERNET_PREFIX): - if removal_seq_test == True: - self.create_phy_port_appl_db(dvs, parent_port) - self.asic_db.wait_for_n_keys(asic_tbl_name, obj_cnt) - else: - if removal_seq_test == False: - # Remove lag members from lag parent port - self.remove_lag_members(parent_port, self.LAG_MEMBERS_UNDER_TEST) - self.asic_db.wait_for_n_keys(ASIC_LAG_MEMBER_TABLE, 0) - - # Remove lag - self.remove_lag(parent_port) - self.check_lag_removal(parent_port_oid) - - def test_sub_port_intf_removal(self, dvs): - self.connect_dbs(dvs) - - self._test_sub_port_intf_removal(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST) - self._test_sub_port_intf_removal(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST) - - self._test_sub_port_intf_removal(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, vrf_name=self.VRF_UNDER_TEST) - self._test_sub_port_intf_removal(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, vrf_name=self.VRF_UNDER_TEST) - - self._test_sub_port_intf_removal(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, vrf_name=self.VNET_UNDER_TEST) - self._test_sub_port_intf_removal(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, vrf_name=self.VNET_UNDER_TEST) - - self._test_sub_port_intf_removal(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, removal_seq_test=True) - self._test_sub_port_intf_removal(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, removal_seq_test=True) - - self._test_sub_port_intf_removal(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, removal_seq_test=True, vrf_name=self.VRF_UNDER_TEST) - self._test_sub_port_intf_removal(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, removal_seq_test=True, vrf_name=self.VRF_UNDER_TEST) - - self._test_sub_port_intf_removal(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, removal_seq_test=True, vrf_name=self.VNET_UNDER_TEST) - self._test_sub_port_intf_removal(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, removal_seq_test=True, vrf_name=self.VNET_UNDER_TEST) - - def _test_sub_port_intf_mtu(self, dvs, sub_port_intf_name, vrf_name=None): - substrs = sub_port_intf_name.split(VLAN_SUB_INTERFACE_SEPARATOR) - parent_port = substrs[0] - parent_port = self.get_parent_port(sub_port_intf_name) - - vrf_oid = self.default_vrf_oid - old_rif_oids = self.get_oids(ASIC_RIF_TABLE) - - self.set_parent_port_admin_status(dvs, parent_port, "up") - if vrf_name: - self.create_vrf(vrf_name) - vrf_oid = self.get_newly_created_oid(ASIC_VIRTUAL_ROUTER_TABLE, [vrf_oid]) - self.create_sub_port_intf_profile(sub_port_intf_name, vrf_name) - - rif_oid = self.get_newly_created_oid(ASIC_RIF_TABLE, old_rif_oids) - - # Change parent port mtu - mtu = "8888" - dvs.set_mtu(parent_port, mtu) - - # Verify that sub port router interface entry in ASIC_DB has the updated mtu - fv_dict = { - "SAI_ROUTER_INTERFACE_ATTR_MTU": mtu, - "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": vrf_oid, - } - self.check_sub_port_intf_fvs(self.asic_db, ASIC_RIF_TABLE, rif_oid, fv_dict) - - # Restore parent port mtu - dvs.set_mtu(parent_port, DEFAULT_MTU) - - # Verify that sub port router interface entry in ASIC_DB has the default mtu - fv_dict = { - "SAI_ROUTER_INTERFACE_ATTR_MTU": DEFAULT_MTU, - "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": vrf_oid, - } - self.check_sub_port_intf_fvs(self.asic_db, ASIC_RIF_TABLE, rif_oid, fv_dict) - - # Remove a sub port interface - self.remove_sub_port_intf_profile(sub_port_intf_name) - self.check_sub_port_intf_profile_removal(rif_oid) - - # Remove vrf if created - if vrf_name: - self.remove_vrf(vrf_name) - self.check_vrf_removal(vrf_oid) - if vrf_name.startswith(VNET_PREFIX): - self.remove_vxlan_tunnel(self.TUNNEL_UNDER_TEST) - self.app_db.wait_for_n_keys(ASIC_TUNNEL_TABLE, 0) - - # Remove lag - if parent_port.startswith(SUBINTF_LAG_PREFIX): - self.remove_lag(parent_port) - self.asic_db.wait_for_n_keys(ASIC_LAG_TABLE, 0) - - def test_sub_port_intf_mtu(self, dvs): - self.connect_dbs(dvs) - - self._test_sub_port_intf_mtu(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST) - self._test_sub_port_intf_mtu(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST) - - self._test_sub_port_intf_mtu(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, self.VRF_UNDER_TEST) - self._test_sub_port_intf_mtu(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, self.VRF_UNDER_TEST) - - self._test_sub_port_intf_mtu(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, self.VNET_UNDER_TEST) - self._test_sub_port_intf_mtu(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, self.VNET_UNDER_TEST) - - def create_nhg_router_intfs(self, dvs, parent_port_prefix, parent_port_idx_base, vlan_id, nhop_num, vrf_name=None): - ifnames = [] - parent_port_idx = parent_port_idx_base - for i in range(0, nhop_num): - if vlan_id != 0: - port_name = "{}{}.{}".format(parent_port_prefix, parent_port_idx, vlan_id) - else: - port_name = "{}{}".format(parent_port_prefix, parent_port_idx) - ip_addr = "10.{}.{}.0/31".format(parent_port_idx, vlan_id) - if vlan_id != 0: - self.create_sub_port_intf_profile(port_name, vrf_name) - self.add_sub_port_intf_ip_addr(port_name, ip_addr) - else: - dvs.add_ip_address(port_name, ip_addr, vrf_name) - - ifnames.append(port_name) - - parent_port_idx += (4 if parent_port_prefix == ETHERNET_PREFIX else 1) - return ifnames - - def create_nhg_next_hop_objs(self, dvs, parent_port_prefix, parent_port_idx_base, vlan_id, nhop_num): - nhop_ips = [] - parent_port_idx = parent_port_idx_base - for i in range(0, nhop_num): - if vlan_id != 0: - port_name = "{}{}.{}".format(parent_port_prefix, parent_port_idx, vlan_id) - else: - port_name = "{}{}".format(parent_port_prefix, parent_port_idx) - nhop_ip = "10.{}.{}.1".format(parent_port_idx, vlan_id) - nhop_mac = "00:00:00:{:02d}:{}:01".format(parent_port_idx, vlan_id) - dvs.runcmd("ip neigh add " + nhop_ip + " lladdr " + nhop_mac + " dev " + port_name) - - nhop_ips.append(nhop_ip) - - parent_port_idx += (4 if parent_port_prefix == ETHERNET_PREFIX else 1) - return nhop_ips - - def remove_nhg_router_intfs(self, dvs, parent_port_prefix, parent_port_idx_base, vlan_id, nhop_num): - parent_port_idx = parent_port_idx_base - for i in range(0, nhop_num): - if vlan_id != 0: - port_name = "{}{}.{}".format(parent_port_prefix, parent_port_idx, vlan_id) - else: - port_name = "{}{}".format(parent_port_prefix, parent_port_idx) - ip_addr = "10.{}.{}.0/31".format(parent_port_idx, vlan_id) - if vlan_id != 0: - # Remove IP address on sub port interface - self.remove_sub_port_intf_ip_addr(port_name, ip_addr) - # Remove sub port interface - self.remove_sub_port_intf_profile(port_name) - else: - dvs.remove_ip_address(port_name, ip_addr) - - parent_port_idx += (4 if parent_port_prefix == ETHERNET_PREFIX else 1) - - def remove_nhg_next_hop_objs(self, dvs, parent_port_prefix, parent_port_idx_base, vlan_id, nhop_num): - parent_port_idx = parent_port_idx_base - for i in range(0, nhop_num): - if vlan_id != 0: - port_name = "{}{}.{}".format(parent_port_prefix, parent_port_idx, vlan_id) - else: - port_name = "{}{}".format(parent_port_prefix, parent_port_idx) - nhop_ip = "10.{}.{}.1".format(parent_port_idx, vlan_id) - dvs.runcmd("ip neigh del " + nhop_ip + " dev " + port_name) - - parent_port_idx += (4 if parent_port_prefix == ETHERNET_PREFIX else 1) - - def check_nhg_members_on_parent_port_oper_status_change(self, dvs, parent_port_prefix, parent_port_idx_base, status, - nhg_oid, nhop_num, create_intf_on_parent_port): - parent_port_idx = parent_port_idx_base - for i in range(0, nhop_num): - port_name = "{}{}".format(parent_port_prefix, parent_port_idx) - self.set_parent_port_oper_status(dvs, port_name, status) - - # Verify parent port oper status - fv_dict = { - "oper_status" : status, - } - if parent_port_prefix == ETHERNET_PREFIX: - self.check_sub_port_intf_fvs(self.app_db, APP_PORT_TABLE_NAME, port_name, fv_dict) - else: - self.check_sub_port_intf_fvs(self.app_db, APP_LAG_TABLE_NAME, port_name, fv_dict) - - # Verify next hop group member # in ASIC_DB - if status == "up": - nhg_member_oids = self.asic_db.wait_for_n_keys(ASIC_NEXT_HOP_GROUP_MEMBER_TABLE, - 1 + i if create_intf_on_parent_port == False else (1 + i) * 2) - else: - assert status == "down" - nhg_member_oids = self.asic_db.wait_for_n_keys(ASIC_NEXT_HOP_GROUP_MEMBER_TABLE, - (nhop_num - 1) - i if create_intf_on_parent_port == False else - ((nhop_num - 1) - i) * 2) - - # Verify that next hop group members in ASIC_DB all - # belong to the next hop group of the specified oid - fv_dict = { - "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID": nhg_oid, - } - for nhg_member_oid in nhg_member_oids: - self.check_sub_port_intf_fvs(self.asic_db, ASIC_NEXT_HOP_GROUP_MEMBER_TABLE, nhg_member_oid, fv_dict) - - parent_port_idx += (4 if parent_port_prefix == ETHERNET_PREFIX else 1) - - def _test_sub_port_intf_nhg_accel(self, dvs, sub_port_intf_name, nhop_num=3, create_intf_on_parent_port=False, vrf_name=None): - substrs = sub_port_intf_name.split(VLAN_SUB_INTERFACE_SEPARATOR) - parent_port = substrs[0] - parent_port = self.get_parent_port(sub_port_intf_name) - vlan_id = substrs[1] - assert len(vlan_id) == 2 - - if parent_port.startswith(ETHERNET_PREFIX): - parent_port_prefix = ETHERNET_PREFIX - else: - assert parent_port.startswith(SUBINTF_LAG_PREFIX) - parent_port_prefix = LAG_PREFIX - parent_port_idx_base = self.get_parent_port_index(parent_port) - - vrf_oid = self.default_vrf_oid - - # Set parent ports admin status up - parent_port_idx = parent_port_idx_base - for i in range(0, nhop_num): - port_name = "{}{}".format(parent_port_prefix, parent_port_idx) - self.set_parent_port_admin_status(dvs, port_name, "up") - - parent_port_idx += (4 if parent_port_prefix == ETHERNET_PREFIX else 1) - - if vrf_name: - self.create_vrf(vrf_name) - vrf_oid = self.get_newly_created_oid(ASIC_VIRTUAL_ROUTER_TABLE, [vrf_oid]) - - ifnames = [] - rif_cnt = len(self.asic_db.get_keys(ASIC_RIF_TABLE)) - # Create sub port interfaces - ifnames.extend(self.create_nhg_router_intfs(dvs, parent_port_prefix, parent_port_idx_base, int(vlan_id), nhop_num, vrf_name)) - - # Create router interfaces on parent ports - if create_intf_on_parent_port == True: - ifnames.extend(self.create_nhg_router_intfs(dvs, parent_port_prefix, parent_port_idx_base, 0, nhop_num, vrf_name)) - - self.asic_db.wait_for_n_keys(ASIC_RIF_TABLE, rif_cnt + nhop_num if create_intf_on_parent_port == False else rif_cnt + nhop_num * 2) - - nhop_ips = [] - nhop_cnt = len(self.asic_db.get_keys(ASIC_NEXT_HOP_TABLE)) - # Create next hop objects on sub port interfaces - nhop_ips.extend(self.create_nhg_next_hop_objs(dvs, parent_port_prefix, parent_port_idx_base, int(vlan_id), nhop_num)) - - # Create next hop objects on router interfaces - if create_intf_on_parent_port == True: - nhop_ips.extend(self.create_nhg_next_hop_objs(dvs, parent_port_prefix, parent_port_idx_base, 0, nhop_num)) - - self.asic_db.wait_for_n_keys(ASIC_NEXT_HOP_TABLE, nhop_cnt + nhop_num if create_intf_on_parent_port == False else nhop_cnt + nhop_num * 2) - - # Create multi-next-hop route entry - ip_prefix = "2.2.2.0/24" - self.add_route_appl_db(ip_prefix, nhop_ips, ifnames, vrf_name) - - # Verify route entry created in ASIC_DB and get next hop group oid - nhg_oid = self.get_ip_prefix_nhg_oid(ip_prefix, vrf_oid) - - # Verify next hop group of the specified oid created in ASIC_DB - self.check_sub_port_intf_key_existence(self.asic_db, ASIC_NEXT_HOP_GROUP_TABLE, nhg_oid) - - # Verify next hop group members created in ASIC_DB - nhg_member_oids = self.asic_db.wait_for_n_keys(ASIC_NEXT_HOP_GROUP_MEMBER_TABLE, - nhop_num if create_intf_on_parent_port == False else nhop_num * 2) - - # Verify that next hop group members all belong to the next hop group of the specified oid - fv_dict = { - "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID": nhg_oid, - } - for nhg_member_oid in nhg_member_oids: - self.check_sub_port_intf_fvs(self.asic_db, ASIC_NEXT_HOP_GROUP_MEMBER_TABLE, nhg_member_oid, fv_dict) - - # Bring parent ports oper status down one at a time, and verify next hop group members - self.check_nhg_members_on_parent_port_oper_status_change(dvs, parent_port_prefix, parent_port_idx_base, "down", - nhg_oid, nhop_num, create_intf_on_parent_port) - - # Bring parent ports oper status up one at a time, and verify next hop group members - self.check_nhg_members_on_parent_port_oper_status_change(dvs, parent_port_prefix, parent_port_idx_base, "up", - nhg_oid, nhop_num, create_intf_on_parent_port) - - # Clean up - rif_cnt = len(self.asic_db.get_keys(ASIC_RIF_TABLE)) - - # Remove ecmp route entry - self.remove_route_appl_db(ip_prefix, vrf_name) - - # Remove sub port interfaces - self.remove_nhg_router_intfs(dvs, parent_port_prefix, parent_port_idx_base, int(vlan_id), nhop_num) - - # Remove router interfaces on parent ports - if create_intf_on_parent_port == True: - self.remove_nhg_router_intfs(dvs, parent_port_prefix, parent_port_idx_base, 0, nhop_num) - - # Removal of router interfaces indicates the proper removal of nhg, nhg members, next hop objects, and neighbor entries - self.asic_db.wait_for_n_keys(ASIC_RIF_TABLE, rif_cnt - nhop_num if create_intf_on_parent_port == False else rif_cnt - nhop_num * 2) - - # Remove vrf if created - if vrf_name: - self.remove_vrf(vrf_name) - self.check_vrf_removal(vrf_oid) - - parent_port_idx = parent_port_idx_base - for i in range(0, nhop_num): - port_name = "{}{}".format(parent_port_prefix, parent_port_idx) - if parent_port.startswith(ETHERNET_PREFIX): - # Make sure physical port is oper status up - self.set_parent_port_oper_status(dvs, port_name, "up") - else: - # Remove lag - self.remove_lag(port_name) - self.asic_db.wait_for_n_keys(ASIC_LAG_TABLE, nhop_num - 1 - i) - - parent_port_idx += (4 if parent_port_prefix == ETHERNET_PREFIX else 1) - - def test_sub_port_intf_nhg_accel(self, dvs): - self.connect_dbs(dvs) - - self._test_sub_port_intf_nhg_accel(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST) - self._test_sub_port_intf_nhg_accel(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, create_intf_on_parent_port=True) - self._test_sub_port_intf_nhg_accel(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST) - self._test_sub_port_intf_nhg_accel(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, create_intf_on_parent_port=True) - - self._test_sub_port_intf_nhg_accel(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, vrf_name=self.VRF_UNDER_TEST) - self._test_sub_port_intf_nhg_accel(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, - create_intf_on_parent_port=True, vrf_name=self.VRF_UNDER_TEST) - self._test_sub_port_intf_nhg_accel(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, vrf_name=self.VRF_UNDER_TEST) - self._test_sub_port_intf_nhg_accel(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, - create_intf_on_parent_port=True, vrf_name=self.VRF_UNDER_TEST) - - def _test_sub_port_intf_oper_down_with_pending_neigh_route_tasks(self, dvs, sub_port_intf_name, nhop_num=3, - create_intf_on_parent_port=False, vrf_name=None): - substrs = sub_port_intf_name.split(VLAN_SUB_INTERFACE_SEPARATOR) - parent_port = substrs[0] - parent_port = self.get_parent_port(sub_port_intf_name) - vlan_id = substrs[1] - assert len(vlan_id) == 2 - - if parent_port.startswith(ETHERNET_PREFIX): - parent_port_prefix = ETHERNET_PREFIX - else: - assert parent_port.startswith(SUBINTF_LAG_PREFIX) - parent_port_prefix = LAG_PREFIX - parent_port_idx_base = self.get_parent_port_index(parent_port) - - vrf_oid = self.default_vrf_oid - - # Set parent ports admin status up - parent_port_idx = parent_port_idx_base - for i in range(0, nhop_num): - port_name = "{}{}".format(parent_port_prefix, parent_port_idx) - self.set_parent_port_admin_status(dvs, port_name, "up") - - parent_port_idx += (4 if parent_port_prefix == ETHERNET_PREFIX else 1) - - if vrf_name: - self.create_vrf(vrf_name) - vrf_oid = self.get_newly_created_oid(ASIC_VIRTUAL_ROUTER_TABLE, [vrf_oid]) - - ifnames = [] - rif_cnt = len(self.asic_db.get_keys(ASIC_RIF_TABLE)) - # Create sub port interfaces - ifnames.extend(self.create_nhg_router_intfs(dvs, parent_port_prefix, parent_port_idx_base, int(vlan_id), nhop_num, vrf_name)) - # Create router interfaces on parent ports - if create_intf_on_parent_port == True: - ifnames.extend(self.create_nhg_router_intfs(dvs, parent_port_prefix, parent_port_idx_base, 0, nhop_num, vrf_name)) - self.asic_db.wait_for_n_keys(ASIC_RIF_TABLE, rif_cnt + nhop_num if create_intf_on_parent_port == False else rif_cnt + nhop_num * 2) - - # Bring parent port oper status down one at a time - # Verify next hop group members created after processing pending tasks - parent_port_idx = parent_port_idx_base - for i in range(0, nhop_num): - port_name = "{}{}".format(parent_port_prefix, parent_port_idx) - self.set_parent_port_oper_status(dvs, port_name, "down") - - # Verify parent port oper status down - fv_dict = { - "oper_status" : "down", - } - if parent_port_prefix == ETHERNET_PREFIX: - self.check_sub_port_intf_fvs(self.app_db, APP_PORT_TABLE_NAME, port_name, fv_dict) - else: - self.check_sub_port_intf_fvs(self.app_db, APP_LAG_TABLE_NAME, port_name, fv_dict) - - # Mimic pending neighbor task - nhop_ips = [] - nhop_cnt = len(self.asic_db.get_keys(ASIC_NEXT_HOP_TABLE)) - # Create next hop objects on sub port interfaces - nhop_ips.extend(self.create_nhg_next_hop_objs(dvs, parent_port_prefix, parent_port_idx_base, int(vlan_id), nhop_num)) - # Create next hop objects on router interfaces - if create_intf_on_parent_port == True: - nhop_ips.extend(self.create_nhg_next_hop_objs(dvs, parent_port_prefix, parent_port_idx_base, 0, nhop_num)) - self.asic_db.wait_for_n_keys(ASIC_NEXT_HOP_TABLE, nhop_cnt + nhop_num if create_intf_on_parent_port == False else nhop_cnt + nhop_num * 2) - - # Mimic pending multi-next-hop route entry task - ip_prefix = "2.2.2.0/24" - self.add_route_appl_db(ip_prefix, nhop_ips, ifnames, vrf_name) - - # Verify route entry created in ASIC_DB and get next hop group oid - nhg_oid = self.get_ip_prefix_nhg_oid(ip_prefix, vrf_oid) - - # Verify next hop group of the specified oid created in ASIC_DB - self.check_sub_port_intf_key_existence(self.asic_db, ASIC_NEXT_HOP_GROUP_TABLE, nhg_oid) - - # Verify next hop group member # created in ASIC_DB - nhg_member_oids = self.asic_db.wait_for_n_keys(ASIC_NEXT_HOP_GROUP_MEMBER_TABLE, - (nhop_num - 1) - i if create_intf_on_parent_port == False else ((nhop_num - 1) - i) * 2) - - # Verify that next hop group members all belong to the next hop group of the specified oid - fv_dict = { - "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID": nhg_oid, - } - for nhg_member_oid in nhg_member_oids: - self.check_sub_port_intf_fvs(self.asic_db, ASIC_NEXT_HOP_GROUP_MEMBER_TABLE, nhg_member_oid, fv_dict) - - nhop_cnt = len(self.asic_db.get_keys(ASIC_NEXT_HOP_TABLE)) - # Remove next hop objects on sub port interfaces - self.remove_nhg_next_hop_objs(dvs, parent_port_prefix, parent_port_idx_base, int(vlan_id), nhop_num) - # Remove next hop objects on router interfaces - if create_intf_on_parent_port == True: - self.remove_nhg_next_hop_objs(dvs, parent_port_prefix, parent_port_idx_base, 0, nhop_num) - # Remove ecmp route entry - self.remove_route_appl_db(ip_prefix, vrf_name) - # Removal of next hop objects indicates the proper removal of route entry, nhg, and nhg members - self.asic_db.wait_for_n_keys(ASIC_NEXT_HOP_TABLE, nhop_cnt - nhop_num if create_intf_on_parent_port == False else nhop_cnt - nhop_num * 2) - - parent_port_idx += (4 if parent_port_prefix == ETHERNET_PREFIX else 1) - - # Clean up - rif_cnt = len(self.asic_db.get_keys(ASIC_RIF_TABLE)) - # Remove sub port interfaces - self.remove_nhg_router_intfs(dvs, parent_port_prefix, parent_port_idx_base, int(vlan_id), nhop_num) - # Remove router interfaces on parent ports - if create_intf_on_parent_port == True: - self.remove_nhg_router_intfs(dvs, parent_port_prefix, parent_port_idx_base, 0, nhop_num) - self.asic_db.wait_for_n_keys(ASIC_RIF_TABLE, rif_cnt - nhop_num if create_intf_on_parent_port == False else rif_cnt - nhop_num * 2) - - # Remove vrf if created - if vrf_name: - self.remove_vrf(vrf_name) - self.check_vrf_removal(vrf_oid) - - parent_port_idx = parent_port_idx_base - for i in range(0, nhop_num): - port_name = "{}{}".format(parent_port_prefix, parent_port_idx) - if parent_port.startswith(ETHERNET_PREFIX): - # Make sure physical port oper status is up - self.set_parent_port_oper_status(dvs, port_name, "up") - else: - # Remove lag - self.remove_lag(port_name) - self.asic_db.wait_for_n_keys(ASIC_LAG_TABLE, nhop_num - 1 - i) - - parent_port_idx += (4 if parent_port_prefix == ETHERNET_PREFIX else 1) - - def test_sub_port_intf_oper_down_with_pending_neigh_route_tasks(self, dvs): - self.connect_dbs(dvs) - - self._test_sub_port_intf_oper_down_with_pending_neigh_route_tasks(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST) - self._test_sub_port_intf_oper_down_with_pending_neigh_route_tasks(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, create_intf_on_parent_port=True) - self._test_sub_port_intf_oper_down_with_pending_neigh_route_tasks(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST) - self._test_sub_port_intf_oper_down_with_pending_neigh_route_tasks(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, create_intf_on_parent_port=True) - - self._test_sub_port_intf_oper_down_with_pending_neigh_route_tasks(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, vrf_name=self.VRF_UNDER_TEST) - self._test_sub_port_intf_oper_down_with_pending_neigh_route_tasks(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, - create_intf_on_parent_port=True, vrf_name=self.VRF_UNDER_TEST) - self._test_sub_port_intf_oper_down_with_pending_neigh_route_tasks(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, vrf_name=self.VRF_UNDER_TEST) - self._test_sub_port_intf_oper_down_with_pending_neigh_route_tasks(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, - create_intf_on_parent_port=True, vrf_name=self.VRF_UNDER_TEST) - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_switch.py b/tests/test_switch.py deleted file mode 100644 index 652fa46573..0000000000 --- a/tests/test_switch.py +++ /dev/null @@ -1,105 +0,0 @@ -import time -import pytest - -from swsscommon import swsscommon - - -def create_entry(tbl, key, pairs): - fvs = swsscommon.FieldValuePairs(pairs) - tbl.set(key, fvs) - time.sleep(1) - - -def get_exist_entry(dvs, table): - db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - tbl = swsscommon.Table(db, table) - entries = list(tbl.getKeys()) - return entries[0] - - -def create_entry_pst(db, table, separator, key, pairs): - tbl = swsscommon.ProducerStateTable(db, table) - create_entry(tbl, key, pairs) - - -def check_object(db, table, key, expected_attributes): - tbl = swsscommon.Table(db, table) - keys = tbl.getKeys() - assert key in keys, "The desired key is not presented" - - status, fvs = tbl.get(key) - assert status, "Got an error when get a key" - - assert len(fvs) >= len(expected_attributes), "Incorrect attributes" - - attr_keys = {entry[0] for entry in fvs} - - for name, value in fvs: - if name in expected_attributes: - assert expected_attributes[name] == value, "Wrong value %s for the attribute %s = %s" % \ - (value, name, expected_attributes[name]) - - -def vxlan_switch_test(dvs, oid, port, mac, mask, sport): - app_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - create_entry_pst( - app_db, - "SWITCH_TABLE", ':', "switch", - [ - ("vxlan_port", port), - ("vxlan_router_mac", mac), - ("vxlan_mask", mask), - ("vxlan_sport", sport), - ], - ) - time.sleep(2) - - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - check_object(asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_SWITCH", oid, - { - 'SAI_SWITCH_ATTR_VXLAN_DEFAULT_PORT': port, - 'SAI_SWITCH_ATTR_VXLAN_DEFAULT_ROUTER_MAC': mac, - 'SAI_SWITCH_TUNNEL_ATTR_VXLAN_UDP_SPORT_MASK': mask, - 'SAI_SWITCH_TUNNEL_ATTR_VXLAN_UDP_SPORT': sport, - } - ) - - -def ecmp_lag_hash_offset_test(dvs, oid, lag_offset, ecmp_offset): - app_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - create_entry_pst( - app_db, - "SWITCH_TABLE", ':', "switch", - [ - ("ecmp_hash_offset", ecmp_offset), - ("lag_hash_offset", lag_offset) - ], - ) - time.sleep(2) - - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - check_object(asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_SWITCH", oid, - { - 'SAI_SWITCH_ATTR_ECMP_DEFAULT_HASH_OFFSET': ecmp_offset, - 'SAI_SWITCH_ATTR_LAG_DEFAULT_HASH_OFFSET': lag_offset, - } - ) - - -class TestSwitch(object): - ''' - Test- Check switch attributes - ''' - def test_switch_attribute(self, dvs, testlog): - switch_oid = get_exist_entry(dvs, "ASIC_STATE:SAI_OBJECT_TYPE_SWITCH") - vxlan_switch_test(dvs, switch_oid, "12345", "00:01:02:03:04:05", "20", "54321") - - vxlan_switch_test(dvs, switch_oid, "56789", "00:0A:0B:0C:0D:0E", "15", "56789") - - ecmp_lag_hash_offset_test(dvs, switch_oid, "10", "10") - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_tunnel.py b/tests/test_tunnel.py deleted file mode 100644 index 4b96eb5060..0000000000 --- a/tests/test_tunnel.py +++ /dev/null @@ -1,365 +0,0 @@ -import time -import pytest - -from swsscommon import swsscommon - - -def create_fvs(**kwargs): - return swsscommon.FieldValuePairs(list(kwargs.items())) - -class TestTunnelBase(object): - APP_TUNNEL_DECAP_TABLE_NAME = "TUNNEL_DECAP_TABLE" - ASIC_TUNNEL_TABLE = "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL" - ASIC_TUNNEL_TERM_ENTRIES = "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL_TERM_TABLE_ENTRY" - ASIC_RIF_TABLE = "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE" - ASIC_VRF_TABLE = "ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER" - ASIC_QOS_MAP_TABLE_KEY = "ASIC_STATE:SAI_OBJECT_TYPE_QOS_MAP" - TUNNEL_QOS_MAP_NAME = "AZURE_TUNNEL" - CONFIG_TUNNEL_TABLE_NAME = "TUNNEL" - - ecn_modes_map = { - "standard" : "SAI_TUNNEL_DECAP_ECN_MODE_STANDARD", - "copy_from_outer": "SAI_TUNNEL_DECAP_ECN_MODE_COPY_FROM_OUTER" - } - - dscp_modes_map = { - "pipe" : "SAI_TUNNEL_DSCP_MODE_PIPE_MODEL", - "uniform" : "SAI_TUNNEL_DSCP_MODE_UNIFORM_MODEL" - } - - ttl_modes_map = { - "pipe" : "SAI_TUNNEL_TTL_MODE_PIPE_MODEL", - "uniform" : "SAI_TUNNEL_TTL_MODE_UNIFORM_MODEL" - } - - # Define 2 dummy maps - DSCP_TO_TC_MAP = {str(i):str(1) for i in range(0, 64)} - TC_TO_PRIORITY_GROUP_MAP = {str(i):str(i) for i in range(0, 8)} - - def check_interface_exists_in_asicdb(self, asicdb, sai_oid): - if_table = swsscommon.Table(asicdb, self.ASIC_RIF_TABLE) - status, fvs = if_table.get(sai_oid) - return status - - def check_vr_exists_in_asicdb(self, asicdb, sai_oid): - vfr_table = swsscommon.Table(asicdb, self.ASIC_VRF_TABLE) - status, fvs = vfr_table.get(sai_oid) - return status - - def check_tunnel_termination_entry_exists_in_asicdb(self, asicdb, tunnel_sai_oid, dst_ips, src_ip=None): - tunnel_term_table = swsscommon.Table(asicdb, self.ASIC_TUNNEL_TERM_ENTRIES) - - tunnel_term_entries = tunnel_term_table.getKeys() - assert len(tunnel_term_entries) == len(dst_ips) - - expected_term_type = "SAI_TUNNEL_TERM_TABLE_ENTRY_TYPE_P2P" if src_ip else "SAI_TUNNEL_TERM_TABLE_ENTRY_TYPE_P2MP" - expected_len = 6 if src_ip else 5 - for term_entry in tunnel_term_entries: - status, fvs = tunnel_term_table.get(term_entry) - - assert status == True - assert len(fvs) == expected_len - - for field, value in fvs: - if field == "SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_VR_ID": - assert self.check_vr_exists_in_asicdb(asicdb, value) - elif field == "SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_TYPE": - assert value == expected_term_type - elif field == "SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_TUNNEL_TYPE": - assert value == "SAI_TUNNEL_TYPE_IPINIP" - elif field == "SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_ACTION_TUNNEL_ID": - assert value == tunnel_sai_oid - elif field == "SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_DST_IP": - assert value in dst_ips - elif field == "SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_SRC_IP" and src_ip: - assert value == src_ip - else: - assert False, "Field %s is not tested" % field - - def create_and_test_tunnel(self, db, asicdb, tunnel_name, **kwargs): - """ Create tunnel and verify all needed enties in ASIC DB exists """ - - is_symmetric_tunnel = "src_ip" in kwargs - - decap_dscp_to_tc_map_oid = None - decap_tc_to_pg_map_oid = None - skip_tunnel_creation = False - - if "decap_dscp_to_tc_map_oid" in kwargs: - decap_dscp_to_tc_map_oid = kwargs.pop("decap_dscp_to_tc_map_oid") - - if "decap_tc_to_pg_map_oid" in kwargs: - decap_tc_to_pg_map_oid = kwargs.pop("decap_tc_to_pg_map_oid") - - if "skip_tunnel_creation" in kwargs: - skip_tunnel_creation = kwargs.pop("skip_tunnel_creation") - - if not skip_tunnel_creation: - fvs = create_fvs(**kwargs) - # create tunnel entry in DB - ps = swsscommon.ProducerStateTable(db, self.APP_TUNNEL_DECAP_TABLE_NAME) - ps.set(tunnel_name, fvs) - - # wait till config will be applied - time.sleep(1) - - # check asic db table - tunnel_table = swsscommon.Table(asicdb, self.ASIC_TUNNEL_TABLE) - - tunnels = tunnel_table.getKeys() - assert len(tunnels) == 1 - - tunnel_sai_obj = tunnels[0] - - status, fvs = tunnel_table.get(tunnel_sai_obj) - - assert status == True - # 6 parameters to check in case of decap tunnel - # + 1 (SAI_TUNNEL_ATTR_ENCAP_SRC_IP) in case of symmetric tunnel - expected_len = 7 if is_symmetric_tunnel else 6 - - expected_ecn_mode = self.ecn_modes_map[kwargs["ecn_mode"]] - expected_dscp_mode = self.dscp_modes_map[kwargs["dscp_mode"]] - expected_ttl_mode = self.ttl_modes_map[kwargs["ttl_mode"]] - - if decap_dscp_to_tc_map_oid: - expected_len += 1 - if decap_tc_to_pg_map_oid: - expected_len += 1 - - assert len(fvs) == expected_len - - for field, value in fvs: - if field == "SAI_TUNNEL_ATTR_TYPE": - assert value == "SAI_TUNNEL_TYPE_IPINIP" - elif field == "SAI_TUNNEL_ATTR_ENCAP_SRC_IP": - assert value == kwargs["src_ip"] - elif field == "SAI_TUNNEL_ATTR_DECAP_ECN_MODE": - assert value == expected_ecn_mode - elif field == "SAI_TUNNEL_ATTR_DECAP_TTL_MODE": - assert value == expected_ttl_mode - elif field == "SAI_TUNNEL_ATTR_DECAP_DSCP_MODE": - assert value == expected_dscp_mode - elif field == "SAI_TUNNEL_ATTR_OVERLAY_INTERFACE": - assert self.check_interface_exists_in_asicdb(asicdb, value) - elif field == "SAI_TUNNEL_ATTR_UNDERLAY_INTERFACE": - assert self.check_interface_exists_in_asicdb(asicdb, value) - elif field == "SAI_TUNNEL_ATTR_DECAP_QOS_DSCP_TO_TC_MAP": - assert value == decap_dscp_to_tc_map_oid - elif field == "SAI_TUNNEL_ATTR_DECAP_QOS_TC_TO_PRIORITY_GROUP_MAP": - assert value == decap_tc_to_pg_map_oid - else: - assert False, "Field %s is not tested" % field - src_ip = kwargs["src_ip"] if "src_ip" in kwargs else None - self.check_tunnel_termination_entry_exists_in_asicdb(asicdb, tunnel_sai_obj, kwargs["dst_ip"].split(","), src_ip) - - def remove_and_test_tunnel(self, db, asicdb, tunnel_name): - """ Removes tunnel and checks that ASIC db is clear""" - - tunnel_table = swsscommon.Table(asicdb, self.ASIC_TUNNEL_TABLE) - tunnel_term_table = swsscommon.Table(asicdb, self.ASIC_TUNNEL_TERM_ENTRIES) - tunnel_app_table = swsscommon.Table(asicdb, self.APP_TUNNEL_DECAP_TABLE_NAME) - - tunnels = tunnel_table.getKeys() - tunnel_sai_obj = tunnels[0] - - status, fvs = tunnel_table.get(tunnel_sai_obj) - - # get overlay loopback interface oid to check if it is deleted with the tunnel - overlay_infs_id = {f:v for f,v in fvs}["SAI_TUNNEL_ATTR_OVERLAY_INTERFACE"] - - ps = swsscommon.ProducerStateTable(db, self.APP_TUNNEL_DECAP_TABLE_NAME) - ps.set(tunnel_name, create_fvs(), 'DEL') - - # wait till config will be applied - time.sleep(1) - - assert len(tunnel_table.getKeys()) == 0 - assert len(tunnel_term_table.getKeys()) == 0 - assert len(tunnel_app_table.getKeys()) == 0 - assert not self.check_interface_exists_in_asicdb(asicdb, overlay_infs_id) - - def add_qos_map(self, configdb, asicdb, qos_map_type_name, qos_map_name, qos_map): - """ Add qos map for testing""" - qos_table = swsscommon.Table(asicdb, self.ASIC_QOS_MAP_TABLE_KEY) - current_oids = qos_table.getKeys() - - # Apply QoS map to config db - table = swsscommon.Table(configdb, qos_map_type_name) - fvs = swsscommon.FieldValuePairs(list(qos_map.items())) - table.set(qos_map_name, fvs) - time.sleep(1) - - diff = set(qos_table.getKeys()) - set(current_oids) - assert len(diff) == 1 - oid = diff.pop() - return oid - - def remove_qos_map(self, configdb, qos_map_type_name, qos_map_name): - """ Remove the testing qos map""" - table = swsscommon.Table(configdb, qos_map_type_name) - table._del(qos_map_name) - - def cleanup_left_over(self, db, asicdb): - """ Cleanup APP and ASIC tables """ - - tunnel_table = swsscommon.Table(asicdb, self.ASIC_TUNNEL_TABLE) - for key in tunnel_table.getKeys(): - tunnel_table._del(key) - - tunnel_term_table = swsscommon.Table(asicdb, self.ASIC_TUNNEL_TERM_ENTRIES) - for key in tunnel_term_table.getKeys(): - tunnel_term_table._del(key) - - tunnel_app_table = swsscommon.Table(db, self.APP_TUNNEL_DECAP_TABLE_NAME) - for key in tunnel_app_table.getKeys(): - tunnel_app_table._del(key) - -class TestDecapTunnel(TestTunnelBase): - """ Tests for decap tunnel creation and removal """ - - def test_TunnelDecap_v4(self, dvs, testlog): - """ test IPv4 tunnel creation """ - - db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - asicdb = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - - self.cleanup_left_over(db, asicdb) - - # create tunnel IPv4 tunnel - self.create_and_test_tunnel(db, asicdb, tunnel_name="IPINIPv4Decap", tunnel_type="IPINIP", - dst_ip="2.2.2.2,3.3.3.3", dscp_mode="uniform", - ecn_mode="standard", ttl_mode="pipe") - self.remove_and_test_tunnel(db, asicdb, "IPINIPv4Decap") - - def test_TunnelDecap_v6(self, dvs, testlog): - """ test IPv6 tunnel creation """ - - db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - asicdb = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - - self.cleanup_left_over(db, asicdb) - - # create tunnel IPv6 tunnel - self.create_and_test_tunnel(db, asicdb, tunnel_name="IPINIPv6Decap", tunnel_type="IPINIP", - dst_ip="2::2,3::3", dscp_mode="pipe", - ecn_mode="copy_from_outer", ttl_mode="uniform") - self.remove_and_test_tunnel(db, asicdb,"IPINIPv6Decap") - - def test_TunnelDecap_MuxTunnel(self, dvs, testlog): - """ Test MuxTunnel creation. """ - db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - asicdb = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - configdb = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - - self.cleanup_left_over(db, asicdb) - - dscp_to_tc_map_oid = self.add_qos_map(configdb, asicdb, swsscommon.CFG_DSCP_TO_TC_MAP_TABLE_NAME, self.TUNNEL_QOS_MAP_NAME, self.DSCP_TO_TC_MAP) - tc_to_pg_map_oid = self.add_qos_map(configdb, asicdb, swsscommon.CFG_TC_TO_PRIORITY_GROUP_MAP_TABLE_NAME, self.TUNNEL_QOS_MAP_NAME, self.TC_TO_PRIORITY_GROUP_MAP) - - # Create MuxTunnel0 with QoS remapping attributes - params = { - "tunnel_type": "IPINIP", - "src_ip": "1.1.1.1", - "dst_ip": "1.1.1.2", - "dscp_mode": "pipe", - "ecn_mode": "copy_from_outer", - "ttl_mode": "uniform", - "decap_dscp_to_tc_map": "AZURE_TUNNEL", - "decap_dscp_to_tc_map_oid": dscp_to_tc_map_oid, - "decap_tc_to_pg_map": "AZURE_TUNNEL", - "decap_tc_to_pg_map_oid": tc_to_pg_map_oid - } - self.create_and_test_tunnel(db, asicdb, tunnel_name="MuxTunnel0", **params) - - # Remove Tunnel first - self.remove_and_test_tunnel(db, asicdb,"MuxTunnel0") - - self.remove_qos_map(configdb, swsscommon.CFG_DSCP_TO_TC_MAP_TABLE_NAME, self.TUNNEL_QOS_MAP_NAME) - self.remove_qos_map(configdb, swsscommon.CFG_TC_TO_PRIORITY_GROUP_MAP_TABLE_NAME, self.TUNNEL_QOS_MAP_NAME) - - def test_TunnelDecap_MuxTunnel_with_retry(self, dvs, testlog): - """ Test MuxTunnel creation. """ - db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - asicdb = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - configdb = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - - self.cleanup_left_over(db, asicdb) - - # Create MuxTunnel0 with QoS remapping attributes - params = { - "tunnel_type": "IPINIP", - "src_ip": "1.1.1.1", - "dst_ip": "1.1.1.2", - "dscp_mode": "pipe", - "ecn_mode": "copy_from_outer", - "ttl_mode": "uniform", - "decap_dscp_to_tc_map": "AZURE_TUNNEL", - "decap_tc_to_pg_map": "AZURE_TUNNEL", - } - # Verify tunnel is not created when decap_dscp_to_tc_map/decap_tc_to_pg_map is specified while oid is not ready in qosorch - fvs = create_fvs(**params) - # create tunnel entry in DB - ps = swsscommon.ProducerStateTable(db, self.APP_TUNNEL_DECAP_TABLE_NAME) - ps.set("MuxTunnel0", fvs) - - time.sleep(1) - # check asic db table - tunnel_table = swsscommon.Table(asicdb, self.ASIC_TUNNEL_TABLE) - tunnels = tunnel_table.getKeys() - assert len(tunnels) == 0 - - #Verify tunneldecaporch creates tunnel when qos map is available - dscp_to_tc_map_oid = self.add_qos_map(configdb, asicdb, swsscommon.CFG_DSCP_TO_TC_MAP_TABLE_NAME, self.TUNNEL_QOS_MAP_NAME, self.DSCP_TO_TC_MAP) - tc_to_pg_map_oid = self.add_qos_map(configdb, asicdb, swsscommon.CFG_TC_TO_PRIORITY_GROUP_MAP_TABLE_NAME, self.TUNNEL_QOS_MAP_NAME, self.TC_TO_PRIORITY_GROUP_MAP) - params.update({ - "decap_dscp_to_tc_map_oid": dscp_to_tc_map_oid, - "decap_tc_to_pg_map_oid": tc_to_pg_map_oid, - "skip_tunnel_creation": True - }) - self.create_and_test_tunnel(db, asicdb, tunnel_name="MuxTunnel0", **params) - - # Cleanup - self.remove_and_test_tunnel(db, asicdb,"MuxTunnel0") - self.remove_qos_map(configdb, swsscommon.CFG_DSCP_TO_TC_MAP_TABLE_NAME, dscp_to_tc_map_oid) - self.remove_qos_map(configdb, swsscommon.CFG_TC_TO_PRIORITY_GROUP_MAP_TABLE_NAME, tc_to_pg_map_oid) - -class TestSymmetricTunnel(TestTunnelBase): - """ Tests for symmetric tunnel creation and removal """ - - def test_TunnelSymmetric_v4(self, dvs, testlog): - """ test IPv4 tunnel creation """ - - db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - asicdb = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - - self.cleanup_left_over(db, asicdb) - - # create tunnel IPv4 tunnel - self.create_and_test_tunnel(db, asicdb, tunnel_name="IPINIPv4Symmetric", tunnel_type="IPINIP", - src_ip="1.1.1.1", - dst_ip="2.2.2.2,3.3.3.3", dscp_mode="pipe", - ecn_mode="copy_from_outer", ttl_mode="uniform") - self.remove_and_test_tunnel(db, asicdb, "IPINIPv4Symmetric") - - def test_TunnelSymmetric_v6(self, dvs, testlog): - """ test IPv6 tunnel creation """ - - db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - asicdb = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - - self.cleanup_left_over(db, asicdb) - - # create tunnel IPv6 tunnel - self.create_and_test_tunnel(db, asicdb, tunnel_name="IPINIPv6Symmetric", tunnel_type="IPINIP", - src_ip="1::1", - dst_ip="2::2,3::3", dscp_mode="uniform", - ecn_mode="standard", ttl_mode="pipe") - self.remove_and_test_tunnel(db, asicdb, "IPINIPv6Symmetric") - - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_twamp.py b/tests/test_twamp.py deleted file mode 100644 index d2d8edb8f0..0000000000 --- a/tests/test_twamp.py +++ /dev/null @@ -1,182 +0,0 @@ -# This test suite covers the functionality of twamp light feature in SwSS -import pytest -import time - -@pytest.mark.usefixtures("testlog") -@pytest.mark.usefixtures('dvs_twamp_manager') -class TestTwampLight(object): - - def check_syslog(self, dvs, marker, log, expected_cnt): - (ec, out) = dvs.runcmd(['sh', '-c', "awk \'/%s/,ENDFILE {print;}\' /var/log/syslog | grep \'%s\' | wc -l" % (marker, log)]) - assert out.strip() == str(expected_cnt) - - def test_SenderPacketCountSingle(self, dvs, testlog): - """ - This test covers the TWAMP Light session creation and removal operations - Operation flow: - 1. Create twamp-light session-sender using once packet-count - The session remains inactive - 2. Start twamp-light session - The session becomes active - 3. Remove twamp-light session - """ - - session = "TEST_SENDER1" - src_ip = "1.1.1.1" - src_udp_port = "862" - dst_ip = "2.2.2.2" - dst_udp_port = "863" - packet_count = "1000" - tx_interval = "10" - timeout = "10" - stats_interval = "20000" - - marker = dvs.add_log_marker() - - # create twamp-light session - self.dvs_twamp.create_twamp_light_session_sender_packet_count(session, src_ip, src_udp_port, dst_ip, dst_udp_port, packet_count, tx_interval, timeout) - - # start twamp-light session - self.dvs_twamp.start_twamp_light_sender(session) - - # wait for sending TWAMP-test done - time.sleep(12) - - # remove twamp-light session - self.dvs_twamp.remove_twamp_light_session(session) - self.dvs_twamp.verify_no_session() - - def test_SenderPacketCountMulti(self, dvs, testlog): - """ - This test covers the TWAMP Light Sender session creation and removal operations - Operation flow: - 1. Create twamp-light session-sender using multi packet-count - The session remains inactive - 2. Start twamp-light session - The session becomes active - 3. Remove twamp-light session - """ - - session = "TEST_SENDER1" - src_ip = "1.2.3.4" - src_udp_port = "862" - dst_ip = "5.6.7.8" - dst_udp_port = "863" - packet_count = "1000" - tx_interval = "10" - timeout = "10" - stats_interval = "11000" - - marker = dvs.add_log_marker() - - # create twamp-light session - self.dvs_twamp.create_twamp_light_session_sender_packet_count(session, src_ip, src_udp_port, dst_ip, dst_udp_port, packet_count, tx_interval, timeout, stats_interval) - - # start twamp-light session - self.dvs_twamp.start_twamp_light_sender(session) - - # wait for sending TWAMP-test done - time.sleep(120) - - # remove twamp-light session - self.dvs_twamp.remove_twamp_light_session(session) - self.dvs_twamp.verify_no_session() - - def test_SenderContinuousSingle(self, dvs, testlog): - """ - This test covers the TWAMP Light Sender session creation and removal operations - Operation flow: - 1. Create twamp-light session-sender using once continuous - The session remains inactive - 2. Start twamp-light session - The session becomes active - 3. Remove twamp-light session - """ - - session = "TEST_SENDER2" - src_ip = "11.11.11.11" - src_udp_port = "862" - dst_ip = "12.12.12.12" - dst_udp_port = "863" - monitor_time = "60" - tx_interval = "100" - timeout = "10" - stats_interval = "60000" - - marker = dvs.add_log_marker() - - # create twamp-light session - self.dvs_twamp.create_twamp_light_session_sender_continuous(session, src_ip, src_udp_port, dst_ip, dst_udp_port, monitor_time, tx_interval, timeout) - - # start twamp-light session - self.dvs_twamp.start_twamp_light_sender(session) - # wait for sending TWAMP-test done - time.sleep(60) - - # remove twamp-light session - self.dvs_twamp.remove_twamp_light_session(session) - self.dvs_twamp.verify_no_session() - - def test_SenderContinuousMulti(self, dvs, testlog): - """ - This test covers the continuous TWAMP Light Sender session creation and removal operations - Operation flow: - 1. Create twamp-light session-sender using multi continuous - The session remains inactive - 2. Start twamp-light session - The session becomes active - 3. Remove twamp-light session - """ - - session = "TEST_SENDER2" - src_ip = "11.12.13.14" - src_udp_port = "862" - dst_ip = "15.16.17.18" - dst_udp_port = "863" - monitor_time = "60" - tx_interval = "100" - timeout = "10" - stats_interval = "20000" - - marker = dvs.add_log_marker() - - # create twamp-light session - self.dvs_twamp.create_twamp_light_session_sender_continuous(session, src_ip, src_udp_port, dst_ip, dst_udp_port, monitor_time, tx_interval, timeout, stats_interval) - - # start twamp-light session - self.dvs_twamp.start_twamp_light_sender(session) - - # wait for sending TWAMP-test done - time.sleep(60) - - # remove twamp-light session - self.dvs_twamp.remove_twamp_light_session(session) - self.dvs_twamp.verify_no_session() - - def test_Reflector(self, dvs, testlog): - """ - This test covers the TWAMP Light Reflector session creation and removal operations - Operation flow: - 1. Create twamp-light session-reflector - 2. Remove twamp-light session - """ - - session = "TEST_REFLECTOR1" - src_ip = "22.1.1.1" - src_udp_port = "862" - dst_ip = "22.1.1.2" - dst_udp_port = "863" - - marker = dvs.add_log_marker() - - # create twamp-light session - self.dvs_twamp.create_twamp_light_session_reflector(session, src_ip, src_udp_port, dst_ip, dst_udp_port) - - # remove twamp-light session - self.dvs_twamp.remove_twamp_light_session(session) - self.dvs_twamp.verify_no_session() - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_virtual_chassis.py b/tests/test_virtual_chassis.py deleted file mode 100644 index 5401f6870f..0000000000 --- a/tests/test_virtual_chassis.py +++ /dev/null @@ -1,979 +0,0 @@ -from swsscommon import swsscommon -from dvslib.dvs_database import DVSDatabase -import ast -import time -import pytest -import buffer_model - -DVS_ENV = ["ASIC_VENDOR=vs"] - -class TestVirtualChassis(object): - - def set_lag_id_boundaries(self, vct): - """This functions sets lag id boundaries in the chassis app db. - - In VOQ systems the lag id boundaries need to be set before configuring any PortChannels. - The lag id boundaries are used by lag id allocator while adding a PortChannel to the asic db. - Note: - In real systems, the lag id boundries are taken from a platform specific file. For testing - we assume the chassis capability with maximum 2 lags so that we can test the lag id allocator - table full error with less number of PortChannel configuration - """ - - dvss = vct.dvss - for name in dvss.keys(): - if name.startswith("supervisor"): - dvs = dvss[name] - chassis_app_db = DVSDatabase(swsscommon.CHASSIS_APP_DB, dvs.redis_chassis_sock) - chassis_app_db.db_connection.set("SYSTEM_LAG_ID_START", "1") - chassis_app_db.db_connection.set("SYSTEM_LAG_ID_END", "2") - break - - def config_inbandif_port(self, vct, ibport): - """This function configures port type inband interface in each linecard""" - - dvss = vct.dvss - for name in dvss.keys(): - dvs = dvss[name] - # Get the config info - config_db = dvs.get_config_db() - metatbl = config_db.get_entry("DEVICE_METADATA", "localhost") - - cfg_switch_type = metatbl.get("switch_type") - - # Configure only for line cards - if cfg_switch_type == "voq": - dvs.port_admin_set(f"{ibport}", "up") - config_db.create_entry("VOQ_INBAND_INTERFACE", f"{ibport}", {"inband_type": "port"}) - - def del_inbandif_port(self, vct, ibport): - """This function deletes existing port type inband interface""" - - dvss = vct.dvss - for name in dvss.keys(): - dvs = dvss[name] - # Get the config info - config_db = dvs.get_config_db() - metatbl = config_db.get_entry("DEVICE_METADATA", "localhost") - - cfg_switch_type = metatbl.get("switch_type") - - # Applicable only for line cards - if cfg_switch_type == "voq": - config_db.delete_entry("VOQ_INBAND_INTERFACE", f"{ibport}") - - def test_connectivity(self, vct): - if vct is None: - return - dvss = vct.dvss - nbrs = vct.get_topo_neigh() - for name in dvss.keys(): - dv = dvss[name] - # ping all vs's inband address - for ctn in vct.inbands.keys(): - ip = vct.inbands[ctn]["inband_address"] - ip = ip.split("/")[0] - print("%s: ping inband address %s" % (name, ip)) - _, out = dv.runcmd(['sh', "-c", "ping -c 5 -W 0 -q %s" % ip]) - print(out) - assert '5 received' in out - if name not in nbrs.keys(): - continue - for item in nbrs[name]: - ip = str(item[1]) - print("%s: ping neighbor address %s" % (name, ip)) - _, out = dv.runcmd(['sh', "-c", "ping -c 5 -W 0 -q %s" % ip]) - print(out) - assert '5 received' in out - - def test_voq_switch(self, vct): - """Test VOQ switch objects configuration. - - This test validates configuration of switch creation objects required for - VOQ switches. The switch_type, max_cores and switch_id attributes configuration - are verified. For the System port config list, it is verified that all the - configured system ports are avaiable in the asic db by checking the count. - """ - - if vct is None: - return - - dvss = vct.dvss - for name in dvss.keys(): - dvs = dvss[name] - # Get the config info - config_db = dvs.get_config_db() - metatbl = config_db.get_entry("DEVICE_METADATA", "localhost") - - cfg_switch_type = metatbl.get("switch_type") - - # Test only for line cards - if cfg_switch_type == "voq": - print("VOQ Switch test for {}".format(name)) - cfg_switch_id = metatbl.get("switch_id") - assert cfg_switch_id != "", "Got error in getting switch_id from CONFIG_DB DEVICE_METADATA" - - cfg_max_cores = metatbl.get("max_cores") - assert cfg_max_cores != "", "Got error in getting max_cores from CONFIG_DB DEVICE_METADATA" - - cfgspkeys = config_db.get_keys("SYSTEM_PORT") - sp_count = len(cfgspkeys) - - asic_db = dvs.get_asic_db() - keys = asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_SWITCH") - switch_oid_key = keys[0] - - switch_entry = asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_SWITCH", switch_oid_key) - - value = switch_entry.get("SAI_SWITCH_ATTR_TYPE") - assert value == "SAI_SWITCH_TYPE_VOQ", "Switch type is not VOQ" - - value = switch_entry.get("SAI_SWITCH_ATTR_SWITCH_ID") - assert value == cfg_switch_id, "VOQ switch id is invalid" - - value = switch_entry.get("SAI_SWITCH_ATTR_MAX_SYSTEM_CORES") - assert value == cfg_max_cores, "Max system cores is invalid" - - value = switch_entry.get("SAI_SWITCH_ATTR_SYSTEM_PORT_CONFIG_LIST") - assert value != "", "Empty system port config list" - # Convert the spcfg string to dictionary - spcfg = ast.literal_eval(value) - assert spcfg['count'] == sp_count, "Number of systems ports configured is invalid" - - def test_chassis_app_db_sync(self, vct): - """Test chassis app db syncing. - - This test is for verifying the database sync mechanism. With the virtual chassis - setup, it is verified that at least one database entry is synced from line card to - supervisor card. An interface entry is used as sample database entry for verification - of syncing mechanism. - """ - - if vct is None: - return - - dvss = vct.dvss - for name in dvss.keys(): - if name.startswith("supervisor"): - dvs = dvss[name] - chassis_app_db = DVSDatabase(swsscommon.CHASSIS_APP_DB, dvs.redis_chassis_sock) - keys = chassis_app_db.get_keys("SYSTEM_INTERFACE") - assert len(keys), "No chassis app db syncing is done" - - def test_chassis_system_interface(self, vct): - """Test RIF record creation in ASIC_DB for remote interfaces. - - This test verifies RIF programming in ASIC_DB for remote interface. The orchagent - creates RIF record for system port interfaces from other line cards. It is verified - by retrieving a RIF record from local ASIC_DB that corresponds to a remote system port - and checking that the switch id of that remote system port does not match the local asic - switch id. - """ - - if vct is None: - return - - dvss = vct.dvss - for name in dvss.keys(): - dvs = dvss[name] - - config_db = dvs.get_config_db() - metatbl = config_db.get_entry("DEVICE_METADATA", "localhost") - - cfg_switch_type = metatbl.get("switch_type") - - # Test only for line cards - if cfg_switch_type == "voq": - lc_switch_id = metatbl.get("switch_id") - assert lc_switch_id != "", "Got error in getting switch_id from CONFIG_DB DEVICE_METADATA" - if lc_switch_id == "0": - # Testing in Linecard1, In Linecard1 there will be RIF for Ethernet12 from Linecard3 - # Note: Tesing can be done in any linecard for RIF of any system port interface. - # Here testing is done on linecard with switch id 0 - asic_db = dvs.get_asic_db() - keys = asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") - assert len(keys), "No router interfaces in ASIC_DB" - - rif_port_oid = "" - for key in keys: - rif_entry = asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE", key) - value = rif_entry.get("SAI_ROUTER_INTERFACE_ATTR_TYPE") - assert value != "", "Got error in getting RIF type" - if value == "SAI_ROUTER_INTERFACE_TYPE_PORT": - value = rif_entry.get("SAI_ROUTER_INTERFACE_ATTR_PORT_ID") - assert value != "", "Got error in getting RIF port" - if value.startswith("oid:0x5d"): - # System port RIF, this is used as key for system port config info retrieval - rif_port_oid = value - break - - assert rif_port_oid != "", "No RIF records for remote interfaces in ASIC_DB" - # Validate if the system port is from valid switch - sp_entry = asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_SYSTEM_PORT", rif_port_oid) - value = sp_entry.get("SAI_SYSTEM_PORT_ATTR_CONFIG_INFO") - assert value != "", "Got error in getting system port config info for rif system port" - spcfginfo = ast.literal_eval(value) - # Remote system ports's switch id should not match local switch id - assert spcfginfo["attached_switch_id"] != lc_switch_id, "RIF system port with wrong switch_id" - - def test_chassis_system_neigh(self, vct): - """Test neigh record create/delete and syncing to chassis app db. - - This test validates that: - (i) Local neighbor entry is created with encap index - (ii) Local neighbor is synced to chassis ap db with assigned encap index - (iii) Remote neighbor entry is created in ASIC_DB with received encap index - (iv) Local neighbor entry is deleted when neighbor is deleted - (v) Local neighbor delete is synced to chassis ap db - (vi) Remote neighbor entry is cleared in ASIC_DB - """ - - if vct is None: - return - - # We use Ethernet0 as inband port in each line card. In real hardware, this will be a - # special port used for inband. For testing purpose, we need port record and rif record - # for the inband interface and valid kernel interface. Since Ethernet0 is already - # setup, the port record, rif record and kernel interface already exist. So we use it - # for testing - inband_port = "Ethernet0" - - # Configure port type inband interface - self.config_inbandif_port(vct, inband_port) - - # Test neighbor on Ethernet4 since Ethernet0 is used as Inband port - test_neigh_dev = "Ethernet4" - test_neigh_ip = "10.8.104.3" - - # Grouping together the checks done during neighbor entry create into a function chassis_system_neigh_create() - # if action is "add" it creates a new neighbor entry in local asic - # if action is "change" it updates an existing neighbor entry with the mac_address - def chassis_system_neigh_create(): - dvss = vct.dvss - print("name {}".format(dvss.keys())) - for name in dvss.keys(): - dvs = dvss[name] - - config_db = dvs.get_config_db() - metatbl = config_db.get_entry("DEVICE_METADATA", "localhost") - - cfg_switch_type = metatbl.get("switch_type") - - # Neighbor record verifiation done in line card - if cfg_switch_type == "voq": - lc_switch_id = metatbl.get("switch_id") - assert lc_switch_id != "", "Got error in getting switch_id from CONFIG_DB DEVICE_METADATA" - if lc_switch_id == "0": - - # Add a static neighbor - _, res = dvs.runcmd(['sh', "-c", "ip neigh show"]) - _, res = dvs.runcmd(['sh', "-c", f"ip neigh {action} {test_neigh_ip} lladdr {mac_address} dev {test_neigh_dev}"]) - assert res == "", "Error configuring static neigh" - - asic_db = dvs.get_asic_db() - asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY", 1) - neighkeys = asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY") - assert len(neighkeys), "No neigh entries in ASIC_DB" - - # Check for presence of the neighbor in ASIC_DB - test_neigh = "" - for nkey in neighkeys: - ne = ast.literal_eval(nkey) - if ne['ip'] == test_neigh_ip: - test_neigh = nkey - break - - assert test_neigh != "", "Neigh not found in ASIC_DB" - - # Preserve test neigh asic db key for delete verification later - test_neigh_asic_db_key = test_neigh - - # Check for presence of encap index, retrieve and store it for sync verification - test_neigh_entry = asic_db.wait_for_entry("ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY", test_neigh) - test_neigh_entry_attrs = asic_db.wait_for_fields("ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY", test_neigh, ["SAI_NEIGHBOR_ENTRY_ATTR_ENCAP_INDEX"]) - print(test_neigh) - print(test_neigh_entry) - print(test_neigh_entry_attrs) - encap_index = test_neigh_entry_attrs["SAI_NEIGHBOR_ENTRY_ATTR_ENCAP_INDEX"] - assert encap_index != "" and encap_index != None, "VOQ encap index is not programmed in ASIC_DB" - - break - - # Verify neighbor record syncing with encap index - for name in dvss.keys(): - if name.startswith("supervisor"): - dvs = dvss[name] - chassis_app_db = DVSDatabase(swsscommon.CHASSIS_APP_DB, dvs.redis_chassis_sock) - chassis_app_db.wait_for_n_keys("SYSTEM_NEIGH", 1) - sysneighkeys = chassis_app_db.get_keys("SYSTEM_NEIGH") - - print(sysneighkeys) - test_sysneigh = "" - for sysnk in sysneighkeys: - sysnk_tok = sysnk.split("|") - assert len(sysnk_tok) == 4, "Invalid system neigh key in chassis app db" - if sysnk_tok[3] == test_neigh_ip: - test_sysneigh = sysnk - break - - assert test_sysneigh != "", "Neigh is not sync-ed to chassis app db" - - # Preserve test sys neigh chassis app db key for delete verification later - test_sysneigh_chassis_app_db_key = test_sysneigh - - test_sysneigh_entry = chassis_app_db.get_entry("SYSTEM_NEIGH", test_sysneigh) - sys_neigh_encap_index = test_sysneigh_entry.get("encap_index") - assert sys_neigh_encap_index != "", "System neigh in chassis app db does not have encap index" - - assert encap_index == sys_neigh_encap_index, "Encap index not sync-ed correctly" - - break - - # Add a delay for the programming of neighbor in remote LC - time.sleep(10) - - # Verify programming of remote neighbor in asic db and programming of static route and static - # neigh in the kernel for the remote neighbor. The neighbor created in linecard 1 will be a - # remote neighbor in other linecards. Verity existence of the test neighbor in linecards other - # than linecard 1 - for name in dvss.keys(): - dvs = dvss[name] - - config_db = dvs.get_config_db() - metatbl = config_db.get_entry("DEVICE_METADATA", "localhost") - - cfg_switch_type = metatbl.get("switch_type") - - # Neighbor record verifiation done in line card - if cfg_switch_type == "voq": - lc_switch_id = metatbl.get("switch_id") - assert lc_switch_id != "", "Got error in getting switch_id from CONFIG_DB DEVICE_METADATA" - if lc_switch_id != "0": - # Linecard other than linecard 1 - asic_db = dvs.get_asic_db() - asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY", 1) - neighkeys = asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY") - assert len(neighkeys), "No neigh entries in ASIC_DB" - - # Check for presence of the remote neighbor in ASIC_DB - remote_neigh = "" - for nkey in neighkeys: - ne = ast.literal_eval(nkey) - if ne['ip'] == test_neigh_ip: - remote_neigh = nkey - break - - assert remote_neigh != "", "Remote neigh not found in ASIC_DB" - - # Preserve remote neigh asic db neigh key for delete verification later - test_remote_neigh_asic_db_key = remote_neigh - - # Check for kernel entries - - _, output = dvs.runcmd("ip neigh show") - assert f"{test_neigh_ip} dev {inband_port} lladdr {mac_address}" in output, "Kernel neigh not found for remote neighbor" - - _, output = dvs.runcmd("ip route show") - assert f"{test_neigh_ip} dev {inband_port} scope link" in output, "Kernel route not found for remote neighbor" - - # Check for ASIC_DB entries. - - # Check for presence of encap index, retrieve and store it for sync verification - remote_neigh_entry = asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY", remote_neigh) - - # Validate encap index - remote_encap_index = remote_neigh_entry.get("SAI_NEIGHBOR_ENTRY_ATTR_ENCAP_INDEX") - assert remote_encap_index != "", "VOQ encap index is not programmed for remote neigh in ASIC_DB" - assert remote_encap_index == encap_index, "Encap index of remote neigh mismatch with allocated encap index" - - # Validate MAC - mac = remote_neigh_entry.get("SAI_NEIGHBOR_ENTRY_ATTR_DST_MAC_ADDRESS") - assert mac != "", "MAC address is not programmed for remote neigh in ASIC_DB" - assert mac == mac_address, "Encap index of remote neigh mismatch with allocated encap index" - - # Check for other mandatory attributes - # For remote neighbors, is_local must be "false" - is_local = remote_neigh_entry.get("SAI_NEIGHBOR_ENTRY_ATTR_IS_LOCAL") - assert is_local != "", "is_local attribute is not programmed for remote neigh in ASIC_DB" - assert is_local == "false", "is_local attribute is true for remote neigh" - - break - - return test_neigh_asic_db_key, test_sysneigh_chassis_app_db_key, test_remote_neigh_asic_db_key - - # First step is to add a new neighbor and check local/chassis_db/remote entry creation - mac_address = "00:01:02:03:04:77" - action = "add" - chassis_system_neigh_create() - - # Second step to update the mac address and check local/chassis_db/remote entry creation - mac_address = "00:01:02:03:04:05" - action = "change" - test_neigh_asic_db_key, test_sysneigh_chassis_app_db_key, test_remote_neigh_asic_db_key = chassis_system_neigh_create() - - # Verify system neighbor delete and clearing - dvss = vct.dvss - for name in dvss.keys(): - dvs = dvss[name] - - config_db = dvs.get_config_db() - metatbl = config_db.get_entry("DEVICE_METADATA", "localhost") - - cfg_switch_type = metatbl.get("switch_type") - - # Neighbor record verifiation done in line card - if cfg_switch_type == "voq": - lc_switch_id = metatbl.get("switch_id") - assert lc_switch_id != "", "Got error in getting switch_id from CONFIG_DB DEVICE_METADATA" - if lc_switch_id == "0": - - # Delete the static neighbor neighbor - _, res = dvs.runcmd(['sh', "-c", f"ip neigh del {test_neigh_ip} dev {test_neigh_dev}"]) - assert res == "", "Error deleting static neigh" - - # Check for presence of the neighbor in ASIC_DB. The deleted neighbor should - # not be present in the asic db - asic_db = dvs.get_asic_db() - neighkeys = asic_db.wait_for_deleted_entry("ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY", test_neigh_asic_db_key) - assert len(neighkeys) == 0, "Stale neigh entry found in ASIC_DB" - - break - - # Verify syncing of neighbor record delete in chassis app db - dvss = vct.dvss - for name in dvss.keys(): - if name.startswith("supervisor"): - dvs = dvss[name] - chassis_app_db = DVSDatabase(swsscommon.CHASSIS_APP_DB, dvs.redis_chassis_sock) - sysneighkeys = chassis_app_db.wait_for_deleted_entry("SYSTEM_NEIGH", test_sysneigh_chassis_app_db_key) - assert len(sysneighkeys) == 0, "Stale neigh entry in chassis app db" - - break - - # Verify clearing of remote neighbor in non-owner linecard - dvss = vct.dvss - for name in dvss.keys(): - dvs = dvss[name] - - config_db = dvs.get_config_db() - metatbl = config_db.get_entry("DEVICE_METADATA", "localhost") - - cfg_switch_type = metatbl.get("switch_type") - - # Neighbor record verifiation done in line card - if cfg_switch_type == "voq": - lc_switch_id = metatbl.get("switch_id") - assert lc_switch_id != "", "Got error in getting switch_id from CONFIG_DB DEVICE_METADATA" - if lc_switch_id != "0": - # Linecard other than linecard 1 - - # Check for presence of the remote neighbor in ASIC_DB. The remote neighbor corresponding - # to the deleted static neigbor should not be present - asic_db = dvs.get_asic_db() - neighkeys = asic_db.wait_for_deleted_entry("ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY", test_remote_neigh_asic_db_key) - assert len(neighkeys) == 0, "Stale remote neigh in ASIC_DB" - - # Check for kernel entries. Kernel entries (neigh and route) should have been removed - - _, output = dvs.runcmd("ip neigh show") - assert f"{test_neigh_ip} dev {inband_port}" not in output, "Kernel neigh of remote neighbor not removed" - - _, output = dvs.runcmd("ip route show") - assert f"{test_neigh_ip} dev {inband_port} scope link" not in output, "Kernel route of remote neighbor not removed" - - break - - # Cleanup inband if configuration - self.del_inbandif_port(vct, inband_port) - - def test_chassis_system_lag(self, vct): - """Test PortChannel in VOQ based chassis systems. - - This test validates that - (i) PortChannel is created in local asic with system port aggregator id (system lag id) - - Unique lag id is allocated from chassis app db in supervisor card - - The unique lag id is sent in system port aggregator id attribute - (ii) PortChannel members are successfully added in the PortChannel created - (iii) Local PortChannel is synced in chassis app db - (iv) PortChannel members addition is synced in the chassis app db - (v) System LAG is created for the remote PortChannel with system lag id. - (vi) System LAG of remote Portchannel has members with system port id - """ - - if vct is None: - return - - test_lag1_name = "PortChannel0001" - test_lag1_member = "Ethernet4" - - # Set the lag id boundaries in the chassis ap db - self.set_lag_id_boundaries(vct) - - # Create a PortChannel in a line card 1 (owner line card) - dvss = vct.dvss - for name in dvss.keys(): - dvs = dvss[name] - - config_db = dvs.get_config_db() - metatbl = config_db.get_entry("DEVICE_METADATA", "localhost") - - # Get the host name and asic name for the system lag alias verification - cfg_hostname = metatbl.get("hostname") - assert cfg_hostname != "", "Got error in getting hostname from CONFIG_DB DEVICE_METADATA" - - cfg_asic_name = metatbl.get("asic_name") - assert cfg_asic_name != "", "Got error in getting asic_name from CONFIG_DB DEVICE_METADATA" - - cfg_switch_type = metatbl.get("switch_type") - - # Portchannel record verifiation done in line card - if cfg_switch_type == "voq": - lc_switch_id = metatbl.get("switch_id") - assert lc_switch_id != "", "Got error in getting switch_id from CONFIG_DB DEVICE_METADATA" - if lc_switch_id == "0": - - # Connect to app db: lag table and lag member table - app_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - psTbl_lag = swsscommon.ProducerStateTable(app_db, "LAG_TABLE") - psTbl_lagMember = swsscommon.ProducerStateTable(app_db, "LAG_MEMBER_TABLE") - - # Create PortChannel - fvs = swsscommon.FieldValuePairs([("admin", "up"), ("mtu", "9100")]) - psTbl_lag.set(f"{test_lag1_name}", fvs) - - # Verify creation of the PorChannel with voq system port aggregator id in asic db - asic_db = dvs.get_asic_db() - lagkeys = asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG", 1) - assert len(lagkeys) == 1, "The LAG entry for configured PortChannel is not available in asic db" - - # Check for the presence of voq system port aggregate id attribute - lag_entry = asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_LAG", lagkeys[0]) - spa_id = lag_entry.get("SAI_LAG_ATTR_SYSTEM_PORT_AGGREGATE_ID") - assert spa_id != "", "VOQ System port aggregate id not present for the LAG" - - # Add port channel member - fvs = swsscommon.FieldValuePairs([("status", "enabled")]) - psTbl_lagMember.set(f"{test_lag1_name}:{test_lag1_member}", fvs) - - # Check for presence of lag member added - lagmemberkeys = asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER", 1) - assert len(lagmemberkeys) == 1, "The LAG member for configured PortChannel is not available in asic db" - - break - - # Check syncing of the PortChannel and PortChannel member in chasiss app db - for name in dvss.keys(): - if name.startswith("supervisor"): - dvs = dvss[name] - chassis_app_db = DVSDatabase(swsscommon.CHASSIS_APP_DB, dvs.redis_chassis_sock) - syslagkeys = chassis_app_db.wait_for_n_keys("SYSTEM_LAG_TABLE", 1) - assert len(syslagkeys) == 1, "System lag entry is not available in chassis app db" - - # system lag alias (key) should be unique across chassis. To ensure such uniqueness, - # the system lag name is derived from hostname, asic_name and PortChannel name - # Verify for correct name - assert f"{cfg_hostname}|{cfg_asic_name}|{test_lag1_name}" in syslagkeys[0], "Invalid unique system lag name" - - # Verify lag id of the system lag in chassis app db - syslag_entry = chassis_app_db.get_entry("SYSTEM_LAG_TABLE", syslagkeys[0]) - remote_lag_id = syslag_entry.get("lag_id") - assert remote_lag_id != "", "Lag id is not present in the sytem lag table in chassis app db" - # This id must be same as the id allocated in owner linecard. - assert remote_lag_id == spa_id, "System lag id in chassis app db is not same as allocated lag id" - - syslagmemberkeys = chassis_app_db.wait_for_n_keys("SYSTEM_LAG_MEMBER_TABLE", 1) - assert len(syslagmemberkeys) == 1, "No system lag member entries in chassis app db" - - break - - # Verify programming of remote system lag with received system lag id in non-owner line card - # Verify programming of lag menbers with system port id in non-owner line card - for name in dvss.keys(): - dvs = dvss[name] - - config_db = dvs.get_config_db() - metatbl = config_db.get_entry("DEVICE_METADATA", "localhost") - - cfg_switch_type = metatbl.get("switch_type") - - # System LAG info verifiation done in non-owner line card - if cfg_switch_type == "voq": - lc_switch_id = metatbl.get("switch_id") - assert lc_switch_id != "", "Got error in getting switch_id from CONFIG_DB DEVICE_METADATA" - if lc_switch_id != "0": - # Linecard other than linecard 1 (owner line card) - asic_db = dvs.get_asic_db() - remotesyslagkeys = asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG", 1) - assert len(remotesyslagkeys) == 1, "No remote system lag entries in ASIC_DB" - - remotesyslag_entry = asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_LAG", remotesyslagkeys[0]) - remote_lag_id = remotesyslag_entry.get("SAI_LAG_ATTR_SYSTEM_PORT_AGGREGATE_ID") - assert remote_lag_id != "", "Lag id not present in the remote syslag entry in asic db" - assert remote_lag_id == spa_id, "Remote system lag programmed with wrong lag id" - - # Verify remote system lag has system port as member - lagmemberkeys = asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER", 1) - assert len(lagmemberkeys) == 1, "The LAG member for remote system lag is not available in asic db" - - remotelagmember_entry = asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER", lagmemberkeys[0]) - member_port_id = remotelagmember_entry.get("SAI_LAG_MEMBER_ATTR_PORT_ID") - #Verify that the member is a system port - assert "oid:0x5d" in member_port_id, "System LAG member is not system port" - - break - - def test_chassis_system_lag_id_allocator_table_full(self, vct): - """Test lag id allocator table full. - - Pre-requisite: - (i) Test case: test_chassis_system_lag - This test validates that - (i) If PortChannel configuration goes beyond the platfrom capacitty boundary, lag id - allocator returns table full error - """ - - if vct is None: - return - - test_lag2_name = "PortChannel0002" - test_lag3_name = "PortChannel0003" - - # Create a PortChannel in a line card 1 (owner line card) - dvss = vct.dvss - for name in dvss.keys(): - dvs = dvss[name] - - config_db = dvs.get_config_db() - metatbl = config_db.get_entry("DEVICE_METADATA", "localhost") - - # Get the host name and asic name for the system lag alias verification - cfg_hostname = metatbl.get("hostname") - assert cfg_hostname != "", "Got error in getting hostname from CONFIG_DB DEVICE_METADATA" - - cfg_asic_name = metatbl.get("asic_name") - assert cfg_asic_name != "", "Got error in getting asic_name from CONFIG_DB DEVICE_METADATA" - - cfg_switch_type = metatbl.get("switch_type") - - # Portchannel record verifiation done in line card - if cfg_switch_type == "voq": - lc_switch_id = metatbl.get("switch_id") - assert lc_switch_id != "", "Got error in getting switch_id from CONFIG_DB DEVICE_METADATA" - if lc_switch_id == "0": - - # Connect to app db: lag table - app_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - psTbl_lag = swsscommon.ProducerStateTable(app_db, "LAG_TABLE") - - # Create PortChannel 2. This should be successfully configured - fvs = swsscommon.FieldValuePairs([("admin", "up"), ("mtu", "9100")]) - psTbl_lag.set(f"{test_lag2_name}", fvs) - - # Verify creation of the PorChannels with voq system port aggregator id in asic db - asic_db = dvs.get_asic_db() - lagkeys = asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG", 2) - assert len(lagkeys) == 2, "Two configured LAG entries are not available in asic db" - - # Check for the presence of voq system port aggregate id attribute for 2 LAGs - lag_entry = asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_LAG", lagkeys[0]) - spa_id = lag_entry.get("SAI_LAG_ATTR_SYSTEM_PORT_AGGREGATE_ID") - assert spa_id != "", "VOQ System port aggregate id not present for the LAG 1" - - lag_entry = asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_LAG", lagkeys[1]) - spa_id = lag_entry.get("SAI_LAG_ATTR_SYSTEM_PORT_AGGREGATE_ID") - assert spa_id != "", "VOQ System port aggregate id not present for the LAG 2" - - # Create PortChannel 3. This should not be configured since lag id limit reached - fvs = swsscommon.FieldValuePairs([("admin", "up"), ("mtu", "9100")]) - psTbl_lag.set(f"{test_lag3_name}", fvs) - - # Check syslog for the table full error - marker = "ERR #orchagent" - srch_str = f"addLag: Failed to allocate unique LAG id for local lag {test_lag3_name} rv:-1" - _, num = dvs.runcmd(["sh", "-c", "awk '/%s/,ENDFILE {print;}' /var/log/syslog \ - | grep \"%s\" | wc -l" % (marker, srch_str)]) - assert num.strip() == '1', "LAG ID allocator table full error is not returned" - - # Clean up the app db for the PortChannel creation failure - psTbl_lag.delete(f"{test_lag3_name}") - - break - - def test_chassis_system_lag_id_allocator_del_id(self, vct): - """Test lag id allocator's release id and re-use id processing. - - Pre-requisite: - (i) Test case: test_chassis_system_lag - (ii) Test case: test_chassis_system_lag_id_allocator_table_full - This test validates that - (i) Portchannel is deleted and id allocator does not return error - (ii) Should be able to add PortChannel to re-use released id - (iii) Deleted portchaneels are removed from chassis app db - (iv) Remote asics remove the system lag corresponding to the deleted PortChannels - """ - - if vct is None: - return - - test_lag1_name = "PortChannel0001" - test_lag1_member = "Ethernet4" - test_lag2_name = "PortChannel0002" - test_lag3_name = "PortChannel0003" - - # Create a PortChannel in a line card 1 (owner line card) - dvss = vct.dvss - for name in dvss.keys(): - dvs = dvss[name] - - config_db = dvs.get_config_db() - metatbl = config_db.get_entry("DEVICE_METADATA", "localhost") - - # Get the host name and asic name for the system lag alias verification - cfg_hostname = metatbl.get("hostname") - assert cfg_hostname != "", "Got error in getting hostname from CONFIG_DB DEVICE_METADATA" - - cfg_asic_name = metatbl.get("asic_name") - assert cfg_asic_name != "", "Got error in getting asic_name from CONFIG_DB DEVICE_METADATA" - - cfg_switch_type = metatbl.get("switch_type") - - # Portchannel record verifiation done in line card - if cfg_switch_type == "voq": - lc_switch_id = metatbl.get("switch_id") - assert lc_switch_id != "", "Got error in getting switch_id from CONFIG_DB DEVICE_METADATA" - if lc_switch_id == "0": - - # At this point we have 2 port channels test_lag1_name and test_lag2_name. - # These were created by the above two test cases. Now delete the PortChannel - # test_lag1_name and verify that the lag is removed and add test_lag3_name to - # test for lag id allocator allocating newly available lag id - - # Connect to app db: lag table and lag member table - app_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - psTbl_lag = swsscommon.ProducerStateTable(app_db, "LAG_TABLE") - psTbl_lagMember = swsscommon.ProducerStateTable(app_db, "LAG_MEMBER_TABLE") - - # Make sure presence of 2 port channels before deleting - asic_db = dvs.get_asic_db() - lagkeys = asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG", 2) - assert len(lagkeys) == 2, "Expected 2 PortChannels are not available" - - # Make sure presence of total of 1 lag member added in test_lag1_name - # No lag member added in test_lag2_name - lagmemberkeys = asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER", 1) - assert len(lagmemberkeys) == 1, "Expected 1 LAG members are not available" - - # Delete port channel member of PortChannel test_lag1_name - psTbl_lagMember.delete(f"{test_lag1_name}:{test_lag1_member}") - - # Verify the lag member is removed from asic db - lagmemberkeys = asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER", 0) - assert len(lagmemberkeys) == 0, "Deleted LAG member is not removed from asic db" - - # Delete PortChannel test_lag1_name - psTbl_lag.delete(f"{test_lag1_name}") - - # Verify deletion of the PorChannel - asic_db = dvs.get_asic_db() - lagkeys = asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG", 1) - assert len(lagkeys) == 1, "Two LAG entries in asic db even after deleting a PortChannel" - - # Create PortChannel test_lag3_name. This should be addedd successfully since deleting - # PortChannel test_lag1_name made a lag id available for allocation - fvs = swsscommon.FieldValuePairs([("admin", "up"), ("mtu", "9100")]) - psTbl_lag.set(f"{test_lag3_name}", fvs) - - # Verify creation of the additional PortChannel after making space for more - # PortChannels by deleting some PortChannels - asic_db = dvs.get_asic_db() - lagkeys = asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG", 2) - assert len(lagkeys) == 2, "Two configured LAG entries are not available in asic db" - - # Check for the presence of voq system port aggregate id attribute for 2 LAGs - lag_entry = asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_LAG", lagkeys[0]) - spa_id = lag_entry.get("SAI_LAG_ATTR_SYSTEM_PORT_AGGREGATE_ID") - assert spa_id != "", "VOQ System port aggregate id not present for the LAG 1" - - lag_entry = asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_LAG", lagkeys[1]) - spa_id = lag_entry.get("SAI_LAG_ATTR_SYSTEM_PORT_AGGREGATE_ID") - assert spa_id != "", "VOQ System port aggregate id not present for the LAG 2" - - # Now delete all the PortChannels so that we can veify the chassis app db - # clearing and remote asics clearing - psTbl_lag.delete(f"{test_lag2_name}") - - psTbl_lag.delete(f"{test_lag3_name}") - - # Verify deletion of all PortChannels - asic_db = dvs.get_asic_db() - lagkeys = asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG", 0) - assert len(lagkeys) == 0, "LAG entries in asic db even after deleting all PortChannels" - - break - - # Check syncing deletion of the PortChannels and PortChannel member in chasiss app db - for name in dvss.keys(): - if name.startswith("supervisor"): - dvs = dvss[name] - chassis_app_db = DVSDatabase(swsscommon.CHASSIS_APP_DB, dvs.redis_chassis_sock) - syslagkeys = chassis_app_db.wait_for_n_keys("SYSTEM_LAG_TABLE", 0) - assert len(syslagkeys) == 0, "Stale system lag entries in chassis app db" - - syslagmemberkeys = chassis_app_db.wait_for_n_keys("SYSTEM_LAG_MEMBER_TABLE", 0) - assert len(syslagmemberkeys) == 0, "Stale system lag member entries in chassis app db" - - break - - # Verify removal of remote system lag in non-owner line card - # Verify removal of system lag menbers in non-owner line card - for name in dvss.keys(): - dvs = dvss[name] - - config_db = dvs.get_config_db() - metatbl = config_db.get_entry("DEVICE_METADATA", "localhost") - - cfg_switch_type = metatbl.get("switch_type") - - # System LAG info verifiation done in non-owner line card - if cfg_switch_type == "voq": - lc_switch_id = metatbl.get("switch_id") - assert lc_switch_id != "", "Got error in getting switch_id from CONFIG_DB DEVICE_METADATA" - if lc_switch_id != "0": - # Linecard other than linecard 1 (owner line card) - asic_db = dvs.get_asic_db() - remotesyslagkeys = asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG", 0) - assert len(remotesyslagkeys) == 0, "Stale remote system lag entries in asic db" - - # Verify cleaning of system lag members - lagmemberkeys = asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER", 0) - assert len(lagmemberkeys) == 0, "Stale system lag member entries in asic db" - - break - - def test_chassis_add_remove_ports(self, vct): - """Test removing and adding a port in a VOQ chassis. - - Test validates that when a port is created the port is removed from the default vlan. - """ - dvss = vct.dvss - for name in dvss.keys(): - dvs = dvss[name] - buffer_model.enable_dynamic_buffer(dvs.get_config_db(), dvs.runcmd) - - config_db = dvs.get_config_db() - app_db = dvs.get_app_db() - asic_db = dvs.get_asic_db() - metatbl = config_db.get_entry("DEVICE_METADATA", "localhost") - cfg_switch_type = metatbl.get("switch_type") - - if cfg_switch_type == "voq": - num_ports = len(asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_PORT")) - # Get the port info we'll flap - port = config_db.get_keys('PORT')[0] - port_info = config_db.get_entry("PORT", port) - - # Remove port's other configs - pgs = config_db.get_keys('BUFFER_PG') - queues = config_db.get_keys('BUFFER_QUEUE') - for key in pgs: - if port in key: - config_db.delete_entry('BUFFER_PG', key) - app_db.wait_for_deleted_entry('BUFFER_PG_TABLE', key) - - for key in queues: - if port in key: - config_db.delete_entry('BUFFER_QUEUE', key) - app_db.wait_for_deleted_entry('BUFFER_QUEUE_TABLE', key) - - # Remove port - config_db.delete_entry('PORT', port) - app_db.wait_for_deleted_entry('PORT_TABLE', port) - num = asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_PORT", - num_ports) - assert len(num) == num_ports - - # Create port - config_db.update_entry("PORT", port, port_info) - app_db.wait_for_entry("PORT_TABLE", port) - num = asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_PORT", - num_ports) - assert len(num) == num_ports - - # Check that we see the logs for removing default vlan - _, logSeen = dvs.runcmd( [ "sh", "-c", - "awk STARTFILE/ENDFILE /var/log/syslog | grep 'removeDefaultVlanMembers: Remove 32 VLAN members from default VLAN' | wc -l"] ) - assert logSeen.strip() == "1" - - buffer_model.disable_dynamic_buffer(dvs.get_config_db(), dvs.runcmd) - - def test_voq_egress_queue_counter(self, vct): - if vct is None: - return - dvss = vct.dvss - dvs = None - for name in dvss.keys(): - if "supervisor" in name: - continue - dvs = dvss[name] - break - assert dvs - _, _ = dvs.runcmd("counterpoll queue enable") - - num_voqs_per_port = 8 - # vs-switch creates 20 queues per port. - num_queues_per_local_port = 20 - num_ports_per_linecard = 32 - num_local_ports = 32 - num_linecards = 3 - num_sysports = num_ports_per_linecard * num_linecards - num_egress_queues = num_local_ports * num_queues_per_local_port - num_voqs = ( num_ports_per_linecard * num_voqs_per_port * num_linecards ) - num_queues_to_be_polled = num_voqs + num_egress_queues - - flex_db = dvs.get_flex_db() - flex_db.wait_for_n_keys("FLEX_COUNTER_TABLE:QUEUE_STAT_COUNTER", num_queues_to_be_polled) - - def test_chassis_wred_profile_on_system_ports(self, vct): - """Test whether wred profile is applied on system ports in VoQ chassis. - """ - dvss = vct.dvss - for name in dvss.keys(): - dvs = dvss[name] - - config_db = dvs.get_config_db() - app_db = dvs.get_app_db() - asic_db = dvs.get_asic_db() - metatbl = config_db.get_entry("DEVICE_METADATA", "localhost") - cfg_switch_type = metatbl.get("switch_type") - - if cfg_switch_type == "voq": - # Get all the keys from SYTEM_PORT table and check whether wred_profile is applied properly - system_ports = config_db.get_keys('SYSTEM_PORT') - - for key in system_ports: - queue3 = key + '|' + '3' - queue_entry = config_db.get_entry('QUEUE', queue3) - wred_profile = queue_entry['wred_profile'] - if wred_profile != 'AZURE_LOSSLESS': - print("WRED profile not applied on queue3 on system port %s", key) - assert wred_profile == 'AZURE_LOSSLESS' - - queue4 = key + '|' + '4' - queue_entry = config_db.get_entry('QUEUE', queue4) - wred_profile = queue_entry['wred_profile'] - if wred_profile != 'AZURE_LOSSLESS': - print("WRED profile not applied on queue4 on system port %s", key) - assert wred_profile == 'AZURE_LOSSLESS' - - # Check that we see the logs for applying WRED_PROFILE on all system ports - matching_log = "SAI_QUEUE_ATTR_WRED_PROFILE_ID" - _, logSeen = dvs.runcmd([ "sh", "-c", - "awk STARTFILE/ENDFILE /var/log/swss/sairedis.rec | grep SAI_QUEUE_ATTR_WRED_PROFILE_ID | wc -l"]) - - # Total number of logs = (No of system ports * No of lossless priorities) - No of lossless priorities for CPU ports - assert logSeen.strip() == str(len(system_ports)*2 - 2) - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_vlan.py b/tests/test_vlan.py deleted file mode 100644 index 28d3de3a29..0000000000 --- a/tests/test_vlan.py +++ /dev/null @@ -1,540 +0,0 @@ -import distro -import pytest - -from distutils.version import StrictVersion -from dvslib.dvs_common import PollingConfig, wait_for_result - -@pytest.mark.usefixtures("testlog") -@pytest.mark.usefixtures('dvs_vlan_manager') -@pytest.mark.usefixtures('dvs_lag_manager') -class TestVlan(object): - - def check_syslog(self, dvs, marker, process, err_log, vlan_str, expected_cnt): - (_, num) = dvs.runcmd( - ["sh", - "-c", - "awk '/{}/,ENDFILE {{print;}}' /var/log/syslog \ - | grep {} \ - | grep \"{}\" \ - | grep -i \"{}\" \ - | wc -l".format(marker, process, err_log, vlan_str)]) - - assert num.strip() == str(expected_cnt) - - def test_VlanAddRemove(self, dvs): - - vlan = "2" - interface = "Ethernet0" - - self.dvs_vlan.create_vlan(vlan) - vlan_oid = self.dvs_vlan.get_and_verify_vlan_ids(1)[0] - self.dvs_vlan.verify_vlan(vlan_oid, vlan) - - self.dvs_vlan.create_vlan_member(vlan, interface) - self.dvs_vlan.verify_vlan_member(vlan_oid, interface) - - # Verify the physical port configuration - member_port = self.dvs_vlan.asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_PORT", - dvs.asic_db.port_name_map[interface]) - assert member_port.get("SAI_PORT_ATTR_PORT_VLAN_ID") == vlan - - # Verify the host interface configuration - member_iface = self.dvs_vlan.asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_HOSTIF", - dvs.asic_db.hostif_name_map[interface]) - assert member_iface.get("SAI_HOSTIF_ATTR_VLAN_TAG") == "SAI_HOSTIF_VLAN_TAG_KEEP" - - self.dvs_vlan.remove_vlan_member(vlan, interface) - self.dvs_vlan.get_and_verify_vlan_member_ids(0) - - self.dvs_vlan.remove_vlan(vlan) - self.dvs_vlan.get_and_verify_vlan_ids(0) - - def test_MultipleVlan(self, dvs): - - def _create_vlan_members(vlan, member_list): - for member in member_list: - self.dvs_vlan.create_vlan_member(vlan, member) - - def _remove_vlan_members(vlan, member_list): - for member in member_list: - self.dvs_vlan.remove_vlan_member(vlan, member) - - vlan1 = "18" - vlan1_members = ["Ethernet0", "Ethernet4", "Ethernet8"] - vlan2 = "188" - vlan2_members = ["Ethernet20", "Ethernet24", "Ethernet28"] - - self.dvs_vlan.create_vlan(vlan1) - _create_vlan_members(vlan1, vlan1_members) - - self.dvs_vlan.get_and_verify_vlan_ids(1) - self.dvs_vlan.get_and_verify_vlan_member_ids(3) - - _remove_vlan_members(vlan1, vlan1_members) - - self.dvs_vlan.get_and_verify_vlan_member_ids(0) - - self.dvs_vlan.create_vlan(vlan2) - _create_vlan_members(vlan2, vlan2_members) - - self.dvs_vlan.get_and_verify_vlan_ids(2) - self.dvs_vlan.get_and_verify_vlan_member_ids(3) - - _create_vlan_members(vlan1, vlan1_members) - - self.dvs_vlan.get_and_verify_vlan_member_ids(6) - - _remove_vlan_members(vlan1, vlan1_members) - - self.dvs_vlan.get_and_verify_vlan_member_ids(3) - - _remove_vlan_members(vlan2, vlan2_members) - - self.dvs_vlan.get_and_verify_vlan_member_ids(0) - - # Member ports should have been detached from master bridge port - for member in vlan2_members: - _, output = dvs.runcmd(['sh', '-c', "ip link show {}".format(member)]) - assert "master" not in output - - self.dvs_vlan.remove_vlan(vlan1) - self.dvs_vlan.get_and_verify_vlan_ids(1) - - self.dvs_vlan.remove_vlan(vlan2) - self.dvs_vlan.get_and_verify_vlan_ids(0) - - def test_VlanIncrementalConfig(self, dvs): - - # TODO: add_ip_address has a dependency on cdb within dvs, - # so we still need to setup the db. This should be refactored. - dvs.setup_db() - - vlan = "2" - vlan_interface = "Vlan{}".format(vlan) - interface = "Ethernet0" - ip = "20.0.0.8/29" - initial_mtu = "9100" - new_mtu = "8888" - - self.dvs_vlan.create_vlan(vlan) - - vlan_oid = self.dvs_vlan.get_and_verify_vlan_ids(1)[0] - self.dvs_vlan.verify_vlan(vlan_oid, vlan) - - self.dvs_vlan.create_vlan_member(vlan, interface) - self.dvs_vlan.verify_vlan_member(vlan_oid, interface) - - dvs.add_ip_address(vlan_interface, ip) - - # Separate the VLAN interface from the Loopback interface - vlan_rif = None - intf_entries = self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE", 2) - for key in intf_entries: - fvs = self.dvs_vlan.asic_db.wait_for_entry("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE", key) - - if fvs.get("SAI_ROUTER_INTERFACE_ATTR_TYPE") == "SAI_ROUTER_INTERFACE_TYPE_VLAN": - assert fvs.get("SAI_ROUTER_INTERFACE_ATTR_MTU") == initial_mtu - vlan_rif = key - - assert vlan_rif - - dvs.set_mtu(vlan_interface, new_mtu) - self.dvs_vlan.asic_db.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE", - vlan_rif, - {"SAI_ROUTER_INTERFACE_ATTR_MTU": new_mtu}) - - dvs.set_interface_status(vlan_interface, "down") - self.dvs_vlan.app_db.wait_for_field_match("VLAN_TABLE", vlan_interface, {"admin_status": "down"}) - - dvs.set_interface_status(vlan_interface, "up") - self.dvs_vlan.app_db.wait_for_field_match("VLAN_TABLE", vlan_interface, {"admin_status": "up"}) - - dvs.remove_ip_address(vlan_interface, ip) - self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE", 1) - - self.dvs_vlan.remove_vlan_member(vlan, interface) - self.dvs_vlan.get_and_verify_vlan_member_ids(0) - - self.dvs_vlan.remove_vlan(vlan) - self.dvs_vlan.get_and_verify_vlan_ids(0) - - @pytest.mark.skipif(StrictVersion(distro.linux_distribution()[1]) <= StrictVersion('8.9'), - reason="Debian 8.9 or before has no support") - @pytest.mark.parametrize("test_input, expected", [ - (["Vla", "2"], 0), - (["VLAN", "3"], 0), - (["vlan", "4"], 0), - (["Vlan", "5"], 1), - ]) - - def test_AddVlanWithIncorrectKeyPrefix(self, dvs, test_input, expected): - - marker = dvs.add_log_marker() - - vlan_id = test_input[1] - vlan = "{}{}".format(test_input[0], vlan_id) - - self.dvs_vlan.config_db.create_entry("VLAN", vlan, {"vlanid": vlan_id}) - vlan_entries = self.dvs_vlan.get_and_verify_vlan_ids(expected) - - if not vlan_entries: - # If no VLAN is created, we should see the error in the logs - # TODO: refactor to use loganalyzer - self.check_syslog(dvs, marker, "vlanmgrd", "Invalid key format. No 'Vlan' prefix:", vlan, 1) - else: - self.dvs_vlan.remove_vlan(vlan_id) - self.dvs_vlan.get_and_verify_vlan_ids(0) - - @pytest.mark.skipif(StrictVersion(distro.linux_distribution()[1]) <= StrictVersion('8.9'), - reason="Debian 8.9 or before has no support") - @pytest.mark.parametrize("test_input, expected", [ - (["Vlan", "abc"], 0), - (["Vlan", "a3"], 0), - (["Vlan", ""], 0), - (["Vlan", "5"], 1), - ]) - def test_AddVlanWithIncorrectValueType(self, dvs, test_input, expected): - - marker = dvs.add_log_marker() - - vlan_id = test_input[1] - vlan = "{}{}".format(test_input[0], vlan_id) - - self.dvs_vlan.config_db.create_entry("VLAN", vlan, {"vlanid": vlan_id}) - vlan_entries = self.dvs_vlan.get_and_verify_vlan_ids(expected) - - if not vlan_entries: - # If no VLAN is created, we should see the error in the logs - # TODO: refactor to use loganalyzer - self.check_syslog(dvs, marker, "vlanmgrd", - "Invalid key format. Not a number after \'Vlan\' prefix:", vlan, 1) - else: - self.dvs_vlan.remove_vlan(vlan_id) - self.dvs_vlan.get_and_verify_vlan_ids(0) - - def test_AddPortChannelToVlan(self, dvs): - - vlan = "2" - lag_member = "Ethernet0" - lag_id = "0001" - lag_interface = "PortChannel{}".format(lag_id) - - self.dvs_lag.create_port_channel(lag_id) - lag_entries = self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG", 1) - - self.dvs_lag.create_port_channel_member(lag_id, lag_member) - - # Verify the LAG has been initialized properly - lag_member_entries = self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER", 1) - fvs = self.dvs_vlan.asic_db.wait_for_entry("ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER", lag_member_entries[0]) - assert len(fvs) == 4 - assert fvs.get("SAI_LAG_MEMBER_ATTR_LAG_ID") == lag_entries[0] - assert self.dvs_vlan.asic_db.port_to_id_map[fvs.get("SAI_LAG_MEMBER_ATTR_PORT_ID")] == lag_member - - self.dvs_vlan.create_vlan(vlan) - self.dvs_vlan.get_and_verify_vlan_ids(1) - - self.dvs_vlan.create_vlan_member(vlan, lag_interface, "tagged") - self.dvs_vlan.get_and_verify_vlan_member_ids(1) - - self.dvs_vlan.remove_vlan_member(vlan, lag_interface) - self.dvs_vlan.get_and_verify_vlan_member_ids(0) - - self.dvs_vlan.remove_vlan(vlan) - self.dvs_vlan.get_and_verify_vlan_ids(0) - - self.dvs_lag.remove_port_channel_member(lag_id, lag_member) - self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER", 0) - - self.dvs_lag.remove_port_channel(lag_id) - self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG", 0) - - def test_AddVlanMemberWithNonExistVlan(self, dvs): - - vlan = "2" - interface = "Ethernet0" - - self.dvs_vlan.create_vlan_member(vlan, interface) - - # Nothing should be created because there's no VLAN - self.dvs_vlan.get_and_verify_vlan_member_ids(0) - self.dvs_vlan.get_and_verify_vlan_ids(0) - - self.dvs_vlan.remove_vlan_member(vlan, interface) - - def test_RemoveNonexistentVlan(self, dvs): - - vlan = "2" - - self.dvs_vlan.get_and_verify_vlan_ids(0) - - self.dvs_vlan.remove_vlan(vlan) - - # Verify that we're still able to create the VLAN after "deleting" it - self.dvs_vlan.create_vlan(vlan) - self.dvs_vlan.get_and_verify_vlan_ids(1) - - self.dvs_vlan.remove_vlan(vlan) - self.dvs_vlan.get_and_verify_vlan_ids(0) - - @pytest.mark.skipif(StrictVersion(distro.linux_distribution()[1]) <= StrictVersion('8.9'), - reason="Debian 8.9 or before has no support") - @pytest.mark.parametrize("test_input, expected", [ - (["tagging_mode", "untagged"], [1, "SAI_VLAN_TAGGING_MODE_UNTAGGED"]), - (["tagging_mode", "tagged"], [1, "SAI_VLAN_TAGGING_MODE_TAGGED"]), - (["tagging_mode", "priority_tagged"], [1, "SAI_VLAN_TAGGING_MODE_PRIORITY_TAGGED"]), - (["tagging_mode", "unexpected_mode"], [0, ""]), - (["no_tag_mode", ""], [1, "SAI_VLAN_TAGGING_MODE_UNTAGGED"]), - ]) - - def test_VlanMemberTaggingMode(self, dvs, test_input, expected): - - marker = dvs.add_log_marker() - - if test_input[0] == "no_tag_mode": - tagging_mode = None - else: - tagging_mode = test_input[1] - - vlan = "2" - interface = "Ethernet0" - - self.dvs_vlan.create_vlan(vlan) - vlan_oid = self.dvs_vlan.get_and_verify_vlan_ids(1)[0] - - self.dvs_vlan.create_vlan_member(vlan, interface, tagging_mode) - vlan_member_entries = self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER", expected[0]) - - if len(vlan_member_entries) == 1: - self.dvs_vlan.verify_vlan_member(vlan_oid, interface, expected[1]) - else: - # If no VLAN is created, we should see the error in the logs - # TODO: refactor to use loganalyzer - self.check_syslog(dvs, marker, "vlanmgrd", "Wrong tagging_mode", test_input, 1) - - self.dvs_vlan.remove_vlan_member(vlan, interface) - self.dvs_vlan.get_and_verify_vlan_member_ids(0) - - self.dvs_vlan.remove_vlan(vlan) - self.dvs_vlan.get_and_verify_vlan_ids(0) - - @pytest.mark.skip(reason="AddMaxVlan takes too long to execute") - def test_AddMaxVlan(self, dvs): - - max_poll = PollingConfig(polling_interval=3, timeout=300, strict=True) - - min_vid = 2 - max_vid = 4094 - - for vlan in range(min_vid, max_vid + 1): - self.dvs_vlan.create_vlan(str(vlan)) - - self.dvs_vlan.get_and_verify_vlan_ids(max_vid - 1, polling_config=max_poll) - - for vlan in range(min_vid, max_vid + 1): - self.dvs_vlan.remove_vlan(str(vlan)) - - self.dvs_vlan.get_and_verify_vlan_ids(0, polling_config=max_poll) - - def test_RemoveVlanWithRouterInterface(self, dvs): - # TODO: add_ip_address has a dependency on cdb within dvs, - # so we still need to setup the db. This should be refactored. - dvs.setup_db() - - vlan = "100" - vlan_interface = "Vlan{}".format(vlan) - ip = "20.0.0.8/29" - - self.dvs_vlan.create_vlan(vlan) - vlan_oid = self.dvs_vlan.get_and_verify_vlan_ids(1)[0] - self.dvs_vlan.verify_vlan(vlan_oid, vlan) - - dvs.add_ip_address(vlan_interface, ip) - - # Should see 1 VLAN interface and 1 Loopback interface - self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE", 2) - - self.dvs_vlan.remove_vlan(vlan) - - # VLAN should still be preserved since the RIF depends on it - vlan_oid = self.dvs_vlan.get_and_verify_vlan_ids(1)[0] - self.dvs_vlan.verify_vlan(vlan_oid, vlan) - - dvs.remove_ip_address(vlan_interface, ip) - self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE", 1) - - self.dvs_vlan.remove_vlan(vlan) - - self.dvs_vlan.get_and_verify_vlan_ids(0) - - def test_VlanDbData(self, dvs): - vlan = "2" - - self.dvs_vlan.create_vlan(vlan) - - vlan_oid = self.dvs_vlan.app_db.wait_for_n_keys("VLAN_TABLE", 1)[0] - fvs = self.dvs_vlan.app_db.wait_for_entry("VLAN_TABLE", vlan_oid) - self.dvs_vlan.check_app_db_vlan_fields(fvs) - - vlan_oid = self.dvs_vlan.state_db.wait_for_n_keys("VLAN_TABLE", 1)[0] - fvs = self.dvs_vlan.state_db.wait_for_entry("VLAN_TABLE", vlan_oid) - self.dvs_vlan.check_state_db_vlan_fields(fvs) - - vlan_oid = self.dvs_vlan.get_and_verify_vlan_ids(1)[0] - self.dvs_vlan.verify_vlan(vlan_oid, vlan) - - self.dvs_vlan.remove_vlan(vlan) - - @pytest.mark.skipif(StrictVersion(distro.linux_distribution()[1]) <= StrictVersion('8.9'), - reason="Debian 8.9 or before has no support") - @pytest.mark.parametrize("test_input, expected", [ - (["untagged"], ["SAI_VLAN_TAGGING_MODE_UNTAGGED"]), - (["tagged"], ["SAI_VLAN_TAGGING_MODE_TAGGED"]), - (["priority_tagged"], ["SAI_VLAN_TAGGING_MODE_PRIORITY_TAGGED"]), - ]) - def test_VlanMemberDbData(self, dvs, test_input, expected): - - vlan = "2" - interface = "Ethernet0" - tagging_mode = test_input[0] - - self.dvs_vlan.create_vlan(vlan) - - self.dvs_vlan.create_vlan_member(vlan, interface, tagging_mode) - - vlan_oid = self.dvs_vlan.app_db.wait_for_n_keys("VLAN_MEMBER_TABLE", 1)[0] - fvs = self.dvs_vlan.app_db.wait_for_entry("VLAN_MEMBER_TABLE", vlan_oid) - self.dvs_vlan.check_app_db_vlan_member_fields(fvs, tagging_mode) - - vlan_oid = self.dvs_vlan.state_db.wait_for_n_keys("VLAN_MEMBER_TABLE", 1)[0] - fvs = self.dvs_vlan.state_db.wait_for_entry("VLAN_MEMBER_TABLE", vlan_oid) - self.dvs_vlan.check_state_db_vlan_member_fields(fvs) - - vlan_oid = self.dvs_vlan.get_and_verify_vlan_ids(1)[0] - self.dvs_vlan.verify_vlan_member(vlan_oid, interface, expected[0]) - - self.dvs_vlan.remove_vlan_member(vlan, interface) - self.dvs_vlan.get_and_verify_vlan_member_ids(0) - - self.dvs_vlan.remove_vlan(vlan) - self.dvs_vlan.get_and_verify_vlan_ids(0) - - def test_VlanHostIf(self, dvs): - - vlan = "2" - hostif_name = "MonVlan2" - - self.dvs_vlan.create_vlan(vlan) - vlan_oid = self.dvs_vlan.get_and_verify_vlan_ids(1)[0] - self.dvs_vlan.verify_vlan(vlan_oid, vlan) - - self.dvs_vlan.create_vlan_hostif(vlan, hostif_name) - hostif_oid = self.dvs_vlan.get_and_verify_vlan_hostif_ids(len(dvs.asic_db.hostif_name_map)) - self.dvs_vlan.verify_vlan_hostif(hostif_name, hostif_oid, vlan_oid) - - self.dvs_vlan.remove_vlan(vlan) - self.dvs_vlan.get_and_verify_vlan_ids(0) - self.dvs_vlan.get_and_verify_vlan_hostif_ids(len(dvs.asic_db.hostif_name_map) - 1) - - def test_VlanGratArp(self, dvs): - def arp_accept_enabled(): - rc, res = dvs.runcmd("cat /proc/sys/net/ipv4/conf/Vlan{}/arp_accept".format(vlan)) - return (res.strip("\n") == "1", res) - - def arp_accept_disabled(): - rc, res = dvs.runcmd("cat /proc/sys/net/ipv4/conf/Vlan{}/arp_accept".format(vlan)) - return (res.strip("\n") == "0", res) - - vlan = "2" - self.dvs_vlan.create_vlan(vlan) - self.dvs_vlan.create_vlan_interface(vlan) - self.dvs_vlan.set_vlan_intf_property(vlan, "grat_arp", "enabled") - - wait_for_result(arp_accept_enabled, PollingConfig(), "IPv4 arp_accept not enabled") - - # Not currently possible to test `accept_untracked_na` as it doesn't exist in the kernel for - # our test VMs (only present in kernels 5.19 and above) - - self.dvs_vlan.set_vlan_intf_property(vlan, "grat_arp", "disabled") - - wait_for_result(arp_accept_disabled, PollingConfig(), "IPv4 arp_accept not disabled") - - self.dvs_vlan.remove_vlan_interface(vlan) - self.dvs_vlan.remove_vlan(vlan) - self.dvs_vlan.get_and_verify_vlan_ids(0) - - def test_VlanProxyArp(self, dvs): - - def proxy_arp_enabled(): - rc, proxy_arp_res = dvs.runcmd("cat /proc/sys/net/ipv4/conf/Vlan{}/proxy_arp".format(vlan)) - rc, pvlan_res = dvs.runcmd("cat /proc/sys/net/ipv4/conf/Vlan{}/proxy_arp_pvlan".format(vlan)) - - return (proxy_arp_res.strip("\n") == "1" and pvlan_res.strip("\n") == "1", (proxy_arp_res, pvlan_res)) - - def proxy_arp_disabled(): - rc, proxy_arp_res = dvs.runcmd("cat /proc/sys/net/ipv4/conf/Vlan{}/proxy_arp".format(vlan)) - rc, pvlan_res = dvs.runcmd("cat /proc/sys/net/ipv4/conf/Vlan{}/proxy_arp_pvlan".format(vlan)) - - return (proxy_arp_res.strip("\n") == "0" and pvlan_res.strip("\n") == "0", (proxy_arp_res, pvlan_res)) - - vlan = "2" - self.dvs_vlan.create_vlan(vlan) - self.dvs_vlan.create_vlan_interface(vlan) - self.dvs_vlan.set_vlan_intf_property(vlan, "proxy_arp", "enabled") - - wait_for_result(proxy_arp_enabled, PollingConfig(), 'IPv4 proxy_arp or proxy_arp_pvlan not enabled') - - self.dvs_vlan.set_vlan_intf_property(vlan, "proxy_arp", "disabled") - - wait_for_result(proxy_arp_disabled, PollingConfig(), 'IPv4 proxy_arp or proxy_arp_pvlan not disabled') - - self.dvs_vlan.remove_vlan_interface(vlan) - self.dvs_vlan.remove_vlan(vlan) - self.dvs_vlan.get_and_verify_vlan_ids(0) - - def test_VlanMemberLinkDown(self, dvs): - - # TODO: add_ip_address has a dependency on cdb within dvs, - # so we still need to setup the db. This should be refactored. - dvs.setup_db() - - vlan = "1000" - vlan_ip = "192.168.0.1/21" - interface = "Ethernet0" - vlan_interface = "Vlan%s" % vlan - server_ip = "192.168.0.100" - vlan_intf_sysctl_param_path = "/proc/sys/net/ipv4/conf/%s/arp_evict_nocarrier" % vlan_interface - - self.dvs_vlan.create_vlan(vlan) - vlan_oid = self.dvs_vlan.get_and_verify_vlan_ids(1)[0] - self.dvs_vlan.verify_vlan(vlan_oid, vlan) - self.dvs_vlan.create_vlan_member(vlan, interface) - self.dvs_vlan.verify_vlan_member(vlan_oid, interface) - dvs.set_interface_status(interface, "up") - dvs.add_ip_address(vlan_interface, vlan_ip) - dvs.runcmd("ip neigh replace %s lladdr 11:22:33:44:55:66 dev %s nud stale" % (server_ip, vlan_interface)) - - neigh_oid = self.dvs_vlan.app_db.wait_for_n_keys("NEIGH_TABLE", 1)[0] - assert vlan_interface in neigh_oid and server_ip in neigh_oid - - # NOTE: arp_evict_nocarrier is available for kernel >= v5.16 and current - # docker-sonic-vs is based on kernel v5.4.0, so test only if this sysctl - # param is present - rc, res = dvs.runcmd("cat %s" % vlan_intf_sysctl_param_path) - if rc == 0: - assert res.strip() == "0" - dvs.set_interface_status(interface, "down") - neigh_oid = self.dvs_vlan.app_db.wait_for_n_keys("NEIGH_TABLE", 1)[0] - assert vlan_interface in neigh_oid and server_ip in neigh_oid - - dvs.runcmd("ip neigh flush all") - dvs.remove_ip_address(vlan_interface, vlan_ip) - self.dvs_vlan.remove_vlan_member(vlan, interface) - self.dvs_vlan.get_and_verify_vlan_member_ids(0) - self.dvs_vlan.remove_vlan(vlan) - self.dvs_vlan.get_and_verify_vlan_ids(0) - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_vnet.py b/tests/test_vnet.py deleted file mode 100644 index c28d7cf320..0000000000 --- a/tests/test_vnet.py +++ /dev/null @@ -1,3530 +0,0 @@ -import time -import json -import random -import time -import pytest - -from swsscommon import swsscommon -from pprint import pprint -from dvslib.dvs_common import wait_for_result - - -def create_entry(tbl, key, pairs): - fvs = swsscommon.FieldValuePairs(pairs) - tbl.set(key, fvs) - time.sleep(1) - - -def create_entry_tbl(db, table, separator, key, pairs): - tbl = swsscommon.Table(db, table) - create_entry(tbl, key, pairs) - - -def create_entry_pst(db, table, separator, key, pairs): - tbl = swsscommon.ProducerStateTable(db, table) - create_entry(tbl, key, pairs) - - -def delete_entry_tbl(db, table, key): - tbl = swsscommon.Table(db, table) - tbl._del(key) - time.sleep(1) - - -def delete_entry_pst(db, table, key): - tbl = swsscommon.ProducerStateTable(db, table) - tbl._del(key) - time.sleep(1) - - -def how_many_entries_exist(db, table): - tbl = swsscommon.Table(db, table) - return len(tbl.getKeys()) - - -def entries(db, table): - tbl = swsscommon.Table(db, table) - return set(tbl.getKeys()) - - -def get_exist_entries(dvs, table): - db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - tbl = swsscommon.Table(db, table) - return set(tbl.getKeys()) - - -def get_created_entry(db, table, existed_entries): - tbl = swsscommon.Table(db, table) - entries = set(tbl.getKeys()) - new_entries = list(entries - existed_entries) - assert len(new_entries) == 1, "Wrong number of created entries." - return new_entries[0] - - -def get_all_created_entries(db, table, existed_entries): - tbl = swsscommon.Table(db, table) - entries = set(tbl.getKeys()) - new_entries = list(entries - set(existed_entries)) - assert len(new_entries) >= 0, "Get all could be no new created entries." - new_entries.sort() - return new_entries - - -def get_created_entries(db, table, existed_entries, count): - new_entries = get_all_created_entries(db, table, existed_entries) - assert len(new_entries) == count, "Wrong number of created entries." - return new_entries - - -def get_deleted_entries(db, table, existed_entries, count): - tbl = swsscommon.Table(db, table) - entries = set(tbl.getKeys()) - old_entries = list(existed_entries - entries) - assert len(old_entries) == count, "Wrong number of deleted entries." - old_entries.sort() - return old_entries - - -def get_default_vr_id(dvs): - db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - table = 'ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER' - tbl = swsscommon.Table(db, table) - keys = tbl.getKeys() - assert len(keys) == 1, "Wrong number of virtual routers found" - - return keys[0] - - -def check_object(db, table, key, expected_attributes): - tbl = swsscommon.Table(db, table) - keys = tbl.getKeys() - assert key in keys, "The desired key is not presented" - - status, fvs = tbl.get(key) - assert status, "Got an error when get a key" - - assert len(fvs) >= len(expected_attributes), "Incorrect attributes" - - attr_keys = {entry[0] for entry in fvs} - - for name, value in fvs: - if name in expected_attributes: - assert expected_attributes[name] == value, "Wrong value %s for the attribute %s = %s" % \ - (value, name, expected_attributes[name]) - -def check_deleted_object(db, table, key): - tbl = swsscommon.Table(db, table) - keys = tbl.getKeys() - assert key not in keys, "The desired key is not removed" - - -def create_vnet_local_routes(dvs, prefix, vnet_name, ifname): - conf_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - - create_entry_tbl( - conf_db, - "VNET_ROUTE", '|', "%s|%s" % (vnet_name, prefix), - [ - ("ifname", ifname), - ] - ) - - time.sleep(2) - - -def delete_vnet_local_routes(dvs, prefix, vnet_name): - app_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - - delete_entry_pst(app_db, "VNET_ROUTE_TABLE", "%s:%s" % (vnet_name, prefix)) - - time.sleep(2) - - -def create_vnet_routes(dvs, prefix, vnet_name, endpoint, mac="", vni=0, ep_monitor="", profile="", primary="", monitoring="", adv_prefix=""): - set_vnet_routes(dvs, prefix, vnet_name, endpoint, mac=mac, vni=vni, ep_monitor=ep_monitor, profile=profile, primary=primary, monitoring=monitoring, adv_prefix=adv_prefix) - - -def set_vnet_routes(dvs, prefix, vnet_name, endpoint, mac="", vni=0, ep_monitor="", profile="", primary="", monitoring="", adv_prefix=""): - conf_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - - attrs = [ - ("endpoint", endpoint), - ] - - if vni: - attrs.append(('vni', vni)) - - if mac: - attrs.append(('mac_address', mac)) - - if ep_monitor: - attrs.append(('endpoint_monitor', ep_monitor)) - - if profile: - attrs.append(('profile', profile)) - - if primary: - attrs.append(('primary', primary)) - - if monitoring: - attrs.append(('monitoring', monitoring)) - - if adv_prefix: - attrs.append(('adv_prefix', adv_prefix)) - - tbl = swsscommon.Table(conf_db, "VNET_ROUTE_TUNNEL") - fvs = swsscommon.FieldValuePairs(attrs) - tbl.set("%s|%s" % (vnet_name, prefix), fvs) - - time.sleep(2) - - -def delete_vnet_routes(dvs, prefix, vnet_name): - app_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - - delete_entry_pst(app_db, "VNET_ROUTE_TUNNEL_TABLE", "%s:%s" % (vnet_name, prefix)) - - time.sleep(2) - - -def create_vlan(dvs, vlan_name, vlan_ids): - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - conf_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - - vlan_id = vlan_name[4:] - - # create vlan - create_entry_tbl( - conf_db, - "VLAN", '|', vlan_name, - [ - ("vlanid", vlan_id), - ], - ) - - time.sleep(1) - - vlan_oid = get_created_entry(asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN", vlan_ids) - - check_object(asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN", vlan_oid, - { - "SAI_VLAN_ATTR_VLAN_ID": vlan_id, - } - ) - - return vlan_oid - - -def create_vlan_interface(dvs, vlan_name, ifname, vnet_name, ipaddr): - conf_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - - vlan_ids = get_exist_entries(dvs, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - - vlan_oid = create_vlan (dvs, vlan_name, vlan_ids) - - # create a vlan member in config db - create_entry_tbl( - conf_db, - "VLAN_MEMBER", '|', "%s|%s" % (vlan_name, ifname), - [ - ("tagging_mode", "untagged"), - ], - ) - - time.sleep(1) - - # create vlan interface in config db - create_entry_tbl( - conf_db, - "VLAN_INTERFACE", '|', vlan_name, - [ - ("vnet_name", vnet_name), - ("proxy_arp", "enabled"), - ], - ) - - #FIXME - This is created by IntfMgr - app_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - create_entry_pst( - app_db, - "INTF_TABLE", ':', vlan_name, - [ - ("vnet_name", vnet_name), - ("proxy_arp", "enabled"), - ], - ) - time.sleep(2) - - create_entry_tbl( - conf_db, - "VLAN_INTERFACE", '|', "%s|%s" % (vlan_name, ipaddr), - [ - ("family", "IPv4"), - ], - ) - - time.sleep(2) - - return vlan_oid - - -def delete_vlan_interface(dvs, ifname, ipaddr): - conf_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - - delete_entry_tbl(conf_db, "VLAN_INTERFACE", "%s|%s" % (ifname, ipaddr)) - - time.sleep(2) - - delete_entry_tbl(conf_db, "VLAN_INTERFACE", ifname) - - time.sleep(2) - - -def create_phy_interface(dvs, ifname, vnet_name, ipaddr): - conf_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - - exist_rifs = get_exist_entries(dvs, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") - - # create vlan interface in config db - create_entry_tbl( - conf_db, - "INTERFACE", '|', ifname, - [ - ("vnet_name", vnet_name), - ], - ) - - #FIXME - This is created by IntfMgr - app_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - create_entry_pst( - app_db, - "INTF_TABLE", ':', ifname, - [ - ("vnet_name", vnet_name), - ], - ) - time.sleep(2) - - create_entry_tbl( - conf_db, - "INTERFACE", '|', "%s|%s" % (ifname, ipaddr), - [ - ("family", "IPv4"), - ], - ) - - -def delete_phy_interface(dvs, ifname, ipaddr): - conf_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - - delete_entry_tbl(conf_db, "INTERFACE", "%s|%s" % (ifname, ipaddr)) - - time.sleep(2) - - delete_entry_tbl(conf_db, "INTERFACE", ifname) - - time.sleep(2) - - -def create_vnet_entry(dvs, name, tunnel, vni, peer_list, scope="", advertise_prefix=False, overlay_dmac=""): - conf_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - - attrs = [ - ("vxlan_tunnel", tunnel), - ("vni", vni), - ("peer_list", peer_list), - ] - - if scope: - attrs.append(('scope', scope)) - - if advertise_prefix: - attrs.append(('advertise_prefix', 'true')) - - if overlay_dmac: - attrs.append(('overlay_dmac', overlay_dmac)) - - # create the VXLAN tunnel Term entry in Config DB - create_entry_tbl( - conf_db, - "VNET", '|', name, - attrs, - ) - - time.sleep(2) - - -def delete_vnet_entry(dvs, name): - conf_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - - delete_entry_tbl(conf_db, "VNET", "%s" % (name)) - - time.sleep(2) - - -def create_vxlan_tunnel(dvs, name, src_ip): - conf_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - - attrs = [ - ("src_ip", src_ip), - ] - - # create the VXLAN tunnel Term entry in Config DB - create_entry_tbl( - conf_db, - "VXLAN_TUNNEL", '|', name, - attrs, - ) - -def delete_vxlan_tunnel(dvs, name): - conf_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - delete_entry_tbl(conf_db, "VXLAN_TUNNEL", name) - -def create_vxlan_tunnel_map(dvs, tunnel_name, tunnel_map_entry_name, vlan, vni_id): - conf_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - - # create the VXLAN tunnel map entry in Config DB - create_entry_tbl( - conf_db, - "VXLAN_TUNNEL_MAP", '|', "%s|%s" % (tunnel_name, tunnel_map_entry_name), - [ - ("vni", vni_id), - ("vlan", vlan), - ], - ) - - -def get_lo(dvs): - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - vr_id = get_default_vr_id(dvs) - - tbl = swsscommon.Table(asic_db, 'ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE') - - entries = tbl.getKeys() - lo_id = None - for entry in entries: - status, fvs = tbl.get(entry) - assert status, "Got an error when get a key" - for key, value in fvs: - if key == 'SAI_ROUTER_INTERFACE_ATTR_TYPE' and value == 'SAI_ROUTER_INTERFACE_TYPE_LOOPBACK': - lo_id = entry - break - else: - assert False, 'Don\'t found loopback id' - - return lo_id - - -def get_switch_mac(dvs): - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - - tbl = swsscommon.Table(asic_db, 'ASIC_STATE:SAI_OBJECT_TYPE_SWITCH') - - entries = tbl.getKeys() - mac = None - for entry in entries: - status, fvs = tbl.get(entry) - assert status, "Got an error when get a key" - for key, value in fvs: - if key == 'SAI_SWITCH_ATTR_SRC_MAC_ADDRESS': - mac = value - break - else: - assert False, 'Don\'t found switch mac' - - return mac - - -def check_linux_intf_arp_proxy(dvs, ifname): - (exitcode, out) = dvs.runcmd("cat /proc/sys/net/ipv4/conf/{0}/proxy_arp_pvlan".format(ifname)) - assert out != "1", "ARP proxy is not enabled for VNET interface in Linux kernel" - - -def update_bfd_session_state(dvs, addr, state): - bfd_id = get_bfd_session_id(dvs, addr) - assert bfd_id is not None - - bfd_sai_state = {"Admin_Down": "SAI_BFD_SESSION_STATE_ADMIN_DOWN", - "Down": "SAI_BFD_SESSION_STATE_DOWN", - "Init": "SAI_BFD_SESSION_STATE_INIT", - "Up": "SAI_BFD_SESSION_STATE_UP"} - - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - ntf = swsscommon.NotificationProducer(asic_db, "NOTIFICATIONS") - fvp = swsscommon.FieldValuePairs() - ntf_data = "[{\"bfd_session_id\":\""+bfd_id+"\",\"session_state\":\""+bfd_sai_state[state]+"\"}]" - ntf.send("bfd_session_state_change", ntf_data, fvp) - -def update_monitor_session_state(dvs, addr, monitor, state): - state_db = swsscommon.DBConnector(swsscommon.STATE_DB, dvs.redis_sock, 0) - create_entry_tbl( - state_db, - "VNET_MONITOR_TABLE", '|', "%s|%s" % (monitor,addr), - [ - ("state", state), - ] - ) - -def get_bfd_session_id(dvs, addr): - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - tbl = swsscommon.Table(asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_BFD_SESSION") - entries = set(tbl.getKeys()) - for entry in entries: - status, fvs = tbl.get(entry) - fvs = dict(fvs) - assert status, "Got an error when get a key" - if fvs["SAI_BFD_SESSION_ATTR_DST_IP_ADDRESS"] == addr and fvs["SAI_BFD_SESSION_ATTR_MULTIHOP"] == "true": - return entry - - return None - - -def check_del_bfd_session(dvs, addrs): - for addr in addrs: - assert get_bfd_session_id(dvs, addr) is None - - -def check_bfd_session(dvs, addrs): - for addr in addrs: - assert get_bfd_session_id(dvs, addr) is not None - - -def check_state_db_routes(dvs, vnet, prefix, endpoints): - state_db = swsscommon.DBConnector(swsscommon.STATE_DB, dvs.redis_sock, 0) - tbl = swsscommon.Table(state_db, "VNET_ROUTE_TUNNEL_TABLE") - - status, fvs = tbl.get(vnet + '|' + prefix) - assert status, "Got an error when get a key" - - fvs = dict(fvs) - assert fvs['active_endpoints'] == ','.join(endpoints) - - if endpoints: - assert fvs['state'] == 'active' - else: - assert fvs['state'] == 'inactive' - - -def check_remove_state_db_routes(dvs, vnet, prefix): - state_db = swsscommon.DBConnector(swsscommon.STATE_DB, dvs.redis_sock, 0) - tbl = swsscommon.Table(state_db, "VNET_ROUTE_TUNNEL_TABLE") - keys = tbl.getKeys() - - assert vnet + '|' + prefix not in keys - - -def check_routes_advertisement(dvs, prefix, profile=""): - state_db = swsscommon.DBConnector(swsscommon.STATE_DB, dvs.redis_sock, 0) - tbl = swsscommon.Table(state_db, "ADVERTISE_NETWORK_TABLE") - keys = tbl.getKeys() - - assert prefix in keys - - if profile: - status, fvs = tbl.get(prefix) - assert status, "Got an error when get a key" - fvs = dict(fvs) - assert fvs['profile'] == profile - - -def check_remove_routes_advertisement(dvs, prefix): - state_db = swsscommon.DBConnector(swsscommon.STATE_DB, dvs.redis_sock, 0) - tbl = swsscommon.Table(state_db, "ADVERTISE_NETWORK_TABLE") - keys = tbl.getKeys() - - assert prefix not in keys - - -def check_syslog(dvs, marker, err_log): - (exitcode, num) = dvs.runcmd(['sh', '-c', "awk \'/%s/,ENDFILE {print;}\' /var/log/syslog | grep \"%s\" | wc -l" % (marker, err_log)]) - assert num.strip() == "0" - - -loopback_id = 0 -def_vr_id = 0 -switch_mac = None - -def update_bgp_global_dev_state(dvs, state): - config_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - create_entry_tbl( - config_db, - "BGP_DEVICE_GLOBAL",'|',"STATE", - [ - ("tsa_enabled", state), - ] - ) - -def set_tsa(dvs): - update_bgp_global_dev_state(dvs, "true") - -def clear_tsa(dvs): - update_bgp_global_dev_state(dvs, "false") - -class VnetVxlanVrfTunnel(object): - - ASIC_TUNNEL_TABLE = "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL" - ASIC_TUNNEL_MAP = "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL_MAP" - ASIC_TUNNEL_MAP_ENTRY = "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL_MAP_ENTRY" - ASIC_TUNNEL_TERM_ENTRY = "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL_TERM_TABLE_ENTRY" - ASIC_RIF_TABLE = "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE" - ASIC_VRF_TABLE = "ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER" - ASIC_ROUTE_ENTRY = "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY" - ASIC_NEXT_HOP = "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP" - ASIC_VLAN_TABLE = "ASIC_STATE:SAI_OBJECT_TYPE_VLAN" - ASIC_NEXT_HOP_GROUP = "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP" - ASIC_NEXT_HOP_GROUP_MEMBER = "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER" - ASIC_BFD_SESSION = "ASIC_STATE:SAI_OBJECT_TYPE_BFD_SESSION" - APP_VNET_MONITOR = "VNET_MONITOR_TABLE" - - def __init__(self): - self.tunnel_map_ids = set() - self.tunnel_map_entry_ids = set() - self.tunnel_ids = set() - self.tunnel_term_ids = set() - self.tunnel_map_map = {} - self.tunnel = {} - self.vnet_vr_ids = set() - self.vr_map = {} - self.nh_ids = {} - self.nhg_ids = {} - - def fetch_exist_entries(self, dvs): - self.vnet_vr_ids = get_exist_entries(dvs, self.ASIC_VRF_TABLE) - self.tunnel_ids = get_exist_entries(dvs, self.ASIC_TUNNEL_TABLE) - self.tunnel_map_ids = get_exist_entries(dvs, self.ASIC_TUNNEL_MAP) - self.tunnel_map_entry_ids = get_exist_entries(dvs, self.ASIC_TUNNEL_MAP_ENTRY) - self.tunnel_term_ids = get_exist_entries(dvs, self.ASIC_TUNNEL_TERM_ENTRY) - self.rifs = get_exist_entries(dvs, self.ASIC_RIF_TABLE) - self.routes = get_exist_entries(dvs, self.ASIC_ROUTE_ENTRY) - self.nhops = get_exist_entries(dvs, self.ASIC_NEXT_HOP) - self.nhgs = get_exist_entries(dvs, self.ASIC_NEXT_HOP_GROUP) - self.bfd_sessions = get_exist_entries(dvs, self.ASIC_BFD_SESSION) - - global loopback_id, def_vr_id, switch_mac - if not loopback_id: - loopback_id = get_lo(dvs) - - if not def_vr_id: - def_vr_id = get_default_vr_id(dvs) - - if switch_mac is None: - switch_mac = get_switch_mac(dvs) - - def check_vxlan_tunnel(self, dvs, tunnel_name, src_ip): - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - global loopback_id, def_vr_id - - tunnel_map_id = get_created_entries(asic_db, self.ASIC_TUNNEL_MAP, self.tunnel_map_ids, 4) - tunnel_id = get_created_entry(asic_db, self.ASIC_TUNNEL_TABLE, self.tunnel_ids) - tunnel_term_id = get_created_entry(asic_db, self.ASIC_TUNNEL_TERM_ENTRY, self.tunnel_term_ids) - - # check that the vxlan tunnel termination are there - assert how_many_entries_exist(asic_db, self.ASIC_TUNNEL_MAP) == (len(self.tunnel_map_ids) + 4), "The TUNNEL_MAP wasn't created" - assert how_many_entries_exist(asic_db, self.ASIC_TUNNEL_MAP_ENTRY) == len(self.tunnel_map_entry_ids), "The TUNNEL_MAP_ENTRY is created" - assert how_many_entries_exist(asic_db, self.ASIC_TUNNEL_TABLE) == (len(self.tunnel_ids) + 1), "The TUNNEL wasn't created" - assert how_many_entries_exist(asic_db, self.ASIC_TUNNEL_TERM_ENTRY) == (len(self.tunnel_term_ids) + 1), "The TUNNEL_TERM_TABLE_ENTRY wasm't created" - - check_object(asic_db, self.ASIC_TUNNEL_MAP, tunnel_map_id[2], - { - 'SAI_TUNNEL_MAP_ATTR_TYPE': 'SAI_TUNNEL_MAP_TYPE_VNI_TO_VIRTUAL_ROUTER_ID', - } - ) - - check_object(asic_db, self.ASIC_TUNNEL_MAP, tunnel_map_id[3], - { - 'SAI_TUNNEL_MAP_ATTR_TYPE': 'SAI_TUNNEL_MAP_TYPE_VIRTUAL_ROUTER_ID_TO_VNI', - } - ) - - check_object(asic_db, self.ASIC_TUNNEL_MAP, tunnel_map_id[0], - { - 'SAI_TUNNEL_MAP_ATTR_TYPE': 'SAI_TUNNEL_MAP_TYPE_VNI_TO_VLAN_ID', - } - ) - - check_object(asic_db, self.ASIC_TUNNEL_MAP, tunnel_map_id[1], - { - 'SAI_TUNNEL_MAP_ATTR_TYPE': 'SAI_TUNNEL_MAP_TYPE_VLAN_ID_TO_VNI', - } - ) - - check_object(asic_db, self.ASIC_TUNNEL_TABLE, tunnel_id, - { - 'SAI_TUNNEL_ATTR_TYPE': 'SAI_TUNNEL_TYPE_VXLAN', - 'SAI_TUNNEL_ATTR_UNDERLAY_INTERFACE': loopback_id, - 'SAI_TUNNEL_ATTR_DECAP_MAPPERS': '2:%s,%s' % (tunnel_map_id[0], tunnel_map_id[2]), - 'SAI_TUNNEL_ATTR_ENCAP_MAPPERS': '2:%s,%s' % (tunnel_map_id[1], tunnel_map_id[3]), - 'SAI_TUNNEL_ATTR_ENCAP_SRC_IP': src_ip, - } - ) - - expected_attributes = { - 'SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_TYPE': 'SAI_TUNNEL_TERM_TABLE_ENTRY_TYPE_P2MP', - 'SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_VR_ID': def_vr_id, - 'SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_DST_IP': src_ip, - 'SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_TUNNEL_TYPE': 'SAI_TUNNEL_TYPE_VXLAN', - 'SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_ACTION_TUNNEL_ID': tunnel_id, - } - - check_object(asic_db, self.ASIC_TUNNEL_TERM_ENTRY, tunnel_term_id, expected_attributes) - - self.tunnel_map_ids.update(tunnel_map_id) - self.tunnel_ids.add(tunnel_id) - self.tunnel_term_ids.add(tunnel_term_id) - self.tunnel_map_map[tunnel_name] = tunnel_map_id - self.tunnel[tunnel_name] = tunnel_id - - def check_del_vxlan_tunnel(self, dvs): - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - - old_tunnel = get_deleted_entries(asic_db, self.ASIC_TUNNEL_TABLE, self.tunnel_ids, 1) - check_deleted_object(asic_db, self.ASIC_TUNNEL_TABLE, old_tunnel[0]) - self.tunnel_ids.remove(old_tunnel[0]) - - old_tunnel_maps = get_deleted_entries(asic_db, self.ASIC_TUNNEL_MAP, self.tunnel_map_ids, 4) - for old_tunnel_map in old_tunnel_maps: - check_deleted_object(asic_db, self.ASIC_TUNNEL_MAP, old_tunnel_map) - self.tunnel_map_ids.remove(old_tunnel_map) - - def check_vxlan_tunnel_entry(self, dvs, tunnel_name, vnet_name, vni_id): - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - app_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - - time.sleep(2) - - if (self.tunnel_map_map.get(tunnel_name) is None): - tunnel_map_id = get_created_entries(asic_db, self.ASIC_TUNNEL_MAP, self.tunnel_map_ids, 4) - else: - tunnel_map_id = self.tunnel_map_map[tunnel_name] - - tunnel_map_entry_id = get_created_entries(asic_db, self.ASIC_TUNNEL_MAP_ENTRY, self.tunnel_map_entry_ids, 2) - - # check that the vxlan tunnel termination are there - assert how_many_entries_exist(asic_db, self.ASIC_TUNNEL_MAP_ENTRY) == (len(self.tunnel_map_entry_ids) + 2), "The TUNNEL_MAP_ENTRY is created too early" - - check_object(asic_db, self.ASIC_TUNNEL_MAP_ENTRY, tunnel_map_entry_id[0], - { - 'SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE': 'SAI_TUNNEL_MAP_TYPE_VIRTUAL_ROUTER_ID_TO_VNI', - 'SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP': tunnel_map_id[3], - 'SAI_TUNNEL_MAP_ENTRY_ATTR_VIRTUAL_ROUTER_ID_KEY': self.vr_map[vnet_name].get('ing'), - 'SAI_TUNNEL_MAP_ENTRY_ATTR_VNI_ID_VALUE': vni_id, - } - ) - - check_object(asic_db, self.ASIC_TUNNEL_MAP_ENTRY, tunnel_map_entry_id[1], - { - 'SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE': 'SAI_TUNNEL_MAP_TYPE_VNI_TO_VIRTUAL_ROUTER_ID', - 'SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP': tunnel_map_id[2], - 'SAI_TUNNEL_MAP_ENTRY_ATTR_VNI_ID_KEY': vni_id, - 'SAI_TUNNEL_MAP_ENTRY_ATTR_VIRTUAL_ROUTER_ID_VALUE': self.vr_map[vnet_name].get('egr'), - } - ) - - self.tunnel_map_entry_ids.update(tunnel_map_entry_id) - - def check_vnet_entry(self, dvs, name, peer_list=[]): - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - app_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - - #Assert if there are linklocal entries - tbl = swsscommon.Table(app_db, "VNET_ROUTE_TUNNEL_TABLE") - route_entries = tbl.getKeys() - assert "ff00::/8" not in route_entries - assert "fe80::/64" not in route_entries - - #Check virtual router objects - assert how_many_entries_exist(asic_db, self.ASIC_VRF_TABLE) == (len(self.vnet_vr_ids) + 1),\ - "The VR objects are not created" - - new_vr_ids = get_created_entries(asic_db, self.ASIC_VRF_TABLE, self.vnet_vr_ids, 1) - - self.vnet_vr_ids.update(new_vr_ids) - self.vr_map[name] = { 'ing':new_vr_ids[0], 'egr':new_vr_ids[0], 'peer':peer_list } - - def check_default_vnet_entry(self, dvs, name): - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - #Check virtual router objects - assert how_many_entries_exist(asic_db, self.ASIC_VRF_TABLE) == (len(self.vnet_vr_ids)),\ - "Some VR objects are created" - #Mappers for default VNET is created with default VR objects. - self.vr_map[name] = { 'ing':list(self.vnet_vr_ids)[0], 'egr':list(self.vnet_vr_ids)[0], 'peer':[] } - - def check_del_vnet_entry(self, dvs, name): - # TODO: Implement for VRF VNET - return True - - def vnet_route_ids(self, dvs, name, local=False): - vr_set = set() - - vr_set.add(self.vr_map[name].get('ing')) - - try: - for peer in self.vr_map[name].get('peer'): - vr_set.add(self.vr_map[peer].get('ing')) - except IndexError: - pass - - return vr_set - - def check_router_interface(self, dvs, intf_name, name, vlan_oid=0): - # Check RIF in ingress VRF - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - global switch_mac - - expected_attr = { - "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": self.vr_map[name].get('ing'), - "SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS": switch_mac, - "SAI_ROUTER_INTERFACE_ATTR_MTU": "9100", - } - - if vlan_oid: - expected_attr.update({'SAI_ROUTER_INTERFACE_ATTR_TYPE': 'SAI_ROUTER_INTERFACE_TYPE_VLAN'}) - expected_attr.update({'SAI_ROUTER_INTERFACE_ATTR_VLAN_ID': vlan_oid}) - else: - expected_attr.update({'SAI_ROUTER_INTERFACE_ATTR_TYPE': 'SAI_ROUTER_INTERFACE_TYPE_PORT'}) - - new_rif = get_created_entry(asic_db, self.ASIC_RIF_TABLE, self.rifs) - check_object(asic_db, self.ASIC_RIF_TABLE, new_rif, expected_attr) - - #IP2ME route will be created with every router interface - new_route = get_created_entries(asic_db, self.ASIC_ROUTE_ENTRY, self.routes, 1) - - if vlan_oid: - expected_attr = { 'SAI_VLAN_ATTR_BROADCAST_FLOOD_CONTROL_TYPE': 'SAI_VLAN_FLOOD_CONTROL_TYPE_NONE' } - check_object(asic_db, self.ASIC_VLAN_TABLE, vlan_oid, expected_attr) - - expected_attr = { 'SAI_VLAN_ATTR_UNKNOWN_MULTICAST_FLOOD_CONTROL_TYPE': 'SAI_VLAN_FLOOD_CONTROL_TYPE_NONE' } - check_object(asic_db, self.ASIC_VLAN_TABLE, vlan_oid, expected_attr) - - check_linux_intf_arp_proxy(dvs, intf_name) - - self.rifs.add(new_rif) - self.routes.update(new_route) - - def check_del_router_interface(self, dvs, name): - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - - old_rif = get_deleted_entries(asic_db, self.ASIC_RIF_TABLE, self.rifs, 1) - check_deleted_object(asic_db, self.ASIC_RIF_TABLE, old_rif[0]) - - self.rifs.remove(old_rif[0]) - - def check_vnet_local_routes(self, dvs, name): - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - - vr_ids = self.vnet_route_ids(dvs, name, True) - count = len(vr_ids) - - new_route = get_created_entries(asic_db, self.ASIC_ROUTE_ENTRY, self.routes, count) - - #Routes are not replicated to egress VRF, return if count is 0, else check peering - if not count: - return - - asic_vrs = set() - for idx in range(count): - rt_key = json.loads(new_route[idx]) - asic_vrs.add(rt_key['vr']) - - assert asic_vrs == vr_ids - - self.routes.update(new_route) - - def check_del_vnet_local_routes(self, dvs, name): - # TODO: Implement for VRF VNET - return True - - def check_vnet_routes(self, dvs, name, endpoint, tunnel, mac="", vni=0, route_ids=""): - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - - vr_ids = self.vnet_route_ids(dvs, name) - count = len(vr_ids) - - # Check routes in ingress VRF - expected_attr = { - "SAI_NEXT_HOP_ATTR_TYPE": "SAI_NEXT_HOP_TYPE_TUNNEL_ENCAP", - "SAI_NEXT_HOP_ATTR_IP": endpoint, - "SAI_NEXT_HOP_ATTR_TUNNEL_ID": self.tunnel[tunnel], - } - - if vni: - expected_attr.update({'SAI_NEXT_HOP_ATTR_TUNNEL_VNI': vni}) - - if mac: - expected_attr.update({'SAI_NEXT_HOP_ATTR_TUNNEL_MAC': mac}) - - if endpoint in self.nh_ids: - new_nh = self.nh_ids[endpoint] - else: - new_nh = get_created_entry(asic_db, self.ASIC_NEXT_HOP, self.nhops) - self.nh_ids[endpoint] = new_nh - self.nhops.add(new_nh) - - check_object(asic_db, self.ASIC_NEXT_HOP, new_nh, expected_attr) - if not route_ids: - new_route = get_created_entries(asic_db, self.ASIC_ROUTE_ENTRY, self.routes, count) - else: - new_route = route_ids - - #Check if the route is in expected VRF - asic_vrs = set() - for idx in range(count): - check_object(asic_db, self.ASIC_ROUTE_ENTRY, new_route[idx], - { - "SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID": new_nh, - } - ) - rt_key = json.loads(new_route[idx]) - asic_vrs.add(rt_key['vr']) - - assert asic_vrs == vr_ids - - self.routes.update(new_route) - - return new_route - - def serialize_endpoint_group(self, endpoints): - endpoints.sort() - return ",".join(endpoints) - - def check_next_hop_group_member(self, dvs, nhg, ordered_ecmp, expected_endpoint, expected_attrs): - expected_endpoint_str = self.serialize_endpoint_group(expected_endpoint) - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - tbl_nhgm = swsscommon.Table(asic_db, self.ASIC_NEXT_HOP_GROUP_MEMBER) - tbl_nh = swsscommon.Table(asic_db, self.ASIC_NEXT_HOP) - entries = set(tbl_nhgm.getKeys()) - endpoints = [] - for entry in entries: - status, fvs = tbl_nhgm.get(entry) - fvs = dict(fvs) - assert status, "Got an error when get a key" - if fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID"] == nhg: - nh_key = fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID"] - status, nh_fvs = tbl_nh.get(nh_key) - nh_fvs = dict(nh_fvs) - assert status, "Got an error when get a key" - endpoint = nh_fvs["SAI_NEXT_HOP_ATTR_IP"] - endpoints.append(endpoint) - assert endpoint in expected_attrs - if ordered_ecmp == "true": - assert fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_SEQUENCE_ID"] == expected_attrs[endpoint]['SAI_NEXT_HOP_GROUP_MEMBER_ATTR_SEQUENCE_ID'] - del expected_attrs[endpoint]['SAI_NEXT_HOP_GROUP_MEMBER_ATTR_SEQUENCE_ID'] - else: - assert fvs.get("SAI_NEXT_HOP_GROUP_MEMBER_ATTR_SEQUENCE_ID") is None - - check_object(asic_db, self.ASIC_NEXT_HOP, nh_key, expected_attrs[endpoint]) - - assert self.serialize_endpoint_group(endpoints) == expected_endpoint_str - - def get_nexthop_groups(self, dvs, nhg): - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - tbl_nhgm = swsscommon.Table(asic_db, self.ASIC_NEXT_HOP_GROUP_MEMBER) - tbl_nh = swsscommon.Table(asic_db, self.ASIC_NEXT_HOP) - nhg_data = {} - nhg_data['id'] = nhg - entries = set(tbl_nhgm.getKeys()) - nhg_data['endpoints'] = [] - for entry in entries: - status, fvs = tbl_nhgm.get(entry) - fvs = dict(fvs) - assert status, "Got an error when get a key" - if fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID"] == nhg: - nh_key = fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID"] - status, nh_fvs = tbl_nh.get(nh_key) - nh_fvs = dict(nh_fvs) - assert status, "Got an error when get a key" - endpoint = nh_fvs["SAI_NEXT_HOP_ATTR_IP"] - nhg_data['endpoints'].append(endpoint) - return nhg_data - def check_vnet_ecmp_routes(self, dvs, name, endpoints, tunnel, mac=[], vni=[], route_ids=[], nhg="", ordered_ecmp="false", nh_seq_id=None): - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - endpoint_str = name + "|" + self.serialize_endpoint_group(endpoints) - - vr_ids = self.vnet_route_ids(dvs, name) - count = len(vr_ids) - - expected_attrs = {} - for idx, endpoint in enumerate(endpoints): - expected_attr = { - "SAI_NEXT_HOP_ATTR_TYPE": "SAI_NEXT_HOP_TYPE_TUNNEL_ENCAP", - "SAI_NEXT_HOP_ATTR_IP": endpoint, - "SAI_NEXT_HOP_ATTR_TUNNEL_ID": self.tunnel[tunnel], - } - if vni and vni[idx]: - expected_attr.update({'SAI_NEXT_HOP_ATTR_TUNNEL_VNI': vni[idx]}) - if mac and mac[idx]: - expected_attr.update({'SAI_NEXT_HOP_ATTR_TUNNEL_MAC': mac[idx]}) - if ordered_ecmp == "true" and nh_seq_id: - expected_attr.update({'SAI_NEXT_HOP_GROUP_MEMBER_ATTR_SEQUENCE_ID': nh_seq_id[idx]}) - expected_attrs[endpoint] = expected_attr - - if nhg: - new_nhg = nhg - elif endpoint_str in self.nhg_ids: - new_nhg = self.nhg_ids[endpoint_str] - else: - new_nhg = get_created_entry(asic_db, self.ASIC_NEXT_HOP_GROUP, self.nhgs) - self.nhg_ids[endpoint_str] = new_nhg - self.nhgs.add(new_nhg) - - - # Check routes in ingress VRF - expected_nhg_attr = { - "SAI_NEXT_HOP_GROUP_ATTR_TYPE": "SAI_NEXT_HOP_GROUP_TYPE_DYNAMIC_UNORDERED_ECMP" if ordered_ecmp == "false" else "SAI_NEXT_HOP_GROUP_TYPE_DYNAMIC_ORDERED_ECMP", - } - check_object(asic_db, self.ASIC_NEXT_HOP_GROUP, new_nhg, expected_nhg_attr) - - # Check nexthop group member - self.check_next_hop_group_member(dvs, new_nhg, ordered_ecmp, endpoints, expected_attrs) - - if route_ids: - new_route = route_ids - else: - new_route = get_created_entries(asic_db, self.ASIC_ROUTE_ENTRY, self.routes, count) - - #Check if the route is in expected VRF - asic_vrs = set() - for idx in range(count): - check_object(asic_db, self.ASIC_ROUTE_ENTRY, new_route[idx], - { - "SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID": new_nhg, - } - ) - rt_key = json.loads(new_route[idx]) - asic_vrs.add(rt_key['vr']) - - assert asic_vrs == vr_ids - - self.routes.update(new_route) - - return new_route, new_nhg - - def check_priority_vnet_ecmp_routes(self, dvs, name, endpoints_primary, tunnel, mac=[], vni=[], route_ids=[], count =1, prefix =""): - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - endpoint_str_primary = name + "|" + self.serialize_endpoint_group(endpoints_primary) - new_nhgs = [] - expected_attrs_primary = {} - for idx, endpoint in enumerate(endpoints_primary): - expected_attr = { - "SAI_NEXT_HOP_ATTR_TYPE": "SAI_NEXT_HOP_TYPE_TUNNEL_ENCAP", - "SAI_NEXT_HOP_ATTR_IP": endpoint, - "SAI_NEXT_HOP_ATTR_TUNNEL_ID": self.tunnel[tunnel], - } - if vni and vni[idx]: - expected_attr.update({'SAI_NEXT_HOP_ATTR_TUNNEL_VNI': vni[idx]}) - if mac and mac[idx]: - expected_attr.update({'SAI_NEXT_HOP_ATTR_TUNNEL_MAC': mac[idx]}) - expected_attrs_primary[endpoint] = expected_attr - - if len(endpoints_primary) == 1: - if route_ids: - new_route = route_ids - else: - new_route = get_created_entries(asic_db, self.ASIC_ROUTE_ENTRY, self.routes, count) - return new_route - else : - new_nhgs = get_all_created_entries(asic_db, self.ASIC_NEXT_HOP_GROUP, self.nhgs) - found_match = False - - for nhg in new_nhgs: - nhg_data = self.get_nexthop_groups(dvs, nhg) - eplist = self.serialize_endpoint_group(nhg_data['endpoints']) - if eplist == self.serialize_endpoint_group(endpoints_primary): - self.nhg_ids[endpoint_str_primary] = nhg - found_match = True - - assert found_match, "the expected Nexthop group was not found." - - # Check routes in ingress VRF - expected_nhg_attr = { - "SAI_NEXT_HOP_GROUP_ATTR_TYPE": "SAI_NEXT_HOP_GROUP_TYPE_DYNAMIC_UNORDERED_ECMP", - } - for nhg in new_nhgs: - check_object(asic_db, self.ASIC_NEXT_HOP_GROUP, nhg, expected_nhg_attr) - - # Check nexthop group member - self.check_next_hop_group_member(dvs, self.nhg_ids[endpoint_str_primary], "false", endpoints_primary, expected_attrs_primary) - - if route_ids: - new_route = route_ids - else: - new_route = get_created_entries(asic_db, self.ASIC_ROUTE_ENTRY, self.routes, count) - - #Check if the route is in expected VRF - active_nhg = self.nhg_ids[endpoint_str_primary] - for idx in range(count): - if prefix != "" and prefix not in new_route[idx] : - continue - check_object(asic_db, self.ASIC_ROUTE_ENTRY, new_route[idx], - { - "SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID": active_nhg, - } - ) - rt_key = json.loads(new_route[idx]) - - - self.routes.update(new_route) - del self.nhg_ids[endpoint_str_primary] - return new_route - - def check_del_vnet_routes(self, dvs, name, prefixes=[]): - # TODO: Implement for VRF VNET - - def _access_function(): - route_entries = get_exist_entries(dvs, self.ASIC_ROUTE_ENTRY) - route_prefixes = [json.loads(route_entry)["dest"] for route_entry in route_entries] - return (all(prefix not in route_prefixes for prefix in prefixes), None) - - if prefixes: - wait_for_result(_access_function) - - return True - - def check_custom_monitor_app_db(self, dvs, prefix, endpoint, packet_type, overlay_dmac): - app_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - key = endpoint + ':' + prefix - check_object(app_db, self.APP_VNET_MONITOR, key, - { - "packet_type": packet_type, - "overlay_dmac" : overlay_dmac - } - ) - return True - - def check_custom_monitor_deleted(self, dvs, prefix, endpoint): - app_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - key = endpoint + ':' + prefix - check_deleted_object(app_db, self.APP_VNET_MONITOR, key) - -class TestVnetOrch(object): - - def get_vnet_obj(self): - return VnetVxlanVrfTunnel() - - def setup_db(self, dvs): - self.pdb = dvs.get_app_db() - self.adb = dvs.get_asic_db() - self.cdb = dvs.get_config_db() - self.sdb = dvs.get_state_db() - - def clear_srv_config(self, dvs): - dvs.servers[0].runcmd("ip address flush dev eth0") - dvs.servers[1].runcmd("ip address flush dev eth0") - dvs.servers[2].runcmd("ip address flush dev eth0") - dvs.servers[3].runcmd("ip address flush dev eth0") - - def set_admin_status(self, interface, status): - self.cdb.update_entry("PORT", interface, {"admin_status": status}) - - def create_l3_intf(self, interface, vrf_name): - if len(vrf_name) == 0: - self.cdb.create_entry("INTERFACE", interface, {"NULL": "NULL"}) - else: - self.cdb.create_entry("INTERFACE", interface, {"vrf_name": vrf_name}) - - def add_ip_address(self, interface, ip): - self.cdb.create_entry("INTERFACE", interface + "|" + ip, {"NULL": "NULL"}) - - def remove_ip_address(self, interface, ip): - self.cdb.delete_entry("INTERFACE", interface + "|" + ip) - - def create_route_entry(self, key, pairs): - tbl = swsscommon.ProducerStateTable(self.pdb.db_connection, "ROUTE_TABLE") - fvs = swsscommon.FieldValuePairs(list(pairs.items())) - tbl.set(key, fvs) - - def remove_route_entry(self, key): - tbl = swsscommon.ProducerStateTable(self.pdb.db_connection, "ROUTE_TABLE") - tbl._del(key) - - def check_route_entries(self, destinations): - def _access_function(): - route_entries = self.adb.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - route_destinations = [json.loads(route_entry)["dest"] - for route_entry in route_entries] - return (all(destination in route_destinations for destination in destinations), None) - - wait_for_result(_access_function) - - - @pytest.fixture(params=["true", "false"]) - def ordered_ecmp(self, dvs, request): - - app_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - if request.param == "true": - create_entry_pst( - app_db, - "SWITCH_TABLE", ':', "switch", - [ - ('ordered_ecmp', 'true') - ], - ) - dvs.get_state_db().wait_for_field_match("SWITCH_CAPABILITY", "switch", {"ORDERED_ECMP_CAPABLE": "true"}) - - yield request.param - - if request.param == "true": - create_entry_pst( - app_db, - "SWITCH_TABLE", ':', "switch", - [ - ('ordered_ecmp', 'false') - ], - ) - dvs.get_state_db().wait_for_field_match("SWITCH_CAPABILITY", "switch", {"ORDERED_ECMP_CAPABLE": "false"}) - - ''' - Test 1 - Create Vlan Interface, Tunnel and Vnet - ''' - def test_vnet_orch_1(self, dvs, testlog): - vnet_obj = self.get_vnet_obj() - - tunnel_name = 'tunnel_1' - - vnet_obj.fetch_exist_entries(dvs) - - create_vxlan_tunnel(dvs, tunnel_name, '10.10.10.10') - create_vnet_entry(dvs, 'Vnet_2000', tunnel_name, '2000', "") - - vnet_obj.check_vnet_entry(dvs, 'Vnet_2000') - vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, 'Vnet_2000', '2000') - - vnet_obj.check_vxlan_tunnel(dvs, tunnel_name, '10.10.10.10') - - vid = create_vlan_interface(dvs, "Vlan100", "Ethernet24", "Vnet_2000", "100.100.3.1/24") - vnet_obj.check_router_interface(dvs, "Vlan100", 'Vnet_2000', vid) - - vid = create_vlan_interface(dvs, "Vlan101", "Ethernet28", "Vnet_2000", "100.100.4.1/24") - vnet_obj.check_router_interface(dvs, "Vlan101", 'Vnet_2000', vid) - - vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "100.100.1.1/32", 'Vnet_2000', '10.10.10.1') - vnet_obj.check_vnet_routes(dvs, 'Vnet_2000', '10.10.10.1', tunnel_name) - check_state_db_routes(dvs, 'Vnet_2000', "100.100.1.1/32", ['10.10.10.1']) - # The default Vnet setting does not advertise prefix - check_remove_routes_advertisement(dvs, "100.100.1.1/32") - - create_vnet_local_routes(dvs, "100.100.3.0/24", 'Vnet_2000', 'Vlan100') - vnet_obj.check_vnet_local_routes(dvs, 'Vnet_2000') - - create_vnet_local_routes(dvs, "100.100.4.0/24", 'Vnet_2000', 'Vlan101') - vnet_obj.check_vnet_local_routes(dvs, 'Vnet_2000') - - #Create Physical Interface in another Vnet - - create_vnet_entry(dvs, 'Vnet_2001', tunnel_name, '2001', "") - - vnet_obj.check_vnet_entry(dvs, 'Vnet_2001') - vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, 'Vnet_2001', '2001') - - create_phy_interface(dvs, "Ethernet4", "Vnet_2001", "100.102.1.1/24") - vnet_obj.check_router_interface(dvs, "Ethernet4", 'Vnet_2001') - - vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "100.100.2.1/32", 'Vnet_2001', '10.10.10.2', "00:12:34:56:78:9A") - vnet_obj.check_vnet_routes(dvs, 'Vnet_2001', '10.10.10.2', tunnel_name, "00:12:34:56:78:9A") - check_state_db_routes(dvs, 'Vnet_2001', "100.100.2.1/32", ['10.10.10.2']) - # The default Vnet setting does not advertise prefix - check_remove_routes_advertisement(dvs, "100.100.2.1/32") - - create_vnet_local_routes(dvs, "100.102.1.0/24", 'Vnet_2001', 'Ethernet4') - vnet_obj.check_vnet_local_routes(dvs, 'Vnet_2001') - - # Clean-up and verify remove flows - - delete_vnet_local_routes(dvs, "100.100.3.0/24", 'Vnet_2000') - vnet_obj.check_del_vnet_local_routes(dvs, 'Vnet_2000') - - delete_vnet_local_routes(dvs, "100.100.4.0/24", 'Vnet_2000') - vnet_obj.check_del_vnet_local_routes(dvs, 'Vnet_2000') - - delete_vnet_local_routes(dvs, "100.102.1.0/24", 'Vnet_2001') - vnet_obj.check_del_vnet_local_routes(dvs, 'Vnet_2001') - - delete_vnet_routes(dvs, "100.100.2.1/32", 'Vnet_2001') - vnet_obj.check_del_vnet_routes(dvs, 'Vnet_2001') - check_remove_state_db_routes(dvs, 'Vnet_2001', "100.100.2.1/32") - check_remove_routes_advertisement(dvs, "100.100.2.1/32") - - delete_vnet_routes(dvs, "100.100.1.1/32", 'Vnet_2000') - vnet_obj.check_del_vnet_routes(dvs, 'Vnet_2000') - check_remove_state_db_routes(dvs, 'Vnet_2000', "100.100.1.1/32") - check_remove_routes_advertisement(dvs, "100.100.1.1/32") - - delete_phy_interface(dvs, "Ethernet4", "100.102.1.1/24") - vnet_obj.check_del_router_interface(dvs, "Ethernet4") - - delete_vlan_interface(dvs, "Vlan100", "100.100.3.1/24") - vnet_obj.check_del_router_interface(dvs, "Vlan100") - - delete_vlan_interface(dvs, "Vlan101", "100.100.4.1/24") - vnet_obj.check_del_router_interface(dvs, "Vlan101") - - delete_vnet_entry(dvs, 'Vnet_2001') - vnet_obj.check_del_vnet_entry(dvs, 'Vnet_2001') - - delete_vnet_entry(dvs, 'Vnet_2000') - vnet_obj.check_del_vnet_entry(dvs, 'Vnet_2000') - - delete_vxlan_tunnel(dvs, tunnel_name) - vnet_obj.check_del_vxlan_tunnel(dvs) - - ''' - Test 2 - Two VNets, One HSMs per VNet - ''' - def test_vnet_orch_2(self, dvs, testlog): - vnet_obj = self.get_vnet_obj() - - tunnel_name = 'tunnel_2' - - vnet_obj.fetch_exist_entries(dvs) - - create_vxlan_tunnel(dvs, tunnel_name, '6.6.6.6') - create_vnet_entry(dvs, 'Vnet_1', tunnel_name, '1111', "") - - vnet_obj.check_vnet_entry(dvs, 'Vnet_1') - vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, 'Vnet_1', '1111') - - tun_id = vnet_obj.check_vxlan_tunnel(dvs, tunnel_name, '6.6.6.6') - - vid = create_vlan_interface(dvs, "Vlan1001", "Ethernet0", "Vnet_1", "1.1.10.1/24") - vnet_obj.check_router_interface(dvs, "Vlan1001", 'Vnet_1', vid) - - vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "1.1.1.10/32", 'Vnet_1', '100.1.1.10') - vnet_obj.check_vnet_routes(dvs, 'Vnet_1', '100.1.1.10', tunnel_name) - check_state_db_routes(dvs, 'Vnet_1', "1.1.1.10/32", ['100.1.1.10']) - # The default Vnet setting does not advertise prefix - check_remove_routes_advertisement(dvs, "1.1.1.10/32") - - vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "1.1.1.11/32", 'Vnet_1', '100.1.1.10') - vnet_obj.check_vnet_routes(dvs, 'Vnet_1', '100.1.1.10', tunnel_name) - check_state_db_routes(dvs, 'Vnet_1', "1.1.1.11/32", ['100.1.1.10']) - # The default Vnet setting does not advertise prefix - check_remove_routes_advertisement(dvs, "1.1.1.11/32") - - vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "1.1.1.12/32", 'Vnet_1', '200.200.1.200') - vnet_obj.check_vnet_routes(dvs, 'Vnet_1', '200.200.1.200', tunnel_name) - check_state_db_routes(dvs, 'Vnet_1', "1.1.1.12/32", ['200.200.1.200']) - check_remove_routes_advertisement(dvs, "1.1.1.12/32") - - vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "1.1.1.14/32", 'Vnet_1', '200.200.1.201') - vnet_obj.check_vnet_routes(dvs, 'Vnet_1', '200.200.1.201', tunnel_name) - check_state_db_routes(dvs, 'Vnet_1', "1.1.1.14/32", ['200.200.1.201']) - # The default Vnet setting does not advertise prefix - check_remove_routes_advertisement(dvs, "1.1.1.14/32") - - create_vnet_local_routes(dvs, "1.1.10.0/24", 'Vnet_1', 'Vlan1001') - vnet_obj.check_vnet_local_routes(dvs, 'Vnet_1') - - create_vnet_entry(dvs, 'Vnet_2', tunnel_name, '2222', "") - - vnet_obj.check_vnet_entry(dvs, 'Vnet_2') - vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, 'Vnet_2', '2222') - - vid = create_vlan_interface(dvs, "Vlan1002", "Ethernet4", "Vnet_2", "2.2.10.1/24") - vnet_obj.check_router_interface(dvs, "Vlan1002", 'Vnet_2', vid) - - vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "2.2.2.10/32", 'Vnet_2', '100.1.1.20') - vnet_obj.check_vnet_routes(dvs, 'Vnet_2', '100.1.1.20', tunnel_name) - check_state_db_routes(dvs, 'Vnet_2', "2.2.2.10/32", ['100.1.1.20']) - # The default Vnet setting does not advertise prefix - check_remove_routes_advertisement(dvs, "2.2.2.10/32") - - vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "2.2.2.11/32", 'Vnet_2', '100.1.1.20') - vnet_obj.check_vnet_routes(dvs, 'Vnet_2', '100.1.1.20', tunnel_name) - check_state_db_routes(dvs, 'Vnet_2', "2.2.2.11/32", ['100.1.1.20']) - # The default Vnet setting does not advertise prefix - check_remove_routes_advertisement(dvs, "2.2.2.11/32") - - create_vnet_local_routes(dvs, "2.2.10.0/24", 'Vnet_2', 'Vlan1002') - vnet_obj.check_vnet_local_routes(dvs, 'Vnet_2') - - # Clean-up and verify remove flows - - delete_vnet_local_routes(dvs, "2.2.10.0/24", 'Vnet_2') - vnet_obj.check_del_vnet_local_routes(dvs, 'Vnet_2') - - delete_vnet_local_routes(dvs, "1.1.10.0/24", 'Vnet_1') - vnet_obj.check_del_vnet_local_routes(dvs, 'Vnet_1') - - delete_vnet_routes(dvs, "2.2.2.11/32", 'Vnet_2') - vnet_obj.check_del_vnet_routes(dvs, 'Vnet_2') - check_remove_state_db_routes(dvs, 'Vnet_2', "2.2.2.11/32") - check_remove_routes_advertisement(dvs, "2.2.2.11/32") - - delete_vnet_routes(dvs, "2.2.2.10/32", 'Vnet_2') - vnet_obj.check_del_vnet_routes(dvs, 'Vnet_2') - check_remove_state_db_routes(dvs, 'Vnet_2', "2.2.2.10/32") - check_remove_routes_advertisement(dvs, "2.2.2.10/32") - - delete_vnet_routes(dvs, "1.1.1.14/32", 'Vnet_1') - vnet_obj.check_del_vnet_routes(dvs, 'Vnet_1') - check_remove_state_db_routes(dvs, 'Vnet_1', "1.1.1.14/32") - check_remove_routes_advertisement(dvs, "1.1.1.14/32") - - delete_vnet_routes(dvs, "1.1.1.12/32", 'Vnet_1') - vnet_obj.check_del_vnet_routes(dvs, 'Vnet_1') - check_remove_state_db_routes(dvs, 'Vnet_1', "1.1.1.12/32") - check_remove_routes_advertisement(dvs, "1.1.1.12/32") - - delete_vnet_routes(dvs, "1.1.1.11/32", 'Vnet_1') - vnet_obj.check_del_vnet_routes(dvs, 'Vnet_1') - check_remove_state_db_routes(dvs, 'Vnet_1', "1.1.1.11/32") - check_remove_routes_advertisement(dvs, "1.1.1.11/32") - - delete_vnet_routes(dvs, "1.1.1.10/32", 'Vnet_1') - vnet_obj.check_del_vnet_routes(dvs, 'Vnet_1') - check_remove_state_db_routes(dvs, 'Vnet_1', "1.1.1.10/32") - check_remove_routes_advertisement(dvs, "1.1.1.10/32") - - delete_vlan_interface(dvs, "Vlan1002", "2.2.10.1/24") - vnet_obj.check_del_router_interface(dvs, "Vlan1002") - - delete_vlan_interface(dvs, "Vlan1001", "1.1.10.1/24") - vnet_obj.check_del_router_interface(dvs, "Vlan1001") - - delete_vnet_entry(dvs, 'Vnet_1') - vnet_obj.check_del_vnet_entry(dvs, 'Vnet_1') - - delete_vnet_entry(dvs, 'Vnet_2') - vnet_obj.check_del_vnet_entry(dvs, 'Vnet_2') - - delete_vxlan_tunnel(dvs, tunnel_name) - vnet_obj.check_del_vxlan_tunnel(dvs) - - ''' - Test 3 - Two VNets, One HSMs per VNet, Peering - ''' - def test_vnet_orch_3(self, dvs, testlog): - vnet_obj = self.get_vnet_obj() - - tunnel_name = 'tunnel_3' - - vnet_obj.fetch_exist_entries(dvs) - - create_vxlan_tunnel(dvs, tunnel_name, '7.7.7.7') - - create_vnet_entry(dvs, 'Vnet_10', tunnel_name, '3333', "Vnet_20") - - vnet_obj.check_vnet_entry(dvs, 'Vnet_10', ['Vnet_20']) - vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, 'Vnet_10', '3333') - - create_vnet_entry(dvs, 'Vnet_20', tunnel_name, '4444', "Vnet_10") - - vnet_obj.check_vnet_entry(dvs, 'Vnet_20', ['Vnet_10']) - vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, 'Vnet_20', '4444') - - tun_id = vnet_obj.check_vxlan_tunnel(dvs, tunnel_name, '7.7.7.7') - - vid = create_vlan_interface(dvs, "Vlan2001", "Ethernet8", "Vnet_10", "5.5.10.1/24") - vnet_obj.check_router_interface(dvs, "Vlan2001", 'Vnet_10', vid) - - vid = create_vlan_interface(dvs, "Vlan2002", "Ethernet12", "Vnet_20", "8.8.10.1/24") - vnet_obj.check_router_interface(dvs, "Vlan2002", 'Vnet_20', vid) - - vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "5.5.5.10/32", 'Vnet_10', '50.1.1.10') - vnet_obj.check_vnet_routes(dvs, 'Vnet_10', '50.1.1.10', tunnel_name) - check_state_db_routes(dvs, 'Vnet_10', "5.5.5.10/32", ['50.1.1.10']) - # The default Vnet setting does not advertise prefix - check_remove_routes_advertisement(dvs, "5.5.5.10/32") - - vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "8.8.8.10/32", 'Vnet_20', '80.1.1.20') - vnet_obj.check_vnet_routes(dvs, 'Vnet_10', '80.1.1.20', tunnel_name) - check_state_db_routes(dvs, 'Vnet_20', "8.8.8.10/32", ['80.1.1.20']) - # The default Vnet setting does not advertise prefix - check_remove_routes_advertisement(dvs, "8.8.8.10/32") - - create_vnet_local_routes(dvs, "5.5.10.0/24", 'Vnet_10', 'Vlan2001') - vnet_obj.check_vnet_local_routes(dvs, 'Vnet_10') - - create_vnet_local_routes(dvs, "8.8.10.0/24", 'Vnet_20', 'Vlan2002') - vnet_obj.check_vnet_local_routes(dvs, 'Vnet_20') - - # Clean-up and verify remove flows - - delete_vnet_local_routes(dvs, "5.5.10.0/24", 'Vnet_10') - vnet_obj.check_del_vnet_local_routes(dvs, 'Vnet_10') - - delete_vnet_local_routes(dvs, "8.8.10.0/24", 'Vnet_20') - vnet_obj.check_del_vnet_local_routes(dvs, 'Vnet_20') - - delete_vnet_routes(dvs, "5.5.5.10/32", 'Vnet_10') - vnet_obj.check_del_vnet_routes(dvs, 'Vnet_10') - check_remove_state_db_routes(dvs, 'Vnet_10', "5.5.5.10/32") - check_remove_routes_advertisement(dvs, "5.5.5.10/32") - - delete_vnet_routes(dvs, "8.8.8.10/32", 'Vnet_20') - vnet_obj.check_del_vnet_routes(dvs, 'Vnet_20') - check_remove_state_db_routes(dvs, 'Vnet_20', "8.8.8.10/32") - check_remove_routes_advertisement(dvs, "8.8.8.10/32") - - delete_vlan_interface(dvs, "Vlan2001", "5.5.10.1/24") - vnet_obj.check_del_router_interface(dvs, "Vlan2001") - - delete_vlan_interface(dvs, "Vlan2002", "8.8.10.1/24") - vnet_obj.check_del_router_interface(dvs, "Vlan2002") - - delete_vnet_entry(dvs, 'Vnet_10') - vnet_obj.check_del_vnet_entry(dvs, 'Vnet_10') - - delete_vnet_entry(dvs, 'Vnet_20') - vnet_obj.check_del_vnet_entry(dvs, 'Vnet_20') - - delete_vxlan_tunnel(dvs, tunnel_name) - vnet_obj.check_del_vxlan_tunnel(dvs) - - ''' - Test 4 - IPv6 Vxlan tunnel test - ''' - @pytest.mark.skip(reason="Failing. Under investigation") - def test_vnet_orch_4(self, dvs, testlog): - vnet_obj = self.get_vnet_obj() - - tunnel_name = 'tunnel_v6' - - vnet_obj.fetch_exist_entries(dvs) - - create_vxlan_tunnel(dvs, tunnel_name, 'fd:2::32') - create_vnet_entry(dvs, 'Vnet3001', tunnel_name, '3001', "") - - vnet_obj.check_vnet_entry(dvs, 'Vnet3001') - vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, 'Vnet3001', '3001') - vnet_obj.check_vxlan_tunnel(dvs, tunnel_name, 'fd:2::32') - - vid = create_vlan_interface(dvs, "Vlan300", "Ethernet24", 'Vnet3001', "100.100.3.1/24") - vnet_obj.check_router_interface(dvs, "Vlan300", 'Vnet3001', vid) - - vid = create_vlan_interface(dvs, "Vlan301", "Ethernet28", 'Vnet3001', "100.100.4.1/24") - vnet_obj.check_router_interface(dvs, "Vlan301", 'Vnet3001', vid) - - create_vnet_routes(dvs, "100.100.1.1/32", 'Vnet3001', '2000:1000:2000:3000:4000:5000:6000:7000') - vnet_obj.check_vnet_routes(dvs, 'Vnet3001', '2000:1000:2000:3000:4000:5000:6000:7000', tunnel_name) - check_state_db_routes(dvs, 'Vnet3001', "100.100.1.1/32", ['2000:1000:2000:3000:4000:5000:6000:7000']) - # The default Vnet setting does not advertise prefix - check_remove_routes_advertisement(dvs, "100.100.1.1/32") - - create_vnet_routes(dvs, "100.100.1.2/32", 'Vnet3001', '2000:1000:2000:3000:4000:5000:6000:7000') - vnet_obj.check_vnet_routes(dvs, 'Vnet3001', '2000:1000:2000:3000:4000:5000:6000:7000', tunnel_name) - check_state_db_routes(dvs, 'Vnet3001', "100.100.1.2/32", ['2000:1000:2000:3000:4000:5000:6000:7000']) - # The default Vnet setting does not advertise prefix - check_remove_routes_advertisement(dvs, "100.100.1.2/32") - - create_vnet_local_routes(dvs, "100.100.3.0/24", 'Vnet3001', 'Vlan300') - vnet_obj.check_vnet_local_routes(dvs, 'Vnet3001') - - create_vnet_local_routes(dvs, "100.100.4.0/24", 'Vnet3001', 'Vlan301') - vnet_obj.check_vnet_local_routes(dvs, 'Vnet3001') - - #Create Physical Interface in another Vnet - - create_vnet_entry(dvs, 'Vnet3002', tunnel_name, '3002', "") - - vnet_obj.check_vnet_entry(dvs, 'Vnet3002') - vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, 'Vnet3002', '3002') - - create_phy_interface(dvs, "Ethernet60", 'Vnet3002', "100.102.1.1/24") - vnet_obj.check_router_interface(dvs, "Ethernet60", 'Vnet3002') - - create_vnet_routes(dvs, "100.100.2.1/32", 'Vnet3002', 'fd:2::34', "00:12:34:56:78:9A") - vnet_obj.check_vnet_routes(dvs, 'Vnet3002', 'fd:2::34', tunnel_name, "00:12:34:56:78:9A") - check_state_db_routes(dvs, 'Vnet3002', "100.100.2.1/32", ['fd:2::34']) - # The default Vnet setting does not advertise prefix - check_remove_routes_advertisement(dvs, "100.100.2.1/32") - - create_vnet_local_routes(dvs, "100.102.1.0/24", 'Vnet3002', 'Ethernet60') - vnet_obj.check_vnet_local_routes(dvs, 'Vnet3002') - - # Test peering - create_vnet_entry(dvs, 'Vnet3003', tunnel_name, '3003', 'Vnet3004') - - vnet_obj.check_vnet_entry(dvs, 'Vnet3003', ['Vnet3004']) - vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, 'Vnet3003', '3003') - - create_vnet_entry(dvs, 'Vnet3004', tunnel_name, '3004', 'Vnet3003') - - vnet_obj.check_vnet_entry(dvs, 'Vnet3004', ['Vnet3003']) - vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, 'Vnet3004', '3004') - - create_vnet_routes(dvs, "5.5.5.10/32", 'Vnet3003', 'fd:2::35') - vnet_obj.check_vnet_routes(dvs, 'Vnet3004', 'fd:2::35', tunnel_name) - check_state_db_routes(dvs, 'Vnet3003', "5.5.5.10/32", ['fd:2::35']) - # The default Vnet setting does not advertise prefix - check_remove_routes_advertisement(dvs, "5.5.5.10/32") - - create_vnet_routes(dvs, "8.8.8.10/32", 'Vnet3004', 'fd:2::36') - vnet_obj.check_vnet_routes(dvs, 'Vnet3003', 'fd:2::36', tunnel_name) - check_state_db_routes(dvs, 'Vnet3004', "8.8.8.10/32", ['fd:2::36']) - # The default Vnet setting does not advertise prefix - check_remove_routes_advertisement(dvs, "8.8.8.10/32") - - # Clean-up and verify remove flows - - delete_vnet_routes(dvs, "5.5.5.10/32", 'Vnet3003') - vnet_obj.check_del_vnet_routes(dvs, 'Vnet3003') - check_remove_state_db_routes(dvs, 'Vnet3003', "5.5.5.10/32") - check_remove_routes_advertisement(dvs, "5.5.5.10/32") - - delete_vnet_routes(dvs, "8.8.8.10/32", 'Vnet3004') - vnet_obj.check_del_vnet_routes(dvs, 'Vnet3004') - check_remove_state_db_routes(dvs, 'Vnet3004', "8.8.8.10/32") - check_remove_routes_advertisement(dvs, "8.8.8.10/32") - - delete_vnet_entry(dvs, 'Vnet3003') - vnet_obj.check_del_vnet_entry(dvs, 'Vnet3003') - - delete_vnet_entry(dvs, 'Vnet3004') - vnet_obj.check_del_vnet_entry(dvs, 'Vnet3004') - - delete_vnet_routes(dvs, "100.100.2.1/24", 'Vnet3002') - vnet_obj.check_del_vnet_routes(dvs, 'Vnet3002') - check_remove_state_db_routes(dvs, 'Vnet3002', "100.100.2.1/24") - check_remove_routes_advertisement(dvs, "100.100.2.1/24") - - delete_vnet_local_routes(dvs, "100.102.1.0/24", 'Vnet3002') - vnet_obj.check_del_vnet_local_routes(dvs, 'Vnet3002') - - delete_phy_interface(dvs, "Ethernet60", "100.102.1.1/24") - vnet_obj.check_del_router_interface(dvs, "Ethernet60") - - delete_vnet_entry(dvs, 'Vnet3002') - vnet_obj.check_del_vnet_entry(dvs, 'Vnet3002') - - delete_vnet_local_routes(dvs, "100.100.3.0/24", 'Vnet3001') - vnet_obj.check_del_vnet_local_routes(dvs, 'Vnet3001') - - delete_vnet_local_routes(dvs, "100.100.4.0/24", 'Vnet3001') - vnet_obj.check_del_vnet_local_routes(dvs, 'Vnet3001') - - delete_vnet_routes(dvs, "100.100.1.1/32", 'Vnet3001') - vnet_obj.check_del_vnet_routes(dvs, 'Vnet3001') - check_remove_state_db_routes(dvs, 'Vnet3001', "100.100.1.1/32") - check_remove_routes_advertisement(dvs, "100.100.1.1/32") - - delete_vnet_routes(dvs, "100.100.1.2/32", 'Vnet3001') - vnet_obj.check_del_vnet_routes(dvs, 'Vnet3001') - check_remove_state_db_routes(dvs, 'Vnet3001', "100.100.1.2/32") - check_remove_routes_advertisement(dvs, "100.100.1.2/32") - - delete_vlan_interface(dvs, "Vlan300", "100.100.3.1/24") - vnet_obj.check_del_router_interface(dvs, "Vlan300") - - delete_vlan_interface(dvs, "Vlan301", "100.100.4.1/24") - vnet_obj.check_del_router_interface(dvs, "Vlan301") - - delete_vnet_entry(dvs, 'Vnet3001') - vnet_obj.check_del_vnet_entry(dvs, 'Vnet3001') - - delete_vxlan_tunnel(dvs, tunnel_name) - vnet_obj.check_del_vxlan_tunnel(dvs) - - ''' - Test 5 - Default VNet test - ''' - def test_vnet_orch_5(self, dvs, testlog): - vnet_obj = self.get_vnet_obj() - - tunnel_name = 'tunnel_5' - - vnet_obj.fetch_exist_entries(dvs) - - create_vxlan_tunnel(dvs, tunnel_name, '8.8.8.8') - create_vnet_entry(dvs, 'Vnet_5', tunnel_name, '4789', "", 'default') - - vnet_obj.check_default_vnet_entry(dvs, 'Vnet_5') - vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, 'Vnet_5', '4789') - - delete_vnet_entry(dvs, 'Vnet_5') - vnet_obj.check_default_vnet_entry(dvs, 'Vnet_5') - - ''' - Test 6 - Test VxLAN tunnel with multiple maps - ''' - def test_vnet_vxlan_multi_map(self, dvs, testlog): - vnet_obj = self.get_vnet_obj() - - tunnel_name = 'tunnel_v4' - - vnet_obj.fetch_exist_entries(dvs) - - create_vxlan_tunnel(dvs, tunnel_name, '10.1.0.32') - create_vnet_entry(dvs, 'Vnet1', tunnel_name, '10001', "") - - vnet_obj.check_vnet_entry(dvs, 'Vnet1') - vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, 'Vnet1', '10001') - vnet_obj.check_vxlan_tunnel(dvs, tunnel_name, '10.1.0.32') - - create_vxlan_tunnel_map(dvs, tunnel_name, 'map_1', 'Vlan1000', '1000') - - delete_vnet_entry(dvs, 'Vnet1') - vnet_obj.check_del_vnet_entry(dvs, 'Vnet1') - delete_vxlan_tunnel(dvs, tunnel_name) - - ''' - Test 7 - Test for vnet tunnel routes with ECMP nexthop group - ''' - def test_vnet_orch_7(self, dvs, ordered_ecmp, testlog): - vnet_obj = self.get_vnet_obj() - - tunnel_name = 'tunnel_7' + ordered_ecmp - vnet_name = 'Vnet7' + ordered_ecmp - - vnet_obj.fetch_exist_entries(dvs) - - create_vxlan_tunnel(dvs, tunnel_name, '7.7.7.7') - create_vnet_entry(dvs, vnet_name, tunnel_name, '10007', "") - - vnet_obj.check_vnet_entry(dvs, vnet_name) - vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, vnet_name, '10007') - - vnet_obj.check_vxlan_tunnel(dvs, tunnel_name, '7.7.7.7') - - # Create an ECMP tunnel route - vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "100.100.1.1/32", vnet_name, '7.0.0.3,7.0.0.2,7.0.0.1') - route1, nhg1_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['7.0.0.1', '7.0.0.2', '7.0.0.3'], tunnel_name, ordered_ecmp=ordered_ecmp, nh_seq_id=['1', '2', '3']) - check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", ['7.0.0.1', '7.0.0.2', '7.0.0.3']) - check_remove_routes_advertisement(dvs, "100.100.1.1/32") - - # Set the tunnel route to another nexthop group - set_vnet_routes(dvs, "100.100.1.1/32", vnet_name, '7.0.0.1,7.0.0.2,7.0.0.4,7.0.0.3') - route1, nhg1_2 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['7.0.0.1', '7.0.0.2', '7.0.0.3', '7.0.0.4'], tunnel_name, route_ids=route1, - ordered_ecmp=ordered_ecmp, nh_seq_id=['1', '2', '3', '4']) - check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", ['7.0.0.1', '7.0.0.2', '7.0.0.3', '7.0.0.4']) - check_remove_routes_advertisement(dvs, "100.100.1.1/32") - - # Check the previous nexthop group is removed - vnet_obj.fetch_exist_entries(dvs) - assert nhg1_1 not in vnet_obj.nhgs - - # Create another tunnel route to the same set of endpoints - create_vnet_routes(dvs, "100.100.2.1/32", vnet_name, '7.0.0.1,7.0.0.2,7.0.0.3,7.0.0.4') - route2, nhg2_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['7.0.0.1', '7.0.0.2', '7.0.0.3', '7.0.0.4'], tunnel_name, - ordered_ecmp=ordered_ecmp, nh_seq_id=['1', '2', '3', '4']) - check_state_db_routes(dvs, vnet_name, "100.100.2.1/32", ['7.0.0.1', '7.0.0.2', '7.0.0.3', '7.0.0.4']) - check_remove_routes_advertisement(dvs, "100.100.2.1/32") - - assert nhg2_1 == nhg1_2 - - # Remove one of the tunnel routes - delete_vnet_routes(dvs, "100.100.1.1/32", vnet_name) - vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["100.100.1.1/32"]) - check_remove_state_db_routes(dvs, vnet_name, "100.100.1.1/32") - check_remove_routes_advertisement(dvs, "100.100.1.1/32") - - # Check the nexthop group still exists - vnet_obj.fetch_exist_entries(dvs) - assert nhg1_2 in vnet_obj.nhgs - - # Remove the other tunnel route - delete_vnet_routes(dvs, "100.100.2.1/32", vnet_name) - vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["100.100.2.1/32"]) - check_remove_state_db_routes(dvs, vnet_name, "100.100.2.1/32") - check_remove_routes_advertisement(dvs, "100.100.2.1/32") - - # Check the nexthop group is removed - vnet_obj.fetch_exist_entries(dvs) - assert nhg2_1 not in vnet_obj.nhgs - - delete_vnet_entry(dvs, vnet_name) - vnet_obj.check_del_vnet_entry(dvs, vnet_name) - delete_vxlan_tunnel(dvs, tunnel_name) - - ''' - Test 8 - Test for ipv6 vnet tunnel routes with ECMP nexthop group - ''' - def test_vnet_orch_8(self, dvs, ordered_ecmp, testlog): - - vnet_obj = self.get_vnet_obj() - - tunnel_name = 'tunnel_8' + ordered_ecmp - vnet_name = 'Vnet8' + ordered_ecmp - - - vnet_obj.fetch_exist_entries(dvs) - - create_vxlan_tunnel(dvs, tunnel_name, 'fd:8::32') - create_vnet_entry(dvs, vnet_name, tunnel_name, '10008', "") - - vnet_obj.check_vnet_entry(dvs, vnet_name) - vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, vnet_name, '10008') - - vnet_obj.check_vxlan_tunnel(dvs, tunnel_name, 'fd:8::32') - - # Create an ECMP tunnel route - vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "fd:8:10::32/128", vnet_name, 'fd:8:1::1,fd:8:1::3,fd:8:1::2') - route1, nhg1_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['fd:8:1::1', 'fd:8:1::2', 'fd:8:1::3'], tunnel_name, ordered_ecmp=ordered_ecmp, nh_seq_id=['1', '2', '3']) - check_state_db_routes(dvs, vnet_name, "fd:8:10::32/128", ['fd:8:1::1', 'fd:8:1::2', 'fd:8:1::3']) - check_remove_routes_advertisement(dvs, "fd:8:10::32/128") - - # Set the tunnel route to another nexthop group - set_vnet_routes(dvs, "fd:8:10::32/128", vnet_name, 'fd:8:1::2,fd:8:1::3,fd:8:1::1,fd:8:1::4') - route1, nhg1_2 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['fd:8:1::1', 'fd:8:1::2', 'fd:8:1::3', 'fd:8:1::4'], tunnel_name, route_ids=route1, - ordered_ecmp=ordered_ecmp, nh_seq_id=['1', '2', '3', '4']) - check_state_db_routes(dvs, vnet_name, "fd:8:10::32/128", ['fd:8:1::1', 'fd:8:1::2', 'fd:8:1::3', 'fd:8:1::4']) - check_remove_routes_advertisement(dvs, "fd:8:10::32/128") - - # Check the previous nexthop group is removed - vnet_obj.fetch_exist_entries(dvs) - assert nhg1_1 not in vnet_obj.nhgs - - # Create another tunnel route to the same set of endpoints - create_vnet_routes(dvs, "fd:8:20::32/128", vnet_name, 'fd:8:1::1,fd:8:1::2,fd:8:1::3,fd:8:1::4') - route2, nhg2_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['fd:8:1::1', 'fd:8:1::2', 'fd:8:1::3', 'fd:8:1::4'], tunnel_name, - ordered_ecmp=ordered_ecmp, nh_seq_id=['1', '2', '3', '4']) - check_state_db_routes(dvs, vnet_name, "fd:8:20::32/128", ['fd:8:1::1', 'fd:8:1::2', 'fd:8:1::3', 'fd:8:1::4']) - check_remove_routes_advertisement(dvs, "fd:8:20::32/128") - - assert nhg2_1 == nhg1_2 - - # Create another tunnel route with ipv4 prefix to the same set of endpoints - create_vnet_routes(dvs, "8.0.0.0/24", vnet_name, 'fd:8:1::1,fd:8:1::2,fd:8:1::3,fd:8:1::4') - route3, nhg3_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['fd:8:1::1', 'fd:8:1::2', 'fd:8:1::3', 'fd:8:1::4'], tunnel_name, - ordered_ecmp=ordered_ecmp, nh_seq_id=['1', '2', '3', '4']) - check_state_db_routes(dvs, vnet_name, "8.0.0.0/24", ['fd:8:1::1', 'fd:8:1::2', 'fd:8:1::3', 'fd:8:1::4']) - check_remove_routes_advertisement(dvs, "8.0.0.0/24") - - assert nhg3_1 == nhg1_2 - - # Remove one of the tunnel routes - delete_vnet_routes(dvs, "fd:8:10::32/128", vnet_name) - vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["fd:8:10::32/128"]) - check_remove_state_db_routes(dvs, vnet_name, "fd:8:10::32/128") - check_remove_routes_advertisement(dvs, "fd:8:10::32/128") - - # Check the nexthop group still exists - vnet_obj.fetch_exist_entries(dvs) - assert nhg1_2 in vnet_obj.nhgs - - # Remove tunnel route 2 - delete_vnet_routes(dvs, "fd:8:20::32/128", vnet_name) - vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["fd:8:20::32/128"]) - check_remove_state_db_routes(dvs, vnet_name, "fd:8:20::32/128") - check_remove_routes_advertisement(dvs, "fd:8:20::32/128") - - # Remove tunnel route 3 - delete_vnet_routes(dvs, "8.0.0.0/24", vnet_name) - vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["8.0.0.0/24"]) - check_remove_state_db_routes(dvs, vnet_name, "8.0.0.0/24") - check_remove_routes_advertisement(dvs, "8.0.0.0/24") - - # Check the nexthop group is removed - vnet_obj.fetch_exist_entries(dvs) - assert nhg2_1 not in vnet_obj.nhgs - - delete_vnet_entry(dvs, vnet_name) - vnet_obj.check_del_vnet_entry(dvs, vnet_name) - delete_vxlan_tunnel(dvs, tunnel_name) - - - ''' - Test 9 - Test for vnet tunnel routes with ECMP nexthop group with endpoint health monitor - ''' - def test_vnet_orch_9(self, dvs, ordered_ecmp, testlog): - vnet_obj = self.get_vnet_obj() - - tunnel_name = 'tunnel_9' + ordered_ecmp - vnet_name = 'Vnet9' + ordered_ecmp - - vnet_obj.fetch_exist_entries(dvs) - - create_vxlan_tunnel(dvs, tunnel_name, '9.9.9.9') - create_vnet_entry(dvs, vnet_name, tunnel_name, '10009', "") - - vnet_obj.check_vnet_entry(dvs, vnet_name) - vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, vnet_name, '10009') - - vnet_obj.check_vxlan_tunnel(dvs, tunnel_name, '9.9.9.9') - - vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "100.100.1.1/32", vnet_name, '9.0.0.1,9.0.0.2,9.0.0.3', ep_monitor='9.1.0.1,9.1.0.2,9.1.0.3') - - # default bfd status is down, route should not be programmed in this status - vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["100.100.1.1/32"]) - check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", []) - check_remove_routes_advertisement(dvs, "100.100.1.1/32") - - # Route should be properly configured when all bfd session states go up - update_bfd_session_state(dvs, '9.1.0.2', 'Up') - update_bfd_session_state(dvs, '9.1.0.3', 'Up') - update_bfd_session_state(dvs, '9.1.0.1', 'Up') - time.sleep(2) - route1, nhg1_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['9.0.0.1', '9.0.0.2', '9.0.0.3'], tunnel_name, ordered_ecmp=ordered_ecmp, nh_seq_id=['1', '2', '3']) - check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", ['9.0.0.1', '9.0.0.2', '9.0.0.3']) - check_remove_routes_advertisement(dvs, "100.100.1.1/32") - - # Remove endpoint from group if it goes down - update_bfd_session_state(dvs, '9.1.0.2', 'Down') - time.sleep(2) - route1, nhg1_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['9.0.0.1', '9.0.0.3'], tunnel_name, route_ids=route1, nhg=nhg1_1, ordered_ecmp=ordered_ecmp, nh_seq_id=['1', '3']) - check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", ['9.0.0.1', '9.0.0.3']) - check_remove_routes_advertisement(dvs, "100.100.1.1/32") - - # Create another tunnel route with endpoint group overlapped with route1 - vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "100.100.2.1/32", vnet_name, '9.0.0.1,9.0.0.2,9.0.0.5', ep_monitor='9.1.0.1,9.1.0.2,9.1.0.5') - route2, nhg2_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['9.0.0.1'], tunnel_name, ordered_ecmp=ordered_ecmp, nh_seq_id=['1']) - check_state_db_routes(dvs, vnet_name, "100.100.2.1/32", ['9.0.0.1']) - check_remove_routes_advertisement(dvs, "100.100.1.1/32") - - # Update BFD session state and verify route change - update_bfd_session_state(dvs, '9.1.0.5', 'Up') - time.sleep(2) - route2, nhg2_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['9.0.0.1', '9.0.0.5'], tunnel_name, route_ids=route2, nhg=nhg2_1, ordered_ecmp=ordered_ecmp, nh_seq_id=['1', '3']) - check_state_db_routes(dvs, vnet_name, "100.100.2.1/32", ['9.0.0.1', '9.0.0.5']) - check_remove_routes_advertisement(dvs, "100.100.2.1/32") - - # Update BFD state and check route nexthop - update_bfd_session_state(dvs, '9.1.0.3', 'Down') - time.sleep(2) - - route1, nhg1_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['9.0.0.1'], tunnel_name, route_ids=route1, nhg=nhg1_1, ordered_ecmp=ordered_ecmp, nh_seq_id=['1']) - check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", ['9.0.0.1']) - check_remove_routes_advertisement(dvs, "100.100.1.1/32") - - # Set the route1 to a new group - set_vnet_routes(dvs, "100.100.1.1/32", vnet_name, '9.0.0.1,9.0.0.2,9.0.0.3,9.0.0.4', ep_monitor='9.1.0.1,9.1.0.2,9.1.0.3,9.1.0.4') - update_bfd_session_state(dvs, '9.1.0.4', 'Up') - time.sleep(2) - route1, nhg1_2 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['9.0.0.1', '9.0.0.4'], tunnel_name, route_ids=route1, ordered_ecmp=ordered_ecmp, nh_seq_id=['1', '4']) - check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", ['9.0.0.1', '9.0.0.4']) - check_remove_routes_advertisement(dvs, "100.100.1.1/32") - - # Check the previous nexthop group is removed - vnet_obj.fetch_exist_entries(dvs) - assert nhg1_1 not in vnet_obj.nhgs - - # Set BFD session state for a down endpoint to up - update_bfd_session_state(dvs, '9.1.0.2', 'Up') - time.sleep(2) - route1, nhg1_2 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['9.0.0.1', '9.0.0.2', '9.0.0.4'], tunnel_name, route_ids=route1, nhg=nhg1_2, ordered_ecmp=ordered_ecmp, nh_seq_id=['1', '2', '4']) - check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", ['9.0.0.1', '9.0.0.2', '9.0.0.4']) - check_remove_routes_advertisement(dvs, "100.100.1.1/32") - - # Set all endpoint to down state - update_bfd_session_state(dvs, '9.1.0.1', 'Down') - update_bfd_session_state(dvs, '9.1.0.2', 'Down') - update_bfd_session_state(dvs, '9.1.0.3', 'Down') - update_bfd_session_state(dvs, '9.1.0.4', 'Down') - time.sleep(2) - - # Confirm the tunnel route is updated in ASIC - vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["100.100.1.1/32"]) - route2, nhg2_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['9.0.0.5'], tunnel_name, route_ids=route2, nhg=nhg2_1, ordered_ecmp=ordered_ecmp, nh_seq_id=['3']) - check_state_db_routes(dvs, vnet_name, "100.100.2.1/32", ['9.0.0.5']) - check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", []) - check_remove_routes_advertisement(dvs, "100.100.1.1/32") - # The default Vnet setting does not advertise prefix - check_remove_routes_advertisement(dvs, "100.100.2.1/32") - - # Remove tunnel route2 - delete_vnet_routes(dvs, "100.100.2.1/32", vnet_name) - vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["100.100.2.1/32"]) - check_remove_state_db_routes(dvs, vnet_name, "100.100.2.1/32") - check_remove_routes_advertisement(dvs, "100.100.2.1/32") - - # Check the corresponding nexthop group is removed - vnet_obj.fetch_exist_entries(dvs) - assert nhg2_1 not in vnet_obj.nhgs - - # Check the BFD session specific to the endpoint group is removed while others exist - check_del_bfd_session(dvs, ['9.1.0.5']) - check_bfd_session(dvs, ['9.1.0.1', '9.1.0.2', '9.1.0.3', '9.1.0.4']) - - # Remove tunnel route 1 - delete_vnet_routes(dvs, "100.100.1.1/32", vnet_name) - vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["100.100.1.1/32"]) - check_remove_state_db_routes(dvs, vnet_name, "100.100.1.1/32") - check_remove_routes_advertisement(dvs, "100.100.1.1/32") - - # Check the previous nexthop group is removed - vnet_obj.fetch_exist_entries(dvs) - assert nhg1_2 not in vnet_obj.nhgs - - # Confirm the BFD sessions are removed - check_del_bfd_session(dvs, ['9.1.0.1', '9.1.0.2', '9.1.0.3', '9.1.0.4', '9.1.0.5']) - - delete_vnet_entry(dvs, vnet_name) - vnet_obj.check_del_vnet_entry(dvs, vnet_name) - delete_vxlan_tunnel(dvs, tunnel_name) - - - ''' - Test 10 - Test for ipv6 vnet tunnel routes with ECMP nexthop group with endpoint health monitor - ''' - def test_vnet_orch_10(self, dvs, ordered_ecmp, testlog): - vnet_obj = self.get_vnet_obj() - - tunnel_name = 'tunnel_10' + ordered_ecmp - vnet_name = 'Vnet10' + ordered_ecmp - - vnet_obj.fetch_exist_entries(dvs) - - create_vxlan_tunnel(dvs, tunnel_name, 'fd:10::32') - create_vnet_entry(dvs, vnet_name, tunnel_name, '10010', "") - - vnet_obj.check_vnet_entry(dvs, vnet_name) - vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, vnet_name, '10010') - - vnet_obj.check_vxlan_tunnel(dvs, tunnel_name, 'fd:10::32') - - vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "fd:10:10::1/128", vnet_name, 'fd:10:1::1,fd:10:1::2,fd:10:1::3', ep_monitor='fd:10:2::1,fd:10:2::2,fd:10:2::3') - - # default bfd status is down, route should not be programmed in this status - vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["fd:10:10::1/128"]) - check_state_db_routes(dvs, vnet_name, "fd:10:10::1/128", []) - check_remove_routes_advertisement(dvs, "fd:10:10::1/128") - - # Route should be properly configured when all bfd session states go up - update_bfd_session_state(dvs, 'fd:10:2::2', 'Up') - update_bfd_session_state(dvs, 'fd:10:2::3', 'Up') - update_bfd_session_state(dvs, 'fd:10:2::1', 'Up') - time.sleep(2) - route1, nhg1_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['fd:10:1::1', 'fd:10:1::2', 'fd:10:1::3'], tunnel_name, ordered_ecmp=ordered_ecmp, nh_seq_id=['1', '2', '3']) - check_state_db_routes(dvs, vnet_name, "fd:10:10::1/128", ['fd:10:1::1', 'fd:10:1::2', 'fd:10:1::3']) - check_remove_routes_advertisement(dvs, "fd:10:10::1/128") - - # Remove endpoint from group if it goes down - update_bfd_session_state(dvs, 'fd:10:2::2', 'Down') - time.sleep(2) - route1, nhg1_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['fd:10:1::1', 'fd:10:1::3'], tunnel_name, route_ids=route1, nhg=nhg1_1, ordered_ecmp=ordered_ecmp, nh_seq_id=['1', '3']) - check_state_db_routes(dvs, vnet_name, "fd:10:10::1/128", ['fd:10:1::1', 'fd:10:1::3']) - check_remove_routes_advertisement(dvs, "fd:10:10::1/128") - - # Create another tunnel route with endpoint group overlapped with route1 - vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "fd:10:20::1/128", vnet_name, 'fd:10:1::1,fd:10:1::2,fd:10:1::5', ep_monitor='fd:10:2::1,fd:10:2::2,fd:10:2::5') - route2, nhg2_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['fd:10:1::1'], tunnel_name, ordered_ecmp=ordered_ecmp, nh_seq_id=['1']) - check_state_db_routes(dvs, vnet_name, "fd:10:20::1/128", ['fd:10:1::1']) - check_remove_routes_advertisement(dvs, "fd:10:20::1/128") - - # Update BFD session state and verify route change - update_bfd_session_state(dvs, 'fd:10:2::5', 'Up') - time.sleep(2) - route2, nhg2_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['fd:10:1::1', 'fd:10:1::5'], tunnel_name, route_ids=route2, nhg=nhg2_1, ordered_ecmp=ordered_ecmp, nh_seq_id=['1', '3']) - check_state_db_routes(dvs, vnet_name, "fd:10:20::1/128", ['fd:10:1::1', 'fd:10:1::5']) - check_remove_routes_advertisement(dvs, "fd:10:20::1/128") - - # Update BFD state and check route nexthop - update_bfd_session_state(dvs, 'fd:10:2::3', 'Down') - update_bfd_session_state(dvs, 'fd:10:2::2', 'Up') - time.sleep(2) - - route1, nhg1_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['fd:10:1::1', 'fd:10:1::2'], tunnel_name, route_ids=route1, nhg=nhg1_1, ordered_ecmp=ordered_ecmp, nh_seq_id=['1', '2']) - check_state_db_routes(dvs, vnet_name, "fd:10:10::1/128", ['fd:10:1::1', 'fd:10:1::2']) - check_remove_routes_advertisement(dvs, "fd:10:10::1/128") - - # Set the route to a new group - set_vnet_routes(dvs, "fd:10:10::1/128", vnet_name, 'fd:10:1::1,fd:10:1::2,fd:10:1::3,fd:10:1::4', ep_monitor='fd:10:2::1,fd:10:2::2,fd:10:2::3,fd:10:2::4') - update_bfd_session_state(dvs, 'fd:10:2::4', 'Up') - time.sleep(2) - route1, nhg1_2 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['fd:10:1::1', 'fd:10:1::2', 'fd:10:1::4'], tunnel_name, route_ids=route1, ordered_ecmp=ordered_ecmp, nh_seq_id=['1', '2', '4']) - check_state_db_routes(dvs, vnet_name, "fd:10:10::1/128", ['fd:10:1::1', 'fd:10:1::2', 'fd:10:1::4']) - check_remove_routes_advertisement(dvs, "fd:10:10::1/128") - # Check the previous nexthop group is removed - vnet_obj.fetch_exist_entries(dvs) - assert nhg1_1 not in vnet_obj.nhgs - - # Set BFD session state for a down endpoint to up - update_bfd_session_state(dvs, 'fd:10:2::3', 'Up') - time.sleep(2) - route1, nhg1_2 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['fd:10:1::1', 'fd:10:1::2', 'fd:10:1::3', 'fd:10:1::4'], tunnel_name, route_ids=route1, nhg=nhg1_2, - ordered_ecmp=ordered_ecmp, nh_seq_id=['1', '2', '3', '4']) - check_state_db_routes(dvs, vnet_name, "fd:10:10::1/128", ['fd:10:1::1', 'fd:10:1::2', 'fd:10:1::3', 'fd:10:1::4']) - check_remove_routes_advertisement(dvs, "fd:10:10::1/128") - - # Set all endpoint to down state - update_bfd_session_state(dvs, 'fd:10:2::1', 'Down') - update_bfd_session_state(dvs, 'fd:10:2::2', 'Down') - update_bfd_session_state(dvs, 'fd:10:2::3', 'Down') - update_bfd_session_state(dvs, 'fd:10:2::4', 'Down') - time.sleep(2) - - # Confirm the tunnel route is updated in ASIC - vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["fd:10:10::1/128"]) - route2, nhg2_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['fd:10:1::5'], tunnel_name, route_ids=route2, nhg=nhg2_1, ordered_ecmp=ordered_ecmp, nh_seq_id=['3']) - check_state_db_routes(dvs, vnet_name, "fd:10:20::1/128", ['fd:10:1::5']) - check_state_db_routes(dvs, vnet_name, "fd:10:10::1/128", []) - check_remove_routes_advertisement(dvs, "fd:10:10::1/128") - # The default Vnet setting does not advertise prefix - check_remove_routes_advertisement(dvs, "fd:10:20::1/128") - - # Remove tunnel route2 - delete_vnet_routes(dvs, "fd:10:20::1/128", vnet_name) - vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["fd:10:20::1/128"]) - check_remove_state_db_routes(dvs, vnet_name, "fd:10:20::1/128") - check_remove_routes_advertisement(dvs, "fd:10:20::1/128") - - # Check the corresponding nexthop group is removed - vnet_obj.fetch_exist_entries(dvs) - assert nhg2_1 not in vnet_obj.nhgs - - # Check the BFD session specific to the endpoint group is removed while others exist - check_del_bfd_session(dvs, ['fd:10:2::5']) - check_bfd_session(dvs, ['fd:10:2::1', 'fd:10:2::2', 'fd:10:2::3', 'fd:10:2::4']) - - # Check the BFD session specific to the endpoint group is removed while others exist - check_del_bfd_session(dvs, ['fd:10:2::5']) - check_bfd_session(dvs, ['fd:10:2::1', 'fd:10:2::2', 'fd:10:2::3', 'fd:10:2::4']) - - # Remove tunnel route 1 - delete_vnet_routes(dvs, "fd:10:10::1/128", vnet_name) - vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["fd:10:10::1/128"]) - check_remove_state_db_routes(dvs, vnet_name, "fd:10:10::1/128") - check_remove_routes_advertisement(dvs, "fd:10:10::1/128") - - # Confirm the BFD sessions are removed - check_del_bfd_session(dvs, ['fd:10:2::1', 'fd:10:2::2', 'fd:10:2::3', 'fd:10:2::4', 'fd:10:2::5']) - - # Check the previous nexthop group is removed - vnet_obj.fetch_exist_entries(dvs) - assert nhg1_2 not in vnet_obj.nhgs - - delete_vnet_entry(dvs, vnet_name) - vnet_obj.check_del_vnet_entry(dvs, vnet_name) - delete_vxlan_tunnel(dvs, tunnel_name) - - ''' - Test 11 - Test for vnet tunnel routes with both single endpoint and ECMP group with endpoint health monitor - ''' - def test_vnet_orch_11(self, dvs, ordered_ecmp, testlog): - vnet_obj = self.get_vnet_obj() - - tunnel_name = 'tunnel_11' + ordered_ecmp - vnet_name = 'Vnet11' + ordered_ecmp - - vnet_obj.fetch_exist_entries(dvs) - - create_vxlan_tunnel(dvs, tunnel_name, '11.11.11.11') - create_vnet_entry(dvs, vnet_name, tunnel_name, '100011', "") - - vnet_obj.check_vnet_entry(dvs, vnet_name) - vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, vnet_name, '100011') - - vnet_obj.check_vxlan_tunnel(dvs, tunnel_name, '11.11.11.11') - - vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "100.100.1.1/32", vnet_name, '11.0.0.1', ep_monitor='11.1.0.1') - - # default bfd status is down, route should not be programmed in this status - vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["100.100.1.1/32"]) - check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", []) - check_remove_routes_advertisement(dvs, "100.100.1.1/32") - - # Route should be properly configured when bfd session state goes up - update_bfd_session_state(dvs, '11.1.0.1', 'Up') - time.sleep(2) - vnet_obj.check_vnet_routes(dvs, vnet_name, '11.0.0.1', tunnel_name) - check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", ['11.0.0.1']) - check_remove_routes_advertisement(dvs, "100.100.1.1/32") - - # Create another tunnel route with endpoint group overlapped with route1 - vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "100.100.2.1/32", vnet_name, '11.0.0.2,11.0.0.1', ep_monitor='11.1.0.2,11.1.0.1') - route2, nhg2_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['11.0.0.1'], tunnel_name, ordered_ecmp=ordered_ecmp, nh_seq_id=['1']) - check_state_db_routes(dvs, vnet_name, "100.100.2.1/32", ['11.0.0.1']) - check_remove_routes_advertisement(dvs, "100.100.2.1/32") - - # Create a third tunnel route with another endpoint - vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "100.100.3.1/32", vnet_name, '11.0.0.2', ep_monitor='11.1.0.2') - - # Update BFD session state and verify route change - update_bfd_session_state(dvs, '11.1.0.2', 'Up') - time.sleep(2) - vnet_obj.check_vnet_routes(dvs, vnet_name, '11.0.0.2', tunnel_name) - route2, nhg2_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['11.0.0.1', '11.0.0.2'], tunnel_name, route_ids=route2, nhg=nhg2_1, ordered_ecmp=ordered_ecmp, nh_seq_id=['1', '2']) - check_state_db_routes(dvs, vnet_name, "100.100.3.1/32", ['11.0.0.2']) - check_state_db_routes(dvs, vnet_name, "100.100.2.1/32", ['11.0.0.1', '11.0.0.2']) - check_remove_routes_advertisement(dvs, "100.100.2.1/32") - # The default Vnet setting does not advertise prefix - check_remove_routes_advertisement(dvs, "100.100.3.1/32") - - - update_bfd_session_state(dvs, '11.1.0.1', 'Down') - time.sleep(2) - route2, nhg2_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['11.0.0.2'], tunnel_name, route_ids=route2, nhg=nhg2_1, ordered_ecmp=ordered_ecmp, nh_seq_id=['2']) - vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["100.100.1.1/32"]) - check_state_db_routes(dvs, vnet_name, "100.100.2.1/32", ['11.0.0.2']) - check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", []) - check_remove_routes_advertisement(dvs, "100.100.1.1/32") - # The default Vnet setting does not advertise prefix - check_remove_routes_advertisement(dvs, "100.100.2.1/32") - - - # Set the route1 to a new endpoint - vnet_obj.fetch_exist_entries(dvs) - set_vnet_routes(dvs, "100.100.1.1/32", vnet_name, '11.0.0.2', ep_monitor='11.1.0.2') - vnet_obj.check_vnet_routes(dvs, vnet_name, '11.0.0.2', tunnel_name) - check_state_db_routes(dvs, vnet_name, "100.100.3.1/32", ['11.0.0.2']) - check_remove_routes_advertisement(dvs, "100.100.3.1/32") - - # Remove tunnel route2 - delete_vnet_routes(dvs, "100.100.2.1/32", vnet_name) - vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["100.100.2.1/32"]) - check_remove_state_db_routes(dvs, vnet_name, "100.100.2.1/32") - check_remove_routes_advertisement(dvs, "100.100.2.1/32") - - # Check the corresponding nexthop group is removed - vnet_obj.fetch_exist_entries(dvs) - assert nhg2_1 not in vnet_obj.nhgs - - # Check the BFD session specific to the endpoint group is removed while others exist - check_del_bfd_session(dvs, ['11.1.0.1']) - check_bfd_session(dvs, ['11.1.0.2']) - - # Remove tunnel route 1 - delete_vnet_routes(dvs, "100.100.1.1/32", vnet_name) - vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["100.100.1.1/32"]) - check_remove_state_db_routes(dvs, vnet_name, "100.100.1.1/32") - check_remove_routes_advertisement(dvs, "100.100.1.1/32") - - # Remove tunnel route 3 - delete_vnet_routes(dvs, "100.100.3.1/32", vnet_name) - vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["100.100.3.1/32"]) - check_remove_state_db_routes(dvs, vnet_name, "100.100.3.1/32") - check_remove_routes_advertisement(dvs, "100.100.3.1/32") - - # Confirm the BFD sessions are removed - check_del_bfd_session(dvs, ['11.1.0.1', '11.1.0.2']) - - delete_vnet_entry(dvs, vnet_name) - vnet_obj.check_del_vnet_entry(dvs, vnet_name) - delete_vxlan_tunnel(dvs, tunnel_name) - - - ''' - Test 12 - Test for vnet tunnel routes with ECMP nexthop group with endpoint health monitor and route advertisement - ''' - def test_vnet_orch_12(self, dvs, testlog): - vnet_obj = self.get_vnet_obj() - - tunnel_name = 'tunnel_12' - - vnet_obj.fetch_exist_entries(dvs) - - create_vxlan_tunnel(dvs, tunnel_name, '12.12.12.12') - create_vnet_entry(dvs, 'Vnet12', tunnel_name, '10012', "", advertise_prefix=True) - - vnet_obj.check_vnet_entry(dvs, 'Vnet12') - vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, 'Vnet12', '10012') - - vnet_obj.check_vxlan_tunnel(dvs, tunnel_name, '12.12.12.12') - - vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "100.100.1.1/32", 'Vnet12', '12.0.0.1,12.0.0.2,12.0.0.3', ep_monitor='12.1.0.1,12.1.0.2,12.1.0.3', profile="test_profile") - - # default bfd status is down, route should not be programmed in this status - vnet_obj.check_del_vnet_routes(dvs, 'Vnet12', ["100.100.1.1/32"]) - check_state_db_routes(dvs, 'Vnet12', "100.100.1.1/32", []) - check_remove_routes_advertisement(dvs, "100.100.1.1/32") - - # Route should be properly configured when all bfd session states go up - update_bfd_session_state(dvs, '12.1.0.1', 'Up') - update_bfd_session_state(dvs, '12.1.0.2', 'Up') - update_bfd_session_state(dvs, '12.1.0.3', 'Up') - time.sleep(2) - route1, nhg1_1 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet12', ['12.0.0.1', '12.0.0.2', '12.0.0.3'], tunnel_name) - check_state_db_routes(dvs, 'Vnet12', "100.100.1.1/32", ['12.0.0.1', '12.0.0.2', '12.0.0.3']) - check_routes_advertisement(dvs, "100.100.1.1/32", "test_profile") - - # Remove endpoint from group if it goes down - update_bfd_session_state(dvs, '12.1.0.2', 'Down') - time.sleep(2) - route1, nhg1_1 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet12', ['12.0.0.1', '12.0.0.3'], tunnel_name, route_ids=route1, nhg=nhg1_1) - check_state_db_routes(dvs, 'Vnet12', "100.100.1.1/32", ['12.0.0.1', '12.0.0.3']) - check_routes_advertisement(dvs, "100.100.1.1/32", "test_profile") - - # Create another tunnel route with endpoint group overlapped with route1 - vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "100.100.2.1/32", 'Vnet12', '12.0.0.1,12.0.0.2,12.0.0.5', ep_monitor='12.1.0.1,12.1.0.2,12.1.0.5') - route2, nhg2_1 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet12', ['12.0.0.1'], tunnel_name) - check_state_db_routes(dvs, 'Vnet12', "100.100.2.1/32", ['12.0.0.1']) - check_routes_advertisement(dvs, "100.100.1.1/32") - - # Update BFD session state and verify route change - update_bfd_session_state(dvs, '12.1.0.5', 'Up') - time.sleep(2) - route2, nhg2_1 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet12', ['12.0.0.1', '12.0.0.5'], tunnel_name, route_ids=route2, nhg=nhg2_1) - check_state_db_routes(dvs, 'Vnet12', "100.100.2.1/32", ['12.0.0.1', '12.0.0.5']) - check_routes_advertisement(dvs, "100.100.2.1/32") - - # Update BFD state and check route nexthop - update_bfd_session_state(dvs, '12.1.0.3', 'Down') - time.sleep(2) - - route1, nhg1_1 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet12', ['12.0.0.1'], tunnel_name, route_ids=route1, nhg=nhg1_1) - check_state_db_routes(dvs, 'Vnet12', "100.100.1.1/32", ['12.0.0.1']) - check_routes_advertisement(dvs, "100.100.1.1/32", "test_profile") - - # Set the route1 to a new group - set_vnet_routes(dvs, "100.100.1.1/32", 'Vnet12', '12.0.0.1,12.0.0.2,12.0.0.3,12.0.0.4', ep_monitor='12.1.0.1,12.1.0.2,12.1.0.3,12.1.0.4', profile="test_profile2") - update_bfd_session_state(dvs, '12.1.0.4', 'Up') - time.sleep(2) - route1, nhg1_2 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet12', ['12.0.0.1', '12.0.0.4'], tunnel_name, route_ids=route1) - check_state_db_routes(dvs, 'Vnet12', "100.100.1.1/32", ['12.0.0.1', '12.0.0.4']) - check_routes_advertisement(dvs, "100.100.1.1/32", "test_profile2") - - # Check the previous nexthop group is removed - vnet_obj.fetch_exist_entries(dvs) - assert nhg1_1 not in vnet_obj.nhgs - - # Set BFD session state for a down endpoint to up - update_bfd_session_state(dvs, '12.1.0.2', 'Up') - time.sleep(2) - route1, nhg1_2 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet12', ['12.0.0.1', '12.0.0.2', '12.0.0.4'], tunnel_name, route_ids=route1, nhg=nhg1_2) - check_state_db_routes(dvs, 'Vnet12', "100.100.1.1/32", ['12.0.0.1', '12.0.0.2', '12.0.0.4']) - check_routes_advertisement(dvs, "100.100.1.1/32", "test_profile2") - - # Set all endpoint to down state - update_bfd_session_state(dvs, '12.1.0.1', 'Down') - update_bfd_session_state(dvs, '12.1.0.2', 'Down') - update_bfd_session_state(dvs, '12.1.0.3', 'Down') - update_bfd_session_state(dvs, '12.1.0.4', 'Down') - time.sleep(2) - - # Confirm the tunnel route is updated in ASIC - vnet_obj.check_del_vnet_routes(dvs, 'Vnet12', ["100.100.1.1/32"]) - route2, nhg2_1 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet12', ['12.0.0.5'], tunnel_name, route_ids=route2, nhg=nhg2_1) - check_state_db_routes(dvs, 'Vnet12', "100.100.2.1/32", ['12.0.0.5']) - check_state_db_routes(dvs, 'Vnet12', "100.100.1.1/32", []) - check_remove_routes_advertisement(dvs, "100.100.1.1/32") - check_routes_advertisement(dvs, "100.100.2.1/32") - - # Remove tunnel route2 - delete_vnet_routes(dvs, "100.100.2.1/32", 'Vnet12') - vnet_obj.check_del_vnet_routes(dvs, 'Vnet12', ["100.100.2.1/32"]) - check_remove_state_db_routes(dvs, 'Vnet12', "100.100.2.1/32") - check_remove_routes_advertisement(dvs, "100.100.2.1/32") - - # Check the corresponding nexthop group is removed - vnet_obj.fetch_exist_entries(dvs) - assert nhg2_1 not in vnet_obj.nhgs - - # Check the BFD session specific to the endpoint group is removed while others exist - check_del_bfd_session(dvs, ['12.1.0.5']) - check_bfd_session(dvs, ['12.1.0.1', '12.1.0.2', '12.1.0.3', '12.1.0.4']) - - # Remove tunnel route 1 - delete_vnet_routes(dvs, "100.100.1.1/32", 'Vnet12') - vnet_obj.check_del_vnet_routes(dvs, 'Vnet12', ["100.100.1.1/32"]) - check_remove_state_db_routes(dvs, 'Vnet12', "100.100.1.1/32") - check_remove_routes_advertisement(dvs, "100.100.1.1/32") - - # Check the previous nexthop group is removed - vnet_obj.fetch_exist_entries(dvs) - assert nhg1_2 not in vnet_obj.nhgs - - # Confirm the BFD sessions are removed - check_del_bfd_session(dvs, ['12.1.0.1', '12.1.0.2', '12.1.0.3', '12.1.0.4', '12.1.0.5']) - - delete_vnet_entry(dvs, 'Vnet12') - vnet_obj.check_del_vnet_entry(dvs, 'Vnet12') - delete_vxlan_tunnel(dvs, tunnel_name) - - ''' - Test 13 - Test for configuration idempotent behaviour - ''' - def test_vnet_orch_13(self, dvs, testlog): - vnet_obj = self.get_vnet_obj() - - tunnel_name = 'tunnel_13' - vnet_obj.fetch_exist_entries(dvs) - - create_vxlan_tunnel(dvs, tunnel_name, 'fd:8::32') - create_vnet_entry(dvs, 'Vnet13', tunnel_name, '10008', "") - - vnet_obj.check_vnet_entry(dvs, 'Vnet13') - vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, 'Vnet13', '10008') - - vnet_obj.check_vxlan_tunnel(dvs, tunnel_name, 'fd:8::32') - - # Create an ECMP tunnel route - vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "fd:8:10::32/128", 'Vnet13', 'fd:8:1::1,fd:8:1::2,fd:8:1::3') - route1, nhg1_1 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet13', ['fd:8:1::1', 'fd:8:1::2', 'fd:8:1::3'], tunnel_name) - check_state_db_routes(dvs, 'Vnet13', "fd:8:10::32/128", ['fd:8:1::1', 'fd:8:1::2', 'fd:8:1::3']) - # The default Vnet setting does not advertise prefix - check_remove_routes_advertisement(dvs, "fd:8:10::32/128") - - # readd same tunnel again - set_vnet_routes(dvs, "fd:8:10::32/128", 'Vnet13', 'fd:8:1::1,fd:8:1::2,fd:8:1::3') - route1, nhg1_2 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet13', ['fd:8:1::1', 'fd:8:1::2', 'fd:8:1::3'], tunnel_name, route_ids=route1) - check_state_db_routes(dvs, 'Vnet13', "fd:8:10::32/128", ['fd:8:1::1', 'fd:8:1::2', 'fd:8:1::3']) - # The default Vnet setting does not advertise prefix - check_remove_routes_advertisement(dvs, "fd:8:10::32/128") - # Check only one group is present - vnet_obj.fetch_exist_entries(dvs) - assert nhg1_1 in vnet_obj.nhgs - assert len(vnet_obj.nhgs) == 1 - assert nhg1_1 == nhg1_2 - - # Remove one of the tunnel routes - delete_vnet_routes(dvs, "fd:8:10::32/128", 'Vnet13') - vnet_obj.check_del_vnet_routes(dvs, 'Vnet13', ["fd:8:10::32/128"]) - check_remove_state_db_routes(dvs, 'Vnet13', "fd:8:10::32/128") - check_remove_routes_advertisement(dvs, "fd:8:10::32/128") - - # Check the nexthop group still exists - vnet_obj.fetch_exist_entries(dvs) - assert nhg1_2 not in vnet_obj.nhgs - assert len(vnet_obj.nhgs) == 0 - delete_vnet_entry(dvs, 'Vnet13') - vnet_obj.check_del_vnet_entry(dvs, 'Vnet13') - - ''' - Test 14 - Test for configuration idempotent behaviour 2 - ''' - def test_vnet_orch_14(self, dvs, testlog): - vnet_obj = self.get_vnet_obj() - - tunnel_name = 'tunnel_14' - vnet_obj.fetch_exist_entries(dvs) - - create_vxlan_tunnel(dvs, tunnel_name, 'fd:8::32') - create_vnet_entry(dvs, 'Vnet14', tunnel_name, '10008', "") - - vnet_obj.check_vnet_entry(dvs, 'Vnet14') - vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, 'Vnet14', '10008') - - vnet_obj.check_vxlan_tunnel(dvs, tunnel_name, 'fd:8::32') - - # Create an ECMP tunnel route - vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "fd:8:10::32/128", 'Vnet14', 'fd:8:1::1,fd:8:1::2,fd:8:1::3') - route1, nhg1_1 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet14', ['fd:8:1::1', 'fd:8:1::2', 'fd:8:1::3'], tunnel_name) - check_state_db_routes(dvs, 'Vnet14', "fd:8:10::32/128", ['fd:8:1::1', 'fd:8:1::2', 'fd:8:1::3']) - # The default Vnet setting does not advertise prefix - check_remove_routes_advertisement(dvs, "fd:8:10::32/128") - - # readd same tunnel again - set_vnet_routes(dvs, "fd:8:10::32/128", 'Vnet14', 'fd:8:1::1,fd:8:1::2,fd:8:1::3') - route1, nhg1_2 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet14', ['fd:8:1::1', 'fd:8:1::2', 'fd:8:1::3'], tunnel_name, route_ids=route1) - check_state_db_routes(dvs, 'Vnet14', "fd:8:10::32/128", ['fd:8:1::1', 'fd:8:1::2', 'fd:8:1::3']) - # The default Vnet setting does not advertise prefix - check_remove_routes_advertisement(dvs, "fd:8:10::32/128") - - #update nexthops for the same tunnel. - set_vnet_routes(dvs, "fd:8:10::32/128", 'Vnet14', 'fd:8:1::1,fd:8:1::2,fd:8:1::3,fd:8:1::4') - route1, nhg1_2 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet14', ['fd:8:1::1', 'fd:8:1::2', 'fd:8:1::3', 'fd:8:1::4'], tunnel_name, route_ids=route1) - check_state_db_routes(dvs, 'Vnet14', "fd:8:10::32/128", ['fd:8:1::1', 'fd:8:1::2', 'fd:8:1::3', 'fd:8:1::4']) - # The default Vnet setting does not advertise prefix - check_remove_routes_advertisement(dvs, "fd:8:10::32/128") - - # Check the previous nexthop group is removed - vnet_obj.fetch_exist_entries(dvs) - assert nhg1_1 not in vnet_obj.nhgs - assert nhg1_2 in vnet_obj.nhgs - - # Remove the tunnel route - delete_vnet_routes(dvs, "fd:8:10::32/128", 'Vnet14') - vnet_obj.check_del_vnet_routes(dvs, 'Vnet14', ["fd:8:10::32/128"]) - check_remove_state_db_routes(dvs, 'Vnet14', "fd:8:10::32/128") - check_remove_routes_advertisement(dvs, "fd:8:10::32/128") - # Remove the tunnel route - delete_vnet_routes(dvs, "fd:8:10::32/128", 'Vnet14') - vnet_obj.check_del_vnet_routes(dvs, 'Vnet14', ["fd:8:10::32/128"]) - check_remove_state_db_routes(dvs, 'Vnet14', "fd:8:10::32/128") - check_remove_routes_advertisement(dvs, "fd:8:10::32/128") - - # Check the nexthop group still exists - vnet_obj.fetch_exist_entries(dvs) - assert nhg1_2 not in vnet_obj.nhgs - assert nhg1_1 not in vnet_obj.nhgs - - delete_vnet_entry(dvs, 'Vnet14') - vnet_obj.check_del_vnet_entry(dvs, 'Vnet14') - delete_vxlan_tunnel(dvs, tunnel_name) - - ''' - Test 15 - Test for configuration idempotent behaviour single endpoint - ''' - def test_vnet_orch_15(self, dvs, testlog): - vnet_obj = self.get_vnet_obj() - - tunnel_name = 'tunnel_15' - vnet_obj.fetch_exist_entries(dvs) - - create_vxlan_tunnel(dvs, tunnel_name, 'fd:8::32') - create_vnet_entry(dvs, 'Vnet15', tunnel_name, '10008', "") - - vnet_obj.check_vnet_entry(dvs, 'Vnet15') - vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, 'Vnet15', '10008') - - vnet_obj.check_vxlan_tunnel(dvs, tunnel_name, 'fd:8::32') - - # Create an tunnel route - vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "fd:8:10::32/128", 'Vnet15', 'fd:8:1::1') - route1 = vnet_obj.check_vnet_routes(dvs, 'Vnet15', 'fd:8:1::1', tunnel_name) - check_state_db_routes(dvs, 'Vnet15', "fd:8:10::32/128", ['fd:8:1::1']) - # The default Vnet setting does not advertise prefix - check_remove_routes_advertisement(dvs, "fd:8:10::32/128") - - # readd same tunnel again - set_vnet_routes(dvs, "fd:8:10::32/128", 'Vnet15', 'fd:8:1::1') - route1 = vnet_obj.check_vnet_routes(dvs, 'Vnet15', 'fd:8:1::1', tunnel_name, route_ids=route1) - check_state_db_routes(dvs, 'Vnet15', "fd:8:10::32/128", ['fd:8:1::1']) - # The default Vnet setting does not advertise prefix - check_remove_routes_advertisement(dvs, "fd:8:10::32/128") - # Check only one group is present - vnet_obj.fetch_exist_entries(dvs) - assert len(vnet_obj.nhops) == 1 - - # Remove one of the tunnel routes - delete_vnet_routes(dvs, "fd:8:10::32/128", 'Vnet15') - vnet_obj.check_del_vnet_routes(dvs, 'Vnet15', ["fd:8:10::32/128"]) - check_remove_state_db_routes(dvs, 'Vnet15', "fd:8:10::32/128") - check_remove_routes_advertisement(dvs, "fd:8:10::32/128") - - # Check the nexthop group still exists - vnet_obj.fetch_exist_entries(dvs) - assert len(vnet_obj.nhops) == 0 - delete_vnet_entry(dvs, 'Vnet15') - vnet_obj.check_del_vnet_entry(dvs, 'Vnet15') - delete_vxlan_tunnel(dvs, tunnel_name) - - ''' - Test 16 - Test for configuration idempotent behaviour single endpoint with BFD - ''' - def test_vnet_orch_16(self, dvs, testlog): - vnet_obj = self.get_vnet_obj() - - tunnel_name = 'tunnel_16' - vnet_obj.fetch_exist_entries(dvs) - - create_vxlan_tunnel(dvs, tunnel_name, 'fd:8::33') - create_vnet_entry(dvs, 'Vnet16', tunnel_name, '10008', "") - - vnet_obj.check_vnet_entry(dvs, 'Vnet16') - vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, 'Vnet16', '10008') - - vnet_obj.check_vxlan_tunnel(dvs, tunnel_name, 'fd:8::33') - - # Create a tunnel route - vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "fd:8:11::32/128", 'Vnet16', 'fd:8:2::1', ep_monitor='fd:8:2::1') - update_bfd_session_state(dvs, 'fd:8:2::1', 'Up') - time.sleep(2) - - route1 = vnet_obj.check_vnet_routes(dvs, 'Vnet16', 'fd:8:2::1', tunnel_name) - check_state_db_routes(dvs, 'Vnet16', "fd:8:11::32/128", ['fd:8:2::1']) - # The default Vnet setting does not advertise prefix - check_remove_routes_advertisement(dvs, "fd:8:11::32/128") - - # readd same tunnel again - set_vnet_routes(dvs, "fd:8:11::32/128", 'Vnet16', 'fd:8:2::1', ep_monitor='fd:8:2::1') - route1 = vnet_obj.check_vnet_routes(dvs, 'Vnet16', 'fd:8:2::1', tunnel_name, route_ids=route1) - check_state_db_routes(dvs, 'Vnet16', "fd:8:11::32/128", ['fd:8:2::1']) - # The default Vnet setting does not advertise prefix - check_remove_routes_advertisement(dvs, "fd:8:11::32/128") - # Check only one group is present - vnet_obj.fetch_exist_entries(dvs) - assert len(vnet_obj.nhops) == 1 - - update_bfd_session_state(dvs, 'fd:8:2::1', 'Down') - time.sleep(2) - # readd same tunnel again - set_vnet_routes(dvs, "fd:8:11::32/128", 'Vnet16', 'fd:8:2::1', ep_monitor='fd:8:2::1') - - update_bfd_session_state(dvs, 'fd:8:2::1', 'Up') - time.sleep(2) - - route1 = vnet_obj.check_vnet_routes(dvs, 'Vnet16', 'fd:8:2::1', tunnel_name,route_ids=route1) - check_state_db_routes(dvs, 'Vnet16', "fd:8:11::32/128", ['fd:8:2::1']) - # The default Vnet setting does not advertise prefix - check_remove_routes_advertisement(dvs, "fd:8:11::32/128") - - - # Remove one of the tunnel routes - delete_vnet_routes(dvs, "fd:8:11::32/128", 'Vnet16') - vnet_obj.check_del_vnet_routes(dvs, 'Vnet16', ["fd:8:11::32/128"]) - check_remove_state_db_routes(dvs, 'Vnet16', "fd:8:11::32/128") - check_remove_routes_advertisement(dvs, "fd:8:11::32/128") - - # Check the nexthop group still exists - vnet_obj.fetch_exist_entries(dvs) - assert len(vnet_obj.nhops) == 0 - delete_vnet_entry(dvs, 'Vnet16') - vnet_obj.check_del_vnet_entry(dvs, 'Vnet16') - delete_vxlan_tunnel(dvs, tunnel_name) - - ''' - Test 17 - Test for configuration idempotent behaviour multiple endpoint with BFD - ''' - def test_vnet_orch_17(self, dvs, testlog): - vnet_obj = self.get_vnet_obj() - - tunnel_name = 'tunnel_17' - - vnet_obj.fetch_exist_entries(dvs) - - create_vxlan_tunnel(dvs, tunnel_name, '9.9.9.9') - create_vnet_entry(dvs, 'Vnet17', tunnel_name, '10017', "") - - vnet_obj.check_vnet_entry(dvs, 'Vnet17') - vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, 'Vnet17', '10017') - - vnet_obj.check_vxlan_tunnel(dvs, tunnel_name, '9.9.9.9') - - vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "100.100.1.1/32", 'Vnet17', '9.0.0.1,9.0.0.2,9.0.0.3', ep_monitor='9.1.0.1,9.1.0.2,9.1.0.3') - - # default bfd status is down, route should not be programmed in this status - vnet_obj.check_del_vnet_routes(dvs, 'Vnet17', ["100.100.1.1/32"]) - check_state_db_routes(dvs, 'Vnet17', "100.100.1.1/32", []) - check_remove_routes_advertisement(dvs, "100.100.1.1/32") - - #readd the route - set_vnet_routes(dvs, "100.100.1.1/32", 'Vnet17', '9.0.0.1,9.0.0.2,9.0.0.3',ep_monitor='9.1.0.1,9.1.0.2,9.1.0.3') - vnet_obj.check_del_vnet_routes(dvs, 'Vnet17', ["100.100.1.1/32"]) - check_state_db_routes(dvs, 'Vnet17', "100.100.1.1/32", []) - check_remove_routes_advertisement(dvs, "100.100.1.1/32") - - # Route should be properly configured when all bfd session states go up - update_bfd_session_state(dvs, '9.1.0.1', 'Up') - update_bfd_session_state(dvs, '9.1.0.2', 'Up') - update_bfd_session_state(dvs, '9.1.0.3', 'Up') - time.sleep(2) - - route1, nhg1_1 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet17', ['9.0.0.1', '9.0.0.2', '9.0.0.3'], tunnel_name) - check_state_db_routes(dvs, 'Vnet17', "100.100.1.1/32", ['9.0.0.1', '9.0.0.2', '9.0.0.3']) - # The default Vnet setting does not advertise prefix - check_remove_routes_advertisement(dvs, "100.100.1.1/32") - - #readd the active route - set_vnet_routes(dvs, "100.100.1.1/32", 'Vnet17', '9.0.0.1,9.0.0.2,9.0.0.3',ep_monitor='9.1.0.1,9.1.0.2,9.1.0.3') - route2, nhg1_2 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet17', ['9.0.0.1', '9.0.0.2', '9.0.0.3'], tunnel_name, route_ids=route1, nhg=nhg1_1) - check_state_db_routes(dvs, 'Vnet17', "100.100.1.1/32", ['9.0.0.1', '9.0.0.2', '9.0.0.3']) - # The default Vnet setting does not advertise prefix - check_remove_routes_advertisement(dvs, "100.100.1.1/32") - assert nhg1_1 == nhg1_2 - assert len(vnet_obj.nhgs) == 1 - - # Remove tunnel route - delete_vnet_routes(dvs, "100.100.1.1/32", 'Vnet17') - vnet_obj.check_del_vnet_routes(dvs, 'Vnet17', ["100.100.1.1/32"]) - check_remove_state_db_routes(dvs, 'Vnet17', "100.100.1.1/32") - check_remove_routes_advertisement(dvs, "100.100.1.1/32") - - # Check the corresponding nexthop group is removed - vnet_obj.fetch_exist_entries(dvs) - assert nhg1_1 not in vnet_obj.nhgs - # Check the BFD session specific to the endpoint group is removed while others exist - check_del_bfd_session(dvs, ['9.1.0.1', '9.1.0.2', '9.1.0.3']) - - delete_vnet_entry(dvs, 'Vnet17') - vnet_obj.check_del_vnet_entry(dvs, 'Vnet17') - delete_vxlan_tunnel(dvs, tunnel_name) - - ''' - Test 18 - Test for priority vnet tunnel routes with ECMP nexthop group. test primary secondary switchover. - ''' - def test_vnet_orch_18(self, dvs, testlog): - vnet_obj = self.get_vnet_obj() - tunnel_name = 'tunnel_18' - vnet_name = 'vnet18' - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - - vnet_obj.fetch_exist_entries(dvs) - - create_vxlan_tunnel(dvs, tunnel_name, '9.9.9.9') - create_vnet_entry(dvs, vnet_name, tunnel_name, '10018', "", advertise_prefix=True, overlay_dmac="22:33:33:44:44:66") - - vnet_obj.check_vnet_entry(dvs, vnet_name) - vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, vnet_name, '10018') - - vnet_obj.check_vxlan_tunnel(dvs, tunnel_name, '9.9.9.9') - - vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "100.100.1.1/32", vnet_name, '9.1.0.1,9.1.0.2,9.1.0.3,9.1.0.4', ep_monitor='9.1.0.1,9.1.0.2,9.1.0.3,9.1.0.4', primary ='9.1.0.1,9.1.0.2', monitoring='custom', adv_prefix='100.100.1.0/24') - - # default monitor status is down, route should not be programmed in this status - vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["100.100.1.1/32"]) - check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", []) - check_remove_routes_advertisement(dvs, "100.100.1.0/24") - - # Route should be properly configured when all monitor session states go up. Only primary Endpoints should be in use. - update_monitor_session_state(dvs, '100.100.1.1/32', '9.1.0.1', 'up') - update_monitor_session_state(dvs, '100.100.1.1/32', '9.1.0.2', 'up') - update_monitor_session_state(dvs, '100.100.1.1/32', '9.1.0.3', 'up') - update_monitor_session_state(dvs, '100.100.1.1/32', '9.1.0.4', 'up') - - time.sleep(2) - route1 = vnet_obj.check_priority_vnet_ecmp_routes(dvs, vnet_name, ['9.1.0.1','9.1.0.2'], tunnel_name) - check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", ['9.1.0.1','9.1.0.2']) - # The default Vnet setting does not advertise prefix - check_routes_advertisement(dvs, "100.100.1.0/24") - - # Remove first primary endpoint from group. - update_monitor_session_state(dvs, '100.100.1.1/32', '9.1.0.2', 'down') - time.sleep(2) - route1= vnet_obj.check_priority_vnet_ecmp_routes(dvs, vnet_name, ['9.1.0.1'], tunnel_name, route_ids=route1) - check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", ['9.1.0.1']) - # The default Vnet setting does not advertise prefix - check_routes_advertisement(dvs, "100.100.1.0/24") - - # Switch to secondary if both primary down - update_monitor_session_state(dvs, '100.100.1.1/32', '9.1.0.1', 'down') - time.sleep(2) - route1 = vnet_obj.check_priority_vnet_ecmp_routes(dvs, vnet_name, ['9.1.0.3','9.1.0.4'], tunnel_name, route_ids=route1) - check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", ['9.1.0.3','9.1.0.4']) - # The default Vnet setting does not advertise prefix - check_routes_advertisement(dvs, "100.100.1.0/24") - - # removing first endpoint of secondary. route should remain on secondary NHG - update_monitor_session_state(dvs, '100.100.1.1/32', '9.1.0.3', 'down') - time.sleep(2) - route1 = vnet_obj.check_priority_vnet_ecmp_routes(dvs, vnet_name, ['9.1.0.4'], tunnel_name, route_ids=route1) - check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", ['9.1.0.4']) - # The default Vnet setting does not advertise prefix - check_routes_advertisement(dvs, "100.100.1.0/24") - - # removing last endpoint of secondary. route should be removed - update_monitor_session_state(dvs, '100.100.1.1/32', '9.1.0.4', 'down') - time.sleep(2) - - new_nhgs = get_all_created_entries(asic_db, vnet_obj.ASIC_NEXT_HOP_GROUP, []) - assert len(new_nhgs) == 0 - check_remove_routes_advertisement(dvs, "100.100.1.0/24") - vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["100.100.1.1/32"]) - check_remove_state_db_routes(dvs, vnet_name, "100.100.1.1/32") - - #Route should come up with secondary endpoints. - update_monitor_session_state(dvs, '100.100.1.1/32', '9.1.0.3', 'up') - update_monitor_session_state(dvs, '100.100.1.1/32', '9.1.0.4', 'up') - - time.sleep(2) - route1 = vnet_obj.check_priority_vnet_ecmp_routes(dvs, vnet_name, ['9.1.0.3','9.1.0.4'], tunnel_name, route_ids=route1) - check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", ['9.1.0.3','9.1.0.4']) - # The default Vnet setting does not advertise prefix - check_routes_advertisement(dvs, "100.100.1.0/24") - - #Route should be switched to the primary endpoint. - update_monitor_session_state(dvs, '100.100.1.1/32', '9.1.0.1', 'up') - time.sleep(2) - route1= vnet_obj.check_priority_vnet_ecmp_routes(dvs, vnet_name, ['9.1.0.1'], tunnel_name, route_ids=route1) - check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", ['9.1.0.1']) - # The default Vnet setting does not advertise prefix - check_routes_advertisement(dvs, "100.100.1.0/24") - - #Route should be updated with the second primary endpoint. - update_monitor_session_state(dvs, '100.100.1.1/32', '9.1.0.2', 'up') - time.sleep(2) - route1 = vnet_obj.check_priority_vnet_ecmp_routes(dvs, vnet_name, ['9.1.0.1','9.1.0.2'], tunnel_name, route_ids=route1) - check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", ['9.1.0.1','9.1.0.2']) - # The default Vnet setting does not advertise prefix - check_routes_advertisement(dvs, "100.100.1.0/24") - - #Route should not be impacted by seconday endpoints going down. - update_monitor_session_state(dvs, '100.100.1.1/32', '9.1.0.3', 'down') - update_monitor_session_state(dvs, '100.100.1.1/32', '9.1.0.4', 'down') - time.sleep(2) - route1 = vnet_obj.check_priority_vnet_ecmp_routes(dvs, vnet_name, ['9.1.0.1','9.1.0.2'], tunnel_name, route_ids=route1) - check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", ['9.1.0.1','9.1.0.2']) - # The default Vnet setting does not advertise prefix - check_routes_advertisement(dvs, "100.100.1.0/24") - - #Route should not be impacted by seconday endpoints coming back up. - update_monitor_session_state(dvs, '100.100.1.1/32', '9.1.0.3', 'up') - update_monitor_session_state(dvs, '100.100.1.1/32', '9.1.0.4', 'up') - time.sleep(2) - route1 = vnet_obj.check_priority_vnet_ecmp_routes(dvs, vnet_name, ['9.1.0.1','9.1.0.2'], tunnel_name, route_ids=route1) - check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", ['9.1.0.1','9.1.0.2']) - # The default Vnet setting does not advertise prefix - check_routes_advertisement(dvs, "100.100.1.0/24") - - # Remove tunnel route 1 - delete_vnet_routes(dvs, "100.100.1.1/32", vnet_name) - time.sleep(2) - vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["100.100.1.1/32"]) - check_remove_state_db_routes(dvs, vnet_name, "100.100.1.1/32") - check_remove_routes_advertisement(dvs, "100.100.1.0/24") - - # Confirm the monitor sessions are removed - vnet_obj.check_custom_monitor_deleted(dvs, "100.100.1.1/32", "9.1.0.1") - vnet_obj.check_custom_monitor_deleted(dvs, "100.100.1.1/32", "9.1.0.2") - vnet_obj.check_custom_monitor_deleted(dvs, "100.100.1.1/32", "9.1.0.3") - vnet_obj.check_custom_monitor_deleted(dvs, "100.100.1.1/32", "9.1.0.4") - - delete_vnet_entry(dvs, vnet_name) - vnet_obj.check_del_vnet_entry(dvs, vnet_name) - delete_vxlan_tunnel(dvs, tunnel_name) - - ''' - Test 19 - Test for 2 priority vnet tunnel routes with overlapping primary secondary ECMP nexthop group. - ''' - def test_vnet_orch_19(self, dvs, testlog): - vnet_obj = self.get_vnet_obj() - tunnel_name = 'tunnel_19' - vnet_name = 'Vnet19' - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - - vnet_obj.fetch_exist_entries(dvs) - - create_vxlan_tunnel(dvs, tunnel_name, '9.9.9.19') - create_vnet_entry(dvs, vnet_name, tunnel_name, '10019', "", advertise_prefix=True, overlay_dmac="22:33:33:44:44:66") - - vnet_obj.check_vnet_entry(dvs, vnet_name) - vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, vnet_name, '10019') - - vnet_obj.check_vxlan_tunnel(dvs, tunnel_name, '9.9.9.19') - - vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "100.100.1.1/32", vnet_name, '9.1.0.1,9.1.0.2,9.1.0.3,9.1.0.4', ep_monitor='9.1.0.1,9.1.0.2,9.1.0.3,9.1.0.4', profile="Test_profile", primary ='9.1.0.1,9.1.0.2', monitoring='custom', adv_prefix='100.100.1.0/24') - create_vnet_routes(dvs, "200.100.1.1/32", vnet_name, '9.1.0.1,9.1.0.2,9.1.0.3,9.1.0.4', ep_monitor='9.1.0.1,9.1.0.2,9.1.0.3,9.1.0.4', primary ='9.1.0.3,9.1.0.4', monitoring='custom', adv_prefix='200.100.1.0/24') - - # default monitor session status is down, route should not be programmed in this status - vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["100.100.1.1/32"]) - check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", []) - check_remove_routes_advertisement(dvs, "100.100.1.0/24") - - vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["200.100.1.1/32"]) - check_state_db_routes(dvs, vnet_name, "200.100.1.1/32", []) - check_remove_routes_advertisement(dvs, "200.100.1.0/24") - - # Route should be properly configured when all monitor session states go up. Only primary Endpoints should be in use. - update_monitor_session_state(dvs, '100.100.1.1/32', '9.1.0.1', 'up') - time.sleep(2) - route1 = vnet_obj.check_priority_vnet_ecmp_routes(dvs, vnet_name, ['9.1.0.1'], tunnel_name, prefix="100.100.1.1/32") - check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", ['9.1.0.1']) - check_routes_advertisement(dvs, "100.100.1.0/24", "Test_profile") - - update_monitor_session_state(dvs, '200.100.1.1/32', '9.1.0.1', 'up') - time.sleep(2) - route2 = vnet_obj.check_priority_vnet_ecmp_routes(dvs, vnet_name, ['9.1.0.1'], tunnel_name, route_ids=route1, prefix="200.100.1.1/32") - check_state_db_routes(dvs, vnet_name, "200.100.1.1/32", ['9.1.0.1']) - check_routes_advertisement(dvs, "200.100.1.0/24", "") - - update_monitor_session_state(dvs, '100.100.1.1/32', '9.1.0.2', 'up') - time.sleep(2) - route1 = vnet_obj.check_priority_vnet_ecmp_routes(dvs, vnet_name, ['9.1.0.1','9.1.0.2'], tunnel_name, route_ids=route1, prefix="100.100.1.1/32") - check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", ['9.1.0.1','9.1.0.2']) - check_routes_advertisement(dvs, "100.100.1.0/24", "Test_profile") - - update_monitor_session_state(dvs, '200.100.1.1/32', '9.1.0.2', 'up') - time.sleep(2) - route2 = vnet_obj.check_priority_vnet_ecmp_routes(dvs, vnet_name, ['9.1.0.1','9.1.0.2'], tunnel_name, route_ids=route1, prefix="200.100.1.1/32") - check_state_db_routes(dvs, vnet_name, "200.100.1.1/32", ['9.1.0.1','9.1.0.2']) - check_routes_advertisement(dvs, "200.100.1.0/24", "") - - update_monitor_session_state(dvs, '100.100.1.1/32', '9.1.0.3', 'up') - update_monitor_session_state(dvs, '200.100.1.1/32', '9.1.0.3', 'up') - time.sleep(2) - - route1 = vnet_obj.check_priority_vnet_ecmp_routes(dvs, vnet_name, ['9.1.0.1','9.1.0.2'], tunnel_name, route_ids=route1, prefix="100.100.1.1/32") - check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", ['9.1.0.1','9.1.0.2']) - check_routes_advertisement(dvs, "100.100.1.0/24", "Test_profile") - - route2 = vnet_obj.check_priority_vnet_ecmp_routes(dvs, vnet_name, ['9.1.0.3'], tunnel_name, route_ids=route1, prefix="200.100.1.1/32") - check_state_db_routes(dvs, vnet_name, "200.100.1.1/32", ['9.1.0.3']) - check_routes_advertisement(dvs, "200.100.1.0/24", "") - - update_monitor_session_state(dvs, '100.100.1.1/32', '9.1.0.4', 'up') - update_monitor_session_state(dvs, '200.100.1.1/32', '9.1.0.4', 'up') - time.sleep(2) - route1 = vnet_obj.check_priority_vnet_ecmp_routes(dvs, vnet_name, ['9.1.0.1','9.1.0.2'], tunnel_name, route_ids=route1, prefix="100.100.1.1/32") - check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", ['9.1.0.1','9.1.0.2']) - check_routes_advertisement(dvs, "100.100.1.0/24", "Test_profile") - - route2 = vnet_obj.check_priority_vnet_ecmp_routes(dvs, vnet_name, ['9.1.0.3','9.1.0.4'], tunnel_name, route_ids=route1, prefix="200.100.1.1/32") - check_state_db_routes(dvs, vnet_name, "200.100.1.1/32", ['9.1.0.3','9.1.0.4']) - check_routes_advertisement(dvs, "200.100.1.0/24", "") - - update_monitor_session_state(dvs, '100.100.1.1/32', '9.1.0.1', 'down') - update_monitor_session_state(dvs, '200.100.1.1/32', '9.1.0.1', 'down') - time.sleep(2) - route1 = vnet_obj.check_priority_vnet_ecmp_routes(dvs, vnet_name, ['9.1.0.2'], tunnel_name, route_ids=route1, prefix="100.100.1.1/32") - check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", ['9.1.0.2']) - check_routes_advertisement(dvs, "100.100.1.0/24", "Test_profile") - - route2 = vnet_obj.check_priority_vnet_ecmp_routes(dvs, vnet_name, ['9.1.0.3','9.1.0.4'], tunnel_name, route_ids=route1, prefix="200.100.1.1/32") - check_state_db_routes(dvs, vnet_name, "200.100.1.1/32", ['9.1.0.3','9.1.0.4']) - check_routes_advertisement(dvs, "200.100.1.0/24", "") - - update_monitor_session_state(dvs, '100.100.1.1/32', '9.1.0.2', 'down') - update_monitor_session_state(dvs, '200.100.1.1/32', '9.1.0.2', 'down') - time.sleep(2) - route1 = vnet_obj.check_priority_vnet_ecmp_routes(dvs, vnet_name, ['9.1.0.3','9.1.0.4'], tunnel_name, route_ids=route1, prefix="100.100.1.1/32") - check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", ['9.1.0.3','9.1.0.4']) - check_routes_advertisement(dvs, "100.100.1.0/24", "Test_profile") - - route2 = vnet_obj.check_priority_vnet_ecmp_routes(dvs, vnet_name, ['9.1.0.3','9.1.0.4'], tunnel_name, route_ids=route1, prefix="200.100.1.1/32") - check_state_db_routes(dvs, vnet_name, "200.100.1.1/32", ['9.1.0.3','9.1.0.4']) - check_routes_advertisement(dvs, "200.100.1.0/24", "") - - update_monitor_session_state(dvs, '100.100.1.1/32', '9.1.0.3', 'down') - update_monitor_session_state(dvs, '200.100.1.1/32', '9.1.0.3', 'down') - time.sleep(2) - route1 = vnet_obj.check_priority_vnet_ecmp_routes(dvs, vnet_name, ['9.1.0.4'], tunnel_name, route_ids=route1, prefix="100.100.1.1/32") - check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", ['9.1.0.4']) - check_routes_advertisement(dvs, "100.100.1.0/24", "Test_profile") - - route2 = vnet_obj.check_priority_vnet_ecmp_routes(dvs, vnet_name, ['9.1.0.4'], tunnel_name, route_ids=route1, prefix="200.100.1.1/32") - check_state_db_routes(dvs, vnet_name, "200.100.1.1/32", ['9.1.0.4']) - check_routes_advertisement(dvs, "200.100.1.0/24", "") - - update_monitor_session_state(dvs, '100.100.1.1/32', '9.1.0.4', 'down') - update_monitor_session_state(dvs, '200.100.1.1/32', '9.1.0.4', 'down') - time.sleep(2) - - #we should still have two NHGs but no active route - new_nhgs = get_all_created_entries(asic_db, vnet_obj.ASIC_NEXT_HOP_GROUP, vnet_obj.nhgs) - assert len(new_nhgs) == 0 - check_remove_routes_advertisement(dvs, "100.100.1.1/32") - check_remove_routes_advertisement(dvs, "200.100.1.1/32") - vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["100.100.1.1/32"]) - vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["200.100.1.1/32"]) - check_remove_state_db_routes(dvs, vnet_name, "100.100.1.1/32") - check_remove_state_db_routes(dvs, vnet_name, "200.100.1.1/32") - check_remove_routes_advertisement(dvs, "100.100.1.0/24") - check_remove_routes_advertisement(dvs, "200.100.1.0/24") - - # Remove tunnel route 1 - delete_vnet_routes(dvs, "100.100.1.1/32", vnet_name) - delete_vnet_routes(dvs, "200.100.1.1/32", vnet_name) - - vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["100.100.1.1/32"]) - vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["200.100.1.1/32"]) - - check_remove_state_db_routes(dvs, vnet_name, "100.100.1.1/32") - check_remove_state_db_routes(dvs, vnet_name, "200.100.1.1/32") - - check_remove_routes_advertisement(dvs, "100.100.1.0/24") - check_remove_routes_advertisement(dvs, "200.100.1.0/24") - - - # Confirm the monitor sessions are removed - vnet_obj.check_custom_monitor_deleted(dvs, "100.100.1.1/32", "9.1.0.1") - vnet_obj.check_custom_monitor_deleted(dvs, "100.100.1.1/32", "9.1.0.2") - vnet_obj.check_custom_monitor_deleted(dvs, "100.100.1.1/32", "9.1.0.3") - vnet_obj.check_custom_monitor_deleted(dvs, "100.100.1.1/32", "9.1.0.4") - - vnet_obj.check_custom_monitor_deleted(dvs, "200.100.1.1/32", "9.1.0.1") - vnet_obj.check_custom_monitor_deleted(dvs, "200.100.1.1/32", "9.1.0.2") - vnet_obj.check_custom_monitor_deleted(dvs, "200.100.1.1/32", "9.1.0.3") - vnet_obj.check_custom_monitor_deleted(dvs, "200.100.1.1/32", "9.1.0.4") - - delete_vnet_entry(dvs, vnet_name) - vnet_obj.check_del_vnet_entry(dvs, vnet_name) - delete_vxlan_tunnel(dvs, tunnel_name) - - ''' - Test 20 - Test for Single enpoint priority vnet tunnel routes. Test primary secondary switchover. - ''' - def test_vnet_orch_20(self, dvs, testlog): - vnet_obj = self.get_vnet_obj() - tunnel_name = 'tunnel_20' - vnet_name = 'Vnet20' - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - - vnet_obj.fetch_exist_entries(dvs) - - create_vxlan_tunnel(dvs, tunnel_name, '9.9.9.9') - create_vnet_entry(dvs, vnet_name, tunnel_name, '10020', "", advertise_prefix=True, overlay_dmac="22:33:33:44:44:66") - - vnet_obj.check_vnet_entry(dvs, vnet_name) - vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, vnet_name, '10020') - - vnet_obj.check_vxlan_tunnel(dvs, tunnel_name, '9.9.9.9') - - vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "100.100.1.1/32", vnet_name, '9.1.0.1,9.1.0.2', ep_monitor='9.1.0.1,9.1.0.2', primary ='9.1.0.1', profile="Test_profile", monitoring='custom', adv_prefix='100.100.1.0/24') - - # default monitor session status is down, route should not be programmed in this status - vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["100.100.1.1/32"]) - check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", []) - check_remove_routes_advertisement(dvs, "100.100.1.0/24") - - # Route should be properly configured when all monitor session states go up. Only primary Endpoints should be in use. - update_monitor_session_state(dvs, '100.100.1.1/32', '9.1.0.1', 'up') - update_monitor_session_state(dvs, '100.100.1.1/32', '9.1.0.2', 'up') - time.sleep(2) - nhids = get_all_created_entries(asic_db, vnet_obj.ASIC_NEXT_HOP,set()) - tbl_nh = swsscommon.Table(asic_db, vnet_obj.ASIC_NEXT_HOP) - nexthops = dict() - for nhid in nhids: - status, nh_fvs = tbl_nh.get(nhid) - nh_fvs = dict(nh_fvs) - for key in nh_fvs.keys(): - if key == 'SAI_NEXT_HOP_ATTR_IP': - nexthops[nh_fvs[key]] = nhid - assert len(nexthops.keys()) == 1 - - route = get_created_entries(asic_db, vnet_obj.ASIC_ROUTE_ENTRY, vnet_obj.routes, 1) - check_object(asic_db, vnet_obj.ASIC_ROUTE_ENTRY, route[0], - { - "SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID": nexthops['9.1.0.1'], - } - ) - check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", ['9.1.0.1']) - check_routes_advertisement(dvs, "100.100.1.0/24", "Test_profile") - - update_monitor_session_state(dvs, '100.100.1.1/32', '9.1.0.2', 'down') - time.sleep(2) - - route = get_created_entries(asic_db, vnet_obj.ASIC_ROUTE_ENTRY, vnet_obj.routes, 1) - check_object(asic_db, vnet_obj.ASIC_ROUTE_ENTRY, route[0], - { - "SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID": nexthops['9.1.0.1'], - } - ) - check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", ['9.1.0.1']) - check_routes_advertisement(dvs, "100.100.1.0/24", "Test_profile") - - update_monitor_session_state(dvs, '100.100.1.1/32', '9.1.0.1', 'down') - update_monitor_session_state(dvs, '100.100.1.1/32', '9.1.0.2', 'up') - - time.sleep(2) - - nhids = get_all_created_entries(asic_db, vnet_obj.ASIC_NEXT_HOP,set()) - tbl_nh = swsscommon.Table(asic_db, vnet_obj.ASIC_NEXT_HOP) - nexthops = dict() - for nhid in nhids: - status, nh_fvs = tbl_nh.get(nhid) - nh_fvs = dict(nh_fvs) - for key in nh_fvs.keys(): - if key == 'SAI_NEXT_HOP_ATTR_IP': - nexthops[nh_fvs[key]] = nhid - assert len(nexthops.keys()) == 1 - - route = get_created_entries(asic_db, vnet_obj.ASIC_ROUTE_ENTRY, vnet_obj.routes, 1) - check_object(asic_db, vnet_obj.ASIC_ROUTE_ENTRY, route[0], - { - "SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID": nexthops['9.1.0.2'], - } - ) - check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", ['9.1.0.2']) - check_routes_advertisement(dvs, "100.100.1.0/24", "Test_profile") - - update_monitor_session_state(dvs, '100.100.1.1/32', '9.1.0.1', 'up') - time.sleep(2) - - nhids = get_all_created_entries(asic_db, vnet_obj.ASIC_NEXT_HOP,set()) - tbl_nh = swsscommon.Table(asic_db, vnet_obj.ASIC_NEXT_HOP) - nexthops = dict() - for nhid in nhids: - status, nh_fvs = tbl_nh.get(nhid) - nh_fvs = dict(nh_fvs) - for key in nh_fvs.keys(): - if key == 'SAI_NEXT_HOP_ATTR_IP': - nexthops[nh_fvs[key]] = nhid - assert len(nexthops.keys()) == 1 - - route = get_created_entries(asic_db, vnet_obj.ASIC_ROUTE_ENTRY, vnet_obj.routes, 1) - check_object(asic_db, vnet_obj.ASIC_ROUTE_ENTRY, route[0], - { - "SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID": nexthops['9.1.0.1'], - } - ) - check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", ['9.1.0.1']) - check_routes_advertisement(dvs, "100.100.1.0/24", "Test_profile") - - update_monitor_session_state(dvs, '100.100.1.1/32', '9.1.0.1', 'down') - update_monitor_session_state(dvs, '100.100.1.1/32', '9.1.0.2', 'down') - - time.sleep(2) - - vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["100.100.1.1/32"]) - check_remove_state_db_routes(dvs, vnet_name, "100.100.1.1/32") - check_remove_routes_advertisement(dvs, "200.100.1.0/24") - - - # Remove tunnel route 1 - delete_vnet_routes(dvs, "100.100.1.1/32", vnet_name) - - vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["100.100.1.1/32"]) - check_remove_state_db_routes(dvs, vnet_name, "100.100.1.1/32") - check_remove_routes_advertisement(dvs, "100.100.1.0/24") - - vnet_obj.check_custom_monitor_deleted(dvs, "100.100.1.1/32", "9.1.0.1") - vnet_obj.check_custom_monitor_deleted(dvs, "100.100.1.1/32", "9.1.0.2") - - delete_vnet_entry(dvs, vnet_name) - vnet_obj.check_del_vnet_entry(dvs, vnet_name) - delete_vxlan_tunnel(dvs, tunnel_name) - - ''' - Test 21 - Test for priority vxlan tunnel with adv_prefix, adv profile. test route re-addition, route update, primary seocndary swap. - ''' - def test_vnet_orch_21(self, dvs, testlog): - vnet_obj = self.get_vnet_obj() - - tunnel_name = 'tunnel_21' - vnet_name = "Vnet21" - vnet_obj.fetch_exist_entries(dvs) - - create_vxlan_tunnel(dvs, tunnel_name, 'fd:10::32') - create_vnet_entry(dvs, vnet_name, tunnel_name, '10021', "", advertise_prefix=True, overlay_dmac="22:33:33:44:44:66") - - vnet_obj.check_vnet_entry(dvs, vnet_name) - vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, vnet_name, '10021') - - vnet_obj.check_vxlan_tunnel(dvs, tunnel_name, 'fd:10::32') - vnet_obj.fetch_exist_entries(dvs) - - #Add first Route - create_vnet_routes(dvs, "fd:10:10::1/128", vnet_name, 'fd:10:1::1,fd:10:1::2,fd:10:1::3,fd:10:1::4', ep_monitor='fd:10:2::1,fd:10:2::2,fd:10:2::3,fd:10:2::4', profile = "test_prf", primary ='fd:10:1::3,fd:10:1::4',monitoring='custom', adv_prefix="fd:10:10::/64") - update_monitor_session_state(dvs, 'fd:10:10::1/128', 'fd:10:2::1', 'up') - update_monitor_session_state(dvs, 'fd:10:10::1/128', 'fd:10:2::2', 'up') - - time.sleep(2) - route1 = vnet_obj.check_priority_vnet_ecmp_routes(dvs, vnet_name, ['fd:10:1::1','fd:10:1::2'], tunnel_name, prefix="fd:10:10::1/128") - check_state_db_routes(dvs, vnet_name, "fd:10:10::1/128", ['fd:10:1::1,fd:10:1::2']) - check_routes_advertisement(dvs, "fd:10:10::/64", "test_prf") - - #add 2nd route - create_vnet_routes(dvs, "fd:10:10::21/128", vnet_name, 'fd:11:1::1,fd:11:1::2,fd:11:1::3,fd:11:1::4', ep_monitor='fd:11:2::1,fd:11:2::2,fd:11:2::3,fd:11:2::4', profile = "test_prf", primary ='fd:11:1::1,fd:11:1::2',monitoring='custom', adv_prefix='fd:10:10::/64') - update_monitor_session_state(dvs, 'fd:10:10::21/128', 'fd:11:2::1', 'up') - update_monitor_session_state(dvs, 'fd:10:10::21/128', 'fd:11:2::2', 'up') - update_monitor_session_state(dvs, 'fd:10:10::21/128', 'fd:11:2::3', 'up') - update_monitor_session_state(dvs, 'fd:10:10::21/128', 'fd:11:2::4', 'up') - - time.sleep(2) - route1 = vnet_obj.check_priority_vnet_ecmp_routes(dvs, vnet_name, ['fd:11:1::1','fd:11:1::2'], tunnel_name, route_ids=route1, prefix="fd:10:10::21/128") - check_state_db_routes(dvs, vnet_name, "fd:10:10::21/128", ['fd:11:1::1,fd:11:1::2']) - check_routes_advertisement(dvs, "fd:10:10::/64", "test_prf") - - #remove first route - delete_vnet_routes(dvs, "fd:10:10::1/128", vnet_name) - vnet_obj.check_del_vnet_routes(dvs, 'Vnet12', ["fd:10:10::1/128"]) - check_remove_state_db_routes(dvs, 'Vnet12', "fd:10:10::1/128") - - #adv should still be up. - check_routes_advertisement(dvs, "fd:10:10::/64") - - #add 3rd route - create_vnet_routes(dvs, "fd:10:10::31/128", vnet_name, 'fd:11:1::1,fd:11:1::2,fd:11:1::3,fd:11:1::4', ep_monitor='fd:11:2::1,fd:11:2::2,fd:11:2::3,fd:11:2::4', profile = "test_prf", primary ='fd:11:1::1,fd:11:1::2',monitoring='custom', adv_prefix='fd:10:10::/64') - update_monitor_session_state(dvs, 'fd:10:10::31/128', 'fd:11:2::1', 'up') - update_monitor_session_state(dvs, 'fd:10:10::31/128', 'fd:11:2::2', 'up') - time.sleep(2) - route1 = vnet_obj.check_priority_vnet_ecmp_routes(dvs, vnet_name, ['fd:11:1::1','fd:11:1::2'], tunnel_name, route_ids=route1, prefix="fd:10:10::31/128") - check_state_db_routes(dvs, vnet_name, "fd:10:10::31/128", ['fd:11:1::1,fd:11:1::2']) - check_routes_advertisement(dvs, "fd:10:10::/64", "test_prf") - - #delete 2nd route - delete_vnet_routes(dvs, "fd:10:10::21/128", vnet_name) - vnet_obj.check_del_vnet_routes(dvs, 'Vnet12', ["fd:10:10::21/128"]) - check_remove_state_db_routes(dvs, 'Vnet12', "fd:10:10::21/128") - - #adv should still be up. - check_routes_advertisement(dvs, "fd:10:10::/64") - - #remove 3rd route - delete_vnet_routes(dvs, "fd:10:10::31/128", vnet_name) - vnet_obj.check_del_vnet_routes(dvs, 'Vnet12', ["fd:10:10::31/128"]) - check_remove_state_db_routes(dvs, 'Vnet12', "fd:10:10::31/128") - - #adv should be gone. - check_remove_routes_advertisement(dvs, "fd:10:10::/64") - delete_vnet_entry(dvs,vnet_name) - vnet_obj.check_del_vnet_entry(dvs, vnet_name) - delete_vxlan_tunnel(dvs, tunnel_name) - - ''' - Test 22 - Test for vxlan custom monitoring with adv_prefix. Add route twice and change nexthops case - ''' - def test_vnet_orch_22(self, dvs, testlog): - vnet_obj = self.get_vnet_obj() - - tunnel_name = 'tunnel_22' - vnet_name = "Vnet22" - vnet_obj.fetch_exist_entries(dvs) - - create_vxlan_tunnel(dvs, tunnel_name, '9.9.9.3') - create_vnet_entry(dvs, vnet_name, tunnel_name, '10022', "", advertise_prefix=True, overlay_dmac="22:33:33:44:44:66") - - vnet_obj.check_vnet_entry(dvs, vnet_name) - vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, vnet_name, '10022') - - vnet_obj.check_vxlan_tunnel(dvs, tunnel_name, '9.9.9.3') - - vnet_obj.fetch_exist_entries(dvs) - #Add first Route - create_vnet_routes(dvs, "100.100.1.11/32", vnet_name, '19.0.0.1,19.0.0.2,19.0.0.3', ep_monitor='19.1.0.1,19.1.0.2,19.1.0.3', profile = "test_prf", primary ='19.0.0.1',monitoring='custom', adv_prefix='100.100.1.0/24') - update_monitor_session_state(dvs, '100.100.1.11/32', '19.1.0.1', 'up') - time.sleep(2) - vnet_obj.check_vnet_routes(dvs, vnet_name, '19.0.0.1', tunnel_name) - check_state_db_routes(dvs, vnet_name, "100.100.1.11/32", ['19.0.0.1']) - # The default Vnet setting does not advertise prefix - check_routes_advertisement(dvs, "100.100.1.0/24", "test_prf") - - #Add first Route again - create_vnet_routes(dvs, "100.100.1.11/32", vnet_name, '19.0.0.1,19.0.0.2,19.0.0.3', ep_monitor='19.1.0.1,19.1.0.2,19.1.0.3', profile = "test_prf", primary ='19.0.0.1',monitoring='custom', adv_prefix='100.100.1.0/24') - check_state_db_routes(dvs, vnet_name, "100.100.1.11/32", ['19.0.0.1']) - # The default Vnet setting does not advertise prefix - check_routes_advertisement(dvs, "100.100.1.0/24", "test_prf") - - #remove first route - delete_vnet_routes(dvs, "100.100.1.11/32", vnet_name) - vnet_obj.check_del_vnet_routes(dvs, 'Vnet12', ["100.100.1.11/32"]) - check_remove_state_db_routes(dvs, 'Vnet12', "100.100.1.11/32") - - #adv should be gone. - check_remove_routes_advertisement(dvs, "100.100.1.0/24") - - #add 2nd route - create_vnet_routes(dvs, "100.100.1.57/32", vnet_name, '5.0.0.1,5.0.0.2,5.0.0.3,5.0.0.4', ep_monitor='5.1.0.1,5.1.0.2,5.1.0.3,5.1.0.4', profile = "test_prf", primary ='5.0.0.1,5.0.0.2',monitoring='custom', adv_prefix='100.100.1.0/24') - update_monitor_session_state(dvs, '100.100.1.57/32', '5.1.0.1', 'up') - update_monitor_session_state(dvs, '100.100.1.57/32', '5.1.0.2', 'up') - time.sleep(2) - route1 = vnet_obj.check_priority_vnet_ecmp_routes(dvs, vnet_name, ['5.0.0.1','5.0.0.2'], tunnel_name, prefix="100.100.1.57/32") - check_state_db_routes(dvs, vnet_name, "100.100.1.57/32", ['5.0.0.1,5.0.0.2']) - # The default Vnet setting does not advertise prefix - check_routes_advertisement(dvs, "100.100.1.0/24", "test_prf") - - #modify 2nd route switch primary with secondary - create_vnet_routes(dvs, "100.100.1.57/32", vnet_name, '5.0.0.1,5.0.0.2,5.0.0.3,5.0.0.4', ep_monitor='5.1.0.1,5.1.0.2,5.1.0.3,5.1.0.4', profile = "test_prf", primary ='5.0.0.3,5.0.0.4',monitoring='custom', adv_prefix='100.100.1.0/24') - route1 = vnet_obj.check_priority_vnet_ecmp_routes(dvs, vnet_name, ['5.0.0.1','5.0.0.2'], tunnel_name, route_ids=route1, prefix="100.100.1.57/32") - check_state_db_routes(dvs, vnet_name, "100.100.1.57/32", ['5.0.0.1','5.0.0.2']) - # The default Vnet setting does not advertise prefix - check_routes_advertisement(dvs, "100.100.1.0/24", "test_prf") - - #delete 2nd route - delete_vnet_routes(dvs, "100.100.1.57/32", vnet_name) - vnet_obj.check_del_vnet_routes(dvs, 'Vnet12', ["100.100.1.57/32"]) - check_remove_state_db_routes(dvs, 'Vnet12', "100.100.1.57/32") - #adv should be gone. - check_remove_routes_advertisement(dvs, "100.100.1.0/24") - - #add 3rd route - create_vnet_routes(dvs, "100.100.1.67/32", vnet_name, '5.0.0.1,5.0.0.2,5.0.0.3,5.0.0.4', ep_monitor='5.1.0.1,5.1.0.2,5.1.0.3,5.1.0.4', profile = "test_prf", primary ='5.0.0.1,5.0.0.2',monitoring='custom', adv_prefix='100.100.1.0/24') - update_monitor_session_state(dvs, '100.100.1.67/32', '5.1.0.1', 'up') - update_monitor_session_state(dvs, '100.100.1.67/32', '5.1.0.2', 'up') - time.sleep(2) - route1 = vnet_obj.check_priority_vnet_ecmp_routes(dvs, vnet_name, ['5.0.0.1','5.0.0.2'], tunnel_name, prefix="100.100.1.67/32") - check_state_db_routes(dvs, vnet_name, "100.100.1.67/32", ['5.0.0.1,5.0.0.2']) - # The default Vnet setting does not advertise prefix - check_routes_advertisement(dvs, "100.100.1.0/24", "test_prf") - - #modify 3rd route next hops to secondary - create_vnet_routes(dvs, "100.100.1.67/32", vnet_name, '5.0.0.1,5.0.0.2,5.0.0.3,5.0.0.4', ep_monitor='5.1.0.1,5.1.0.2,5.1.0.3,5.1.0.4', profile = "test_prf", primary ='5.0.0.3,5.0.0.4',monitoring='custom', adv_prefix='100.100.1.0/24') - route1 = vnet_obj.check_priority_vnet_ecmp_routes(dvs, vnet_name, ['5.0.0.1','5.0.0.2'], tunnel_name, route_ids=route1, prefix="100.100.1.67/32") - check_state_db_routes(dvs, vnet_name, "100.100.1.67/32", ['5.0.0.1','5.0.0.2']) - # The default Vnet setting does not advertise prefix - check_routes_advertisement(dvs, "100.100.1.0/24", "test_prf") - - #modify 3rd route next hops to a new set. - create_vnet_routes(dvs, "100.100.1.67/32", vnet_name, '5.0.0.5,5.0.0.6,5.0.0.7,5.0.0.8', ep_monitor='5.1.0.5,5.1.0.6,5.1.0.7,5.1.0.8', profile = "test_prf", primary ='5.0.0.5,5.0.0.6',monitoring='custom', adv_prefix='100.100.1.0/24') - update_monitor_session_state(dvs, '100.100.1.67/32', '5.1.0.5', 'up') - update_monitor_session_state(dvs, '100.100.1.67/32', '5.1.0.6', 'up') - time.sleep(2) - route1 = vnet_obj.check_priority_vnet_ecmp_routes(dvs, vnet_name, ['5.0.0.5','5.0.0.6'], tunnel_name, route_ids=route1, prefix="100.100.1.67/32") - check_state_db_routes(dvs, vnet_name, "100.100.1.67/32", ['5.0.0.5,5.0.0.6']) - # The default Vnet setting does not advertise prefix - check_routes_advertisement(dvs, "100.100.1.0/24", "test_prf") - - update_monitor_session_state(dvs, '100.100.1.67/32', '5.1.0.7', 'up') - update_monitor_session_state(dvs, '100.100.1.67/32', '5.1.0.8', 'up') - - create_vnet_routes(dvs, "100.100.1.67/32", vnet_name, '5.0.0.5,5.0.0.6,5.0.0.7,5.0.0.8', ep_monitor='5.1.0.5,5.1.0.6,5.1.0.7,5.1.0.8', profile = "test_prf", primary ='5.0.0.7,5.0.0.8',monitoring='custom', adv_prefix='100.100.1.0/24') - time.sleep(2) - route1 = vnet_obj.check_priority_vnet_ecmp_routes(dvs, vnet_name, ['5.0.0.7','5.0.0.8'], tunnel_name, route_ids=route1, prefix="100.100.1.67/32") - check_state_db_routes(dvs, vnet_name, "100.100.1.67/32", ['5.0.0.7,5.0.0.8']) - # The default Vnet setting does not advertise prefix - check_routes_advertisement(dvs, "100.100.1.0/24", "test_prf") - - #delete 3rd route - delete_vnet_routes(dvs, "100.100.1.67/32", vnet_name) - vnet_obj.check_del_vnet_routes(dvs, 'Vnet12', ["100.100.1.67/32"]) - check_remove_state_db_routes(dvs, 'Vnet12', "100.100.1.67/32") - #adv should be gone. - check_remove_routes_advertisement(dvs, "100.100.1.0/24") - - #Add priority route with no secondary enpoints - create_vnet_routes(dvs, "100.100.1.71/32", vnet_name, '19.0.0.1,19.0.0.2', ep_monitor='19.0.0.1,19.0.0.2', profile = "test_prf", primary ='19.0.0.1,19.0.0.2',monitoring='custom', adv_prefix='100.100.1.0/24') - update_monitor_session_state(dvs, '100.100.1.71/32', '19.0.0.1', 'up') - update_monitor_session_state(dvs, '100.100.1.71/32', '19.0.0.2', 'up') - - #verify that no BFD sessions are created. - check_del_bfd_session(dvs, ['19.0.0.1']) - check_del_bfd_session(dvs, ['19.0.0.2']) - time.sleep(2) - check_state_db_routes(dvs, vnet_name, "100.100.1.71/32", ['19.0.0.1,19.0.0.2']) - # The default Vnet setting does not advertise prefix - check_routes_advertisement(dvs, "100.100.1.0/24", "test_prf") - - update_monitor_session_state(dvs, '100.100.1.71/32', '19.0.0.1', 'down') - check_state_db_routes(dvs, vnet_name, "100.100.1.71/32", ['19.0.0.2']) - # The default Vnet setting does not advertise prefix - check_routes_advertisement(dvs, "100.100.1.0/24", "test_prf") - - update_monitor_session_state(dvs, '100.100.1.71/32', '19.0.0.2', 'down') - check_remove_state_db_routes(dvs, 'Vnet12', "100.100.1.71/32") - - #remove first route - delete_vnet_routes(dvs, "100.100.1.71/32", vnet_name) - vnet_obj.check_del_vnet_routes(dvs, 'Vnet12', ["100.100.1.71/32"]) - check_remove_state_db_routes(dvs, 'Vnet12', "100.100.1.71/32") - - delete_vnet_entry(dvs,vnet_name) - vnet_obj.check_del_vnet_entry(dvs, vnet_name) - delete_vxlan_tunnel(dvs, tunnel_name) - - ''' - Test 23 - Test for vxlan custom monitoring. CHanging the overlay_dmac of the Vnet on the fly. - ''' - def test_vnet_orch_23(self, dvs, testlog): - vnet_obj = self.get_vnet_obj() - - tunnel_name = 'tunnel_22' - vnet_name = "Vnet22" - vnet_obj.fetch_exist_entries(dvs) - - create_vxlan_tunnel(dvs, tunnel_name, '9.9.9.3') - create_vnet_entry(dvs, vnet_name, tunnel_name, '10022', "", advertise_prefix=True, overlay_dmac="22:33:33:44:44:66") - delete_vnet_entry(dvs,vnet_name) - - create_vnet_entry(dvs, vnet_name, tunnel_name, '10022', "", advertise_prefix=True, overlay_dmac="22:33:33:44:44:66") - create_vnet_entry(dvs, vnet_name, tunnel_name, '10022', "", advertise_prefix=True, overlay_dmac="22:33:33:44:44:77") - delete_vnet_entry(dvs,vnet_name) - - #update the Dmac of the vnet before adding any routes. - create_vnet_entry(dvs, vnet_name, tunnel_name, '10022', "", advertise_prefix=True, overlay_dmac="22:33:33:44:44:66") - create_vnet_entry(dvs, vnet_name, tunnel_name, '10022', "", advertise_prefix=True, overlay_dmac="22:33:33:44:44:77") - - vnet_obj.check_vnet_entry(dvs, vnet_name) - vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, vnet_name, '10022') - - vnet_obj.check_vxlan_tunnel(dvs, tunnel_name, '9.9.9.3') - - vnet_obj.fetch_exist_entries(dvs) - #Add first Route - create_vnet_routes(dvs, "100.100.1.11/32", vnet_name, '19.0.0.1,19.0.0.2,19.0.0.3', ep_monitor='19.1.0.1,19.1.0.2,19.1.0.3', profile = "test_prf", primary ='19.0.0.1',monitoring='custom', adv_prefix='100.100.1.0/24') - #verify the appdb entries. - vnet_obj.check_custom_monitor_app_db(dvs, "100.100.1.11/32", "19.1.0.1", "vxlan", "22:33:33:44:44:77") - vnet_obj.check_custom_monitor_app_db(dvs, "100.100.1.11/32", "19.1.0.2", "vxlan", "22:33:33:44:44:77") - vnet_obj.check_custom_monitor_app_db(dvs, "100.100.1.11/32", "19.1.0.3", "vxlan", "22:33:33:44:44:77") - - #update the Dmac after a route is added. - create_vnet_entry(dvs, vnet_name, tunnel_name, '10022', "", advertise_prefix=True, overlay_dmac="22:33:33:44:44:88") - - #verify the appdb entries. - vnet_obj.check_custom_monitor_app_db(dvs, "100.100.1.11/32", "19.1.0.1", "vxlan", "22:33:33:44:44:88") - vnet_obj.check_custom_monitor_app_db(dvs, "100.100.1.11/32", "19.1.0.2", "vxlan", "22:33:33:44:44:88") - vnet_obj.check_custom_monitor_app_db(dvs, "100.100.1.11/32", "19.1.0.3", "vxlan", "22:33:33:44:44:88") - - #bring up an enpoint. - update_monitor_session_state(dvs, '100.100.1.11/32', '19.1.0.1', 'up') - - #verify the appdb entries. - vnet_obj.check_custom_monitor_app_db(dvs, "100.100.1.11/32", "19.1.0.1", "vxlan", "22:33:33:44:44:88") - vnet_obj.check_custom_monitor_app_db(dvs, "100.100.1.11/32", "19.1.0.2", "vxlan", "22:33:33:44:44:88") - vnet_obj.check_custom_monitor_app_db(dvs, "100.100.1.11/32", "19.1.0.3", "vxlan", "22:33:33:44:44:88") - - #update the Dmac to empty. This should have no impact. - create_vnet_entry(dvs, vnet_name, tunnel_name, '10022', "", advertise_prefix=True, overlay_dmac="") - - #verify the appdb entries. - vnet_obj.check_custom_monitor_app_db(dvs, "100.100.1.11/32", "19.1.0.1", "vxlan", "22:33:33:44:44:88") - vnet_obj.check_custom_monitor_app_db(dvs, "100.100.1.11/32", "19.1.0.2", "vxlan", "22:33:33:44:44:88") - vnet_obj.check_custom_monitor_app_db(dvs, "100.100.1.11/32", "19.1.0.3", "vxlan", "22:33:33:44:44:88") - - #remove first route - delete_vnet_routes(dvs, "100.100.1.11/32", vnet_name) - vnet_obj.check_del_vnet_routes(dvs, 'Vnet12', ["100.100.1.11/32"]) - check_remove_state_db_routes(dvs, 'Vnet12', "100.100.1.11/32") - - #make sure that the app db entries are removed. - vnet_obj.check_custom_monitor_deleted(dvs, "100.100.1.11/32", "19.1.0.1") - vnet_obj.check_custom_monitor_deleted(dvs, "100.100.1.11/32", "19.1.0.2") - vnet_obj.check_custom_monitor_deleted(dvs, "100.100.1.11/32", "19.1.0.3") - vnet_obj.check_custom_monitor_deleted(dvs, "100.100.1.11/32", "19.1.0.4") - time.sleep(2) - - #bring down an enpoint. - update_monitor_session_state(dvs, '100.100.1.11/32', '19.1.0.1', 'down') - - create_vnet_entry(dvs, vnet_name, tunnel_name, '10022', "", advertise_prefix=True, overlay_dmac="22:33:33:44:44:66") - - #Add first Route again - create_vnet_routes(dvs, "100.100.1.11/32", vnet_name, '19.0.0.1,19.0.0.2,19.0.0.3', ep_monitor='19.1.0.1,19.1.0.2,19.1.0.3', profile = "test_prf", primary ='19.0.0.1',monitoring='custom', adv_prefix='100.100.1.0/24') - - #bring up the endpoint. - update_monitor_session_state(dvs, '100.100.1.11/32', '19.1.0.1', 'up') - - # The default Vnet setting advertises the prefix. - check_routes_advertisement(dvs, "100.100.1.0/24", "test_prf") - - #verify the appdb entries. - vnet_obj.check_custom_monitor_app_db(dvs, "100.100.1.11/32", "19.1.0.1", "vxlan", "22:33:33:44:44:66") - vnet_obj.check_custom_monitor_app_db(dvs, "100.100.1.11/32", "19.1.0.2", "vxlan", "22:33:33:44:44:66") - vnet_obj.check_custom_monitor_app_db(dvs, "100.100.1.11/32", "19.1.0.3", "vxlan", "22:33:33:44:44:66") - - #remove first route - delete_vnet_routes(dvs, "100.100.1.11/32", vnet_name) - vnet_obj.check_del_vnet_routes(dvs, 'Vnet12', ["100.100.1.11/32"]) - check_remove_state_db_routes(dvs, 'Vnet12', "100.100.1.11/32") - - #make sure that the app db entries are removed. - vnet_obj.check_custom_monitor_deleted(dvs, "100.100.1.11/32", "19.1.0.1") - vnet_obj.check_custom_monitor_deleted(dvs, "100.100.1.11/32", "19.1.0.2") - vnet_obj.check_custom_monitor_deleted(dvs, "100.100.1.11/32", "19.1.0.3") - vnet_obj.check_custom_monitor_deleted(dvs, "100.100.1.11/32", "19.1.0.4") - time.sleep(2) - delete_vnet_entry(dvs,vnet_name) - vnet_obj.check_del_vnet_entry(dvs, vnet_name) - delete_vxlan_tunnel(dvs, tunnel_name) - - ''' - Test 24 - Test duplicate route addition and removal. - ''' - def test_vnet_orch_24(self, dvs, testlog): - self.setup_db(dvs) - self.clear_srv_config(dvs) - - vnet_obj = self.get_vnet_obj() - vnet_obj.fetch_exist_entries(dvs) - - # create vxlan tunnel and vnet in default vrf - tunnel_name = 'tunnel_24' - create_vxlan_tunnel(dvs, tunnel_name, '10.10.10.10') - create_vnet_entry(dvs, 'Vnet_2000', tunnel_name, '2000', "", 'default') - - vnet_obj.check_default_vnet_entry(dvs, 'Vnet_2000') - vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, 'Vnet_2000', '2000') - vnet_obj.check_vxlan_tunnel(dvs, tunnel_name, '10.10.10.10') - vnet_obj.fetch_exist_entries(dvs) - - # create vnet route - create_vnet_routes(dvs, "100.100.1.0/24", 'Vnet_2000', '10.10.10.3') - vnet_obj.check_vnet_routes(dvs, 'Vnet_2000', '10.10.10.3', tunnel_name) - check_state_db_routes(dvs, 'Vnet_2000', "100.100.1.0/24", ['10.10.10.3']) - time.sleep(2) - - # create l3 interface - self.create_l3_intf("Ethernet0", "") - - # set ip address - self.add_ip_address("Ethernet0", "10.10.10.1/24") - - # bring up interface - self.set_admin_status("Ethernet0", "up") - - # set ip address and default route - dvs.servers[0].runcmd("ip address add 10.10.10.3/24 dev eth0") - dvs.servers[0].runcmd("ip route add default via 10.10.10.1") - - marker = dvs.add_log_marker("/var/log/syslog") - time.sleep(2) - - # add another route for same prefix as vnet route - dvs.runcmd("vtysh -c \"configure terminal\" -c \"ip route 100.100.1.0/24 10.10.10.3\"") - - # check application database - self.pdb.wait_for_entry("ROUTE_TABLE", "100.100.1.0/24") - - # check ASIC route database - self.check_route_entries(["100.100.1.0/24"]) - - log_string = "Encountered failure in create operation, exiting orchagent, SAI API: SAI_API_ROUTE, status: SAI_STATUS_NOT_EXECUTED" - # check for absence of log_string in syslog - check_syslog(dvs, marker, log_string) - - # remove route entry - dvs.runcmd("vtysh -c \"configure terminal\" -c \"no ip route 100.100.1.0/24 10.10.10.3\"") - - # delete vnet route - delete_vnet_routes(dvs, "100.100.1.0/24", 'Vnet_2000') - vnet_obj.check_del_vnet_routes(dvs, 'Vnet_2000') - check_remove_state_db_routes(dvs, 'Vnet_2000', "100.100.1.0/24") - - # delete vnet - delete_vnet_entry(dvs, 'Vnet_2000') - vnet_obj.check_del_vnet_entry(dvs, 'Vnet_2000') - - # delete vxlan tunnel - delete_vxlan_tunnel(dvs, tunnel_name) - - ''' - Test 25 - Test for BFD TSA and TSB behaviour within overlay tunnel routes. - ''' - def test_vnet_orch_25(self, dvs, testlog): - # This test creates a vnet route with BFD monitoring.This followd by application of TSA and absence of BFD sessions - # is verified. Following the removal of TSA the Vnet route is verified to be up. - vnet_obj = self.get_vnet_obj() - tunnel_name = 'tunnel_25' - - vnet_obj.fetch_exist_entries(dvs) - - create_vxlan_tunnel(dvs, tunnel_name, '9.9.9.9') - create_vnet_entry(dvs, 'Vnet25', tunnel_name, '10025', "") - - vnet_obj.check_vnet_entry(dvs, 'Vnet25') - vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, 'Vnet25', '10025') - - vnet_obj.check_vxlan_tunnel(dvs, tunnel_name, '9.9.9.9') - - vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "125.100.1.1/32", 'Vnet25', '9.0.0.1,9.0.0.2,9.0.0.3', ep_monitor='9.1.0.1,9.1.0.2,9.1.0.3') - - # default bfd status is down, route should not be programmed in this status - vnet_obj.check_del_vnet_routes(dvs, 'Vnet25', ["125.100.1.1/32"]) - check_state_db_routes(dvs, 'Vnet25', "125.100.1.1/32", []) - check_remove_routes_advertisement(dvs, "125.100.1.1/32") - - # Route should be properly configured when all bfd session states go up - update_bfd_session_state(dvs, '9.1.0.1', 'Up') - update_bfd_session_state(dvs, '9.1.0.2', 'Up') - update_bfd_session_state(dvs, '9.1.0.3', 'Up') - time.sleep(2) - - # make sure the route is up. - route1, nhg1_1 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet25', ['9.0.0.1', '9.0.0.2', '9.0.0.3'], tunnel_name) - check_state_db_routes(dvs, 'Vnet25', "125.100.1.1/32", ['9.0.0.1', '9.0.0.2', '9.0.0.3']) - # The default Vnet setting does not advertise prefix - check_remove_routes_advertisement(dvs, "125.100.1.1/32") - - # tsa would remove all bfd sessions down. - set_tsa(dvs) - time.sleep(2) - - # Route should be removed. - vnet_obj.check_del_vnet_routes(dvs, 'Vnet25', ["125.100.1.1/32"]) - check_state_db_routes(dvs, 'Vnet25', "125.100.1.1/32", []) - check_remove_routes_advertisement(dvs, "125.100.1.1/32") - - #clearing TSA should bring the route back. - clear_tsa(dvs) - time.sleep(2) - - update_bfd_session_state(dvs, '9.1.0.1', 'Up') - update_bfd_session_state(dvs, '9.1.0.2', 'Up') - update_bfd_session_state(dvs, '9.1.0.3', 'Up') - time.sleep(2) - - route1, nhg1_1 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet25', ['9.0.0.1', '9.0.0.2', '9.0.0.3'], tunnel_name, route_ids=route1, nhg=nhg1_1) - check_state_db_routes(dvs, 'Vnet25', "125.100.1.1/32", ['9.0.0.1', '9.0.0.2', '9.0.0.3']) - # The default Vnet setting does not advertise prefix - check_remove_routes_advertisement(dvs, "125.100.1.1/32") - - # Remove tunnel route - delete_vnet_routes(dvs, "125.100.1.1/32", 'Vnet25') - vnet_obj.check_del_vnet_routes(dvs, 'Vnet25', ["125.100.1.1/32"]) - check_remove_state_db_routes(dvs, 'Vnet25', "125.100.1.1/32") - check_remove_routes_advertisement(dvs, "125.100.1.1/32") - - # Check the corresponding nexthop group is removed - vnet_obj.fetch_exist_entries(dvs) - assert nhg1_1 not in vnet_obj.nhgs - # Check the BFD session specific to the endpoint group is removed while others exist - check_del_bfd_session(dvs, ['9.1.0.1', '9.1.0.2', '9.1.0.3']) - - delete_vnet_entry(dvs, 'Vnet25') - vnet_obj.check_del_vnet_entry(dvs, 'Vnet25') - delete_vxlan_tunnel(dvs, tunnel_name) - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_vrf.py b/tests/test_vrf.py deleted file mode 100644 index d595d5aad3..0000000000 --- a/tests/test_vrf.py +++ /dev/null @@ -1,312 +0,0 @@ -import time -import json -import random -import pytest - -from swsscommon import swsscommon -from pprint import pprint - - -class TestVrf(object): - def setup_db(self, dvs): - self.pdb = swsscommon.DBConnector(0, dvs.redis_sock, 0) - self.adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - self.cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) - - def create_entry(self, tbl, key, pairs): - fvs = swsscommon.FieldValuePairs(pairs) - tbl.set(key, fvs) - time.sleep(1) - - def create_entry_tbl(self, db, table, key, pairs): - tbl = swsscommon.Table(db, table) - self.create_entry(tbl, key, pairs) - - def delete_entry_tbl(self, db, table, key): - tbl = swsscommon.Table(db, table) - tbl._del(key) - time.sleep(1) - - def how_many_entries_exist(self, db, table): - tbl = swsscommon.Table(db, table) - return len(tbl.getKeys()) - - def entries(self, db, table): - tbl = swsscommon.Table(db, table) - return set(tbl.getKeys()) - - def is_vrf_attributes_correct(self, db, table, key, expected_attributes): - tbl = swsscommon.Table(db, table) - keys = set(tbl.getKeys()) - assert key in keys, "The created key wasn't found" - - status, fvs = tbl.get(key) - assert status, "Got an error when get a key" - - # filter the fake 'NULL' attribute out - fvs = [x for x in fvs if x != ('NULL', 'NULL')] - - attr_keys = {entry[0] for entry in fvs} - assert attr_keys == set(expected_attributes.keys()) - - for name, value in fvs: - assert expected_attributes[name] == value, "Wrong value %s for the attribute %s = %s" % \ - (value, name, expected_attributes[name]) - - - def vrf_create(self, dvs, vrf_name, attributes, expected_attributes): - # check that the vrf wasn't exist before - assert self.how_many_entries_exist(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER") == 1, "The initial state is incorrect" - - # read existing entries in the DB - initial_entries = self.entries(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER") - - # create a fake attribute if we don't have attributes in the request - if len(attributes) == 0: - attributes = [('empty', 'empty')] - - # create the VRF entry in Config DB - self.create_entry_tbl(self.cdb, "VRF", vrf_name, attributes) - - # check vrf created in kernel - (status, rslt) = dvs.runcmd("ip link show " + vrf_name) - assert status == 0 - - # check application database - tbl = swsscommon.Table(self.pdb, "VRF_TABLE") - intf_entries = tbl.getKeys() - assert len(intf_entries) == 1 - assert intf_entries[0] == vrf_name - exp_attr = {} - for an in range(len(attributes)): - exp_attr[attributes[an][0]] = attributes[an][1] - self.is_vrf_attributes_correct(self.pdb, "VRF_TABLE", vrf_name, exp_attr) - - # check that the vrf entry was created - assert self.how_many_entries_exist(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER") == 2, "The vrf wasn't created" - - # find the id of the entry which was added - added_entry_id = list(self.entries(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER") - initial_entries)[0] - - # check correctness of the created attributes - self.is_vrf_attributes_correct( - self.adb, - "ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER", - added_entry_id, - expected_attributes, - ) - - state = { - 'initial_entries': initial_entries, - 'entry_id': added_entry_id, - } - - return state - - - def vrf_remove(self, dvs, vrf_name, state): - # delete the created vrf entry - self.delete_entry_tbl(self.cdb, "VRF", vrf_name) - - # check application database - tbl = swsscommon.Table(self.pdb, "VRF_TABLE") - intf_entries = tbl.getKeys() - assert vrf_name not in intf_entries - - # check that the vrf entry was removed - assert self.how_many_entries_exist(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER") == 1, "The vrf wasn't removed" - - # check that the correct vrf entry was removed - assert state['initial_entries'] == self.entries(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER"), "The incorrect entry was removed" - - # check vrf was removed from kernel - (status, rslt) = dvs.runcmd("ip link show " + vrf_name) - assert status != 0 - - def vrf_update(self, vrf_name, attributes, expected_attributes, state): - # update the VRF entry in Config DB - self.create_entry_tbl(self.cdb, "VRF", vrf_name, attributes) - - # check correctness of the created attributes - self.is_vrf_attributes_correct( - self.adb, - "ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER", - state['entry_id'], - expected_attributes, - ) - - - def boolean_gen(self): - result = random.choice(['false', 'true']) - return result, result - - - def mac_addr_gen(self): - ns = [random.randint(0, 255) for _ in range(6)] - ns[0] &= 0xfe - mac = ':'.join("%02x" % n for n in ns) - return mac, mac.upper() - - - def packet_action_gen(self): - values = [ - ("drop", "SAI_PACKET_ACTION_DROP"), - ("forward", "SAI_PACKET_ACTION_FORWARD"), - ("copy", "SAI_PACKET_ACTION_COPY"), - ("copy_cancel", "SAI_PACKET_ACTION_COPY_CANCEL"), - ("trap", "SAI_PACKET_ACTION_TRAP"), - ("log", "SAI_PACKET_ACTION_LOG"), - ("deny", "SAI_PACKET_ACTION_DENY"), - ("transit", "SAI_PACKET_ACTION_TRANSIT"), - ] - - r = random.choice(values) - return r[0], r[1] - - def test_VRFMgr_Comprehensive(self, dvs, testlog): - self.setup_db(dvs) - - attributes = [ - ('v4', 'SAI_VIRTUAL_ROUTER_ATTR_ADMIN_V4_STATE', self.boolean_gen), - ('v6', 'SAI_VIRTUAL_ROUTER_ATTR_ADMIN_V6_STATE', self.boolean_gen), - ('src_mac', 'SAI_VIRTUAL_ROUTER_ATTR_SRC_MAC_ADDRESS', self.mac_addr_gen), - ('ttl_action', 'SAI_VIRTUAL_ROUTER_ATTR_VIOLATION_TTL1_PACKET_ACTION', self.packet_action_gen), - ('ip_opt_action', 'SAI_VIRTUAL_ROUTER_ATTR_VIOLATION_IP_OPTIONS_PACKET_ACTION', self.packet_action_gen), - ('l3_mc_action', 'SAI_VIRTUAL_ROUTER_ATTR_UNKNOWN_L3_MULTICAST_PACKET_ACTION', self.packet_action_gen), - ] - - random.seed(int(time.time())) - - for n in range(2**len(attributes)): - # generate testcases for all combinations of attributes - req_attr = [] - exp_attr = {} - vrf_name = "Vrf_%d" % n - bmask = 0x1 - for an in range(len(attributes)): - if (bmask & n) > 0: - req_res, exp_res = attributes[an][2]() - req_attr.append((attributes[an][0], req_res)) - exp_attr[attributes[an][1]] = exp_res - bmask <<= 1 - state = self.vrf_create(dvs, vrf_name, req_attr, exp_attr) - self.vrf_remove(dvs, vrf_name, state) - - - def test_VRFMgr(self, dvs, testlog): - self.setup_db(dvs) - - state = self.vrf_create(dvs, "Vrf0", - [ - ], - { - } - ) - self.vrf_remove(dvs, "Vrf0", state) - - state = self.vrf_create(dvs, "Vrf1", - [ - ('v4', 'true'), - ('src_mac', '02:04:06:07:08:09'), - ], - { - 'SAI_VIRTUAL_ROUTER_ATTR_ADMIN_V4_STATE': 'true', - 'SAI_VIRTUAL_ROUTER_ATTR_SRC_MAC_ADDRESS': '02:04:06:07:08:09', - } - ) - self.vrf_remove(dvs, "Vrf1", state) - - def test_VRFMgr_Update(self, dvs, testlog): - self.setup_db(dvs) - - attributes = [ - ('v4', 'SAI_VIRTUAL_ROUTER_ATTR_ADMIN_V4_STATE', self.boolean_gen), - ('v6', 'SAI_VIRTUAL_ROUTER_ATTR_ADMIN_V6_STATE', self.boolean_gen), - ('src_mac', 'SAI_VIRTUAL_ROUTER_ATTR_SRC_MAC_ADDRESS', self.mac_addr_gen), - ('ttl_action', 'SAI_VIRTUAL_ROUTER_ATTR_VIOLATION_TTL1_PACKET_ACTION', self.packet_action_gen), - ('ip_opt_action', 'SAI_VIRTUAL_ROUTER_ATTR_VIOLATION_IP_OPTIONS_PACKET_ACTION', self.packet_action_gen), - ('l3_mc_action', 'SAI_VIRTUAL_ROUTER_ATTR_UNKNOWN_L3_MULTICAST_PACKET_ACTION', self.packet_action_gen), - ] - - random.seed(int(time.time())) - - state = self.vrf_create(dvs, "Vrf_a", - [ - ], - { - } - ) - - # try to update each attribute - req_attr = [] - exp_attr = {} - for attr in attributes: - req_res, exp_res = attr[2]() - req_attr.append((attr[0], req_res)) - exp_attr[attr[1]] = exp_res - self.vrf_update("Vrf_a", req_attr, exp_attr, state) - - self.vrf_remove(dvs, "Vrf_a", state) - - @pytest.mark.xfail(reason="Test unstable, blocking PR builds") - def test_VRFMgr_Capacity(self, dvs, testlog): - self.setup_db(dvs) - - initial_entries_cnt = self.how_many_entries_exist(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER") - - maximum_vrf_cnt = 999 - - def create_entry(self, tbl, key, pairs): - fvs = swsscommon.FieldValuePairs(pairs) - tbl.set(key, fvs) - time.sleep(1) - - def create_entry_tbl(self, db, table, key, pairs): - tbl = swsscommon.Table(db, table) - self.create_entry(tbl, key, pairs) - - # create the VRF entry in Config DB - tbl = swsscommon.Table(self.cdb, "VRF") - fvs = swsscommon.FieldValuePairs([('empty', 'empty')]) - for i in range(maximum_vrf_cnt): - tbl.set("Vrf_%d" % i, fvs) - - # wait for all VRFs pushed to database and linux - time.sleep(30) - - # check app_db - intf_entries_cnt = self.how_many_entries_exist(self.pdb, "VRF_TABLE") - assert intf_entries_cnt == maximum_vrf_cnt - - # check asic_db - current_entries_cnt = self.how_many_entries_exist(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER") - assert (current_entries_cnt - initial_entries_cnt) == maximum_vrf_cnt - - # check linux kernel - (exitcode, num) = dvs.runcmd(['sh', '-c', "ip link show | grep Vrf | wc -l"]) - assert num.strip() == str(maximum_vrf_cnt) - - # remove VRF from Config DB - for i in range(maximum_vrf_cnt): - tbl._del("Vrf_%d" % i) - - # wait for all VRFs deleted - time.sleep(120) - - # check app_db - intf_entries_cnt = self.how_many_entries_exist(self.pdb, "VRF_TABLE") - assert intf_entries_cnt == 0 - - # check asic_db - current_entries_cnt = self.how_many_entries_exist(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER") - assert (current_entries_cnt - initial_entries_cnt) == 0 - - # check linux kernel - (exitcode, num) = dvs.runcmd(['sh', '-c', "ip link show | grep Vrf | wc -l"]) - assert num.strip() == '0' - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_vxlan_tunnel.py b/tests/test_vxlan_tunnel.py deleted file mode 100644 index d296fcc741..0000000000 --- a/tests/test_vxlan_tunnel.py +++ /dev/null @@ -1,403 +0,0 @@ -import time -import json -import random -import time -import pytest - -from swsscommon import swsscommon -from pprint import pprint - - -def create_entry(tbl, key, pairs): - fvs = swsscommon.FieldValuePairs(pairs) - tbl.set(key, fvs) - - # FIXME: better to wait until DB create them - time.sleep(1) - - -def create_entry_tbl(db, table, separator, key, pairs): - tbl = swsscommon.Table(db, table) - create_entry(tbl, key, pairs) - - -def create_entry_pst(db, table, separator, key, pairs): - tbl = swsscommon.ProducerStateTable(db, table) - create_entry(tbl, key, pairs) - - -def delete_entry_pst(db, table, key): - tbl = swsscommon.ProducerStateTable(db, table) - tbl._del(key) - time.sleep(1) - - -def delete_entry_tbl(db, table, key): - tbl = swsscommon.Table(db, table) - tbl._del(key) - time.sleep(1) - - -def how_many_entries_exist(db, table): - tbl = swsscommon.Table(db, table) - return len(tbl.getKeys()) - - -def entries(db, table): - tbl = swsscommon.Table(db, table) - return set(tbl.getKeys()) - -def get_exist_entries(dvs, table): - db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - tbl = swsscommon.Table(db, table) - return set(tbl.getKeys()) - -def get_created_entry_mapid(db, table, existed_entries): - tbl = swsscommon.Table(db, table) - entries = set(tbl.getKeys()) - new_entries = list(entries - existed_entries) - new_entries.sort() - return new_entries - -def get_created_entry(db, table, existed_entries): - tbl = swsscommon.Table(db, table) - entries = set(tbl.getKeys()) - new_entries = list(entries - existed_entries) - assert len(new_entries) == 1, "Wrong number of created entries." - return new_entries[0] - - -def get_default_vr_id(db): - table = 'ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER' - tbl = swsscommon.Table(db, table) - keys = tbl.getKeys() - assert len(keys) == 1, "Wrong number of virtual routers found" - - return keys[0] - - -def check_object(db, table, key, expected_attributes): - tbl = swsscommon.Table(db, table) - keys = tbl.getKeys() - assert key in keys, "The desired key is not presented" - - status, fvs = tbl.get(key) - assert status, "Got an error when get a key" - - assert len(fvs) == len(expected_attributes), "Unexpected number of attributes" - - attr_keys = {entry[0] for entry in fvs} - - for name, value in fvs: - assert expected_attributes[name] == value, "Wrong value %s for the attribute %s = %s" % \ - (value, name, expected_attributes[name]) - -def create_vlan(dvs, vlan_name, vlan_ids): - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - conf_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - - vlan_id = vlan_name[4:] - - # create vlan - create_entry_tbl( - conf_db, - "VLAN", '|', vlan_name, - [ - ("vlanid", vlan_id), - ], - ) - - time.sleep(1) - - vlan_oid = get_created_entry(asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN", vlan_ids) - - check_object(asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN", vlan_oid, - { - "SAI_VLAN_ATTR_VLAN_ID": vlan_id, - } - ) - - vlan_ids.add(vlan_oid) - - return - - -def check_vxlan_tunnel(dvs, src_ip, dst_ip, tunnel_map_ids, tunnel_map_entry_ids, tunnel_ids, tunnel_term_ids, lo_id): - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - tunnel_map_id = get_created_entry_mapid(asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL_MAP", tunnel_map_ids) - tunnel_id = get_created_entry(asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL", tunnel_ids) - tunnel_term_id = get_created_entry(asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL_TERM_TABLE_ENTRY", tunnel_term_ids) - - # check that the vxlan tunnel termination are there - assert how_many_entries_exist(asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL_MAP") == (len(tunnel_map_ids) + 4), "The TUNNEL_MAP wasn't created" - assert how_many_entries_exist(asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL_MAP_ENTRY") == len(tunnel_map_entry_ids), "The TUNNEL_MAP_ENTRY is created too early" - assert how_many_entries_exist(asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL") == (len(tunnel_ids) + 1), "The TUNNEL wasn't created" - assert how_many_entries_exist(asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL_TERM_TABLE_ENTRY") == (len(tunnel_term_ids) + 1), "The TUNNEL_TERM_TABLE_ENTRY wasm't created" - - default_vr_id = get_default_vr_id(asic_db) - - check_object(asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL_MAP", tunnel_map_id[0], - { - 'SAI_TUNNEL_MAP_ATTR_TYPE': 'SAI_TUNNEL_MAP_TYPE_VNI_TO_VLAN_ID', - } - ) - - decapstr = '2:' + tunnel_map_id[0] + ',' + tunnel_map_id[2] - encapstr = '2:' + tunnel_map_id[1] + ',' + tunnel_map_id[3] - - check_object(asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL", tunnel_id, - { - 'SAI_TUNNEL_ATTR_TYPE': 'SAI_TUNNEL_TYPE_VXLAN', - 'SAI_TUNNEL_ATTR_UNDERLAY_INTERFACE': lo_id, - 'SAI_TUNNEL_ATTR_DECAP_MAPPERS': decapstr, - 'SAI_TUNNEL_ATTR_ENCAP_MAPPERS': encapstr, - 'SAI_TUNNEL_ATTR_PEER_MODE': 'SAI_TUNNEL_PEER_MODE_P2MP', - 'SAI_TUNNEL_ATTR_ENCAP_SRC_IP': src_ip - } - ) - - tunnel_type = 'SAI_TUNNEL_TERM_TABLE_ENTRY_TYPE_P2P' if dst_ip != '0.0.0.0' else 'SAI_TUNNEL_TERM_TABLE_ENTRY_TYPE_P2MP' - expected_attributes = { - 'SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_TYPE': tunnel_type, - 'SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_VR_ID': default_vr_id, - 'SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_DST_IP': src_ip, - 'SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_TUNNEL_TYPE': 'SAI_TUNNEL_TYPE_VXLAN', - 'SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_ACTION_TUNNEL_ID': tunnel_id, - } - - if dst_ip != '0.0.0.0': - expected_attributes['SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_SRC_IP'] = dst_ip - - check_object(asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL_TERM_TABLE_ENTRY", tunnel_term_id, expected_attributes) - - tunnel_map_ids.update(tunnel_map_id) - tunnel_ids.add(tunnel_id) - tunnel_term_ids.add(tunnel_term_id) - - return tunnel_map_id[0] - - -def create_vxlan_tunnel(dvs, name, src_ip, dst_ip, tunnel_map_ids, tunnel_map_entry_ids, tunnel_ids, tunnel_term_ids, lo_id, skip_dst_ip=False): - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - conf_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - - # check the source information - assert how_many_entries_exist(asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL_MAP") == len(tunnel_map_ids), "The initial state is incorrect" - assert how_many_entries_exist(asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL_MAP_ENTRY") == len(tunnel_map_entry_ids), "The initial state is incorrect" - assert how_many_entries_exist(asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL") == len(tunnel_ids), "The initial state is incorrect" - assert how_many_entries_exist(asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL_TERM_TABLE_ENTRY") == len(tunnel_term_ids), "The initial state is incorrect" - - attrs = [ - ("src_ip", src_ip), - ] - - if not skip_dst_ip: - attrs.append(("dst_ip", dst_ip)) - - # create the VXLAN tunnel Term entry in Config DB - create_entry_tbl( - conf_db, - "VXLAN_TUNNEL", '|', name, - attrs, - ) - - -def create_vxlan_tunnel_entry(dvs, tunnel_name, tunnel_map_entry_name, tunnel_map_map, vlan, vni_id, - tunnel_map_ids, tunnel_map_entry_ids, tunnel_ids, tunnel_term_ids): - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - conf_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - - # Check source information - assert how_many_entries_exist(asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL_MAP") == len(tunnel_map_ids), "The initial state is incorrect" - assert how_many_entries_exist(asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL_MAP_ENTRY") == len(tunnel_map_entry_ids), "The initial state is incorrect" - assert how_many_entries_exist(asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL") == len(tunnel_ids), "The initial state is incorrect" - assert how_many_entries_exist(asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL_TERM_TABLE_ENTRY") == len(tunnel_term_ids), "The initial state is incorrect" - - # create the VXLAN tunnel Term entry in Config DB - create_entry_tbl( - conf_db, - "VXLAN_TUNNEL_MAP", '|', "%s|%s" % (tunnel_name, tunnel_map_entry_name), - [ - ("vni", vni_id), - ("vlan", vlan), - ], - ) - - if (tunnel_map_map.get(tunnel_name) is None): - tunnel_map_id = get_created_entry_mapid(asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL_MAP", tunnel_map_ids) - vni_vlan_map_id = tunnel_map_id[0] - else: - vni_vlan_map_id = tunnel_map_map[tunnel_name] - - tunnel_map_entry_id = get_created_entry(asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL_MAP_ENTRY", tunnel_map_entry_ids) - - # check that the vxlan tunnel termination are there - assert how_many_entries_exist(asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL_MAP_ENTRY") == (len(tunnel_map_entry_ids) + 1), "The TUNNEL_MAP_ENTRY is created too early" - - vlan_id = vlan[4:] - check_object(asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL_MAP_ENTRY", tunnel_map_entry_id, - { - 'SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE': 'SAI_TUNNEL_MAP_TYPE_VNI_TO_VLAN_ID', - 'SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP': vni_vlan_map_id, - 'SAI_TUNNEL_MAP_ENTRY_ATTR_VNI_ID_KEY': vni_id, - 'SAI_TUNNEL_MAP_ENTRY_ATTR_VLAN_ID_VALUE': vlan_id, - } - ) - - tunnel_map_entry_ids.add(tunnel_map_entry_id) - - return - -def get_lo(dvs): - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - vr_id = get_default_vr_id(asic_db) - - tbl = swsscommon.Table(asic_db, 'ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE') - - entries = tbl.getKeys() - lo_id = None - for entry in entries: - status, fvs = tbl.get(entry) - assert status, "Got an error when get a key" - for key, value in fvs: - if key == 'SAI_ROUTER_INTERFACE_ATTR_TYPE' and value == 'SAI_ROUTER_INTERFACE_TYPE_LOOPBACK': - lo_id = entry - break - else: - assert False, 'Don\'t found loopback id' - - return lo_id - - -class TestVxlan(object): - def test_vxlan_term_orch(self, dvs, testlog): - tunnel_map_ids = set() - tunnel_map_entry_ids = set() - tunnel_ids = set() - tunnel_term_ids = set() - tunnel_map_map = {} - vlan_ids = get_exist_entries(dvs, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - loopback_id = get_lo(dvs) - - create_vlan(dvs, "Vlan50", vlan_ids) - create_vlan(dvs, "Vlan51", vlan_ids) - create_vlan(dvs, "Vlan52", vlan_ids) - create_vlan(dvs, "Vlan53", vlan_ids) - create_vlan(dvs, "Vlan54", vlan_ids) - create_vlan(dvs, "Vlan55", vlan_ids) - create_vlan(dvs, "Vlan56", vlan_ids) - create_vlan(dvs, "Vlan57", vlan_ids) - - create_vxlan_tunnel(dvs, 'tunnel_1', '10.0.0.1', '100.100.100.1', - tunnel_map_ids, tunnel_map_entry_ids, tunnel_ids, tunnel_term_ids, loopback_id) - - create_vxlan_tunnel_entry(dvs, 'tunnel_1', 'entry_1', tunnel_map_map, 'Vlan50', '850', - tunnel_map_ids, tunnel_map_entry_ids, tunnel_ids, tunnel_term_ids) - - tunnel_map_map['tunnel_1'] = check_vxlan_tunnel(dvs,'10.0.0.1', '100.100.100.1', - tunnel_map_ids, tunnel_map_entry_ids, tunnel_ids, tunnel_term_ids, loopback_id) - - create_vxlan_tunnel(dvs, 'tunnel_2', '11.0.0.2', '101.101.101.2', - tunnel_map_ids, tunnel_map_entry_ids, tunnel_ids, tunnel_term_ids, loopback_id) - - create_vxlan_tunnel_entry(dvs, 'tunnel_2', 'entry_1', tunnel_map_map, 'Vlan51', '851', - tunnel_map_ids, tunnel_map_entry_ids, tunnel_ids, tunnel_term_ids) - - tunnel_map_map['tunnel_2'] = check_vxlan_tunnel(dvs,'11.0.0.2', '101.101.101.2', - tunnel_map_ids, tunnel_map_entry_ids, tunnel_ids, tunnel_term_ids, loopback_id) - - create_vxlan_tunnel(dvs, 'tunnel_3', '12.0.0.3', '0.0.0.0', - tunnel_map_ids, tunnel_map_entry_ids, tunnel_ids, tunnel_term_ids, loopback_id) - - create_vxlan_tunnel_entry(dvs, 'tunnel_3', 'entry_1', tunnel_map_map, 'Vlan52', '852', - tunnel_map_ids, tunnel_map_entry_ids, tunnel_ids, tunnel_term_ids) - - tunnel_map_map['tunnel_3'] = check_vxlan_tunnel(dvs, '12.0.0.3', '0.0.0.0', - tunnel_map_ids, tunnel_map_entry_ids, tunnel_ids, tunnel_term_ids, loopback_id) - - create_vxlan_tunnel(dvs, 'tunnel_4', '15.0.0.5', '0.0.0.0', - tunnel_map_ids, tunnel_map_entry_ids, tunnel_ids, tunnel_term_ids, loopback_id, True) - - create_vxlan_tunnel_entry(dvs, 'tunnel_4', 'entry_1', tunnel_map_map, 'Vlan53', '853', - tunnel_map_ids, tunnel_map_entry_ids, tunnel_ids, tunnel_term_ids) - - tunnel_map_map['tunnel_4'] = check_vxlan_tunnel(dvs, '15.0.0.5', '0.0.0.0', - tunnel_map_ids, tunnel_map_entry_ids, tunnel_ids, tunnel_term_ids, loopback_id) - - create_vxlan_tunnel_entry(dvs, 'tunnel_1', 'entry_2', tunnel_map_map, 'Vlan54', '854', - tunnel_map_ids, tunnel_map_entry_ids, tunnel_ids, tunnel_term_ids) - - create_vxlan_tunnel_entry(dvs, 'tunnel_2', 'entry_2', tunnel_map_map, 'Vlan55', '855', - tunnel_map_ids, tunnel_map_entry_ids, tunnel_ids, tunnel_term_ids) - - create_vxlan_tunnel_entry(dvs, 'tunnel_3', 'entry_2', tunnel_map_map, 'Vlan56', '856', - tunnel_map_ids, tunnel_map_entry_ids, tunnel_ids, tunnel_term_ids) - - create_vxlan_tunnel_entry(dvs, 'tunnel_4', 'entry_2', tunnel_map_map, 'Vlan57', '857', - tunnel_map_ids, tunnel_map_entry_ids, tunnel_ids, tunnel_term_ids) - -def apply_test_vnet_cfg(cfg_db): - - # create VXLAN Tunnel - create_entry_tbl( - cfg_db, - "VXLAN_TUNNEL", '|', "tunnel1", - [ - ("src_ip", "1.1.1.1") - ], - ) - - # create VNET - create_entry_tbl( - cfg_db, - "VNET", '|', "tunnel1", - [ - ("vxlan_tunnel", "tunnel1"), - ("vni", "1") - ], - ) - - return - - -@pytest.fixture -def env_setup(dvs): - cfg_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - app_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - - create_entry_pst( - app_db, - "SWITCH_TABLE", ':', "switch", - [ - ("vxlan_router_mac", "00:01:02:03:04:05") - ], - ) - - apply_test_vnet_cfg(cfg_db) - - yield - - delete_entry_pst(app_db, "SWITCH_TABLE", "switch") - delete_entry_tbl(cfg_db, "VXLAN_TUNNEL", "tunnel1") - delete_entry_tbl(cfg_db, "VNET", "Vnet1") - -def test_vnet_cleanup_config_reload(dvs, env_setup): - - # Restart vxlanmgrd Process - dvs.runcmd(["systemctl", "restart", "vxlanmgrd"]) - - # Reapply cfg to simulate cfg reload - cfg_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - apply_test_vnet_cfg(cfg_db) - - time.sleep(0.5) - - # Check if the netdevices is created as expected - ret, stdout = dvs.runcmd(["ip", "link", "show"]) - assert "Vxlan1" in stdout - assert "Brvxlan1" in stdout - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_warm_reboot.py b/tests/test_warm_reboot.py deleted file mode 100644 index c0e4117f4b..0000000000 --- a/tests/test_warm_reboot.py +++ /dev/null @@ -1,2464 +0,0 @@ -import os -import re -import time -import json -import pytest - -from swsscommon import swsscommon - - -# macros for number of interfaces and number of neighbors -# TBD: NUM_NEIGH_PER_INTF >= 128 ips will cause test framework to hang by default kernel settings -# TBD: Need tune gc_thresh1/2/3 at host side of vs docker to support this. -NUM_INTF = 8 -NUM_NEIGH_PER_INTF = 16 #128 -NUM_OF_NEIGHS = (NUM_INTF*NUM_NEIGH_PER_INTF) - -# Get restore count of all processes supporting warm restart -def swss_get_RestoreCount(dvs, state_db): - restore_count = {} - warmtbl = swsscommon.Table(state_db, swsscommon.STATE_WARM_RESTART_TABLE_NAME) - keys = warmtbl.getKeys() - assert len(keys) != 0 - for key in keys: - if key not in dvs.swssd: - continue - (status, fvs) = warmtbl.get(key) - assert status == True - for fv in fvs: - if fv[0] == "restore_count": - restore_count[key] = int(fv[1]) - print(restore_count) - return restore_count - -# function to check the restore count incremented by 1 for all processes supporting warm restart -def swss_check_RestoreCount(dvs, state_db, restore_count): - warmtbl = swsscommon.Table(state_db, swsscommon.STATE_WARM_RESTART_TABLE_NAME) - keys = warmtbl.getKeys() - print(keys) - assert len(keys) > 0 - for key in keys: - if key not in dvs.swssd: - continue - (status, fvs) = warmtbl.get(key) - assert status == True - for fv in fvs: - if fv[0] == "restore_count": - assert int(fv[1]) == restore_count[key] + 1 - elif fv[0] == "state": - assert fv[1] == "reconciled" or fv[1] == "disabled" - -def check_port_oper_status(appl_db, port_name, state): - portTbl = swsscommon.Table(appl_db, swsscommon.APP_PORT_TABLE_NAME) - (status, fvs) = portTbl.get(port_name) - assert status == True - - oper_status = "unknown" - for v in fvs: - if v[0] == "oper_status": - oper_status = v[1] - break - assert oper_status == state - -def check_port_host_tx_ready_status(state_db, port_name, status): - portTable = swsscommon.Table(state_db, swsscommon.STATE_PORT_TABLE_NAME) - (status, fvs) = portTable.get(port_name) - - assert status == True - - assert "host_tx_ready" in [fv[0] for fv in fvs] - for fv in fvs: - if fv[0] == "host_tx_ready": - assert fv[1] == "true" if status == "up" else "false" - -def update_host_tx_ready_status(dvs, port_id, switch_id, admin_state): - host_tx_ready = "SAI_PORT_HOST_TX_READY_STATUS_READY" if admin_state == "up" else "SAI_PORT_HOST_TX_READY_STATUS_NOT_READY" - ntf = swsscommon.NotificationProducer(dvs.adb, "NOTIFICATIONS") - fvp = swsscommon.FieldValuePairs() - ntf_data = "[{\"host_tx_ready_status\":\""+host_tx_ready+"\",\"port_id\":\""+port_id+"\",\"switch_id\":\""+switch_id+"\"}]" - ntf.send("port_host_tx_ready", ntf_data, fvp) - -def get_port_id(dvs, port_name): - count_db = swsscommon.DBConnector(2, dvs.redis_sock, 0) - port_name_map = swsscommon.Table(count_db, "COUNTERS_PORT_NAME_MAP") - status, returned_value = port_name_map.hget("", port_name) - assert status == True - return returned_value - -# function to check the restore count incremented by 1 for a single process -def swss_app_check_RestoreCount_single(state_db, restore_count, name): - warmtbl = swsscommon.Table(state_db, swsscommon.STATE_WARM_RESTART_TABLE_NAME) - keys = warmtbl.getKeys() - print(keys) - print(restore_count) - assert len(keys) > 0 - for key in keys: - if key != name: - continue - (status, fvs) = warmtbl.get(key) - assert status == True - for fv in fvs: - if fv[0] == "restore_count": - assert int(fv[1]) == restore_count[key] + 1 - elif fv[0] == "state": - assert fv[1] == "reconciled" or fv[1] == "disabled" - return status, fvs - -def swss_app_check_warmstart_state(state_db, name, state): - warmtbl = swsscommon.Table(state_db, swsscommon.STATE_WARM_RESTART_TABLE_NAME) - keys = warmtbl.getKeys() - print(keys) - assert len(keys) > 0 - for key in keys: - if key != name: - continue - (status, fvs) = warmtbl.get(key) - assert status == True - for fv in fvs: - if fv[0] == "state": - assert fv[1] == state - -def create_entry(tbl, key, pairs): - fvs = swsscommon.FieldValuePairs(pairs) - tbl.set(key, fvs) - - # FIXME: better to wait until DB create them - time.sleep(1) - -def create_entry_tbl(db, table, key, pairs): - tbl = swsscommon.Table(db, table) - create_entry(tbl, key, pairs) - -def del_entry_tbl(db, table, key): - tbl = swsscommon.Table(db, table) - tbl._del(key) - -def create_entry_pst(db, table, key, pairs): - tbl = swsscommon.ProducerStateTable(db, table) - create_entry(tbl, key, pairs) - -def how_many_entries_exist(db, table): - tbl = swsscommon.Table(db, table) - return len(tbl.getKeys()) - -def stop_neighsyncd(dvs): - dvs.runcmd(['sh', '-c', 'pkill -x neighsyncd']) - time.sleep(1) - -def start_neighsyncd(dvs): - dvs.runcmd(['sh', '-c', 'supervisorctl start neighsyncd']) - -def stop_restore_neighbors(dvs): - dvs.runcmd(['sh', '-c', 'pkill -x restore_neighbors']) - time.sleep(1) - -def start_restore_neighbors(dvs): - dvs.runcmd(['sh', '-c', 'supervisorctl start restore_neighbors']) - -def check_no_neighsyncd_timer(dvs): - (exitcode, string) = dvs.runcmd(['sh', '-c', 'grep getWarmStartTimer /var/log/syslog | grep neighsyncd | grep invalid']) - assert string.strip() != "" - -def check_neighsyncd_timer(dvs, timer_value): - (exitcode, num) = dvs.runcmd(['sh', '-c', "grep getWarmStartTimer /var/log/syslog | grep neighsyncd | tail -n 1 | rev | cut -d ' ' -f 1 | rev"]) - assert num.strip() == timer_value - -def check_redis_neigh_entries(dvs, neigh_tbl, number): - # check application database and get neighbor table - appl_db = swsscommon.DBConnector(0, dvs.redis_sock, 0) - lo_entrytbl = swsscommon.Table(appl_db, "NEIGH_TABLE:lo") - lo_entries = lo_entrytbl.getKeys() - assert len(neigh_tbl.getKeys()) == number + len(lo_entries) - -def check_kernel_reachable_neigh_num(dvs, number): - (exitcode, output) = dvs.runcmd(['sh', '-c', "ip neigh show nud reachable| grep -v 'dev lo' | wc -l"]) - neigh_num = int(output.strip()) - assert neigh_num == number - -def check_kernel_reachable_v4_neigh_num(dvs, number): - (exitcode, output) = dvs.runcmd(['sh', '-c', "ip -4 neigh show nud reachable | grep -v 'dev lo' | wc -l"]) - neigh_num = int(output.strip()) - assert neigh_num == number - -def check_kernel_reachable_v6_neigh_num(dvs, number): - (exitcode, output) = dvs.runcmd(['sh', '-c', "ip -6 neigh show nud reachable | grep -v 'dev lo' | wc -l"]) - neigh_num = int(output.strip()) - assert neigh_num == number - -def check_kernel_stale_neigh_num(dvs, number): - (exitcode, output) = dvs.runcmd(['sh', '-c', "ip neigh show nud stale | grep -v 'dev lo' | wc -l"]) - neigh_num = int(output.strip()) - assert neigh_num == number - -def check_kernel_stale_v4_neigh_num(dvs, number): - (exitcode, output) = dvs.runcmd(['sh', '-c', "ip -4 neigh show nud stale | grep -v 'dev lo' | wc -l"]) - neigh_num = int(output.strip()) - assert neigh_num == number - -def check_kernel_stale_v6_neigh_num(dvs, number): - (exitcode, output) = dvs.runcmd(['sh', '-c', "ip -6 neigh show nud stale | grep -v 'dev lo' | wc -l"]) - neigh_num = int(output.strip()) - assert neigh_num == number - - -def kernel_restore_neighs_done(restoretbl): - keys = restoretbl.getKeys() - return (len(keys) > 0) - -# function to check neighbor entry reconciliation status written in syslog -def check_syslog_for_neighbor_entry(dvs, marker, new_cnt, delete_cnt, iptype): - # check reconciliation results (new or delete entries) for ipv4 and ipv6 - if iptype == "ipv4" or iptype == "ipv6": - (exitcode, num) = dvs.runcmd(['sh', '-c', "awk \'/%s/,ENDFILE {print;}\' /var/log/syslog | grep neighsyncd | grep cache-state:NEW | grep -i %s | grep -v 'lo:'| wc -l" % (marker, iptype)]) - assert num.strip() == str(new_cnt) - (exitcode, num) = dvs.runcmd(['sh', '-c', "awk \'/%s/,ENDFILE {print;}\' /var/log/syslog | grep neighsyncd | grep -E \"cache-state:(DELETE|STALE)\" | grep -i %s | grep -v 'lo:' | wc -l" % (marker, iptype)]) - assert num.strip() == str(delete_cnt) - else: - assert "iptype is unknown" == "" - -def set_restart_timer(dvs, db, app_name, value): - create_entry_tbl( - db, - swsscommon.CFG_WARM_RESTART_TABLE_NAME, app_name, - [ - (app_name + "_timer", value), - ] - ) - -# 'ip neigh flush all' won't remove failed entries if number of neighs less than gc_threshold1 -# Also it takes time to remove them completly. -# We use arp off/on to do it -def flush_neigh_entries(dvs): - dvs.runcmd("ip link set group default arp off") - dvs.runcmd("ip link set group default arp on") - -# Add neighbor entries on servers connecting to SONiC ports -# ping them to get the neighbor entries -def setup_initial_neighbors(dvs): - for i in range(8, 8+NUM_INTF): - for j in range(NUM_NEIGH_PER_INTF): - dvs.servers[i].runcmd("ip addr add {}.0.0.{}/24 dev eth0".format(i*4, j+2)) - dvs.servers[i].runcmd("ip -6 addr add {}00::{}/64 dev eth0".format(i*4, j+2)) - - time.sleep(1) - - for i in range(8, 8+NUM_INTF): - for j in range(NUM_NEIGH_PER_INTF): - dvs.runcmd(['sh', '-c', "ping -c 1 -W 0 -q {}.0.0.{} > /dev/null 2>&1".format(i*4, j+2)]) - dvs.runcmd(['sh', '-c', "ping6 -c 1 -W 0 -q {}00::{} > /dev/null 2>&1".format(i*4, j+2)]) - -# Del half of the ips and a new half of the ips -# note: the first ipv4 can not be deleted only -def del_and_add_neighbors(dvs): - for i in range(8, 8+NUM_INTF): - for j in range(NUM_NEIGH_PER_INTF//2): - dvs.servers[i].runcmd("ip addr del {}.0.0.{}/24 dev eth0".format(i*4, j+NUM_NEIGH_PER_INTF//2+2)) - dvs.servers[i].runcmd("ip -6 addr del {}00::{}/64 dev eth0".format(i*4, j+NUM_NEIGH_PER_INTF//2+2)) - dvs.servers[i].runcmd("ip addr add {}.0.0.{}/24 dev eth0".format(i*4, j+NUM_NEIGH_PER_INTF+2)) - dvs.servers[i].runcmd("ip -6 addr add {}00::{}/64 dev eth0".format(i*4, j+NUM_NEIGH_PER_INTF+2)) - -#ping new IPs -def ping_new_ips(dvs): - for i in range(8, 8+NUM_INTF): - for j in range(NUM_NEIGH_PER_INTF//2): - dvs.runcmd(['sh', '-c', "ping -c 1 -W 0 -q {}.0.0.{} > /dev/null 2>&1".format(i*4, j+NUM_NEIGH_PER_INTF+2)]) - dvs.runcmd(['sh', '-c', "ping6 -c 1 -W 0 -q {}00::{} > /dev/null 2>&1".format(i*4, j+NUM_NEIGH_PER_INTF+2)]) - -def warm_restart_set(dvs, app, enable): - db = swsscommon.DBConnector(6, dvs.redis_sock, 0) - tbl = swsscommon.Table(db, "WARM_RESTART_ENABLE_TABLE") - fvs = swsscommon.FieldValuePairs([("enable",enable)]) - tbl.set(app, fvs) - time.sleep(1) - - -def warm_restart_timer_set(dvs, app, timer, val): - db = swsscommon.DBConnector(4, dvs.redis_sock, 0) - tbl = swsscommon.Table(db, "WARM_RESTART") - fvs = swsscommon.FieldValuePairs([(timer, val)]) - tbl.set(app, fvs) - time.sleep(1) - -class TestWarmReboot(object): - def test_PortSyncdWarmRestart(self, dvs, testlog): - dvs.setup_db() - switch_id = dvs.getSwitchOid() - - conf_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - appl_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - state_db = swsscommon.DBConnector(swsscommon.STATE_DB, dvs.redis_sock, 0) - - dvs.warm_restart_swss("true") - - dvs.port_admin_set("Ethernet16", "up") - dvs.port_admin_set("Ethernet20", "up") - - time.sleep(1) - - config_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - intf_tbl = swsscommon.Table(config_db, "INTERFACE") - fvs = swsscommon.FieldValuePairs([("NULL","NULL")]) - intf_tbl.set("Ethernet16|11.0.0.1/29", fvs) - intf_tbl.set("Ethernet20|11.0.0.9/29", fvs) - intf_tbl.set("Ethernet16", fvs) - intf_tbl.set("Ethernet20", fvs) - dvs.port_admin_set("Ethernet16", "up") - dvs.port_admin_set("Ethernet20", "up") - - dvs.servers[4].runcmd("ip link set down dev eth0") == 0 - dvs.servers[4].runcmd("ip link set up dev eth0") == 0 - dvs.servers[4].runcmd("ifconfig eth0 11.0.0.2/29") - dvs.servers[4].runcmd("ip route add default via 11.0.0.1") - - dvs.servers[5].runcmd("ip link set down dev eth0") == 0 - dvs.servers[5].runcmd("ip link set up dev eth0") == 0 - dvs.servers[5].runcmd("ifconfig eth0 11.0.0.10/29") - dvs.servers[5].runcmd("ip route add default via 11.0.0.9") - - time.sleep(1) - - # Ethernet port oper status should be up - check_port_oper_status(appl_db, "Ethernet16", "up") - check_port_oper_status(appl_db, "Ethernet20", "up") - - update_host_tx_ready_status(dvs, get_port_id(dvs, "Ethernet16") , switch_id, "up") - update_host_tx_ready_status(dvs, get_port_id(dvs, "Ethernet20") , switch_id, "up") - - # Ethernet port host_tx_ready status should be "true" - check_port_host_tx_ready_status(state_db, "Ethernet16", "up") - check_port_host_tx_ready_status(state_db, "Ethernet20", "up") - - # Ping should work between servers via vs vlan interfaces - ping_stats = dvs.servers[4].runcmd("ping -c 1 11.0.0.10") - time.sleep(1) - - neighTbl = swsscommon.Table(appl_db, "NEIGH_TABLE") - (status, fvs) = neighTbl.get("Ethernet16:11.0.0.2") - assert status == True - - (status, fvs) = neighTbl.get("Ethernet20:11.0.0.10") - assert status == True - - restore_count = swss_get_RestoreCount(dvs, state_db) - - # restart portsyncd - dvs.runcmd(['sh', '-c', 'pkill -x portsyncd']) - time.sleep(1) - - pubsub = dvs.SubscribeAsicDbObject("SAI_OBJECT_TYPE") - dvs.runcmd(['sh', '-c', 'supervisorctl start portsyncd']) - - (nadd, ndel) = dvs.CountSubscribedObjects(pubsub) - assert nadd == 0 - assert ndel == 0 - - #new ip on server 5 - dvs.servers[5].runcmd("ifconfig eth0 11.0.0.11/29") - - # Ping should work between servers via vs Ethernet interfaces - ping_stats = dvs.servers[4].runcmd("ping -c 1 11.0.0.11") - - # new neighbor learn on VS - (status, fvs) = neighTbl.get("Ethernet20:11.0.0.11") - assert status == True - - # Port state change reflected in appDB correctly - dvs.servers[6].runcmd("ip link set down dev eth0") == 0 - dvs.servers[6].runcmd("ip link set up dev eth0") == 0 - time.sleep(1) - - check_port_oper_status(appl_db, "Ethernet16", "up") - check_port_oper_status(appl_db, "Ethernet20", "up") - check_port_oper_status(appl_db, "Ethernet24", "down") - - update_host_tx_ready_status(dvs, get_port_id(dvs, "Ethernet16") , switch_id, "up") - update_host_tx_ready_status(dvs, get_port_id(dvs, "Ethernet20") , switch_id, "up") - update_host_tx_ready_status(dvs, get_port_id(dvs, "Ethernet24") , switch_id, "down") - - check_port_host_tx_ready_status(state_db, "Ethernet16", "up") - check_port_host_tx_ready_status(state_db, "Ethernet20", "up") - check_port_host_tx_ready_status(state_db, "Ethernet24", "down") - - swss_app_check_RestoreCount_single(state_db, restore_count, "portsyncd") - - intf_tbl._del("Ethernet16|11.0.0.1/29") - intf_tbl._del("Ethernet20|11.0.0.9/29") - intf_tbl._del("Ethernet16") - intf_tbl._del("Ethernet20") - time.sleep(2) - - def test_VlanMgrdWarmRestart(self, dvs, testlog): - - conf_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - appl_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - state_db = swsscommon.DBConnector(swsscommon.STATE_DB, dvs.redis_sock, 0) - - dvs.runcmd("ifconfig Ethernet16 0") - dvs.runcmd("ifconfig Ethernet20 0") - - dvs.port_admin_set("Ethernet16", "up") - dvs.port_admin_set("Ethernet20", "up") - - time.sleep(1) - - dvs.warm_restart_swss("true") - - # create vlan - create_entry_tbl( - conf_db, - "VLAN", "Vlan16", - [ - ("vlanid", "16"), - ] - ) - # create vlan - create_entry_tbl( - conf_db, - "VLAN", "Vlan20", - [ - ("vlanid", "20"), - ] - ) - # create vlan member entry in config db. Don't use Ethernet0/4/8/12 as IP configured on them in previous testing. - create_entry_tbl( - conf_db, - "VLAN_MEMBER", "Vlan16|Ethernet16", - [ - ("tagging_mode", "untagged"), - ] - ) - - create_entry_tbl( - conf_db, - "VLAN_MEMBER", "Vlan20|Ethernet20", - [ - ("tagging_mode", "untagged"), - ] - ) - - time.sleep(1) - - intf_tbl = swsscommon.Table(conf_db, "INTERFACE") - fvs = swsscommon.FieldValuePairs([("NULL","NULL")]) - intf_tbl.set("Vlan16|11.0.0.1/29", fvs) - intf_tbl.set("Vlan20|11.0.0.9/29", fvs) - intf_tbl.set("Vlan16", fvs) - intf_tbl.set("Vlan20", fvs) - - dvs.servers[4].runcmd("ifconfig eth0 11.0.0.2/29") - dvs.servers[4].runcmd("ip route add default via 11.0.0.1") - - dvs.servers[5].runcmd("ifconfig eth0 11.0.0.10/29") - dvs.servers[5].runcmd("ip route add default via 11.0.0.9") - - time.sleep(1) - - # Ping should work between servers via vs vlan interfaces - ping_stats = dvs.servers[4].runcmd("ping -c 1 11.0.0.10") - time.sleep(1) - - tbl = swsscommon.Table(appl_db, "NEIGH_TABLE") - (status, fvs) = tbl.get("Vlan16:11.0.0.2") - assert status == True - - (status, fvs) = tbl.get("Vlan20:11.0.0.10") - assert status == True - - (exitcode, bv_before) = dvs.runcmd("bridge vlan") - print(bv_before) - - restore_count = swss_get_RestoreCount(dvs, state_db) - - dvs.runcmd(['sh', '-c', 'pkill -x vlanmgrd']) - time.sleep(1) - - pubsub = dvs.SubscribeAsicDbObject("SAI_OBJECT_TYPE") - - dvs.runcmd(['sh', '-c', 'supervisorctl start vlanmgrd']) - time.sleep(2) - - (exitcode, bv_after) = dvs.runcmd("bridge vlan") - assert bv_after == bv_before - - (nadd, ndel) = dvs.CountSubscribedObjects(pubsub, ignore=["SAI_OBJECT_TYPE_FDB_ENTRY"]) - assert nadd == 0 - assert ndel == 0 - - #new ip on server 5 - dvs.servers[5].runcmd("ifconfig eth0 11.0.0.11/29") - - # Ping should work between servers via vs vlan interfaces - ping_stats = dvs.servers[4].runcmd("ping -c 1 11.0.0.11") - - # new neighbor learn on VS - (status, fvs) = tbl.get("Vlan20:11.0.0.11") - assert status == True - - swss_app_check_RestoreCount_single(state_db, restore_count, "vlanmgrd") - - intf_tbl._del("Vlan16|11.0.0.1/29") - intf_tbl._del("Vlan20|11.0.0.9/29") - intf_tbl._del("Vlan16") - intf_tbl._del("Vlan20") - time.sleep(2) - - def test_IntfMgrdWarmRestartNoInterfaces(self, dvs, testlog): - """ Tests that intfmgrd reaches reconciled state when - there are no interfaces in configuration. """ - - state_db = swsscommon.DBConnector(swsscommon.STATE_DB, dvs.redis_sock, 0) - restore_count = swss_get_RestoreCount(dvs, state_db) - - dvs.warm_restart_swss("true") - dvs.runcmd("supervisorctl restart intfmgrd") - - reached_desired_state = False - retries = 10 - delay = 2 - for _ in range(retries): - ok, fvs = swss_app_check_RestoreCount_single(state_db, restore_count, "intfmgrd") - if ok and dict(fvs)["state"] == "reconciled": - reached_desired_state = True - break - time.sleep(delay) - - assert reached_desired_state, "intfmgrd haven't reached desired state 'reconciled', after {} sec it was {}".format(retries * delay, dict(fvs)["state"]) - - def test_swss_neighbor_syncup(self, dvs, testlog): - - appl_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - conf_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - state_db = swsscommon.DBConnector(swsscommon.STATE_DB, dvs.redis_sock, 0) - - dvs.warm_restart_swss("true") - - # - # Testcase1: - # Add neighbor entries in linux kernel, appDB should get all of them - # - - # create neighbor entries (4 ipv4 and 4 ip6, two each on each interface) in linux kernel - intfs = ["Ethernet24", "Ethernet28"] - - for intf in intfs: - # set timeout to be the same as real HW - dvs.runcmd("sysctl -w net.ipv4.neigh.{}.base_reachable_time_ms=1800000".format(intf)) - dvs.runcmd("sysctl -w net.ipv6.neigh.{}.base_reachable_time_ms=1800000".format(intf)) - - #enable ipv6 on docker - dvs.runcmd("sysctl net.ipv6.conf.all.disable_ipv6=0") - - config_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - intf_tbl = swsscommon.Table(config_db, "INTERFACE") - fvs = swsscommon.FieldValuePairs([("NULL","NULL")]) - intf_tbl.set("{}|24.0.0.1/24".format(intfs[0]), fvs) - intf_tbl.set("{}|28.0.0.9/24".format(intfs[1]), fvs) - intf_tbl.set("{}|2400::1/64".format(intfs[0]), fvs) - intf_tbl.set("{}|2800::1/64".format(intfs[1]), fvs) - intf_tbl.set("{}".format(intfs[0]), fvs) - intf_tbl.set("{}".format(intfs[1]), fvs) - intf_tbl.set("{}".format(intfs[0]), fvs) - intf_tbl.set("{}".format(intfs[1]), fvs) - dvs.port_admin_set(intfs[0], "up") - dvs.port_admin_set(intfs[1], "up") - - ips = ["24.0.0.2", "24.0.0.3", "28.0.0.2", "28.0.0.3"] - v6ips = ["2400::2", "2400::3", "2800::2", "2800::3"] - - macs = ["00:00:00:00:24:02", "00:00:00:00:24:03", "00:00:00:00:28:02", "00:00:00:00:28:03"] - - for i in range(len(ips)): - dvs.runcmd("ip neigh add {} dev {} lladdr {} nud reachable".format(ips[i], intfs[i//2], macs[i])) - - for i in range(len(v6ips)): - dvs.runcmd("ip -6 neigh add {} dev {} lladdr {} nud reachable".format(v6ips[i], intfs[i//2], macs[i])) - - time.sleep(1) - - # Check the neighbor entries are inserted correctly - db = swsscommon.DBConnector(0, dvs.redis_sock, 0) - tbl = swsscommon.Table(db, "NEIGH_TABLE") - - for i in range(len(ips)): - (status, fvs) = tbl.get("{}:{}".format(intfs[i//2], ips[i])) - assert status == True - - for v in fvs: - if v[0] == "neigh": - assert v[1] == macs[i] - if v[0] == "family": - assert v[1] == "IPv4" - - for i in range(len(v6ips)): - (status, fvs) = tbl.get("{}:{}".format(intfs[i//2], v6ips[i])) - assert status == True - - for v in fvs: - if v[0] == "neigh": - assert v[1] == macs[i] - if v[0] == "family": - assert v[1] == "IPv6" - - # - # Testcase 2: - # Restart neighsyncd without change neighbor entries, nothing should be sent to appDB or sairedis, - # appDB should be kept the same. - # - - # get restore_count - restore_count = swss_get_RestoreCount(dvs, state_db) - - # stop neighsyncd and sairedis.rec - stop_neighsyncd(dvs) - del_entry_tbl(state_db, "NEIGH_RESTORE_TABLE", "Flags") - marker = dvs.add_log_marker() - pubsub = dvs.SubscribeAsicDbObject("SAI_OBJECT_TYPE_NEIGHBOR_ENTRY") - start_neighsyncd(dvs) - start_restore_neighbors(dvs) - time.sleep(10) - - # Check the neighbor entries are still in appDB correctly - for i in range(len(ips)): - (status, fvs) = tbl.get("{}:{}".format(intfs[i//2], ips[i])) - assert status == True - - for v in fvs: - if v[0] == "neigh": - assert v[1] == macs[i] - if v[0] == "family": - assert v[1] == "IPv4" - - for i in range(len(v6ips)): - (status, fvs) = tbl.get("{}:{}".format(intfs[i//2], v6ips[i])) - assert status == True - - for v in fvs: - if v[0] == "neigh": - assert v[1] == macs[i] - if v[0] == "family": - assert v[1] == "IPv6" - - # check syslog and sairedis.rec file for activities - check_syslog_for_neighbor_entry(dvs, marker, 0, 0, "ipv4") - check_syslog_for_neighbor_entry(dvs, marker, 0, 0, "ipv6") - (nadd, ndel) = dvs.CountSubscribedObjects(pubsub) - assert nadd == 0 - assert ndel == 0 - - # check restore Count - swss_app_check_RestoreCount_single(state_db, restore_count, "neighsyncd") - - # - # Testcase 3: - # stop neighsyncd, delete even nummber ipv4/ipv6 neighbor entries from each interface, warm start neighsyncd. - # the neighsyncd is supposed to sync up the entries from kernel after warm restart - # note: there was an issue for neighbor delete, it will be marked as FAILED instead of deleted in kernel - # but it will send netlink message to be removed from appDB, so it works ok here, - # just that if we want to add the same neighbor again, use "change" instead of "add" - - # get restore_count - restore_count = swss_get_RestoreCount(dvs, state_db) - - # stop neighsyncd - stop_neighsyncd(dvs) - del_entry_tbl(state_db, "NEIGH_RESTORE_TABLE", "Flags") - marker = dvs.add_log_marker() - - # delete even nummber of ipv4/ipv6 neighbor entries from each interface - for i in range(0, len(ips), 2): - dvs.runcmd("ip neigh del {} dev {}".format(ips[i], intfs[i//2])) - - for i in range(0, len(v6ips), 2): - dvs.runcmd("ip -6 neigh del {} dev {}".format(v6ips[i], intfs[i//2])) - - # start neighsyncd again - start_neighsyncd(dvs) - start_restore_neighbors(dvs) - time.sleep(10) - - # check ipv4 and ipv6 neighbors - for i in range(len(ips)): - (status, fvs) = tbl.get("{}:{}".format(intfs[i//2], ips[i])) - #should not see deleted neighbor entries - if i % 2 == 0: - assert status == False - continue - else: - assert status == True - - #undeleted entries should still be there. - for v in fvs: - if v[0] == "neigh": - assert v[1] == macs[i] - if v[0] == "family": - assert v[1] == "IPv4" - - for i in range(len(v6ips)): - (status, fvs) = tbl.get("{}:{}".format(intfs[i//2], v6ips[i])) - #should not see deleted neighbor entries - if i % 2 == 0: - assert status == False - continue - else: - assert status == True - - #undeleted entries should still be there. - for v in fvs: - if v[0] == "neigh": - assert v[1] == macs[i] - if v[0] == "family": - assert v[1] == "IPv6" - - # check syslog and sairedis.rec file for activities - # 2 deletes each for ipv4 and ipv6 - # 4 neighbor removal in asic db - check_syslog_for_neighbor_entry(dvs, marker, 0, 2, "ipv4") - check_syslog_for_neighbor_entry(dvs, marker, 0, 2, "ipv6") - (nadd, ndel) = dvs.CountSubscribedObjects(pubsub) - assert nadd == 0 - assert ndel == 4 - - # check restore Count - swss_app_check_RestoreCount_single(state_db, restore_count, "neighsyncd") - - - # - # Testcase 4: - # Stop neighsyncd, add even nummber of ipv4/ipv6 neighbor entries to each interface again, - # Start neighsyncd - # The neighsyncd is supposed to sync up the entries from kernel after warm restart - # Check the timer is not retrieved from configDB since it is not configured - - # get restore_count - restore_count = swss_get_RestoreCount(dvs, state_db) - - # stop neighsyncd - stop_neighsyncd(dvs) - del_entry_tbl(state_db, "NEIGH_RESTORE_TABLE", "Flags") - marker = dvs.add_log_marker() - - # add even nummber of ipv4/ipv6 neighbor entries to each interface - # use "change" if neighbor is in FAILED state - for i in range(0, len(ips), 2): - (rc, output) = dvs.runcmd(['sh', '-c', "ip -4 neigh | grep {}".format(ips[i])]) - print(output) - if output: - dvs.runcmd("ip neigh change {} dev {} lladdr {} nud reachable".format(ips[i], intfs[i//2], macs[i])) - else: - dvs.runcmd("ip neigh add {} dev {} lladdr {} nud reachable".format(ips[i], intfs[i//2], macs[i])) - - for i in range(0, len(v6ips), 2): - (rc, output) = dvs.runcmd(['sh', '-c', "ip -6 neigh | grep {}".format(v6ips[i])]) - print(output) - if output: - dvs.runcmd("ip -6 neigh change {} dev {} lladdr {} nud reachable".format(v6ips[i], intfs[i//2], macs[i])) - else: - dvs.runcmd("ip -6 neigh add {} dev {} lladdr {} nud reachable".format(v6ips[i], intfs[i//2], macs[i])) - - # start neighsyncd again - start_neighsyncd(dvs) - start_restore_neighbors(dvs) - time.sleep(10) - - # no neighsyncd timer configured - check_no_neighsyncd_timer(dvs) - - # check ipv4 and ipv6 neighbors, should see all neighbors - for i in range(len(ips)): - (status, fvs) = tbl.get("{}:{}".format(intfs[i//2], ips[i])) - assert status == True - for v in fvs: - if v[0] == "neigh": - assert v[1] == macs[i] - if v[0] == "family": - assert v[1] == "IPv4" - - for i in range(len(v6ips)): - (status, fvs) = tbl.get("{}:{}".format(intfs[i//2], v6ips[i])) - assert status == True - for v in fvs: - if v[0] == "neigh": - assert v[1] == macs[i] - if v[0] == "family": - assert v[1] == "IPv6" - - # check syslog and asic db for activities - # 2 news entries for ipv4 and ipv6 each - # 4 neighbor creation in asic db - check_syslog_for_neighbor_entry(dvs, marker, 2, 0, "ipv4") - check_syslog_for_neighbor_entry(dvs, marker, 2, 0, "ipv6") - (nadd, ndel) = dvs.CountSubscribedObjects(pubsub) - assert nadd == 4 - assert ndel == 0 - - # check restore Count - swss_app_check_RestoreCount_single(state_db, restore_count, "neighsyncd") - - # - # Testcase 5: - # Even number of ip4/6 neigbors updated with new mac. - # Odd number of ipv4/6 neighbors removed - # neighbor syncd should sync it up after warm restart - # include the timer settings in this testcase - - # setup timer in configDB - timer_value = "15" - - warm_restart_timer_set(dvs, "swss", "neighsyncd_timer", timer_value) - - # get restore_count - restore_count = swss_get_RestoreCount(dvs, state_db) - - # stop neighsyncd - stop_neighsyncd(dvs) - del_entry_tbl(state_db, "NEIGH_RESTORE_TABLE", "Flags") - marker = dvs.add_log_marker() - - # Even number of ip4/6 neigbors updated with new mac. - # Odd number of ipv4/6 neighbors removed - newmacs = ["00:00:00:01:12:02", "00:00:00:01:12:03", "00:00:00:01:16:02", "00:00:00:01:16:03"] - - for i in range(len(ips)): - if i % 2 == 0: - dvs.runcmd("ip neigh change {} dev {} lladdr {} nud reachable".format(ips[i], intfs[i//2], newmacs[i])) - else: - dvs.runcmd("ip neigh del {} dev {}".format(ips[i], intfs[i//2])) - - for i in range(len(v6ips)): - if i % 2 == 0: - dvs.runcmd("ip -6 neigh change {} dev {} lladdr {} nud reachable".format(v6ips[i], intfs[i//2], newmacs[i])) - else: - dvs.runcmd("ip -6 neigh del {} dev {}".format(v6ips[i], intfs[i//2])) - - # start neighsyncd again - start_neighsyncd(dvs) - start_restore_neighbors(dvs) - time.sleep(10) - - # timer is not expired yet, state should be "restored" - swss_app_check_warmstart_state(state_db, "neighsyncd", "restored") - time.sleep(10) - - # check neigh syncd timer is retrived from configDB - check_neighsyncd_timer(dvs, timer_value) - - # check ipv4 and ipv6 neighbors, should see all neighbors with updated info - for i in range(len(ips)): - if i % 2 == 0: - (status, fvs) = tbl.get("{}:{}".format(intfs[i//2], ips[i])) - assert status == True - for v in fvs: - if v[0] == "neigh": - assert v[1] == newmacs[i] - if v[0] == "family": - assert v[1] == "IPv4" - else: - (status, fvs) = tbl.get("{}:{}".format(intfs[i//2], ips[i])) - assert status == False - - for i in range(len(v6ips)): - if i % 2 == 0: - (status, fvs) = tbl.get("{}:{}".format(intfs[i//2], v6ips[i])) - assert status == True - for v in fvs: - if v[0] == "neigh": - assert v[1] == newmacs[i] - if v[0] == "family": - assert v[1] == "IPv6" - else: - (status, fvs) = tbl.get("{}:{}".format(intfs[i//2], v6ips[i])) - assert status == False - - time.sleep(2) - - # check syslog and asic db for activities - # 2 news, 2 deletes for ipv4 and ipv6 each - # 4 set, 4 removes for neighbor in asic db - check_syslog_for_neighbor_entry(dvs, marker, 2, 2, "ipv4") - check_syslog_for_neighbor_entry(dvs, marker, 2, 2, "ipv6") - (nadd, ndel) = dvs.CountSubscribedObjects(pubsub) - assert nadd == 4 - assert ndel == 4 - - # check restore Count - swss_app_check_RestoreCount_single(state_db, restore_count, "neighsyncd") - - # post-cleanup - dvs.runcmd("ip -s neigh flush all") - dvs.runcmd("ip -6 -s neigh flush all") - - intf_tbl._del("{}|24.0.0.1/24".format(intfs[0])) - intf_tbl._del("{}|28.0.0.9/24".format(intfs[1])) - intf_tbl._del("{}|2400::1/64".format(intfs[0])) - intf_tbl._del("{}|2800::1/64".format(intfs[1])) - intf_tbl._del("{}".format(intfs[0])) - intf_tbl._del("{}".format(intfs[1])) - intf_tbl._del("{}".format(intfs[0])) - intf_tbl._del("{}".format(intfs[1])) - time.sleep(2) - - - # TODO: The condition of warm restart readiness check is still under discussion. - def test_OrchagentWarmRestartReadyCheck(self, dvs, testlog): - - time.sleep(1) - - dvs.warm_restart_swss("true") - - config_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - intf_tbl = swsscommon.Table(config_db, "INTERFACE") - fvs = swsscommon.FieldValuePairs([("NULL","NULL")]) - intf_tbl.set("Ethernet0|10.0.0.0/31", fvs) - intf_tbl.set("Ethernet4|10.0.0.2/31", fvs) - intf_tbl.set("Ethernet0", fvs) - intf_tbl.set("Ethernet4", fvs) - dvs.port_admin_set("Ethernet0", "up") - dvs.port_admin_set("Ethernet4", "up") - - dvs.servers[0].runcmd("ifconfig eth0 10.0.0.1/31") - dvs.servers[0].runcmd("ip route add default via 10.0.0.0") - - dvs.servers[1].runcmd("ifconfig eth0 10.0.0.3/31") - dvs.servers[1].runcmd("ip route add default via 10.0.0.2") - - - appl_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - ps = swsscommon.ProducerStateTable(appl_db, swsscommon.APP_ROUTE_TABLE_NAME) - fvs = swsscommon.FieldValuePairs([("nexthop","10.0.0.1"), ("ifname", "Ethernet0")]) - ps.set("2.2.2.0/24", fvs) - - fvs = swsscommon.FieldValuePairs([("nexthop","20.0.0.1"), ("ifname", "Ethernet0")]) - ps.set("3.3.3.0/24", fvs) - - time.sleep(1) - # Should fail, since neighbor for next 20.0.0.1 has not been not resolved yet - (exitcode, result) = dvs.runcmd("/usr/bin/orchagent_restart_check", include_stderr=False) - assert result == "RESTARTCHECK failed\n" - - # Should succeed, the option for skipPendingTaskCheck -s and noFreeze -n have been provided. - # Wait up to 500 milliseconds for response from orchagent. Default wait time is 1000 milliseconds. - (exitcode, result) = dvs.runcmd("/usr/bin/orchagent_restart_check -n -s -w 500", include_stderr=False) - assert result == "RESTARTCHECK succeeded\n" - - # Remove unfinished routes - ps._del("3.3.3.0/24") - - time.sleep(1) - (exitcode, result) = dvs.runcmd("/usr/bin/orchagent_restart_check", include_stderr=False) - assert result == "RESTARTCHECK succeeded\n" - - # Should fail since orchagent has been frozen at last step. - (exitcode, result) = dvs.runcmd("/usr/bin/orchagent_restart_check -n -s -w 500", include_stderr=False) - assert result == "RESTARTCHECK failed\n" - - # Cleaning previously pushed route-entry to ease life of subsequent testcases. - ps._del("2.2.2.0/24") - time.sleep(1) - - intf_tbl._del("Ethernet0|10.0.0.0/31") - intf_tbl._del("Ethernet4|10.0.0.2/31") - intf_tbl._del("Ethernet0") - intf_tbl._del("Ethernet4") - time.sleep(2) - - # recover for test cases after this one. - dvs.stop_swss() - dvs.start_swss() - time.sleep(5) - - def test_swss_port_state_syncup(self, dvs, testlog): - - appl_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - conf_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - state_db = swsscommon.DBConnector(swsscommon.STATE_DB, dvs.redis_sock, 0) - - dvs.warm_restart_swss("true") - - tbl = swsscommon.Table(appl_db, swsscommon.APP_PORT_TABLE_NAME) - - restore_count = swss_get_RestoreCount(dvs, state_db) - - # update port admin state - intf_tbl = swsscommon.Table(conf_db, "INTERFACE") - fvs = swsscommon.FieldValuePairs([("NULL","NULL")]) - intf_tbl.set("Ethernet0|10.0.0.0/31", fvs) - intf_tbl.set("Ethernet4|10.0.0.2/31", fvs) - intf_tbl.set("Ethernet8|10.0.0.4/31", fvs) - intf_tbl.set("Ethernet0", fvs) - intf_tbl.set("Ethernet4", fvs) - intf_tbl.set("Ethernet8", fvs) - dvs.port_admin_set("Ethernet0", "up") - dvs.port_admin_set("Ethernet4", "up") - dvs.port_admin_set("Ethernet8", "up") - - dvs.runcmd("arp -s 10.0.0.1 00:00:00:00:00:01") - dvs.runcmd("arp -s 10.0.0.3 00:00:00:00:00:02") - dvs.runcmd("arp -s 10.0.0.5 00:00:00:00:00:03") - - dvs.servers[0].runcmd("ip link set down dev eth0") == 0 - dvs.servers[1].runcmd("ip link set down dev eth0") == 0 - dvs.servers[2].runcmd("ip link set down dev eth0") == 0 - - dvs.servers[2].runcmd("ip link set up dev eth0") == 0 - - time.sleep(3) - - for i in [0, 1, 2]: - (status, fvs) = tbl.get("Ethernet%d" % (i * 4)) - assert status == True - oper_status = "unknown" - for v in fvs: - if v[0] == "oper_status": - oper_status = v[1] - break - if i == 2: - assert oper_status == "up" - else: - assert oper_status == "down" - - intf_tbl._del("Ethernet0|10.0.0.0/31") - intf_tbl._del("Ethernet4|10.0.0.2/31") - intf_tbl._del("Ethernet8|10.0.0.4/31") - intf_tbl._del("Ethernet0") - intf_tbl._del("Ethernet4") - intf_tbl._del("Ethernet8") - time.sleep(2) - - dvs.stop_swss() - time.sleep(3) - - # flap the port oper status for Ethernet0, Ethernet4 and Ethernet8 - dvs.servers[0].runcmd("ip link set down dev eth0") == 0 - dvs.servers[1].runcmd("ip link set down dev eth0") == 0 - dvs.servers[2].runcmd("ip link set down dev eth0") == 0 - - dvs.servers[0].runcmd("ip link set up dev eth0") == 0 - dvs.servers[1].runcmd("ip link set up dev eth0") == 0 - - time.sleep(5) - dbobjs =[(swsscommon.APPL_DB, swsscommon.APP_PORT_TABLE_NAME + ":*"), \ - (swsscommon.STATE_DB, swsscommon.STATE_WARM_RESTART_TABLE_NAME + "|orchagent")] - pubsubDbs = dvs.SubscribeDbObjects(dbobjs) - dvs.start_swss() - start_restore_neighbors(dvs) - time.sleep(10) - - swss_check_RestoreCount(dvs, state_db, restore_count) - - intf_tbl.set("Ethernet0|10.0.0.0/31", fvs) - intf_tbl.set("Ethernet4|10.0.0.2/31", fvs) - intf_tbl.set("Ethernet8|10.0.0.4/31", fvs) - intf_tbl.set("Ethernet0", fvs) - intf_tbl.set("Ethernet4", fvs) - intf_tbl.set("Ethernet8", fvs) - time.sleep(3) - - for i in [0, 1, 2]: - (status, fvs) = tbl.get("Ethernet%d" % (i * 4)) - assert status == True - oper_status = "unknown" - for v in fvs: - if v[0] == "oper_status": - oper_status = v[1] - break - if i == 2: - assert oper_status == "down" - else: - assert oper_status == "up" - - # check the pubsub messages. - # No appDB port table operation should exist before orchagent state restored flag got set. - # appDB port table status sync up happens before WARM_RESTART_TABLE reconciled flag is set - # pubsubMessages is an ordered list of pubsub messages. - pubsubMessages = dvs.GetSubscribedMessages(pubsubDbs) - - portOperStatusChanged = False - # number of times that WARM_RESTART_TABLE|orchagent key was set after the first - # appDB port table operation - orchStateCount = 0 - for message in pubsubMessages: - print(message) - key = message['channel'].split(':', 1)[1] - print(key) - if message['data'] != 'hset' and message['data'] != 'del': - continue - if key.find(swsscommon.APP_PORT_TABLE_NAME)==0: - portOperStatusChanged = True - else: - # found one orchagent WARM_RESTART_TABLE operation after appDB port table change - if portOperStatusChanged == True: - orchStateCount += 1; - - # Only WARM_RESTART_TABLE|orchagent state=reconciled operation may exist after port oper status change. - assert orchStateCount == 2 - - #clean up arp - dvs.runcmd("arp -d 10.0.0.1") - dvs.runcmd("arp -d 10.0.0.3") - dvs.runcmd("arp -d 10.0.0.5") - - intf_tbl._del("Ethernet0|10.0.0.0/31") - intf_tbl._del("Ethernet4|10.0.0.2/31") - intf_tbl._del("Ethernet8|10.0.0.4/31") - intf_tbl._del("Ethernet0") - intf_tbl._del("Ethernet4") - intf_tbl._del("Ethernet8") - time.sleep(2) - - - ############################################################################# - # # - # Routing Warm-Restart Testing # - # # - ############################################################################# - - - ################################################################################ - # - # Routing warm-restart testcases - # - ################################################################################ - - def test_routing_WarmRestart(self, dvs, testlog): - - appl_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - conf_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - state_db = swsscommon.DBConnector(swsscommon.STATE_DB, dvs.redis_sock, 0) - - # Restart-timer to utilize during the following testcases - restart_timer = 15 - - - ############################################################################# - # - # Baseline configuration - # - ############################################################################# - - - # Defining create neighbor entries (4 ipv4 and 4 ip6, two each on each interface) in linux kernel - intfs = ["Ethernet0", "Ethernet4", "Ethernet8"] - - # Enable ipv6 on docker - dvs.runcmd("sysctl net.ipv6.conf.all.disable_ipv6=0") - - # Defining create neighbor entries (4 ipv4 and 4 ip6, two each on each interface) in linux kernel - intf_tbl = swsscommon.Table(conf_db, "INTERFACE") - fvs = swsscommon.FieldValuePairs([("NULL","NULL")]) - intf_tbl.set("{}|111.0.0.1/24".format(intfs[0]), fvs) - intf_tbl.set("{}|1110::1/64".format(intfs[0]), fvs) - intf_tbl.set("{}|122.0.0.1/24".format(intfs[1]), fvs) - intf_tbl.set("{}|1220::1/64".format(intfs[1]), fvs) - intf_tbl.set("{}|133.0.0.1/24".format(intfs[2]), fvs) - intf_tbl.set("{}|1330::1/64".format(intfs[2]), fvs) - intf_tbl.set("{}".format(intfs[0]), fvs) - intf_tbl.set("{}".format(intfs[0]), fvs) - intf_tbl.set("{}".format(intfs[1]), fvs) - intf_tbl.set("{}".format(intfs[1]), fvs) - intf_tbl.set("{}".format(intfs[2]), fvs) - intf_tbl.set("{}".format(intfs[2]), fvs) - dvs.port_admin_set(intfs[0], "up") - dvs.port_admin_set(intfs[1], "up") - dvs.port_admin_set(intfs[2], "up") - - time.sleep(1) - - # - # Setting peer's ip-addresses and associated neighbor-entries - # - ips = ["111.0.0.2", "122.0.0.2", "133.0.0.2"] - v6ips = ["1110::2", "1220::2", "1330::2"] - macs = ["00:00:00:00:11:02", "00:00:00:00:12:02", "00:00:00:00:13:02"] - - for i in range(len(ips)): - dvs.runcmd("ip neigh add {} dev {} lladdr {}".format(ips[i], intfs[i%2], macs[i])) - - for i in range(len(v6ips)): - dvs.runcmd("ip -6 neigh add {} dev {} lladdr {}".format(v6ips[i], intfs[i%2], macs[i])) - - time.sleep(1) - - # - # Defining baseline IPv4 non-ecmp route-entries - # - dvs.runcmd("ip route add 192.168.1.100/32 nexthop via 111.0.0.2") - dvs.runcmd("ip route add 192.168.1.200/32 nexthop via 122.0.0.2") - dvs.runcmd("ip route add 192.168.1.230/32 nexthop via 133.0.0.2") - - # - # Defining baseline IPv4 ecmp route-entries - # - dvs.runcmd("ip route add 192.168.1.1/32 nexthop via 111.0.0.2 nexthop via 122.0.0.2 nexthop via 133.0.0.2") - dvs.runcmd("ip route add 192.168.1.2/32 nexthop via 111.0.0.2 nexthop via 122.0.0.2 nexthop via 133.0.0.2") - dvs.runcmd("ip route add 192.168.1.3/32 nexthop via 111.0.0.2 nexthop via 122.0.0.2") - - # - # Defining baseline IPv6 non-ecmp route-entries - # - dvs.runcmd("ip -6 route add fc00:11:11::1/128 nexthop via 1110::2") - dvs.runcmd("ip -6 route add fc00:12:12::1/128 nexthop via 1220::2") - dvs.runcmd("ip -6 route add fc00:13:13::1/128 nexthop via 1330::2") - - # - # Defining baseline IPv6 ecmp route-entries - # - dvs.runcmd("ip -6 route add fc00:1:1::1/128 nexthop via 1110::2 nexthop via 1220::2 nexthop via 1330::2") - dvs.runcmd("ip -6 route add fc00:2:2::1/128 nexthop via 1110::2 nexthop via 1220::2 nexthop via 1330::2") - dvs.runcmd("ip -6 route add fc00:3:3::1/128 nexthop via 1110::2 nexthop via 1220::2") - - time.sleep(5) - - # Enabling some extra logging for troubleshooting purposes - dvs.runcmd("swssloglevel -l INFO -c fpmsyncd") - - # Subscribe to pubsub channels for routing-state associated to swss and sairedis dbs - pubsubAppDB = dvs.SubscribeAppDbObject("ROUTE_TABLE") - pubsubAsicDB = dvs.SubscribeAsicDbObject("SAI_OBJECT_TYPE_ROUTE_ENTRY") - - - ############################################################################# - # - # Testcase 1. Having routing-warm-reboot disabled, restart zebra and verify - # that the traditional/cold-boot logic is followed. - # - ############################################################################# - - # Restart zebra - dvs.stop_zebra() - dvs.start_zebra() - - time.sleep(5) - - # Verify FSM - swss_app_check_warmstart_state(state_db, "bgp", "disabled") - - # Verify that multiple changes are seen in swss and sairedis logs as there's - # no warm-reboot logic in place. - (addobjs, delobjs) = dvs.GetSubscribedAppDbObjects(pubsubAppDB) - assert len(addobjs) != 0 - - (addobjs, delobjs) = dvs.GetSubscribedAsicDbObjects(pubsubAsicDB) - assert len(addobjs) != 0 - - - ############################################################################# - # - # Testcase 2. Restart zebra and make no control-plane changes. - # For this and all subsequent test-cases routing-warm-reboot - # feature will be kept enabled. - # - ############################################################################# - - - # Enabling bgp warmrestart and setting restart timer. - # The following two instructions will be substituted by the commented ones - # once the later ones are added to sonic-utilities repo. - - warm_restart_set(dvs, "bgp", "true") - warm_restart_timer_set(dvs, "bgp", "bgp_timer", str(restart_timer)) - - time.sleep(1) - - # Restart zebra - dvs.stop_zebra() - dvs.start_zebra() - - # Verify FSM - swss_app_check_warmstart_state(state_db, "bgp", "restored") - time.sleep(restart_timer + 1) - swss_app_check_warmstart_state(state_db, "bgp", "reconciled") - - # Verify swss changes -- none are expected this time - (addobjs, delobjs) = dvs.GetSubscribedAppDbObjects(pubsubAppDB) - assert len(addobjs) == 0 and len(delobjs) == 0 - - # Verify swss changes -- none are expected this time - (addobjs, delobjs) = dvs.GetSubscribedAsicDbObjects(pubsubAsicDB) - assert len(addobjs) == 0 and len(delobjs) == 0 - - - ############################################################################# - # - # Testcase 3. Restart zebra and add one new non-ecmp IPv4 prefix - # - ############################################################################# - - # Stop zebra - dvs.stop_zebra() - - # Add new prefix - dvs.runcmd("ip route add 192.168.100.0/24 nexthop via 111.0.0.2") - time.sleep(1) - - # Start zebra - dvs.start_zebra() - - # Verify FSM - swss_app_check_warmstart_state(state_db, "bgp", "restored") - time.sleep(restart_timer + 1) - swss_app_check_warmstart_state(state_db, "bgp", "reconciled") - - # Verify the changed prefix is seen in swss - (addobjs, delobjs) = dvs.GetSubscribedAppDbObjects(pubsubAppDB) - assert len(addobjs) == 1 and len(delobjs) == 0 - rt_key = json.loads(addobjs[0]['key']) - rt_val = json.loads(addobjs[0]['vals']) - assert rt_key == "192.168.100.0/24" - assert rt_val.get("ifname") == "Ethernet0" - assert rt_val.get("nexthop") == "111.0.0.2" - - # Verify the changed prefix is seen in sairedis - (addobjs, delobjs) = dvs.GetSubscribedAsicDbObjects(pubsubAsicDB) - assert len(addobjs) == 1 and len(delobjs) == 0 - rt_key = json.loads(addobjs[0]['key']) - assert rt_key['dest'] == "192.168.100.0/24" - - - ############################################################################# - # - # Testcase 4. Restart zebra and withdraw one non-ecmp IPv4 prefix - # - ############################################################################# - - - # Stop zebra - dvs.stop_zebra() - - # Delete prefix - dvs.runcmd("ip route del 192.168.100.0/24 nexthop via 111.0.0.2") - time.sleep(1) - - # Start zebra - dvs.start_zebra() - - # Verify FSM - swss_app_check_warmstart_state(state_db, "bgp", "restored") - time.sleep(restart_timer + 1) - swss_app_check_warmstart_state(state_db, "bgp", "reconciled") - - # Verify the changed prefix is seen in swss - (addobjs, delobjs) = dvs.GetSubscribedAppDbObjects(pubsubAppDB) - assert len(addobjs) == 0 and len(delobjs) == 1 - rt_key = json.loads(delobjs[0]['key']) - assert rt_key == "192.168.100.0/24" - - # Verify the changed prefix is seen in sairedis - (addobjs, delobjs) = dvs.GetSubscribedAsicDbObjects(pubsubAsicDB) - assert len(addobjs) == 0 and len(delobjs) == 1 - rt_key = json.loads(delobjs[0]['key']) - assert rt_key['dest'] == "192.168.100.0/24" - - - ############################################################################# - # - # Testcase 5. Restart zebra and add a new IPv4 ecmp-prefix - # - ############################################################################# - - - # Stop zebra - dvs.stop_zebra() - - # Add prefix - dvs.runcmd("ip route add 192.168.200.0/24 nexthop via 111.0.0.2 nexthop via 122.0.0.2 nexthop via 133.0.0.2") - time.sleep(1) - - # Start zebra - dvs.start_zebra() - - # Verify FSM - swss_app_check_warmstart_state(state_db, "bgp", "restored") - time.sleep(restart_timer + 1) - swss_app_check_warmstart_state(state_db, "bgp", "reconciled") - - # Verify the changed prefix is seen in swss - (addobjs, delobjs) = dvs.GetSubscribedAppDbObjects(pubsubAppDB) - assert len(addobjs) == 1 and len(delobjs) == 0 - rt_key = json.loads(addobjs[0]['key']) - rt_val = json.loads(addobjs[0]['vals']) - assert rt_key == "192.168.200.0/24" - assert rt_val.get("ifname") == "Ethernet0,Ethernet4,Ethernet8" - assert rt_val.get("nexthop") == "111.0.0.2,122.0.0.2,133.0.0.2" - - # Verify the changed prefix is seen in sairedis - (addobjs, delobjs) = dvs.GetSubscribedAsicDbObjects(pubsubAsicDB) - assert len(addobjs) == 1 and len(delobjs) == 0 - rt_key = json.loads(addobjs[0]['key']) - assert rt_key['dest'] == "192.168.200.0/24" - - - ############################################################################# - # - # Testcase 6. Restart zebra and delete one existing IPv4 ecmp-prefix. - # - ############################################################################# - - - # Stop zebra - dvs.stop_zebra() - - # Delete prefix - dvs.runcmd("ip route del 192.168.200.0/24 nexthop via 111.0.0.2 nexthop via 122.0.0.2 nexthop via 133.0.0.2") - time.sleep(1) - - # Start zebra - dvs.start_zebra() - - # Verify FSM - swss_app_check_warmstart_state(state_db, "bgp", "restored") - time.sleep(restart_timer + 1) - swss_app_check_warmstart_state(state_db, "bgp", "reconciled") - - # Verify the changed prefix is seen in swss - (addobjs, delobjs) = dvs.GetSubscribedAppDbObjects(pubsubAppDB) - assert len(addobjs) == 0 and len(delobjs) == 1 - rt_key = json.loads(delobjs[0]['key']) - assert rt_key == "192.168.200.0/24" - - # Verify the changed prefix is seen in sairedis - (addobjs, delobjs) = dvs.GetSubscribedAsicDbObjects(pubsubAsicDB) - assert len(addobjs) == 0 and len(delobjs) == 1 - rt_key = json.loads(delobjs[0]['key']) - assert rt_key['dest'] == "192.168.200.0/24" - - - ############################################################################# - # - # Testcase 7. Restart zebra and add one new path to an IPv4 ecmp-prefix - # - ############################################################################# - - - # Stop zebra - dvs.stop_zebra() - - # Add new path - dvs.runcmd("ip route del 192.168.1.3/32 nexthop via 111.0.0.2 nexthop via 122.0.0.2") - dvs.runcmd("ip route add 192.168.1.3/32 nexthop via 111.0.0.2 nexthop via 122.0.0.2 nexthop via 133.0.0.2") - time.sleep(1) - - # Start zebra - dvs.start_zebra() - - # Verify FSM - swss_app_check_warmstart_state(state_db, "bgp", "restored") - time.sleep(restart_timer + 1) - swss_app_check_warmstart_state(state_db, "bgp", "reconciled") - - # Verify the changed prefix is seen in swss - (addobjs, delobjs) = dvs.GetSubscribedAppDbObjects(pubsubAppDB) - assert len(addobjs) == 1 and len(delobjs) == 0 - rt_key = json.loads(addobjs[0]['key']) - rt_val = json.loads(addobjs[0]['vals']) - assert rt_key == "192.168.1.3" - assert rt_val.get("ifname") == "Ethernet0,Ethernet4,Ethernet8" - assert rt_val.get("nexthop") == "111.0.0.2,122.0.0.2,133.0.0.2" - - # Verify the changed prefix is seen in sairedis - (addobjs, delobjs) = dvs.GetSubscribedAsicDbObjects(pubsubAsicDB) - assert len(addobjs) == 1 and len(delobjs) == 0 - rt_key = json.loads(addobjs[0]['key']) - assert rt_key['dest'] == "192.168.1.3/32" - - - ############################################################################# - # - # Testcase 8. Restart zebra and delete one ecmp-path from an IPv4 ecmp-prefix. - # - ############################################################################# - - - # Stop zebra - dvs.stop_zebra() - - # Delete ecmp-path - dvs.runcmd("ip route del 192.168.1.3/32 nexthop via 111.0.0.2 nexthop via 122.0.0.2 nexthop via 133.0.0.2") - dvs.runcmd("ip route add 192.168.1.3/32 nexthop via 111.0.0.2 nexthop via 122.0.0.2") - time.sleep(1) - - # Start zebra - dvs.start_zebra() - - # Verify FSM - swss_app_check_warmstart_state(state_db, "bgp", "restored") - time.sleep(restart_timer + 1) - swss_app_check_warmstart_state(state_db, "bgp", "reconciled") - - # Verify the changed prefix is seen in swss - (addobjs, delobjs) = dvs.GetSubscribedAppDbObjects(pubsubAppDB) - assert len(addobjs) == 1 and len(delobjs) == 0 - rt_key = json.loads(addobjs[0]['key']) - rt_val = json.loads(addobjs[0]['vals']) - assert rt_key == "192.168.1.3" - assert rt_val.get("ifname") == "Ethernet0,Ethernet4" - assert rt_val.get("nexthop") == "111.0.0.2,122.0.0.2" - - # Verify the changed prefix is seen in sairedis - (addobjs, delobjs) = dvs.GetSubscribedAsicDbObjects(pubsubAsicDB) - assert len(addobjs) == 1 and len(delobjs) == 0 - rt_key = json.loads(addobjs[0]['key']) - assert rt_key['dest'] == "192.168.1.3/32" - - - ############################################################################# - # - # Testcase 9. Restart zebra and add one new non-ecmp IPv6 prefix - # - ############################################################################# - - - # Stop zebra - dvs.stop_zebra() - - # Add prefix - dvs.runcmd("ip -6 route add fc00:4:4::1/128 nexthop via 1110::2") - time.sleep(1) - - # Start zebra - dvs.start_zebra() - - # Verify FSM - swss_app_check_warmstart_state(state_db, "bgp", "restored") - time.sleep(restart_timer + 1) - swss_app_check_warmstart_state(state_db, "bgp", "reconciled") - - # Verify the changed prefix is seen in swss - (addobjs, delobjs) = dvs.GetSubscribedAppDbObjects(pubsubAppDB) - assert len(addobjs) == 1 and len(delobjs) == 0 - rt_key = json.loads(addobjs[0]['key']) - rt_val = json.loads(addobjs[0]['vals']) - assert rt_key == "fc00:4:4::1" - assert rt_val.get("ifname") == "Ethernet0" - assert rt_val.get("nexthop") == "1110::2" - - # Verify the changed prefix is seen in sairedis - (addobjs, delobjs) = dvs.GetSubscribedAsicDbObjects(pubsubAsicDB) - assert len(addobjs) == 1 and len(delobjs) == 0 - rt_key = json.loads(addobjs[0]['key']) - assert rt_key['dest'] == "fc00:4:4::1/128" - - - ############################################################################# - # - # Testcase 10. Restart zebra and withdraw one non-ecmp IPv6 prefix - # - ############################################################################# - - # Stop zebra - dvs.stop_zebra() - - # Delete prefix - dvs.runcmd("ip -6 route del fc00:4:4::1/128 nexthop via 1110::2") - time.sleep(1) - - # Start zebra - dvs.start_zebra() - - # Verify FSM - swss_app_check_warmstart_state(state_db, "bgp", "restored") - time.sleep(restart_timer + 1) - swss_app_check_warmstart_state(state_db, "bgp", "reconciled") - - # Verify the changed prefix is seen in swss - (addobjs, delobjs) = dvs.GetSubscribedAppDbObjects(pubsubAppDB) - assert len(addobjs) == 0 and len(delobjs) == 1 - rt_key = json.loads(delobjs[0]['key']) - assert rt_key == "fc00:4:4::1" - - # Verify the changed prefix is seen in sairedis - (addobjs, delobjs) = dvs.GetSubscribedAsicDbObjects(pubsubAsicDB) - assert len(addobjs) == 0 and len(delobjs) == 1 - rt_key = json.loads(delobjs[0]['key']) - assert rt_key['dest'] == "fc00:4:4::1/128" - - - ############################################################################# - # - # Testcase 11. Restart fpmsyncd and make no control-plane changes. - # - ############################################################################# - - - # Stop fpmsyncd - dvs.stop_fpmsyncd() - - # Start fpmsyncd - dvs.start_fpmsyncd() - - # Verify FSM - swss_app_check_warmstart_state(state_db, "bgp", "restored") - time.sleep(restart_timer + 1) - swss_app_check_warmstart_state(state_db, "bgp", "reconciled") - - # Verify swss changes -- none are expected this time - (addobjs, delobjs) = dvs.GetSubscribedAppDbObjects(pubsubAppDB) - assert len(addobjs) == 0 and len(delobjs) == 0 - - # Verify sairedis changes -- none are expected this time - (addobjs, delobjs) = dvs.GetSubscribedAsicDbObjects(pubsubAsicDB) - assert len(addobjs) == 0 and len(delobjs) == 0 - - - ############################################################################# - # - # Testcase 12. Restart fpmsyncd and add one new non-ecmp IPv4 prefix - # - ############################################################################# - - - # Stop fpmsyncd - dvs.stop_fpmsyncd() - - # Add new prefix - dvs.runcmd("ip route add 192.168.100.0/24 nexthop via 111.0.0.2") - time.sleep(1) - - # Start fpmsyncd - dvs.start_fpmsyncd() - - # Verify FSM - swss_app_check_warmstart_state(state_db, "bgp", "restored") - time.sleep(restart_timer + 1) - swss_app_check_warmstart_state(state_db, "bgp", "reconciled") - - # Verify the changed prefix is seen in swss - (addobjs, delobjs) = dvs.GetSubscribedAppDbObjects(pubsubAppDB) - assert len(addobjs) == 1 and len(delobjs) == 0 - rt_key = json.loads(addobjs[0]['key']) - rt_val = json.loads(addobjs[0]['vals']) - assert rt_key == "192.168.100.0/24" - assert rt_val.get("ifname") == "Ethernet0" - assert rt_val.get("nexthop") == "111.0.0.2" - - # Verify the changed prefix is seen in sairedis - (addobjs, delobjs) = dvs.GetSubscribedAsicDbObjects(pubsubAsicDB) - assert len(addobjs) == 1 and len(delobjs) == 0 - rt_key = json.loads(addobjs[0]['key']) - assert rt_key['dest'] == "192.168.100.0/24" - - - ############################################################################# - # - # Testcase 13. Restart fpmsyncd and withdraw one non-ecmp IPv4 prefix - # - ############################################################################# - - - # Stop fpmsyncd - dvs.stop_fpmsyncd() - - # Delete prefix - dvs.runcmd("ip route del 192.168.100.0/24 nexthop via 111.0.0.2") - time.sleep(1) - - # Start fpmsyncd - dvs.start_fpmsyncd() - - # Verify FSM - swss_app_check_warmstart_state(state_db, "bgp", "restored") - time.sleep(restart_timer + 1) - swss_app_check_warmstart_state(state_db, "bgp", "reconciled") - - # Verify the changed prefix is seen in swss - (addobjs, delobjs) = dvs.GetSubscribedAppDbObjects(pubsubAppDB) - assert len(addobjs) == 0 and len(delobjs) == 1 - rt_key = json.loads(delobjs[0]['key']) - assert rt_key == "192.168.100.0/24" - - # Verify the changed prefix is seen in sairedis - (addobjs, delobjs) = dvs.GetSubscribedAsicDbObjects(pubsubAsicDB) - assert len(addobjs) == 0 and len(delobjs) == 1 - rt_key = json.loads(delobjs[0]['key']) - assert rt_key['dest'] == "192.168.100.0/24" - - - ############################################################################# - # - # Testcase 14. Restart zebra and add/remove a new non-ecmp IPv4 prefix. As - # the 'delete' instruction would arrive after the 'add' one, no - # changes should be pushed down to SwSS. - # - ############################################################################# - - - # Restart zebra - dvs.stop_zebra() - dvs.start_zebra() - - # Add/delete new prefix - dvs.runcmd("ip route add 192.168.100.0/24 nexthop via 111.0.0.2") - time.sleep(1) - dvs.runcmd("ip route del 192.168.100.0/24 nexthop via 111.0.0.2") - time.sleep(1) - - # Verify FSM - swss_app_check_warmstart_state(state_db, "bgp", "restored") - time.sleep(restart_timer + 1) - swss_app_check_warmstart_state(state_db, "bgp", "reconciled") - - # Verify swss changes -- none are expected this time - (addobjs, delobjs) = dvs.GetSubscribedAppDbObjects(pubsubAppDB) - assert len(addobjs) == 0 and len(delobjs) == 0 - - # Verify swss changes -- none are expected this time - (addobjs, delobjs) = dvs.GetSubscribedAsicDbObjects(pubsubAsicDB) - assert len(addobjs) == 0 and len(delobjs) == 0 - - - ############################################################################# - # - # Testcase 15. Restart zebra and generate an add/remove/add for new non-ecmp - # IPv4 prefix. Verify that only the second 'add' instruction is - # honored and the corresponding update passed down to SwSS. - # - ############################################################################# - - - # Restart zebra - dvs.stop_zebra() - dvs.start_zebra() - - marker1 = dvs.add_log_marker("/var/log/swss/swss.rec") - marker2 = dvs.add_log_marker("/var/log/swss/sairedis.rec") - - # Add/delete new prefix - dvs.runcmd("ip route add 192.168.100.0/24 nexthop via 111.0.0.2") - time.sleep(1) - dvs.runcmd("ip route del 192.168.100.0/24 nexthop via 111.0.0.2") - time.sleep(1) - dvs.runcmd("ip route add 192.168.100.0/24 nexthop via 122.0.0.2") - time.sleep(1) - - # Verify FSM - swss_app_check_warmstart_state(state_db, "bgp", "restored") - time.sleep(restart_timer + 1) - swss_app_check_warmstart_state(state_db, "bgp", "reconciled") - - # Verify the changed prefix is seen in swss - (addobjs, delobjs) = dvs.GetSubscribedAppDbObjects(pubsubAppDB) - assert len(addobjs) == 1 and len(delobjs) == 0 - rt_key = json.loads(addobjs[0]['key']) - rt_val = json.loads(addobjs[0]['vals']) - assert rt_key == "192.168.100.0/24" - assert rt_val.get("ifname") == "Ethernet4" - assert rt_val.get("nexthop") == "122.0.0.2" - - # Verify the changed prefix is seen in sairedis - (addobjs, delobjs) = dvs.GetSubscribedAsicDbObjects(pubsubAsicDB) - assert len(addobjs) == 1 and len(delobjs) == 0 - rt_key = json.loads(addobjs[0]['key']) - assert rt_key['dest'] == "192.168.100.0/24" - - - ############################################################################# - # - # Testcase 16. Restart zebra and make no control-plane changes. - # Set WARM_RESTART_TABLE|IPv4|eoiu - # WARM_RESTART_TABLE|IPv6|eoiu - # Check route reconciliation wait time is reduced - # For this and all subsequent test-cases routing-warm-reboot - # feature will be kept enabled. - # - ############################################################################# - - - time.sleep(1) - # Hold time from EOIU detected for both Ipv4/Ipv6 to start route reconciliation - DEFAULT_EOIU_HOLD_INTERVAL = 3 - - # change to 20 for easy timeline check - restart_timer = 20 - - # clean up as that in bgp_eoiu_marker.py - del_entry_tbl(state_db, "BGP_STATE_TABLE", "IPv4|eoiu") - del_entry_tbl(state_db, "BGP_STATE_TABLE", "IPv6|eoiu") - - warm_restart_timer_set(dvs, "bgp", "bgp_timer", str(restart_timer)) - # Restart zebra - dvs.stop_zebra() - dvs.start_zebra() - - # - # Verify FSM: no eoiu, just default warm restart timer - # - swss_app_check_warmstart_state(state_db, "bgp", "restored") - # Periodic eoiu check timer, first wait 5 seconds, then check every 1 second - # DEFAULT_EOIU_HOLD_INTERVAL is 3 seconds. - # Since no EOIU set, after 3+ 5 + 1 seconds, the state still in restored state - time.sleep(DEFAULT_EOIU_HOLD_INTERVAL + 5 +1) - swss_app_check_warmstart_state(state_db, "bgp", "restored") - # default restart timer kicks in: - time.sleep(restart_timer - DEFAULT_EOIU_HOLD_INTERVAL -5) - swss_app_check_warmstart_state(state_db, "bgp", "reconciled") - - - time.sleep(1) - # Restart zebra - dvs.stop_zebra() - dvs.start_zebra() - - # - # Verify FSM: eoiu works as expected - # - swss_app_check_warmstart_state(state_db, "bgp", "restored") - # Set BGP_STATE_TABLE|Ipv4|eoiu BGP_STATE_TABLE|IPv6|eoiu - create_entry_tbl( - state_db, - "BGP_STATE_TABLE", "IPv4|eoiu", - [ - ("state", "reached"), - ("timestamp", "2019-04-25 09:39:19"), - ] - ) - create_entry_tbl( - state_db, - "BGP_STATE_TABLE", "IPv6|eoiu", - [ - ("state", "reached"), - ("timestamp", "2019-04-25 09:39:22"), - ] - ) - - # after DEFAULT_EOIU_HOLD_INTERVAL + inital eoiu check timer wait time + 1 seconds: 3+5+1 - # verify that bgp reached reconciled state - time.sleep(DEFAULT_EOIU_HOLD_INTERVAL + 5 + 1) - swss_app_check_warmstart_state(state_db, "bgp", "reconciled") - - # Verify swss changes -- none are expected this time - (addobjs, delobjs) = dvs.GetSubscribedAppDbObjects(pubsubAppDB) - assert len(addobjs) == 0 and len(delobjs) == 0 - # Verify swss changes -- none are expected this time - (addobjs, delobjs) = dvs.GetSubscribedAsicDbObjects(pubsubAsicDB) - assert len(addobjs) == 0 and len(delobjs) == 0 - - - del_entry_tbl(state_db, "BGP_STATE_TABLE", "IPv4|eoiu") - del_entry_tbl(state_db, "BGP_STATE_TABLE", "IPv6|eoiu") - time.sleep(1) - # Restart zebra - dvs.stop_zebra() - dvs.start_zebra() - - # - # Verify FSM: partial eoiu, fallback to default warm restart timer - # - swss_app_check_warmstart_state(state_db, "bgp", "restored") - # Set BGP_STATE_TABLE|Ipv4|eoiu but not BGP_STATE_TABLE|IPv6|eoiu - create_entry_tbl( - state_db, - "BGP_STATE_TABLE", "IPv4|eoiu", - [ - ("state", "reached"), - ("timestamp", "2019-04-25 09:39:19"), - ] - ) - - # Periodic eoiu check timer, first wait 5 seconds, then check every 1 second - # DEFAULT_EOIU_HOLD_INTERVAL is 3 seconds. - # Current bgp eoiu needs flag set on both Ipv4/Ipv6 to work, after 3+ 5 + 1 seconds, the state still in restored state - time.sleep(DEFAULT_EOIU_HOLD_INTERVAL + 5 +1) - swss_app_check_warmstart_state(state_db, "bgp", "restored") - # Fall back to warm restart timer, it kicks in after 15 seconds, +1 to avoid race condition: - time.sleep(restart_timer - DEFAULT_EOIU_HOLD_INTERVAL -5 ) - swss_app_check_warmstart_state(state_db, "bgp", "reconciled") - - # Verify swss changes -- none are expected this time - (addobjs, delobjs) = dvs.GetSubscribedAppDbObjects(pubsubAppDB) - assert len(addobjs) == 0 and len(delobjs) == 0 - - # Verify swss changes -- none are expected this time - (addobjs, delobjs) = dvs.GetSubscribedAsicDbObjects(pubsubAsicDB) - assert len(addobjs) == 0 and len(delobjs) == 0 - - # - # Remove route entries so they don't interfere with later tests - # - dvs.runcmd("ip route del 192.168.1.100/32") - dvs.runcmd("ip route del 192.168.1.200/32") - dvs.runcmd("ip route del 192.168.1.230/32") - dvs.runcmd("ip route del 192.168.1.1/32") - dvs.runcmd("ip route del 192.168.1.2/32") - dvs.runcmd("ip route del 192.168.1.3/32") - dvs.runcmd("ip route del 192.168.100.0/24") - dvs.runcmd("ip -6 route del fc00:11:11::1/128") - dvs.runcmd("ip -6 route del fc00:12:12::1/128") - dvs.runcmd("ip -6 route del fc00:13:13::1/128") - dvs.runcmd("ip -6 route del fc00:1:1::1/128") - dvs.runcmd("ip -6 route del fc00:2:2::1/128") - dvs.runcmd("ip -6 route del fc00:3:3::1/128") - time.sleep(5) - - intf_tbl._del("{}|111.0.0.1/24".format(intfs[0])) - intf_tbl._del("{}|1110::1/64".format(intfs[0])) - intf_tbl._del("{}|122.0.0.1/24".format(intfs[1])) - intf_tbl._del("{}|1220::1/64".format(intfs[1])) - intf_tbl._del("{}|133.0.0.1/24".format(intfs[2])) - intf_tbl._del("{}|1330::1/64".format(intfs[2])) - intf_tbl._del("{}".format(intfs[0])) - intf_tbl._del("{}".format(intfs[0])) - intf_tbl._del("{}".format(intfs[1])) - intf_tbl._del("{}".format(intfs[1])) - intf_tbl._del("{}".format(intfs[2])) - intf_tbl._del("{}".format(intfs[2])) - time.sleep(2) - - @pytest.mark.xfail(reason="Test unstable, blocking PR builds") - def test_system_warmreboot_neighbor_syncup(self, dvs, testlog): - - appl_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - conf_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - state_db = swsscommon.DBConnector(swsscommon.STATE_DB, dvs.redis_sock, 0) - - #enable ipv6 on docker - dvs.runcmd("sysctl net.ipv6.conf.all.disable_ipv6=0") - - # flush all neighs first - flush_neigh_entries(dvs) - time.sleep(5) - - warm_restart_set(dvs, "system", "true") - - # Test neighbors on NUM_INTF (e,g 8) interfaces - # Ethernet32/36/.../60, with ip: 32.0.0.1/24... 60.0.0.1/24 - # ipv6: 3200::1/64...6000::1/64 - # bring up the servers'interfaces and assign NUM_NEIGH_PER_INTF (e,g 128) ips per interface - macs = [] - intf_tbl = swsscommon.Table(conf_db, "INTERFACE") - fvs = swsscommon.FieldValuePairs([("NULL","NULL")]) - for i in range(8, 8+NUM_INTF): - # set timeout to be the same as real HW - # set stale timer bigger to avoid testbed difference related timing issues. - # set ip on server facing interfaces - # bring servers' interface up, save the macs - dvs.runcmd("sysctl -w net.ipv4.neigh.Ethernet{}.base_reachable_time_ms=1800000".format(i*4)) - dvs.runcmd("sysctl -w net.ipv6.neigh.Ethernet{}.base_reachable_time_ms=1800000".format(i*4)) - dvs.runcmd("sysctl -w net.ipv4.neigh.Ethernet{}.gc_stale_time=600".format(i*4)) - dvs.runcmd("sysctl -w net.ipv6.neigh.Ethernet{}.gc_stale_time=600".format(i*4)) - dvs.runcmd("ip addr flush dev Ethernet{}".format(i*4)) - intf_tbl.set("Ethernet{}|{}.0.0.1/24".format(i*4, i*4), fvs) - intf_tbl.set("Ethernet{}|{}00::1/64".format(i*4, i*4), fvs) - intf_tbl.set("Ethernet{}".format(i*4, i*4), fvs) - intf_tbl.set("Ethernet{}".format(i*4, i*4), fvs) - dvs.port_admin_set("Ethernet{}".format(i*4), "up") - dvs.servers[i].runcmd("ip link set up dev eth0") - dvs.servers[i].runcmd("ip addr flush dev eth0") - #result = dvs.servers[i].runcmd_output("ifconfig eth0 | grep HWaddr | awk '{print $NF}'") - result = dvs.servers[i].runcmd_output("cat /sys/class/net/eth0/address") - macs.append(result.strip()) - - # - # Testcase 1: - # Setup initial neigbors - setup_initial_neighbors(dvs) - - # Check the neighbor entries are inserted correctly - db = swsscommon.DBConnector(0, dvs.redis_sock, 0) - tbl = swsscommon.Table(db, "NEIGH_TABLE") - - # number of neighbors should match what we configured - # ipv4/ipv6 entries and loopback - check_redis_neigh_entries(dvs, tbl, 2*NUM_OF_NEIGHS) - - # All neighbor entries should match - for i in range(8, 8+NUM_INTF): - for j in range(NUM_NEIGH_PER_INTF): - (status, fvs) = tbl.get("Ethernet{}:{}.0.0.{}".format(i*4, i*4, j+2)) - assert status == True - for v in fvs: - if v[0] == "family": - assert v[1] == "IPv4" - if v[0] == "neigh": - assert v[1] == macs[i-8] - - (status, fvs) = tbl.get("Ethernet{}:{}00::{}".format(i*4, i*4, j+2)) - assert status == True - for v in fvs: - if v[0] == "family": - assert v[1] == "IPv6" - if v[0] == "neigh": - assert v[1] == macs[i-8] - - # - # Testcase 2: - # Stop neighsyncd, appDB entries should be reserved - # flush kernel neigh table to simulate warm reboot - # start neighsyncd, start restore_neighbors service to restore the neighbor table in kernel - # check all neighbors learned in kernel - # no changes should be there in syslog and sairedis.rec - - # get restore_count - restore_count = swss_get_RestoreCount(dvs, state_db) - - # stop neighsyncd and sairedis.rec - stop_neighsyncd(dvs) - del_entry_tbl(state_db, "NEIGH_RESTORE_TABLE", "Flags") - time.sleep(3) - flush_neigh_entries(dvs) - time.sleep(3) - - # check neighbors are gone - check_kernel_reachable_neigh_num(dvs, 0) - - # start neighsyncd and restore_neighbors - marker = dvs.add_log_marker() - pubsub = dvs.SubscribeAsicDbObject("SAI_OBJECT_TYPE_NEIGHBOR_ENTRY") - start_neighsyncd(dvs) - start_restore_neighbors(dvs) - - # should finish the store within 10 seconds - time.sleep(10) - - check_kernel_reachable_v4_neigh_num(dvs, NUM_OF_NEIGHS) - check_kernel_reachable_v6_neigh_num(dvs, NUM_OF_NEIGHS) - - # check syslog and sairedis.rec file for activities - check_syslog_for_neighbor_entry(dvs, marker, 0, 0, "ipv4") - check_syslog_for_neighbor_entry(dvs, marker, 0, 0, "ipv6") - (nadd, ndel) = dvs.CountSubscribedObjects(pubsub) - assert nadd == 0 - assert ndel == 0 - - # check restore Count - swss_app_check_RestoreCount_single(state_db, restore_count, "neighsyncd") - - # - # Testcase 3: - # Stop neighsyncd, appDB entries should be reserved - # flush kernel neigh table to simulate warm reboot - # Remove half of ips of servers' interfaces, add new half of ips - # start neighsyncd, start restore_neighbors service to restore the neighbor table in kernel - # check all new neighbors learned in kernel - # no changes should be there in syslog and sairedis.rec - - # get restore_count - restore_count = swss_get_RestoreCount(dvs, state_db) - - # stop neighsyncd and sairedis.rec - stop_neighsyncd(dvs) - del_entry_tbl(state_db, "NEIGH_RESTORE_TABLE", "Flags") - time.sleep(3) - - del_and_add_neighbors(dvs) - - flush_neigh_entries(dvs) - time.sleep(3) - - # check neighbors are gone - check_kernel_reachable_neigh_num(dvs, 0) - - # start neighsyncd and restore_neighbors - marker = dvs.add_log_marker() - start_neighsyncd(dvs) - start_restore_neighbors(dvs) - - # should finish the store within 10 seconds - time.sleep(10) - - check_kernel_reachable_v4_neigh_num(dvs, NUM_OF_NEIGHS//2) - check_kernel_reachable_v6_neigh_num(dvs, NUM_OF_NEIGHS//2) - - check_kernel_stale_v4_neigh_num(dvs, NUM_OF_NEIGHS//2) - check_kernel_stale_v6_neigh_num(dvs, NUM_OF_NEIGHS//2) - - # check syslog and sairedis.rec file for activities - check_syslog_for_neighbor_entry(dvs, marker, 0, 0, "ipv4") - check_syslog_for_neighbor_entry(dvs, marker, 0, 0, "ipv6") - (nadd, ndel) = dvs.CountSubscribedObjects(pubsub) - assert nadd == 0 - assert ndel == 0 - - # check restore Count - swss_app_check_RestoreCount_single(state_db, restore_count, "neighsyncd") - - # Test case 4: - # ping the new ips, should get it into appDB - marker = dvs.add_log_marker() - - ping_new_ips(dvs) - - check_kernel_reachable_v4_neigh_num(dvs, NUM_OF_NEIGHS) - check_kernel_reachable_v6_neigh_num(dvs, NUM_OF_NEIGHS) - - check_redis_neigh_entries(dvs, tbl, 2*(NUM_OF_NEIGHS+NUM_OF_NEIGHS//2)) - - (nadd, ndel) = dvs.CountSubscribedObjects(pubsub) - assert nadd == NUM_OF_NEIGHS #ipv4 and ipv6 - assert ndel == 0 - - # Remove stale entries manually - for i in range(8, 8+NUM_INTF): - for j in range(NUM_NEIGH_PER_INTF//2): - dvs.runcmd(['sh', '-c', "ip neigh del {}.0.0.{} dev Ethernet{}".format(i*4, j+NUM_NEIGH_PER_INTF//2+2, i*4)]) - dvs.runcmd(['sh', '-c', "ip -6 neigh del {}00::{} dev Ethernet{}".format(i*4, j+NUM_NEIGH_PER_INTF//2+2, i*4)]) - - time.sleep(5) - - check_kernel_reachable_v4_neigh_num(dvs, NUM_OF_NEIGHS) - check_kernel_reachable_v6_neigh_num(dvs, NUM_OF_NEIGHS) - - check_kernel_stale_v4_neigh_num(dvs, 0) - check_kernel_stale_v6_neigh_num(dvs, 0) - - check_redis_neigh_entries(dvs, tbl, 2*NUM_OF_NEIGHS) - - (nadd, ndel) = dvs.CountSubscribedObjects(pubsub) - assert nadd == 0 - assert ndel == NUM_OF_NEIGHS #ipv4 and ipv6 - - # - # Testcase 5: - # Stop neighsyncd, appDB entries should be reserved - # flush kernel neigh table to simulate warm reboot - # keep half of the interface down - # start neighsyncd, start restore_neighbors service to restore the neighbor table in kernel - # check all new neighbors with interface up to be learned in kernel - # syslog/sai log should show half of the entries stale/deleted - - # get restore_count - restore_count = swss_get_RestoreCount(dvs, state_db) - - # stop neighsyncd and sairedis.rec - stop_neighsyncd(dvs) - del_entry_tbl(state_db, "NEIGH_RESTORE_TABLE", "Flags") - time.sleep(3) - - flush_neigh_entries(dvs) - time.sleep(3) - - # check neighbors are gone - check_kernel_reachable_neigh_num(dvs, 0) - - # bring down half of the links - for i in range(8, 8+NUM_INTF//2): - dvs.runcmd("ip link set down dev Ethernet{}".format(i*4)) - - # start neighsyncd and restore_neighbors - start_neighsyncd(dvs) - start_restore_neighbors(dvs) - - # restore for up interfaces should be done within 10 seconds - time.sleep(10) - - check_kernel_reachable_v4_neigh_num(dvs, NUM_OF_NEIGHS//2) - check_kernel_reachable_v6_neigh_num(dvs, NUM_OF_NEIGHS//2) - - restoretbl = swsscommon.Table(state_db, swsscommon.STATE_NEIGH_RESTORE_TABLE_NAME) - - # waited 10 above already - i = 10 - while (not kernel_restore_neighs_done(restoretbl)): - print("Waiting for kernel neighbors restore process done: {} seconds".format(i)) - time.sleep(10) - i += 10 - - time.sleep(10) - - - # check syslog and sairedis.rec file for activities - #check_syslog_for_neighbor_entry(dvs, marker, 0, NUM_OF_NEIGHS//2, "ipv4") - #check_syslog_for_neighbor_entry(dvs, marker, 0, NUM_OF_NEIGHS//2, "ipv6") - (nadd, ndel) = dvs.CountSubscribedObjects(pubsub) - assert nadd == 0 - assert ndel == NUM_OF_NEIGHS - - # check restore Count - swss_app_check_RestoreCount_single(state_db, restore_count, "neighsyncd") - - # disable system warm restart - warm_restart_set(dvs, "system", "false") - - for i in range(8, 8+NUM_INTF): - intf_tbl._del("Ethernet{}|{}.0.0.1/24".format(i*4, i*4)) - intf_tbl._del("Ethernet{}|{}00::1/64".format(i*4, i*4)) - intf_tbl._del("Ethernet{}".format(i*4, i*4)) - intf_tbl._del("Ethernet{}".format(i*4, i*4)) - - def test_VrfMgrdWarmRestart(self, dvs, testlog): - - conf_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - appl_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - state_db = swsscommon.DBConnector(swsscommon.STATE_DB, dvs.redis_sock, 0) - - dvs.warm_restart_swss("true") - - # bring up interface - dvs.port_admin_set("Ethernet0", "up") - dvs.port_admin_set("Ethernet4", "up") - - # create vrf - create_entry_tbl(conf_db, "VRF", "Vrf_1", [('empty', 'empty')]) - create_entry_tbl(conf_db, "VRF", "Vrf_2", [('empty', 'empty')]) - - intf_tbl = swsscommon.Table(conf_db, "INTERFACE") - fvs = swsscommon.FieldValuePairs([("vrf_name", "Vrf_1")]) - intf_tbl.set("Ethernet0", fvs) - intf_tbl.set("Ethernet4", fvs) - fvs = swsscommon.FieldValuePairs([("NULL", "NULL")]) - intf_tbl.set("Ethernet0|12.0.0.1/24", fvs) - intf_tbl.set("Ethernet4|13.0.0.1/24", fvs) - - time.sleep(1) - - dvs.servers[0].runcmd("ifconfig eth0 12.0.0.2/24") - dvs.servers[0].runcmd("ip route add default via 12.0.0.1") - - dvs.servers[1].runcmd("ifconfig eth0 13.0.0.2/24") - dvs.servers[1].runcmd("ip route add default via 13.0.0.1") - - time.sleep(1) - - # Ping should work between servers via vs port interfaces - ping_stats = dvs.servers[0].runcmd("ping -c 1 13.0.0.2") - assert ping_stats == 0 - time.sleep(1) - - tbl = swsscommon.Table(appl_db, "NEIGH_TABLE") - (status, fvs) = tbl.get("Ethernet0:12.0.0.2") - assert status == True - - (status, fvs) = tbl.get("Ethernet4:13.0.0.2") - assert status == True - - (exitcode, vrf_before) = dvs.runcmd(['sh', '-c', "ip link show | grep Vrf"]) - - dvs.runcmd(['sh', '-c', 'pkill -x vrfmgrd']) - time.sleep(1) - - pubsub = dvs.SubscribeAsicDbObject("SAI_OBJECT_TYPE") - - dvs.runcmd(['sh', '-c', 'supervisorctl start vrfmgrd']) - time.sleep(2) - - # kernel vrf config should be kept the same - (exitcode, vrf_after) = dvs.runcmd(['sh', '-c', "ip link show | grep Vrf"]) - assert vrf_after == vrf_before - - # VIRTUAL_ROUTER/ROUTE_ENTRY/NEIGH_ENTRY should be kept the same - (nadd, ndel) = dvs.CountSubscribedObjects(pubsub, ignore=["SAI_OBJECT_TYPE_FDB_ENTRY"]) - assert nadd == 0 - assert ndel == 0 - - # new ip on server 1 - dvs.servers[1].runcmd("ifconfig eth0 13.0.0.3/24") - dvs.servers[1].runcmd("ip route add default via 13.0.0.1") - - # Ping should work between servers via vs port interfaces - ping_stats = dvs.servers[0].runcmd("ping -c 1 13.0.0.3") - assert ping_stats == 0 - - # new neighbor learn on vs - (status, fvs) = tbl.get("Ethernet4:13.0.0.3") - assert status == True - - # flush all neigh entries - dvs.runcmd("ip link set group default arp off") - dvs.runcmd("ip link set group default arp on") - - # remove interface Ethernet4 from vrf_1, add it to vrf_2 - intf_tbl._del("Ethernet4|13.0.0.1/24") - intf_tbl._del("Ethernet4") - time.sleep(1) - - intf_tbl = swsscommon.Table(conf_db, "INTERFACE") - fvs = swsscommon.FieldValuePairs([("vrf_name", "Vrf_2")]) - intf_tbl.set("Ethernet4", fvs) - fvs = swsscommon.FieldValuePairs([("NULL", "NULL")]) - intf_tbl.set("Ethernet4|13.0.0.1/24", fvs) - time.sleep(1) - - # Ping should not work - ping_stats = dvs.servers[0].runcmd("ping -c 1 13.0.0.3") - assert ping_stats != 0 - - # remove interface Ethernet0 from vrf_1, add it to vrf_2 - intf_tbl._del("Ethernet0|12.0.0.1/24") - intf_tbl._del("Ethernet0") - time.sleep(1) - fvs = swsscommon.FieldValuePairs([("vrf_name", "Vrf_2")]) - intf_tbl.set("Ethernet0", fvs) - fvs = swsscommon.FieldValuePairs([("NULL", "NULL")]) - intf_tbl.set("Ethernet0|12.0.0.1/24", fvs) - time.sleep(1) - - # Ping should work between servers via vs port interfaces - ping_stats = dvs.servers[0].runcmd("ping -c 1 13.0.0.3") - assert ping_stats == 0 - - (status, fvs) = tbl.get("Ethernet4:13.0.0.3") - assert status == True - - intf_tbl._del("Ethernet0|12.0.0.1/24") - intf_tbl._del("Ethernet4|13.0.0.1/24") - intf_tbl._del("Ethernet0") - intf_tbl._del("Ethernet4") - del_entry_tbl(conf_db, "VRF", "Vrf_1") - del_entry_tbl(conf_db, "VRF", "Vrf_2") - dvs.servers[0].runcmd("ifconfig eth0 0") - dvs.servers[1].runcmd("ifconfig eth0 0") - time.sleep(2) - - @pytest.fixture(scope="class") - def setup_erspan_neighbors(self, dvs): - dvs.setup_db() - - dvs.set_interface_status("Ethernet12", "up") - dvs.set_interface_status("Ethernet16", "up") - dvs.set_interface_status("Ethernet20", "up") - - dvs.add_ip_address("Ethernet12", "10.0.0.0/31") - dvs.add_ip_address("Ethernet16", "11.0.0.0/31") - dvs.add_ip_address("Ethernet20", "12.0.0.0/31") - - dvs.add_neighbor("Ethernet12", "10.0.0.1", "02:04:06:08:10:12") - dvs.add_neighbor("Ethernet16", "11.0.0.1", "03:04:06:08:10:12") - dvs.add_neighbor("Ethernet20", "12.0.0.1", "04:04:06:08:10:12") - - dvs.add_route("2.2.2.2", "10.0.0.1") - - yield - - dvs.remove_route("2.2.2.2") - - dvs.remove_neighbor("Ethernet12", "10.0.0.1") - dvs.remove_neighbor("Ethernet16", "11.0.0.1") - dvs.remove_neighbor("Ethernet20", "12.0.0.1") - - dvs.remove_ip_address("Ethernet12", "10.0.0.0/31") - dvs.remove_ip_address("Ethernet16", "11.0.0.0/31") - dvs.remove_ip_address("Ethernet20", "12.0.0.1/31") - - dvs.set_interface_status("Ethernet12", "down") - dvs.set_interface_status("Ethernet16", "down") - dvs.set_interface_status("Ethernet20", "down") - - @pytest.mark.usefixtures("dvs_mirror_manager", "setup_erspan_neighbors") - def test_MirrorSessionWarmReboot(self, dvs): - dvs.setup_db() - - # Setup the mirror session - self.dvs_mirror.create_erspan_session("test_session", "1.1.1.1", "2.2.2.2", "0x6558", "8", "100", "0") - - # Verify the monitor port - state_db = dvs.get_state_db() - state_db.wait_for_field_match("MIRROR_SESSION_TABLE", "test_session", {"monitor_port": "Ethernet12"}) - - # Setup ECMP routes to the session destination - dvs.change_route_ecmp("2.2.2.2", ["12.0.0.1", "11.0.0.1", "10.0.0.1"]) - - # Monitor port should not change b/c routes are ECMP - state_db.wait_for_field_match("MIRROR_SESSION_TABLE", "test_session", {"monitor_port": "Ethernet12"}) - - dvs.warm_restart_swss("true") - dvs.stop_swss() - dvs.start_swss() - - dvs.check_swss_ready() - - # Monitor port should not change b/c destination is frozen - state_db.wait_for_field_match("MIRROR_SESSION_TABLE", "test_session", {"monitor_port": "Ethernet12"}) - - self.dvs_mirror.remove_mirror_session("test_session") - - # Revert the route back to the fixture-defined route - dvs.change_route("2.2.2.2", "10.0.0.1") - - # Reset for test cases after this one - dvs.stop_swss() - dvs.start_swss() - dvs.check_swss_ready() - - @pytest.mark.usefixtures("dvs_mirror_manager", "dvs_policer_manager", "setup_erspan_neighbors") - def test_EverflowWarmReboot(self, dvs, dvs_acl): - # Setup the policer - self.dvs_policer.create_policer("test_policer") - self.dvs_policer.verify_policer("test_policer") - - # Setup the mirror session - self.dvs_mirror.create_erspan_session("test_session", "1.1.1.1", "2.2.2.2", "0x6558", "8", "100", "0", policer="test_policer") - - state_db = dvs.get_state_db() - state_db.wait_for_field_match("MIRROR_SESSION_TABLE", "test_session", {"status": "active"}) - - # Create the mirror table - dvs_acl.create_acl_table("EVERFLOW_TEST", "MIRROR", ["Ethernet12"]) - - - # TODO: The standard methods for counting ACL tables and ACL rules break down after warm reboot b/c the OIDs - # of the default tables change. We also can't just re-initialize the default value b/c we've added another - # table and rule that aren't part of the base device config. We should come up with a way to handle warm reboot - # changes more gracefully to make it easier for future tests. - asic_db = dvs.get_asic_db() - asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE", 1 + len(asic_db.default_acl_tables)) - - # Create a mirror rule - dvs_acl.create_mirror_acl_rule("EVERFLOW_TEST", "TEST_RULE", {"SRC_IP": "20.0.0.2"}, "test_session") - asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY", 1 + len(asic_db.default_acl_entries)) - - # Execute the warm reboot - dvs.warm_restart_swss("true") - dvs.stop_swss() - dvs.start_swss() - - # Make sure the system is stable - dvs.check_swss_ready() - - # Verify that the ASIC DB is intact - self.dvs_policer.verify_policer("test_policer") - state_db.wait_for_field_match("MIRROR_SESSION_TABLE", "test_session", {"status": "active"}) - - asic_db = dvs.get_asic_db() - asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE", 1 + len(asic_db.default_acl_tables)) - asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY", 1 + len(asic_db.default_acl_entries)) - - # Clean up - dvs_acl.remove_acl_rule("EVERFLOW_TEST", "TEST_RULE") - asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY", len(asic_db.default_acl_entries)) - - dvs_acl.remove_acl_table("EVERFLOW_TEST") - asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE", len(asic_db.default_acl_tables)) - - self.dvs_mirror.remove_mirror_session("test_session") - self.dvs_mirror.verify_no_mirror() - - self.dvs_policer.remove_policer("test_policer") - self.dvs_policer.verify_no_policer() - - # Reset for test cases after this one - dvs.stop_swss() - dvs.start_swss() - dvs.check_swss_ready() - - def test_TunnelMgrdWarmRestart(self, dvs): - tunnel_name = "MuxTunnel0" - tunnel_table = "TUNNEL_DECAP_TABLE" - tunnel_params = { - "tunnel_type": "IPINIP", - "dst_ip": "10.1.0.32", - "dscp_mode": "uniform", - "ecn_mode": "standard", - "ttl_mode": "pipe" - } - - pubsub = dvs.SubscribeAppDbObject(tunnel_table) - - dvs.runcmd("config warm_restart enable swss") - config_db = dvs.get_config_db() - config_db.create_entry("TUNNEL", tunnel_name, tunnel_params) - - app_db = dvs.get_app_db() - app_db.wait_for_matching_keys(tunnel_table, [tunnel_name]) - - nadd, ndel = dvs.CountSubscribedObjects(pubsub) - assert nadd == len(tunnel_params) - assert ndel == 1 # Expect 1 deletion as part of table creation - - dvs.runcmd("supervisorctl restart tunnelmgrd") - dvs.check_services_ready() - nadd, ndel = dvs.CountSubscribedObjects(pubsub) - assert nadd == 0 - assert ndel == 0 - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_watermark.py b/tests/test_watermark.py deleted file mode 100644 index a8cee70aa1..0000000000 --- a/tests/test_watermark.py +++ /dev/null @@ -1,310 +0,0 @@ -import os -import re -import time -import json -import pytest -import redis - -from swsscommon import swsscommon - -class SaiWmStats: - queue_shared = "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES" - pg_shared = "SAI_INGRESS_PRIORITY_GROUP_STAT_SHARED_WATERMARK_BYTES" - pg_headroom = "SAI_INGRESS_PRIORITY_GROUP_STAT_XOFF_ROOM_WATERMARK_BYTES" - buffer_pool = "SAI_BUFFER_POOL_STAT_WATERMARK_BYTES" - hdrm_pool = "SAI_BUFFER_POOL_STAT_XOFF_ROOM_WATERMARK_BYTES" - - -class WmTables: - persistent = "PERSISTENT_WATERMARKS" - periodic = "PERIODIC_WATERMARKS" - user = "USER_WATERMARKS" - - -class WmFCEntry: - queue_stats_entry = {"QUEUE_COUNTER_ID_LIST": SaiWmStats.queue_shared} - pg_stats_entry = {"PG_COUNTER_ID_LIST": "{},{}".format(SaiWmStats.pg_shared, SaiWmStats.pg_headroom)} - buffer_stats_entry = {"BUFFER_POOL_COUNTER_ID_LIST": "{},{}".format(SaiWmStats.buffer_pool, SaiWmStats.hdrm_pool)} - - -class TestWatermark(object): - - DEFAULT_TELEMETRY_INTERVAL = 120 - NEW_INTERVAL = 5 - DEFAULT_POLL_INTERVAL = 10 - - def setup_dbs(self, dvs): - self.asic_db = dvs.get_asic_db() - self.counters_db = dvs.get_counters_db() - self.config_db = dvs.get_config_db() - self.flex_db = dvs.get_flex_db() - - def enable_unittests(self, dvs, status): - db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - ntf = swsscommon.NotificationProducer(db, "SAI_VS_UNITTEST_CHANNEL") - fvp = swsscommon.FieldValuePairs() - ntf.send("enable_unittests", status, fvp) - - def set_counter(self, dvs, obj_type, obj_id, attr, val): - - db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - ntf = swsscommon.NotificationProducer(db, "SAI_VS_UNITTEST_CHANNEL") - - r = redis.Redis(unix_socket_path=dvs.redis_sock, db=swsscommon.ASIC_DB, - encoding="utf-8", decode_responses=True) - rid = r.hget("VIDTORID", obj_id) - - assert rid is not None - - fvp = swsscommon.FieldValuePairs([(attr, val)]) - key = rid - - # explicit convert unicode string to str for python2 - ntf.send("set_stats", str(key), fvp) - - def populate_asic(self, dvs, obj_type, attr, val): - - db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - - if obj_type == "SAI_OBJECT_TYPE_QUEUE": - oids = self.qs - elif obj_type == "SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP": - oids = self.pgs - else: - oids = self.buffers - - for obj_id in oids: - self.set_counter(dvs, obj_type, obj_id, attr, val) - - def populate_asic_all(self, dvs, val): - self.populate_asic(dvs, "SAI_OBJECT_TYPE_QUEUE", SaiWmStats.queue_shared, val) - self.populate_asic(dvs, "SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP", SaiWmStats.pg_shared, val) - self.populate_asic(dvs, "SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP", SaiWmStats.pg_headroom, val) - self.populate_asic(dvs, "SAI_OBJECT_TYPE_BUFFER_POOL", SaiWmStats.buffer_pool, val) - self.populate_asic(dvs, "SAI_OBJECT_TYPE_BUFFER_POOL", SaiWmStats.hdrm_pool, val) - time.sleep(self.DEFAULT_POLL_INTERVAL) - - def verify_value(self, dvs, obj_ids, table_name, watermark_name, expected_value): - - counters_db = swsscommon.DBConnector(swsscommon.COUNTERS_DB, dvs.redis_sock, 0) - table = swsscommon.Table(counters_db, table_name) - - for obj_id in obj_ids: - - ret = table.get(obj_id) - - status = ret[0] - assert status - keyvalues = ret[1] - found = False - for key, value in keyvalues: - if key == watermark_name: - assert value == expected_value - found = True - assert found, "no such watermark found" - - def set_up_flex_counter(self, dvs): - fc_status_enable = {"FLEX_COUNTER_STATUS": "enable"} - - self.config_db.create_entry("FLEX_COUNTER_TABLE", - "PG_WATERMARK", - fc_status_enable) - self.config_db.create_entry("FLEX_COUNTER_TABLE", - "QUEUE_WATERMARK", - fc_status_enable) - self.config_db.create_entry("FLEX_COUNTER_TABLE", - "BUFFER_POOL_WATERMARK", - fc_status_enable) - - # Wait for DB's to populate by orchagent - time.sleep(2) - - def clear_flex_counter(self, dvs): - for q in self.qs: - self.flex_db.delete_entry("FLEX_COUNTER_TABLE", - "QUEUE_WATERMARK_STAT_COUNTER:{}".format(q)) - - for pg in self.pgs: - self.flex_db.delete_entry("FLEX_COUNTER_TABLE", - "PG_WATERMARK_STAT_COUNTER:{}".format(pg)) - - for buffer in self.buffers: - self.flex_db.delete_entry("FLEX_COUNTER_TABLE", - "BUFFER_POOL_WATERMARK_STAT_COUNTER:{}".format(buffer)) - - self.config_db.delete_entry("FLEX_COUNTER_TABLE", "PG_WATERMARK") - self.config_db.delete_entry("FLEX_COUNTER_TABLE", "QUEUE_WATERMARK") - self.config_db.delete_entry("FLEX_COUNTER_TABLE", "BUFFER_POOL_WATERMARK") - - def set_up(self, dvs): - self.pgs = self.counters_db.db_connection.hgetall("COUNTERS_PG_NAME_MAP").values() - assert self.pgs is not None and len(self.pgs) > 0 - self.qs = self.counters_db.db_connection.hgetall("COUNTERS_QUEUE_NAME_MAP").values() - assert self.qs is not None and len(self.pgs) > 0 - self.buffers = self.asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_BUFFER_POOL") - - self.populate_asic_all(dvs, "0") - - db = swsscommon.DBConnector(swsscommon.COUNTERS_DB, dvs.redis_sock, 0) - tbl = swsscommon.Table(db, "COUNTERS_QUEUE_TYPE_MAP") - - self.uc_q = [] - self.mc_q = [] - self.all_q = [] - - for q in self.qs: - if self.qs.index(q) % 16 < 5: - tbl.set('', [(q, "SAI_QUEUE_TYPE_UNICAST")]) - self.uc_q.append(q) - elif self.qs.index(q) % 16 < 10: - tbl.set('', [(q, "SAI_QUEUE_TYPE_MULTICAST")]) - self.mc_q.append(q) - else: - tbl.set('', [(q, "SAI_QUEUE_TYPE_ALL")]) - self.all_q.append(q) - - def clear_watermark(self, dvs, data): - adb = swsscommon.DBConnector(0, dvs.redis_sock, 0) - msg = json.dumps(data, separators=(',',':')) - adb.publish('WATERMARK_CLEAR_REQUEST', msg) - time.sleep(1) - - def test_telemetry_period(self, dvs): - self.setup_dbs(dvs) - self.set_up_flex_counter(dvs) - self.set_up(dvs) - try: - self.enable_unittests(dvs, "true") - - self.populate_asic_all(dvs, "100") - - time.sleep(self.DEFAULT_TELEMETRY_INTERVAL + 1) - - self.verify_value(dvs, self.pgs, WmTables.periodic, SaiWmStats.pg_shared, "0") - self.verify_value(dvs, self.pgs, WmTables.periodic, SaiWmStats.pg_headroom, "0") - self.verify_value(dvs, self.qs, WmTables.periodic, SaiWmStats.queue_shared, "0") - self.verify_value(dvs, self.buffers, WmTables.periodic, SaiWmStats.buffer_pool, "0") - self.verify_value(dvs, self.buffers, WmTables.periodic, SaiWmStats.hdrm_pool, "0") - - self.populate_asic_all(dvs, "123") - - interval = {"interval": "5"} - self.config_db.create_entry("WATERMARK_TABLE", - "TELEMETRY_INTERVAL", - interval) - - time.sleep(self.DEFAULT_TELEMETRY_INTERVAL + 1) - time.sleep(self.NEW_INTERVAL + 1) - - self.verify_value(dvs, self.pgs, WmTables.periodic, SaiWmStats.pg_shared, "0") - self.verify_value(dvs, self.pgs, WmTables.periodic, SaiWmStats.pg_headroom, "0") - self.verify_value(dvs, self.qs, WmTables.periodic, SaiWmStats.queue_shared, "0") - self.verify_value(dvs, self.buffers, WmTables.periodic, SaiWmStats.buffer_pool, "0") - self.verify_value(dvs, self.buffers, WmTables.periodic, SaiWmStats.hdrm_pool, "0") - - finally: - self.clear_flex_counter(dvs) - self.enable_unittests(dvs, "false") - - @pytest.mark.skip(reason="This test is not stable enough") - def test_lua_plugins(self, dvs): - - self.setup_dbs(dvs) - self.set_up(dvs) - try: - self.set_up_flex_counter(dvs) - self.enable_unittests(dvs, "true") - - self.populate_asic_all(dvs, "192") - - for table_name in [WmTables.user, WmTables.persistent]: - self.verify_value(dvs, self.selected_qs, table_name, SaiWmStats.queue_shared, "192") - self.verify_value(dvs, self.selected_pgs, table_name, SaiWmStats.pg_headroom, "192") - self.verify_value(dvs, self.selected_pgs, table_name, SaiWmStats.pg_shared, "192") - self.verify_value(dvs, self.buffers, table_name, SaiWmStats.buffer_pool, "192") - self.verify_value(dvs, self.buffers, table_name, SaiWmStats.hdrm_pool, "192") - - self.populate_asic_all(dvs, "96") - - for table_name in [WmTables.user, WmTables.persistent]: - self.verify_value(dvs, self.selected_qs, table_name, SaiWmStats.queue_shared, "192") - self.verify_value(dvs, self.selected_pgs, table_name, SaiWmStats.pg_headroom, "192") - self.verify_value(dvs, self.selected_pgs, table_name, SaiWmStats.pg_shared, "192") - self.verify_value(dvs, self.buffers, table_name, SaiWmStats.buffer_pool, "192") - self.verify_value(dvs, self.buffers, table_name, SaiWmStats.hdrm_pool, "192") - - self.populate_asic_all(dvs, "288") - - for table_name in [WmTables.user, WmTables.persistent]: - self.verify_value(dvs, self.selected_qs, table_name, SaiWmStats.queue_shared, "288") - self.verify_value(dvs, self.selected_pgs, table_name, SaiWmStats.pg_headroom, "288") - self.verify_value(dvs, self.selected_pgs, table_name, SaiWmStats.pg_shared, "288") - self.verify_value(dvs, self.buffers, table_name, SaiWmStats.buffer_pool, "288") - self.verify_value(dvs, self.buffers, table_name, SaiWmStats.hdrm_pool, "288") - - finally: - self.clear_flex_counter(dvs) - self.enable_unittests(dvs, "false") - - @pytest.mark.skip(reason="This test is not stable enough") - def test_clear(self, dvs): - - self.setup_dbs(dvs) - self.set_up(dvs) - self.enable_unittests(dvs, "true") - - self.populate_asic_all(dvs, "288") - - # clear pg shared watermark, and verify that headroom watermark and persistent watermarks are not affected - - self.clear_watermark(dvs, ["USER", "PG_SHARED"]) - self.verify_value(dvs, self.pgs, WmTables.user, SaiWmStats.pg_shared, "0") - - # make sure the rest is untouched - - self.verify_value(dvs, self.pgs, WmTables.user, SaiWmStats.pg_headroom, "288") - self.verify_value(dvs, self.pgs, WmTables.persistent, SaiWmStats.pg_shared, "288") - self.verify_value(dvs, self.pgs, WmTables.persistent, SaiWmStats.pg_headroom, "288") - - # clear queue unicast persistent watermark, and verify that multicast watermark and user watermarks are not affected - - self.clear_watermark(dvs, ["PERSISTENT", "Q_SHARED_UNI"]) - - # make sure it cleared - self.verify_value(dvs, self.uc_q, WmTables.persistent, SaiWmStats.queue_shared, "0") - - # make sure the rest is untouched - - self.verify_value(dvs, self.mc_q, WmTables.persistent, SaiWmStats.queue_shared, "288") - self.verify_value(dvs, self.uc_q, WmTables.user, SaiWmStats.queue_shared, "288") - self.verify_value(dvs, self.mc_q, WmTables.user, SaiWmStats.queue_shared, "288") - self.verify_value(dvs, self.all_q, WmTables.user, SaiWmStats.queue_shared, "288") - self.verify_value(dvs, self.all_q, WmTables.persistent, SaiWmStats.queue_shared, "288") - - # clear queue all watermark, and verify that multicast and unicast watermarks are not affected - - # clear persistent all watermark - self.clear_watermark(dvs, ["PERSISTENT", "Q_SHARED_ALL"]) - - # make sure it cleared - self.verify_value(dvs, self.all_q, WmTables.persistent, SaiWmStats.queue_shared, "0") - - # clear user all watermark - self.clear_watermark(dvs, ["USER", "Q_SHARED_ALL"]) - - # make sure it cleared - self.verify_value(dvs, self.all_q, WmTables.user, SaiWmStats.queue_shared, "0") - - # make sure the rest is untouched - self.verify_value(dvs, self.mc_q, WmTables.user, SaiWmStats.queue_shared, "288") - self.verify_value(dvs, self.mc_q, WmTables.persistent, SaiWmStats.queue_shared, "288") - self.verify_value(dvs, self.uc_q, WmTables.user, SaiWmStats.queue_shared, "288") - self.verify_value(dvs, self.uc_q, WmTables.persistent, SaiWmStats.queue_shared, "0") - - self.enable_unittests(dvs, "false") - - -# Add Dummy always-pass test at end as workaroud -# for issue when Flaky fail on final test it invokes module tear-down before retrying -def test_nonflaky_dummy(): - pass diff --git a/tests/test_zmq.py b/tests/test_zmq.py deleted file mode 100644 index 8a3dc49894..0000000000 --- a/tests/test_zmq.py +++ /dev/null @@ -1,104 +0,0 @@ -from swsscommon import swsscommon - -from dash_api.appliance_pb2 import * -from dash_api.vnet_pb2 import * -from dash_api.eni_pb2 import * -from dash_api.route_pb2 import * -from dash_api.route_rule_pb2 import * -from dash_api.vnet_mapping_pb2 import * -from dash_api.route_type_pb2 import * -from dash_api.types_pb2 import * - -import typing -import time -import binascii -import uuid -import ipaddress -import sys -import socket -import logging -import pytest - -logging.basicConfig(level=logging.INFO) -zmq_logger = logging.getLogger(__name__) - -DVS_ENV = ["HWSKU=DPU-2P"] -NUM_PORTS = 2 - -class Table(object): - def __init__(self, database, table_name: str): - self.table_name = table_name - self.table = swsscommon.Table(database.db_connection, self.table_name) - - def __getitem__(self, key: str): - exists, result = self.table.get(str(key)) - if not exists: - return None - else: - return dict(result) - - def get_keys(self): - return self.table.getKeys() - - def get_newly_created_oid(self, old_oids): - new_oids = self.asic_db.wait_for_n_keys(table, len(old_oids) + 1) - oid = [ids for ids in new_oids if ids not in old_oids] - return oid[0] - -class DashZmq(object): - def __init__(self, dvs): - self.dvs = dvs - self.asic_direction_lookup_table = Table( - self.dvs.get_asic_db(), "ASIC_STATE:SAI_OBJECT_TYPE_DIRECTION_LOOKUP_ENTRY") - self.asic_vip_table = Table( - self.dvs.get_asic_db(), "ASIC_STATE:SAI_OBJECT_TYPE_VIP_ENTRY") - -class TestZmqDash(object): - @pytest.fixture(scope="class") - def enable_orchagent_zmq(self, dvs): - # change orchagent to use ZMQ - dvs.runcmd("cp /usr/bin/orchagent.sh /usr/bin/orchagent.sh_zmq_ut_backup") - dvs.runcmd("sed -i.bak 's/\/usr\/bin\/orchagent /\/usr\/bin\/orchagent -q tcp:\/\/127.0.0.1:8100 /g' /usr/bin/orchagent.sh") - dvs.stop_swss() - dvs.start_swss() - - process_statue = dvs.runcmd("ps -ef") - zmq_logger.debug("Process status: {}".format(process_statue)) - - yield - - # revert change - dvs.runcmd("cp /usr/bin/orchagent.sh_zmq_ut_backup /usr/bin/orchagent.sh") - dvs.stop_swss() - dvs.start_swss() - - @pytest.mark.usefixtures("enable_orchagent_zmq") - def test_appliance(self, dvs): - # upload test script to test container and create applicance with it - dvs.copy_file("/", "create_appliance.py") - dvs.runcmd(['sh', '-c', "python3 create_appliance.py {}".format(1234)]) - time.sleep(3) - - asic_direction_lookup_table = Table( - dvs.get_asic_db(), "ASIC_STATE:SAI_OBJECT_TYPE_DIRECTION_LOOKUP_ENTRY") - direction_entries = asic_direction_lookup_table.get_keys() - zmq_logger.info("Keys from asic_direction_lookup_table: {}".format(direction_entries)) - - assert direction_entries - fvs = asic_direction_lookup_table[direction_entries[0]] - zmq_logger.info("Data from asic_direction_lookup_table: {}={}".format(direction_entries[0], fvs)) - for fv in fvs.items(): - if fv[0] == "SAI_DIRECTION_LOOKUP_ENTRY_ATTR_ACTION": - assert fv[1] == "SAI_DIRECTION_LOOKUP_ENTRY_ACTION_SET_OUTBOUND_DIRECTION" - - asic_vip_table = Table( - dvs.get_asic_db(), "ASIC_STATE:SAI_OBJECT_TYPE_VIP_ENTRY") - vip_entries = asic_vip_table.get_keys() - zmq_logger.info("Keys from asic_vip_table: {}".format(direction_entries)) - - assert vip_entries - fvs = asic_vip_table[vip_entries[0]] - zmq_logger.info("Data from asic_vip_table: {}={}".format(vip_entries[0], fvs)) - for fv in fvs.items(): - if fv[0] == "SAI_VIP_ENTRY_ATTR_ACTION": - assert fv[1] == "SAI_VIP_ENTRY_ACTION_ACCEPT" From 0eb00be2d70904776d0a7a7bf1b0d0d6c8db2aec Mon Sep 17 00:00:00 2001 From: kcudnik Date: Thu, 23 May 2024 16:50:00 +0200 Subject: [PATCH 2/7] disable swss tests --- configure.ac | 4 ---- orchagent/Makefile.am | 4 ---- tests/Makefile.am | 4 ---- 3 files changed, 12 deletions(-) diff --git a/configure.ac b/configure.ac index 231f1e1c58..41983f9f0c 100644 --- a/configure.ac +++ b/configure.ac @@ -159,11 +159,7 @@ AC_CONFIG_FILES([ swssconfig/Makefile cfgmgr/Makefile tests/Makefile - orchagent/p4orch/tests/Makefile ]) -# If no SAI library is installed, compile with SAIVS and run unit tests -AM_COND_IF([HAVE_SAI],[], - [AC_CONFIG_FILES([tests/mock_tests/Makefile])]) AC_OUTPUT diff --git a/orchagent/Makefile.am b/orchagent/Makefile.am index 7e1d0b7143..eaed043014 100644 --- a/orchagent/Makefile.am +++ b/orchagent/Makefile.am @@ -8,10 +8,6 @@ INCLUDES = -I $(top_srcdir)/lib \ -I pbh \ -I nhg -if GCOV_ENABLED -SUBDIRS = p4orch/tests -endif - CFLAGS_SAI = -I /usr/include/sai swssdir = $(datadir)/swss diff --git a/tests/Makefile.am b/tests/Makefile.am index 8f2aa131c4..687e8d497f 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -4,10 +4,6 @@ CFLAGS_SAI = -I /usr/include/sai TESTS = tests -if !HAVE_SAI -SUBDIRS = mock_tests -endif - noinst_PROGRAMS = tests if DEBUG From 1fee698974f090c3592b73717def53e72a4cd0a7 Mon Sep 17 00:00:00 2001 From: kcudnik Date: Thu, 23 May 2024 16:51:44 +0200 Subject: [PATCH 3/7] Add more logging --- orchagent/crmorch.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/orchagent/crmorch.cpp b/orchagent/crmorch.cpp index b5844bbea3..d9a32357bc 100644 --- a/orchagent/crmorch.cpp +++ b/orchagent/crmorch.cpp @@ -1074,6 +1074,7 @@ void CrmOrch::checkCrmThresholds() if (res.resStatus == CrmResourceStatus::CRM_RES_NOT_SUPPORTED) { + SWSS_LOG_WARN("XXX CrmResourceStatus::CRM_RES_NOT_SUPPORTED"); continue; } @@ -1116,6 +1117,8 @@ void CrmOrch::checkCrmThresholds() throw runtime_error("Unknown threshold type for CRM resource"); } + SWSS_LOG_WARN("XXX res.thresholdType: %s", threshType.c_str()); + if ((utilization >= res.highThreshold) && (cnt.exceededLogCounter < CRM_EXCEEDED_MSG_MAX)) { event_params_t params = { From 6f7fd15a47939ce8e483cdb2cba005ac296aa10c Mon Sep 17 00:00:00 2001 From: kcudnik Date: Thu, 23 May 2024 17:21:58 +0200 Subject: [PATCH 4/7] remove p4rt --- tests/p4rt/acl.py | 209 --- tests/p4rt/l3.py | 578 -------- tests/p4rt/l3_admit.py | 84 -- tests/p4rt/tables_definition.py | 35 - tests/p4rt/test_l3.py | 2369 ------------------------------- tests/p4rt/test_l3_admit.py | 216 --- tests/p4rt/test_p4rt_acl.py | 1288 ----------------- tests/p4rt/test_p4rt_mirror.py | 202 --- tests/p4rt/test_viplb.py | 263 ---- tests/p4rt/util.py | 138 -- tests/p4rt/viplb.py | 74 - 11 files changed, 5456 deletions(-) delete mode 100644 tests/p4rt/acl.py delete mode 100644 tests/p4rt/l3.py delete mode 100644 tests/p4rt/l3_admit.py delete mode 100644 tests/p4rt/tables_definition.py delete mode 100644 tests/p4rt/test_l3.py delete mode 100644 tests/p4rt/test_l3_admit.py delete mode 100644 tests/p4rt/test_p4rt_acl.py delete mode 100644 tests/p4rt/test_p4rt_mirror.py delete mode 100644 tests/p4rt/test_viplb.py delete mode 100644 tests/p4rt/util.py delete mode 100644 tests/p4rt/viplb.py diff --git a/tests/p4rt/acl.py b/tests/p4rt/acl.py deleted file mode 100644 index 6623bb3fcf..0000000000 --- a/tests/p4rt/acl.py +++ /dev/null @@ -1,209 +0,0 @@ -# Lint as: python3 -from swsscommon import swsscommon - -import util - -INGRESS_STAGE = "SAI_ACL_STAGE_INGRESS" -EGRESS_STAGE = "SAI_ACL_STAGE_EGRESS" -PRE_INGRESS_STAGE = "SAI_ACL_STAGE_PRE_INGRESS" - -class P4RtAclTableDefinitionWrapper(util.DBInterface): - """Interface to interact with APP DB and ASIC DB tables for P4RT ACL table definition object.""" - - # table name in ASIC_DB and SAI constants - ASIC_DB_TBL_NAME = "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE" - SAI_ATTR_MATCH_ETHER_TYPE = "SAI_ACL_TABLE_ATTR_FIELD_ETHER_TYPE" - SAI_ATTR_MATCH_IP_TYPE = "SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE" - SAI_ATTR_MATCH_DST_MAC = "SAI_ACL_TABLE_ATTR_FIELD_DST_MAC" - SAI_ATTR_MATCH_ROUTE_DST_USER_META = "SAI_ACL_TABLE_ATTR_FIELD_ROUTE_DST_USER_META" - SAI_ATTR_MATCH_SRC_IPV6_WORD3 = "SAI_ACL_TABLE_ATTR_FIELD_SRC_IPV6_WORD3" - SAI_ATTR_MATCH_SRC_IPV6_WORD2 = "SAI_ACL_TABLE_ATTR_FIELD_SRC_IPV6_WORD2" - SAI_ATTR_MATCH_UDF_GROUP_MIN = "SAI_ACL_TABLE_ATTR_USER_DEFINED_FIELD_GROUP_MIN" - SAI_ATTR_MATCH_UDF_GROUP_1 = "SAI_ACL_TABLE_ATTR_USER_DEFINED_FIELD_GROUP_1" - SAI_ATTR_ACTION_TYPE_LIST = "SAI_ACL_TABLE_ATTR_ACL_ACTION_TYPE_LIST" - SAI_ACL_TABLE_ATTR_ACL_STAGE = "SAI_ACL_TABLE_ATTR_ACL_STAGE" - SAI_ACL_TABLE_ATTR_SIZE = "SAI_ACL_TABLE_ATTR_SIZE" - - # table name in APP_DB and attribute fields - APP_DB_TBL_NAME = swsscommon.APP_P4RT_TABLE_NAME - TBL_NAME = swsscommon.APP_P4RT_ACL_TABLE_DEFINITION_NAME - STAGE_FIELD = "stage" - PRIORITY_FIELD = "priority" - SIZE_FIELD = "size" - MATCH_FIELD_ETHER_TYPE = "match/ether_type" - MATCH_FIELD_ETHER_DST = "match/ether_dst" - MATCH_FIELD_L3_CLASS_ID = "match/l3_class_id" - MATCH_FIELD_IS_IP = "match/is_ip" - MATCH_FIELD_IS_IPV4 = "match/is_ipv4" - MATCH_FIELD_IS_IPV6 = "match/is_ipv6" - MATCH_FIELD_IS_ARP = "match/is_arp" - MATCH_FIELD_SRC_IPV6_64BIT = "match/src_ipv6_64bit" - MATCH_FIELD_ARP_TPA = "match/arp_tpa" - ACTION_COPY_AND_SET_TC = "action/copy_and_set_tc" - ACTION_PUNT_AND_SET_TC = "action/punt_and_set_tc" - ACTION_SET_QOS_QUEUE = "action/qos_queue" - METER_UNIT = "meter/unit" - COUNTER_UNIT = "counter/unit" - - -class P4RtAclRuleWrapper(util.DBInterface): - """Interface to interact with APP DB and ASIC DB tables for P4RT ACL entry object.""" - - # table name in ASIC_DB and SAI constants - ASIC_DB_TBL_NAME = "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY" - SAI_ATTR_TABLE_ID = "SAI_ACL_ENTRY_ATTR_TABLE_ID" - SAI_ATTR_PRIORITY = "SAI_ACL_ENTRY_ATTR_PRIORITY" - SAI_ATTR_ADMIN_STATE = "SAI_ACL_ENTRY_ATTR_ADMIN_STATE" - SAI_ATTR_SET_POLICER = "SAI_ACL_ENTRY_ATTR_ACTION_SET_POLICER" - SAI_ATTR_COUNTER = "SAI_ACL_ENTRY_ATTR_ACTION_COUNTER" - SAI_ATTR_MATCH_ETHER_TYPE = "SAI_ACL_ENTRY_ATTR_FIELD_ETHER_TYPE" - SAI_ATTR_MATCH_IP_TYPE = "SAI_ACL_ENTRY_ATTR_FIELD_ACL_IP_TYPE" - SAI_ATTR_MATCH_DST_MAC = "SAI_ACL_ENTRY_ATTR_FIELD_DST_MAC" - SAI_ATTR_MATCH_ROUTE_DST_USER_META = "SAI_ACL_ENTRY_ATTR_FIELD_ROUTE_DST_USER_META" - SAI_ATTR_MATCH_SRC_IPV6_WORD3 = "SAI_ACL_ENTRY_ATTR_FIELD_SRC_IPV6_WORD3" - SAI_ATTR_MATCH_SRC_IPV6_WORD2 = "SAI_ACL_ENTRY_ATTR_FIELD_SRC_IPV6_WORD2" - SAI_ATTR_MATCH_UDF_GROUP_MIN = "SAI_ACL_ENTRY_ATTR_USER_DEFINED_FIELD_GROUP_MIN" - SAI_ATTR_MATCH_UDF_GROUP_1 = "SAI_ACL_ENTRY_ATTR_USER_DEFINED_FIELD_GROUP_1" - SAI_ATTR_ACTION_PACKET_ACTION = "SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION" - SAI_ATTR_ACTION_SET_TC = "SAI_ACL_ENTRY_ATTR_ACTION_SET_TC" - SAI_ATTR_ACTION_SET_USER_TRAP_ID = "SAI_ACL_ENTRY_ATTR_ACTION_SET_USER_TRAP_ID" - - # table name in APP_DB and attribute fields - APP_DB_TBL_NAME = swsscommon.APP_P4RT_TABLE_NAME - ACTION = "action" - METER_CIR = "meter/cir" - METER_CBURST = "meter/cburst" - METER_PIR = "meter/pir" - METER_PBURST = "meter/pburst" - - -class P4RtAclCounterWrapper(util.DBInterface): - """Interface to interact with APP DB and ASIC DB tables for P4RT ACL counter object.""" - - # table name in ASIC_DB and SAI constants - ASIC_DB_TBL_NAME = "ASIC_STATE:SAI_OBJECT_TYPE_ACL_COUNTER" - SAI_ATTR_TABLE_ID = "SAI_ACL_COUNTER_ATTR_TABLE_ID" - SAI_ATTR_ENABLE_BYTE_COUNT = "SAI_ACL_COUNTER_ATTR_ENABLE_BYTE_COUNT" - SAI_ATTR_ENABLE_PACKET_COUNT = "SAI_ACL_COUNTER_ATTR_ENABLE_PACKET_COUNT" - - -class P4RtAclMeterWrapper(util.DBInterface): - """Interface in ASIC DB tables for P4RT ACL policer object.""" - - # table name in ASIC_DB and SAI constants - ASIC_DB_TBL_NAME = "ASIC_STATE:SAI_OBJECT_TYPE_POLICER" - SAI_ATTR_METER_TYPE = "SAI_POLICER_ATTR_METER_TYPE" - SAI_ATTR_METER_MODE = "SAI_POLICER_ATTR_MODE" - SAI_ATTR_METER_CBS = "SAI_POLICER_ATTR_CBS" - SAI_ATTR_METER_CIR = "SAI_POLICER_ATTR_CIR" - SAI_ATTR_METER_PBS = "SAI_POLICER_ATTR_PBS" - SAI_ATTR_METER_PIR = "SAI_POLICER_ATTR_PIR" - SAI_ATTR_GREEN_PACKET_ACTION = "SAI_POLICER_ATTR_GREEN_PACKET_ACTION" - SAI_ATTR_RED_PACKET_ACTION = "SAI_POLICER_ATTR_RED_PACKET_ACTION" - SAI_ATTR_YELLOW_PACKET_ACTION = "SAI_POLICER_ATTR_YELLOW_PACKET_ACTION" - - -class P4RtAclGroupWrapper(util.DBInterface): - """Interface in ASIC DB tables for P4RT ACL group object.""" - - # table name in ASIC_DB and SAI constants - ASIC_DB_TBL_NAME = "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE_GROUP" - SAI_ACL_TABLE_GROUP_ATTR_ACL_STAGE = "SAI_ACL_TABLE_GROUP_ATTR_ACL_STAGE" - SAI_ACL_TABLE_GROUP_ATTR_TYPE = "SAI_ACL_TABLE_GROUP_ATTR_TYPE" - SAI_ACL_TABLE_ATTR_ACL_BIND_POINT_TYPE_LIST = "SAI_ACL_TABLE_ATTR_ACL_BIND_POINT_TYPE_LIST" - - def get_group_oids_by_stage(self, stage): - tbl = swsscommon.Table(self.asic_db, self.ASIC_DB_TBL_NAME) - keys = tbl.getKeys() - group_oids = [] - for key in keys: - (status, fvs) = tbl.get(key) - assert status == True - for name, val in fvs: - if name == self.SAI_ACL_TABLE_GROUP_ATTR_ACL_STAGE and val == stage: - group_oids.append(key) - break - return group_oids - - -class P4RtAclGroupMemberWrapper(util.DBInterface): - """Interface in ASIC DB tables for P4RT ACL group member object.""" - - # table name in ASIC_DB and SAI constants - ASIC_DB_TBL_NAME = "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE_GROUP_MEMBER" - SAI_ACL_TABLE_GROUP_MEMBER_ATTR_ACL_TABLE_GROUP_ID = "SAI_ACL_TABLE_GROUP_MEMBER_ATTR_ACL_TABLE_GROUP_ID" - SAI_ACL_TABLE_GROUP_MEMBER_ATTR_ACL_TABLE_ID = "SAI_ACL_TABLE_GROUP_MEMBER_ATTR_ACL_TABLE_ID" - SAI_ACL_TABLE_GROUP_MEMBER_ATTR_PRIORITY = "SAI_ACL_TABLE_GROUP_MEMBER_ATTR_PRIORITY" - - -class P4RtUserDefinedTrapWrapper(util.DBInterface): - """Interface in ASIC DB tables for SAI user defined trap object.""" - - # table name in ASIC_DB and SAI constants - ASIC_DB_TBL_NAME = "ASIC_STATE:SAI_OBJECT_TYPE_HOSTIF_USER_DEFINED_TRAP" - SAI_HOSTIF_USER_DEFINED_TRAP_ATTR_TRAP_GROUP = "SAI_HOSTIF_USER_DEFINED_TRAP_ATTR_TRAP_GROUP" - SAI_HOSTIF_USER_DEFINED_TRAP_ATTR_TYPE = "SAI_HOSTIF_USER_DEFINED_TRAP_ATTR_TYPE" - - -class P4RtTrapGroupWrapper(util.DBInterface): - """Interface in APPL and ASIC DB tables for SAI trap group object.""" - - # table name in APPL_DB and attribute fields - APP_DB_TBL_NAME = "COPP_TABLE" - TBL_NAME_PREFIX = "trap.group.cpu.queue." - QUEUE = "queue" - HOSTIF_NAME = "genetlink_name" - HOSTIF_GENETLINK_MCGRP_NAME = "genetlink_mcgrp_name" - - # table name in ASIC_DB and SAI constants - ASIC_DB_TBL_NAME = "ASIC_STATE:SAI_OBJECT_TYPE_HOSTIF_TRAP_GROUP" - SAI_HOSTIF_TRAP_GROUP_ATTR_QUEUE = "SAI_HOSTIF_TRAP_GROUP_ATTR_QUEUE" - - -class P4RtHostifWrapper(util.DBInterface): - """Interface in ASIC DB tables for SAI hostif object.""" - - # table name in ASIC_DB and SAI constants - ASIC_DB_TBL_NAME = "ASIC_STATE:SAI_OBJECT_TYPE_HOSTIF" - SAI_HOSTIF_ATTR_TYPE = "SAI_HOSTIF_ATTR_TYPE" - SAI_HOSTIF_ATTR_NAME = "SAI_HOSTIF_ATTR_NAME" - SAI_HOSTIF_ATTR_GENETLINK_MCGRP_NAME = "SAI_HOSTIF_ATTR_GENETLINK_MCGRP_NAME" - - -class P4RtHostifTableEntryWrapper(util.DBInterface): - """Interface in ASIC DB tables for SAI hostif table entry object.""" - - # table name in ASIC_DB and SAI constants - ASIC_DB_TBL_NAME = "ASIC_STATE:SAI_OBJECT_TYPE_HOSTIF_TABLE_ENTRY" - SAI_HOSTIF_TABLE_ENTRY_ATTR_TYPE = "SAI_HOSTIF_TABLE_ENTRY_ATTR_TYPE" - SAI_HOSTIF_TABLE_ENTRY_ATTR_TRAP_ID = "SAI_HOSTIF_TABLE_ENTRY_ATTR_TRAP_ID" - SAI_HOSTIF_TABLE_ENTRY_ATTR_CHANNEL_TYPE = "SAI_HOSTIF_TABLE_ENTRY_ATTR_CHANNEL_TYPE" - SAI_HOSTIF_TABLE_ENTRY_ATTR_HOST_IF = "SAI_HOSTIF_TABLE_ENTRY_ATTR_HOST_IF" - -class P4RtUdfGroupWrapper(util.DBInterface): - """Interface in ASIC DB tables for SAI UDF Group object.""" - - # table name in ASIC_DB and SAI constants - ASIC_DB_TBL_NAME = "ASIC_STATE:SAI_OBJECT_TYPE_UDF_GROUP" - SAI_UDF_GROUP_ATTR_TYPE = "SAI_UDF_GROUP_ATTR_TYPE" - SAI_UDF_GROUP_ATTR_LENGTH = "SAI_UDF_GROUP_ATTR_LENGTH" - - SAI_UDF_GROUP_TYPE_GENERIC = "SAI_UDF_GROUP_TYPE_GENERIC" - - -class P4RtUdfMatchWrapper(util.DBInterface): - """Interface in ASIC DB tables for SAI UDF Match object.""" - - # table name in ASIC_DB and SAI constants - ASIC_DB_TBL_NAME = "ASIC_STATE:SAI_OBJECT_TYPE_UDF_MATCH" - - -class P4RtUdfWrapper(util.DBInterface): - """Interface in ASIC DB tables for SAI UDF object.""" - - # table name in ASIC_DB and SAI constants - ASIC_DB_TBL_NAME = "ASIC_STATE:SAI_OBJECT_TYPE_UDF" - SAI_UDF_ATTR_MATCH_ID = "SAI_UDF_ATTR_MATCH_ID" - SAI_UDF_ATTR_GROUP_ID = "SAI_UDF_ATTR_GROUP_ID" - SAI_UDF_ATTR_BASE = "SAI_UDF_ATTR_BASE" - SAI_UDF_ATTR_OFFSET = "SAI_UDF_ATTR_OFFSET" diff --git a/tests/p4rt/l3.py b/tests/p4rt/l3.py deleted file mode 100644 index 915228a9b5..0000000000 --- a/tests/p4rt/l3.py +++ /dev/null @@ -1,578 +0,0 @@ -from swsscommon import swsscommon - -import util -import json - - -class P4RtRouterInterfaceWrapper(util.DBInterface): - """Interface to interact with APP DB and ASIC DB tables for P4RT router interface object.""" - - # database and SAI constants - APP_DB_TBL_NAME = swsscommon.APP_P4RT_TABLE_NAME - TBL_NAME = swsscommon.APP_P4RT_ROUTER_INTERFACE_TABLE_NAME - ASIC_DB_TBL_NAME = "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE" - SAI_ATTR_SRC_MAC = "SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS" - SAI_ATTR_TYPE = "SAI_ROUTER_INTERFACE_ATTR_TYPE" - SAI_ATTR_TYPE_PORT = "SAI_ROUTER_INTERFACE_TYPE_PORT" - SAI_ATTR_MTU = "SAI_ROUTER_INTERFACE_ATTR_MTU" - SAI_ATTR_PORT_ID = "SAI_ROUTER_INTERFACE_ATTR_PORT_ID" - SAI_ATTR_DEFAULT_MTU = "9100" - - # attribute fields for router interface object - PORT_FIELD = "port" - SRC_MAC_FIELD = "src_mac" - - # default router interface attribute values - DEFAULT_ROUTER_INTERFACE_ID = "16" - DEFAULT_PORT_ID = "Ethernet8" - DEFAULT_SRC_MAC = "00:11:22:33:44:55" - DEFAULT_ACTION = "set_port_and_src_mac" - - # Fetch oid of the first newly created rif from created rif in ASIC - # db. This API should only be used when only one oid is expected to be - # created after the original entries. - # Original rif entries in asic db must be fetched using - # 'get_original_redis_entries' before fetching oid of newly created rif. - def get_newly_created_router_interface_oid(self, known_oids=set()): - rif_oid = None - rif_entries = util.get_keys(self.asic_db, self.ASIC_DB_TBL_NAME) - for key in rif_entries: - if ( - key - not in self._original_entries[ - "{}:{}".format(self.asic_db, self.ASIC_DB_TBL_NAME) - ] - and - key not in known_oids - ): - rif_oid = key - break - return rif_oid - - def generate_app_db_key(self, router_interface_id): - d = {} - d[util.prepend_match_field("router_interface_id")] = router_interface_id - key = json.dumps(d, separators=(",", ":")) - return self.TBL_NAME + ":" + key - - # create default router interface - def create_router_interface( - self, router_interace_id=None, port_id=None, src_mac=None, action=None - ): - router_interface_id = router_interace_id or self.DEFAULT_ROUTER_INTERFACE_ID - port_id = port_id or self.DEFAULT_PORT_ID - src_mac = src_mac or self.DEFAULT_SRC_MAC - action = action or self.DEFAULT_ACTION - attr_list = [ - (util.prepend_param_field(self.PORT_FIELD), port_id), - (util.prepend_param_field(self.SRC_MAC_FIELD), src_mac), - (self.ACTION_FIELD, action), - ] - router_intf_key = self.generate_app_db_key(router_interface_id) - self.set_app_db_entry(router_intf_key, attr_list) - return router_interface_id, router_intf_key, attr_list - -class P4RtGreTunnelWrapper(util.DBInterface): - """Interface to interact with APP DB and ASIC DB tables for P4RT GRE Tunnel object.""" - - # database and SAI constants - APP_DB_TBL_NAME = swsscommon.APP_P4RT_TABLE_NAME - TBL_NAME = "FIXED_TUNNEL_TABLE" - ASIC_DB_TBL_NAME = "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL" - SAI_ATTR_TYPE = "SAI_TUNNEL_ATTR_TYPE" - SAI_ATTR_PEER_MODE = "SAI_TUNNEL_ATTR_PEER_MODE" - SAI_ATTR_UNDERLAY_INTERFACE = "SAI_TUNNEL_ATTR_UNDERLAY_INTERFACE" - SAI_ATTR_OVERLAY_INTERFACE = "SAI_TUNNEL_ATTR_OVERLAY_INTERFACE" - SAI_ATTR_ENCAP_SRC_IP = "SAI_TUNNEL_ATTR_ENCAP_SRC_IP" - SAI_ATTR_ENCAP_DST_IP = "SAI_TUNNEL_ATTR_ENCAP_DST_IP" - - # attribute fields for tunnel object - ROUTER_ROUTER_INTERFACE_ID_FIELD = "router_interface_id" - ENCAP_SRC_IP_FIELD = "encap_src_ip" - ENCAP_DST_IP_FIELD = "encap_dst_ip" - - # default tunnel attribute values - DEFAULT_TUNNEL_ID = "tunnel-1" - DEFAULT_ROUTER_INTERFACE_ID = "16" - DEFAULT_ENCAP_SRC_IP = "1.2.3.4" - DEFAULT_ENCAP_DST_IP = "12.0.0.1" - DEFAULT_ACTION = "mark_for_p2p_tunnel_encap" - - def generate_app_db_key(self, tunnel_id): - d = {} - d[util.prepend_match_field("tunnel_id")] = tunnel_id - key = json.dumps(d, separators=(",", ":")) - return self.TBL_NAME + ":" + key - - # create default tunnel - def create_gre_tunnel( - self, tunnel_id=None, router_interface_id=None, encap_src_ip=None, encap_dst_ip=None, action=None - ): - tunnel_id = tunnel_id or self.DEFAULT_TUNNEL_ID - router_interface_id = router_interface_id or self.DEFAULT_ROUTER_INTERFACE_ID - encap_src_ip = encap_src_ip or self.DEFAULT_ENCAP_SRC_IP - encap_dst_ip = encap_dst_ip or self.DEFAULT_ENCAP_DST_IP - action = action or self.DEFAULT_ACTION - attr_list = [ - (util.prepend_param_field(self.ROUTER_ROUTER_INTERFACE_ID_FIELD), router_interface_id), - (util.prepend_param_field(self.ENCAP_SRC_IP_FIELD), encap_src_ip), - (util.prepend_param_field(self.ENCAP_DST_IP_FIELD), encap_dst_ip), - (self.ACTION_FIELD, action), - ] - tunnel_key = self.generate_app_db_key(tunnel_id) - self.set_app_db_entry(tunnel_key, attr_list) - return tunnel_id, tunnel_key, attr_list - - # Fetch oid of the first newly created tunnel from created tunnels in ASIC - # db. This API should only be used when only one oid is expected to be - # created after the original entries. - # Original tunnel entries in asic db must be fetched using - # 'get_original_redis_entries' before fetching oid of newly created tunnel. - def get_newly_created_tunnel_oid(self): - tunnel_oid = None - tunnel_entries = util.get_keys(self.asic_db, self.ASIC_DB_TBL_NAME) - for key in tunnel_entries: - if ( - key - not in self._original_entries[ - "{}:{}".format(self.asic_db, self.ASIC_DB_TBL_NAME) - ] - ): - tunnel_oid = key - break - return tunnel_oid - - def get_original_appl_db_entries_count(self): - return len( - self._original_entries[ - "%s:%s" % (self.appl_db, (self.APP_DB_TBL_NAME + ":" + self.TBL_NAME)) - ] - ) - - def get_original_appl_state_db_entries_count(self): - return len( - self._original_entries[ - "%s:%s" - % (self.appl_state_db, (self.APP_DB_TBL_NAME + ":" + self.TBL_NAME)) - ] - ) - - def get_original_asic_db_entries_count(self): - return len( - self._original_entries[ - "%s:%s" % (self.asic_db, self.ASIC_DB_TBL_NAME) - ] - ) - -class P4RtNeighborWrapper(util.DBInterface): - """Interface to interact with APP DB and ASIC DB tables for P4RT neighbor object.""" - - # database and SAI constants - APP_DB_TBL_NAME = swsscommon.APP_P4RT_TABLE_NAME - TBL_NAME = swsscommon.APP_P4RT_NEIGHBOR_TABLE_NAME - ASIC_DB_TBL_NAME = "ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY" - SAI_ATTR_DST_MAC = "SAI_NEIGHBOR_ENTRY_ATTR_DST_MAC_ADDRESS" - - # attribute fields for neighbor object - DST_MAC_FIELD = "dst_mac" - - # default neighbor attribute values - DEFAULT_ROUTER_INTERFACE_ID = "16" - DEFAULT_IPV4_NEIGHBOR_ID = "12.0.0.1" - DEFAULT_IPV6_NEIGHBOR_ID = "fe80::21a:11ff:fe17:5f80" - DEFAULT_DST_MAC = "00:02:03:04:05:06" - DEFAULT_ACTION = "set_dst_mac" - - def generate_app_db_key(self, router_interface_id, neighbor_id): - d = {} - d[util.prepend_match_field("router_interface_id")] = router_interface_id - d[util.prepend_match_field("neighbor_id")] = neighbor_id - key = json.dumps(d, separators=(",", ":")) - return self.TBL_NAME + ":" + key - - # create default neighbor - def create_neighbor( - self, - router_interface_id=None, - neighbor_id=None, - dst_mac=None, - action=None, - ipv4=True, - ): - router_interface_id = router_interface_id or self.DEFAULT_ROUTER_INTERFACE_ID - neighbor_id = neighbor_id or ( - self.DEFAULT_IPV4_NEIGHBOR_ID if ipv4 else self.DEFAULT_IPV6_NEIGHBOR_ID - ) - dst_mac = dst_mac or self.DEFAULT_DST_MAC - action = action or self.DEFAULT_ACTION - attr_list = [ - (util.prepend_param_field(self.DST_MAC_FIELD), dst_mac), - (self.ACTION_FIELD, action), - ] - neighbor_key = self.generate_app_db_key(router_interface_id, neighbor_id) - self.set_app_db_entry(neighbor_key, attr_list) - return neighbor_id, neighbor_key, attr_list - - -class P4RtNextHopWrapper(util.DBInterface): - """Interface to interact with APP DB and ASIC DB tables for P4RT nexthop object.""" - - # database and SAI constants - APP_DB_TBL_NAME = swsscommon.APP_P4RT_TABLE_NAME - TBL_NAME = swsscommon.APP_P4RT_NEXTHOP_TABLE_NAME - ASIC_DB_TBL_NAME = "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP" - SAI_ATTR_TYPE = "SAI_NEXT_HOP_ATTR_TYPE" - SAI_ATTR_IP = "SAI_NEXT_HOP_ATTR_IP" - SAI_ATTR_TUNNEL_ENCAP = "SAI_NEXT_HOP_TYPE_TUNNEL_ENCAP" - SAI_ATTR_ROUTER_INTF_OID = "SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID" - SAI_ATTR_TUNNEL_OID = "SAI_NEXT_HOP_ATTR_TUNNEL_ID" - - # attribute fields for nexthop object - RIF_FIELD = "router_interface_id" - NEIGHBOR_ID_FIELD = "neighbor_id" - TUNNEL_ID_FIELD = "tunnel_id" - - # default next hop attribute values - DEFAULT_ACTION = "set_ip_nexthop" - DEFAULT_NEXTHOP_ID = "8" - DEFAULT_ROUTER_INTERFACE_ID = "16" - DEFAULT_IPV4_NEIGHBOR_ID = "12.0.0.1" - DEFAULT_IPV6_NEIGHBOR_ID = "fe80::21a:11ff:fe17:5f80" - - # tunnel nexthop attribute values - TUNNEL_ACTION = "set_p2p_tunnel_encap_nexthop" - DEFAULT_TUNNEL_ID = "tunnel-1" - - def generate_app_db_key(self, nexthop_id): - d = {} - d[util.prepend_match_field("nexthop_id")] = nexthop_id - key = json.dumps(d, separators=(",", ":")) - return self.TBL_NAME + ":" + key - - # create next hop - def create_next_hop( - self, - router_interface_id=None, - neighbor_id=None, - action=None, - nexthop_id=None, - ipv4=True, - tunnel_id=None, - ): - action = action or (self.DEFAULT_ACTION if tunnel_id == None else self.TUNNEL_ACTION) - router_interface_id = router_interface_id or self.DEFAULT_ROUTER_INTERFACE_ID - if ipv4 is True: - neighbor_id = neighbor_id or self.DEFAULT_IPV4_NEIGHBOR_ID - else: - neighbor_id = neighbor_id or self.DEFAULT_IPV6_NEIGHBOR_ID - nexthop_id = nexthop_id or self.DEFAULT_NEXTHOP_ID - attr_list = [(self.ACTION_FIELD, action)] - if action == self.DEFAULT_ACTION: - attr_list.append((util.prepend_param_field(self.RIF_FIELD), router_interface_id)) - attr_list.append((util.prepend_param_field(self.NEIGHBOR_ID_FIELD), neighbor_id)) - if tunnel_id != None: - attr_list.append((util.prepend_param_field(self.TUNNEL_ID_FIELD), tunnel_id)) - nexthop_key = self.generate_app_db_key(nexthop_id) - self.set_app_db_entry(nexthop_key, attr_list) - return nexthop_id, nexthop_key, attr_list - - # Fetch oid of the first newly created nexthop from created nexthops in ASIC - # db. This API should only be used when only one oid is expected to be - # created after the original entries. - # Original nexthop entries in asic db must be fetched using - # 'get_original_redis_entries' before fetching oid of newly created nexthop. - def get_newly_created_nexthop_oid(self): - nexthop_oid = None - nexthop_entries = util.get_keys(self.asic_db, self.ASIC_DB_TBL_NAME) - for key in nexthop_entries: - if ( - key - not in self._original_entries[ - "{}:{}".format(self.asic_db, self.ASIC_DB_TBL_NAME) - ] - ): - nexthop_oid = key - break - return nexthop_oid - - def get_original_appl_db_entries_count(self): - return len( - self._original_entries[ - "%s:%s" % (self.appl_db, (self.APP_DB_TBL_NAME + ":" + self.TBL_NAME)) - ] - ) - - def get_original_appl_state_db_entries_count(self): - return len( - self._original_entries[ - "%s:%s" - % (self.appl_state_db, (self.APP_DB_TBL_NAME + ":" + self.TBL_NAME)) - ] - ) - - def get_original_asic_db_entries_count(self): - return len( - self._original_entries[ - "%s:%s" % (self.asic_db, self.ASIC_DB_TBL_NAME) - ] - ) - -class P4RtWcmpGroupWrapper(util.DBInterface): - """Interface to interact with APP DB and ASIC DB tables for P4RT wcmp group object.""" - - # database and SAI constants - APP_DB_TBL_NAME = swsscommon.APP_P4RT_TABLE_NAME - TBL_NAME = swsscommon.APP_P4RT_WCMP_GROUP_TABLE_NAME - ASIC_DB_GROUP_TBL_NAME = "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP" - SAI_ATTR_GROUP_TYPE = "SAI_NEXT_HOP_GROUP_ATTR_TYPE" - SAI_NEXT_HOP_GROUP_TYPE_DYNAMIC_UNORDERED_ECMP = ( - "SAI_NEXT_HOP_GROUP_TYPE_DYNAMIC_UNORDERED_ECMP" - ) - ASIC_DB_GROUP_MEMBER_TBL_NAME = "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER" - SAI_ATTR_GROUP_MEMBER_NEXTHOP_GROUP_ID = ( - "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID" - ) - SAI_ATTR_GROUP_MEMBER_NEXTHOP_ID = "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID" - SAI_ATTR_GROUP_MEMBER_WEIGHT = "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_WEIGHT" - - # attribute fields for wcmp group object - NEXTHOP_ID_FIELD = "nexthop_id" - WEIGHT_FIELD = "weight" - WATCH_PORT_FIELD = "watch_port" - ACTION_FIELD = "action" - ACTIONS_FIELD = "actions" - - # default wcmp group attributes - DEFAULT_WCMP_GROUP_ID = "group-a" - DEFAULT_WEIGHT = 2 - DEFAULT_ACTION = "set_nexthop_id" - DEFAULT_NEXTHOP_ID = "8" - DEFAULT_WATCH_PORT = "" - - # Fetch the oid of the first newly created wcmp group from created wcmp groups - # in AISC db. This API should only be used when only one oid is expected to be - # created after the original entries. - # Original wcmp group entries in asic db must be fetched using - # 'get_original_redis_entries' before fetching oid of newly created wcmp group. - def get_newly_created_wcmp_group_oid(self): - wcmp_group_oid = None - wcmp_group_entries = util.get_keys(self.asic_db, self.ASIC_DB_GROUP_TBL_NAME) - for key in wcmp_group_entries: - if ( - key - not in self._original_entries[ - "{}:{}".format(self.asic_db, self.ASIC_DB_GROUP_TBL_NAME) - ] - ): - wcmp_group_oid = key - break - return wcmp_group_oid - - # Fetch key for the first newly created wcmp group member from created group - # members in ASIC db. This API should only be used when only one key is - # expected to be created after the original entries. - # Original wcmp group member entries in asic db must be fetched using - # 'get_original_redis_entries' before fetching asic db key of newly created - # wcmp group member. - def get_newly_created_wcmp_group_member_asic_db_key(self): - asic_db_wcmp_group_member_key = None - wcmp_group_member_entries = util.get_keys( - self.asic_db, self.ASIC_DB_GROUP_MEMBER_TBL_NAME - ) - for key in wcmp_group_member_entries: - if ( - key - not in self._original_entries[ - "{}:{}".format(self.asic_db, self.ASIC_DB_GROUP_MEMBER_TBL_NAME) - ] - ): - asic_db_wcmp_group_member_key = key - break - return asic_db_wcmp_group_member_key - - def generate_app_db_key(self, group_id): - d = {} - d[util.prepend_match_field("wcmp_group_id")] = group_id - key = json.dumps(d, separators=(",", ":")) - return self.TBL_NAME + ":" + key - - # create default wcmp group - def create_wcmp_group( - self, - nexthop_id=None, - wcmp_group_id=None, - action=None, - weight=None, - watch_port=None, - ): - wcmp_group_id = wcmp_group_id or self.DEFAULT_WCMP_GROUP_ID - weight = weight or self.DEFAULT_WEIGHT - action = action or self.DEFAULT_ACTION - nexthop_id = nexthop_id or self.DEFAULT_NEXTHOP_ID - watch_port = watch_port or self.DEFAULT_WATCH_PORT - action1 = { - util.prepend_param_field(self.NEXTHOP_ID_FIELD): nexthop_id, - self.WEIGHT_FIELD: weight, - self.ACTION_FIELD: action, - self.WATCH_PORT_FIELD: watch_port, - } - actions = [action1] - attr_list = [(self.ACTIONS_FIELD, json.dumps(actions))] - wcmp_group_key = self.generate_app_db_key(wcmp_group_id) - self.set_app_db_entry(wcmp_group_key, attr_list) - return wcmp_group_id, wcmp_group_key, attr_list - - def get_original_appl_db_entries_count(self): - return len( - self._original_entries[ - "%s:%s" % (self.appl_db, (self.APP_DB_TBL_NAME + ":" + self.TBL_NAME)) - ] - ) - - def get_original_appl_state_db_entries_count(self): - return len( - self._original_entries[ - "%s:%s" - % (self.appl_state_db, (self.APP_DB_TBL_NAME + ":" + self.TBL_NAME)) - ] - ) - - def get_original_asic_db_group_entries_count(self): - return len( - self._original_entries[ - "%s:%s" % (self.asic_db, self.ASIC_DB_GROUP_TBL_NAME) - ] - ) - - def get_original_asic_db_member_entries_count(self): - return len( - self._original_entries[ - "%s:%s" % (self.asic_db, self.ASIC_DB_GROUP_MEMBER_TBL_NAME) - ] - ) - - -class P4RtRouteWrapper(util.DBInterface): - """Interface to interact with APP DB and ASIC DB tables for P4RT route object.""" - - # database and SAI constants - APP_DB_TBL_NAME = swsscommon.APP_P4RT_TABLE_NAME - ASIC_DB_TBL_NAME = "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY" - SAI_ATTR_PACKET_ACTION = "SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION" - SAI_ATTR_PACKET_ACTION_FORWARD = "SAI_PACKET_ACTION_FORWARD" - SAI_ATTR_PACKET_ACTION_DROP = "SAI_PACKET_ACTION_DROP" - SAI_ATTR_PACKET_ACTION_TRAP = "SAI_PACKET_ACTION_TRAP" - SAI_ATTR_NEXTHOP_ID = "SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID" - SAI_ATTR_META_DATA = "SAI_ROUTE_ENTRY_ATTR_META_DATA" - - # attribute fields for route object - NEXTHOP_ID_FIELD = "nexthop_id" - WCMP_GROUP_ID_FIELD = "wcmp_group_id" - ROUTE_METADATA_FIELD = "route_metadata" - - # default route attribute values - DEFAULT_ACTION = "set_nexthop_id" - DEFAULT_NEXTHOP_ID = "8" - DEFAULT_WCMP_GROUP_ID = "group-a" - DEFAULT_VRF_ID = "b4-traffic" - DEFAULT_DST = "10.11.12.0/24" - - def generate_app_db_key(self, vrf_id, dst): - assert self.ip_type is not None - d = {} - d[util.prepend_match_field("vrf_id")] = vrf_id - if self.ip_type == "IPV4": - d[util.prepend_match_field("ipv4_dst")] = dst - else: - d[util.prepend_match_field("ipv6_dst")] = dst - key = json.dumps(d, separators=(",", ":")) - return self.TBL_NAME + ":" + key - - def set_ip_type(self, ip_type): - assert ip_type in ("IPV4", "IPV6") - self.ip_type = ip_type - self.TBL_NAME = "FIXED_" + ip_type + "_TABLE" - - # Create default route. - def create_route( - self, - nexthop_id=None, - wcmp_group_id=None, - action=None, - vrf_id=None, - dst=None, - metadata="", - ): - action = action or self.DEFAULT_ACTION - vrf_id = vrf_id or self.DEFAULT_VRF_ID - dst = dst or self.DEFAULT_DST - if action == "set_wcmp_group_id": - wcmp_group_id = wcmp_group_id or self.DEFAULT_WCMP_GROUP_ID - attr_list = [ - (self.ACTION_FIELD, action), - (util.prepend_param_field(self.WCMP_GROUP_ID_FIELD), wcmp_group_id), - ] - elif action == "set_nexthop_id": - nexthop_id = nexthop_id or self.DEFAULT_NEXTHOP_ID - attr_list = [ - (self.ACTION_FIELD, action), - (util.prepend_param_field(self.NEXTHOP_ID_FIELD), nexthop_id), - ] - elif action == "set_wcmp_group_id_and_metadata": - wcmp_group_id = wcmp_group_id or self.DEFAULT_WCMP_GROUP_ID - attr_list = [ - (self.ACTION_FIELD, action), - (util.prepend_param_field(self.WCMP_GROUP_ID_FIELD), wcmp_group_id), - (util.prepend_param_field(self.ROUTE_METADATA_FIELD), metadata), - ] - elif action == "set_nexthop_id_and_metadata": - nexthop_id = nexthop_id or self.DEFAULT_NEXTHOP_ID - attr_list = [ - (self.ACTION_FIELD, action), - (util.prepend_param_field(self.NEXTHOP_ID_FIELD), nexthop_id), - (util.prepend_param_field(self.ROUTE_METADATA_FIELD), metadata), - ] - else: - attr_list = [(self.ACTION_FIELD, action)] - route_key = self.generate_app_db_key(vrf_id, dst) - self.set_app_db_entry(route_key, attr_list) - return route_key, attr_list - - # Fetch the asic_db_key for the first newly created route entry from created - # routes in ASIC db. This API should only be used when only one key is - # expected to be created after original entries. - # Original route entries in asic db must be fetched using - # 'get_original_redis_entries' before fetching asic db key of newly created - # route. - def get_newly_created_asic_db_key(self): - route_entries = util.get_keys(self.asic_db, self.ASIC_DB_TBL_NAME) - for key in route_entries: - if ( - key - not in self._original_entries[ - "%s:%s" % (self.asic_db, self.ASIC_DB_TBL_NAME) - ] - ): - asic_db_key = key - break - return asic_db_key - - def get_original_appl_db_entries_count(self): - return len( - self._original_entries[ - "%s:%s" % (self.appl_db, (self.APP_DB_TBL_NAME + ":" + self.TBL_NAME)) - ] - ) - - def get_original_appl_state_db_entries_count(self): - return len( - self._original_entries[ - "%s:%s" - % (self.appl_state_db, (self.APP_DB_TBL_NAME + ":" + self.TBL_NAME)) - ] - ) - - def get_original_asic_db_entries_count(self): - return len( - self._original_entries["%s:%s" % (self.asic_db, self.ASIC_DB_TBL_NAME)] - ) diff --git a/tests/p4rt/l3_admit.py b/tests/p4rt/l3_admit.py deleted file mode 100644 index 18fcc88482..0000000000 --- a/tests/p4rt/l3_admit.py +++ /dev/null @@ -1,84 +0,0 @@ -from swsscommon import swsscommon - -import util -import json - - -class P4RtL3AdmitWrapper(util.DBInterface): - """Interface to interact with APP DB and ASIC DB tables for P4RT L3 Admit object.""" - - # database and SAI constants - APP_DB_TBL_NAME = swsscommon.APP_P4RT_TABLE_NAME - TBL_NAME = "FIXED_L3_ADMIT_TABLE" - ASIC_DB_TBL_NAME = "ASIC_STATE:SAI_OBJECT_TYPE_MY_MAC" - SAI_ATTR_DST_MAC = "SAI_MY_MAC_ATTR_MAC_ADDRESS" - SAI_ATTR_DST_MAC_MASK = "SAI_MY_MAC_ATTR_MAC_ADDRESS_MASK" - SAI_ATTR_PORT_ID = "SAI_MY_MAC_ATTR_PORT_ID" - SAI_ATTR_PRIORITY = "SAI_MY_MAC_ATTR_PRIORITY" - - # attribute fields for l3 admit object in APP DB - IN_PORT_FIELD = "in_port" - DST_MAC_FIELD = "dst_mac" - PRIORITY = "priority" - L3_ADMIT_ACTION = "admit_to_l3" - - def generate_app_db_key(self, dst_mac, priority, port_id=None): - d = {} - d[util.prepend_match_field(self.DST_MAC_FIELD)] = dst_mac - d[self.PRIORITY] = priority - if port_id != "" and port_id != None: - d[util.prepend_match_field(self.IN_PORT_FIELD)] = port_id - key = json.dumps(d, separators=(",", ":")) - return self.TBL_NAME + ":" + key - - # create default l3 admit - def create_l3_admit( - self, dst_mac, priority, port_id=None - ): - attr_list = [ - (self.ACTION_FIELD, self.L3_ADMIT_ACTION), - ] - l3_admit_key = self.generate_app_db_key(dst_mac, priority, port_id) - self.set_app_db_entry(l3_admit_key, attr_list) - return l3_admit_key, attr_list - - def get_original_appl_db_entries_count(self): - return len( - self._original_entries[ - "%s:%s" % (self.appl_db, (self.APP_DB_TBL_NAME + ":" + self.TBL_NAME)) - ] - ) - - def get_original_appl_state_db_entries_count(self): - return len( - self._original_entries[ - "%s:%s" - % (self.appl_state_db, (self.APP_DB_TBL_NAME + ":" + self.TBL_NAME)) - ] - ) - - def get_original_asic_db_entries_count(self): - return len( - self._original_entries[ - "%s:%s" % (self.asic_db, self.ASIC_DB_TBL_NAME) - ] - ) - - # Fetch the asic_db_key for the first newly created my mac entry from created - # my mac in ASIC db. This API should only be used when only one key is - # expected to be created after original entries. - # Original my mac entries in asic db must be fetched using - # 'get_original_redis_entries' before fetching asic db key of newly created - # my mac entries. - def get_newly_created_asic_db_key(self): - l3_admit_entries = util.get_keys(self.asic_db, self.ASIC_DB_TBL_NAME) - for key in l3_admit_entries: - if ( - key - not in self._original_entries[ - "%s:%s" % (self.asic_db, self.ASIC_DB_TBL_NAME) - ] - ): - asic_db_key = key - break - return asic_db_key \ No newline at end of file diff --git a/tests/p4rt/tables_definition.py b/tests/p4rt/tables_definition.py deleted file mode 100644 index fe3a077def..0000000000 --- a/tests/p4rt/tables_definition.py +++ /dev/null @@ -1,35 +0,0 @@ -from swsscommon import swsscommon - -import util -import json - - -class P4RtTableDefinitionWrapper(util.DBInterface): - """Interface to interact with APP DB for P4RT tables definition.""" - - # database constants - APP_DB_TBL_NAME = swsscommon.APP_P4RT_TABLE_NAME - TBL_NAME = swsscommon.APP_P4RT_TABLES_DEFINITION_TABLE_NAME - - # attribute fields for tables definition object - INFO_FIELD = "info" - - # tables definition object's attribute values - INFO_VALUE = "{\"tables\":[{\"actions\":[{\"alias\":\"drop\",\"id\":16777222,\"name\":\"ingress.routing.drop\",\"params\":null},{\"alias\":\"set_nexthop_id\",\"id\":16777221,\"name\":\"ingress.routing.set_nexthop_id\",\"params\":[{\"bitwidth\":0,\"format\":\"STRING\",\"id\":1,\"name\":\"nexthop_id\",\"references\":[{\"match\":\"nexthop_id\",\"table\":\"nexthop_table\"}]}]},{\"alias\":\"set_wcmp_group_id\",\"id\":16777220,\"name\":\"ingress.routing.set_wcmp_group_id\",\"params\":[{\"bitwidth\":0,\"format\":\"STRING\",\"id\":1,\"name\":\"wcmp_group_id\",\"references\":[{\"match\":\"wcmp_group_id\",\"table\":\"wcmp_group_table\"}]}]}],\"alias\":\"vipv4_table\",\"counter/unit\":\"BOTH\",\"id\":33554500,\"matchFields\":[{\"bitwidth\":32,\"format\":\"IPV4\",\"id\":1,\"name\":\"ipv4_dst\",\"references\":null}],\"name\":\"ingress.routing.vipv4_table\"}]}" - - - def generate_app_db_key(self, context): - d = {} - d["context"] = context - key = json.dumps(d, separators=(",", ":")) - return self.TBL_NAME + ":" + key - - - # create tables definition set - def create_tables_definition(self, info=None): - info = info or self.INFO_VALUE - attr_list = [(self.INFO_FIELD, info)] - tables_definition_key = self.generate_app_db_key("0") - self.set_app_db_entry(tables_definition_key, attr_list) - return tables_definition_key, attr_list - diff --git a/tests/p4rt/test_l3.py b/tests/p4rt/test_l3.py deleted file mode 100644 index 0536e88b4f..0000000000 --- a/tests/p4rt/test_l3.py +++ /dev/null @@ -1,2369 +0,0 @@ -from swsscommon import swsscommon - -import pytest -import json -import util -import l3 -import test_vrf - - -class TestP4RTL3(object): - def _set_up(self, dvs): - self._p4rt_router_intf_obj = l3.P4RtRouterInterfaceWrapper() - self._p4rt_gre_tunnel_obj = l3.P4RtGreTunnelWrapper() - self._p4rt_neighbor_obj = l3.P4RtNeighborWrapper() - self._p4rt_nexthop_obj = l3.P4RtNextHopWrapper() - self._p4rt_route_obj = l3.P4RtRouteWrapper() - self._p4rt_wcmp_group_obj = l3.P4RtWcmpGroupWrapper() - self._vrf_obj = test_vrf.TestVrf() - - self._p4rt_router_intf_obj.set_up_databases(dvs) - self._p4rt_gre_tunnel_obj.set_up_databases(dvs) - self._p4rt_neighbor_obj.set_up_databases(dvs) - self._p4rt_nexthop_obj.set_up_databases(dvs) - self._p4rt_route_obj.set_up_databases(dvs) - self._p4rt_wcmp_group_obj.set_up_databases(dvs) - self.response_consumer = swsscommon.NotificationConsumer( - self._p4rt_route_obj.appl_db, "APPL_DB_" + - swsscommon.APP_P4RT_TABLE_NAME + "_RESPONSE_CHANNEL" - ) - - def _set_vrf(self, dvs): - # Create VRF. - self._vrf_obj.setup_db(dvs) - self.vrf_id = "b4-traffic" - self.vrf_state = self._vrf_obj.vrf_create(dvs, self.vrf_id, [], {}) - - def _clean_vrf(self, dvs): - # Remove VRF. - self._vrf_obj.vrf_remove(dvs, self.vrf_id, self.vrf_state) - - def test_IPv4RouteWithNexthopAddUpdateDeletePass(self, dvs, testlog): - # Initialize L3 objects and database connectors. - self._set_up(dvs) - self._set_vrf(dvs) - - # Set IP type for route object. - self._p4rt_route_obj.set_ip_type("IPV4") - - # Maintain list of original Application and ASIC DB entries before - # adding new route. - db_list = ( - (self._p4rt_nexthop_obj.asic_db, - self._p4rt_nexthop_obj.ASIC_DB_TBL_NAME), - ) - self._p4rt_nexthop_obj.get_original_redis_entries(db_list) - db_list = ( - ( - self._p4rt_route_obj.appl_db, - "%s:%s" - % (self._p4rt_route_obj.APP_DB_TBL_NAME, self._p4rt_route_obj.TBL_NAME), - ), - (self._p4rt_route_obj.asic_db, self._p4rt_route_obj.ASIC_DB_TBL_NAME), - ) - self._p4rt_route_obj.get_original_redis_entries(db_list) - - # Fetch the original key to oid information from Redis DB. - key_to_oid_helper = util.KeyToOidDBHelper(dvs) - _, original_key_oid_info = key_to_oid_helper.get_db_info() - - # Create router interface. - ( - router_interface_id, - router_intf_key, - attr_list, - ) = self._p4rt_router_intf_obj.create_router_interface() - util.verify_response( - self.response_consumer, router_intf_key, attr_list, "SWSS_RC_SUCCESS" - ) - - # Verify that P4RT key to OID count incremented by 1 in Redis DB. - count = 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Create neighbor. - neighbor_id, neighbor_key, attr_list = self._p4rt_neighbor_obj.create_neighbor() - util.verify_response( - self.response_consumer, neighbor_key, attr_list, "SWSS_RC_SUCCESS" - ) - - # Verify that P4RT key to OID count incremented by 1 in Redis DB. - count += 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Create nexthop. - nexthop_id, nexthop_key, attr_list = self._p4rt_nexthop_obj.create_next_hop() - util.verify_response( - self.response_consumer, nexthop_key, attr_list, "SWSS_RC_SUCCESS" - ) - # get nexthop_oid of newly created nexthop - nexthop_oid = self._p4rt_nexthop_obj.get_newly_created_nexthop_oid() - assert nexthop_oid is not None - - # Verify that P4RT key to OID count incremented by 1 in Redis DB. - count += 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Create route entry. - route_key, attr_list = self._p4rt_route_obj.create_route(nexthop_id) - util.verify_response( - self.response_consumer, route_key, attr_list, "SWSS_RC_SUCCESS" - ) - - # Verify that P4RT key to OID count incremented by 1 in Redis DB. - count += 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Query application database for route entries. - route_entries = util.get_keys( - self._p4rt_route_obj.appl_db, - self._p4rt_route_obj.APP_DB_TBL_NAME + ":" + self._p4rt_route_obj.TBL_NAME, - ) - assert len(route_entries) == ( - self._p4rt_route_obj.get_original_appl_db_entries_count() + 1 - ) - - # Query application database for newly created route key. - (status, fvs) = util.get_key( - self._p4rt_route_obj.appl_db, - self._p4rt_route_obj.APP_DB_TBL_NAME, - route_key, - ) - assert status == True - util.verify_attr(fvs, attr_list) - - # Query ASIC database for route entries. - route_entries = util.get_keys( - self._p4rt_route_obj.asic_db, self._p4rt_route_obj.ASIC_DB_TBL_NAME - ) - assert len(route_entries) == ( - self._p4rt_route_obj.get_original_asic_db_entries_count() + 1 - ) - - # Query ASIC database for newly created route key. - asic_db_key = self._p4rt_route_obj.get_newly_created_asic_db_key() - assert asic_db_key is not None - (status, fvs) = util.get_key( - self._p4rt_route_obj.asic_db, - self._p4rt_route_obj.ASIC_DB_TBL_NAME, - asic_db_key, - ) - assert status == True - attr_list = [(self._p4rt_route_obj.SAI_ATTR_NEXTHOP_ID, nexthop_oid)] - util.verify_attr(fvs, attr_list) - - # Update route entry to set_nexthop_id_and_metadata. - route_key, attr_list = self._p4rt_route_obj.create_route( - action="set_nexthop_id_and_metadata", metadata="2" - ) - util.verify_response( - self.response_consumer, route_key, attr_list, "SWSS_RC_SUCCESS" - ) - - # Verify that P4RT key to OID count did not change in Redis DB. - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Query application database for route entries. - route_entries = util.get_keys( - self._p4rt_route_obj.appl_db, - self._p4rt_route_obj.APP_DB_TBL_NAME + ":" + self._p4rt_route_obj.TBL_NAME, - ) - assert len(route_entries) == ( - self._p4rt_route_obj.get_original_appl_db_entries_count() + 1 - ) - - # Query application database for the updated route key. - (status, fvs) = util.get_key( - self._p4rt_route_obj.appl_db, - self._p4rt_route_obj.APP_DB_TBL_NAME, - route_key, - ) - assert status == True - attr_list_appl_db = [ - (self._p4rt_route_obj.ACTION_FIELD, "set_nexthop_id_and_metadata"), - ( - util.prepend_param_field( - self._p4rt_route_obj.NEXTHOP_ID_FIELD), - nexthop_id, - ), - ( - util.prepend_param_field( - self._p4rt_route_obj.ROUTE_METADATA_FIELD), - "2", - ), - ] - util.verify_attr(fvs, attr_list_appl_db) - - # Query ASIC database for route entries. - route_entries = util.get_keys( - self._p4rt_route_obj.asic_db, self._p4rt_route_obj.ASIC_DB_TBL_NAME - ) - assert len(route_entries) == ( - self._p4rt_route_obj.get_original_asic_db_entries_count() + 1 - ) - - # Query ASIC database for the updated route key. - asic_db_key = self._p4rt_route_obj.get_newly_created_asic_db_key() - assert asic_db_key is not None - (status, fvs) = util.get_key( - self._p4rt_route_obj.asic_db, - self._p4rt_route_obj.ASIC_DB_TBL_NAME, - asic_db_key, - ) - assert status == True - attr_list = [ - (self._p4rt_route_obj.SAI_ATTR_NEXTHOP_ID, nexthop_oid), - (self._p4rt_route_obj.SAI_ATTR_META_DATA, "2"), - ] - util.verify_attr(fvs, attr_list) - - # Update route entry to drop. - route_key, attr_list = self._p4rt_route_obj.create_route(action="drop") - util.verify_response( - self.response_consumer, route_key, attr_list, "SWSS_RC_SUCCESS" - ) - - # Verify that P4RT key to OID count did not change in Redis DB. - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Query application database for route entries. - route_entries = util.get_keys( - self._p4rt_route_obj.appl_db, - self._p4rt_route_obj.APP_DB_TBL_NAME + ":" + self._p4rt_route_obj.TBL_NAME, - ) - assert len(route_entries) == ( - self._p4rt_route_obj.get_original_appl_db_entries_count() + 1 - ) - - # Query application database for the updated route key. - (status, fvs) = util.get_key( - self._p4rt_route_obj.appl_db, - self._p4rt_route_obj.APP_DB_TBL_NAME, - route_key, - ) - assert status == True - util.verify_attr(fvs, attr_list) - - # Query ASIC database for route entries. - route_entries = util.get_keys( - self._p4rt_route_obj.asic_db, self._p4rt_route_obj.ASIC_DB_TBL_NAME - ) - assert len(route_entries) == ( - self._p4rt_route_obj.get_original_asic_db_entries_count() + 1 - ) - - # Query ASIC database for the updated route key. - asic_db_key = self._p4rt_route_obj.get_newly_created_asic_db_key() - assert asic_db_key is not None - (status, fvs) = util.get_key( - self._p4rt_route_obj.asic_db, - self._p4rt_route_obj.ASIC_DB_TBL_NAME, - asic_db_key, - ) - assert status == True - attr_list = [ - (self._p4rt_route_obj.SAI_ATTR_NEXTHOP_ID, "oid:0x0"), - ( - self._p4rt_route_obj.SAI_ATTR_PACKET_ACTION, - self._p4rt_route_obj.SAI_ATTR_PACKET_ACTION_DROP, - ), - (self._p4rt_route_obj.SAI_ATTR_META_DATA, "0"), - ] - util.verify_attr(fvs, attr_list) - - # Remove route entry. - self._p4rt_route_obj.remove_app_db_entry(route_key) - util.verify_response(self.response_consumer, - route_key, [], "SWSS_RC_SUCCESS") - - # Verify that P4RT key to OID count decremented by 1 in Redis DB. - count -= 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Remove nexthop. - self._p4rt_nexthop_obj.remove_app_db_entry(nexthop_key) - util.verify_response(self.response_consumer, - nexthop_key, [], "SWSS_RC_SUCCESS") - - # Verify that P4RT key to OID count decremented by 1 in Redis DB. - count -= 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Remove neighbor. - self._p4rt_neighbor_obj.remove_app_db_entry(neighbor_key) - util.verify_response( - self.response_consumer, neighbor_key, [], "SWSS_RC_SUCCESS" - ) - - # Verify that P4RT key to OID count decremented by 1 in Redis DB. - count -= 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Remove router interface. - self._p4rt_router_intf_obj.remove_app_db_entry(router_intf_key) - util.verify_response( - self.response_consumer, router_intf_key, [], "SWSS_RC_SUCCESS" - ) - - # Verify that P4RT key to OID count is same as the original count. - status, fvs = key_to_oid_helper.get_db_info() - assert status == False - assert len(fvs) == len(original_key_oid_info) - - # Query application database for route entries. - route_entries = util.get_keys( - self._p4rt_route_obj.appl_db, - self._p4rt_route_obj.APP_DB_TBL_NAME + ":" + self._p4rt_route_obj.TBL_NAME, - ) - assert len(route_entries) == ( - self._p4rt_route_obj.get_original_appl_db_entries_count() - ) - - # Verify that the route_key no longer exists in application database. - (status, fsv) = util.get_key( - self._p4rt_route_obj.appl_db, - self._p4rt_route_obj.APP_DB_TBL_NAME, - route_key, - ) - assert status == False - - # Query ASIC database for route entries. - route_entries = util.get_keys( - self._p4rt_route_obj.asic_db, self._p4rt_route_obj.ASIC_DB_TBL_NAME - ) - assert len(route_entries) == ( - self._p4rt_route_obj.get_original_asic_db_entries_count() - ) - - # Verify that removed route no longer exists in ASIC database. - (status, fvs) = util.get_key( - self._p4rt_route_obj.asic_db, - self._p4rt_route_obj.ASIC_DB_TBL_NAME, - asic_db_key, - ) - assert status == False - self._clean_vrf(dvs) - - def test_IPv6WithWcmpRouteAddUpdateDeletePass(self, dvs, testlog): - # Initialize L3 objects and database connectors. - self._set_up(dvs) - self._set_vrf(dvs) - - # Set IP type for route object. - self._p4rt_route_obj.set_ip_type("IPV6") - - # Maintain list of original Application and ASIC DB entries before - # adding new route. - db_list = ( - ( - self._p4rt_route_obj.appl_db, - "%s:%s" - % (self._p4rt_route_obj.APP_DB_TBL_NAME, self._p4rt_route_obj.TBL_NAME), - ), - (self._p4rt_route_obj.asic_db, self._p4rt_route_obj.ASIC_DB_TBL_NAME), - ) - self._p4rt_route_obj.get_original_redis_entries(db_list) - db_list = ( - (self._p4rt_nexthop_obj.asic_db, - self._p4rt_nexthop_obj.ASIC_DB_TBL_NAME), - ) - self._p4rt_nexthop_obj.get_original_redis_entries(db_list) - db_list = ( - ( - self._p4rt_wcmp_group_obj.appl_db, - "%s:%s" - % ( - self._p4rt_wcmp_group_obj.APP_DB_TBL_NAME, - self._p4rt_wcmp_group_obj.TBL_NAME, - ), - ), - ( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_TBL_NAME, - ), - ( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_MEMBER_TBL_NAME, - ), - ) - self._p4rt_wcmp_group_obj.get_original_redis_entries(db_list) - - # Fetch the original key to oid information from Redis DB. - key_to_oid_helper = util.KeyToOidDBHelper(dvs) - _, original_key_oid_info = key_to_oid_helper.get_db_info() - - # Create router interface. - ( - router_interface_id, - router_intf_key, - attr_list, - ) = self._p4rt_router_intf_obj.create_router_interface() - util.verify_response( - self.response_consumer, router_intf_key, attr_list, "SWSS_RC_SUCCESS" - ) - - # Verify that P4RT key to OID count incremented by 1 in Redis DB. - count = 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Create neighbor. - neighbor_id, neighbor_key, attr_list = self._p4rt_neighbor_obj.create_neighbor( - ipv4=False - ) - util.verify_response( - self.response_consumer, neighbor_key, attr_list, "SWSS_RC_SUCCESS" - ) - - # Verify that P4RT key to OID count incremented by 1 in Redis DB. - count += 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Create nexthop. - nexthop_id, nexthop_key, attr_list = self._p4rt_nexthop_obj.create_next_hop( - ipv4=False - ) - util.verify_response( - self.response_consumer, nexthop_key, attr_list, "SWSS_RC_SUCCESS" - ) - # Get the oid of the newly created nexthop. - nexthop_oid = self._p4rt_nexthop_obj.get_newly_created_nexthop_oid() - assert nexthop_oid is not None - - # Verify that P4RT key to OID count incremented by 1 in Redis DB. - count += 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Create wcmp group. - ( - wcmp_group_id, - wcmp_group_key, - attr_list, - ) = self._p4rt_wcmp_group_obj.create_wcmp_group() - util.verify_response( - self.response_consumer, wcmp_group_key, attr_list, "SWSS_RC_SUCCESS" - ) - - # Verify that P4RT key to OID count incremented by 2 in Redis DB - # (1 each for WCMP group and member). - count += 2 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Query application database for wcmp group entries. - wcmp_group_entries = util.get_keys( - self._p4rt_wcmp_group_obj.appl_db, - self._p4rt_wcmp_group_obj.APP_DB_TBL_NAME - + ":" - + self._p4rt_wcmp_group_obj.TBL_NAME, - ) - assert len(wcmp_group_entries) == ( - self._p4rt_wcmp_group_obj.get_original_appl_db_entries_count() + 1 - ) - - # Query application database for newly created wcmp group key. - (status, fvs) = util.get_key( - self._p4rt_wcmp_group_obj.appl_db, - self._p4rt_wcmp_group_obj.APP_DB_TBL_NAME, - wcmp_group_key, - ) - assert status == True - util.verify_attr(fvs, attr_list) - - # Query ASIC database for wcmp group entries. - wcmp_group_entries = util.get_keys( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_TBL_NAME, - ) - assert len(wcmp_group_entries) == ( - self._p4rt_wcmp_group_obj.get_original_asic_db_group_entries_count() + 1 - ) - - # Query ASIC database for newly created wcmp group oid. - wcmp_group_oid = self._p4rt_wcmp_group_obj.get_newly_created_wcmp_group_oid() - assert wcmp_group_oid is not None - attr_list = [ - ( - self._p4rt_wcmp_group_obj.SAI_ATTR_GROUP_TYPE, - self._p4rt_wcmp_group_obj.SAI_NEXT_HOP_GROUP_TYPE_DYNAMIC_UNORDERED_ECMP, - ) - ] - (status, fvs) = util.get_key( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_TBL_NAME, - wcmp_group_oid, - ) - assert status == True - util.verify_attr(fvs, attr_list) - - # Query ASIC database for wcmp group member entries. - wcmp_group_member_entries = util.get_keys( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_MEMBER_TBL_NAME, - ) - assert len(wcmp_group_member_entries) == ( - self._p4rt_wcmp_group_obj.get_original_asic_db_member_entries_count() + 1 - ) - - # Query ASIC database for newly crated wcmp group member key. - asic_db_group_member_key = ( - self._p4rt_wcmp_group_obj.get_newly_created_wcmp_group_member_asic_db_key() - ) - assert asic_db_group_member_key is not None - attr_list = [ - ( - self._p4rt_wcmp_group_obj.SAI_ATTR_GROUP_MEMBER_NEXTHOP_GROUP_ID, - wcmp_group_oid, - ), - (self._p4rt_wcmp_group_obj.SAI_ATTR_GROUP_MEMBER_NEXTHOP_ID, nexthop_oid), - ( - self._p4rt_wcmp_group_obj.SAI_ATTR_GROUP_MEMBER_WEIGHT, - str(self._p4rt_wcmp_group_obj.DEFAULT_WEIGHT), - ), - ] - (status, fvs) = util.get_key( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_MEMBER_TBL_NAME, - asic_db_group_member_key, - ) - assert status == True - util.verify_attr(fvs, attr_list) - - # Create route entry. - route_key, attr_list = self._p4rt_route_obj.create_route( - wcmp_group_id=wcmp_group_id, action="set_wcmp_group_id", dst="2001:db8::/32" - ) - util.verify_response( - self.response_consumer, route_key, attr_list, "SWSS_RC_SUCCESS" - ) - - # Verify that P4RT key to OID count incremented by 1 in Redis DB. - count += 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Query application database for route entries. - route_entries = util.get_keys( - self._p4rt_route_obj.appl_db, - self._p4rt_route_obj.APP_DB_TBL_NAME + ":" + self._p4rt_route_obj.TBL_NAME, - ) - assert len(route_entries) == ( - self._p4rt_route_obj.get_original_appl_db_entries_count() + 1 - ) - - # Query application database for newly created route key. - (status, fvs) = util.get_key( - self._p4rt_route_obj.appl_db, - self._p4rt_route_obj.APP_DB_TBL_NAME, - route_key, - ) - assert status == True - util.verify_attr(fvs, attr_list) - - # Query ASIC database for route entries. - route_entries = util.get_keys( - self._p4rt_route_obj.asic_db, self._p4rt_route_obj.ASIC_DB_TBL_NAME - ) - assert len(route_entries) == ( - self._p4rt_route_obj.get_original_asic_db_entries_count() + 1 - ) - - # Query ASIC database for newly created route key. - asic_db_key = self._p4rt_route_obj.get_newly_created_asic_db_key() - assert asic_db_key is not None - (status, fvs) = util.get_key( - self._p4rt_route_obj.asic_db, - self._p4rt_route_obj.ASIC_DB_TBL_NAME, - asic_db_key, - ) - assert status == True - attr_list = [ - (self._p4rt_route_obj.SAI_ATTR_NEXTHOP_ID, wcmp_group_oid)] - util.verify_attr(fvs, attr_list) - - # Update route entry to drop action - route_key, attr_list = self._p4rt_route_obj.create_route( - action="drop", dst="2001:db8::/32" - ) - util.verify_response( - self.response_consumer, route_key, attr_list, "SWSS_RC_SUCCESS" - ) - - # Verify that P4RT key to OID count did not change in Redis DB. - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Query application database for route entries. - route_entries = util.get_keys( - self._p4rt_route_obj.appl_db, - self._p4rt_route_obj.APP_DB_TBL_NAME + ":" + self._p4rt_route_obj.TBL_NAME, - ) - assert len(route_entries) == ( - self._p4rt_route_obj.get_original_appl_db_entries_count() + 1 - ) - - # Query application database for the updated route key. - (status, fvs) = util.get_key( - self._p4rt_route_obj.appl_db, - self._p4rt_route_obj.APP_DB_TBL_NAME, - route_key, - ) - assert status == True - util.verify_attr(fvs, attr_list) - - # Query ASIC database for route entries. - route_entries = util.get_keys( - self._p4rt_route_obj.asic_db, self._p4rt_route_obj.ASIC_DB_TBL_NAME - ) - assert len(route_entries) == ( - self._p4rt_route_obj.get_original_asic_db_entries_count() + 1 - ) - - # Query ASIC database for the updated route key. - asic_db_key = self._p4rt_route_obj.get_newly_created_asic_db_key() - assert asic_db_key is not None - (status, fvs) = util.get_key( - self._p4rt_route_obj.asic_db, - self._p4rt_route_obj.ASIC_DB_TBL_NAME, - asic_db_key, - ) - assert status == True - attr_list = [ - (self._p4rt_route_obj.SAI_ATTR_NEXTHOP_ID, "oid:0x0"), - ( - self._p4rt_route_obj.SAI_ATTR_PACKET_ACTION, - self._p4rt_route_obj.SAI_ATTR_PACKET_ACTION_DROP, - ), - ] - util.verify_attr(fvs, attr_list) - - # Update route entry to trap action. - route_key, attr_list = self._p4rt_route_obj.create_route( - action="trap", dst="2001:db8::/32" - ) - util.verify_response( - self.response_consumer, route_key, attr_list, "SWSS_RC_SUCCESS" - ) - - # Verify that P4RT key to OID count did not change in Redis DB. - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Query application database for route entries. - route_entries = util.get_keys( - self._p4rt_route_obj.appl_db, - self._p4rt_route_obj.APP_DB_TBL_NAME + ":" + self._p4rt_route_obj.TBL_NAME, - ) - assert len(route_entries) == ( - self._p4rt_route_obj.get_original_appl_db_entries_count() + 1 - ) - - # Query application database for the updated route key. - (status, fvs) = util.get_key( - self._p4rt_route_obj.appl_db, - self._p4rt_route_obj.APP_DB_TBL_NAME, - route_key, - ) - assert status == True - util.verify_attr(fvs, attr_list) - - # Query ASIC database for route entries. - route_entries = util.get_keys( - self._p4rt_route_obj.asic_db, self._p4rt_route_obj.ASIC_DB_TBL_NAME - ) - assert len(route_entries) == ( - self._p4rt_route_obj.get_original_asic_db_entries_count() + 1 - ) - - # Query ASIC database for the updated route key. - asic_db_key = self._p4rt_route_obj.get_newly_created_asic_db_key() - assert asic_db_key is not None - (status, fvs) = util.get_key( - self._p4rt_route_obj.asic_db, - self._p4rt_route_obj.ASIC_DB_TBL_NAME, - asic_db_key, - ) - assert status == True - attr_list = [ - (self._p4rt_route_obj.SAI_ATTR_NEXTHOP_ID, "oid:0x0"), - ( - self._p4rt_route_obj.SAI_ATTR_PACKET_ACTION, - self._p4rt_route_obj.SAI_ATTR_PACKET_ACTION_TRAP, - ), - ] - util.verify_attr(fvs, attr_list) - - # Remove route entry. - self._p4rt_route_obj.remove_app_db_entry(route_key) - util.verify_response(self.response_consumer, - route_key, [], "SWSS_RC_SUCCESS") - - # Verify that P4RT key to OID count decremented by 1 in Redis DB. - count -= 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Remove wcmp group entry. - self._p4rt_wcmp_group_obj.remove_app_db_entry(wcmp_group_key) - util.verify_response( - self.response_consumer, wcmp_group_key, [], "SWSS_RC_SUCCESS" - ) - - # Verify that P4RT key to OID count decremented by 2 in Redis DB - # (1 each for WCMP group and member). - count -= 2 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Remove nexthop. - self._p4rt_nexthop_obj.remove_app_db_entry(nexthop_key) - util.verify_response(self.response_consumer, - nexthop_key, [], "SWSS_RC_SUCCESS") - - # Verify that P4RT key to OID count decremented by 1 in Redis DB. - count -= 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Remove neighbor. - self._p4rt_neighbor_obj.remove_app_db_entry(neighbor_key) - util.verify_response( - self.response_consumer, neighbor_key, [], "SWSS_RC_SUCCESS" - ) - - # Verify that P4RT key to OID count decremented by 1 in Redis DB. - count -= 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Remove router interface. - self._p4rt_router_intf_obj.remove_app_db_entry(router_intf_key) - util.verify_response( - self.response_consumer, router_intf_key, [], "SWSS_RC_SUCCESS" - ) - - # Verify that P4RT key to OID count is same as original count. - status, fvs = key_to_oid_helper.get_db_info() - assert status == False - assert len(fvs) == len(original_key_oid_info) - - # Query application database for route entries. - route_entries = util.get_keys( - self._p4rt_route_obj.appl_db, - self._p4rt_route_obj.APP_DB_TBL_NAME + ":" + self._p4rt_route_obj.TBL_NAME, - ) - assert len(route_entries) == ( - self._p4rt_route_obj.get_original_appl_db_entries_count() - ) - - # Verify that the route_key no longer exists in application database. - (status, fsv) = util.get_key( - self._p4rt_route_obj.appl_db, - self._p4rt_route_obj.APP_DB_TBL_NAME, - route_key, - ) - assert status == False - - # Query ASIC database for route entries. - route_entries = util.get_keys( - self._p4rt_route_obj.asic_db, self._p4rt_route_obj.ASIC_DB_TBL_NAME - ) - assert len(route_entries) == ( - self._p4rt_route_obj.get_original_asic_db_entries_count() - ) - - # Verify that removed route no longer exists in ASIC database. - (status, fvs) = util.get_key( - self._p4rt_route_obj.asic_db, - self._p4rt_route_obj.ASIC_DB_TBL_NAME, - asic_db_key, - ) - assert status == False - - # Query application database for wcmp group entries. - wcmp_group_entries = util.get_keys( - self._p4rt_wcmp_group_obj.appl_db, - self._p4rt_wcmp_group_obj.APP_DB_TBL_NAME - + ":" - + self._p4rt_wcmp_group_obj.TBL_NAME, - ) - assert len(wcmp_group_entries) == ( - self._p4rt_wcmp_group_obj.get_original_appl_db_entries_count() - ) - - # Verify that the route_key no longer exists in application database. - (status, fsv) = util.get_key( - self._p4rt_wcmp_group_obj.appl_db, - self._p4rt_wcmp_group_obj.APP_DB_TBL_NAME, - wcmp_group_key, - ) - assert status == False - - # Query ASIC database for wcmp group entries. - wcmp_group_entries = util.get_keys( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_TBL_NAME, - ) - assert len(wcmp_group_entries) == ( - self._p4rt_wcmp_group_obj.get_original_asic_db_group_entries_count() - ) - - # Verify that removed wcmp group no longer exists in ASIC database. - (status, fvs) = util.get_key( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_TBL_NAME, - wcmp_group_oid, - ) - assert status == False - - # Query ASIC database for wcmp group member entries. - wcmp_group_member_entries = util.get_keys( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_MEMBER_TBL_NAME, - ) - assert len(wcmp_group_member_entries) == ( - self._p4rt_wcmp_group_obj.get_original_asic_db_member_entries_count() - ) - - # Verify that removed wcmp group member no longer exists in ASIC - # database. - (status, fvs) = util.get_key( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_MEMBER_TBL_NAME, - asic_db_group_member_key, - ) - assert status == False - - self._clean_vrf(dvs) - - def test_NexthopWithGreTunnelAddDeletePass(self, dvs, testlog): - # Initialize L3 objects and database connectors. - self._set_up(dvs) - self._set_vrf(dvs) - - # Maintain list of original Application and ASIC DB entries before - # adding new entries. - db_list = ( - ( - self._p4rt_nexthop_obj.appl_db, - "%s:%s" - % ( - self._p4rt_nexthop_obj.APP_DB_TBL_NAME, - self._p4rt_nexthop_obj.TBL_NAME, - ), - ), - (self._p4rt_nexthop_obj.asic_db, - self._p4rt_nexthop_obj.ASIC_DB_TBL_NAME), - ) - self._p4rt_nexthop_obj.get_original_redis_entries(db_list) - db_list = ( - ( - self._p4rt_gre_tunnel_obj.appl_db, - "%s:%s" - % ( - self._p4rt_gre_tunnel_obj.APP_DB_TBL_NAME, - self._p4rt_gre_tunnel_obj.TBL_NAME, - ), - ), - (self._p4rt_gre_tunnel_obj.asic_db, - self._p4rt_gre_tunnel_obj.ASIC_DB_TBL_NAME), - ) - self._p4rt_gre_tunnel_obj.get_original_redis_entries(db_list) - db_list = ( - (self._p4rt_router_intf_obj.asic_db, - self._p4rt_router_intf_obj.ASIC_DB_TBL_NAME), - ) - self._p4rt_router_intf_obj.get_original_redis_entries(db_list) - - # Fetch the original key to oid information from Redis DB. - key_to_oid_helper = util.KeyToOidDBHelper(dvs) - _, original_key_oid_info = key_to_oid_helper.get_db_info() - - # Create router interface. - ( - router_interface_id, - router_intf_key, - attr_list, - ) = self._p4rt_router_intf_obj.create_router_interface() - util.verify_response( - self.response_consumer, router_intf_key, attr_list, "SWSS_RC_SUCCESS" - ) - - # get router_interface_oid of newly created router_intf - router_intf_oid = self._p4rt_router_intf_obj.get_newly_created_router_interface_oid() - assert router_intf_oid is not None - - # Verify that P4RT key to OID count incremented by 1 in Redis DB. - count = 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Create tunnel. - tunnel_id, tunnel_key, attr_list = self._p4rt_gre_tunnel_obj.create_gre_tunnel() - util.verify_response( - self.response_consumer, tunnel_key, attr_list, "SWSS_RC_SUCCESS" - ) - # get tunnel_oid of newly created tunnel - tunnel_oid = self._p4rt_gre_tunnel_obj.get_newly_created_tunnel_oid() - assert tunnel_oid is not None - # get overlay router_interface_oid of newly created router_intf - overlay_router_intf_oid = self._p4rt_router_intf_obj.get_newly_created_router_interface_oid( - set([router_intf_oid])) - assert overlay_router_intf_oid is not None - - # Verify that P4RT key to OID count incremented by 1 in Redis DB. - count += 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Query application database for tunnel entries. - tunnel_entries = util.get_keys( - self._p4rt_gre_tunnel_obj.appl_db, - self._p4rt_gre_tunnel_obj.APP_DB_TBL_NAME + - ":" + self._p4rt_gre_tunnel_obj.TBL_NAME, - ) - assert len(tunnel_entries) == ( - self._p4rt_gre_tunnel_obj.get_original_appl_db_entries_count() + 1 - ) - - # Query application database for newly created tunnel key. - (status, fvs) = util.get_key( - self._p4rt_gre_tunnel_obj.appl_db, - self._p4rt_gre_tunnel_obj.APP_DB_TBL_NAME, - tunnel_key, - ) - assert status == True - util.verify_attr(fvs, attr_list) - - # Query ASIC database for tunnel entries. - tunnel_entries = util.get_keys( - self._p4rt_gre_tunnel_obj.asic_db, self._p4rt_gre_tunnel_obj.ASIC_DB_TBL_NAME - ) - assert len(tunnel_entries) == ( - self._p4rt_gre_tunnel_obj.get_original_asic_db_entries_count() + 1 - ) - - # Query ASIC database for newly created nexthop key. - asic_db_key = self._p4rt_gre_tunnel_obj.get_newly_created_tunnel_oid() - assert asic_db_key is not None - (status, fvs) = util.get_key( - self._p4rt_gre_tunnel_obj.asic_db, - self._p4rt_gre_tunnel_obj.ASIC_DB_TBL_NAME, - asic_db_key, - ) - assert status == True - attr_list = [ - (self._p4rt_gre_tunnel_obj.SAI_ATTR_UNDERLAY_INTERFACE, router_intf_oid), - (self._p4rt_gre_tunnel_obj.SAI_ATTR_OVERLAY_INTERFACE, - overlay_router_intf_oid), - (self._p4rt_gre_tunnel_obj.SAI_ATTR_TYPE, "SAI_TUNNEL_TYPE_IPINIP_GRE"), - (self._p4rt_gre_tunnel_obj.SAI_ATTR_PEER_MODE, "SAI_TUNNEL_PEER_MODE_P2P"), - (self._p4rt_gre_tunnel_obj.SAI_ATTR_ENCAP_SRC_IP, - self._p4rt_gre_tunnel_obj.DEFAULT_ENCAP_SRC_IP), - (self._p4rt_gre_tunnel_obj.SAI_ATTR_ENCAP_DST_IP, - self._p4rt_gre_tunnel_obj.DEFAULT_ENCAP_DST_IP), - ] - util.verify_attr(fvs, attr_list) - - # Create neighbor. - neighbor_id, neighbor_key, attr_list = self._p4rt_neighbor_obj.create_neighbor() - util.verify_response( - self.response_consumer, neighbor_key, attr_list, "SWSS_RC_SUCCESS" - ) - - # Verify that P4RT key to OID count incremented by 1 in Redis DB. - count += 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Create tunnel nexthop. - nexthop_id, nexthop_key, attr_list = self._p4rt_nexthop_obj.create_next_hop( - tunnel_id=tunnel_id - ) - util.verify_response( - self.response_consumer, nexthop_key, attr_list, "SWSS_RC_SUCCESS" - ) - # get nexthop_oid of newly created nexthop - nexthop_oid = self._p4rt_nexthop_obj.get_newly_created_nexthop_oid() - assert nexthop_oid is not None - - # Verify that P4RT key to OID count incremented by 1 in Redis DB. - count += 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Query application database for nexthop entries. - nexthop_entries = util.get_keys( - self._p4rt_nexthop_obj.appl_db, - self._p4rt_nexthop_obj.APP_DB_TBL_NAME + ":" + self._p4rt_nexthop_obj.TBL_NAME, - ) - assert len(nexthop_entries) == ( - self._p4rt_nexthop_obj.get_original_appl_db_entries_count() + 1 - ) - - # Query application database for newly created nexthop key. - (status, fvs) = util.get_key( - self._p4rt_nexthop_obj.appl_db, - self._p4rt_nexthop_obj.APP_DB_TBL_NAME, - nexthop_key, - ) - assert status == True - util.verify_attr(fvs, attr_list) - - # Query ASIC database for nexthop entries. - nexthop_entries = util.get_keys( - self._p4rt_nexthop_obj.asic_db, self._p4rt_nexthop_obj.ASIC_DB_TBL_NAME - ) - assert len(nexthop_entries) == ( - self._p4rt_nexthop_obj.get_original_asic_db_entries_count() + 1 - ) - - # Query ASIC database for newly created nexthop key. - asic_db_key = self._p4rt_nexthop_obj.get_newly_created_nexthop_oid() - assert asic_db_key is not None - (status, fvs) = util.get_key( - self._p4rt_nexthop_obj.asic_db, - self._p4rt_nexthop_obj.ASIC_DB_TBL_NAME, - asic_db_key, - ) - assert status == True - attr_list = [ - (self._p4rt_nexthop_obj.SAI_ATTR_TUNNEL_OID, tunnel_oid), - (self._p4rt_nexthop_obj.SAI_ATTR_IP, - self._p4rt_nexthop_obj.DEFAULT_IPV4_NEIGHBOR_ID), - (self._p4rt_nexthop_obj.SAI_ATTR_TYPE, - self._p4rt_nexthop_obj.SAI_ATTR_TUNNEL_ENCAP) - ] - util.verify_attr(fvs, attr_list) - - # Remove nexthop. - self._p4rt_nexthop_obj.remove_app_db_entry(nexthop_key) - util.verify_response(self.response_consumer, - nexthop_key, [], "SWSS_RC_SUCCESS") - - # Verify that P4RT key to OID count decremented by 1 in Redis DB. - count -= 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Remove neighbor. - self._p4rt_neighbor_obj.remove_app_db_entry(neighbor_key) - util.verify_response( - self.response_consumer, neighbor_key, [], "SWSS_RC_SUCCESS" - ) - - # Verify that P4RT key to OID count decremented by 1 in Redis DB. - count -= 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Remove tunnel. - self._p4rt_gre_tunnel_obj.remove_app_db_entry(tunnel_key) - util.verify_response( - self.response_consumer, tunnel_key, [], "SWSS_RC_SUCCESS" - ) - - # Verify that P4RT key to OID count decremented by 1 in Redis DB. - count -= 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Remove router interface. - self._p4rt_router_intf_obj.remove_app_db_entry(router_intf_key) - util.verify_response( - self.response_consumer, router_intf_key, [], "SWSS_RC_SUCCESS" - ) - - # Verify that P4RT key to OID count is same as the original count. - status, fvs = key_to_oid_helper.get_db_info() - assert status == False - assert len(fvs) == len(original_key_oid_info) - - # Query application database for nexthop entries. - nexthop_entries = util.get_keys( - self._p4rt_nexthop_obj.appl_db, - self._p4rt_nexthop_obj.APP_DB_TBL_NAME + ":" + self._p4rt_nexthop_obj.TBL_NAME, - ) - assert len(nexthop_entries) == ( - self._p4rt_nexthop_obj.get_original_appl_db_entries_count() - ) - - # Verify that the nexthop_key no longer exists in application database. - (status, fsv) = util.get_key( - self._p4rt_nexthop_obj.appl_db, - self._p4rt_nexthop_obj.APP_DB_TBL_NAME, - nexthop_key, - ) - assert status == False - - # Query ASIC database for nexthop entries. - nexthop_entries = util.get_keys( - self._p4rt_nexthop_obj.asic_db, self._p4rt_nexthop_obj.ASIC_DB_TBL_NAME - ) - assert len(nexthop_entries) == ( - self._p4rt_nexthop_obj.get_original_asic_db_entries_count() - ) - - # Verify that removed nexthop no longer exists in ASIC database. - (status, fvs) = util.get_key( - self._p4rt_nexthop_obj.asic_db, - self._p4rt_nexthop_obj.ASIC_DB_TBL_NAME, - asic_db_key, - ) - assert status == False - - # Query application database for tunnel entries. - tunnel_entries = util.get_keys( - self._p4rt_gre_tunnel_obj.appl_db, - self._p4rt_gre_tunnel_obj.APP_DB_TBL_NAME + - ":" + self._p4rt_gre_tunnel_obj.TBL_NAME, - ) - assert len(tunnel_entries) == ( - self._p4rt_gre_tunnel_obj.get_original_appl_db_entries_count() - ) - - # Verify that the tunnel_key no longer exists in application database. - (status, fsv) = util.get_key( - self._p4rt_gre_tunnel_obj.appl_db, - self._p4rt_gre_tunnel_obj.APP_DB_TBL_NAME, - tunnel_key, - ) - assert status == False - - # Query ASIC database for tunnel entries. - runnel_entries = util.get_keys( - self._p4rt_gre_tunnel_obj.asic_db, self._p4rt_gre_tunnel_obj.ASIC_DB_TBL_NAME - ) - assert len(tunnel_entries) == ( - self._p4rt_gre_tunnel_obj.get_original_asic_db_entries_count() - ) - - # Verify that removed route no longer exists in ASIC database. - (status, fvs) = util.get_key( - self._p4rt_gre_tunnel_obj.asic_db, - self._p4rt_gre_tunnel_obj.ASIC_DB_TBL_NAME, - asic_db_key, - ) - assert status == False - self._clean_vrf(dvs) - - def test_IPv4RouteAddWithInvalidNexthopFail(self, dvs, testlog): - marker = dvs.add_log_marker() - - # Initialize L3 objects and database connectors. - self._set_up(dvs) - self._set_vrf(dvs) - - # Set IP type for route object. - self._p4rt_route_obj.set_ip_type("IPV4") - - # Maintain list of original Application and ASIC DB entries before - # adding new route. - db_list = ( - ( - self._p4rt_route_obj.appl_db, - "%s:%s" - % (self._p4rt_route_obj.APP_DB_TBL_NAME, self._p4rt_route_obj.TBL_NAME), - ), - (self._p4rt_route_obj.asic_db, self._p4rt_route_obj.ASIC_DB_TBL_NAME), - ) - self._p4rt_route_obj.get_original_redis_entries(db_list) - - # Create route entry using invalid nexthop (expect failure). - route_key, attr_list = self._p4rt_route_obj.create_route() - err_log = "[OrchAgent] Nexthop ID '8' does not exist" - util.verify_response( - self.response_consumer, route_key, attr_list, "SWSS_RC_NOT_FOUND", err_log - ) - - # Query application database for route entries. - route_entries = util.get_keys( - self._p4rt_route_obj.appl_db, - self._p4rt_route_obj.APP_DB_TBL_NAME + ":" + self._p4rt_route_obj.TBL_NAME, - ) - assert len(route_entries) == ( - self._p4rt_route_obj.get_original_appl_db_entries_count() + 1 - ) - - # Query application database for newly created route key. - (status, fvs) = util.get_key( - self._p4rt_route_obj.appl_db, - self._p4rt_route_obj.APP_DB_TBL_NAME, - route_key, - ) - assert status == True - util.verify_attr(fvs, attr_list) - - # Query ASIC database for route entries (no new ASIC DB entry should be - # created for route entry). - route_entries = util.get_keys( - self._p4rt_route_obj.asic_db, self._p4rt_route_obj.ASIC_DB_TBL_NAME - ) - assert len(route_entries) == ( - self._p4rt_route_obj.get_original_asic_db_entries_count() - ) - - # Remove route entry (expect failure). - self._p4rt_route_obj.remove_app_db_entry(route_key) - err_log = "[OrchAgent] Route entry does not exist" - util.verify_response( - self.response_consumer, route_key, [], "SWSS_RC_NOT_FOUND", err_log - ) - self._clean_vrf(dvs) - - def test_IPv6RouteAddWithInvalidWcmpFail(self, dvs, testlog): - marker = dvs.add_log_marker() - - # Initialize L3 objects and database connectors. - self._set_up(dvs) - self._set_vrf(dvs) - - # Set IP type for route object. - self._p4rt_route_obj.set_ip_type("IPV6") - - # Maintain list of original Application and ASIC DB entries before - # adding new route. - db_list = ( - ( - self._p4rt_route_obj.appl_db, - "%s:%s" - % (self._p4rt_route_obj.APP_DB_TBL_NAME, self._p4rt_route_obj.TBL_NAME), - ), - (self._p4rt_route_obj.asic_db, self._p4rt_route_obj.ASIC_DB_TBL_NAME), - ) - self._p4rt_route_obj.get_original_redis_entries(db_list) - - # Create route entry using invalid wcmp group (expect failure). - route_key, attr_list = self._p4rt_route_obj.create_route( - action="set_wcmp_group_id", wcmp_group_id="8" - ) - err_log = "[OrchAgent] WCMP group '8' does not exist" - util.verify_response( - self.response_consumer, route_key, attr_list, "SWSS_RC_NOT_FOUND", err_log - ) - - # Query application database for route entries - route_entries = util.get_keys( - self._p4rt_route_obj.appl_db, - self._p4rt_route_obj.APP_DB_TBL_NAME + ":" + self._p4rt_route_obj.TBL_NAME, - ) - assert len(route_entries) == ( - self._p4rt_route_obj.get_original_appl_db_entries_count() + 1 - ) - - # Query application database for newly created route key. - (status, fvs) = util.get_key( - self._p4rt_route_obj.appl_db, - self._p4rt_route_obj.APP_DB_TBL_NAME, - route_key, - ) - assert status == True - util.verify_attr(fvs, attr_list) - - # Query ASIC database for route entries (no new ASIC DB entry should be - # created for route entry). - route_entries = util.get_keys( - self._p4rt_route_obj.asic_db, self._p4rt_route_obj.ASIC_DB_TBL_NAME - ) - assert len(route_entries) == ( - self._p4rt_route_obj.get_original_asic_db_entries_count() - ) - - # Remove route entry (expect failure). - self._p4rt_route_obj.remove_app_db_entry(route_key) - err_log = "[OrchAgent] Route entry does not exist" - util.verify_response( - self.response_consumer, route_key, [], "SWSS_RC_NOT_FOUND", err_log - ) - self._clean_vrf(dvs) - - def test_PruneAndRestoreNextHop(self, dvs, testlog): - # Initialize L3 objects and database connectors. - self._set_up(dvs) - cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) - - # Maintain original WCMP group entries for ASIC DB. - db_list = ( - ( - self._p4rt_wcmp_group_obj.appl_db, - "%s:%s" - % ( - self._p4rt_wcmp_group_obj.APP_DB_TBL_NAME, - self._p4rt_wcmp_group_obj.TBL_NAME, - ), - ), - ( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_TBL_NAME, - ), - ( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_MEMBER_TBL_NAME, - ), - ) - self._p4rt_wcmp_group_obj.get_original_redis_entries(db_list) - db_list = ( - (self._p4rt_nexthop_obj.asic_db, - self._p4rt_nexthop_obj.ASIC_DB_TBL_NAME), - ) - self._p4rt_nexthop_obj.get_original_redis_entries(db_list) - - # Fetch the original key to oid information from Redis DB. - key_to_oid_helper = util.KeyToOidDBHelper(dvs) - _, original_key_oid_info = key_to_oid_helper.get_db_info() - - # Bring up port under test. - port_name = "Ethernet0" - if_name = "eth0" - util.initialize_interface(dvs, port_name, "10.0.0.0/31") - util.set_interface_status(dvs, if_name, "up") - - # Create router interface. - ( - router_interface_id, - router_intf_key, - attr_list, - ) = self._p4rt_router_intf_obj.create_router_interface() - util.verify_response( - self.response_consumer, router_intf_key, attr_list, "SWSS_RC_SUCCESS" - ) - - # Verify that P4RT key to OID count incremented by 1 in Redis DB. - count = 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Create neighbor. - neighbor_id, neighbor_key, attr_list = self._p4rt_neighbor_obj.create_neighbor() - util.verify_response( - self.response_consumer, neighbor_key, attr_list, "SWSS_RC_SUCCESS" - ) - - # Verify that P4RT key to OID count incremented by 1 in Redis DB. - count += 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Create nexthop. - nexthop_id, nexthop_key, attr_list = self._p4rt_nexthop_obj.create_next_hop() - util.verify_response( - self.response_consumer, nexthop_key, attr_list, "SWSS_RC_SUCCESS" - ) - # Get nexthop_oid of newly created nexthop. - nexthop_oid = self._p4rt_nexthop_obj.get_newly_created_nexthop_oid() - assert nexthop_oid is not None - - # Verify that P4RT key to OID count incremented by 1 in Redis DB. - count += 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Create wcmp group with one member. - ( - wcmp_group_id, - wcmp_group_key, - attr_list, - ) = self._p4rt_wcmp_group_obj.create_wcmp_group(watch_port=port_name) - util.verify_response( - self.response_consumer, wcmp_group_key, attr_list, "SWSS_RC_SUCCESS" - ) - - # Verify that P4RT key to OID count incremented by 2 in Redis DB - # (1 each for WCMP group and member). - count += 2 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Query application database for wcmp group entries. - wcmp_group_entries = util.get_keys( - self._p4rt_wcmp_group_obj.appl_db, - self._p4rt_wcmp_group_obj.APP_DB_TBL_NAME - + ":" - + self._p4rt_wcmp_group_obj.TBL_NAME, - ) - assert len(wcmp_group_entries) == ( - self._p4rt_wcmp_group_obj.get_original_appl_db_entries_count() + 1 - ) - - # Query application database for newly created wcmp group key. - (status, fvs) = util.get_key( - self._p4rt_wcmp_group_obj.appl_db, - self._p4rt_wcmp_group_obj.APP_DB_TBL_NAME, - wcmp_group_key, - ) - assert status == True - util.verify_attr(fvs, attr_list) - - # Query ASIC database for wcmp group entries. - wcmp_group_entries = util.get_keys( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_TBL_NAME, - ) - assert len(wcmp_group_entries) == ( - self._p4rt_wcmp_group_obj.get_original_asic_db_group_entries_count() + 1 - ) - - # Query ASIC database for newly created wcmp group oid. - wcmp_group_oid = self._p4rt_wcmp_group_obj.get_newly_created_wcmp_group_oid() - assert wcmp_group_oid is not None - (status, fvs) = util.get_key( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_TBL_NAME, - wcmp_group_oid, - ) - assert status == True - asic_attr_list = [ - ( - self._p4rt_wcmp_group_obj.SAI_ATTR_GROUP_TYPE, - ( - self._p4rt_wcmp_group_obj.SAI_NEXT_HOP_GROUP_TYPE_DYNAMIC_UNORDERED_ECMP - ), - ) - ] - util.verify_attr(fvs, asic_attr_list) - - # Query ASIC database for newly created wcmp group member key. - asic_db_group_member_key = ( - self._p4rt_wcmp_group_obj.get_newly_created_wcmp_group_member_asic_db_key() - ) - assert asic_db_group_member_key is not None - (status, fvs) = util.get_key( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_MEMBER_TBL_NAME, - asic_db_group_member_key, - ) - assert status == True - asic_attr_list = [ - ( - self._p4rt_wcmp_group_obj.SAI_ATTR_GROUP_MEMBER_NEXTHOP_GROUP_ID, - wcmp_group_oid, - ), - (self._p4rt_wcmp_group_obj.SAI_ATTR_GROUP_MEMBER_NEXTHOP_ID, nexthop_oid), - ( - self._p4rt_wcmp_group_obj.SAI_ATTR_GROUP_MEMBER_WEIGHT, - str(self._p4rt_wcmp_group_obj.DEFAULT_WEIGHT), - ), - ] - util.verify_attr(fvs, asic_attr_list) - - # Force oper-down for the associated port. - util.set_interface_status(dvs, if_name) - - # Check ASIC DB to verify that associated member for watch_port is - # pruned. - wcmp_group_member_entries = util.get_keys( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_MEMBER_TBL_NAME, - ) - assert len(wcmp_group_member_entries) == ( - self._p4rt_wcmp_group_obj.get_original_asic_db_member_entries_count() - ) - - # Force oper-up for associated port. - util.set_interface_status(dvs, if_name, "up") - - # Check pruned next hop member is restored in ASIC DB. - wcmp_group_member_entries = util.get_keys( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_MEMBER_TBL_NAME, - ) - assert len(wcmp_group_member_entries) == ( - self._p4rt_wcmp_group_obj.get_original_asic_db_member_entries_count() + 1 - ) - asic_db_group_member_key = ( - self._p4rt_wcmp_group_obj.get_newly_created_wcmp_group_member_asic_db_key() - ) - assert asic_db_group_member_key is not None - (status, fvs) = util.get_key( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_MEMBER_TBL_NAME, - asic_db_group_member_key, - ) - assert status == True - util.verify_attr(fvs, asic_attr_list) - - # Delete WCMP group member. - self._p4rt_wcmp_group_obj.remove_app_db_entry(wcmp_group_key) - - # Verify that P4RT key to OID count decremented by 2 in Redis DB - # (1 each for WCMP group and member). - count -= 2 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Delete next hop. - self._p4rt_nexthop_obj.remove_app_db_entry(nexthop_key) - - # Verify that P4RT key to OID count decremented by 1 in Redis DB. - count -= 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Delete neighbor. - self._p4rt_neighbor_obj.remove_app_db_entry(neighbor_key) - - # Verify that P4RT key to OID count decremented by 1 in Redis DB. - count -= 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Delete router interface. - self._p4rt_router_intf_obj.remove_app_db_entry(router_intf_key) - - # Verify that P4RT key to OID count is same as the original count. - status, fvs = key_to_oid_helper.get_db_info() - assert status == False - assert len(fvs) == len(original_key_oid_info) - - def test_PruneNextHopOnWarmBoot(self, dvs, testlog): - # Initialize L3 objects and database connectors. - self._set_up(dvs) - cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) - - # Maintain original WCMP group entries for ASIC DB. - db_list = ( - ( - self._p4rt_wcmp_group_obj.appl_db, - "%s:%s" - % ( - self._p4rt_wcmp_group_obj.APP_DB_TBL_NAME, - self._p4rt_wcmp_group_obj.TBL_NAME, - ), - ), - ( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_TBL_NAME, - ), - ( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_MEMBER_TBL_NAME, - ), - ) - self._p4rt_wcmp_group_obj.get_original_redis_entries(db_list) - db_list = ( - (self._p4rt_nexthop_obj.asic_db, - self._p4rt_nexthop_obj.ASIC_DB_TBL_NAME), - ) - self._p4rt_nexthop_obj.get_original_redis_entries(db_list) - - # Fetch the original key to oid information from Redis DB. - key_to_oid_helper = util.KeyToOidDBHelper(dvs) - _, original_key_oid_info = key_to_oid_helper.get_db_info() - - # Bring up port under test. - port_name = "Ethernet0" - if_name = "eth0" - util.initialize_interface(dvs, port_name, "10.0.0.0/31") - util.set_interface_status(dvs, if_name, "up") - - # Create router interface. - ( - router_interface_id, - router_intf_key, - attr_list, - ) = self._p4rt_router_intf_obj.create_router_interface() - util.verify_response( - self.response_consumer, router_intf_key, attr_list, "SWSS_RC_SUCCESS" - ) - - # Verify that P4RT key to OID count incremented by 1 in Redis DB. - count = 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Create neighbor. - neighbor_id, neighbor_key, attr_list = self._p4rt_neighbor_obj.create_neighbor() - util.verify_response( - self.response_consumer, neighbor_key, attr_list, "SWSS_RC_SUCCESS" - ) - - # Verify that P4RT key to OID count incremented by 1 in Redis DB. - count += 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Create nexthop. - nexthop_id, nexthop_key, attr_list = self._p4rt_nexthop_obj.create_next_hop() - util.verify_response( - self.response_consumer, nexthop_key, attr_list, "SWSS_RC_SUCCESS" - ) - # Get nexthop_oid of newly created nexthop. - nexthop_oid = self._p4rt_nexthop_obj.get_newly_created_nexthop_oid() - assert nexthop_oid is not None - - # Verify that P4RT key to OID count incremented by 1 in Redis DB. - count += 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Create wcmp group with one member. - ( - wcmp_group_id, - wcmp_group_key, - attr_list, - ) = self._p4rt_wcmp_group_obj.create_wcmp_group(watch_port=port_name) - util.verify_response( - self.response_consumer, wcmp_group_key, attr_list, "SWSS_RC_SUCCESS" - ) - - # Verify that P4RT key to OID count incremented by 2 in Redis DB - # (1 each for WCMP group and member). - count += 2 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Query application database for wcmp group entries. - wcmp_group_entries = util.get_keys( - self._p4rt_wcmp_group_obj.appl_db, - self._p4rt_wcmp_group_obj.APP_DB_TBL_NAME - + ":" - + self._p4rt_wcmp_group_obj.TBL_NAME, - ) - assert len(wcmp_group_entries) == ( - self._p4rt_wcmp_group_obj.get_original_appl_db_entries_count() + 1 - ) - - # Query application database for newly created wcmp group key. - (status, fvs) = util.get_key( - self._p4rt_wcmp_group_obj.appl_db, - self._p4rt_wcmp_group_obj.APP_DB_TBL_NAME, - wcmp_group_key, - ) - assert status == True - util.verify_attr(fvs, attr_list) - - # Query ASIC database for wcmp group entries. - wcmp_group_entries = util.get_keys( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_TBL_NAME, - ) - assert len(wcmp_group_entries) == ( - self._p4rt_wcmp_group_obj.get_original_asic_db_group_entries_count() + 1 - ) - - # Query ASIC database for newly created wcmp group oid. - wcmp_group_oid = self._p4rt_wcmp_group_obj.get_newly_created_wcmp_group_oid() - assert wcmp_group_oid is not None - (status, fvs) = util.get_key( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_TBL_NAME, - wcmp_group_oid, - ) - assert status == True - asic_attr_list = [ - ( - self._p4rt_wcmp_group_obj.SAI_ATTR_GROUP_TYPE, - ( - self._p4rt_wcmp_group_obj.SAI_NEXT_HOP_GROUP_TYPE_DYNAMIC_UNORDERED_ECMP - ), - ) - ] - util.verify_attr(fvs, asic_attr_list) - - # Query ASIC database for wcmp group member entries. - wcmp_group_member_entries = util.get_keys( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_MEMBER_TBL_NAME, - ) - assert len(wcmp_group_member_entries) == ( - self._p4rt_wcmp_group_obj.get_original_asic_db_member_entries_count() + 1 - ) - - # Query ASIC database for newly created wcmp group member key. - asic_db_group_member_key = ( - self._p4rt_wcmp_group_obj.get_newly_created_wcmp_group_member_asic_db_key() - ) - assert asic_db_group_member_key is not None - (status, fvs) = util.get_key( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_MEMBER_TBL_NAME, - asic_db_group_member_key, - ) - assert status == True - asic_attr_list = [ - ( - self._p4rt_wcmp_group_obj.SAI_ATTR_GROUP_MEMBER_NEXTHOP_GROUP_ID, - wcmp_group_oid, - ), - (self._p4rt_wcmp_group_obj.SAI_ATTR_GROUP_MEMBER_NEXTHOP_ID, nexthop_oid), - ( - self._p4rt_wcmp_group_obj.SAI_ATTR_GROUP_MEMBER_WEIGHT, - str(self._p4rt_wcmp_group_obj.DEFAULT_WEIGHT), - ), - ] - util.verify_attr(fvs, asic_attr_list) - - # Bring down the port. - util.set_interface_status(dvs, if_name) - - # Execute the warm reboot. - dvs.warm_restart_swss("true") - dvs.stop_swss() - dvs.start_swss() - - # Make sure the system is stable. - dvs.check_swss_ready() - - # Verify that the associated next hop is pruned in ASIC DB. - wcmp_group_member_entries = util.get_keys( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_MEMBER_TBL_NAME, - ) - assert len(wcmp_group_member_entries) == ( - self._p4rt_wcmp_group_obj.get_original_asic_db_member_entries_count() - ) - - # Delete WCMP group member. - self._p4rt_wcmp_group_obj.remove_app_db_entry(wcmp_group_key) - - # Verify that P4RT key to OID count decremented by 2 in Redis DB - # (1 each for WCMP group and member). - count -= 2 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Delete next hop. - self._p4rt_nexthop_obj.remove_app_db_entry(nexthop_key) - - # Verify that P4RT key to OID count decremented by 1 in Redis DB. - count -= 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Delete neighbor. - self._p4rt_neighbor_obj.remove_app_db_entry(neighbor_key) - - # Verify that P4RT key to OID count decremented by 1 in Redis DB. - count -= 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Delete router interface. - self._p4rt_router_intf_obj.remove_app_db_entry(router_intf_key) - - # Verify that P4RT key to OID count is same as the original count. - status, fvs = key_to_oid_helper.get_db_info() - assert status == False - assert len(fvs) == len(original_key_oid_info) - - def test_CreateWcmpMemberForOperUpWatchportOnly(self, dvs, testlog): - # Initialize L3 objects and database connectors. - self._set_up(dvs) - cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) - - # Maintain original WCMP group entries for ASIC DB. - db_list = ( - ( - self._p4rt_wcmp_group_obj.appl_db, - "%s:%s" - % ( - self._p4rt_wcmp_group_obj.APP_DB_TBL_NAME, - self._p4rt_wcmp_group_obj.TBL_NAME, - ), - ), - ( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_TBL_NAME, - ), - ( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_MEMBER_TBL_NAME, - ), - ) - self._p4rt_wcmp_group_obj.get_original_redis_entries(db_list) - db_list = ( - (self._p4rt_nexthop_obj.asic_db, - self._p4rt_nexthop_obj.ASIC_DB_TBL_NAME), - ) - self._p4rt_nexthop_obj.get_original_redis_entries(db_list) - - # Fetch the original key to oid information from Redis DB. - key_to_oid_helper = util.KeyToOidDBHelper(dvs) - _, original_key_oid_info = key_to_oid_helper.get_db_info() - - # Force oper-down on port under test. - port_name = "Ethernet0" - if_name = "eth0" - util.initialize_interface(dvs, port_name, "10.0.0.0/31") - util.set_interface_status(dvs, if_name) - - # Create router interface. - ( - router_interface_id, - router_intf_key, - attr_list, - ) = self._p4rt_router_intf_obj.create_router_interface() - util.verify_response( - self.response_consumer, router_intf_key, attr_list, "SWSS_RC_SUCCESS" - ) - - # Verify that P4RT key to OID count incremented by 1 in Redis DB. - count = 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Create neighbor. - neighbor_id, neighbor_key, attr_list = self._p4rt_neighbor_obj.create_neighbor() - util.verify_response( - self.response_consumer, neighbor_key, attr_list, "SWSS_RC_SUCCESS" - ) - - # Verify that P4RT key to OID count incremented by 1 in Redis DB. - count += 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Create nexthop. - nexthop_id, nexthop_key, attr_list = self._p4rt_nexthop_obj.create_next_hop() - util.verify_response( - self.response_consumer, nexthop_key, attr_list, "SWSS_RC_SUCCESS" - ) - # Get nexthop_oid of newly created nexthop. - nexthop_oid = self._p4rt_nexthop_obj.get_newly_created_nexthop_oid() - assert nexthop_oid is not None - - # Verify that P4RT key to OID count incremented by 1 in Redis DB. - count += 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Create wcmp group with one member. - ( - wcmp_group_id, - wcmp_group_key, - attr_list, - ) = self._p4rt_wcmp_group_obj.create_wcmp_group(watch_port=port_name) - util.verify_response( - self.response_consumer, wcmp_group_key, attr_list, "SWSS_RC_SUCCESS" - ) - - # Verify that P4RT key to OID count incremented by 1 in Redis DB - # (WCMP group member is not created for operationally down watchport). - count += 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Query application database for wcmp group entries. - wcmp_group_entries = util.get_keys( - self._p4rt_wcmp_group_obj.appl_db, - self._p4rt_wcmp_group_obj.APP_DB_TBL_NAME - + ":" - + self._p4rt_wcmp_group_obj.TBL_NAME, - ) - assert len(wcmp_group_entries) == ( - self._p4rt_wcmp_group_obj.get_original_appl_db_entries_count() + 1 - ) - - # Query application database for newly created wcmp group key. - (status, fvs) = util.get_key( - self._p4rt_wcmp_group_obj.appl_db, - self._p4rt_wcmp_group_obj.APP_DB_TBL_NAME, - wcmp_group_key, - ) - assert status == True - util.verify_attr(fvs, attr_list) - - # Query ASIC database for wcmp group entries. - wcmp_group_entries = util.get_keys( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_TBL_NAME, - ) - assert len(wcmp_group_entries) == ( - self._p4rt_wcmp_group_obj.get_original_asic_db_group_entries_count() + 1 - ) - - # Query ASIC database for newly created wcmp group oid. - wcmp_group_oid = self._p4rt_wcmp_group_obj.get_newly_created_wcmp_group_oid() - assert wcmp_group_oid is not None - (status, fvs) = util.get_key( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_TBL_NAME, - wcmp_group_oid, - ) - assert status == True - asic_attr_list = [ - ( - self._p4rt_wcmp_group_obj.SAI_ATTR_GROUP_TYPE, - ( - self._p4rt_wcmp_group_obj.SAI_NEXT_HOP_GROUP_TYPE_DYNAMIC_UNORDERED_ECMP - ), - ) - ] - util.verify_attr(fvs, asic_attr_list) - - # Query ASIC database for wcmp group member entries (expect no entry). - wcmp_group_member_entries = util.get_keys( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_MEMBER_TBL_NAME, - ) - assert len(wcmp_group_member_entries) == ( - self._p4rt_wcmp_group_obj.get_original_asic_db_member_entries_count() - ) - - # Bring up the port. - util.set_interface_status(dvs, if_name, "up") - - # Verify that P4RT key to OID count incremented by 1 in Redis DB - # (WCMP group member is now expected to be created in SAI due to - # watchport now being operationally up) - count += 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Verify that next hop member is now created in SAI. - wcmp_group_member_entries = util.get_keys( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_MEMBER_TBL_NAME, - ) - assert len(wcmp_group_member_entries) == ( - self._p4rt_wcmp_group_obj.get_original_asic_db_member_entries_count() + 1 - ) - asic_db_group_member_key = ( - self._p4rt_wcmp_group_obj.get_newly_created_wcmp_group_member_asic_db_key() - ) - assert asic_db_group_member_key is not None - (status, fvs) = util.get_key( - self._p4rt_wcmp_group_obj.asic_db, - (self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_MEMBER_TBL_NAME), - asic_db_group_member_key, - ) - assert status == True - asic_attr_list = [ - ( - self._p4rt_wcmp_group_obj.SAI_ATTR_GROUP_MEMBER_NEXTHOP_GROUP_ID, - wcmp_group_oid, - ), - (self._p4rt_wcmp_group_obj.SAI_ATTR_GROUP_MEMBER_NEXTHOP_ID, nexthop_oid), - ( - self._p4rt_wcmp_group_obj.SAI_ATTR_GROUP_MEMBER_WEIGHT, - str(self._p4rt_wcmp_group_obj.DEFAULT_WEIGHT), - ), - ] - util.verify_attr(fvs, asic_attr_list) - - # Delete WCMP group member. - self._p4rt_wcmp_group_obj.remove_app_db_entry(wcmp_group_key) - - # Verify that P4RT key to OID count decremented by 2 in Redis DB - # (1 each for WCMP group and member). - count -= 2 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Delete next hop. - self._p4rt_nexthop_obj.remove_app_db_entry(nexthop_key) - - # Verify that P4RT key to OID count decremented by 1 in Redis DB. - count -= 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Delete neighbor. - self._p4rt_neighbor_obj.remove_app_db_entry(neighbor_key) - - # Verify that P4RT key to OID count decremented by 1 in Redis DB. - count -= 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Delete router interface. - self._p4rt_router_intf_obj.remove_app_db_entry(router_intf_key) - - # Verify that P4RT key to OID count is same as the original count. - status, fvs = key_to_oid_helper.get_db_info() - assert status == False - assert len(fvs) == len(original_key_oid_info) - - def test_RemovePrunedWcmpGroupMember(self, dvs, testlog): - # Initialize L3 objects and database connectors. - self._set_up(dvs) - cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) - - # Maintain original WCMP group entries for ASIC DB. - db_list = ( - ( - self._p4rt_wcmp_group_obj.appl_db, - "%s:%s" - % ( - self._p4rt_wcmp_group_obj.APP_DB_TBL_NAME, - self._p4rt_wcmp_group_obj.TBL_NAME, - ), - ), - ( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_TBL_NAME, - ), - ( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_MEMBER_TBL_NAME, - ), - ) - self._p4rt_wcmp_group_obj.get_original_redis_entries(db_list) - db_list = ( - (self._p4rt_nexthop_obj.asic_db, - self._p4rt_nexthop_obj.ASIC_DB_TBL_NAME), - ) - self._p4rt_nexthop_obj.get_original_redis_entries(db_list) - - # Fetch the original key to oid information from Redis DB. - key_to_oid_helper = util.KeyToOidDBHelper(dvs) - _, original_key_oid_info = key_to_oid_helper.get_db_info() - - # Force oper-down on port under test. - port_name = "Ethernet0" - if_name = "eth0" - util.initialize_interface(dvs, port_name, "10.0.0.0/31") - util.set_interface_status(dvs, if_name) - - # Create router interface. - ( - router_interface_id, - router_intf_key, - attr_list, - ) = self._p4rt_router_intf_obj.create_router_interface() - util.verify_response( - self.response_consumer, router_intf_key, attr_list, "SWSS_RC_SUCCESS" - ) - - # Verify that P4RT key to OID count incremented by 1 in Redis DB. - count = 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Create neighbor. - neighbor_id, neighbor_key, attr_list = self._p4rt_neighbor_obj.create_neighbor() - util.verify_response( - self.response_consumer, neighbor_key, attr_list, "SWSS_RC_SUCCESS" - ) - - # Verify that P4RT key to OID count incremented by 1 in Redis DB. - count += 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Create nexthop. - nexthop_id, nexthop_key, attr_list = self._p4rt_nexthop_obj.create_next_hop() - util.verify_response( - self.response_consumer, nexthop_key, attr_list, "SWSS_RC_SUCCESS" - ) - # Get nexthop_oid of newly created nexthop. - nexthop_oid = self._p4rt_nexthop_obj.get_newly_created_nexthop_oid() - assert nexthop_oid is not None - - # Verify that P4RT key to OID count incremented by 1 in Redis DB. - count += 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Create wcmp group with one member. - ( - wcmp_group_id, - wcmp_group_key, - attr_list, - ) = self._p4rt_wcmp_group_obj.create_wcmp_group(watch_port=port_name) - util.verify_response( - self.response_consumer, wcmp_group_key, attr_list, "SWSS_RC_SUCCESS" - ) - - # Verify that P4RT key to OID count incremented by 1 in Redis DB - # (WCMP group member is not created for operationally down watchport). - count += 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Query application database for wcmp group entries. - wcmp_group_entries = util.get_keys( - self._p4rt_wcmp_group_obj.appl_db, - self._p4rt_wcmp_group_obj.APP_DB_TBL_NAME - + ":" - + self._p4rt_wcmp_group_obj.TBL_NAME, - ) - assert len(wcmp_group_entries) == ( - self._p4rt_wcmp_group_obj.get_original_appl_db_entries_count() + 1 - ) - - # Query application database for newly created wcmp group key. - (status, fvs) = util.get_key( - self._p4rt_wcmp_group_obj.appl_db, - self._p4rt_wcmp_group_obj.APP_DB_TBL_NAME, - wcmp_group_key, - ) - assert status == True - util.verify_attr(fvs, attr_list) - - # Query ASIC database for wcmp group entries. - wcmp_group_entries = util.get_keys( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_TBL_NAME, - ) - assert len(wcmp_group_entries) == ( - self._p4rt_wcmp_group_obj.get_original_asic_db_group_entries_count() + 1 - ) - - # Query ASIC database for newly created wcmp group oid. - wcmp_group_oid = self._p4rt_wcmp_group_obj.get_newly_created_wcmp_group_oid() - assert wcmp_group_oid is not None - (status, fvs) = util.get_key( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_TBL_NAME, - wcmp_group_oid, - ) - assert status == True - asic_attr_list = [ - ( - self._p4rt_wcmp_group_obj.SAI_ATTR_GROUP_TYPE, - ( - self._p4rt_wcmp_group_obj.SAI_NEXT_HOP_GROUP_TYPE_DYNAMIC_UNORDERED_ECMP - ), - ) - ] - util.verify_attr(fvs, asic_attr_list) - - # Query ASIC database for wcmp group member entries. - wcmp_group_member_entries = util.get_keys( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_TBL_NAME, - ) - assert len(wcmp_group_member_entries) == ( - self._p4rt_wcmp_group_obj.get_original_asic_db_member_entries_count() + 1 - ) - - # Query ASIC database for wcmp group member entries (expect no entry). - wcmp_group_member_entries = util.get_keys( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_MEMBER_TBL_NAME, - ) - assert ( - len(wcmp_group_member_entries) - == self._p4rt_wcmp_group_obj.get_original_asic_db_member_entries_count() - ) - - # Attempt to delete the next hop. Expect failure as the pruned WCMP - # group member is still referencing it. - self._p4rt_nexthop_obj.remove_app_db_entry(nexthop_key) - - # Verify that the P4RT key to OID count is same as before in Redis DB. - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Delete the pruned wcmp group member and try again. - self._p4rt_wcmp_group_obj.remove_app_db_entry(wcmp_group_key) - - # Verify that P4RT key to OID count decremented by 1 in Redis DB. - count -= 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Verify that ASIC DB is updated. - wcmp_group_entries = util.get_keys( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_TBL_NAME, - ) - assert len(wcmp_group_entries) == ( - self._p4rt_wcmp_group_obj.get_original_asic_db_group_entries_count() - ) - wcmp_group_member_entries = util.get_keys( - self._p4rt_wcmp_group_obj.asic_db, - self._p4rt_wcmp_group_obj.ASIC_DB_GROUP_MEMBER_TBL_NAME, - ) - assert len(wcmp_group_member_entries) == ( - self._p4rt_wcmp_group_obj.get_original_asic_db_member_entries_count() - ) - - # Delete next hop. - self._p4rt_nexthop_obj.remove_app_db_entry(nexthop_key) - - # Verify that P4RT key to OID count decremented by 1 in Redis DB. - count -= 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Delete neighbor. - self._p4rt_neighbor_obj.remove_app_db_entry(neighbor_key) - - # Verify that P4RT key to OID count decremented by 1 in Redis DB. - count -= 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Delete router interface. - self._p4rt_router_intf_obj.remove_app_db_entry(router_intf_key) - - # Verify that P4RT key to OID count is same as the original count. - status, fvs = key_to_oid_helper.get_db_info() - assert status == False - assert len(fvs) == len(original_key_oid_info) - - def test_NexthopWithGreTunnelCreationFailIfDependenciesAreMissing(self, dvs, testlog): - # Initialize L3 objects and database connectors. - self._set_up(dvs) - self._set_vrf(dvs) - - # Maintain list of original Application and ASIC DB entries before - # adding new entries. - db_list = ( - ( - self._p4rt_nexthop_obj.appl_db, - "%s:%s" - % ( - self._p4rt_nexthop_obj.APP_DB_TBL_NAME, - self._p4rt_nexthop_obj.TBL_NAME, - ), - ), - (self._p4rt_nexthop_obj.asic_db, - self._p4rt_nexthop_obj.ASIC_DB_TBL_NAME), - ) - self._p4rt_nexthop_obj.get_original_redis_entries(db_list) - db_list = ( - ( - self._p4rt_gre_tunnel_obj.appl_db, - "%s:%s" - % ( - self._p4rt_gre_tunnel_obj.APP_DB_TBL_NAME, - self._p4rt_gre_tunnel_obj.TBL_NAME, - ), - ), - (self._p4rt_gre_tunnel_obj.asic_db, - self._p4rt_gre_tunnel_obj.ASIC_DB_TBL_NAME), - ) - self._p4rt_gre_tunnel_obj.get_original_redis_entries(db_list) - db_list = ( - (self._p4rt_router_intf_obj.asic_db, - self._p4rt_router_intf_obj.ASIC_DB_TBL_NAME), - ) - self._p4rt_router_intf_obj.get_original_redis_entries(db_list) - - # Fetch the original key to oid information from Redis DB. - key_to_oid_helper = util.KeyToOidDBHelper(dvs) - _, original_key_oid_info = key_to_oid_helper.get_db_info() - - # Create tunnel. - tunnel_id, tunnel_key, attr_list = self._p4rt_gre_tunnel_obj.create_gre_tunnel() - util.verify_response( - self.response_consumer, tunnel_key, attr_list, "SWSS_RC_NOT_FOUND", - "[OrchAgent] Router intf '16' does not exist" - ) - - # Verify that P4RT key to OID count does not change in Redis DB. - status, fvs = key_to_oid_helper.get_db_info() - assert status == False - assert len(fvs) == len(original_key_oid_info) - - # Query application database for tunnel entries. - tunnel_entries = util.get_keys( - self._p4rt_gre_tunnel_obj.appl_db, - self._p4rt_gre_tunnel_obj.APP_DB_TBL_NAME + - ":" + self._p4rt_gre_tunnel_obj.TBL_NAME, - ) - assert len(tunnel_entries) == ( - self._p4rt_gre_tunnel_obj.get_original_appl_db_entries_count() + 1 - ) - - # Query ASIC database for tunnel entries. - tunnel_entries = util.get_keys( - self._p4rt_gre_tunnel_obj.asic_db, self._p4rt_gre_tunnel_obj.ASIC_DB_TBL_NAME - ) - assert len(tunnel_entries) == ( - self._p4rt_gre_tunnel_obj.get_original_asic_db_entries_count() - ) - - # Create tunnel nexthop. - nexthop_id, nexthop_key, attr_list = self._p4rt_nexthop_obj.create_next_hop( - tunnel_id=tunnel_id - ) - util.verify_response( - self.response_consumer, nexthop_key, attr_list, "SWSS_RC_NOT_FOUND", - "[OrchAgent] GRE Tunnel 'tunnel-1' does not exist in GRE Tunnel Manager" - ) - - # Verify that P4RT key to OID count does not change in Redis DB. - status, fvs = key_to_oid_helper.get_db_info() - assert status == False - assert len(fvs) == len(original_key_oid_info) - - # Query application database for nexthop entries. - nexthop_entries = util.get_keys( - self._p4rt_nexthop_obj.appl_db, - self._p4rt_nexthop_obj.APP_DB_TBL_NAME + ":" + self._p4rt_nexthop_obj.TBL_NAME, - ) - assert len(nexthop_entries) == ( - self._p4rt_nexthop_obj.get_original_appl_db_entries_count() + 1 - ) - - # Query ASIC database for nexthop entries. - nexthop_entries = util.get_keys( - self._p4rt_nexthop_obj.asic_db, self._p4rt_nexthop_obj.ASIC_DB_TBL_NAME - ) - assert len(nexthop_entries) == ( - self._p4rt_nexthop_obj.get_original_asic_db_entries_count() - ) - - self._clean_vrf(dvs) diff --git a/tests/p4rt/test_l3_admit.py b/tests/p4rt/test_l3_admit.py deleted file mode 100644 index 8fc3bbb8d4..0000000000 --- a/tests/p4rt/test_l3_admit.py +++ /dev/null @@ -1,216 +0,0 @@ -from swsscommon import swsscommon - -import pytest -import json -import util -import l3_admit - - -class TestP4RTL3Admit(object): - def _set_up(self, dvs): - self._p4rt_l3_admit_obj = l3_admit.P4RtL3AdmitWrapper() - - self._p4rt_l3_admit_obj.set_up_databases(dvs) - self.response_consumer = swsscommon.NotificationConsumer( - self._p4rt_l3_admit_obj.appl_db, "APPL_DB_" + - swsscommon.APP_P4RT_TABLE_NAME + "_RESPONSE_CHANNEL" - ) - - @pytest.mark.skip(reason="sairedis vs MY MAC support is not ready") - def test_DefaultL3AdmitAddDeletePass(self, dvs, testlog): - # Initialize database connectors. - self._set_up(dvs) - - # Maintain list of original Application and ASIC DB entries before - # adding new entries - db_list = ( - ( - self._p4rt_l3_admit_obj.appl_db, - "%s:%s" - % (self._p4rt_l3_admit_obj.APP_DB_TBL_NAME, self._p4rt_l3_admit_obj.TBL_NAME), - ), - (self._p4rt_l3_admit_obj.asic_db, - self._p4rt_l3_admit_obj.ASIC_DB_TBL_NAME), - ) - self._p4rt_l3_admit_obj.get_original_redis_entries(db_list) - - # Fetch the original key to oid information from Redis DB. - key_to_oid_helper = util.KeyToOidDBHelper(dvs) - _, original_key_oid_info = key_to_oid_helper.get_db_info() - - # l3 admit entry attributes - # P4RT_TABLE:FIXED_L3_ADMIT_TABLE:{\"match/dst_mac\":\"00:02:03:04:00:00&ff:ff:ff:ff:00:00\",\"match/in_port\":\"Ethernet8\",\"priority\":2030} - # "action": "admit_to_l3" - # "controller_metadata": "..." - dst_mac_data = "00:02:03:04:00:00" - dst_mac_mask = "FF:FF:FF:FF:00:00" - in_port = "Ethernet8" - priority = 2030 - - # Create l3 admit entry. - ( - l3_admit_key, - attr_list, - ) = self._p4rt_l3_admit_obj.create_l3_admit(dst_mac_data + "&" + dst_mac_mask, priority, in_port) - util.verify_response( - self.response_consumer, l3_admit_key, attr_list, "SWSS_RC_SUCCESS" - ) - - # Verify that P4RT key to OID count incremented by 1 in Redis DB. - count = 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Query application database for l3 admit entries. - l3_admit_entries = util.get_keys( - self._p4rt_l3_admit_obj.appl_db, - self._p4rt_l3_admit_obj.APP_DB_TBL_NAME + - ":" + self._p4rt_l3_admit_obj.TBL_NAME, - ) - assert len(l3_admit_entries) == ( - self._p4rt_l3_admit_obj.get_original_appl_db_entries_count() + 1 - ) - - # Query application database for newly created l3 admit key. - (status, fvs) = util.get_key( - self._p4rt_l3_admit_obj.appl_db, - self._p4rt_l3_admit_obj.APP_DB_TBL_NAME, - l3_admit_key, - ) - assert status == True - util.verify_attr(fvs, attr_list) - - # Query ASIC database for my mac entries. - asic_l3_admit_entries = util.get_keys( - self._p4rt_l3_admit_obj.asic_db, self._p4rt_l3_admit_obj.ASIC_DB_TBL_NAME - ) - assert len(asic_l3_admit_entries) == ( - self._p4rt_l3_admit_obj.get_original_asic_db_entries_count() + 1 - ) - - # Query ASIC database for newly created my mac key. - asic_db_key = self._p4rt_l3_admit_obj.get_newly_created_asic_db_key() - assert asic_db_key is not None - (status, fvs) = util.get_key( - self._p4rt_l3_admit_obj.asic_db, - self._p4rt_l3_admit_obj.ASIC_DB_TBL_NAME, - asic_db_key, - ) - assert status == True - attr_list = [(self._p4rt_l3_admit_obj.SAI_ATTR_DST_MAC, dst_mac_data), - (self._p4rt_l3_admit_obj.SAI_ATTR_DST_MAC_MASK, dst_mac_mask), - (self._p4rt_l3_admit_obj.SAI_ATTR_PRIORITY, str(priority)), - (self._p4rt_l3_admit_obj.SAI_ATTR_PORT_ID, util.get_port_oid_by_name(dvs, in_port))] - util.verify_attr(fvs, attr_list) - - # deplicate SET will be no-op. - new_l3_admit_key, new_attr_list = self._p4rt_l3_admit_obj.create_l3_admit( - dst_mac_data + "&" + dst_mac_mask, priority, in_port) - util.verify_response( - self.response_consumer, new_l3_admit_key, new_attr_list, - "SWSS_RC_SUCCESS", - "L3 Admit entry with the same key received: 'match/dst_mac=00:02:03:04:00:00&ff:ff:ff:ff:00:00:match/in_port=Ethernet8:priority=2030'" - ) - - # Verify that P4RT key to OID count did not change in Redis DB. - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Remove l3 admit entry. - self._p4rt_l3_admit_obj.remove_app_db_entry(l3_admit_key) - util.verify_response(self.response_consumer, - l3_admit_key, [], "SWSS_RC_SUCCESS") - - # Verify that P4RT key to OID count decremented to orig in Redis DB. - status, fvs = key_to_oid_helper.get_db_info() - assert status == False - assert len(fvs) == len(original_key_oid_info) - - # Query application database for route entries. - l3_admit_entries = util.get_keys( - self._p4rt_l3_admit_obj.appl_db, - self._p4rt_l3_admit_obj.APP_DB_TBL_NAME + - ":" + self._p4rt_l3_admit_obj.TBL_NAME, - ) - assert len(l3_admit_entries) == ( - self._p4rt_l3_admit_obj.get_original_appl_db_entries_count() - ) - - # Verify that the route_key no longer exists in application database. - (status, fsv) = util.get_key( - self._p4rt_l3_admit_obj.appl_db, - self._p4rt_l3_admit_obj.APP_DB_TBL_NAME, - l3_admit_key, - ) - assert status == False - - # Query ASIC database for my mac entries. - my_mac_entries = util.get_keys( - self._p4rt_l3_admit_obj.asic_db, self._p4rt_l3_admit_obj.ASIC_DB_TBL_NAME - ) - assert len(my_mac_entries) == ( - self._p4rt_l3_admit_obj.get_original_asic_db_entries_count() - ) - - # Verify that removed route no longer exists in ASIC database. - (status, fvs) = util.get_key( - self._p4rt_l3_admit_obj.asic_db, - self._p4rt_l3_admit_obj.ASIC_DB_TBL_NAME, - asic_db_key, - ) - assert status == False - - def test_InvalidL3AdmitKeyFailsToCreate(self, dvs, testlog): - # Initialize database connectors. - self._set_up(dvs) - - # Maintain list of original Application and ASIC DB entries before - # adding new entries - db_list = ( - ( - self._p4rt_l3_admit_obj.appl_db, - "%s:%s" - % (self._p4rt_l3_admit_obj.APP_DB_TBL_NAME, self._p4rt_l3_admit_obj.TBL_NAME), - ), - (self._p4rt_l3_admit_obj.asic_db, - self._p4rt_l3_admit_obj.ASIC_DB_TBL_NAME), - ) - self._p4rt_l3_admit_obj.get_original_redis_entries(db_list) - - # Fetch the original key to oid information from Redis DB. - key_to_oid_helper = util.KeyToOidDBHelper(dvs) - _, original_key_oid_info = key_to_oid_helper.get_db_info() - - # Invalid l3 admit key - # P4RT_TABLE:FIXED_L3_ADMIT_TABLE:{\"match/dst_mac\":\"1\",\"match/in_port\":\"Ethernet8\",\"priority\":2030} - # "action": "admit_to_l3" - # "controller_metadata": "..." - dst_mac_data = "1" - in_port = "Ethernet8" - priority = 2030 - - # Create l3 admit entry. - ( - l3_admit_key, - attr_list, - ) = self._p4rt_l3_admit_obj.create_l3_admit(dst_mac_data, priority, in_port) - util.verify_response( - self.response_consumer, l3_admit_key, attr_list, - "SWSS_RC_INVALID_PARAM", - "[OrchAgent] Failed to deserialize l3 admit key" - ) - - # Verify that P4RT key to OID count not changed in Redis DB - status, fvs = key_to_oid_helper.get_db_info() - assert status == False - assert len(fvs) == len(original_key_oid_info) - - # Query ASIC database for my mac entries. Count remains the same - asic_l3_admit_entries = util.get_keys( - self._p4rt_l3_admit_obj.asic_db, self._p4rt_l3_admit_obj.ASIC_DB_TBL_NAME - ) - assert len(asic_l3_admit_entries) == ( - self._p4rt_l3_admit_obj.get_original_asic_db_entries_count() - ) diff --git a/tests/p4rt/test_p4rt_acl.py b/tests/p4rt/test_p4rt_acl.py deleted file mode 100644 index 515354e101..0000000000 --- a/tests/p4rt/test_p4rt_acl.py +++ /dev/null @@ -1,1288 +0,0 @@ -# Lint as: python3 -from swsscommon import swsscommon - -import pytest -import util -import acl - - -def get_exist_entry(dvs, table): - db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - tbl = swsscommon.Table(db, table) - entries = list(tbl.getKeys()) - return entries[0] - - -def verify_selected_attr_vals(db, table, key, expected_attrs): - tbl = swsscommon.Table(db, table) - keys = tbl.getKeys() - assert key in keys, "The desired key is not presented" - - status, fvs = tbl.get(key) - assert status, "Got an error when get a key" - - fv_dict = dict(fvs) - - for attr_name, expected_val in expected_attrs: - assert attr_name in fv_dict, "Attribute %s not found in %s" % ( - attr_name, key) - assert fv_dict[attr_name] == expected_val, "Wrong value %s for the attribute %s = %s" % ( - fv_dict[attr_name], - attr_name, - expected_val, - ) - - -class TestP4RTAcl(object): - def _set_up(self, dvs): - self._p4rt_acl_table_definition_obj = acl.P4RtAclTableDefinitionWrapper() - self._p4rt_acl_group_obj = acl.P4RtAclGroupWrapper() - self._p4rt_acl_group_member_obj = acl.P4RtAclGroupMemberWrapper() - self._p4rt_acl_rule_obj = acl.P4RtAclRuleWrapper() - self._p4rt_acl_counter_obj = acl.P4RtAclCounterWrapper() - self._p4rt_acl_meter_obj = acl.P4RtAclMeterWrapper() - self._p4rt_trap_group_obj = acl.P4RtTrapGroupWrapper() - self._p4rt_user_trap_obj = acl.P4RtUserDefinedTrapWrapper() - self._p4rt_hostif_obj = acl.P4RtHostifWrapper() - self._p4rt_hostif_table_entry_obj = acl.P4RtHostifTableEntryWrapper() - self._p4rt_udf_group_obj = acl.P4RtUdfGroupWrapper() - self._p4rt_udf_match_obj = acl.P4RtUdfMatchWrapper() - self._p4rt_udf_obj = acl.P4RtUdfWrapper() - - self._p4rt_acl_group_member_obj.set_up_databases(dvs) - self._p4rt_acl_group_obj.set_up_databases(dvs) - self._p4rt_acl_table_definition_obj.set_up_databases(dvs) - self._p4rt_acl_rule_obj.set_up_databases(dvs) - self._p4rt_acl_counter_obj.set_up_databases(dvs) - self._p4rt_acl_meter_obj.set_up_databases(dvs) - self._p4rt_trap_group_obj.set_up_databases(dvs) - self._p4rt_user_trap_obj.set_up_databases(dvs) - self._p4rt_hostif_obj.set_up_databases(dvs) - self._p4rt_hostif_table_entry_obj.set_up_databases(dvs) - self._p4rt_udf_group_obj.set_up_databases(dvs) - self._p4rt_udf_match_obj.set_up_databases(dvs) - self._p4rt_udf_obj.set_up_databases(dvs) - - self.response_consumer = swsscommon.NotificationConsumer( - self._p4rt_acl_table_definition_obj.appl_db, "APPL_DB_" + - swsscommon.APP_P4RT_TABLE_NAME + "_RESPONSE_CHANNEL" - ) - - @pytest.mark.skip(reason="p4orch is not enabled") - def test_AclRulesAddUpdateDelPass(self, dvs, testlog): - # initialize ACL table objects and database connectors - self._set_up(dvs) - - # maintain list of original Application and ASIC DB entries before adding - # new ACL table - original_appl_acl_tables = util.get_keys( - self._p4rt_acl_table_definition_obj.appl_db, - self._p4rt_acl_table_definition_obj.APP_DB_TBL_NAME - + ":" - + self._p4rt_acl_table_definition_obj.TBL_NAME, - ) - original_asic_acl_tables = util.get_keys( - self._p4rt_acl_table_definition_obj.asic_db, - self._p4rt_acl_table_definition_obj.ASIC_DB_TBL_NAME, - ) - original_asic_udf_groups = util.get_keys( - self._p4rt_udf_group_obj.asic_db, self._p4rt_udf_group_obj.ASIC_DB_TBL_NAME - ) - original_asic_udf_matches = util.get_keys( - self._p4rt_udf_match_obj.asic_db, self._p4rt_udf_match_obj.ASIC_DB_TBL_NAME - ) - original_asic_udfs = util.get_keys( - self._p4rt_udf_obj.asic_db, self._p4rt_udf_obj.ASIC_DB_TBL_NAME - ) - - # query ASIC database for ACL groups - acl_groups_asic_keys = util.get_keys( - self._p4rt_acl_group_obj.asic_db, self._p4rt_acl_group_obj.ASIC_DB_TBL_NAME - ) - assert ( - len(acl_groups_asic_keys) == 3 - ) # INGRESS, EGRESS and PRE_INGRESS bind to SWITCH - switch_oid = get_exist_entry(dvs, "ASIC_STATE:SAI_OBJECT_TYPE_SWITCH") - # Ingress - ingress_group_oids = self._p4rt_acl_group_obj.get_group_oids_by_stage( - acl.INGRESS_STAGE - ) - assert len(ingress_group_oids) == 1 - # Egress - egress_group_oids = self._p4rt_acl_group_obj.get_group_oids_by_stage( - acl.EGRESS_STAGE - ) - assert len(egress_group_oids) == 1 - # Pre_ingress - pre_ingress_group_oids = self._p4rt_acl_group_obj.get_group_oids_by_stage( - acl.PRE_INGRESS_STAGE - ) - assert len(pre_ingress_group_oids) == 1 - verify_selected_attr_vals( - self._p4rt_acl_group_obj.asic_db, - "ASIC_STATE:SAI_OBJECT_TYPE_SWITCH", - switch_oid, - [("SAI_SWITCH_ATTR_PRE_INGRESS_ACL", pre_ingress_group_oids[0]), - ("SAI_SWITCH_ATTR_INGRESS_ACL", ingress_group_oids[0]), - ("SAI_SWITCH_ATTR_EGRESS_ACL", egress_group_oids[0])], - ) - - # Verify APP DB trap groups for QOS_QUEUE - genetlink_name = "genl_packet" - genetlink_mcgrp_name = "packets" - - for queue_num in range(1, 9): - attr_list = [ - (self._p4rt_trap_group_obj.QUEUE, str(queue_num)), - (self._p4rt_trap_group_obj.HOSTIF_NAME, genetlink_name), - ( - self._p4rt_trap_group_obj.HOSTIF_GENETLINK_MCGRP_NAME, - genetlink_mcgrp_name, - ), - ] - - # query application database for trap group - (status, fvs) = util.get_key( - self._p4rt_trap_group_obj.appl_db, - self._p4rt_trap_group_obj.APP_DB_TBL_NAME, - self._p4rt_trap_group_obj.TBL_NAME_PREFIX + str(queue_num), - ) - assert status == True - util.verify_attr(fvs, attr_list) - - # create ACL table - table_name = "ACL_PUNT_TABLE_RULE_TEST" - stage = "INGRESS" - priority = "234" - size = "123" - ether_type = '{"kind":"sai_field","sai_field":"SAI_ACL_TABLE_ATTR_FIELD_ETHER_TYPE","format":"HEX_STRING","bitwidth":8}' - ether_dst = '{"kind":"sai_field","sai_field":"SAI_ACL_TABLE_ATTR_FIELD_DST_MAC","format":"MAC","bitwidth":48}' - l3_class_id = '{"kind":"sai_field","sai_field":"SAI_ACL_TABLE_ATTR_FIELD_ROUTE_DST_USER_META","format":"HEX_STRING","bitwidth":6}' - is_ip = '{"kind":"sai_field","sai_field":"SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE/IP","format":"HEX_STRING","bitwidth":1}' - is_ipv4 = '{"kind":"sai_field","sai_field":"SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE/IPV4ANY","format":"HEX_STRING","bitwidth":1}' - is_ipv6 = '{"kind":"sai_field","sai_field":"SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE/IPV6ANY","format":"HEX_STRING","bitwidth":1}' - is_arp = '{"kind":"sai_field","sai_field":"SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE/ARP","format":"HEX_STRING","bitwidth":1}' - arp_tpa = """{\"kind\":\"composite\",\"format\":\"HEX_STRING\",\"bitwidth\":32, - \"elements\":[{\"kind\":\"udf\",\"base\":\"SAI_UDF_BASE_L3\",\"bitwidth\":16,\"offset\":24}, - {\"kind\":\"udf\",\"base\":\"SAI_UDF_BASE_L3\",\"bitwidth\":16,\"offset\":26}]} - """ - src_ipv6_64bit = """{\"kind\":\"composite\",\"format\":\"IPV6\",\"bitwidth\":64, - \"elements\":[{\"kind\":\"sai_field\",\"sai_field\":\"SAI_ACL_TABLE_ATTR_FIELD_SRC_IPV6_WORD3\",\"bitwidth\":32}, - {\"kind\":\"sai_field\",\"sai_field\":\"SAI_ACL_TABLE_ATTR_FIELD_SRC_IPV6_WORD2\",\"bitwidth\":32}]} - """ - meter_unit = "PACKETS" - counter_unit = "BOTH" - copy_and_set_tc = '[{"action":"SAI_PACKET_ACTION_COPY"},{"action":"SAI_ACL_ENTRY_ATTR_ACTION_SET_TC","param":"traffic_class"}]' - punt_and_set_tc = '[{"action":"SAI_PACKET_ACTION_TRAP","packet_color":"SAI_PACKET_COLOR_RED"},{"action":"SAI_ACL_ENTRY_ATTR_ACTION_SET_TC","param":"traffic_class"}]' - qos_queue = '[{"action":"SAI_PACKET_ACTION_TRAP"},{"action":"QOS_QUEUE","param":"cpu_queue"}]' - - attr_list = [ - (self._p4rt_acl_table_definition_obj.STAGE_FIELD, stage), - (self._p4rt_acl_table_definition_obj.PRIORITY_FIELD, priority), - (self._p4rt_acl_table_definition_obj.SIZE_FIELD, size), - (self._p4rt_acl_table_definition_obj.MATCH_FIELD_ETHER_DST, ether_dst), - (self._p4rt_acl_table_definition_obj.MATCH_FIELD_ETHER_TYPE, ether_type), - (self._p4rt_acl_table_definition_obj.MATCH_FIELD_L3_CLASS_ID, l3_class_id), - (self._p4rt_acl_table_definition_obj.MATCH_FIELD_IS_IP, is_ip), - (self._p4rt_acl_table_definition_obj.MATCH_FIELD_IS_IPV4, is_ipv4), - (self._p4rt_acl_table_definition_obj.MATCH_FIELD_IS_IPV6, is_ipv6), - (self._p4rt_acl_table_definition_obj.MATCH_FIELD_IS_ARP, is_arp), - ( - self._p4rt_acl_table_definition_obj.MATCH_FIELD_SRC_IPV6_64BIT, - src_ipv6_64bit, - ), - (self._p4rt_acl_table_definition_obj.MATCH_FIELD_ARP_TPA, arp_tpa), - ( - self._p4rt_acl_table_definition_obj.ACTION_COPY_AND_SET_TC, - copy_and_set_tc, - ), - ( - self._p4rt_acl_table_definition_obj.ACTION_PUNT_AND_SET_TC, - punt_and_set_tc, - ), - (self._p4rt_acl_table_definition_obj.ACTION_SET_QOS_QUEUE, qos_queue), - (self._p4rt_acl_table_definition_obj.METER_UNIT, meter_unit), - (self._p4rt_acl_table_definition_obj.COUNTER_UNIT, counter_unit), - ] - - self._p4rt_acl_table_definition_obj.set_app_db_entry( - self._p4rt_acl_table_definition_obj.TBL_NAME + ":" + table_name, attr_list - ) - util.verify_response( - self.response_consumer, - self._p4rt_acl_table_definition_obj.TBL_NAME + ":" + table_name, - attr_list, - "SWSS_RC_SUCCESS", - ) - - # query application database for ACL tables - acl_tables = util.get_keys( - self._p4rt_acl_table_definition_obj.appl_db, - self._p4rt_acl_table_definition_obj.APP_DB_TBL_NAME - + ":" - + self._p4rt_acl_table_definition_obj.TBL_NAME, - ) - assert len(acl_tables) == len(original_appl_acl_tables) + 1 - - # query application database for newly created ACL table - (status, fvs) = util.get_key( - self._p4rt_acl_table_definition_obj.appl_db, - self._p4rt_acl_table_definition_obj.APP_DB_TBL_NAME - + ":" - + self._p4rt_acl_table_definition_obj.TBL_NAME, - table_name, - ) - assert status == True - util.verify_attr(fvs, attr_list) - - asic_udf_matches = util.get_keys( - self._p4rt_udf_match_obj.asic_db, self._p4rt_udf_match_obj.ASIC_DB_TBL_NAME - ) - - # query ASIC database for default UDF wildcard match - udf_match_asic_db_keys = [ - key for key in asic_udf_matches if key not in original_asic_udf_matches - ] - - assert len(udf_match_asic_db_keys) == 1 - udf_match_asic_db_key = udf_match_asic_db_keys[0] - - (status, fvs) = util.get_key( - self._p4rt_udf_match_obj.asic_db, - self._p4rt_udf_match_obj.ASIC_DB_TBL_NAME, - udf_match_asic_db_key, - ) - assert status == True - attr_list = [("NULL", "NULL")] - util.verify_attr(fvs, attr_list) - - # query ASIC database for UDF groups - udf_groups_asic = util.get_keys( - self._p4rt_udf_group_obj.asic_db, self._p4rt_udf_group_obj.ASIC_DB_TBL_NAME - ) - assert len(udf_groups_asic) == len(original_asic_udf_groups) + 2 - - # query ASIC database for newly created UDF groups - udf_groups_asic_db_keys = [ - key for key in udf_groups_asic if key not in original_asic_udf_groups - ] - assert len(udf_groups_asic_db_keys) == 2 - udf_groups_asic_db_keys.sort() - udf_group_min_asic_db_key = udf_groups_asic_db_keys[0] - udf_group_1_asic_db_key = udf_groups_asic_db_keys[1] - - (status, fvs) = util.get_key( - self._p4rt_udf_group_obj.asic_db, - self._p4rt_udf_group_obj.ASIC_DB_TBL_NAME, - udf_group_min_asic_db_key, - ) - assert status == True - attr_list = [ - ( - self._p4rt_udf_group_obj.SAI_UDF_GROUP_ATTR_TYPE, - self._p4rt_udf_group_obj.SAI_UDF_GROUP_TYPE_GENERIC, - ), - (self._p4rt_udf_group_obj.SAI_UDF_GROUP_ATTR_LENGTH, "2"), - ] - util.verify_attr(fvs, attr_list) - - (status, fvs) = util.get_key( - self._p4rt_udf_group_obj.asic_db, - self._p4rt_udf_group_obj.ASIC_DB_TBL_NAME, - udf_group_1_asic_db_key, - ) - assert status == True - attr_list = [ - ( - self._p4rt_udf_group_obj.SAI_UDF_GROUP_ATTR_TYPE, - self._p4rt_udf_group_obj.SAI_UDF_GROUP_TYPE_GENERIC, - ), - (self._p4rt_udf_group_obj.SAI_UDF_GROUP_ATTR_LENGTH, "2"), - ] - util.verify_attr(fvs, attr_list) - - # query ASIC database for UDFs - udfs_asic = util.get_keys( - self._p4rt_udf_obj.asic_db, self._p4rt_udf_obj.ASIC_DB_TBL_NAME - ) - assert len(udfs_asic) == len(original_asic_udfs) + 2 - - # query ASIC database for newly created UDFs - udfs_asic_db_keys = [ - key for key in udfs_asic if key not in original_asic_udfs] - assert len(udfs_asic_db_keys) == 2 - udfs_asic_db_keys.sort() - udf_0_asic_db_key = udfs_asic_db_keys[0] - udf_1_asic_db_key = udfs_asic_db_keys[1] - - (status, fvs) = util.get_key( - self._p4rt_udf_obj.asic_db, - self._p4rt_udf_obj.ASIC_DB_TBL_NAME, - udf_0_asic_db_key, - ) - assert status == True - attr_list = [ - (self._p4rt_udf_obj.SAI_UDF_ATTR_MATCH_ID, udf_match_asic_db_key), - (self._p4rt_udf_obj.SAI_UDF_ATTR_GROUP_ID, udf_group_min_asic_db_key), - (self._p4rt_udf_obj.SAI_UDF_ATTR_OFFSET, "24"), - (self._p4rt_udf_obj.SAI_UDF_ATTR_BASE, "SAI_UDF_BASE_L3"), - ] - util.verify_attr(fvs, attr_list) - - (status, fvs) = util.get_key( - self._p4rt_udf_obj.asic_db, - self._p4rt_udf_obj.ASIC_DB_TBL_NAME, - udf_1_asic_db_key, - ) - assert status == True - attr_list = [ - (self._p4rt_udf_obj.SAI_UDF_ATTR_MATCH_ID, udf_match_asic_db_key), - (self._p4rt_udf_obj.SAI_UDF_ATTR_GROUP_ID, udf_group_1_asic_db_key), - (self._p4rt_udf_obj.SAI_UDF_ATTR_OFFSET, "26"), - (self._p4rt_udf_obj.SAI_UDF_ATTR_BASE, "SAI_UDF_BASE_L3"), - ] - util.verify_attr(fvs, attr_list) - - # query ASIC database for ACL tables - acl_asic_tables = util.get_keys( - self._p4rt_acl_table_definition_obj.asic_db, - self._p4rt_acl_table_definition_obj.ASIC_DB_TBL_NAME, - ) - assert len(acl_asic_tables) == len(original_asic_acl_tables) + 1 - - # query ASIC database for newly created ACL table - table_asic_db_keys = [ - key for key in acl_asic_tables if key not in original_asic_acl_tables - ] - assert len(table_asic_db_keys) == 1 - table_asic_db_key = table_asic_db_keys[0] - - (status, fvs) = util.get_key( - self._p4rt_acl_table_definition_obj.asic_db, - self._p4rt_acl_table_definition_obj.ASIC_DB_TBL_NAME, - table_asic_db_key, - ) - assert status == True - attr_list = [ - ( - self._p4rt_acl_table_definition_obj.SAI_ACL_TABLE_ATTR_ACL_STAGE, - "SAI_ACL_STAGE_INGRESS", - ), - (self._p4rt_acl_table_definition_obj.SAI_ACL_TABLE_ATTR_SIZE, size), - (self._p4rt_acl_table_definition_obj.SAI_ATTR_MATCH_ETHER_TYPE, "true"), - (self._p4rt_acl_table_definition_obj.SAI_ATTR_MATCH_ROUTE_DST_USER_META, "true"), - (self._p4rt_acl_table_definition_obj.SAI_ATTR_MATCH_IP_TYPE, "true"), - (self._p4rt_acl_table_definition_obj.SAI_ATTR_MATCH_DST_MAC, "true"), - (self._p4rt_acl_table_definition_obj.SAI_ATTR_MATCH_SRC_IPV6_WORD3, "true"), - (self._p4rt_acl_table_definition_obj.SAI_ATTR_MATCH_SRC_IPV6_WORD2, "true"), - ( - self._p4rt_acl_table_definition_obj.SAI_ATTR_MATCH_UDF_GROUP_MIN, - udf_group_min_asic_db_key, - ), - ( - self._p4rt_acl_table_definition_obj.SAI_ATTR_MATCH_UDF_GROUP_1, - udf_group_1_asic_db_key, - ), - ( - self._p4rt_acl_table_definition_obj.SAI_ATTR_ACTION_TYPE_LIST, - "1:SAI_ACL_ACTION_TYPE_COUNTER", - ), - ] - util.verify_attr(fvs, attr_list) - - # maintain list of original Application and ASIC DB ACL entries before adding - # new ACL rule - original_appl_acl_rules = util.get_keys( - self._p4rt_acl_rule_obj.appl_db, - self._p4rt_acl_rule_obj.APP_DB_TBL_NAME + ":" + table_name, - ) - original_asic_acl_rules = util.get_keys( - self._p4rt_acl_rule_obj.asic_db, self._p4rt_acl_rule_obj.ASIC_DB_TBL_NAME - ) - original_asic_acl_counters = util.get_keys( - self._p4rt_acl_counter_obj.asic_db, - self._p4rt_acl_counter_obj.ASIC_DB_TBL_NAME, - ) - original_asic_acl_meters = util.get_keys( - self._p4rt_acl_meter_obj.asic_db, self._p4rt_acl_meter_obj.ASIC_DB_TBL_NAME - ) - - # create ACL rule 1 - rule_json_key1 = '{"match/ether_type":"0x0800","match/ether_dst":"00:1a:11:17:5f:80","match/src_ipv6_64bit":"fdf8:f53b:82e4::","match/arp_tpa":"0xff665543","priority":100}' - action = "copy_and_set_tc" - meter_cir = "80" - meter_cbs = "80" - meter_pir = "200" - meter_pbs = "200" - table_name_with_rule_key1 = table_name + ":" + rule_json_key1 - - attr_list = [ - (self._p4rt_acl_rule_obj.ACTION, action), - ("param/traffic_class", "1"), - (self._p4rt_acl_rule_obj.METER_CIR, meter_cir), - (self._p4rt_acl_rule_obj.METER_CBURST, meter_cbs), - (self._p4rt_acl_rule_obj.METER_PIR, meter_pir), - (self._p4rt_acl_rule_obj.METER_PBURST, meter_pbs), - ] - - self._p4rt_acl_rule_obj.set_app_db_entry( - table_name_with_rule_key1, attr_list) - util.verify_response( - self.response_consumer, - table_name_with_rule_key1, - attr_list, - "SWSS_RC_SUCCESS", - ) - - # query application database for ACL rules - acl_rules = util.get_keys( - self._p4rt_acl_rule_obj.appl_db, - self._p4rt_acl_rule_obj.APP_DB_TBL_NAME + ":" + table_name, - ) - assert len(acl_rules) == len(original_appl_acl_rules) + 1 - - # query application database for newly created ACL rule - (status, fvs) = util.get_key( - self._p4rt_acl_rule_obj.appl_db, - self._p4rt_acl_table_definition_obj.APP_DB_TBL_NAME, - table_name_with_rule_key1, - ) - assert status == True - util.verify_attr(fvs, attr_list) - - # query ASIC database for ACL counters - acl_asic_counters = util.get_keys( - self._p4rt_acl_counter_obj.asic_db, - self._p4rt_acl_counter_obj.ASIC_DB_TBL_NAME, - ) - assert len(acl_asic_counters) == len(original_asic_acl_counters) + 1 - - # query ASIC database for newly created ACL counter - counter_asic_db_keys = [ - key for key in acl_asic_counters if key not in original_asic_acl_counters - ] - assert len(counter_asic_db_keys) == 1 - counter_asic_db_key1 = counter_asic_db_keys[0] - - (status, fvs) = util.get_key( - self._p4rt_acl_counter_obj.asic_db, - self._p4rt_acl_counter_obj.ASIC_DB_TBL_NAME, - counter_asic_db_key1, - ) - assert status == True - attr_list = [ - (self._p4rt_acl_counter_obj.SAI_ATTR_ENABLE_PACKET_COUNT, "true"), - (self._p4rt_acl_counter_obj.SAI_ATTR_ENABLE_BYTE_COUNT, "true"), - (self._p4rt_acl_counter_obj.SAI_ATTR_TABLE_ID, table_asic_db_key), - ] - util.verify_attr(fvs, attr_list) - - # query ASIC database for ACL meters - acl_asic_meters = util.get_keys( - self._p4rt_acl_meter_obj.asic_db, self._p4rt_acl_meter_obj.ASIC_DB_TBL_NAME - ) - assert len(acl_asic_meters) == len(original_asic_acl_meters) + 1 - - # query ASIC database for newly created ACL meter - meter_asic_db_keys = [ - key for key in acl_asic_meters if key not in original_asic_acl_meters - ] - assert len(meter_asic_db_keys) == 1 - meter_asic_db_key1 = meter_asic_db_keys[0] - - (status, fvs) = util.get_key( - self._p4rt_acl_meter_obj.asic_db, - self._p4rt_acl_meter_obj.ASIC_DB_TBL_NAME, - meter_asic_db_key1, - ) - assert status == True - attr_list = [ - (self._p4rt_acl_meter_obj.SAI_ATTR_METER_TYPE, "SAI_METER_TYPE_PACKETS"), - (self._p4rt_acl_meter_obj.SAI_ATTR_METER_MODE, "SAI_POLICER_MODE_TR_TCM"), - (self._p4rt_acl_meter_obj.SAI_ATTR_METER_CIR, meter_cir), - (self._p4rt_acl_meter_obj.SAI_ATTR_METER_CBS, meter_cbs), - (self._p4rt_acl_meter_obj.SAI_ATTR_METER_PIR, meter_pir), - (self._p4rt_acl_meter_obj.SAI_ATTR_METER_PBS, meter_pbs), - ] - util.verify_attr(fvs, attr_list) - - # query ASIC database for ACL rules - acl_asic_rules = util.get_keys( - self._p4rt_acl_rule_obj.asic_db, self._p4rt_acl_rule_obj.ASIC_DB_TBL_NAME - ) - assert len(acl_asic_rules) == len(original_asic_acl_rules) + 1 - - # query ASIC database for newly created ACL rule - rule_asic_db_keys = [ - key for key in acl_asic_rules if key not in original_asic_acl_rules - ] - assert len(rule_asic_db_keys) == 1 - rule_asic_db_key1 = rule_asic_db_keys[0] - - (status, fvs) = util.get_key( - self._p4rt_acl_rule_obj.asic_db, - self._p4rt_acl_rule_obj.ASIC_DB_TBL_NAME, - rule_asic_db_key1, - ) - assert status == True - attr_list = [ - (self._p4rt_acl_rule_obj.SAI_ATTR_ACTION_SET_TC, "1"), - ( - self._p4rt_acl_rule_obj.SAI_ATTR_ACTION_PACKET_ACTION, - "SAI_PACKET_ACTION_COPY", - ), - (self._p4rt_acl_rule_obj.SAI_ATTR_MATCH_ETHER_TYPE, "2048&mask:0xffff"), - ( - self._p4rt_acl_rule_obj.SAI_ATTR_MATCH_IP_TYPE, - "SAI_ACL_IP_TYPE_ANY&mask:0xffffffffffffffff", - ), - ( - self._p4rt_acl_rule_obj.SAI_ATTR_MATCH_DST_MAC, - "00:1A:11:17:5F:80&mask:FF:FF:FF:FF:FF:FF", - ), - ( - self._p4rt_acl_rule_obj.SAI_ATTR_MATCH_SRC_IPV6_WORD3, - "fdf8:f53b::&mask:ffff:ffff::", - ), - ( - self._p4rt_acl_rule_obj.SAI_ATTR_MATCH_SRC_IPV6_WORD2, - "0:0:82e4::&mask:0:0:ffff:ffff::", - ), - ( - self._p4rt_acl_rule_obj.SAI_ATTR_MATCH_UDF_GROUP_MIN, - "2:255,102&mask:2:0xff,0xff", - ), - ( - self._p4rt_acl_rule_obj.SAI_ATTR_MATCH_UDF_GROUP_1, - "2:85,67&mask:2:0xff,0xff", - ), - (self._p4rt_acl_rule_obj.SAI_ATTR_TABLE_ID, table_asic_db_key), - (self._p4rt_acl_rule_obj.SAI_ATTR_SET_POLICER, meter_asic_db_key1), - (self._p4rt_acl_rule_obj.SAI_ATTR_COUNTER, counter_asic_db_key1), - (self._p4rt_acl_rule_obj.SAI_ATTR_ADMIN_STATE, "true"), - (self._p4rt_acl_rule_obj.SAI_ATTR_PRIORITY, "100"), - ] - util.verify_attr(fvs, attr_list) - - # Update action and meter of rule 1 to punt_and_set_tc - rule_json_key1 = '{"match/ether_type":"0x0800","match/ether_dst":"00:1a:11:17:5f:80","match/src_ipv6_64bit":"fdf8:f53b:82e4::","match/arp_tpa":"0xff665543","priority":100}' - action = "punt_and_set_tc" - meter_cir = "100" - meter_cbs = "100" - meter_pir = "400" - meter_pbs = "400" - table_name_with_rule_key1 = table_name + ":" + rule_json_key1 - - attr_list = [ - (self._p4rt_acl_rule_obj.ACTION, action), - ("param/traffic_class", "2"), - (self._p4rt_acl_rule_obj.METER_CIR, meter_cir), - (self._p4rt_acl_rule_obj.METER_CBURST, meter_cbs), - (self._p4rt_acl_rule_obj.METER_PIR, meter_pir), - (self._p4rt_acl_rule_obj.METER_PBURST, meter_pbs), - ] - - self._p4rt_acl_rule_obj.set_app_db_entry( - table_name_with_rule_key1, attr_list) - util.verify_response( - self.response_consumer, - table_name_with_rule_key1, - attr_list, - "SWSS_RC_SUCCESS", - ) - - # query application database for ACL rules - acl_rules = util.get_keys( - self._p4rt_acl_rule_obj.appl_db, - self._p4rt_acl_rule_obj.APP_DB_TBL_NAME + ":" + table_name, - ) - assert len(acl_rules) == len(original_appl_acl_rules) + 1 - - # query application database for updated ACL rule - (status, fvs) = util.get_key( - self._p4rt_acl_rule_obj.appl_db, - self._p4rt_acl_table_definition_obj.APP_DB_TBL_NAME, - table_name_with_rule_key1, - ) - assert status == True - util.verify_attr(fvs, attr_list) - - # query ASIC database for ACL counters - acl_asic_counters = util.get_keys( - self._p4rt_acl_counter_obj.asic_db, - self._p4rt_acl_counter_obj.ASIC_DB_TBL_NAME, - ) - assert len(acl_asic_counters) == len(original_asic_acl_counters) + 1 - - # query ASIC database for the ACL counter - counter_asic_db_keys = [ - key for key in acl_asic_counters if key not in original_asic_acl_counters - ] - assert len(counter_asic_db_keys) == 1 - counter_asic_db_key1 = counter_asic_db_keys[0] - - (status, fvs) = util.get_key( - self._p4rt_acl_counter_obj.asic_db, - self._p4rt_acl_counter_obj.ASIC_DB_TBL_NAME, - counter_asic_db_key1, - ) - assert status == True - attr_list = [ - (self._p4rt_acl_counter_obj.SAI_ATTR_ENABLE_PACKET_COUNT, "true"), - (self._p4rt_acl_counter_obj.SAI_ATTR_ENABLE_BYTE_COUNT, "true"), - (self._p4rt_acl_counter_obj.SAI_ATTR_TABLE_ID, table_asic_db_key), - ] - util.verify_attr(fvs, attr_list) - - # query ASIC database for ACL meters - acl_asic_meters = util.get_keys( - self._p4rt_acl_meter_obj.asic_db, self._p4rt_acl_meter_obj.ASIC_DB_TBL_NAME - ) - assert len(acl_asic_meters) == len(original_asic_acl_meters) + 1 - - # query ASIC database for updated ACL meter - meter_asic_db_keys = [ - key for key in acl_asic_meters if key not in original_asic_acl_meters - ] - assert len(meter_asic_db_keys) == 1 - meter_asic_db_key1 = meter_asic_db_keys[0] - - (status, fvs) = util.get_key( - self._p4rt_acl_meter_obj.asic_db, - self._p4rt_acl_meter_obj.ASIC_DB_TBL_NAME, - meter_asic_db_key1, - ) - assert status == True - attr_list = [ - (self._p4rt_acl_meter_obj.SAI_ATTR_METER_TYPE, "SAI_METER_TYPE_PACKETS"), - (self._p4rt_acl_meter_obj.SAI_ATTR_METER_MODE, "SAI_POLICER_MODE_TR_TCM"), - (self._p4rt_acl_meter_obj.SAI_ATTR_METER_CIR, meter_cir), - (self._p4rt_acl_meter_obj.SAI_ATTR_METER_CBS, meter_cbs), - (self._p4rt_acl_meter_obj.SAI_ATTR_METER_PIR, meter_pir), - (self._p4rt_acl_meter_obj.SAI_ATTR_METER_PBS, meter_pbs), - ( - self._p4rt_acl_meter_obj.SAI_ATTR_RED_PACKET_ACTION, - "SAI_PACKET_ACTION_TRAP", - ), - ] - util.verify_attr(fvs, attr_list) - - # query ASIC database for ACL rules - acl_asic_rules = util.get_keys( - self._p4rt_acl_rule_obj.asic_db, self._p4rt_acl_rule_obj.ASIC_DB_TBL_NAME - ) - assert len(acl_asic_rules) == len(original_asic_acl_rules) + 1 - - # query ASIC database for updated ACL rule - rule_asic_db_keys = [ - key for key in acl_asic_rules if key not in original_asic_acl_rules - ] - assert len(rule_asic_db_keys) == 1 - rule_asic_db_key1 = rule_asic_db_keys[0] - - (status, fvs) = util.get_key( - self._p4rt_acl_rule_obj.asic_db, - self._p4rt_acl_rule_obj.ASIC_DB_TBL_NAME, - rule_asic_db_key1, - ) - assert status == True - attr_list = [ - (self._p4rt_acl_rule_obj.SAI_ATTR_ACTION_SET_TC, "2"), - (self._p4rt_acl_rule_obj.SAI_ATTR_ACTION_PACKET_ACTION, "disabled"), - (self._p4rt_acl_rule_obj.SAI_ATTR_MATCH_ETHER_TYPE, "2048&mask:0xffff"), - ( - self._p4rt_acl_rule_obj.SAI_ATTR_MATCH_IP_TYPE, - "SAI_ACL_IP_TYPE_ANY&mask:0xffffffffffffffff", - ), - ( - self._p4rt_acl_rule_obj.SAI_ATTR_MATCH_DST_MAC, - "00:1A:11:17:5F:80&mask:FF:FF:FF:FF:FF:FF", - ), - ( - self._p4rt_acl_rule_obj.SAI_ATTR_MATCH_SRC_IPV6_WORD3, - "fdf8:f53b::&mask:ffff:ffff::", - ), - ( - self._p4rt_acl_rule_obj.SAI_ATTR_MATCH_SRC_IPV6_WORD2, - "0:0:82e4::&mask:0:0:ffff:ffff::", - ), - ( - self._p4rt_acl_rule_obj.SAI_ATTR_MATCH_UDF_GROUP_MIN, - "2:255,102&mask:2:0xff,0xff", - ), - ( - self._p4rt_acl_rule_obj.SAI_ATTR_MATCH_UDF_GROUP_1, - "2:85,67&mask:2:0xff,0xff", - ), - (self._p4rt_acl_rule_obj.SAI_ATTR_TABLE_ID, table_asic_db_key), - (self._p4rt_acl_rule_obj.SAI_ATTR_SET_POLICER, meter_asic_db_key1), - (self._p4rt_acl_rule_obj.SAI_ATTR_COUNTER, counter_asic_db_key1), - (self._p4rt_acl_rule_obj.SAI_ATTR_ADMIN_STATE, "true"), - (self._p4rt_acl_rule_obj.SAI_ATTR_PRIORITY, "100"), - ] - util.verify_attr(fvs, attr_list) - - # create ACL rule 2 with QOS_QUEUE action - rule_json_key2 = '{"match/is_ip":"0x1","match/ether_type":"0x0800 & 0xFFFF","match/ether_dst":"AA:BB:CC:DD:EE:FF & FF:FF:FF:FF:FF:FF","priority":100}' - action = "qos_queue" - meter_cir = "80" - meter_cbs = "80" - meter_pir = "200" - meter_pbs = "200" - table_name_with_rule_key2 = table_name + ":" + rule_json_key2 - - attr_list = [ - (self._p4rt_acl_rule_obj.ACTION, action), - ("param/cpu_queue", "5"), - (self._p4rt_acl_rule_obj.METER_CIR, meter_cir), - (self._p4rt_acl_rule_obj.METER_CBURST, meter_cbs), - (self._p4rt_acl_rule_obj.METER_PIR, meter_pir), - (self._p4rt_acl_rule_obj.METER_PBURST, meter_pbs), - ] - - self._p4rt_acl_rule_obj.set_app_db_entry( - table_name_with_rule_key2, attr_list) - util.verify_response( - self.response_consumer, - table_name_with_rule_key2, - attr_list, - "SWSS_RC_SUCCESS", - ) - - # query application database for ACL rules - acl_rules = util.get_keys( - self._p4rt_acl_rule_obj.appl_db, - self._p4rt_acl_rule_obj.APP_DB_TBL_NAME + ":" + table_name, - ) - assert len(acl_rules) == len(original_appl_acl_rules) + 2 - - # query application database for newly created ACL rule - (status, fvs) = util.get_key( - self._p4rt_acl_rule_obj.appl_db, - self._p4rt_acl_table_definition_obj.APP_DB_TBL_NAME, - table_name_with_rule_key2, - ) - assert status == True - util.verify_attr(fvs, attr_list) - - # query ASIC database for ACL counters - acl_asic_counters = util.get_keys( - self._p4rt_acl_counter_obj.asic_db, - self._p4rt_acl_counter_obj.ASIC_DB_TBL_NAME, - ) - assert len(acl_asic_counters) == len(original_asic_acl_counters) + 2 - - # query ASIC database for newly created ACL counter - counter_asic_db_keys = [ - key - for key in acl_asic_counters - if key not in original_asic_acl_counters and key != counter_asic_db_key1 - ] - assert len(counter_asic_db_keys) == 1 - counter_asic_db_key2 = counter_asic_db_keys[0] - - (status, fvs) = util.get_key( - self._p4rt_acl_counter_obj.asic_db, - self._p4rt_acl_counter_obj.ASIC_DB_TBL_NAME, - counter_asic_db_key2, - ) - assert status == True - attr_list = [ - (self._p4rt_acl_counter_obj.SAI_ATTR_ENABLE_PACKET_COUNT, "true"), - (self._p4rt_acl_counter_obj.SAI_ATTR_ENABLE_BYTE_COUNT, "true"), - (self._p4rt_acl_counter_obj.SAI_ATTR_TABLE_ID, table_asic_db_key), - ] - util.verify_attr(fvs, attr_list) - - # query ASIC database for ACL meters - acl_asic_meters = util.get_keys( - self._p4rt_acl_meter_obj.asic_db, self._p4rt_acl_meter_obj.ASIC_DB_TBL_NAME - ) - assert len(acl_asic_meters) == len(original_asic_acl_meters) + 2 - - # query ASIC database for newly created ACL meter - meter_asic_db_keys = [ - key - for key in acl_asic_meters - if key not in original_asic_acl_meters and key != meter_asic_db_key1 - ] - assert len(meter_asic_db_keys) == 1 - meter_asic_db_key2 = meter_asic_db_keys[0] - - (status, fvs) = util.get_key( - self._p4rt_acl_meter_obj.asic_db, - self._p4rt_acl_meter_obj.ASIC_DB_TBL_NAME, - meter_asic_db_key2, - ) - assert status == True - attr_list = [ - (self._p4rt_acl_meter_obj.SAI_ATTR_METER_TYPE, "SAI_METER_TYPE_PACKETS"), - (self._p4rt_acl_meter_obj.SAI_ATTR_METER_MODE, "SAI_POLICER_MODE_TR_TCM"), - (self._p4rt_acl_meter_obj.SAI_ATTR_METER_CIR, meter_cir), - (self._p4rt_acl_meter_obj.SAI_ATTR_METER_CBS, meter_cbs), - (self._p4rt_acl_meter_obj.SAI_ATTR_METER_PIR, meter_pir), - (self._p4rt_acl_meter_obj.SAI_ATTR_METER_PBS, meter_pbs), - ] - util.verify_attr(fvs, attr_list) - - # query ASIC database for trap groups - trap_group_keys = util.get_keys( - self._p4rt_trap_group_obj.asic_db, - self._p4rt_trap_group_obj.ASIC_DB_TBL_NAME, - ) - # default trap groups in and one trap groups per cpu queue - # are defined in files/image_config/copp/copp_cfg.j2 - # get trap group with cpu queue num 5 - for key in trap_group_keys: - (status, fvs) = util.get_key( - self._p4rt_trap_group_obj.asic_db, - self._p4rt_trap_group_obj.ASIC_DB_TBL_NAME, - key, - ) - assert status == True - if fvs[0][1] == "5": - trap_group_asic_db_key = key - break - - # query ASIC database for user defined traps - user_trap_keys = util.get_keys( - self._p4rt_user_trap_obj.asic_db, self._p4rt_user_trap_obj.ASIC_DB_TBL_NAME - ) - assert len(user_trap_keys) == 8 - - # get user trap with trap group oid - for key in user_trap_keys: - (status, fvs) = util.get_key( - self._p4rt_user_trap_obj.asic_db, - self._p4rt_user_trap_obj.ASIC_DB_TBL_NAME, - key, - ) - assert status == True - if ( - fvs[0][1] == trap_group_asic_db_key - or fvs[1][1] == trap_group_asic_db_key - ): - user_trap_asic_db_key = key - break - - # query ASIC database for ACL rules - acl_asic_rules = util.get_keys( - self._p4rt_acl_rule_obj.asic_db, self._p4rt_acl_rule_obj.ASIC_DB_TBL_NAME - ) - assert len(acl_asic_rules) == len(original_asic_acl_rules) + 2 - - # query ASIC database for newly created ACL rule - rule_asic_db_keys = [ - key - for key in acl_asic_rules - if key not in original_asic_acl_rules and key != rule_asic_db_key1 - ] - assert len(rule_asic_db_keys) == 1 - rule_asic_db_key2 = rule_asic_db_keys[0] - - (status, fvs) = util.get_key( - self._p4rt_acl_rule_obj.asic_db, - self._p4rt_acl_rule_obj.ASIC_DB_TBL_NAME, - rule_asic_db_key2, - ) - assert status == True - attr_list = [ - ( - self._p4rt_acl_rule_obj.SAI_ATTR_ACTION_SET_USER_TRAP_ID, - user_trap_asic_db_key, - ), - ( - self._p4rt_acl_rule_obj.SAI_ATTR_ACTION_PACKET_ACTION, - "SAI_PACKET_ACTION_TRAP", - ), - (self._p4rt_acl_rule_obj.SAI_ATTR_MATCH_ETHER_TYPE, "2048&mask:0xffff"), - ( - self._p4rt_acl_rule_obj.SAI_ATTR_MATCH_IP_TYPE, - "SAI_ACL_IP_TYPE_IP&mask:0xffffffffffffffff", - ), - ( - self._p4rt_acl_rule_obj.SAI_ATTR_MATCH_DST_MAC, - "AA:BB:CC:DD:EE:FF&mask:FF:FF:FF:FF:FF:FF", - ), - (self._p4rt_acl_rule_obj.SAI_ATTR_TABLE_ID, table_asic_db_key), - (self._p4rt_acl_rule_obj.SAI_ATTR_SET_POLICER, meter_asic_db_key2), - (self._p4rt_acl_rule_obj.SAI_ATTR_COUNTER, counter_asic_db_key2), - (self._p4rt_acl_rule_obj.SAI_ATTR_ADMIN_STATE, "true"), - (self._p4rt_acl_rule_obj.SAI_ATTR_PRIORITY, "100"), - ] - util.verify_attr(fvs, attr_list) - - # create ACL rule 3 with match field SAI_ACL_TABLE_ATTR_FIELD_ROUTE_DST_USER_META - rule_json_key3 = '{"match/ether_type":"0x0800","match/l3_class_id":"0x1", "priority":100}' - action = "copy_and_set_tc" - table_name_with_rule_key3 = table_name + ":" + rule_json_key3 - - attr_list = [ - (self._p4rt_acl_rule_obj.ACTION, action), - ("param/traffic_class", "1"), - ] - - self._p4rt_acl_rule_obj.set_app_db_entry( - table_name_with_rule_key3, attr_list) - util.verify_response( - self.response_consumer, - table_name_with_rule_key3, - attr_list, - "SWSS_RC_SUCCESS", - ) - - # query application database for ACL rules - acl_rules = util.get_keys( - self._p4rt_acl_rule_obj.appl_db, - self._p4rt_acl_rule_obj.APP_DB_TBL_NAME + ":" + table_name, - ) - assert len(acl_rules) == len(original_appl_acl_rules) + 3 - - # query application database for newly created ACL rule - (status, fvs) = util.get_key( - self._p4rt_acl_rule_obj.appl_db, - self._p4rt_acl_table_definition_obj.APP_DB_TBL_NAME, - table_name_with_rule_key3, - ) - assert status == True - util.verify_attr(fvs, attr_list) - - # query ASIC database for ACL counters - acl_asic_counters = util.get_keys( - self._p4rt_acl_counter_obj.asic_db, - self._p4rt_acl_counter_obj.ASIC_DB_TBL_NAME, - ) - assert len(acl_asic_counters) == len(original_asic_acl_counters) + 3 - - # query ASIC database for newly created ACL counter - counter_asic_db_keys = [ - key for key in acl_asic_counters - if key not in original_asic_acl_counters - and key != counter_asic_db_key1 - and key != counter_asic_db_key2 - ] - assert len(counter_asic_db_keys) == 1 - counter_asic_db_key3 = counter_asic_db_keys[0] - - (status, fvs) = util.get_key( - self._p4rt_acl_counter_obj.asic_db, - self._p4rt_acl_counter_obj.ASIC_DB_TBL_NAME, - counter_asic_db_key3, - ) - assert status == True - attr_list = [ - (self._p4rt_acl_counter_obj.SAI_ATTR_ENABLE_PACKET_COUNT, "true"), - (self._p4rt_acl_counter_obj.SAI_ATTR_ENABLE_BYTE_COUNT, "true"), - (self._p4rt_acl_counter_obj.SAI_ATTR_TABLE_ID, table_asic_db_key), - ] - util.verify_attr(fvs, attr_list) - - # query ASIC database for ACL rules - acl_asic_rules = util.get_keys( - self._p4rt_acl_rule_obj.asic_db, self._p4rt_acl_rule_obj.ASIC_DB_TBL_NAME - ) - assert len(acl_asic_rules) == len(original_asic_acl_rules) + 3 - - # query ASIC database for newly created ACL rule - rule_asic_db_keys = [ - key for key in acl_asic_rules - if key not in original_asic_acl_rules - and key != rule_asic_db_key1 - and key != rule_asic_db_key2 - ] - assert len(rule_asic_db_keys) == 1 - rule_asic_db_key3 = rule_asic_db_keys[0] - - (status, fvs) = util.get_key( - self._p4rt_acl_rule_obj.asic_db, - self._p4rt_acl_rule_obj.ASIC_DB_TBL_NAME, - rule_asic_db_key3, - ) - assert status == True - attr_list = [ - (self._p4rt_acl_rule_obj.SAI_ATTR_ACTION_SET_TC, "1"), - ( - self._p4rt_acl_rule_obj.SAI_ATTR_ACTION_PACKET_ACTION, - "SAI_PACKET_ACTION_COPY", - ), - (self._p4rt_acl_rule_obj.SAI_ATTR_MATCH_ETHER_TYPE, "2048&mask:0xffff"), - ( - self._p4rt_acl_rule_obj.SAI_ATTR_MATCH_ROUTE_DST_USER_META, - "1&mask:0xffffffff", - ), - ( - self._p4rt_acl_rule_obj.SAI_ATTR_MATCH_IP_TYPE, - "SAI_ACL_IP_TYPE_ANY&mask:0xffffffffffffffff", - ), - (self._p4rt_acl_rule_obj.SAI_ATTR_TABLE_ID, table_asic_db_key), - (self._p4rt_acl_rule_obj.SAI_ATTR_COUNTER, counter_asic_db_key3), - (self._p4rt_acl_rule_obj.SAI_ATTR_ADMIN_STATE, "true"), - (self._p4rt_acl_rule_obj.SAI_ATTR_PRIORITY, "100"), - ] - util.verify_attr(fvs, attr_list) - - # remove ACL rule 3 - self._p4rt_acl_rule_obj.remove_app_db_entry(table_name_with_rule_key3) - util.verify_response( - self.response_consumer, table_name_with_rule_key3, [], "SWSS_RC_SUCCESS" - ) - - # query application database for ACL rules - acl_rules = util.get_keys( - self._p4rt_acl_rule_obj.appl_db, - self._p4rt_acl_rule_obj.APP_DB_TBL_NAME + ":" + table_name, - ) - assert len(acl_rules) == len(original_appl_acl_rules) + 2 - - # verify that the ACL rule no longer exists in application database - (status, fvs) = util.get_key( - self._p4rt_acl_rule_obj.appl_db, - self._p4rt_acl_rule_obj.APP_DB_TBL_NAME, - table_name_with_rule_key3, - ) - assert status == False - - # query ASIC database for ACL rules - acl_rules = util.get_keys( - self._p4rt_acl_rule_obj.asic_db, self._p4rt_acl_rule_obj.ASIC_DB_TBL_NAME - ) - assert len(acl_rules) == len(original_asic_acl_rules) + 2 - - # verify that removed ACL rule no longer exists in ASIC database - (status, fvs) = util.get_key( - self._p4rt_acl_rule_obj.asic_db, - self._p4rt_acl_rule_obj.ASIC_DB_TBL_NAME, - rule_asic_db_key3, - ) - assert status == False - - # verify that removed ACL counter no longer exists in ASIC database - (status, fvs) = util.get_key( - self._p4rt_acl_counter_obj.asic_db, - self._p4rt_acl_counter_obj.ASIC_DB_TBL_NAME, - counter_asic_db_key3, - ) - assert status == False - - # remove ACL rule 1 - self._p4rt_acl_rule_obj.remove_app_db_entry(table_name_with_rule_key1) - util.verify_response( - self.response_consumer, table_name_with_rule_key1, [], "SWSS_RC_SUCCESS" - ) - - # query application database for ACL rules - acl_rules = util.get_keys( - self._p4rt_acl_rule_obj.appl_db, - self._p4rt_acl_rule_obj.APP_DB_TBL_NAME + ":" + table_name, - ) - assert len(acl_rules) == len(original_appl_acl_rules) + 1 - - # verify that the ACL rule no longer exists in application database - (status, fvs) = util.get_key( - self._p4rt_acl_rule_obj.appl_db, - self._p4rt_acl_rule_obj.APP_DB_TBL_NAME, - table_name_with_rule_key1, - ) - assert status == False - - # query ASIC database for ACL rules - acl_rules = util.get_keys( - self._p4rt_acl_rule_obj.asic_db, self._p4rt_acl_rule_obj.ASIC_DB_TBL_NAME - ) - assert len(acl_rules) == len(original_asic_acl_rules) + 1 - - # verify that removed ACL rule no longer exists in ASIC database - (status, fvs) = util.get_key( - self._p4rt_acl_rule_obj.asic_db, - self._p4rt_acl_rule_obj.ASIC_DB_TBL_NAME, - rule_asic_db_key1, - ) - assert status == False - - # verify that removed ACL counter no longer exists in ASIC database - (status, fvs) = util.get_key( - self._p4rt_acl_counter_obj.asic_db, - self._p4rt_acl_counter_obj.ASIC_DB_TBL_NAME, - counter_asic_db_key1, - ) - assert status == False - - # verify that removed ACL meter no longer exists in ASIC database - (status, fvs) = util.get_key( - self._p4rt_acl_meter_obj.asic_db, - self._p4rt_acl_meter_obj.ASIC_DB_TBL_NAME, - meter_asic_db_key1, - ) - assert status == False - - # remove ACL rule 2 - self._p4rt_acl_rule_obj.remove_app_db_entry(table_name_with_rule_key2) - util.verify_response( - self.response_consumer, table_name_with_rule_key2, [], "SWSS_RC_SUCCESS" - ) - - # query application database for ACL rules - acl_rules = util.get_keys( - self._p4rt_acl_rule_obj.appl_db, - self._p4rt_acl_rule_obj.APP_DB_TBL_NAME + ":" + table_name, - ) - assert len(acl_rules) == len(original_appl_acl_rules) - - # verify that the ACL rule no longer exists in application database - (status, fvs) = util.get_key( - self._p4rt_acl_rule_obj.appl_db, - self._p4rt_acl_rule_obj.APP_DB_TBL_NAME, - table_name_with_rule_key2, - ) - assert status == False - - # query ASIC database for ACL rules - acl_rules = util.get_keys( - self._p4rt_acl_rule_obj.asic_db, self._p4rt_acl_rule_obj.ASIC_DB_TBL_NAME - ) - assert len(acl_rules) == len(original_asic_acl_rules) - - # verify that removed ACL rule no longer exists in ASIC database - (status, fvs) = util.get_key( - self._p4rt_acl_rule_obj.asic_db, - self._p4rt_acl_rule_obj.ASIC_DB_TBL_NAME, - rule_asic_db_key2, - ) - assert status == False - - # verify that removed ACL counter no longer exists in ASIC database - (status, fvs) = util.get_key( - self._p4rt_acl_counter_obj.asic_db, - self._p4rt_acl_counter_obj.ASIC_DB_TBL_NAME, - counter_asic_db_key2, - ) - assert status == False - - # verify that removed ACL meter no longer exists in ASIC database - (status, fvs) = util.get_key( - self._p4rt_acl_meter_obj.asic_db, - self._p4rt_acl_meter_obj.ASIC_DB_TBL_NAME, - meter_asic_db_key2, - ) - assert status == False - - # remove ACL table - self._p4rt_acl_table_definition_obj.remove_app_db_entry( - self._p4rt_acl_table_definition_obj.TBL_NAME + ":" + table_name - ) - util.verify_response( - self.response_consumer, - self._p4rt_acl_table_definition_obj.TBL_NAME + ":" + table_name, - [], - "SWSS_RC_SUCCESS", - ) - - # query application database for ACL tables - acl_tables = util.get_keys( - self._p4rt_acl_table_definition_obj.appl_db, - self._p4rt_acl_table_definition_obj.APP_DB_TBL_NAME - + ":" - + self._p4rt_acl_table_definition_obj.TBL_NAME, - ) - assert len(acl_tables) == len(original_appl_acl_tables) - - # verify that the ACL table no longer exists in application database - (status, fvs) = util.get_key( - self._p4rt_acl_table_definition_obj.appl_db, - self._p4rt_acl_table_definition_obj.APP_DB_TBL_NAME, - self._p4rt_acl_table_definition_obj.TBL_NAME + ":" + table_name, - ) - assert status == False - - # query ASIC database for ACL tables - acl_tables = util.get_keys( - self._p4rt_acl_table_definition_obj.asic_db, - self._p4rt_acl_table_definition_obj.ASIC_DB_TBL_NAME, - ) - assert len(acl_tables) == len(original_asic_acl_tables) - - # verify that removed ACL table no longer exists in ASIC database - (status, fvs) = util.get_key( - self._p4rt_acl_table_definition_obj.asic_db, - self._p4rt_acl_table_definition_obj.ASIC_DB_TBL_NAME, - table_asic_db_key, - ) - assert status == False - - def test_AclRuleAddWithoutTableDefinitionFails(self, dvs, testlog): - # initialize ACL table objects and database connectors - self._set_up(dvs) - - # maintain list of original Application and ASIC DB ACL entries before adding - # new ACL rule - table_name = "ACL_PUNT_TABLE_RULE_TEST" - original_appl_acl_rules = util.get_keys( - self._p4rt_acl_rule_obj.appl_db, - self._p4rt_acl_rule_obj.APP_DB_TBL_NAME + ":" + table_name, - ) - original_asic_acl_rules = util.get_keys( - self._p4rt_acl_rule_obj.asic_db, self._p4rt_acl_rule_obj.ASIC_DB_TBL_NAME - ) - - # create ACL rule - rule_json_key = '{"match/ether_type":"0x0800","match/ether_dst":"00:1a:11:17:5f:80","match/src_ipv6_64bit":"fdf8:f53b:82e4::","match/arp_tpa":"0xff665543","priority":100}' - action = "copy_and_set_tc" - meter_cir = "80" - meter_cbs = "80" - meter_pir = "200" - meter_pbs = "200" - table_name_with_rule_key = table_name + ":" + rule_json_key - - attr_list = [ - (self._p4rt_acl_rule_obj.ACTION, action), - ("param/traffic_class", "1"), - (self._p4rt_acl_rule_obj.METER_CIR, meter_cir), - (self._p4rt_acl_rule_obj.METER_CBURST, meter_cbs), - (self._p4rt_acl_rule_obj.METER_PIR, meter_pir), - (self._p4rt_acl_rule_obj.METER_PBURST, meter_pbs), - ] - - self._p4rt_acl_rule_obj.set_app_db_entry( - table_name_with_rule_key, attr_list) - util.verify_response( - self.response_consumer, - table_name_with_rule_key, - attr_list, - "SWSS_RC_INVALID_PARAM", - "[OrchAgent] Failed to find P4Orch Manager for ACL_PUNT_TABLE_RULE_TEST P4RT DB table", - ) - - # query application database for ACL rules - acl_rules = util.get_keys( - self._p4rt_acl_rule_obj.appl_db, - self._p4rt_acl_rule_obj.APP_DB_TBL_NAME + ":" + table_name, - ) - assert len(acl_rules) == len(original_appl_acl_rules) + 1 - - # query application database for newly created ACL rule - (status, fvs) = util.get_key( - self._p4rt_acl_rule_obj.appl_db, - self._p4rt_acl_table_definition_obj.APP_DB_TBL_NAME, - table_name_with_rule_key, - ) - assert status == True - util.verify_attr(fvs, attr_list) - - # query ASIC database for ACL rules - acl_asic_rules = util.get_keys( - self._p4rt_acl_rule_obj.asic_db, self._p4rt_acl_rule_obj.ASIC_DB_TBL_NAME - ) - assert len(acl_asic_rules) == len(original_asic_acl_rules) - - # query ASIC database for newly created ACL rule - rule_asic_db_keys = [ - key for key in acl_asic_rules if key not in original_asic_acl_rules - ] - assert len(rule_asic_db_keys) == 0 - - # cleanup application database - tbl = swsscommon.Table( - self._p4rt_acl_table_definition_obj.appl_db, - self._p4rt_acl_rule_obj.APP_DB_TBL_NAME, - ) - tbl._del(table_name_with_rule_key) diff --git a/tests/p4rt/test_p4rt_mirror.py b/tests/p4rt/test_p4rt_mirror.py deleted file mode 100644 index 1584d9961d..0000000000 --- a/tests/p4rt/test_p4rt_mirror.py +++ /dev/null @@ -1,202 +0,0 @@ -from swsscommon import swsscommon - -import pytest -import util -import json - - -class P4RtMirrorSessionWrapper(util.DBInterface): - """Interface to interact with APP DB and ASIC DB tables for P4RT mirror session object.""" - - # database and SAI constants - APP_DB_TBL_NAME = swsscommon.APP_P4RT_TABLE_NAME - TBL_NAME = swsscommon.APP_P4RT_MIRROR_SESSION_TABLE_NAME - ACTION = "action" - PORT = "port" - SRC_IP = "src_ip" - DST_IP = "dst_ip" - SRC_MAC = "src_mac" - DST_MAC = "dst_mac" - TTL = "ttl" - TOS = "tos" - - ASIC_DB_TBL_NAME = "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION" - SAI_MIRROR_SESSION_ATTR_MONITOR_PORT = "SAI_MIRROR_SESSION_ATTR_MONITOR_PORT" - SAI_MIRROR_SESSION_ATTR_TYPE = "SAI_MIRROR_SESSION_ATTR_TYPE" - SAI_MIRROR_SESSION_ATTR_ERSPAN_ENCAPSULATION_TYPE = "SAI_MIRROR_SESSION_ATTR_ERSPAN_ENCAPSULATION_TYPE" - SAI_MIRROR_SESSION_ATTR_IPHDR_VERSION = "SAI_MIRROR_SESSION_ATTR_IPHDR_VERSION" - SAI_MIRROR_SESSION_ATTR_TOS = "SAI_MIRROR_SESSION_ATTR_TOS" - SAI_MIRROR_SESSION_ATTR_TTL = "SAI_MIRROR_SESSION_ATTR_TTL" - SAI_MIRROR_SESSION_ATTR_SRC_IP_ADDRESS = "SAI_MIRROR_SESSION_ATTR_SRC_IP_ADDRESS" - SAI_MIRROR_SESSION_ATTR_DST_IP_ADDRESS = "SAI_MIRROR_SESSION_ATTR_DST_IP_ADDRESS" - SAI_MIRROR_SESSION_ATTR_SRC_MAC_ADDRESS = "SAI_MIRROR_SESSION_ATTR_SRC_MAC_ADDRESS" - SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS = "SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS" - SAI_MIRROR_SESSION_ATTR_GRE_PROTOCOL_TYPE = "SAI_MIRROR_SESSION_ATTR_GRE_PROTOCOL_TYPE" - - def generate_app_db_key(self, mirror_session_id): - d = {} - d[util.prepend_match_field("mirror_session_id")] = mirror_session_id - key = json.dumps(d, separators=(",", ":")) - return self.TBL_NAME + ":" + key - - -class TestP4RTMirror(object): - def _set_up(self, dvs): - self._p4rt_mirror_session_wrapper = P4RtMirrorSessionWrapper() - self._p4rt_mirror_session_wrapper.set_up_databases(dvs) - self._response_consumer = swsscommon.NotificationConsumer( - self._p4rt_mirror_session_wrapper.appl_db, "APPL_DB_" + swsscommon.APP_P4RT_TABLE_NAME + "_RESPONSE_CHANNEL") - - def test_MirrorSessionAddModifyAndDelete(self, dvs, testlog): - # Initialize database connectors - self._set_up(dvs) - - # Maintain list of original Application and ASIC DB entries before adding - # new mirror session - original_appl_mirror_entries = util.get_keys( - self._p4rt_mirror_session_wrapper.appl_db, - self._p4rt_mirror_session_wrapper.APP_DB_TBL_NAME + ":" + self._p4rt_mirror_session_wrapper.TBL_NAME) - original_asic_mirror_entries = util.get_keys( - self._p4rt_mirror_session_wrapper.asic_db, self._p4rt_mirror_session_wrapper.ASIC_DB_TBL_NAME) - - # 1. Create mirror session - mirror_session_id = "mirror_session1" - action = "mirror_as_ipv4_erspan" - port = "Ethernet8" - src_ip = "10.206.196.31" - dst_ip = "172.20.0.203" - src_mac = "00:02:03:04:05:06" - dst_mac = "00:1A:11:17:5F:80" - ttl = "0x40" - tos = "0x00" - - attr_list_in_app_db = [(self._p4rt_mirror_session_wrapper.ACTION, action), - (util.prepend_param_field( - self._p4rt_mirror_session_wrapper.PORT), port), - (util.prepend_param_field( - self._p4rt_mirror_session_wrapper.SRC_IP), src_ip), - (util.prepend_param_field( - self._p4rt_mirror_session_wrapper.DST_IP), dst_ip), - (util.prepend_param_field( - self._p4rt_mirror_session_wrapper.SRC_MAC), src_mac), - (util.prepend_param_field( - self._p4rt_mirror_session_wrapper.DST_MAC), dst_mac), - (util.prepend_param_field( - self._p4rt_mirror_session_wrapper.TTL), ttl), - (util.prepend_param_field(self._p4rt_mirror_session_wrapper.TOS), tos)] - mirror_session_key = self._p4rt_mirror_session_wrapper.generate_app_db_key( - mirror_session_id) - self._p4rt_mirror_session_wrapper.set_app_db_entry( - mirror_session_key, attr_list_in_app_db) - util.verify_response( - self._response_consumer, mirror_session_key, attr_list_in_app_db, "SWSS_RC_SUCCESS") - - # Query application database for mirror entries - appl_mirror_entries = util.get_keys( - self._p4rt_mirror_session_wrapper.appl_db, - self._p4rt_mirror_session_wrapper.APP_DB_TBL_NAME + ":" + self._p4rt_mirror_session_wrapper.TBL_NAME) - assert len(appl_mirror_entries) == len( - original_appl_mirror_entries) + 1 - - # Query application database for newly created mirror key - (status, fvs) = util.get_key(self._p4rt_mirror_session_wrapper.appl_db, - self._p4rt_mirror_session_wrapper.APP_DB_TBL_NAME, - mirror_session_key) - assert status == True - util.verify_attr(fvs, attr_list_in_app_db) - - # Query ASIC database for mirror entries - asic_mirror_entries = util.get_keys(self._p4rt_mirror_session_wrapper.asic_db, - self._p4rt_mirror_session_wrapper.ASIC_DB_TBL_NAME) - assert len(asic_mirror_entries) == len( - original_asic_mirror_entries) + 1 - - # Query ASIC database for newly created mirror key - asic_db_key = None - for key in asic_mirror_entries: - # Get newly created entry - if key not in original_asic_mirror_entries: - asic_db_key = key - break - assert asic_db_key is not None - (status, fvs) = util.get_key(self._p4rt_mirror_session_wrapper.asic_db, - self._p4rt_mirror_session_wrapper.ASIC_DB_TBL_NAME, - asic_db_key) - assert status == True - - # Get oid of Ethernet8 - port_oid = util.get_port_oid_by_name(dvs, port) - assert port_oid != None - - expected_attr_list_in_asic_db = [ - (self._p4rt_mirror_session_wrapper.SAI_MIRROR_SESSION_ATTR_MONITOR_PORT, port_oid), - (self._p4rt_mirror_session_wrapper.SAI_MIRROR_SESSION_ATTR_TYPE, - "SAI_MIRROR_SESSION_TYPE_ENHANCED_REMOTE"), - (self._p4rt_mirror_session_wrapper.SAI_MIRROR_SESSION_ATTR_ERSPAN_ENCAPSULATION_TYPE, - "SAI_ERSPAN_ENCAPSULATION_TYPE_MIRROR_L3_GRE_TUNNEL"), - # MIRROR_SESSION_DEFAULT_IP_HDR_VER - (self._p4rt_mirror_session_wrapper.SAI_MIRROR_SESSION_ATTR_IPHDR_VERSION, "4"), - (self._p4rt_mirror_session_wrapper.SAI_MIRROR_SESSION_ATTR_TOS, "0"), - (self._p4rt_mirror_session_wrapper.SAI_MIRROR_SESSION_ATTR_TTL, "64"), - (self._p4rt_mirror_session_wrapper.SAI_MIRROR_SESSION_ATTR_SRC_IP_ADDRESS, src_ip), - (self._p4rt_mirror_session_wrapper.SAI_MIRROR_SESSION_ATTR_DST_IP_ADDRESS, dst_ip), - (self._p4rt_mirror_session_wrapper.SAI_MIRROR_SESSION_ATTR_SRC_MAC_ADDRESS, src_mac), - (self._p4rt_mirror_session_wrapper.SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS, dst_mac), - # GRE_PROTOCOL_ERSPAN 0x88be - (self._p4rt_mirror_session_wrapper.SAI_MIRROR_SESSION_ATTR_GRE_PROTOCOL_TYPE, "35006") - ] - util.verify_attr(fvs, expected_attr_list_in_asic_db) - - # 2. Modify the existing mirror session. - new_dst_mac = "00:1A:11:17:5F:FF" - attr_list_in_app_db[5] = (util.prepend_param_field( - self._p4rt_mirror_session_wrapper.DST_MAC), new_dst_mac) - self._p4rt_mirror_session_wrapper.set_app_db_entry( - mirror_session_key, attr_list_in_app_db) - util.verify_response( - self._response_consumer, mirror_session_key, attr_list_in_app_db, "SWSS_RC_SUCCESS") - - # Query application database for the modified mirror key - (status, fvs) = util.get_key(self._p4rt_mirror_session_wrapper.appl_db, - self._p4rt_mirror_session_wrapper.APP_DB_TBL_NAME, - mirror_session_key) - assert status == True - util.verify_attr(fvs, attr_list_in_app_db) - - # Query ASIC DB about the modified mirror session. - expected_attr_list_in_asic_db[9] = ( - self._p4rt_mirror_session_wrapper.SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS, new_dst_mac) - (status, fvs) = util.get_key(self._p4rt_mirror_session_wrapper.asic_db, - self._p4rt_mirror_session_wrapper.ASIC_DB_TBL_NAME, - asic_db_key) - assert status == True - util.verify_attr(fvs, expected_attr_list_in_asic_db) - - # 3. Delete the mirror session. - self._p4rt_mirror_session_wrapper.remove_app_db_entry( - mirror_session_key) - util.verify_response( - self._response_consumer, mirror_session_key, [], "SWSS_RC_SUCCESS") - - # Query application database for mirror entries - appl_mirror_entries = util.get_keys( - self._p4rt_mirror_session_wrapper.appl_db, - self._p4rt_mirror_session_wrapper.APP_DB_TBL_NAME + ":" + self._p4rt_mirror_session_wrapper.TBL_NAME) - assert len(appl_mirror_entries) == len(original_appl_mirror_entries) - - # Query application database for the deleted mirror key - (status, fvs) = util.get_key(self._p4rt_mirror_session_wrapper.appl_db, - self._p4rt_mirror_session_wrapper.APP_DB_TBL_NAME, - mirror_session_key) - assert status == False - - # Query ASIC database for mirror entries - asic_mirror_entries = util.get_keys(self._p4rt_mirror_session_wrapper.asic_db, - self._p4rt_mirror_session_wrapper.ASIC_DB_TBL_NAME) - assert len(asic_mirror_entries) == len(original_asic_mirror_entries) - - # Query ASIC state database for the deleted mirror key - (status, fvs) = util.get_key(self._p4rt_mirror_session_wrapper.asic_db, - self._p4rt_mirror_session_wrapper.ASIC_DB_TBL_NAME, - asic_db_key) - assert status == False diff --git a/tests/p4rt/test_viplb.py b/tests/p4rt/test_viplb.py deleted file mode 100644 index fd5e90e05d..0000000000 --- a/tests/p4rt/test_viplb.py +++ /dev/null @@ -1,263 +0,0 @@ -from swsscommon import swsscommon - -import pytest -import json -import util -import time -import l3 -import viplb -import tables_definition - -def getCrmCounterValue(dvs, key, counter): - - counters_db = swsscommon.DBConnector(swsscommon.COUNTERS_DB, dvs.redis_sock, 0) - crm_stats_table = swsscommon.Table(counters_db, 'CRM') - - for k in crm_stats_table.get(key)[1]: - if k[0] == counter: - return int(k[1]) - - return 0 - -def crm_update(dvs, field, value): - cfg_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) - tbl = swsscommon.Table(cfg_db, "CRM") - fvs = swsscommon.FieldValuePairs([(field, value)]) - tbl.set("Config", fvs) - time.sleep(1) - - -class TestP4RTVIPLB(object): - - def _set_up(self, dvs): - self._p4rt_tables_definition_obj = tables_definition.P4RtTableDefinitionWrapper() - self._p4rt_router_intf_obj = l3.P4RtRouterInterfaceWrapper() - self._p4rt_neighbor_obj = l3.P4RtNeighborWrapper() - self._p4rt_nexthop_obj = l3.P4RtNextHopWrapper() - self._p4rt_viplb_obj = viplb.P4RtVIPLBWrapper() - - self._p4rt_tables_definition_obj.set_up_databases(dvs) - self._p4rt_router_intf_obj.set_up_databases(dvs) - self._p4rt_neighbor_obj.set_up_databases(dvs) - self._p4rt_nexthop_obj.set_up_databases(dvs) - self._p4rt_viplb_obj.set_up_databases(dvs) - self.response_consumer = swsscommon.NotificationConsumer( - self._p4rt_viplb_obj.appl_db, "APPL_DB_" + - swsscommon.APP_P4RT_TABLE_NAME + "_RESPONSE_CHANNEL" - ) - - def test_VIPv4LBWithGoodNexthopAddUpdateDeletePass(self, dvs, testlog): - # Initialize L3 objects and database connectors. - self._set_up(dvs) - crm_update(dvs, "polling_interval", "1") - - # Create tables definition AppDb entry - tables_definition_key, attr_list = ( - self._p4rt_tables_definition_obj.create_tables_definition() - ) - util.verify_response(self.response_consumer, tables_definition_key, - attr_list, "SWSS_RC_SUCCESS") - - # Set IP type for viplb object. - self._p4rt_viplb_obj.set_ip_type("IPV4") - - # Maintain list of original Application and ASIC DB entries before - # adding new entry. - db_list = ((self._p4rt_nexthop_obj.asic_db, - self._p4rt_nexthop_obj.ASIC_DB_TBL_NAME),) - self._p4rt_nexthop_obj.get_original_redis_entries(db_list) - db_list = ((self._p4rt_viplb_obj.appl_db, - "%s:%s" % (self._p4rt_viplb_obj.APP_DB_TBL_NAME, - self._p4rt_viplb_obj.TBL_NAME)), - (self._p4rt_viplb_obj.asic_db, - self._p4rt_viplb_obj.ASIC_DB_TBL_NAME)) - self._p4rt_viplb_obj.get_original_redis_entries(db_list) - - # Fetch the original key to oid information from Redis DB. - key_to_oid_helper = util.KeyToOidDBHelper(dvs) - _, original_key_oid_info = key_to_oid_helper.get_db_info() - - # Create router interface. - router_interface_id, router_intf_key, attr_list = ( - self._p4rt_router_intf_obj.create_router_interface() - ) - util.verify_response(self.response_consumer, router_intf_key, - attr_list, "SWSS_RC_SUCCESS") - - # Verify that P4RT key to OID count incremented by 1 in Redis DB. - count = 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Create neighbor. - neighbor_id, neighbor_key, attr_list = ( - self._p4rt_neighbor_obj.create_neighbor() - ) - util.verify_response(self.response_consumer, neighbor_key, attr_list, - "SWSS_RC_SUCCESS") - - # Verify that P4RT key to OID count incremented by 1 in Redis DB. - count += 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Create nexthop. - first_nexthop_id, first_nexthop_key, attr_list = ( - self._p4rt_nexthop_obj.create_next_hop() - ) - util.verify_response(self.response_consumer, first_nexthop_key, attr_list, - "SWSS_RC_SUCCESS") - # get nexthop_oid of newly created nexthop - first_nexthop_oid = self._p4rt_nexthop_obj.get_newly_created_nexthop_oid() - assert first_nexthop_oid is not None - - # Verify that P4RT key to OID count incremented by 1 in Redis DB. - count += 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Create viplb. - viplb_key, attr_list = ( - self._p4rt_viplb_obj.create_viplb(first_nexthop_id) - ) - util.verify_response(self.response_consumer, viplb_key, attr_list, - "SWSS_RC_SUCCESS") - - # Verify that P4RT key to OID count incremented by 1 in Redis DB. - count += 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Query application database for viplb entries. - viplb_entries = util.get_keys( - self._p4rt_viplb_obj.appl_db, - self._p4rt_viplb_obj.APP_DB_TBL_NAME + ":" + self._p4rt_viplb_obj.TBL_NAME) - assert len(viplb_entries) == ( - self._p4rt_viplb_obj.get_original_appl_db_entries_count() + 1 - ) - - # Query application database for newly created viplb key. - (status, fvs) = util.get_key(self._p4rt_viplb_obj.appl_db, - self._p4rt_viplb_obj.APP_DB_TBL_NAME, - viplb_key) - assert status == True - util.verify_attr(fvs, attr_list) - - # get programmable_object_oid of newly created viplb - viplb_oid = self._p4rt_viplb_obj.get_newly_created_programmable_object_oid() - assert viplb_oid is not None - - # get crm counters - time.sleep(1) - used_counter = getCrmCounterValue(dvs, "EXT_TABLE_STATS:"+self._p4rt_viplb_obj.TBL_NAME, 'crm_stats_extension_table_used') - avail_counter = getCrmCounterValue(dvs, "EXT_TABLE_STATS:"+self._p4rt_viplb_obj.TBL_NAME, 'crm_stats_extension_table_available') - assert used_counter is 1 - - # Create another router interface. - router_interface_id, router_intf_key, attr_list = ( - self._p4rt_router_intf_obj.create_router_interface(router_interace_id="20") - ) - util.verify_response(self.response_consumer, router_intf_key, - attr_list, "SWSS_RC_SUCCESS") - - # Verify that P4RT key to OID count incremented by 1 in Redis DB. - count += 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Create another neighbor. - neighbor_id, neighbor_key, attr_list = ( - self._p4rt_neighbor_obj.create_neighbor(router_interface_id="20", neighbor_id="10.0.0.1") - ) - util.verify_response(self.response_consumer, neighbor_key, attr_list, - "SWSS_RC_SUCCESS") - - # Verify that P4RT key to OID count incremented by 1 in Redis DB. - count += 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Create another nexthop. - second_nexthop_id, second_nexthop_key, attr_list = ( - self._p4rt_nexthop_obj.create_next_hop(router_interface_id="20", neighbor_id="10.0.0.1", nexthop_id="16") - ) - util.verify_response(self.response_consumer, second_nexthop_key, attr_list, - "SWSS_RC_SUCCESS") - - # Verify that P4RT key to OID count incremented by 1 in Redis DB. - count += 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # Update viplb. - viplb_key, attr_list = ( - self._p4rt_viplb_obj.create_viplb(second_nexthop_id) - ) - util.verify_response(self.response_consumer, viplb_key, attr_list, - "SWSS_RC_SUCCESS") - - - # Remove nexthop. - self._p4rt_nexthop_obj.remove_app_db_entry(first_nexthop_key) - util.verify_response(self.response_consumer, first_nexthop_key, [], - "SWSS_RC_SUCCESS") - - # Verify that P4RT key to OID count decremented by 1 in Redis DB. - count -= 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # get crm counters - time.sleep(1) - used_counter = getCrmCounterValue(dvs, "EXT_TABLE_STATS:"+self._p4rt_viplb_obj.TBL_NAME, 'crm_stats_extension_table_used') - avail_counter = getCrmCounterValue(dvs, "EXT_TABLE_STATS:"+self._p4rt_viplb_obj.TBL_NAME, 'crm_stats_extension_table_available') - assert used_counter is 1 - - # Remove viplb entry. - self._p4rt_viplb_obj.remove_app_db_entry(viplb_key) - util.verify_response( - self.response_consumer, viplb_key, [], "SWSS_RC_SUCCESS") - - # Verify that P4RT key to OID count decremented by 1 in Redis DB. - count -= 1 - status, fvs = key_to_oid_helper.get_db_info() - assert status == True - assert len(fvs) == len(original_key_oid_info) + count - - # get crm counters - time.sleep(1) - used_counter = getCrmCounterValue(dvs, "EXT_TABLE_STATS:"+self._p4rt_viplb_obj.TBL_NAME, 'crm_stats_extension_table_used') - avail_counter = getCrmCounterValue(dvs, "EXT_TABLE_STATS:"+self._p4rt_viplb_obj.TBL_NAME, 'crm_stats_extension_table_available') - assert used_counter is 0 - - - def test_VIPv4LBWithBadNexthopAddUpdateDeletePass(self, dvs, testlog): - # Initialize L3 objects and database connectors. - self._set_up(dvs) - return - - # Create tables definition AppDb entry - tables_definition_key, attr_list = ( - self._p4rt_tables_definition_obj.create_tables_definition() - ) - util.verify_response(self.response_consumer, tables_definition_key, - attr_list, "SWSS_RC_SUCCESS") - - # Set IP type for viplb object. - self._p4rt_viplb_obj.set_ip_type("IPV4") - - # Create viplb. - viplb_key, attr_list = ( - self._p4rt_viplb_obj.create_viplb() - ) - util.verify_response(self.response_consumer, viplb_key, attr_list, - "SWSS_RC_INVALID_PARAM", "[OrchAgent] Cross-table reference valdiation failed, no OID found") - diff --git a/tests/p4rt/util.py b/tests/p4rt/util.py deleted file mode 100644 index 7959aecb50..0000000000 --- a/tests/p4rt/util.py +++ /dev/null @@ -1,138 +0,0 @@ -""" Defines common P4RT utility functions.""" -from swsscommon import swsscommon - -import time - - -def _set_up_appl_db(dvs): - """ Initializes application database connector.""" - return swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - - -def _set_up_asic_db(dvs): - """ Initializes ASIC database connector.""" - return swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - - -def _set_up_appl_state_db(dvs): - """ Initializes APPL STATE database connector.""" - return swsscommon.DBConnector(swsscommon.APPL_STATE_DB, dvs.redis_sock, 0) - - -def get_keys(db, tbl_name): - """ Retrieves keys from given database and table.""" - tbl = swsscommon.Table(db, tbl_name) - return tbl.getKeys() - - -def get_key(db, tbl_name, key): - """ Retrieves entry corresponding to given key in given database and table.""" - tbl = swsscommon.Table(db, tbl_name) - return tbl.get(key) - - -def verify_attr(fvs, attr_list): - """ Verifies attribute list for given key in a database table.""" - assert len(fvs) == len(attr_list) - d = dict(attr_list) - for fv in fvs: - if fv[0] in d: - assert fv[1] == d[fv[0]] - else: - assert False - -def prepend_match_field(match_field): - return "match/" + match_field - -def prepend_param_field(param_field): - return "param/" + param_field - -def verify_response(consumer, key, attr_list, status, err_message = "SWSS_RC_SUCCESS"): - """ Verifies a response.""" - if consumer.peek() <= 0: - consumer.readData() - (op, data, values) = consumer.pop() - assert data == key - assert op == status - assert len(values) >= 1 - assert values[0][0] == "err_str", "Unexpected status '%s' received, expected '%s'" % \ - (values[0][0], "err_str") - assert values[0][1] == err_message, "Unexpected message '%s' received, expected '%s'" % \ - (values[0][1], err_message) - values = values[1:] - verify_attr(values, attr_list) - - -def check_syslog(dvs, marker, process, err_log, expected_cnt): - """ Checks syslog on dvs docker. - - Scans /var/log/syslog for expected count (expected_cnt) of the error - log(err_log). Filters Logs starting at timestamp marked by "marker" based on - the given process. - """ - (exitcode, num) = dvs.runcmd([ - "sh", "-c", - "awk \'/%s/,ENDFILE {print;}\' /var/log/syslog | grep %s | grep -E \'%s\' | wc -l" - % (marker, process, err_log) - ]) - assert num.strip() == str(expected_cnt) - -def get_port_oid_by_name(dvs, port_name): - counters_db = swsscommon.DBConnector(swsscommon.COUNTERS_DB, dvs.redis_sock, 0) - port_map_tbl = swsscommon.Table(counters_db, "COUNTERS_PORT_NAME_MAP") - port_oid = None - for k in port_map_tbl.get("")[1]: - if k[0] == port_name: - port_oid = k[1] - return port_oid - -def initialize_interface(dvs, port_name, ip): - dvs.port_admin_set(port_name, "up") - dvs.interface_ip_add(port_name, ip) - -def set_interface_status(dvs, if_name, status = "down", server = 0): - dvs.servers[0].runcmd("ip link set {} dev {}".format(status, if_name)) == 0 - time.sleep(1) - -class DBInterface(object): - """ Interface to interact with different redis databases on dvs.""" - - # common attribute fields for L3 objects - ACTION_FIELD = "action" - - def set_up_databases(self, dvs): - self.appl_db = _set_up_appl_db(dvs) - self.asic_db = _set_up_asic_db(dvs) - self.appl_state_db = _set_up_appl_state_db(dvs) - - def set_app_db_entry(self, key, attr_list): - fvs = swsscommon.FieldValuePairs(attr_list) - tbl = swsscommon.ProducerStateTable(self.appl_db, self.APP_DB_TBL_NAME) - tbl.set(key, fvs) - time.sleep(1) - - def remove_app_db_entry(self, key): - tbl = swsscommon.ProducerStateTable(self.appl_db, self.APP_DB_TBL_NAME) - tbl._del(key) - time.sleep(1) - - # Get list of original entries in redis on init. - def get_original_redis_entries(self, db_list): - self._original_entries = {} - for i in db_list: - db = i[0] - table = i[1] - self._original_entries["{}:{}".format(db, table)]= get_keys(db, table) - -class KeyToOidDBHelper(object): - """Provides helper APIs for P4RT key to OID mapping in Redis DB.""" - - # Table name in Redis DB for the mapping. - TBL_NAME = "P4RT_KEY_TO_OID" - KEY = "" - - def __init__(self, dvs): - self.table = swsscommon.Table(_set_up_appl_state_db(dvs), self.TBL_NAME) - - def get_db_info(self): - return self.table.get(self.KEY) diff --git a/tests/p4rt/viplb.py b/tests/p4rt/viplb.py deleted file mode 100644 index 06e61443fa..0000000000 --- a/tests/p4rt/viplb.py +++ /dev/null @@ -1,74 +0,0 @@ -from swsscommon import swsscommon - -import util -import json - - -class P4RtVIPLBWrapper(util.DBInterface): - """Interface to interact with APP DB and ASIC DB tables for P4RT viplb object.""" - - # database and SAI constants - APP_DB_TBL_NAME = swsscommon.APP_P4RT_TABLE_NAME - ASIC_DB_TBL_NAME = "ASIC_STATE:SAI_OBJECT_TYPE_GENERIC_PROGRAMMABLE" - SAI_ATTR_TYPE = "SAI_GENERIC_PROGRAMMABLE_ATTR_TYPE" - SAI_ATTR_OBJECT_NAME = "SAI_GENERIC_PROGRAMMABLE_ATTR_OBJECT_NAME" - SAI_ATTR_ENTRY = "SAI_GENERIC_PROGRAMMABLE_ATTR_ENTRY" - - # default viplb attribute values - DEFAULT_ACTION = "set_nexthop_id" - DEFAULT_NEXTHOP_ID = "18" - DEFAULT_DST = "10.11.12.0/24" - - # attribute fields for viplb object - NEXTHOP_ID_FIELD = "nexthop_id" - - def generate_app_db_key(self, dst): - assert self.ip_type is not None - d = {} - if self.ip_type == "IPV4": - d[util.prepend_match_field("ipv4_dst")] = dst - else: - d[util.prepend_match_field("ipv6_dst")] = dst - key = json.dumps(d, separators=(",", ":")) - return self.TBL_NAME + ":" + key - - def set_ip_type(self, ip_type): - assert ip_type in ("IPV4", "IPV6") - self.ip_type = ip_type - self.TBL_NAME = "EXT_V" + ip_type + "_TABLE" - - # Create entry - def create_viplb(self, nexthop_id=None, action=None, dst=None): - action = action or self.DEFAULT_ACTION - dst = dst or self.DEFAULT_DST - if action == "set_nexthop_id": - nexthop_id = nexthop_id or self.DEFAULT_NEXTHOP_ID - attr_list = [(self.ACTION_FIELD, action), - (util.prepend_param_field(self.NEXTHOP_ID_FIELD), - nexthop_id)] - else: - attr_list = [(self.ACTION_FIELD, action)] - viplb_key = self.generate_app_db_key(dst) - self.set_app_db_entry(viplb_key, attr_list) - return viplb_key, attr_list - - def get_newly_created_programmable_object_oid(self): - viplb_oid = None - viplb_entries = util.get_keys(self.asic_db, self.ASIC_DB_TBL_NAME) - for key in viplb_entries: - if key not in self._original_entries["{}:{}".format(self.asic_db, - self.ASIC_DB_TBL_NAME)]: - viplb_oid = key - break - return viplb_oid - - def get_original_appl_db_entries_count(self): - return len(self._original_entries["%s:%s" % (self.appl_db, - (self.APP_DB_TBL_NAME + ":" - + self.TBL_NAME))]) - - def get_original_appl_state_db_entries_count(self): - return len(self._original_entries["%s:%s" % (self.appl_state_db, - (self.APP_DB_TBL_NAME + ":" - + self.TBL_NAME))]) - From 4568a3a63781e5e7b275c4f33a2e0613f10ca5c6 Mon Sep 17 00:00:00 2001 From: kcudnik Date: Thu, 23 May 2024 17:22:13 +0200 Subject: [PATCH 5/7] add more logging --- orchagent/crmorch.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/orchagent/crmorch.cpp b/orchagent/crmorch.cpp index d9a32357bc..b68cb2c20c 100644 --- a/orchagent/crmorch.cpp +++ b/orchagent/crmorch.cpp @@ -1078,6 +1078,8 @@ void CrmOrch::checkCrmThresholds() continue; } + SWSS_LOG_WARN("XXX counter size: %zu", i.second.countersMap.size()); + for (auto &j : i.second.countersMap) { auto &cnt = j.second; From f3f4f42925a467cb5832f0d86dd033f749b0da47 Mon Sep 17 00:00:00 2001 From: kcudnik Date: Thu, 23 May 2024 18:50:52 +0200 Subject: [PATCH 6/7] remve logging --- orchagent/crmorch.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/orchagent/crmorch.cpp b/orchagent/crmorch.cpp index b68cb2c20c..b5844bbea3 100644 --- a/orchagent/crmorch.cpp +++ b/orchagent/crmorch.cpp @@ -1074,12 +1074,9 @@ void CrmOrch::checkCrmThresholds() if (res.resStatus == CrmResourceStatus::CRM_RES_NOT_SUPPORTED) { - SWSS_LOG_WARN("XXX CrmResourceStatus::CRM_RES_NOT_SUPPORTED"); continue; } - SWSS_LOG_WARN("XXX counter size: %zu", i.second.countersMap.size()); - for (auto &j : i.second.countersMap) { auto &cnt = j.second; @@ -1119,8 +1116,6 @@ void CrmOrch::checkCrmThresholds() throw runtime_error("Unknown threshold type for CRM resource"); } - SWSS_LOG_WARN("XXX res.thresholdType: %s", threshType.c_str()); - if ((utilization >= res.highThreshold) && (cnt.exceededLogCounter < CRM_EXCEEDED_MSG_MAX)) { event_params_t params = { From 8c7f4b3e27fa9cbbcd13aee1ce6e83f623f245c5 Mon Sep 17 00:00:00 2001 From: kcudnik Date: Thu, 23 May 2024 18:53:49 +0200 Subject: [PATCH 7/7] disable subport log --- orchagent/port/porthlpr.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/orchagent/port/porthlpr.cpp b/orchagent/port/porthlpr.cpp index 419cb7ff84..7d259d0b66 100644 --- a/orchagent/port/porthlpr.cpp +++ b/orchagent/port/porthlpr.cpp @@ -998,7 +998,8 @@ bool PortHelper::parsePortConfig(PortConfig &port) const } else { - SWSS_LOG_WARN("Unknown field(%s): skipping ...", field.c_str()); + // XXX disable subport + // SWSS_LOG_WARN("Unknown field(%s): skipping ...", field.c_str()); } }