@@ -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+
158229static 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