Skip to content

Commit 8926340

Browse files
apoorv-aristadcaugher
authored andcommitted
[sonic-mgmt] modify fec-stats test for fec_flr (sonic-net#20619)
* [sonic-mgmt] modify fec-stats test for fec_flr Modify test_verify_fec_stats_counters() to check for presense of FEC_FLR and FEC_FLR_PREDICTED fields in fec-stats command output, and if present check if the values in the column are valid Floats. * modify test cases according to latest changes * modify the regex pattern, make r_squared compulsory * move fec flr tests to layer1/
1 parent ecf1586 commit 8926340

File tree

1 file changed

+150
-0
lines changed

1 file changed

+150
-0
lines changed

tests/layer1/test_fec_error.py

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
import logging
2+
import pytest
3+
import re
4+
5+
from tests.common.platform.interface_utils import get_fec_eligible_interfaces
6+
7+
pytestmark = [
8+
pytest.mark.disable_loganalyzer, # disable automatic loganalyzer
9+
pytest.mark.topology('any')
10+
]
11+
12+
SUPPORTED_PLATFORMS = [
13+
"mlnx_msn",
14+
"8101_32fh",
15+
"8111_32eh",
16+
"arista",
17+
"x86_64-nvidia",
18+
"x86_64-88_lc0_36fh_m-r0",
19+
"x86_64-nexthop_4010-r0",
20+
"marvell"
21+
]
22+
23+
SUPPORTED_SPEEDS = [
24+
"50G", "100G", "200G", "400G", "800G", "1600G"
25+
]
26+
27+
28+
def test_verify_fec_stats_counters(duthosts, enum_rand_one_per_hwsku_frontend_hostname):
29+
"""
30+
@Summary: Verify the FEC stats counters are valid
31+
Also, check for any uncorrectable FEC errors
32+
"""
33+
duthost = duthosts[enum_rand_one_per_hwsku_frontend_hostname]
34+
35+
# Get operationally up and interfaces with supported speeds
36+
interfaces = get_fec_eligible_interfaces(duthost, SUPPORTED_SPEEDS)
37+
38+
if not interfaces:
39+
pytest.skip("Skipping this test as there is no fec eligible interface")
40+
41+
logging.info("Get output of 'show interfaces counters fec-stats'")
42+
intf_status = duthost.show_and_parse("show interfaces counters fec-stats")
43+
44+
def skip_ber_counters_test(intf_status: dict) -> bool:
45+
"""
46+
Check whether the BER fields (Pre-FEC and Post-FEC BER)
47+
exists in the "show interfaces counters fec-stats"
48+
CLI output
49+
"""
50+
if intf_status.get('fec_pre_ber') is None or intf_status.get('fec_post_ber') is None:
51+
pytest.skip("Pre-FEC and Post-FEC BER fields missing on interface. intf_status: {}".format(intf_status))
52+
return True
53+
return False
54+
55+
def skip_fec_flr_counters_test(intf_status: dict) -> bool:
56+
"""
57+
Check whether the Observed FLR field FLR(O) exists
58+
in the "show interfaces counters fec-stats"
59+
CLI output
60+
"""
61+
if intf_status.get('flr(o)') is None:
62+
pytest.skip("FLR(O) field is missing on interface. intf_status: {}".format(intf_status))
63+
return True
64+
return False
65+
66+
def skip_predicted_flr_counters_test(intf_status: dict) -> bool:
67+
"""
68+
Check whether the Predicted FLR field FLR(P) exists
69+
in the "show interfaces counters fec-stats"
70+
CLI output
71+
"""
72+
if intf_status.get('flr(p) (accuracy)') is None:
73+
pytest.skip("FLR(P) field is missing on interface. intf_status: {}".format(intf_status))
74+
return True
75+
return False
76+
77+
def validate_predicted_flr(value_string) -> bool:
78+
"""
79+
Validate predicted flr string is in the correct
80+
format when not N/A.
81+
Expected format :
82+
* 0
83+
* 7.81e-10 (89%)
84+
"""
85+
# Pattern for just "0"
86+
if value_string == "0":
87+
return True
88+
89+
# Pattern for scientific notation with required accuracy percentage
90+
# e.g., "7.81e-10 (89%)"
91+
pattern = r'^[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)\s+\(\d+%\)$'
92+
if re.match(pattern, value_string):
93+
return True
94+
95+
raise ValueError(f"Invalid predicted FLR format: {value_string}")
96+
97+
for intf in intf_status:
98+
intf_name = intf['iface']
99+
speed = duthost.get_speed(intf_name)
100+
# Speed is a empty string if the port isn't up
101+
if speed == '':
102+
continue
103+
# Convert the speed to gbps format
104+
speed_gbps = f"{int(speed) // 1000}G"
105+
if speed_gbps not in SUPPORTED_SPEEDS:
106+
continue
107+
108+
# Removes commas from "show interfaces counters fec-stats" (i.e. 12,354 --> 12354) to allow int conversion
109+
fec_corr = intf.get('fec_corr', '').replace(',', '').lower()
110+
fec_uncorr = intf.get('fec_uncorr', '').replace(',', '').lower()
111+
fec_symbol_err = intf.get('fec_symbol_err', '').replace(',', '').lower()
112+
# Check if fec_corr, fec_uncorr, and fec_symbol_err are valid integers
113+
try:
114+
fec_corr_int = int(fec_corr)
115+
fec_uncorr_int = int(fec_uncorr)
116+
fec_symbol_err_int = int(fec_symbol_err)
117+
except ValueError:
118+
pytest.fail("FEC stat counters are not valid integers for interface {}, \
119+
fec_corr: {} fec_uncorr: {} fec_symbol_err: {}"
120+
.format(intf_name, fec_corr, fec_uncorr, fec_symbol_err))
121+
122+
# Check for non-zero FEC uncorrectable errors
123+
if fec_uncorr_int > 0:
124+
pytest.fail("FEC uncorrectable errors are non-zero for interface {}: {}"
125+
.format(intf_name, fec_uncorr_int))
126+
127+
# FEC correctable codeword errors should always be less than actual FEC symbol errors, check it
128+
if fec_corr_int > 0 and fec_corr_int > fec_symbol_err_int:
129+
pytest.fail("FEC symbol errors:{} are higher than FEC correctable errors:{} for interface {}"
130+
.format(fec_symbol_err_int, fec_corr_int, intf_name))
131+
132+
# Test for observed flr
133+
if not skip_fec_flr_counters_test(intf):
134+
fec_flr = intf.get('flr(o)', '').lower()
135+
try:
136+
if fec_flr != "n/a":
137+
float(fec_flr)
138+
except ValueError:
139+
pytest.fail("fec_flr is not a valid float for interface {}, \
140+
fec_flr: {}".format(intf_name, fec_flr))
141+
142+
# Test for predicted flr
143+
if not skip_predicted_flr_counters_test(intf):
144+
fec_flr_predicted = intf.get('flr(p) (accuracy)', '').lower()
145+
try:
146+
if fec_flr_predicted != "n/a":
147+
validate_predicted_flr(fec_flr_predicted)
148+
except ValueError:
149+
pytest.fail("predicted_flr is not a valid float for interface {}, \
150+
flr(p): {}".format(intf_name, fec_flr_predicted))

0 commit comments

Comments
 (0)