diff --git a/tests/conftest.py b/tests/conftest.py index 9264417214d..f0f06a3de69 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -28,6 +28,7 @@ from dvslib import dvs_policer from dvslib import dvs_hash from dvslib import dvs_switch +from dvslib import dvs_twamp from buffer_model import enable_dynamic_buffer @@ -1942,8 +1943,17 @@ def dvs_hash_manager(request, dvs): dvs.get_config_db()) @pytest.fixture(scope="class") +<<<<<<< HEAD def dvs_switch_manager(request, dvs): request.cls.dvs_switch = dvs_switch.DVSSwitch(dvs.get_asic_db()) +======= +def dvs_twamp_manager(request, dvs): + request.cls.dvs_twamp = dvs_twamp.DVSTwamp(dvs.get_asic_db(), + dvs.get_config_db(), + dvs.get_state_db(), + dvs.get_counters_db(), + dvs.get_app_db()) +>>>>>>> [tests][twamporch] TWAMP Light orchagent implementation. (#2927) ##################### DPB fixtures ########################################### def create_dpb_config_file(dvs): diff --git a/tests/dvslib/dvs_twamp.py b/tests/dvslib/dvs_twamp.py new file mode 100644 index 00000000000..366c05508ce --- /dev/null +++ b/tests/dvslib/dvs_twamp.py @@ -0,0 +1,96 @@ +class DVSTwamp(object): + def __init__(self, adb, cdb, sdb, cntrdb, appdb): + self.asic_db = adb + self.config_db = cdb + self.state_db = sdb + self.counters_db = cntrdb + self.app_db = appdb + + def create_twamp_light_session_sender_packet_count(self, name, sip, sport, dip, dport, packet_count=100, tx_interval=100, timeout=5, stats_interval=None): + twamp_light_entry = {"mode": "LIGHT", + "role": "SENDER", + "src_ip": sip, + "src_udp_port": sport, + "dst_ip": dip, + "dst_udp_port": dport, + "packet_count": packet_count, + "tx_interval": tx_interval, + "timeout": timeout + } + if stats_interval: + twamp_light_entry["statistics_interval"] = str(stats_interval) + else: + twamp_light_entry["statistics_interval"] = str(int(packet_count) * int(tx_interval) + int(timeout)*1000) + self.config_db.create_entry("TWAMP_SESSION", name, twamp_light_entry) + + def create_twamp_light_session_sender_continuous(self, name, sip, sport, dip, dport, monitor_time=0, tx_interval=100, timeout=5, stats_interval=None): + twamp_light_entry = {"mode": "LIGHT", + "role": "SENDER", + "src_ip": sip, + "src_udp_port": sport, + "dst_ip": dip, + "dst_udp_port": dport, + "monitor_time": monitor_time, + "tx_interval": tx_interval, + "timeout": timeout + } + if stats_interval: + twamp_light_entry["statistics_interval"] = str(stats_interval) + else: + twamp_light_entry["statistics_interval"] = str(int(monitor_time)*1000) + self.config_db.create_entry("TWAMP_SESSION", name, twamp_light_entry) + + def create_twamp_light_session_reflector(self, name, sip, sport, dip, dport): + twamp_light_entry = {"mode": "LIGHT", + "role": "REFLECTOR", + "src_ip": sip, + "src_udp_port": sport, + "dst_ip": dip, + "dst_udp_port": dport + } + self.config_db.create_entry("TWAMP_SESSION", name, twamp_light_entry) + + def start_twamp_light_sender(self, name): + twamp_light_entry = {"admin_state": "enabled"} + self.config_db.create_entry("TWAMP_SESSION", name, twamp_light_entry) + + def stop_twamp_light_sender(self, name): + twamp_light_entry = {"admin_state": "disabled"} + self.config_db.create_entry("TWAMP_SESSION", name, twamp_light_entry) + + def remove_twamp_light_session(self, name): + self.config_db.delete_entry("TWAMP_SESSION", name) + + def get_twamp_light_session_status(self, name): + return self.get_twamp_light_session_state(name)["status"] + + def get_twamp_light_session_state(self, name): + tbl = swsscommon.Table(self.sdb, "TWAMP_SESSION_TABLE") + (status, fvs) = tbl.get(name) + assert status == True + assert len(fvs) > 0 + return { fv[0]: fv[1] for fv in fvs } + + def verify_session_status(self, name, status="active", expected=1): + self.state_db.wait_for_n_keys("TWAMP_SESSION_TABLE", expected) + if expected: + self.state_db.wait_for_field_match("TWAMP_SESSION_TABLE", name, {"status": status}) + + def verify_no_mirror(self): + self.config_db.wait_for_n_keys("TWAMP_SESSION", 0) + self.state_db.wait_for_n_keys("TWAMP_SESSION_TABLE", 0) + + def verify_session_asic_db(self, dvs, name, asic_table=None, expected=1): + session_oids = self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_TWAMP_SESSION", expected) + session_oid = session_oids[0] + dvs.asic_db.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_TWAMP_SESSION", session_oid, asic_table) + + def verify_session_counter_db(self, dvs, name, counter_table=None, expected=1, expected_item=1): + fvs = dvs.counters_db.get_entry("COUNTERS_TWAMP_SESSION_NAME_MAP", "") + fvs = dict(fvs) + total_key = self.counters_db.db_connection.keys("COUNTERS:{}".format(fvs[name])) + assert len(total_key) == expected, "TWAMP Light counter entries are not available in counter db" + dvs.counters_db.wait_for_field_match("COUNTERS", fvs[name], counter_table) + item_keys = self.counters_db.db_connection.keys("COUNTERS:{}:INDEX:*".format(fvs[name])) + assert len(item_keys) == expected_item, "TWAMP Light counter entries are not available in counter db" + diff --git a/tests/test_twamp.py b/tests/test_twamp.py new file mode 100644 index 00000000000..b310a1e5b9a --- /dev/null +++ b/tests/test_twamp.py @@ -0,0 +1,333 @@ +# 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 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 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 session + The session becomes active + 3. Remove miror session + """ + dvs.setup_db() + + 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) + self.dvs_twamp.verify_session_status(session, "inactive") + + # start twamp-light session + self.dvs_twamp.start_twamp_light_sender(session) + self.dvs_twamp.verify_session_status(session, "active") + self.check_syslog(dvs, marker, "Failed to create twamp session", 0) + + expected_asic_table = {"SAI_TWAMP_SESSION_ATTR_TWAMP_MODE": "SAI_TWAMP_MODE_LIGHT", + "SAI_TWAMP_SESSION_ATTR_SESSION_ROLE": "SAI_TWAMP_SESSION_ROLE_SENDER", + "SAI_TWAMP_SESSION_ATTR_HW_LOOKUP_VALID": "true", + "SAI_TWAMP_SESSION_ATTR_SRC_IP": src_ip, + "SAI_TWAMP_SESSION_ATTR_DST_IP": dst_ip, + "SAI_TWAMP_SESSION_ATTR_UDP_SRC_PORT": src_udp_port, + "SAI_TWAMP_SESSION_ATTR_UDP_DST_PORT": dst_udp_port, + "SAI_TWAMP_SESSION_ATTR_TWAMP_PKT_TX_MODE": "SAI_TWAMP_PKT_TX_MODE_PACKET_COUNT", + "SAI_TWAMP_SESSION_ATTR_TX_PKT_CNT": packet_count, + "SAI_TWAMP_SESSION_ATTR_TX_INTERVAL": tx_interval, + "SAI_TWAMP_SESSION_ATTR_TIMEOUT": timeout, + "SAI_TWAMP_SESSION_ATTR_STATISTICS_INTERVAL": stats_interval, + "SAI_TWAMP_SESSION_ATTR_SESSION_ENABLE_TRANSMIT": "true"} + self.dvs_twamp.verify_session_asic_db(dvs, session, expected_asic_table) + + # wait for sending TWAMP-test done + time.sleep(12) + self.dvs_twamp.verify_session_status(session, "inactive") + + expected_count_db = {"SAI_TWAMP_SESSION_STAT_RX_PACKETS": "0", + "SAI_TWAMP_SESSION_STAT_RX_BYTE": "0", + "SAI_TWAMP_SESSION_STAT_TX_PACKETS": "0", + "SAI_TWAMP_SESSION_STAT_TX_BYTE": "0", + "SAI_TWAMP_SESSION_STAT_DROP_PACKETS": "0", + "SAI_TWAMP_SESSION_STAT_MAX_LATENCY": "0", + "SAI_TWAMP_SESSION_STAT_MIN_LATENCY": "0", + "SAI_TWAMP_SESSION_STAT_AVG_LATENCY": "0", + "SAI_TWAMP_SESSION_STAT_MAX_JITTER": "0", + "SAI_TWAMP_SESSION_STAT_MIN_JITTER": "0", + "SAI_TWAMP_SESSION_STAT_AVG_JITTER": "0"} + self.dvs_twamp.verify_session_counter_db(dvs, session, counter_table=expected_count_db, expected=1, expected_item=1) + + # remove twamp-light session + self.dvs_twamp.remove_twamp_light_session(session) + self.dvs_twamp.verify_no_mirror() + + 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 session + The session becomes active + 3. Remove miror session + """ + dvs.setup_db() + + 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) + self.dvs_twamp.verify_session_status(session, "inactive") + + # start twamp-light session + self.dvs_twamp.start_twamp_light_sender(session) + self.dvs_twamp.verify_session_status(session, "active") + self.check_syslog(dvs, marker, "Failed to create twamp session", 0) + + expected_asic_table = {"SAI_TWAMP_SESSION_ATTR_TWAMP_MODE": "SAI_TWAMP_MODE_LIGHT", + "SAI_TWAMP_SESSION_ATTR_SESSION_ROLE": "SAI_TWAMP_SESSION_ROLE_SENDER", + "SAI_TWAMP_SESSION_ATTR_HW_LOOKUP_VALID": "true", + "SAI_TWAMP_SESSION_ATTR_SRC_IP": src_ip, + "SAI_TWAMP_SESSION_ATTR_DST_IP": dst_ip, + "SAI_TWAMP_SESSION_ATTR_UDP_SRC_PORT": src_udp_port, + "SAI_TWAMP_SESSION_ATTR_UDP_DST_PORT": dst_udp_port, + "SAI_TWAMP_SESSION_ATTR_TWAMP_PKT_TX_MODE": "SAI_TWAMP_PKT_TX_MODE_PACKET_COUNT", + "SAI_TWAMP_SESSION_ATTR_TX_PKT_CNT": packet_count, + "SAI_TWAMP_SESSION_ATTR_TX_INTERVAL": tx_interval, + "SAI_TWAMP_SESSION_ATTR_TIMEOUT": timeout, + "SAI_TWAMP_SESSION_ATTR_STATISTICS_INTERVAL": stats_interval, + "SAI_TWAMP_SESSION_ATTR_SESSION_ENABLE_TRANSMIT": "true"} + self.dvs_twamp.verify_session_asic_db(dvs, session, expected_asic_table) + + # wait for sending TWAMP-test done + time.sleep(120) + self.dvs_twamp.verify_session_status(session, "inactive") + + expected_count_db = {"SAI_TWAMP_SESSION_STAT_RX_PACKETS": "0", + "SAI_TWAMP_SESSION_STAT_RX_BYTE": "0", + "SAI_TWAMP_SESSION_STAT_TX_PACKETS": "0", + "SAI_TWAMP_SESSION_STAT_TX_BYTE": "0", + "SAI_TWAMP_SESSION_STAT_DROP_PACKETS": "0", + "SAI_TWAMP_SESSION_STAT_MAX_LATENCY": "0", + "SAI_TWAMP_SESSION_STAT_MIN_LATENCY": "0", + "SAI_TWAMP_SESSION_STAT_AVG_LATENCY": "0", + "SAI_TWAMP_SESSION_STAT_MAX_JITTER": "0", + "SAI_TWAMP_SESSION_STAT_MIN_JITTER": "0", + "SAI_TWAMP_SESSION_STAT_AVG_JITTER": "0"} + self.dvs_twamp.verify_session_counter_db(dvs, session, counter_table=expected_count_db, expected=1, expected_item=10) + + # remove twamp-light session + self.dvs_twamp.remove_twamp_light_session(session) + self.dvs_twamp.verify_no_mirror() + + 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 session + The session becomes active + 3. Remove miror session + """ + dvs.setup_db() + + 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) + self.dvs_twamp.verify_session_status(session, "inactive") + + # start twamp-light session + self.dvs_twamp.start_twamp_light_sender(session) + self.dvs_twamp.verify_session_status(session, "active") + self.check_syslog(dvs, marker, "Failed to create twamp session", 0) + + expected_asic_table = {"SAI_TWAMP_SESSION_ATTR_TWAMP_MODE": "SAI_TWAMP_MODE_LIGHT", + "SAI_TWAMP_SESSION_ATTR_SESSION_ROLE": "SAI_TWAMP_SESSION_ROLE_SENDER", + "SAI_TWAMP_SESSION_ATTR_HW_LOOKUP_VALID": "true", + "SAI_TWAMP_SESSION_ATTR_SRC_IP": src_ip, + "SAI_TWAMP_SESSION_ATTR_DST_IP": dst_ip, + "SAI_TWAMP_SESSION_ATTR_UDP_SRC_PORT": src_udp_port, + "SAI_TWAMP_SESSION_ATTR_UDP_DST_PORT": dst_udp_port, + "SAI_TWAMP_SESSION_ATTR_TWAMP_PKT_TX_MODE": "SAI_TWAMP_PKT_TX_MODE_PERIOD", + "SAI_TWAMP_SESSION_ATTR_TX_PKT_PERIOD": monitor_time, + "SAI_TWAMP_SESSION_ATTR_TX_INTERVAL": tx_interval, + "SAI_TWAMP_SESSION_ATTR_TIMEOUT": timeout, + "SAI_TWAMP_SESSION_ATTR_STATISTICS_INTERVAL": stats_interval, + "SAI_TWAMP_SESSION_ATTR_SESSION_ENABLE_TRANSMIT": "true"} + self.dvs_twamp.verify_session_asic_db(dvs, session, expected_asic_table) + + # wait for sending TWAMP-test done + time.sleep(60) + self.dvs_twamp.verify_session_status(session, "inactive") + + expected_count_db = {"SAI_TWAMP_SESSION_STAT_RX_PACKETS": "0", + "SAI_TWAMP_SESSION_STAT_RX_BYTE": "0", + "SAI_TWAMP_SESSION_STAT_TX_PACKETS": "0", + "SAI_TWAMP_SESSION_STAT_TX_BYTE": "0", + "SAI_TWAMP_SESSION_STAT_DROP_PACKETS": "0", + "SAI_TWAMP_SESSION_STAT_MAX_LATENCY": "0", + "SAI_TWAMP_SESSION_STAT_MIN_LATENCY": "0", + "SAI_TWAMP_SESSION_STAT_AVG_LATENCY": "0", + "SAI_TWAMP_SESSION_STAT_MAX_JITTER": "0", + "SAI_TWAMP_SESSION_STAT_MIN_JITTER": "0", + "SAI_TWAMP_SESSION_STAT_AVG_JITTER": "0"} + self.dvs_twamp.verify_session_counter_db(dvs, session, counter_table=expected_count_db, expected=1, expected_item=1) + + # remove twamp-light session + self.dvs_twamp.remove_twamp_light_session(session) + self.dvs_twamp.verify_no_mirror() + + + 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 session + The session becomes active + 3. Remove miror session + """ + dvs.setup_db() + + 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) + self.dvs_twamp.verify_session_status(session, "inactive") + + # start twamp-light session + self.dvs_twamp.start_twamp_light_sender(session) + self.dvs_twamp.verify_session_status(session, "active") + self.check_syslog(dvs, marker, "Failed to create twamp session", 0) + + expected_asic_table = {"SAI_TWAMP_SESSION_ATTR_TWAMP_MODE": "SAI_TWAMP_MODE_LIGHT", + "SAI_TWAMP_SESSION_ATTR_SESSION_ROLE": "SAI_TWAMP_SESSION_ROLE_SENDER", + "SAI_TWAMP_SESSION_ATTR_HW_LOOKUP_VALID": "true", + "SAI_TWAMP_SESSION_ATTR_SRC_IP": src_ip, + "SAI_TWAMP_SESSION_ATTR_DST_IP": dst_ip, + "SAI_TWAMP_SESSION_ATTR_UDP_SRC_PORT": src_udp_port, + "SAI_TWAMP_SESSION_ATTR_UDP_DST_PORT": dst_udp_port, + "SAI_TWAMP_SESSION_ATTR_TWAMP_PKT_TX_MODE": "SAI_TWAMP_PKT_TX_MODE_PERIOD", + "SAI_TWAMP_SESSION_ATTR_TX_PKT_PERIOD": monitor_time, + "SAI_TWAMP_SESSION_ATTR_TX_INTERVAL": tx_interval, + "SAI_TWAMP_SESSION_ATTR_TIMEOUT": timeout, + "SAI_TWAMP_SESSION_ATTR_STATISTICS_INTERVAL": stats_interval, + "SAI_TWAMP_SESSION_ATTR_SESSION_ENABLE_TRANSMIT": "true"} + self.dvs_twamp.verify_session_asic_db(dvs, session, expected_asic_table) + + # wait for sending TWAMP-test done + time.sleep(60) + self.dvs_twamp.verify_session_status(session, "inactive") + + expected_count_db = {"SAI_TWAMP_SESSION_STAT_RX_PACKETS": "0", + "SAI_TWAMP_SESSION_STAT_RX_BYTE": "0", + "SAI_TWAMP_SESSION_STAT_TX_PACKETS": "0", + "SAI_TWAMP_SESSION_STAT_TX_BYTE": "0", + "SAI_TWAMP_SESSION_STAT_DROP_PACKETS": "0", + "SAI_TWAMP_SESSION_STAT_MAX_LATENCY": "0", + "SAI_TWAMP_SESSION_STAT_MIN_LATENCY": "0", + "SAI_TWAMP_SESSION_STAT_AVG_LATENCY": "0", + "SAI_TWAMP_SESSION_STAT_MAX_JITTER": "0", + "SAI_TWAMP_SESSION_STAT_MIN_JITTER": "0", + "SAI_TWAMP_SESSION_STAT_AVG_JITTER": "0"} + self.dvs_twamp.verify_session_counter_db(dvs, session, counter_table=expected_count_db, expected=1, expected_item=3) + + # remove twamp-light session + self.dvs_twamp.remove_twamp_light_session(session) + self.dvs_twamp.verify_no_mirror() + + 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 miror session + """ + dvs.setup_db() + + 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) + self.dvs_twamp.verify_session_status(session, "active") + self.check_syslog(dvs, marker, "Failed to create twamp session", 0) + + expected_asic_table = {"SAI_TWAMP_SESSION_ATTR_TWAMP_MODE": "SAI_TWAMP_MODE_LIGHT", + "SAI_TWAMP_SESSION_ATTR_SESSION_ROLE": "SAI_TWAMP_SESSION_ROLE_REFLECTOR", + "SAI_TWAMP_SESSION_ATTR_HW_LOOKUP_VALID": "true", + "SAI_TWAMP_SESSION_ATTR_SRC_IP": src_ip, + "SAI_TWAMP_SESSION_ATTR_DST_IP": dst_ip, + "SAI_TWAMP_SESSION_ATTR_UDP_SRC_PORT": src_udp_port, + "SAI_TWAMP_SESSION_ATTR_UDP_DST_PORT": dst_udp_port} + self.dvs_twamp.verify_session_asic_db(dvs, session, expected_asic_table) + + # remove twamp-light session + self.dvs_twamp.remove_twamp_light_session(session) + self.dvs_twamp.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