more on control_iperf.py support

This commit is contained in:
Bob 2025-12-14 14:48:56 -08:00
parent 71fd317229
commit 0d7674052b
1 changed files with 31 additions and 6 deletions

View File

@ -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");
}
}