Skip to content

Commit 478fad8

Browse files
fengming-yekartben
authored andcommitted
net: zperf: udp upload clock compensate
When clock accuracy is 1KHz or lower, udp_upload rate has much lower accuracy. eg. 20M rate has 60M actual throughput. It's because any packet_duration less than 1000us will be treated as 1 tick. In this case rate cannot control throughput. Add clock compensate when time clock is lower than 1KHz to fix it. In every 10 ticks or longer delta time, calculate packets sent actual number and expected number, and then compensate ticks. And add compensate ticks to delay ticks count. If we cannot compensate a minus ticks as delay cannot be negative, add it to next compensate period. If compensate sum ticks is lower than -1000, it means current rate is higher than low level capability. So no need to compensate in remaining traffic. Signed-off-by: Fengming Ye <frank.ye@nxp.com>
1 parent 58edd1b commit 478fad8

File tree

1 file changed

+92
-3
lines changed

1 file changed

+92
-3
lines changed

subsys/net/lib/zperf/zperf_udp_uploader.c

Lines changed: 92 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,77 @@ static inline int zperf_upload_fin(int sock,
155155
return 0;
156156
}
157157

158+
#define USECS_PER_TICK (Z_HZ_us / Z_HZ_ticks)
159+
#if (USECS_PER_TICK >= 1000)
160+
#define ZPERF_UDP_UPLOAD_CLOCK_COMPENSATE
161+
#endif
162+
163+
#ifdef ZPERF_UDP_UPLOAD_CLOCK_COMPENSATE
164+
struct compensate_ctx {
165+
int period;
166+
int64_t period_start;
167+
int packet_duration_us;
168+
int actual_pkts;
169+
int compensate;
170+
};
171+
172+
/**
173+
* Add compensate to packet delay when time clock accuracy is lower than 1kHz.
174+
* After given period, compare actual sent packets with expected sent packets,
175+
* and get summary compensate ticks.
176+
* Then try to compensate in this loop.
177+
* If delay is not enough as it cannot be less than 0, pile up compensate ticks.
178+
*/
179+
static int cal_compensate_delay(struct compensate_ctx *ctx, int64_t loop_time, int delay)
180+
{
181+
int64_t delta_time;
182+
int expected_pkts;
183+
int compensate_pkts;
184+
int compensate_ticks;
185+
int compensate_delay = delay;
186+
187+
if (ctx->period == 0) {
188+
return delay;
189+
}
190+
191+
if (ctx->period_start == -1) {
192+
ctx->period_start = loop_time;
193+
ctx->actual_pkts = 0;
194+
}
195+
196+
ctx->actual_pkts++;
197+
delta_time = loop_time - ctx->period_start;
198+
199+
if (delta_time < ctx->period) {
200+
return delay;
201+
}
202+
203+
/* calculate compensate ticks and maintain it during whole traffic */
204+
expected_pkts = delta_time * USECS_PER_TICK / ctx->packet_duration_us;
205+
compensate_pkts = ctx->actual_pkts - expected_pkts;
206+
compensate_ticks = compensate_pkts * ctx->packet_duration_us / USECS_PER_TICK;
207+
ctx->compensate += compensate_ticks;
208+
209+
if (ctx->compensate >= 0 || (ctx->compensate + delay) > 0) {
210+
compensate_delay += ctx->compensate;
211+
ctx->compensate = 0;
212+
} else {
213+
compensate_delay = 0;
214+
ctx->compensate += delay;
215+
}
216+
217+
/* restart statistic period */
218+
ctx->period_start = -1;
219+
220+
/* rate is higher than capability, no need to compensate */
221+
if (ctx->compensate < -1000) {
222+
ctx->period = 0;
223+
}
224+
225+
return compensate_delay;
226+
}
227+
#endif
228+
158229
static int udp_upload(int sock, int port,
159230
const struct zperf_upload_params *param,
160231
struct zperf_results *results)
@@ -175,6 +246,10 @@ static int udp_upload(int sock, int port,
175246
uint32_t print_period;
176247
bool is_mcast_pkt = false;
177248
int ret;
249+
int compensate_delay;
250+
#ifdef ZPERF_UDP_UPLOAD_CLOCK_COMPENSATE
251+
struct compensate_ctx ctx = {0};
252+
#endif
178253

179254
if (packet_size > PACKET_SIZE_MAX) {
180255
NET_WARN("Packet size too large! max size: %u", PACKET_SIZE_MAX);
@@ -196,6 +271,13 @@ static int udp_upload(int sock, int port,
196271
/* Default data payload */
197272
(void)memset(sample_packet, 'z', sizeof(sample_packet));
198273

274+
#ifdef ZPERF_UDP_UPLOAD_CLOCK_COMPENSATE
275+
/* compensate period, by default 10 ticks */
276+
ctx.period = 10;
277+
ctx.period_start = -1;
278+
ctx.packet_duration_us = packet_duration_us;
279+
#endif
280+
199281
do {
200282
struct zperf_udp_datagram *datagram;
201283
struct zperf_client_hdr_v1 *hdr;
@@ -222,6 +304,13 @@ static int udp_upload(int sock, int port,
222304
delay = 0U; /* delay should never be negative */
223305
}
224306

307+
/* add clock compensate to packet delay when clock accuracy is lower than 1KHz */
308+
#ifdef ZPERF_UDP_UPLOAD_CLOCK_COMPENSATE
309+
compensate_delay = cal_compensate_delay(&ctx, loop_time, (int)delay);
310+
#else
311+
compensate_delay = delay;
312+
#endif
313+
225314
last_loop_time = loop_time;
226315

227316
usecs64 = param->unix_offset_us + k_ticks_to_us_floor64(loop_time - start_time);
@@ -268,7 +357,7 @@ static int udp_upload(int sock, int port,
268357
if (IS_ENABLED(CONFIG_NET_ZPERF_LOG_LEVEL_DBG)) {
269358
if (print_time >= loop_time) {
270359
NET_DBG("nb_packets=%u\tdelay=%u\tadjust=%d",
271-
nb_packets, (unsigned int)delay,
360+
nb_packets, (unsigned int)compensate_delay,
272361
(int)adjust);
273362
print_time += print_period;
274363
}
@@ -278,8 +367,8 @@ static int udp_upload(int sock, int port,
278367
#if defined(CONFIG_ARCH_POSIX)
279368
k_busy_wait(USEC_PER_MSEC);
280369
#else
281-
if (delay != 0) {
282-
k_sleep(K_TICKS(delay));
370+
if (compensate_delay > 0) {
371+
k_sleep(K_TICKS(compensate_delay));
283372
}
284373
#endif
285374
} while (last_loop_time < end_time);

0 commit comments

Comments
 (0)