Merge remote-tracking branch 'origin/ci-iperf3-log-fix' into integration_2025_w32 (!3552)
CI: refactor iperf3 UDP analysis function - add helper function to covert reported bitrate values to Mbps for calculations - clean up the UDP analysis function, improve test report formatting - fix an issue where Gbps values were incorrectly reported (example: https://jenkins-oai.eurecom.fr/job/RAN-SA-AERIAL-CN5G/4802/) - update CI unit test report checks to match the new formatting
This commit is contained in:
+52
-49
@@ -83,6 +83,29 @@ def Iperf_ComputeTime(args):
|
|||||||
raise Exception('Iperf time not found!')
|
raise Exception('Iperf time not found!')
|
||||||
return int(result.group('iperf_time'))
|
return int(result.group('iperf_time'))
|
||||||
|
|
||||||
|
def convert_to_mbps(value, magnitude):
|
||||||
|
value = float(value)
|
||||||
|
if magnitude == 'K' or magnitude == 'k':
|
||||||
|
return value / 1000
|
||||||
|
elif magnitude == 'M':
|
||||||
|
return value
|
||||||
|
elif magnitude == 'G':
|
||||||
|
return value * 1000
|
||||||
|
else:
|
||||||
|
return value
|
||||||
|
|
||||||
|
def extract_iperf_data(res):
|
||||||
|
if not res:
|
||||||
|
return None
|
||||||
|
bitrate_val = res.group('bitrate')
|
||||||
|
magnitude = res.group('magnitude')
|
||||||
|
return {
|
||||||
|
'bitrate_mbps': convert_to_mbps(bitrate_val, magnitude),
|
||||||
|
'jitter': res.group('jitter'),
|
||||||
|
'packetloss': res.group('packetloss'),
|
||||||
|
'bitrate_disp': f'{float(bitrate_val):.2f} {magnitude}bps'
|
||||||
|
}
|
||||||
|
|
||||||
def Iperf_analyzeV3TCPJson(filename, iperf_tcp_rate_target):
|
def Iperf_analyzeV3TCPJson(filename, iperf_tcp_rate_target):
|
||||||
try:
|
try:
|
||||||
with open(filename) as f:
|
with open(filename) as f:
|
||||||
@@ -130,54 +153,37 @@ def Iperf_analyzeV3BIDIRJson(filename):
|
|||||||
return (True, msg)
|
return (True, msg)
|
||||||
|
|
||||||
def Iperf_analyzeV3UDP(filename, iperf_bitrate_threshold, iperf_packetloss_threshold, target_bitrate):
|
def Iperf_analyzeV3UDP(filename, iperf_bitrate_threshold, iperf_packetloss_threshold, target_bitrate):
|
||||||
if (not os.path.isfile(filename)):
|
if not os.path.isfile(filename):
|
||||||
return (False, 'Iperf3 UDP: Log file not present')
|
return (False, 'Iperf3 UDP: Log file not present')
|
||||||
if (os.path.getsize(filename)==0):
|
if os.path.getsize(filename) == 0:
|
||||||
return (False, 'Iperf3 UDP: Log file is empty')
|
return (False, 'Iperf3 UDP: Log file is empty')
|
||||||
sender_bitrate = None
|
|
||||||
receiver_bitrate = None
|
|
||||||
with open(filename, 'r') as server_file:
|
|
||||||
for line in server_file.readlines():
|
|
||||||
res_sender = re.search(r'(?P<bitrate>[0-9\.]+)\s+(?P<unit>[KMG]?bits\/sec)\s+(?P<jitter>[0-9\.]+\s+ms)\s+(?P<lostPack>-?\d+)/(?P<sentPack>-?\d+) \((?P<lost>[0-9\.]+).*?\s+(sender)', line)
|
|
||||||
res_receiver = re.search(r'(?P<bitrate>[0-9\.]+)\s+(?P<unit>[KMG]?bits\/sec)\s+(?P<jitter>[0-9\.]+\s+ms)\s+(?P<lostPack>-?\d+)/(?P<receivedPack>-?\d+)\s+\((?P<lost>[0-9\.]+)%\).*?(receiver)', line)
|
|
||||||
if res_sender is not None:
|
|
||||||
sender_bitrate = res_sender.group('bitrate')
|
|
||||||
sender_unit = res_sender.group('unit')
|
|
||||||
sender_jitter = res_sender.group('jitter')
|
|
||||||
sender_lostPack = res_sender.group('lostPack')
|
|
||||||
sender_sentPack = res_sender.group('sentPack')
|
|
||||||
sender_packetloss = res_sender.group('lost')
|
|
||||||
if res_receiver is not None:
|
|
||||||
receiver_bitrate = res_receiver.group('bitrate')
|
|
||||||
receiver_unit = res_receiver.group('unit')
|
|
||||||
receiver_jitter = res_receiver.group('jitter')
|
|
||||||
receiver_lostPack = res_receiver.group('lostPack')
|
|
||||||
receiver_receivedPack = res_receiver.group('receivedPack')
|
|
||||||
receiver_packetloss = res_receiver.group('lost')
|
|
||||||
|
|
||||||
if receiver_bitrate is not None and sender_bitrate is not None:
|
sender_data = None
|
||||||
if sender_unit == 'Kbits/sec':
|
receiver_data = None
|
||||||
sender_bitrate = float(sender_bitrate) / 1000
|
with open(filename, 'r') as server_file:
|
||||||
if receiver_unit == 'Kbits/sec':
|
for line in server_file:
|
||||||
receiver_bitrate = float(receiver_bitrate) / 1000
|
res_sender = re.search(r'(?P<bitrate>[0-9\.]+)\s+(?P<magnitude>[kKMG]?)bits\/sec\s+(?P<jitter>[0-9\.]+\s+ms)\s+(?P<lostPack>-?\d+)/(?P<sentPack>-?\d+)\s+\((?P<packetloss>[0-9\.eE\-\+]+).*?\s+(sender)', line)
|
||||||
br_perf = 100 * float(receiver_bitrate) / float(target_bitrate)
|
res_receiver = re.search(r'(?P<bitrate>[0-9\.]+)\s+(?P<magnitude>[kKMG]?)bits\/sec\s+(?P<jitter>[0-9\.]+\s+ms)\s+(?P<lostPack>-?\d+)/(?P<receivedPack>-?\d+)\s+\((?P<packetloss>[0-9\.eE\-\+]+)%\).*?(receiver)', line)
|
||||||
br_perf = '%.2f ' % br_perf
|
if res_sender:
|
||||||
sender_bitrate = '%.2f ' % float(sender_bitrate)
|
sender_data = extract_iperf_data(res_sender)
|
||||||
receiver_bitrate = '%.2f ' % float(receiver_bitrate)
|
if res_receiver:
|
||||||
req_msg = f'Sender Bitrate : {sender_bitrate} Mbps'
|
receiver_data = extract_iperf_data(res_receiver)
|
||||||
bir_msg = f'Receiver Bitrate: {receiver_bitrate} Mbps'
|
if not sender_data or not receiver_data:
|
||||||
brl_msg = f'{br_perf}%'
|
|
||||||
jit_msg = f'Jitter : {receiver_jitter}'
|
|
||||||
pal_msg = f'Packet Loss : {receiver_packetloss} %'
|
|
||||||
if float(br_perf) < float(iperf_bitrate_threshold):
|
|
||||||
brl_msg = f'too low! < {iperf_bitrate_threshold}%'
|
|
||||||
if float(receiver_packetloss) > float(iperf_packetloss_threshold):
|
|
||||||
pal_msg += f' (too high! > {iperf_packetloss_threshold}%)'
|
|
||||||
result = float(br_perf) >= float(iperf_bitrate_threshold) and float(receiver_packetloss) <= float(iperf_packetloss_threshold)
|
|
||||||
return (result, f'{req_msg}\n{bir_msg} ({brl_msg})\n{jit_msg}\n{pal_msg}')
|
|
||||||
else:
|
|
||||||
return (False, 'Could not analyze iperf report')
|
return (False, 'Could not analyze iperf report')
|
||||||
|
|
||||||
|
br_perf = 100 * receiver_data['bitrate_mbps'] / float(target_bitrate)
|
||||||
|
br_perf_str = f'{br_perf:.2f}%'
|
||||||
|
req_msg = f"Sender Bitrate : {sender_data['bitrate_disp']}"
|
||||||
|
bir_msg = f"Receiver Bitrate: {receiver_data['bitrate_disp']} ({br_perf_str})"
|
||||||
|
jit_msg = f"Jitter : {receiver_data['jitter']}"
|
||||||
|
pal_msg = f"Packet Loss : {receiver_data['packetloss']}%"
|
||||||
|
if br_perf < float(iperf_bitrate_threshold):
|
||||||
|
bir_msg += f' (too low! < {iperf_bitrate_threshold}%)'
|
||||||
|
if float(receiver_data['packetloss']) > float(iperf_packetloss_threshold):
|
||||||
|
pal_msg += f' (too high! > {iperf_packetloss_threshold}%)'
|
||||||
|
result = br_perf >= float(iperf_bitrate_threshold) and float(receiver_data['packetloss']) <= float(iperf_packetloss_threshold)
|
||||||
|
return (result, f'{req_msg}\n{bir_msg}\n{jit_msg}\n{pal_msg}')
|
||||||
|
|
||||||
def Iperf_analyzeV2UDP(server_filename, iperf_bitrate_threshold, iperf_packetloss_threshold, target_bitrate):
|
def Iperf_analyzeV2UDP(server_filename, iperf_bitrate_threshold, iperf_packetloss_threshold, target_bitrate):
|
||||||
result = None
|
result = None
|
||||||
if (not os.path.isfile(server_filename)):
|
if (not os.path.isfile(server_filename)):
|
||||||
@@ -190,12 +196,9 @@ def Iperf_analyzeV2UDP(server_filename, iperf_bitrate_threshold, iperf_packetlos
|
|||||||
result = re.search(statusTemplate, str(line)) or result
|
result = re.search(statusTemplate, str(line)) or result
|
||||||
if result is None:
|
if result is None:
|
||||||
return (False, 'Could not parse server report!')
|
return (False, 'Could not parse server report!')
|
||||||
bitrate = float(result.group('bitrate'))
|
bitrate_val = float(result.group('bitrate'))
|
||||||
magn = result.group('magnitude')
|
magnitude = result.group('magnitude')
|
||||||
if magn == "k" or magn == "K":
|
bitrate = convert_to_mbps(bitrate_val, magnitude)
|
||||||
bitrate /= 1000
|
|
||||||
elif magn == "G": # we assume bitrate in Mbps, therefore it must be G now
|
|
||||||
bitrate *= 1000
|
|
||||||
jitter = float(result.group('jitter'))
|
jitter = float(result.group('jitter'))
|
||||||
packetloss = float(result.group('packetloss'))
|
packetloss = float(result.group('packetloss'))
|
||||||
br_perf = float(bitrate)/float(target_bitrate) * 100
|
br_perf = float(bitrate)/float(target_bitrate) * 100
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
Sender Bitrate : 0.52 Mbps
|
Sender Bitrate : 524.00 Kbps
|
||||||
Receiver Bitrate: 0.52 Mbps (too low! < 99%)
|
Receiver Bitrate: 524.00 Kbps (52.40%) (too low! < 99%)
|
||||||
Jitter : 0.026 ms
|
Jitter : 0.026 ms
|
||||||
Packet Loss : 10 % (too high! > 0%)
|
Packet Loss : 10% (too high! > 0%)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
Sender Bitrate : 0.00 Mbps
|
Sender Bitrate : 0.00 bps
|
||||||
Receiver Bitrate: 3.98 Mbps (too low! < 99%)
|
Receiver Bitrate: 3.98 Mbps (4.97%) (too low! < 99%)
|
||||||
Jitter : 3.847 ms
|
Jitter : 3.847 ms
|
||||||
Packet Loss : 0.038 % (too high! > 0%)
|
Packet Loss : 0.038% (too high! > 0%)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
Sender Bitrate : 1.03 Mbps
|
Sender Bitrate : 1.03 Mbps
|
||||||
Receiver Bitrate: 0.00 Mbps (too low! < 99%)
|
Receiver Bitrate: 0.00 bps (0.00%) (too low! < 99%)
|
||||||
Jitter : 0.000 ms
|
Jitter : 0.000 ms
|
||||||
Packet Loss : 0 %
|
Packet Loss : 0%
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
Sender Bitrate : 1.00 Mbps
|
Sender Bitrate : 996.00 Kbps
|
||||||
Receiver Bitrate: 1.00 Mbps (99.60 %)
|
Receiver Bitrate: 996.00 Kbps (99.60%)
|
||||||
Jitter : 0.029 ms
|
Jitter : 0.029 ms
|
||||||
Packet Loss : 0 %
|
Packet Loss : 0%
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
Sender Bitrate : 4.67 Mbps
|
Sender Bitrate : 4.67 Mbps
|
||||||
Receiver Bitrate: 4.67 Mbps (100.00 %)
|
Receiver Bitrate: 4.67 Mbps (100.00%)
|
||||||
Jitter : 3.413 ms
|
Jitter : 3.413 ms
|
||||||
Packet Loss : 0 %
|
Packet Loss : 0%
|
||||||
|
|||||||
@@ -60,5 +60,20 @@ class TestPingIperf(unittest.TestCase):
|
|||||||
success = self.ci.Iperf2_Unidir(self.html, self.cont, infra_file=infra_file)
|
success = self.ci.Iperf2_Unidir(self.html, self.cont, infra_file=infra_file)
|
||||||
self.assertTrue(success)
|
self.assertTrue(success)
|
||||||
|
|
||||||
|
def test_iperf_highrate(self):
|
||||||
|
# note: needs to be five seconds because Iperf() adds -O 3, so if it is
|
||||||
|
# too short, the server is terminated before the client loaded
|
||||||
|
# everything
|
||||||
|
self.ci.iperf_args = "-u -t 5 -b 1000M -R -O 0"
|
||||||
|
self.ci.svr_id = "test"
|
||||||
|
self.ci.svr_node = "localhost"
|
||||||
|
self.ci.iperf_packetloss_threshold = "0"
|
||||||
|
self.ci.iperf_bitrate_threshold = "0"
|
||||||
|
self.ci.iperf_profile = "balanced"
|
||||||
|
infra_file = "tests/config/infra_ping_iperf.yaml"
|
||||||
|
# TODO Should need nothing but options and UE(s) to use
|
||||||
|
success = self.ci.Iperf(self.html, self.cont, infra_file=infra_file)
|
||||||
|
self.assertTrue(success)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
Reference in New Issue
Block a user