aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/akcom-udpecho.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/akcom-udpecho.c')
-rw-r--r--src/akcom-udpecho.c207
1 files changed, 134 insertions, 73 deletions
diff --git a/src/akcom-udpecho.c b/src/akcom-udpecho.c
index f044f13..085f4ca 100644
--- a/src/akcom-udpecho.c
+++ b/src/akcom-udpecho.c
@@ -103,13 +103,24 @@
103#define PACKAGE_VERSION "0.0" 103#define PACKAGE_VERSION "0.0"
104#endif 104#endif
105 105
106#define my_sec2msec( sec ) ( sec * 1000 )
106#define my_sec2usec( sec ) ( sec * 1000000 ) 107#define my_sec2usec( sec ) ( sec * 1000000 )
107#define my_sec2nsec( sec ) ( sec * 1000000000 ) 108#define my_sec2nsec( sec ) ( sec * 1000000000 )
108#define my_usec2sec( usec ) ( usec / 1000000 ) 109
110#define my_msec2sec( msec ) ( msec / 1000 )
111#define my_msec2usec( msec ) ( msec * 1000 )
112#define my_msec2nsec( msec ) ( msec * 1000000 )
113
114#define my_usec2sec( usec ) ( usec / 1000000 )
115#define my_usec2msec( usec ) ( usec / 1000 )
109#define my_usec2nsec( usec ) ( usec * 1000 ) 116#define my_usec2nsec( usec ) ( usec * 1000 )
110#define my_nsec2sec( nsec ) ( nsec / 1000000000 ) 117
118#define my_nsec2sec( nsec ) ( nsec / 1000000000 )
119#define my_nsec2msec( nsec ) ( nsec / 1000000 )
111#define my_nsec2usec( nsec ) ( nsec / 1000 ) 120#define my_nsec2usec( nsec ) ( nsec / 1000 )
112 121
122#define my_usec2msec_tenths( usec ) ((usec%1000)/100)
123
113 124
114///////////////// 125/////////////////
115// // 126// //
@@ -135,6 +146,7 @@ typedef struct udp_echo_plus
135 uint32_t reply_time; 146 uint32_t reply_time;
136 uint32_t failures; 147 uint32_t failures;
137 uint32_t iteration; 148 uint32_t iteration;
149 struct timespec send_time;
138 uint8_t bytes[]; 150 uint8_t bytes[];
139} echoplus_t; 151} echoplus_t;
140 152
@@ -195,6 +207,12 @@ static void
195 int signum ); 207 int signum );
196 208
197 209
210extern uint64_t
211my_timespec_delta(
212 struct timespec * ts1,
213 struct timespec * ts2,
214 struct timespec * delta );
215
198 216
199// display program usage 217// display program usage
200static void 218static void
@@ -419,10 +437,10 @@ my_loop(
419 echoplus_t * sndbuff ) 437 echoplus_t * sndbuff )
420{ 438{
421 int rc; 439 int rc;
422 uint64_t epoch; 440 uint64_t pckt_time;
423 uint64_t epoch_adj; 441 uint64_t pckt_time_adj;
424 uint64_t epoch_max; 442 uint64_t epoch_usec;
425 uint64_t delay; 443 uint64_t pckt_delay;
426 uint32_t stats_sent; 444 uint32_t stats_sent;
427 uint32_t stats_rcvd; 445 uint32_t stats_rcvd;
428 uint64_t stats_max; 446 uint64_t stats_max;
@@ -433,6 +451,7 @@ my_loop(
433 uint64_t stats_avg_adj; 451 uint64_t stats_avg_adj;
434 ssize_t size; 452 ssize_t size;
435 struct pollfd fds[2]; 453 struct pollfd fds[2];
454 struct timespec ts_sent;
436 struct timespec start; 455 struct timespec start;
437 struct timespec now; 456 struct timespec now;
438 457
@@ -454,90 +473,99 @@ my_loop(
454 stats_avg = 0; 473 stats_avg = 0;
455 stats_avg_adj = 0; 474 stats_avg_adj = 0;
456 475
457 // start clock 476 // initialize timers
458 clock_gettime(CLOCK_MONOTONIC_RAW, &start); 477 clock_gettime(CLOCK_MONOTONIC_RAW, &start);
459 start.tv_sec -= cnf_interval; 478 start.tv_sec -= cnf_interval;
460 epoch = 0; 479 ts_sent.tv_sec = start.tv_sec;
480 ts_sent.tv_nsec = start.tv_nsec;
461 481
462 // master loop 482 // master loop
463 while (!(should_stop)) 483 while (!(should_stop))
464 { 484 {
465 // calculate loop epoch 485 // calculate loop epoch
466 clock_gettime(CLOCK_MONOTONIC_RAW, &now); 486 clock_gettime(CLOCK_MONOTONIC_RAW, &now);
467 epoch = ((uint64_t)now.tv_sec * 10000) + ((uint64_t)now.tv_nsec / 100000); 487 epoch_usec = my_sec2usec((uint64_t)now.tv_sec) + my_nsec2usec((uint64_t)now.tv_nsec);
468 epoch -= ((uint64_t)start.tv_sec * 10000) + ((uint64_t)start.tv_nsec / 100000); 488 epoch_usec -= my_sec2usec((uint64_t)start.tv_sec) + my_nsec2usec((uint64_t)start.tv_nsec);
469 489
470 // trigger stop 490 // trigger stop
471 if ( ((cnf_count)) && (stats_sent >= cnf_count) ) 491 if ( ((cnf_count)) && (stats_sent >= cnf_count) )
472 { 492 {
473 epoch_max = cnf_count * (uint64_t)cnf_interval * 10000; 493 if (stats_rcvd == stats_sent)
474 epoch_max += (uint64_t)cnf_timeout * 10000; 494 {
475 if (( epoch >= epoch_max) || (stats_rcvd >= stats_sent))
476 should_stop = 1; 495 should_stop = 1;
496 continue;
497 };
498 if (my_timespec_delta(&now, &ts_sent, NULL) > my_sec2usec((uint64_t)cnf_timeout))
499 {
500 should_stop = 1;
501 continue;
502 };
477 }; 503 };
478 504
479 // send UDP echo request 505 // send UDP echo request
480 if ((stats_sent < (epoch/(10000*cnf_interval))) && ((stats_sent < cnf_count) || (!(cnf_count))) ) 506 if ((stats_sent < (epoch_usec/my_sec2usec(cnf_interval))) && ((stats_sent < cnf_count) || (!(cnf_count))) )
481 { 507 {
482 stats_sent++; 508 stats_sent++;
483 sndbuff->req_sn = htonl((uint32_t)stats_sent); 509 sndbuff->req_sn = htonl((uint32_t)stats_sent);
510 sndbuff->send_time.tv_sec = now.tv_sec;
511 sndbuff->send_time.tv_nsec = now.tv_nsec;
512 ts_sent.tv_sec = now.tv_sec;
513 ts_sent.tv_nsec = now.tv_nsec;
484 send(s, sndbuff, cnf_packetsize, 0); 514 send(s, sndbuff, cnf_packetsize, 0);
485 }; 515 };
486 516
487 // receive UDP echo response 517 // receive UDP echo response
488 if ((rc = poll(fds, 1, 0)) > 0) 518 if ((rc = poll(fds, 1, 0)) <= 0)
489 { 519 {
490 if ((size = recv(s, rcvbuff, cnf_packetsize, 0)) == (ssize_t)cnf_packetsize) 520 usleep(50);
491 { 521 continue;
492 rcvbuff->req_sn = ntohl(rcvbuff->req_sn); 522 };
493 rcvbuff->res_sn = ntohl(rcvbuff->res_sn); 523
494 rcvbuff->recv_time = ntohl(rcvbuff->recv_time); 524 // reads packet
495 rcvbuff->reply_time = ntohl(rcvbuff->reply_time); 525 if ((size = recv(s, rcvbuff, cnf_packetsize, 0)) != (ssize_t)cnf_packetsize)
496 rcvbuff->failures = ntohl(rcvbuff->failures); 526 continue;
497 rcvbuff->iteration = ntohl(1); 527 rcvbuff->req_sn = ntohl(rcvbuff->req_sn);
498 if ((cnf_debug)) 528 rcvbuff->res_sn = ntohl(rcvbuff->res_sn);
499 { 529 rcvbuff->recv_time = ntohl(rcvbuff->recv_time);
500 printf(" packet: GenSN/REspSN: %08" PRIx32 " %08" PRIx32 "\n", rcvbuff->req_sn, rcvbuff->res_sn); 530 rcvbuff->reply_time = ntohl(rcvbuff->reply_time);
501 printf(" Recv/Reply Time: %08" PRIx32 " %08" PRIx32 "\n", rcvbuff->recv_time, rcvbuff->reply_time); 531 rcvbuff->failures = ntohl(rcvbuff->failures);
502 printf(" Failures: %08" PRIx32 "\n", rcvbuff->failures); 532 rcvbuff->iteration = ntohl(1);
503 printf(" Iteration: %08" PRIx32 "\n", rcvbuff->iteration); 533 if ((cnf_debug))
504 }; 534 {
505 stats_rcvd++; 535 printf(" packet: GenSN/REspSN: %08" PRIx32 " %08" PRIx32 "\n", rcvbuff->req_sn, rcvbuff->res_sn);
506 delay = rcvbuff->reply_time - rcvbuff->recv_time; 536 printf(" Recv/Reply Time: %08" PRIx32 " %08" PRIx32 "\n", rcvbuff->recv_time, rcvbuff->reply_time);
507 delay /= 100000000; 537 printf(" Failures: %08" PRIx32 "\n", rcvbuff->failures);
508 epoch -= (rcvbuff->req_sn * 10000); 538 printf(" Iteration: %08" PRIx32 "\n", rcvbuff->iteration);
509 epoch_adj = epoch - delay; 539 };
510 stats_avg += epoch; 540 stats_rcvd++;
511 stats_avg_adj += epoch_adj; 541
512 if ( (!(stats_min)) || (epoch < stats_min) ) 542 // performs stats on packet
513 stats_min = epoch; 543 pckt_time = my_timespec_delta(&now, &rcvbuff->send_time, NULL);
514 if ( (!(stats_max)) || (epoch > stats_max) ) 544 pckt_delay = rcvbuff->reply_time - rcvbuff->recv_time;
515 stats_max = epoch; 545 pckt_time_adj = pckt_time - pckt_delay;
516 if ( (!(stats_min_adj)) || (epoch_adj < stats_min_adj) ) 546 stats_avg += pckt_time;
517 stats_min_adj = epoch_adj; 547 stats_avg_adj += pckt_time_adj;
518 if ( (!(stats_max_adj)) || (epoch_adj > stats_max_adj) ) 548 stats_min = ( (!(stats_min)) || (pckt_time < stats_min) ) ? pckt_time : stats_min;
519 stats_max_adj = epoch_adj; 549 stats_max = ( (!(stats_max)) || (pckt_time > stats_max) ) ? pckt_time : stats_max;
520 if ((cnf_echoplus)) 550 stats_min_adj = ( (!(stats_min_adj)) || (pckt_time_adj < stats_min_adj) ) ? pckt_time_adj : stats_min_adj;
521 { 551 stats_max_adj = ( (!(stats_max_adj)) || (pckt_time_adj > stats_max_adj) ) ? pckt_time_adj : stats_max_adj;
522 printf("udpecho_seq=%u failures=%" PRIu32 " time=%" PRIu64 ".%" PRIu64 " ms delay=%" PRIu64 ".%" PRIu64 " ms adj_time=%" PRIu64 ".%" PRIu64 " ms\n", 552
523 rcvbuff->req_sn, 553 // print packet
524 rcvbuff->failures, 554 if (!(cnf_echoplus))
525 epoch/10, epoch%10,
526 delay/10, delay%10,
527 epoch_adj/10, epoch_adj%10
528 );
529 } else
530 {
531 printf("udpecho_seq=%u time=%" PRIu64 ".%" PRIu64 " ms\n",
532 rcvbuff->req_sn,
533 epoch/10, epoch%10
534 );
535 };
536 };
537 } else
538 { 555 {
539 usleep(100); 556 printf("udpecho_seq=%u time=%" PRIu64 ".%" PRIu64 " ms\n",
557 rcvbuff->req_sn,
558 my_usec2msec(pckt_time), ((pckt_time%1000)/100)
559 );
560 continue;
540 }; 561 };
562 printf("udpecho_seq=%u failures=%" PRIu32 " time=%" PRIu64 ".%" PRIu64 " ms delay=%" PRIu64 ".%" PRIu64 " ms adj_time=%" PRIu64 ".%" PRIu64 " ms\n",
563 rcvbuff->req_sn,
564 rcvbuff->failures,
565 my_usec2msec(pckt_time), my_usec2msec_tenths(pckt_time),
566 my_usec2msec(pckt_delay), my_usec2msec_tenths(pckt_delay),
567 my_usec2msec(pckt_time_adj), my_usec2msec_tenths(pckt_time_adj)
568 );
541 }; 569 };
542 570
543 if (!(cnf_silent)) 571 if (!(cnf_silent))
@@ -549,19 +577,19 @@ my_loop(
549 stats_rcvd, 577 stats_rcvd,
550 ((stats_sent - stats_rcvd) * 100) / stats_sent, 578 ((stats_sent - stats_rcvd) * 100) / stats_sent,
551 (((stats_sent - stats_rcvd) * 1000) / stats_sent) % 10 579 (((stats_sent - stats_rcvd) * 1000) / stats_sent) % 10
552 ); 580 );
553 printf("round-trip min/avg/max = %" PRIu64 ".%" PRIu64 "/%" PRIu64 ".%" PRIu64 "/%" PRIu64 ".%" PRIu64 " ms\n", 581 printf("round-trip min/avg/max = %" PRIu64 ".%" PRIu64 "/%" PRIu64 ".%" PRIu64 "/%" PRIu64 ".%" PRIu64 " ms\n",
554 stats_min/10, stats_min%10, 582 my_usec2msec(stats_min), my_usec2msec_tenths(stats_min),
555 (stats_avg/stats_rcvd)/10, (stats_avg/stats_rcvd)%10, 583 my_usec2msec(stats_avg/stats_rcvd), my_usec2msec_tenths(stats_avg/stats_rcvd),
556 stats_max/10, stats_max%10 584 my_usec2msec(stats_max), my_usec2msec_tenths(stats_max)
557 ); 585 );
558 if ((cnf_echoplus)) 586 if ((cnf_echoplus))
559 { 587 {
560 printf("adjusted round-trip min/avg/max = %" PRIu64 ".%" PRIu64 "/%" PRIu64 ".%" PRIu64 "/%" PRIu64 ".%" PRIu64 " ms\n", 588 printf("adjusted round-trip min/avg/max = %" PRIu64 ".%" PRIu64 "/%" PRIu64 ".%" PRIu64 "/%" PRIu64 ".%" PRIu64 " ms\n",
561 stats_min_adj/10, stats_min_adj%10, 589 my_usec2msec(stats_min_adj), my_usec2msec_tenths(stats_min_adj),
562 (stats_avg_adj/stats_rcvd)/10, (stats_avg_adj/stats_rcvd)%10, 590 my_usec2msec(stats_avg_adj/stats_rcvd), my_usec2msec_tenths(stats_avg_adj/stats_rcvd),
563 stats_max_adj/10, stats_max_adj%10 591 my_usec2msec(stats_max_adj), my_usec2msec_tenths(stats_max_adj)
564 ); 592 );
565 }; 593 };
566 }; 594 };
567 595
@@ -651,6 +679,39 @@ my_stop(
651} 679}
652 680
653 681
682// calculates delta between timespecs and returns result as microscond
683uint64_t
684my_timespec_delta(
685 struct timespec * ts1,
686 struct timespec * ts2,
687 struct timespec * delta )
688{
689 struct timespec ts;
690 uint64_t usec;
691
692 assert(ts1 != NULL);
693 assert(ts2 != NULL);
694
695 if (!(delta))
696 delta = &ts;
697
698 delta->tv_sec = ts1->tv_sec;
699 delta->tv_nsec = ts1->tv_nsec;
700 if (delta->tv_nsec < ts2->tv_nsec)
701 {
702 delta->tv_sec--;
703 delta->tv_nsec += my_sec2nsec(1);
704 };
705 delta->tv_sec -= ts2->tv_sec;
706 delta->tv_nsec -= ts2->tv_nsec;
707
708 usec = my_sec2usec(delta->tv_sec);
709 usec += my_nsec2usec(delta->tv_nsec);
710
711 return(usec);
712}
713
714
654// display program usage 715// display program usage
655void 716void
656my_usage( 717my_usage(