diff --git a/tests/dhcp_relay/test_dhcpv6_relay.py b/tests/dhcp_relay/test_dhcpv6_relay.py index 2d3e54aebfc..2c440cec7c5 100644 --- a/tests/dhcp_relay/test_dhcpv6_relay.py +++ b/tests/dhcp_relay/test_dhcpv6_relay.py @@ -22,6 +22,11 @@ SINGLE_TOR_MODE = 'single' DUAL_TOR_MODE = 'dual' +NEW_COUNTER_VALUE_FORMAT = ( + "{'Unknown':'0','Solicit':'0','Advertise':'0','Request':'0','Confirm':'0','Renew':'0','Rebind':'0','Reply':'0'," + "'Release':'0','Decline':'0','Reconfigure':'0','Information-Request':'0','Relay-Forward':'0','Relay-Reply':'0'," + "'Malformed':'0'}" +) logger = logging.getLogger(__name__) @@ -33,6 +38,50 @@ def wait_all_bgp_up(duthost): pytest.fail("not all bgp sessions are up after config change") +def check_dhcpv6_relay_counter(duthost, ifname, type, dir): + # new counter table + # sonic-db-cli STATE_DB hgetall 'DHCPv6_COUNTER_TABLE|Vlan1000' + # {'TX': "{'Unknown':'0','Solicit':'0','Advertise':'0','Request':'0','Confirm':'0','Renew':'0','Rebind':'0', + # 'Reply':'0', 'Release':'0','Decline':'0','Reconfigure':'0','Information-Request':'0','Relay-Forward':'0', + # 'Relay-Reply':'0','Malformed':'0'}", 'RX': "{'Unknown':'0','Solicit':'0','Advertise':'0','Request':'0', + # 'Confirm':'0','Renew':'0','Rebind':'0','Reply':'0', 'Release':'0','Decline':'0','Reconfigure':'0', + # 'Information-Request':'0','Relay-Forward':'0','Relay-Reply':'0','Malformed':'0'}"} + # + # old counter table + # sonic-db-cli STATE_DB hgetall 'DHCPv6_COUNTER_TABLE|Vlan1000' + # {'Unknown':'0','Solicit':'0','Advertise':'0','Request':'0','Confirm':'0','Renew':'0','Rebind':'0','Reply':'0', + # 'Release':'0','Decline':'0','Reconfigure':'0','Information-Request':'0','Relay-Forward':'0','Relay-Reply':'0', + # 'Malformed':'0'} + # + cmd_new_version = 'sonic-db-cli STATE_DB hget "DHCPv6_COUNTER_TABLE|{}" {}'.format(ifname, dir) + cmd_old_version = 'sonic-db-cli STATE_DB hget "DHCPv6_COUNTER_TABLE|{}" {}'.format(ifname, type) + output_new = duthost.shell(cmd_new_version)['stdout'] + if len(output_new) != 0: + counters = eval(output_new) + assert int(counters[type]) > 0, "{}({}) missing {} count".format(ifname, dir, type) + else: + # old version only support vlan couting + if 'Vlan' not in ifname: + return + output_old = duthost.shell(cmd_old_version)['stdout'] + assert int(output_old) > 0, "{} missing {} count".format(ifname, type) + + +def init_counter(duthost, ifname, types): + cmd_new_version = 'sonic-db-cli STATE_DB hget "DHCPv6_COUNTER_TABLE|{}" RX'.format(ifname) + output_new = duthost.shell(cmd_new_version)['stdout'] + if len(output_new) != 0: + counters_str = NEW_COUNTER_VALUE_FORMAT + cmd = 'sonic-db-cli STATE_DB hmset "DHCPv6_COUNTER_TABLE|{}" "RX" "{}"'.format(ifname, str(counters_str)) + duthost.shell(cmd) + cmd = 'sonic-db-cli STATE_DB hmset "DHCPv6_COUNTER_TABLE|{}" "TX" "{}"'.format(ifname, str(counters_str)) + duthost.shell(cmd) + else: + for type in types: + cmd = 'sonic-db-cli STATE_DB hmset "DHCPv6_COUNTER_TABLE|{}" {} 0'.format(ifname, type) + duthost.shell(cmd) + + @pytest.fixture(scope="module") def testing_config(duthosts, rand_one_dut_hostname, tbinfo): duthost = duthosts[rand_one_dut_hostname] @@ -140,6 +189,7 @@ def dut_dhcp_relay_data(duthosts, rand_one_dut_hostname, tbinfo): dhcp_relay_data['uplink_interfaces'] = uplink_interfaces dhcp_relay_data['uplink_port_indices'] = uplink_port_indices dhcp_relay_data['down_interface_link_local'] = down_interface_link_local + dhcp_relay_data['loopback_iface'] = mg_facts['minigraph_lo_interfaces'] dhcp_relay_data['loopback_ipv6'] = mg_facts['minigraph_lo_interfaces'][1]['addr'] if 'dualtor' in tbinfo['topo']['name']: dhcp_relay_data['is_dualtor'] = True @@ -195,15 +245,15 @@ def test_dhcpv6_relay_counter(ptfhost, duthosts, rand_one_dut_hostname, dut_dhcp duthost = duthosts[rand_one_dut_hostname] skip_release(duthost, ["201911", "202106"]) - messages = ["Unknown", "Solicit", "Advertise", "Request", "Confirm", "Renew", "Rebind", "Reply", "Release", - "Decline", "Reconfigure", "Information-Request", "Relay-Forward", "Relay-Reply", "Malformed"] + message_types = ["Unknown", "Solicit", "Advertise", "Request", "Confirm", "Renew", "Rebind", "Reply", "Release", + "Decline", "Reconfigure", "Information-Request", "Relay-Forward", "Relay-Reply", "Malformed"] for dhcp_relay in dut_dhcp_relay_data: - for message in messages: - cmd = 'sonic-db-cli STATE_DB hmset "DHCPv6_COUNTER_TABLE|{}" {} 0'\ - .format(dhcp_relay['downlink_vlan_iface']['name'], message) - duthost.shell(cmd) + init_counter(duthost, dhcp_relay['client_iface']['name'], message_types) + init_counter(duthost, dhcp_relay['downlink_vlan_iface']['name'], message_types) + if dhcp_relay['is_dualtor']: + init_counter(duthost, dhcp_relay['loopback_iface'][0]['name'], message_types) # Send the DHCP relay traffic on the PTF host ptf_runner(ptfhost, @@ -224,16 +274,35 @@ def test_dhcpv6_relay_counter(ptfhost, duthosts, rand_one_dut_hostname, dut_dhcp "is_dualtor": str(dhcp_relay['is_dualtor'])}, log_file="/tmp/dhcpv6_relay_test.DHCPCounterTest.log", is_python3=True) - for message in messages: - if message == "Relay-Reply" and dhcp_relay['is_dualtor']: - get_message = 'sonic-db-cli STATE_DB hget "DHCPv6_COUNTER_TABLE|Loopback0" {}'.format(message) - message_count = duthost.shell(get_message)['stdout'] - assert int(message_count) > 0, "Missing {} count".format(message) - else: - get_message = 'sonic-db-cli STATE_DB hget "DHCPv6_COUNTER_TABLE|{}" {}'\ - .format(dhcp_relay['downlink_vlan_iface']['name'], message) - message_count = duthost.shell(get_message)['stdout'] - assert int(message_count) > 0, "Missing {} count".format(message) + for type in message_types: + if type in ["Solicit", "Request", "Confirm", "Renew", "Rebind", "Release", "Decline", + "Information-Request"]: + check_dhcpv6_relay_counter(duthost, dhcp_relay['client_iface']['name'], type, "RX") + check_dhcpv6_relay_counter(duthost, dhcp_relay['downlink_vlan_iface']['name'], type, "RX") + if type in ["Malformed"]: + # Malformed DHCPv6 Client packet, depend on malformed content. If Type is good but option is malformed + # First Type will be increased on downlink Ethernet interface first. Then increase Malformed counter + # on downlink_vlan_iface. + check_dhcpv6_relay_counter(duthost, dhcp_relay['downlink_vlan_iface']['name'], type, "RX") + if type in ["Unknown"]: + # From Server Relay-Reply Unknown DHCPv6 type, it's a valid Relay-Reply so Relay-Reply counter + # is normal increased. But in relay message type is unknown type so drop on downlink_vlan_iface + # interface + check_dhcpv6_relay_counter(duthost, dhcp_relay['downlink_vlan_iface']['name'], type, "RX") + if type in ["Advertise", "Reply", "Reconfigure"]: + check_dhcpv6_relay_counter(duthost, dhcp_relay['downlink_vlan_iface']['name'], type, "TX") + check_dhcpv6_relay_counter(duthost, dhcp_relay['client_iface']['name'], type, "TX") + if type in ["Relay-Forward"]: + # Relay-Forward, send out from downlink_vlan_iface first, then send out from uplink interfaces + check_dhcpv6_relay_counter(duthost, dhcp_relay['downlink_vlan_iface']['name'], type, "TX") + # TBD, add uplink interface TX counter check in future + if type in ["Relay-Reply"]: + if dhcp_relay['is_dualtor']: + # dual tor, Relay-Reply will be received on loopback interface + check_dhcpv6_relay_counter(duthost, dhcp_relay['loopback_iface'][0]['name'], type, "RX") + else: + # Single tor, Relay-Reply will be received on downlink_vlan_iface + check_dhcpv6_relay_counter(duthost, dhcp_relay['downlink_vlan_iface']['name'], type, "RX") def test_dhcp_relay_default(ptfhost, dut_dhcp_relay_data, validate_dut_routes_exist, testing_config,