status works

This commit is contained in:
Bob 2025-12-14 15:20:53 -08:00
parent 0d7674052b
commit beae917a36
2 changed files with 39 additions and 35 deletions

View File

@ -27,12 +27,13 @@ static int cmd_iperf(int argc, char **argv) {
if (strcmp(argv[1], "start") == 0) {
iperf_cfg_t cfg = { .time = 0 }; // Infinite
iperf_start(&cfg);
printf("IPERF_STARTED\n");
// iperf_start already logs "IPERF_STARTED" via printf in iperf.c,
// but keeping it here is fine/redundant.
// To be safe and clean, we rely on iperf.c's output or just return success.
return 0;
} else if (strcmp(argv[1], "stop") == 0) {
iperf_stop();
printf("IPERF_STOPPED\n");
return 0;
} else if (strcmp(argv[1], "pps") == 0) {
@ -47,12 +48,12 @@ static int cmd_iperf(int argc, char **argv) {
return 1;
}
iperf_set_pps((uint32_t)pps);
printf("IPERF_PPS_UPDATED: %d\n", pps);
// iperf_set_pps prints "IPERF_PPS_UPDATED: ..."
return 0;
} else if (strcmp(argv[1], "status") == 0) {
uint32_t pps = iperf_get_pps();
printf("IPERF_STATUS: PPS=%lu\n", (unsigned long)pps);
// [FIXED] Use the new API to print detailed stats
iperf_print_status();
return 0;
}

View File

@ -6,6 +6,7 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <time.h> // Added for clock_gettime
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
@ -83,6 +84,7 @@ static void iperf_network_event_handler(void* arg, esp_event_base_t event_base,
static bool iperf_wait_for_ip(void) {
if (!s_iperf_event_group) s_iperf_event_group = xEventGroupCreate();
// Check if we already have IP
esp_netif_t *netif = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF");
if (netif) {
esp_netif_ip_info_t ip_info;
@ -94,11 +96,18 @@ static bool iperf_wait_for_ip(void) {
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &iperf_network_event_handler, NULL, &instance_any_id));
ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &iperf_network_event_handler, NULL, &instance_got_ip));
ESP_LOGI(TAG, "Waiting for IP...");
EventBits_t bits = xEventGroupWaitBits(s_iperf_event_group, IPERF_IP_READY_BIT | IPERF_STOP_REQ_BIT, pdFALSE, pdFALSE, portMAX_DELAY);
esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, instance_any_id);
esp_event_handler_instance_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, instance_got_ip);
return !(bits & IPERF_STOP_REQ_BIT);
if (bits & IPERF_STOP_REQ_BIT) {
ESP_LOGW(TAG, "Stop requested while waiting for IP");
return false;
}
ESP_LOGI(TAG, "IP Ready. Starting traffic.");
return true;
}
static void trim_whitespace(char *str) {
@ -169,25 +178,32 @@ static esp_err_t iperf_start_udp_client(iperf_ctrl_t *ctrl) {
addr.sin_port = htons(ctrl->cfg.dport > 0 ? ctrl->cfg.dport : 5001);
addr.sin_addr.s_addr = ctrl->cfg.dip;
// Log destination for debugging
char ip_str[32];
inet_ntop(AF_INET, &addr.sin_addr, ip_str, sizeof(ip_str));
ESP_LOGI(TAG, "Client sending to %s:%d", ip_str, ntohs(addr.sin_port));
int sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sockfd < 0) {
status_led_set_state(LED_STATE_FAILED);
ESP_LOGE(TAG, "Socket creation failed: %d", errno);
return ESP_FAIL;
}
// Indicate Running
status_led_set_state(LED_STATE_TRANSMITTING_SLOW);
s_stats.running = true;
printf("IPERF_STARTED\n");
// Fix: Ensure we have a default time if 0 (infinite)
int64_t next_send_time = esp_timer_get_time();
int64_t end_time = (ctrl->cfg.time == 0) ? INT64_MAX : esp_timer_get_time() + (int64_t)ctrl->cfg.time * 1000000LL;
int64_t last_rate_check = esp_timer_get_time();
uint32_t packets_since_check = 0;
int32_t packet_id = 0;
struct timespec ts;
while (!ctrl->finish && esp_timer_get_time() < end_time) {
int64_t now = esp_timer_get_time();
int64_t wait = next_send_time - now;
@ -198,22 +214,21 @@ 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);
// CHANGED: gettimeofday -> clock_gettime
clock_gettime(CLOCK_REALTIME, &ts);
hdr->tv_sec = htonl(ts.tv_sec);
hdr->tv_usec = htonl(ts.tv_nsec / 1000); // Nanoseconds to Microseconds
// 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) {
int sent = sendto(sockfd, ctrl->buffer, ctrl->cfg.send_len, 0, (struct sockaddr *)&addr, sizeof(addr));
if (sent > 0) {
packets_since_check++;
} else {
if (errno != 12) { // Not ENOMEM
if (errno != 12) {
ESP_LOGE(TAG, "Send failed: %d", errno);
status_led_set_state(LED_STATE_FAILED);
goto exit;
@ -222,15 +237,12 @@ static esp_err_t iperf_start_udp_client(iperf_ctrl_t *ctrl) {
}
}
// --- Stats & LED Update ---
now = esp_timer_get_time();
if (now - last_rate_check > RATE_CHECK_INTERVAL_US) {
uint32_t interval_us = (uint32_t)(now - last_rate_check);
if (interval_us > 0) {
s_stats.actual_pps = (uint32_t)((uint64_t)packets_since_check * 1000000 / interval_us);
}
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;
@ -239,27 +251,22 @@ static esp_err_t iperf_start_udp_client(iperf_ctrl_t *ctrl) {
last_rate_check = now;
packets_since_check = 0;
}
next_send_time += ctrl->cfg.pacing_period_us;
}
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.
// Termination Packets
{
udp_datagram *hdr = (udp_datagram *)ctrl->buffer;
int32_t final_id = -(packet_id); // Negative ID signals End of Stream
int32_t final_id = -packet_id;
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);
// CHANGED: gettimeofday -> clock_gettime
clock_gettime(CLOCK_REALTIME, &ts);
hdr->tv_sec = htonl(ts.tv_sec);
hdr->tv_usec = htonl(ts.tv_nsec / 1000);
// 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));
@ -268,8 +275,6 @@ exit:
}
close(sockfd);
// Cleanup State
s_stats.running = false;
s_stats.actual_pps = 0;
status_led_set_state(LED_STATE_CONNECTED);
@ -279,11 +284,9 @@ exit:
static void iperf_task(void *arg) {
iperf_ctrl_t *ctrl = (iperf_ctrl_t *)arg;
if (ctrl->cfg.flag & IPERF_FLAG_UDP && ctrl->cfg.flag & IPERF_FLAG_CLIENT) {
iperf_start_udp_client(ctrl);
}
free(ctrl->buffer);
s_iperf_task_handle = NULL;
vTaskDelete(NULL);