Introduction to Iperf3.1.3

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_procB

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!

Guess you like

Origin blog.csdn.net/edw200/article/details/72424306