Compared with the introduction of Iperf3.1.3 transplantation published last time, this chapter mainly introduces Iperf3.1.3 tools and optimizes individual functions, including pairing proofreading and broadband test optimization.
1. Software process:
2. Time management module
2.1 , design a time linked list
The linked list uses time as the sorting position of the linked list items, and the greater the time, the lower the ranking;
Code:
This function implements time addition calculation
usecs is the time coefficient, generally the value is 0 or 1000000L*n , such as client "-t"=test->duration=5 , n=5 ;
Then t->tv_sec is the current coefficient plus 5s ;
static void
add_usecs( struct timeval* t, int64_t usecs )
{
t->tv_sec += usecs / 1000000L;
t->tv_usec += usecs % 1000000L;
if ( t->tv_usec >= 1000000L ) {
t->tv_sec += t->tv_usec / 1000000L;
t->tv_usec %= 1000000L;
}
}
Ensure that the time of the linked list is increasing from left to right, and the time of the head of the linked list is the smallest.
static void
list_add( Timer* t )
{
Timer* t2;
Timer* t2prev;
if ( timers == NULL ) {
/* The list is empty. */
timers = t;
t->prev = t->next = NULL;
} else {
//当前时间项小于链表头时间项,则当前项作为链表头,大的链表项向后移一位。
if ( t->time.tv_sec < timers->time.tv_sec ||
( t->time.tv_sec == timers->time.tv_sec &&
t->time.tv_usec < timers->time.tv_usec ) ) {
/* The new timer goes at the head of the list. */
t->prev = NULL;
t->next = timers;
timers->prev = t;
timers = t;
} else {
//当前时间项大于链表头时间项,则当前项添加在链表头后移一位。
/* Walk the list to find the insertion point. */
for ( t2prev = timers, t2 = timers->next; t2 != NULL;
t2prev = t2, t2 = t2->next ) {
if ( t->time.tv_sec < t2->time.tv_sec ||
( t->time.tv_sec == t2->time.tv_sec &&
t->time.tv_usec < t2->time.tv_usec ) ) {
/* Found it. */
t2prev->next = t;
t->prev = t2prev;
t->next = t2;
t2->prev = t;
return;
}
}
/* Oops, got to the end of the list. Add to tail. */
t2prev->next = t;
t->prev = t2prev;
t->next = NULL;
}
}
}
2.2 , time management registration and execution function
void
tmr_run( struct timeval* nowP )
{
struct timeval now;
Timer* t;
Timer* next;
getnow( nowP, &now );
for ( t = timers; t != NULL; t = next ) {
next = t->next;
/* Since the list is sorted, as soon as we find a timer
** that isn't ready yet, we are done.
*/
//链表时间大于当前时间则退出,防止回调函数只执行一次;
if ( t->time.tv_sec > now.tv_sec ||
( t->time.tv_sec == now.tv_sec &&
t->time.tv_usec > now.tv_usec ) )
break;
(t->timer_proc)( t->client_data, &now );//回调函数
if ( t->periodic ) {
/* Reschedule. */
add_usecs( &t->time, t->usecs );//时间累加
list_resort( t );//添加到链表中,将现执行链表头去掉,添加累加时间后的链表;
} else
tmr_cancel( t );//直接删除链表头
}
}
//timer_proc为回调函数
//client_data回调函数传参
Timer*
tmr_create(
struct timeval* nowP, TimerProc* timer_proc, TimerClientData client_data,
int64_t usecs, int periodic )
{
struct timeval now;
Timer* t;
getnow( nowP, &now );
if ( free_timers != NULL ) {
t = free_timers;
free_timers = t->next;
} else {
t = (Timer*) malloc( sizeof(Timer) );
if ( t == NULL )
return NULL;
}
t->timer_proc = timer_proc;
t->client_data = client_data;
t->usecs = usecs;
t->periodic = periodic;
t->time = now;
add_usecs( &t->time, usecs );
/* Add the new timer to the active list. */
list_add( t );
return t;
}
2.3 , implementation example
SEC_TO_US = 1000000L;
tmr_create(&now, test_timer_proc, cd, 5 * SEC_TO_US, 0);
tmr_create(&now, client_stats_timer_proc, cd, 1 * SEC_TO_US, 1);
tmr_create(&now, client_reporter_timer_proc, cd, 1 * SEC_TO_US, 1);
test_timer_proc flag A;
client_stats_timer_proc为B ;
client_reporter_timer_proc is C ;
Set linked list by time (seconds) 1 2 3 4 5
Execute the first tmr_run B|C B|C A
Execute until the time of the third linked list item is greater than the current time, then launch, the following are similar;
Execute the second tmr_run B|C B|C A
Execute the third tmr_run B|C B|C A
Execute the fourth tmr_run B|C A|B|C
The entire process is completed when the fourth execution reaches A ;
3. Add MD5 checksum
During the iperf3 protocol verification process, the client sends a string of 36 characters to the server, and the server verifies the string;
Client 36 generates rules for strings:
1. The first sixteen digits are the machine system time ( 10 digits second + 6 digits microseconds), and the acquisition function is gettimeofday();
2. The last 20 characters are the generation rules, calculate the 32 - digit md5 check value from the above 16 -digit string + "hlzt2015*01234567890qwertyuiopasdfghjklzxcvbnm" , and intercept the first 20 strings;
3. Combine character strings 1 and 2 into 32 character strings;
Example: 149377389618076447a681a68b92b034dc4e3a2577801e57
0~10 digits from left to right are machine system time ( seconds ) 1493773896 ;
11~16 digits, a total of 6 digits are machine system time ( microseconds ) 180764 ;
17~48 are a total of 32 bits for the MD5 check value 47a681a68b92b034dc4e3a2577801e57 ;
The final string sent to the server is: 149377389618076447a681a68b92b034dc4e
Server verification process:
1. First judge the time value of the first 16 digits, and the tolerance time is half an hour;
2. Finally judge the 20 -digit MD5 check value
Example: Get the string: 149377389618076447a681a68b92b034dc4e
Get the time ( seconds ) 1493773896 , compared with the current time, it is not more than 30 minutes;
Get the 20 -digit MD5 check value: 47a681a68b92b034dc4e , compare it with your own check MD5 ;
4. iperf test bandwidth rules
The Iperf test bandwidth is single-channel, that is, each execution can only test a single downstream or upstream; Iperf sets a 128K byte packet, and tests the upstream by how many bytes ( byte/sec ) can be sent / received in one second \ downlink bandwidth;
Here we have designed a mechanism. In the test interval of 5~20 , we sort the data packets per second from small to large, remove the value of 0 , take the middle value of the effective value, multiply the middle value by 4 as the high-level benchmark value, and remove the value greater than For the data of the high-order reference value, divide the middle value by 4 as the low-order reference value, and remove the data smaller than the low-order reference value. Then divide the effective value by the response time to get the bandwidth value;
Here I have optimized the Iperf3.1.3 tool last time, which can be found in my blog!