From 75c56ac47b96b0c0e742f49ad85f790b52c15eeb Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 14 Nov 2025 11:37:46 +1100 Subject: [PATCH 1/3] iperf3: Get working on the unix port of MicroPython. Signed-off-by: Damien George --- python-ecosys/iperf3/iperf3.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/python-ecosys/iperf3/iperf3.py b/python-ecosys/iperf3/iperf3.py index 363d10d59..169a8ed07 100644 --- a/python-ecosys/iperf3/iperf3.py +++ b/python-ecosys/iperf3/iperf3.py @@ -534,7 +534,7 @@ def main(): client(opt_host, opt_udp, opt_reverse) -if sys.platform == "linux": +if sys.implementation.name != "micropython": def pollable_is_sock(pollable, sock): return sock is not None and pollable[0] == sock.fileno() @@ -544,12 +544,12 @@ def ticks_us(): def ticks_diff(a, b): return a - b - - if __name__ == "__main__": - main() else: def pollable_is_sock(pollable, sock): return pollable[0] == sock from time import ticks_us, ticks_diff + +if sys.platform == "linux" and __name__ == "__main__": + main() From 2536a3dbe3275176a6a391db9ce8c9d278f2c200 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 14 Nov 2025 11:38:35 +1100 Subject: [PATCH 2/3] iperf3: Factor out data transfer logic to separate function. So it can be reused by the server code. Signed-off-by: Damien George --- python-ecosys/iperf3/iperf3.py | 66 ++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 27 deletions(-) diff --git a/python-ecosys/iperf3/iperf3.py b/python-ecosys/iperf3/iperf3.py index 169a8ed07..0da460d1f 100644 --- a/python-ecosys/iperf3/iperf3.py +++ b/python-ecosys/iperf3/iperf3.py @@ -198,6 +198,33 @@ def make_cookie(): return cookie +def _transfer(udp, reverse, addr, s_data, buf, udp_last_send, udp_packet_id, udp_interval, stats): + if udp: + if reverse: + recvninto(s_data, buf) + udp_in_sec, udp_in_usec, udp_in_id = struct.unpack_from(">III", buf, 0) + if udp_in_id != udp_packet_id + 1: + stats.add_lost_packets(udp_in_id - (udp_packet_id + 1)) + udp_packet_id = udp_in_id + stats.add_bytes(len(buf)) + else: + t = ticks_us() + if t - udp_last_send > udp_interval: + udp_last_send += udp_interval + udp_packet_id += 1 + struct.pack_into(">III", buf, 0, t // 1000000, t % 1000000, udp_packet_id) + n = s_data.sendto(buf, addr) + stats.add_bytes(n) + else: + if reverse: + recvninto(s_data, buf) + n = len(buf) + else: + n = s_data.send(buf) + stats.add_bytes(n) + return udp_last_send, udp_packet_id + + def server_once(): # Listen for a connection ai = socket.getaddrinfo("0.0.0.0", 5201) @@ -360,6 +387,7 @@ def client(host, udp=False, reverse=False, bandwidth=10 * 1024 * 1024): else: param["tcp"] = True param["len"] = 3000 + udp_interval = None if reverse: param["reverse"] = True @@ -403,33 +431,17 @@ def client(host, udp=False, reverse=False, bandwidth=10 * 1024 * 1024): stats.stop() else: # Send/receiver data - if udp: - if reverse: - recvninto(s_data, buf) - udp_in_sec, udp_in_usec, udp_in_id = struct.unpack_from(">III", buf, 0) - # print(udp_in_sec, udp_in_usec, udp_in_id) - if udp_in_id != udp_packet_id + 1: - stats.add_lost_packets(udp_in_id - (udp_packet_id + 1)) - udp_packet_id = udp_in_id - stats.add_bytes(len(buf)) - else: - # print('UDP send', udp_last_send, t, udp_interval) - if t - udp_last_send > udp_interval: - udp_last_send += udp_interval - udp_packet_id += 1 - struct.pack_into( - ">III", buf, 0, t // 1000000, t % 1000000, udp_packet_id - ) - n = s_data.sendto(buf, ai[-1]) - stats.add_bytes(n) - else: - if reverse: - recvninto(s_data, buf) - n = len(buf) - else: - # print('TCP send', len(buf)) - n = s_data.send(buf) - stats.add_bytes(n) + udp_last_send, udp_packet_id = _transfer( + udp, + reverse, + ai[-1], + s_data, + buf, + udp_last_send, + udp_packet_id, + udp_interval, + stats, + ) elif pollable_is_sock(pollable, s_ctrl): # Receive command From 5309fcc671b2c008d477836b182fd60d58ee9a40 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 14 Nov 2025 11:39:09 +1100 Subject: [PATCH 3/3] iperf3: Fix server UDP mode. The main issues were: - incorrect magic response value - should be using sendto instead of send for UDP Signed-off-by: Damien George --- python-ecosys/iperf3/iperf3.py | 29 +++++++++++++++++++++-------- python-ecosys/iperf3/manifest.py | 2 +- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/python-ecosys/iperf3/iperf3.py b/python-ecosys/iperf3/iperf3.py index 0da460d1f..05d69f774 100644 --- a/python-ecosys/iperf3/iperf3.py +++ b/python-ecosys/iperf3/iperf3.py @@ -260,13 +260,21 @@ def server_once(): s_data, addr = s_listen.accept() print("Accepted connection:", addr) recvn(s_data, COOKIE_SIZE) + udp = False + udp_packet_id = 0 + udp_interval = None + udp_last_send = None elif param.get("udp", False): # Close TCP connection and open UDP "connection" s_listen.close() s_data = socket.socket(ai[0], socket.SOCK_DGRAM) s_data.bind(ai[-1]) data, addr = s_data.recvfrom(4) - s_data.sendto(b"\x12\x34\x56\x78", addr) + s_data.sendto(struct.pack("