status works
This commit is contained in:
parent
0d7674052b
commit
beae917a36
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue