From 0d7674052bd8769dcb9c18aff3cc827b3e080cf7 Mon Sep 17 00:00:00 2001 From: Bob Date: Sun, 14 Dec 2025 14:48:56 -0800 Subject: [PATCH] more on control_iperf.py support --- components/iperf/iperf.c | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/components/iperf/iperf.c b/components/iperf/iperf.c index 2375808..31abc82 100644 --- a/components/iperf/iperf.c +++ b/components/iperf/iperf.c @@ -64,7 +64,6 @@ void iperf_print_status(void) { err = (float)diff * 100.0f / (float)s_stats.config_pps; } - // Format expected by Python regex printf("IPERF_STATUS: Running=%d, Config=%" PRIu32 ", Actual=%" PRIu32 ", Err=%.1f%%\n", s_stats.running, s_stats.config_pps, s_stats.actual_pps, err); } @@ -198,12 +197,19 @@ static esp_err_t iperf_start_udp_client(iperf_ctrl_t *ctrl) { for (int k = 0; k < ctrl->cfg.burst_count; k++) { udp_datagram *hdr = (udp_datagram *)ctrl->buffer; + + // 1. Sequence ID hdr->id = htonl(packet_id++); + + // 2. Timestamp struct timeval tv; gettimeofday(&tv, NULL); hdr->tv_sec = htonl(tv.tv_sec); hdr->tv_usec = htonl(tv.tv_usec); + // 3. ID2 (Required for some iperf parsers) + hdr->id2 = hdr->id; + if (sendto(sockfd, ctrl->buffer, ctrl->cfg.send_len, 0, (struct sockaddr *)&addr, sizeof(addr)) > 0) { packets_since_check++; } else { @@ -221,12 +227,10 @@ static esp_err_t iperf_start_udp_client(iperf_ctrl_t *ctrl) { if (now - last_rate_check > RATE_CHECK_INTERVAL_US) { uint32_t interval_us = (uint32_t)(now - last_rate_check); - // Calculate actual PPS if (interval_us > 0) { s_stats.actual_pps = (uint32_t)((uint64_t)packets_since_check * 1000000 / interval_us); } - // LED Feedback uint32_t config_pps = iperf_get_pps(); uint32_t threshold = (config_pps * 3) / 4; led_state_t target = (s_stats.actual_pps >= threshold) ? LED_STATE_TRANSMITTING : LED_STATE_TRANSMITTING_SLOW; @@ -240,11 +244,34 @@ static esp_err_t iperf_start_udp_client(iperf_ctrl_t *ctrl) { } exit: + // --- SEND TERMINATION PACKETS --- + // Send a negative sequence ID to tell the server the session is done. + // This allows immediate restart without waiting for server timeout. + { + udp_datagram *hdr = (udp_datagram *)ctrl->buffer; + int32_t final_id = -(packet_id); // Negative ID signals End of Stream + + hdr->id = htonl(final_id); + hdr->id2 = hdr->id; + + struct timeval tv; + gettimeofday(&tv, NULL); + hdr->tv_sec = htonl(tv.tv_sec); + hdr->tv_usec = htonl(tv.tv_usec); + + // Send a burst of death packets to ensure delivery over UDP + for(int i=0; i<10; i++) { + sendto(sockfd, ctrl->buffer, ctrl->cfg.send_len, 0, (struct sockaddr *)&addr, sizeof(addr)); + vTaskDelay(pdMS_TO_TICKS(2)); + } + ESP_LOGI(TAG, "Sent termination packets (ID: %ld)", (long)final_id); + } + close(sockfd); + // Cleanup State s_stats.running = false; s_stats.actual_pps = 0; - // Reset LED to Green (Connected) status_led_set_state(LED_STATE_CONNECTED); printf("IPERF_STOPPED\n"); return ESP_OK; @@ -258,7 +285,6 @@ static void iperf_task(void *arg) { } free(ctrl->buffer); - // CRITICAL: Clear handle so start() can run again s_iperf_task_handle = NULL; vTaskDelete(NULL); } @@ -289,7 +315,6 @@ void iperf_stop(void) { s_iperf_ctrl.finish = true; if (s_iperf_event_group) xEventGroupSetBits(s_iperf_event_group, IPERF_STOP_REQ_BIT); } else { - // If already stopped, just print to satisfy controller printf("IPERF_STOPPED\n"); } }