samples: net: zperf: Convert to use usec directly
Currently the code uses hw cycles and tries to convert them to usec. I noticed some failures with this, for example the test duration was sometimes missed meaning that instead of testing 5 seconds, we bailed out after 2 sec etc. After the kernel k_timeout_t changes, which added APIs to support usec accuracy, we can use usec and ticks here. This simplifies the code a bit. Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
This commit is contained in:
parent
c8d7dcc897
commit
77a74414d1
6 changed files with 84 additions and 95 deletions
|
@ -37,32 +37,6 @@
|
|||
|
||||
#define PACKET_SIZE_MAX 1024
|
||||
|
||||
#define HW_CYCLES_TO_USEC(__hw_cycle__) \
|
||||
( \
|
||||
((uint64_t)(__hw_cycle__) * (uint64_t)USEC_PER_SEC) / \
|
||||
((uint64_t)sys_clock_hw_cycles_per_sec()) \
|
||||
)
|
||||
|
||||
#define HW_CYCLES_TO_SEC(__hw_cycle__) \
|
||||
( \
|
||||
((uint64_t)(HW_CYCLES_TO_USEC(__hw_cycle__))) / \
|
||||
((uint64_t)USEC_PER_SEC) \
|
||||
)
|
||||
|
||||
#define USEC_TO_HW_CYCLES(__usec__) \
|
||||
( \
|
||||
((uint64_t)(__usec__) * (uint64_t)sys_clock_hw_cycles_per_sec()) / \
|
||||
((uint64_t)USEC_PER_SEC) \
|
||||
)
|
||||
|
||||
#define SEC_TO_HW_CYCLES(__sec__) \
|
||||
USEC_TO_HW_CYCLES((uint64_t)(__sec__) * \
|
||||
(uint64_t)USEC_PER_SEC)
|
||||
|
||||
#define MSEC_TO_HW_CYCLES(__msec__) \
|
||||
USEC_TO_HW_CYCLES((uint64_t)(__msec__) * \
|
||||
(uint64_t)MSEC_PER_SEC)
|
||||
|
||||
struct zperf_udp_datagram {
|
||||
int32_t id;
|
||||
uint32_t tv_sec;
|
||||
|
|
|
@ -49,7 +49,7 @@ struct session {
|
|||
uint32_t outorder;
|
||||
uint32_t error;
|
||||
uint64_t length;
|
||||
uint32_t start_time;
|
||||
int64_t start_time;
|
||||
uint32_t last_time;
|
||||
int32_t jitter;
|
||||
int32_t last_transit_time;
|
||||
|
|
|
@ -41,14 +41,14 @@ static void tcp_received(struct net_context *context,
|
|||
{
|
||||
const struct shell *shell = tcp_shell;
|
||||
struct session *session;
|
||||
uint32_t time;
|
||||
int64_t time;
|
||||
|
||||
if (!shell) {
|
||||
printk("Shell is not set!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
time = k_cycle_get_32();
|
||||
time = k_uptime_ticks();
|
||||
|
||||
session = get_tcp_session(context);
|
||||
if (!session) {
|
||||
|
@ -63,7 +63,7 @@ static void tcp_received(struct net_context *context,
|
|||
shell_fprintf(shell, SHELL_NORMAL,
|
||||
"New TCP session started\n");
|
||||
zperf_reset_session_stats(session);
|
||||
session->start_time = k_cycle_get_32();
|
||||
session->start_time = k_uptime_ticks();
|
||||
session->state = STATE_ONGOING;
|
||||
__fallthrough;
|
||||
case STATE_ONGOING:
|
||||
|
@ -75,18 +75,19 @@ static void tcp_received(struct net_context *context,
|
|||
|
||||
if (pkt == NULL && status == 0) { /* EOF */
|
||||
uint32_t rate_in_kbps;
|
||||
uint32_t duration = HW_CYCLES_TO_USEC(
|
||||
time_delta(session->start_time, time));
|
||||
uint32_t duration;
|
||||
|
||||
duration = k_ticks_to_us_ceil32(time -
|
||||
session->start_time);
|
||||
|
||||
session->state = STATE_COMPLETED;
|
||||
|
||||
/* Compute baud rate */
|
||||
if (duration != 0U) {
|
||||
rate_in_kbps = (uint32_t)
|
||||
(((uint64_t)session->length *
|
||||
(uint64_t)8 *
|
||||
((session->length * 8ULL *
|
||||
(uint64_t)USEC_PER_SEC) /
|
||||
((uint64_t)duration * 1024U));
|
||||
((uint64_t)duration * 1024ULL));
|
||||
} else {
|
||||
rate_in_kbps = 0U;
|
||||
}
|
||||
|
|
|
@ -27,10 +27,9 @@ void zperf_tcp_upload(const struct shell *shell,
|
|||
unsigned int packet_size,
|
||||
struct zperf_results *results)
|
||||
{
|
||||
uint32_t duration = MSEC_TO_HW_CYCLES(duration_in_ms);
|
||||
int64_t duration = z_timeout_end_calc(K_MSEC(duration_in_ms));
|
||||
int64_t start_time, last_print_time, end_time, remaining;
|
||||
uint32_t nb_packets = 0U, nb_errors = 0U;
|
||||
uint32_t start_time, last_print_time, end_time;
|
||||
uint8_t time_elapsed = 0U, finished = 0U;
|
||||
uint32_t alloc_errors = 0U;
|
||||
|
||||
if (packet_size > PACKET_SIZE_MAX) {
|
||||
|
@ -41,7 +40,7 @@ void zperf_tcp_upload(const struct shell *shell,
|
|||
}
|
||||
|
||||
/* Start the loop */
|
||||
start_time = k_cycle_get_32();
|
||||
start_time = k_uptime_ticks();
|
||||
last_print_time = start_time;
|
||||
|
||||
shell_fprintf(shell, SHELL_NORMAL,
|
||||
|
@ -57,10 +56,6 @@ void zperf_tcp_upload(const struct shell *shell,
|
|||
|
||||
do {
|
||||
int ret = 0;
|
||||
uint32_t loop_time;
|
||||
|
||||
/* Timestamps */
|
||||
loop_time = k_cycle_get_32();
|
||||
|
||||
/* Send the packet */
|
||||
ret = net_context_send(ctx, sample_packet,
|
||||
|
@ -87,15 +82,6 @@ void zperf_tcp_upload(const struct shell *shell,
|
|||
}
|
||||
} else {
|
||||
nb_packets++;
|
||||
|
||||
if (time_elapsed) {
|
||||
finished = 1U;
|
||||
}
|
||||
}
|
||||
|
||||
if (!time_elapsed && time_delta(start_time,
|
||||
loop_time) > duration) {
|
||||
time_elapsed = 1U;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ARCH_POSIX)
|
||||
|
@ -103,14 +89,16 @@ void zperf_tcp_upload(const struct shell *shell,
|
|||
#else
|
||||
k_yield();
|
||||
#endif
|
||||
} while (!finished);
|
||||
|
||||
end_time = k_cycle_get_32();
|
||||
remaining = duration - k_uptime_ticks();
|
||||
} while (remaining > 0);
|
||||
|
||||
end_time = k_uptime_ticks();
|
||||
|
||||
/* Add result coming from the client */
|
||||
results->nb_packets_sent = nb_packets;
|
||||
results->client_time_in_us =
|
||||
HW_CYCLES_TO_USEC(time_delta(start_time, end_time));
|
||||
k_ticks_to_us_ceil32(end_time - start_time);
|
||||
results->packet_size = packet_size;
|
||||
results->nb_packets_errors = nb_errors;
|
||||
|
||||
|
|
|
@ -125,7 +125,7 @@ static void udp_received(struct net_context *context,
|
|||
struct zperf_udp_datagram *hdr;
|
||||
struct session *session;
|
||||
int32_t transit_time;
|
||||
uint32_t time;
|
||||
int64_t time;
|
||||
int32_t id;
|
||||
|
||||
if (!pkt) {
|
||||
|
@ -139,7 +139,7 @@ static void udp_received(struct net_context *context,
|
|||
goto out;
|
||||
}
|
||||
|
||||
time = k_cycle_get_32();
|
||||
time = k_uptime_ticks();
|
||||
|
||||
session = get_session(pkt, ip_hdr, proto_hdr, SESSION_UDP);
|
||||
if (!session) {
|
||||
|
@ -180,17 +180,18 @@ static void udp_received(struct net_context *context,
|
|||
|
||||
shell_fprintf(shell, SHELL_NORMAL, "End of session!\n");
|
||||
|
||||
duration = HW_CYCLES_TO_USEC(
|
||||
time_delta(session->start_time, time));
|
||||
duration = k_ticks_to_us_ceil32(time -
|
||||
session->start_time);
|
||||
|
||||
/* Update state machine */
|
||||
session->state = STATE_COMPLETED;
|
||||
|
||||
/* Compute baud rate */
|
||||
if (duration != 0U) {
|
||||
rate_in_kbps = (uint32_t)
|
||||
(((uint64_t)session->length * (uint64_t)8 *
|
||||
((session->length * 8ULL *
|
||||
(uint64_t)USEC_PER_SEC) /
|
||||
((uint64_t)duration * 1024U));
|
||||
((uint64_t)duration * 1024ULL));
|
||||
} else {
|
||||
rate_in_kbps = 0U;
|
||||
}
|
||||
|
@ -246,10 +247,10 @@ static void udp_received(struct net_context *context,
|
|||
session->length += net_pkt_remaining_data(pkt);
|
||||
|
||||
/* Compute jitter */
|
||||
transit_time = time_delta(HW_CYCLES_TO_USEC(time),
|
||||
ntohl(hdr->tv_sec) *
|
||||
USEC_PER_SEC +
|
||||
ntohl(hdr->tv_usec));
|
||||
transit_time = time_delta(
|
||||
k_ticks_to_us_ceil32(time),
|
||||
ntohl(hdr->tv_sec) * USEC_PER_SEC +
|
||||
ntohl(hdr->tv_usec));
|
||||
if (session->last_transit_time != 0) {
|
||||
int32_t delta_transit = transit_time -
|
||||
session->last_transit_time;
|
||||
|
|
|
@ -75,13 +75,15 @@ static void stat_received(struct net_context *context,
|
|||
static inline void zperf_upload_fin(const struct shell *shell,
|
||||
struct net_context *context,
|
||||
uint32_t nb_packets,
|
||||
uint32_t end_time,
|
||||
uint64_t end_time,
|
||||
uint32_t packet_size,
|
||||
struct zperf_results *results)
|
||||
{
|
||||
struct net_pkt *stat = NULL;
|
||||
struct zperf_udp_datagram *datagram;
|
||||
struct zperf_client_hdr_v1 *hdr;
|
||||
uint32_t secs = k_ticks_to_ms_ceil32(end_time) / 1000U;
|
||||
uint32_t usecs = k_ticks_to_us_ceil32(end_time) - secs * USEC_PER_SEC;
|
||||
int loop = 2;
|
||||
int ret;
|
||||
|
||||
|
@ -90,9 +92,8 @@ static inline void zperf_upload_fin(const struct shell *shell,
|
|||
|
||||
/* Fill the packet header */
|
||||
datagram->id = htonl(-nb_packets);
|
||||
datagram->tv_sec = htonl(HW_CYCLES_TO_SEC(end_time));
|
||||
datagram->tv_usec = htonl(HW_CYCLES_TO_USEC(end_time) %
|
||||
USEC_PER_SEC);
|
||||
datagram->tv_sec = htonl(secs);
|
||||
datagram->tv_usec = htonl(usecs);
|
||||
|
||||
hdr = (struct zperf_client_hdr_v1 *)(sample_packet +
|
||||
sizeof(*datagram));
|
||||
|
@ -164,14 +165,15 @@ void zperf_udp_upload(const struct shell *shell,
|
|||
unsigned int rate_in_kbps,
|
||||
struct zperf_results *results)
|
||||
{
|
||||
uint32_t packet_duration = (uint32_t)(((uint64_t) packet_size *
|
||||
SEC_TO_HW_CYCLES(1) * 8U) /
|
||||
(uint64_t)(rate_in_kbps * 1024U));
|
||||
uint32_t duration = MSEC_TO_HW_CYCLES(duration_in_ms);
|
||||
uint32_t print_interval = SEC_TO_HW_CYCLES(1);
|
||||
uint32_t delay = packet_duration;
|
||||
uint32_t packet_duration = ((uint32_t)packet_size * 8U * USEC_PER_SEC) /
|
||||
(rate_in_kbps * 1024U);
|
||||
uint64_t duration = z_timeout_end_calc(K_MSEC(duration_in_ms));
|
||||
int64_t print_interval = z_timeout_end_calc(K_SECONDS(1));
|
||||
uint64_t delay = packet_duration;
|
||||
uint32_t nb_packets = 0U;
|
||||
uint32_t start_time, last_print_time, last_loop_time, end_time;
|
||||
int64_t start_time, end_time;
|
||||
int64_t last_print_time, last_loop_time;
|
||||
int64_t remaining, print_info;
|
||||
|
||||
if (packet_size > PACKET_SIZE_MAX) {
|
||||
shell_fprintf(shell, SHELL_WARNING,
|
||||
|
@ -185,8 +187,18 @@ void zperf_udp_upload(const struct shell *shell,
|
|||
packet_size = sizeof(struct zperf_udp_datagram);
|
||||
}
|
||||
|
||||
if (packet_duration > 1000U) {
|
||||
shell_fprintf(shell, SHELL_NORMAL,
|
||||
"Packet duration %u ms\n",
|
||||
(unsigned int)(packet_duration / 1000U));
|
||||
} else {
|
||||
shell_fprintf(shell, SHELL_NORMAL,
|
||||
"Packet duration %u us\n",
|
||||
(unsigned int)packet_duration);
|
||||
}
|
||||
|
||||
/* Start the loop */
|
||||
start_time = k_cycle_get_32();
|
||||
start_time = k_uptime_ticks();
|
||||
last_print_time = start_time;
|
||||
last_loop_time = start_time;
|
||||
|
||||
|
@ -195,38 +207,44 @@ void zperf_udp_upload(const struct shell *shell,
|
|||
do {
|
||||
struct zperf_udp_datagram *datagram;
|
||||
struct zperf_client_hdr_v1 *hdr;
|
||||
uint32_t loop_time;
|
||||
uint32_t secs, usecs;
|
||||
int64_t loop_time;
|
||||
int32_t adjust;
|
||||
int ret;
|
||||
|
||||
/* Timestamp */
|
||||
loop_time = k_cycle_get_32();
|
||||
loop_time = k_uptime_ticks();
|
||||
|
||||
/* Algorithm to maintain a given baud rate */
|
||||
if (last_loop_time != loop_time) {
|
||||
adjust = packet_duration - time_delta(last_loop_time,
|
||||
loop_time);
|
||||
adjust = (int32_t)(packet_duration -
|
||||
k_ticks_to_us_ceil32(loop_time -
|
||||
last_loop_time));
|
||||
} else {
|
||||
/* It's the first iteration so no need for adjustment
|
||||
*/
|
||||
adjust = 0;
|
||||
}
|
||||
|
||||
if (adjust >= 0 || -adjust < delay) {
|
||||
if (adjust >= 0) {
|
||||
delay += adjust;
|
||||
} else if ((uint64_t)-adjust < delay) {
|
||||
delay -= (uint64_t)-adjust;
|
||||
} else {
|
||||
delay = 0U; /* delay should never be a negative value */
|
||||
delay = 0U; /* delay should never be negative */
|
||||
}
|
||||
|
||||
last_loop_time = loop_time;
|
||||
|
||||
secs = k_ticks_to_ms_ceil32(loop_time) / 1000U;
|
||||
usecs = k_ticks_to_us_ceil32(loop_time) - secs * USEC_PER_SEC;
|
||||
|
||||
/* Fill the packet header */
|
||||
datagram = (struct zperf_udp_datagram *)sample_packet;
|
||||
|
||||
datagram->id = htonl(nb_packets);
|
||||
datagram->tv_sec = htonl(HW_CYCLES_TO_SEC(loop_time));
|
||||
datagram->tv_usec =
|
||||
htonl(HW_CYCLES_TO_USEC(loop_time) % USEC_PER_SEC);
|
||||
datagram->tv_sec = htonl(secs);
|
||||
datagram->tv_usec = htonl(usecs);
|
||||
|
||||
hdr = (struct zperf_client_hdr_v1 *)(sample_packet +
|
||||
sizeof(*datagram));
|
||||
|
@ -251,25 +269,32 @@ void zperf_udp_upload(const struct shell *shell,
|
|||
}
|
||||
|
||||
/* Print log every seconds */
|
||||
if (time_delta(last_print_time, loop_time) > print_interval) {
|
||||
print_info = print_interval - k_uptime_ticks();
|
||||
if (print_info <= 0) {
|
||||
shell_fprintf(shell, SHELL_WARNING,
|
||||
"nb_packets=%u\tdelay=%u\tadjust=%d\n",
|
||||
nb_packets, delay, adjust);
|
||||
last_print_time = loop_time;
|
||||
nb_packets, (unsigned int)delay,
|
||||
(int)adjust);
|
||||
print_interval = z_timeout_end_calc(K_SECONDS(1));
|
||||
}
|
||||
|
||||
remaining = duration - k_uptime_ticks();
|
||||
|
||||
/* Wait */
|
||||
#if defined(CONFIG_ARCH_POSIX)
|
||||
k_busy_wait(USEC_PER_MSEC);
|
||||
#else
|
||||
while (time_delta(loop_time, k_cycle_get_32()) < delay) {
|
||||
k_yield();
|
||||
if (delay != 0) {
|
||||
if (k_us_to_ticks_floor64(delay) > remaining) {
|
||||
delay = k_ticks_to_us_ceil64(remaining);
|
||||
}
|
||||
|
||||
k_sleep(K_USEC(delay));
|
||||
}
|
||||
#endif
|
||||
} while (remaining > 0);
|
||||
|
||||
} while (time_delta(start_time, last_loop_time) < duration);
|
||||
|
||||
end_time = k_cycle_get_32();
|
||||
end_time = k_uptime_ticks();
|
||||
|
||||
zperf_upload_fin(shell, context, nb_packets, end_time, packet_size,
|
||||
results);
|
||||
|
@ -277,6 +302,6 @@ void zperf_udp_upload(const struct shell *shell,
|
|||
/* Add result coming from the client */
|
||||
results->nb_packets_sent = nb_packets;
|
||||
results->client_time_in_us =
|
||||
HW_CYCLES_TO_USEC(time_delta(start_time, end_time));
|
||||
k_ticks_to_us_ceil32(end_time - start_time);
|
||||
results->packet_size = packet_size;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue