FreeBSD Bugzilla – Attachment 190162 Details for
Bug 225535
Delays in TCP connection over Gigabit Ethernet connections; Regression from 6.3-RELEASE
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
cycle_clock.c
cycle_clock.c (text/plain), 9.64 KB, created by
Aleksander Derevianko
on 2018-01-29 14:36:08 UTC
(
hide
)
Description:
cycle_clock.c
Filename:
MIME Type:
Creator:
Aleksander Derevianko
Created:
2018-01-29 14:36:08 UTC
Size:
9.64 KB
patch
obsolete
> > >#include <stdio.h> >#include <stdlib.h> >#include <errno.h> >#include <unistd.h> > >#include <sys/socket.h> >#include <sys/types.h> >#include <netinet/in.h> >#include <arpa/inet.h> >#include <netinet/tcp.h> > > >#include <string.h> > >#include <time.h> >#include <sys/time.h> >#include <stdint.h> > > >#include <sched.h> >#include <time.h> >#include <sys/mman.h> > > >#ifndef MAX ># define MAX(a,b) ((a)>(b) ? (a):(b)) >#endif > >#define TRY(expr,errval) if ((expr)==(errval)) \ > { \ > char tryString[1024]; \ > sprintf(tryString,"%s:%i",__FILE__,__LINE__); \ > perror(tryString); \ > } > > >static void setSchedPolicyAndPriority( int policy, int priority ) >{ > struct sched_param schedParam; > > TRY(sched_getparam(0, &schedParam),-1); > schedParam.sched_priority = > (priority == -1 ? sched_get_priority_min(policy): priority); > > TRY(sched_setscheduler(0,policy,&schedParam),-1); >}; > > > >void save_64(char * buffer, uint64_t value) >{ >uint32_t up = value>>32; >uint32_t down = value; >up=htonl(up); >down=htonl(down); >memcpy(buffer,&up,4); >memcpy(buffer+4,&down,4); >}; > >void load_64(char * buffer, uint64_t * value) >{ >uint32_t up; >uint32_t down; >memcpy(&up,buffer,4); >memcpy(&down,buffer+4,4); >up=ntohl(up); >down=ntohl(down); >*value=up; >*value<<=32; >*value|=down; >}; > >void hexdump(const char * str, char * buff, int len) >{ >int i; >printf("%s",str); >for(i=0; i < len; i++) > { > printf("%02X " , (unsigned int)(unsigned char)(buff[i])); > }; >printf("\n"); >fflush(stdout); >}; > >void save_time(char * buffer,struct timespec * tm) >{ >uint64_t seconds=(uint64_t)tm->tv_sec; >uint64_t nanoseconds=(uint64_t)tm->tv_nsec; >save_64(buffer,seconds); >save_64(buffer+8,nanoseconds); >//hexdump("save_time :",buffer,16); >}; > >void load_time(char * buffer,struct timespec * tm) >{ >uint64_t seconds; >uint64_t nanoseconds; >//hexdump("load_time :",buffer,16); >load_64(buffer,&seconds); >load_64(buffer+8,&nanoseconds); >tm->tv_sec=seconds; >tm->tv_nsec=nanoseconds; >}; > >// return to - from in milliseconds (1/1000 sec) >int32_t time_diff(struct timespec * start, struct timespec * stop) // in milleseconds >{ > struct timespec result; > > if ((stop->tv_nsec - start->tv_nsec) < 0) { > result.tv_sec = stop->tv_sec - start->tv_sec - 1; > result.tv_nsec = stop->tv_nsec - start->tv_nsec + 1000000000; > } else { > result.tv_sec = stop->tv_sec - start->tv_sec; > result.tv_nsec = stop->tv_nsec - start->tv_nsec; > }; > > return ((result.tv_sec*1000) + (result.tv_nsec/1000000)); >}; > >int64_t evaluate_something_difficult(int max) >{ > // just nothing interesting; > int64_t a1=1; > int64_t a2=2; > int i=0; > int64_t res=0; > for(i=0; i < max; i++) > { > res = a1 + a2; > a1=a2; > a2=res; > }; > return res; >}; > >int main(int argc, char * argv[]) >{ >struct sockaddr_in s_addr; >int is_listen=1; >if (argc < 4) > { > printf("Usage: %s ip_address port connect|listen\n",argv[0]); > return 1; > }; > >setSchedPolicyAndPriority( SCHED_RR, 3); > >s_addr.sin_family = AF_INET; >s_addr.sin_port=htons(atoi(argv[2])); >if ( ! inet_aton(argv[1], & s_addr.sin_addr)) > { > printf("Failed to convert '%s' to proper IPv4 address!\n",argv[1]); > return 2; > }; > >if (strcmp(argv[3],"connect") == 0) is_listen=0; > >if (is_listen) > printf("Listen on port %d, accepting connections from %s\n", > ntohs(s_addr.sin_port), inet_ntoa( s_addr.sin_addr )); >else > printf("Attempting to connect to %s:%d\n", > inet_ntoa( s_addr.sin_addr ), ntohs(s_addr.sin_port)); > >// create socket >int sock = socket(AF_INET, SOCK_STREAM,0); >if (sock < 0) { > printf("Failed to create tcp socket: %s\n",strerror(errno)); > return 3; > }; > >// listen/connect >if (is_listen) > { > struct sockaddr_in listen_addr; > struct sockaddr_in conn_addr; > socklen_t a_len=sizeof(conn_addr); > int val=1; > > listen_addr = s_addr; > listen_addr.sin_addr.s_addr = htonl(INADDR_ANY); > > if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&val,sizeof(val)) != 0) > { > perror("SO_REUSEADDR setsockopt"); > }; > > if (bind(sock, (struct sockaddr *)&listen_addr, sizeof(listen_addr)) < 0) > { > printf("Failed to bind to port %d: %s\n", > ntohs(s_addr.sin_port), strerror(errno)); > return 4; > }; > listen(sock,1); > > int conn_sock = accept(sock,(struct sockaddr *)&conn_addr,&a_len); > if (conn_sock < 0) { > printf("accept return %d: %s\n",conn_sock,strerror(errno)); > return(5); > }; > > printf("Accepted connection from %s:%d\n", > inet_ntoa( conn_addr.sin_addr ), ntohs(conn_addr.sin_port) ); > if (s_addr.sin_addr.s_addr != conn_addr.sin_addr.s_addr) > { > printf("Connection rejected, we do not expect it from this IP\n"); > return 6; > }; > > close(sock); > sock=conn_sock; > errno=0; > } >else > { // connecting > s_addr.sin_family = AF_INET; > while(1) > { > if (connect(sock,(struct sockaddr *)&s_addr, sizeof(s_addr) ) < 0) > { > printf("Failed to connect to %s:%d : %s\n", > inet_ntoa( s_addr.sin_addr ), ntohs(s_addr.sin_port), strerror(errno)); > sleep(1); > } > else > { > printf("Connected successfully.\n"); > break; > }; > }; > }; > >#define BUFF_SIZE 40960 >#define CYCLE_TIME 300 // milliseconds > >int i=0; >char send_buffer[BUFF_SIZE]; >char recv_buffer[BUFF_SIZE]; >memset(send_buffer,is_listen,BUFF_SIZE); > >struct timespec partner_last_cycle; >struct timespec own_last_cycle; > >int yes = 1; >if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,(char *) &yes, sizeof(yes)) != 0) > { > printf("Failed to set TCP_NODELAY=1 in setsockopt: %s\n", strerror(errno)); > return 20; > }; > >uint32_t filter = 0; > >uint32_t nTooLongSleep=0; // FreeBSD nanosleep() usually return after too long time > >// main cycle >for(i=0; 1; i++) > { > int len; > > struct timespec pre_start_cycle_moment; > struct timespec sync_send_fnish_moment; > struct timespec start_cycle_moment; > struct timespec partner_start_cycle_moment; > struct timespec send_finish_moment; > struct timespec recv_finish_moment; > struct timespec eval_finish_moment; > int eval_time; > > clock_gettime( CLOCK_MONOTONIC, &pre_start_cycle_moment ); > // sync cycles. > uint32_t data=htonl(i); > if (send(sock,&data,sizeof(data),0) != sizeof(data)) > { > printf("Failed to send cycle sync: %s\n",strerror(errno)); > return 18; > }; > > clock_gettime( CLOCK_MONOTONIC, &sync_send_fnish_moment); > > if (recv(sock,&data,sizeof(data),0) != sizeof(data)) > { > printf("Failed to recv cycle sync: %s\n",strerror(errno)); > return 19; > }; > > if (ntohl(data) != i) > { > printf("Wrong cycle number received, expecting %d received %d\n",i, ntohl(data)); > return 19; > }; > > clock_gettime( CLOCK_MONOTONIC, &start_cycle_moment ); > > uint32_t sync_time = time_diff( &pre_start_cycle_moment, &start_cycle_moment ); > > save_time(send_buffer, &start_cycle_moment ); > > uint32_t tdt = htonl(sync_time); > memcpy(send_buffer+128, &tdt, sizeof(tdt)); > > len=send(sock,send_buffer,BUFF_SIZE,0); > if (len != BUFF_SIZE) { > printf("Failed to send data: %s\n",strerror(errno)); > return 8; > }; > > clock_gettime( CLOCK_MONOTONIC, &send_finish_moment ); > > // send > // recv - sync cycles. > len=0; > while(len < BUFF_SIZE) > { > int slen=recv(sock,recv_buffer+len,BUFF_SIZE-len,0); > if (slen <= 0) { > printf("Failed to recv data (received %d from %d): %s\n", > len, BUFF_SIZE, strerror(errno)); > return 9; > }; > len+=slen; > }; > > load_time(recv_buffer, &partner_start_cycle_moment); > memcpy(&tdt,recv_buffer+128, sizeof(tdt)); > uint32_t his_sync_time = ntohl(tdt); > > clock_gettime( CLOCK_MONOTONIC, &recv_finish_moment ); > > // perform some evaluations > > int64_t eval=evaluate_something_difficult(10*1000*1000 + i%1000); > > > clock_gettime( CLOCK_MONOTONIC, &eval_finish_moment); > > eval_time = time_diff( &start_cycle_moment, &eval_finish_moment); > > // evaluate how long time to sleep > struct timespec req_time; > req_time.tv_sec=0; > req_time.tv_nsec=(CYCLE_TIME - eval_time - nTooLongSleep ) * 1000000; // 0.6 sec if wait_time==0 > > nanosleep(&req_time,NULL); > > struct timespec real_sleep; > clock_gettime( CLOCK_MONOTONIC, &real_sleep); > int sleep_time; > sleep_time = time_diff(&eval_finish_moment, &real_sleep); > > nTooLongSleep += sleep_time - (CYCLE_TIME-eval_time); > > // printf("call nanosleep for %d, real sleep for %d, nTooLongSleep=%d\n", > // (int)(req_time.tv_nsec/1000000), sleep_time, nTooLongSleep); > > > printf("times %d: send_sync %d recv_sync %d send_data %d recv_data %d eval %d sleep %d\n", i, > time_diff(&pre_start_cycle_moment, &sync_send_fnish_moment), > time_diff(&sync_send_fnish_moment, &start_cycle_moment), > time_diff(&start_cycle_moment, &send_finish_moment), > time_diff(&send_finish_moment, &recv_finish_moment), > time_diff(&recv_finish_moment, &eval_finish_moment), > time_diff(&eval_finish_moment, &real_sleep)); > > printf("cycle %d: DIFF=%d my_cycle=%d his_cycle=%d eval_time=%d sync_time=%d his_sync_time=%d filter=%d\n",i, > time_diff(&own_last_cycle, &start_cycle_moment) - time_diff(&partner_last_cycle, &partner_start_cycle_moment), > time_diff(&own_last_cycle, &start_cycle_moment), > time_diff(&partner_last_cycle, &partner_start_cycle_moment), > eval_time, sync_time, his_sync_time, filter); > > > fflush(stdout); > > own_last_cycle=start_cycle_moment; > partner_last_cycle=partner_start_cycle_moment; > > }; > >// exit >close(sock); >return 0; >};
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 225535
: 190162 |
190196
|
190201