|
18 | 18 | from tests.common.mellanox_data import is_mellanox_device as isMellanoxDevice |
19 | 19 | from ipaddress import IPv6Network, IPv6Address |
20 | 20 | from random import getrandbits |
| 21 | +from tests.common.portstat_utilities import parse_portstat |
| 22 | +from collections import defaultdict |
21 | 23 |
|
22 | 24 |
|
23 | 25 | def increment_ip_address(ip, incr=1): |
@@ -959,14 +961,22 @@ def get_egress_queue_count(duthost, port, priority): |
959 | 961 | Returns: |
960 | 962 | tuple (int, int): total count of packets and bytes in the queue |
961 | 963 | """ |
962 | | - raw_out = duthost.shell("show queue counters {} | sed -n '/UC{}/p'".format(port, priority))['stdout'] |
963 | | - total_pkts = raw_out.split()[2] if 2 < len(raw_out.split()) else "0" |
964 | | - if total_pkts == "N/A": |
965 | | - total_pkts = "0" |
| 964 | + # If DUT is multi-asic, asic will be used. |
| 965 | + if duthost.is_multi_asic: |
| 966 | + asic = duthost.get_port_asic_instance(port).get_asic_namespace() |
| 967 | + raw_out = duthost.shell("sudo ip netns exec {} show queue counters {} | sed -n '/UC{}/p'". |
| 968 | + format(asic, port, priority))['stdout'] |
| 969 | + total_pkts = "0" if raw_out.split()[2] == "N/A" else raw_out.split()[2] |
| 970 | + total_bytes = "0" if raw_out.split()[3] == "N/A" else raw_out.split()[3] |
| 971 | + else: |
| 972 | + raw_out = duthost.shell("show queue counters {} | sed -n '/UC{}/p'".format(port, priority))['stdout'] |
| 973 | + total_pkts = raw_out.split()[2] if 2 < len(raw_out.split()) else "0" |
| 974 | + if total_pkts == "N/A": |
| 975 | + total_pkts = "0" |
966 | 976 |
|
967 | | - total_bytes = raw_out.split()[3] if 3 < len(raw_out.split()) else "0" |
968 | | - if total_bytes == "N/A": |
969 | | - total_bytes = "0" |
| 977 | + total_bytes = raw_out.split()[3] if 3 < len(raw_out.split()) else "0" |
| 978 | + if total_bytes == "N/A": |
| 979 | + total_bytes = "0" |
970 | 980 |
|
971 | 981 | return int(total_pkts.replace(',', '')), int(total_bytes.replace(',', '')) |
972 | 982 |
|
@@ -1061,3 +1071,120 @@ def start_pfcwd_fwd(duthost, asic_value=None): |
1061 | 1071 | stop_pfcwd(duthost, asic_value) |
1062 | 1072 | duthost.shell('sudo ip netns exec {} pfcwd start --action forward 200 --restoration-time 200'. |
1063 | 1073 | format(asic_value)) |
| 1074 | + |
| 1075 | + |
| 1076 | +def clear_counters(duthost, port): |
| 1077 | + """ |
| 1078 | + Clear PFC, Queuecounters, Drop and generic counters from SONiC CLI. |
| 1079 | + Args: |
| 1080 | + duthost (Ansible host instance): Device under test |
| 1081 | + port (str): port name |
| 1082 | + Returns: |
| 1083 | + None |
| 1084 | + """ |
| 1085 | + |
| 1086 | + duthost.shell("sudo sonic-clear counters \n") |
| 1087 | + duthost.shell("sudo sonic-clear pfccounters \n") |
| 1088 | + duthost.shell("sudo sonic-clear priority-group drop counters \n") |
| 1089 | + duthost.shell("sonic-clear counters \n") |
| 1090 | + duthost.shell("sonic-clear pfccounters \n") |
| 1091 | + |
| 1092 | + if (duthost.is_multi_asic): |
| 1093 | + asic = duthost.get_port_asic_instance(port).get_asic_namespace() |
| 1094 | + duthost.shell("sudo ip netns exec {} sonic-clear queuecounters \n".format(asic)) |
| 1095 | + duthost.shell("sudo ip netns exec {} sonic-clear dropcounters \n".format(asic)) |
| 1096 | + else: |
| 1097 | + duthost.shell("sonic-clear queuecounters \n") |
| 1098 | + duthost.shell("sonic-clear dropcounters \n") |
| 1099 | + |
| 1100 | + |
| 1101 | +def get_interface_stats(duthost, port): |
| 1102 | + """ |
| 1103 | + Get the Rx and Tx port failures, throughput and pkts from SONiC CLI. |
| 1104 | + This is the equivalent of the "show interface counters" command. |
| 1105 | + Args: |
| 1106 | + duthost (Ansible host instance): device under test |
| 1107 | + port (str): port name |
| 1108 | + Returns: |
| 1109 | + i_stats (dict): Returns various parameters for given DUT and port. |
| 1110 | + """ |
| 1111 | + # Initializing nested dictionary i_stats |
| 1112 | + i_stats = defaultdict(dict) |
| 1113 | + i_stats[duthost.hostname][port] = {} |
| 1114 | + |
| 1115 | + n_out = parse_portstat(duthost.command('portstat -i {}'.format(port))['stdout_lines'])[port] |
| 1116 | + # rx_err, rx_ovr and rx_drp are counted in single counter rx_fail |
| 1117 | + # tx_err, tx_ovr and tx_drp are counted in single counter tx_fail |
| 1118 | + rx_err = ['rx_err', 'rx_ovr', 'rx_drp'] |
| 1119 | + tx_err = ['tx_err', 'tx_ovr', 'tx_drp'] |
| 1120 | + rx_fail = 0 |
| 1121 | + tx_fail = 0 |
| 1122 | + for m in rx_err: |
| 1123 | + rx_fail = rx_fail + int(n_out[m].replace(',', '')) |
| 1124 | + for m in tx_err: |
| 1125 | + tx_fail = tx_fail + int(n_out[m].replace(',', '')) |
| 1126 | + |
| 1127 | + # Any throughput below 1MBps is measured as 0 for simplicity. |
| 1128 | + thrput = n_out['rx_bps'] |
| 1129 | + if thrput.split(' ')[1] == 'MB/s' and (thrput.split(' ')[0]) != '0.00': |
| 1130 | + i_stats[duthost.hostname][port]['rx_thrput_Mbps'] = float(thrput.split(' ')[0]) * 8 |
| 1131 | + else: |
| 1132 | + i_stats[duthost.hostname][port]['rx_thrput_Mbps'] = 0 |
| 1133 | + thrput = n_out['tx_bps'] |
| 1134 | + if thrput.split(' ')[1] == 'MB/s' and (thrput.split(' ')[0]) != '0.00': |
| 1135 | + i_stats[duthost.hostname][port]['tx_thrput_Mbps'] = float(thrput.split(' ')[0]) * 8 |
| 1136 | + else: |
| 1137 | + i_stats[duthost.hostname][port]['rx_thrput_Mbps'] = 0 |
| 1138 | + |
| 1139 | + i_stats[duthost.hostname][port]['rx_pkts'] = int(n_out['rx_ok'].replace(',', '')) |
| 1140 | + i_stats[duthost.hostname][port]['tx_pkts'] = int(n_out['tx_ok'].replace(',', '')) |
| 1141 | + i_stats[duthost.hostname][port]['rx_fail'] = rx_fail |
| 1142 | + i_stats[duthost.hostname][port]['tx_fail'] = tx_fail |
| 1143 | + |
| 1144 | + return i_stats |
| 1145 | + |
| 1146 | + |
| 1147 | +def get_queue_count_all_prio(duthost, port): |
| 1148 | + """ |
| 1149 | + Get the egress queue count in packets and bytes for a given port and priority from SONiC CLI. |
| 1150 | + This is the equivalent of the "show queue counters" command. |
| 1151 | + Args: |
| 1152 | + duthost (Ansible host instance): device under test |
| 1153 | + port (str): port name |
| 1154 | + Returns: |
| 1155 | + queue_dict (dict): key-value with key=dut+port+prio and value=queue count |
| 1156 | + """ |
| 1157 | + # Initializing nested dictionary queue_dict |
| 1158 | + queue_dict = defaultdict(dict) |
| 1159 | + queue_dict[duthost.hostname][port] = {} |
| 1160 | + |
| 1161 | + # Preparing the dictionary for all 7 priority queues. |
| 1162 | + for priority in range(7): |
| 1163 | + total_pkts, _ = get_egress_queue_count(duthost, port, priority) |
| 1164 | + queue_dict[duthost.hostname][port]['prio_' + str(priority)] = total_pkts |
| 1165 | + |
| 1166 | + return queue_dict |
| 1167 | + |
| 1168 | + |
| 1169 | +def get_pfc_count(duthost, port): |
| 1170 | + """ |
| 1171 | + Get the PFC frame count for a given port from SONiC CLI |
| 1172 | + Args: |
| 1173 | + duthost (Ansible host instance): device under test |
| 1174 | + port (str): port name |
| 1175 | + Returns: |
| 1176 | + pfc_dict (dict) : Returns Rx and Tx PFC for the given DUT and interface. |
| 1177 | + """ |
| 1178 | + pfc_dict = defaultdict(dict) |
| 1179 | + pfc_dict[duthost.hostname][port] = {} |
| 1180 | + raw_out = duthost.shell("show pfc counters | sed -n '/Port Tx/,/^$/p' | grep '{} '".format(port))['stdout'] |
| 1181 | + pause_frame_count = raw_out.split() |
| 1182 | + for m in range(1, len(pause_frame_count)): |
| 1183 | + pfc_dict[duthost.hostname][port]['tx_pfc_'+str(m-1)] = int(pause_frame_count[m].replace(',', '')) |
| 1184 | + |
| 1185 | + raw_out = duthost.shell("show pfc counters | sed -n '/Port Rx/,/^$/p' | grep '{} '".format(port))['stdout'] |
| 1186 | + pause_frame_count = raw_out.split() |
| 1187 | + for m in range(1, len(pause_frame_count)): |
| 1188 | + pfc_dict[duthost.hostname][port]['rx_pfc_'+str(m-1)] = int(pause_frame_count[m].replace(',', '')) |
| 1189 | + |
| 1190 | + return pfc_dict |
0 commit comments