]>
git.saurik.com Git - apple/network_cmds.git/blob - frame_delay/frame_delay.c
2 * Copyright (c) 2009-2015 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
30 * Usage for frame_delay
33 * ./frame_delay -m server -t <tcp/udp> -p <port> -n <num_frames> -f <frame_size>
36 * ./frame_delay -m client -t <tcp/udp> -i <srv_ipv4_add> -p <srv_port> -n <num_frames> -f <frame_size> -d <delay_ms> -k <traffic_class>
41 * 1. UDP fragmentation and reassembly
50 #include <sys/types.h>
51 #include <sys/socket.h>
52 #include <netinet/in.h>
53 #include <arpa/inet.h>
56 /* Server Static variable */
57 static int so
, srv_so
;
58 static int srv_port
= 0;
59 static struct sockaddr_in laddr
, dst_addr
;
60 /* Client Static variable */
61 static struct sockaddr_in srv_addr
;
62 static uint32_t tc
= 0;
64 void ErrorUsage(void);
66 uint32_t str2svc(const char *str
);
68 void ShowStastics(int64_t *DiffsBuf
, int num_frames
);
69 /* Returns difference between two timevals in microseconds */
70 int64_t time_diff(struct timeval
*b
, struct timeval
*a
);
72 void tcpServer(int frame_size
, int num_frames
, char *buf
, int64_t *DiffsBuf
);
74 void udpServer(int frame_size
, int num_frames
, char *buf
, int64_t *DiffsBuf
);
76 void tcpClient(int num_frames
, int frame_size
,
77 const char *buf
, struct timespec sleep_time
);
79 void udpClient(int num_frames
, int frame_size
,
80 const char *buf
, struct timespec sleep_time
);
84 main(int argc
, char *argv
[])
86 int num_frames
= 0, frame_size
= 0, delay_ms
= 0, rc
= 0;
87 char *buf
= NULL
, ch
, *type
= NULL
, *mode
= NULL
, *ip_addr
= NULL
;
89 struct timespec sleep_time
;
91 while ((ch
= getopt(argc
, argv
, "m:p:f:n:t:d:i:k:")) != -1) {
98 srv_port
= atoi(optarg
);
102 frame_size
= atoi(optarg
);
106 num_frames
= atoi(optarg
);
111 bzero(&srv_addr
, sizeof(srv_addr
));
112 rc
= inet_aton(optarg
, &srv_addr
.sin_addr
);
114 perror("inet_ntoa failed");
119 delay_ms
= atoi(optarg
);
127 tc
= str2svc(optarg
);
131 printf("Invalid option: %c\n", ch
);
136 /* General check for both server and client */
137 if (srv_port
<= 0 || frame_size
<= 0 || num_frames
<= 0 || !mode
|| !type
) {
140 if ( strcmp(type
, "tcp") != 0 && strcmp(type
, "udp") != 0 ) {
143 /* Allocate memory for buf */
144 buf
= calloc(1, frame_size
);
146 printf("malloc failed\n");
149 if ( strcmp(mode
, "server") == 0 ) {
151 printf("<LOG> : Start %s server on port %d with expected frame size of %d\n",
152 type
, srv_port
, frame_size
);
153 DiffsBuf
= (int64_t *)calloc(num_frames
, sizeof(int64_t));
154 if (DiffsBuf
== NULL
) {
155 printf("malloc failed\n");
158 if( strcmp(type
, "tcp") == 0) {
160 tcpServer(frame_size
, num_frames
, buf
, DiffsBuf
);
163 udpServer(frame_size
, num_frames
, buf
, DiffsBuf
);
166 else if ( strcmp(mode
, "client") == 0 ){
167 if ( !ip_addr
|| (tc
> 0 && (tc
< SO_TC_BK_SYS
|| tc
> SO_TC_CTL
)) ){
171 printf("<LOG> : Start sending %d %s frames to %s:%d with a frame size of %d\n",
172 num_frames
, type
, ip_addr
, srv_port
, frame_size
);
173 /* Resolving sleep time bug : delay_ms should just be calculated once */
174 bzero(&sleep_time
, sizeof(sleep_time
));
175 while (delay_ms
>= 1000) {
179 sleep_time
.tv_nsec
= delay_ms
* 1000 * 1000;
180 if( strcmp(type
, "tcp") == 0) {
181 /* Call TCP client */
182 tcpClient(num_frames
, frame_size
, buf
, sleep_time
);
184 /* Call UDP client */
185 udpClient(num_frames
, frame_size
, buf
, sleep_time
);
195 printf("Correct Usage");
196 printf("Server : frame_delay -m server -t <tcp/udp> -p <port> -n <num_frames> -f <frame_size>\n");
197 printf("Client : frame_delay -m client -t <tcp/udp> -i <srv_ipv4_add> -p <srv_port> -n <num_frames> -f <frame_size> -d <delay_ms> -k <traffic_class>\n");
203 str2svc(const char *str
)
208 if (str
== NULL
|| *str
== '\0')
210 else if (strcasecmp(str
, "BK_SYS") == 0)
212 else if (strcasecmp(str
, "BK") == 0)
214 else if (strcasecmp(str
, "BE") == 0)
216 else if (strcasecmp(str
, "RD") == 0)
218 else if (strcasecmp(str
, "OAM") == 0)
220 else if (strcasecmp(str
, "AV") == 0)
222 else if (strcasecmp(str
, "RV") == 0)
224 else if (strcasecmp(str
, "VI") == 0)
226 else if (strcasecmp(str
, "VO") == 0)
228 else if (strcasecmp(str
, "CTL") == 0)
231 svc
= (uint32_t)strtoul(str
, &endptr
, 0);
240 ShowStastics(int64_t *DiffsBuf
, int num_frames
) {
242 int64_t sum
= 0, mean
= 0;
245 while(i
< num_frames
)
246 sum
+= DiffsBuf
[i
++];
247 mean
= sum
/ num_frames
;
248 printf("<LOG> : Mean: %.2f usecs\n", sum
/ (double)num_frames
);
249 /* Popular Standard Deviation */
252 while(i
< num_frames
) {
253 sum
+= (DiffsBuf
[i
]-mean
)*(DiffsBuf
[i
]-mean
);
256 printf("<LOG> : Popular Standard Deviation: %.2f usecs\n",
257 sqrt(sum
/(double)num_frames
));
260 /* Returns difference between two timevals in microseconds */
262 time_diff(struct timeval
*b
, struct timeval
*a
)
265 usecs
= (a
->tv_sec
- b
->tv_sec
) * 1000 * 1000;
266 usecs
+= (int64_t)(a
->tv_usec
- b
->tv_usec
);
274 tcpServer(int frame_size
, int num_frames
, char *buf
, int64_t *DiffsBuf
) {
275 int rc
= 0, i
= 0, ignore_count
= 0;
276 uint32_t dst_len
= 0;
277 struct timeval before
, after
;
280 /* New change from Padama */
281 uint64_t prev_frame_ts
= 0, prev_recv
= 0, frame_ts
= 0, cur_recv
= 0;
282 uint64_t min_variation
= 0, max_variation
= 0, avg_variation
= 0;
284 printf("<LOG> : TCP Server\n");
285 so
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
287 perror("failed to create socket");
290 bzero(&laddr
, sizeof(laddr
));
291 laddr
.sin_family
= AF_INET
;
292 laddr
.sin_port
= htons(srv_port
);
293 rc
= bind(so
, (const struct sockaddr
*)&laddr
, sizeof(laddr
));
295 perror("failed to bind");
300 perror("failed to listen");
303 srv_so
= accept(so
, (struct sockaddr
*)&dst_addr
, &dst_len
);
305 perror("failed to accept");
309 if ( i
== num_frames
) {
310 printf("<LOG> : Completed\n");
313 printf("<LOG> : Waiting for receiving\n");
314 bzero(&before
, sizeof(before
));
315 bzero(&after
, sizeof(after
));
316 rc
= gettimeofday(&before
, NULL
);
318 perror("gettimeofday failed");
321 bytes
= recv(srv_so
, buf
, frame_size
, MSG_WAITALL
);
323 perror("recv failed");
326 else if (bytes
> 0 && bytes
!= frame_size
) {
327 printf("Client exited\n");
328 printf("Didn't recv the complete frame, bytes %ld\n",
332 else if (bytes
== 0) {
335 rc
= gettimeofday(&after
, NULL
);
337 perror("gettimeofday failed");
340 cur_recv
= after
.tv_sec
* 1000 * 1000 + after
.tv_usec
;
341 memcpy((void *)&frame_ts
, buf
, sizeof(frame_ts
));
342 if (prev_frame_ts
> 0) {
343 int64_t d_variation
= 0;
344 d_variation
= (int64_t)((cur_recv
- prev_recv
) -
345 (frame_ts
- prev_frame_ts
));
346 /* printf("Frame %u ts %llu d_variation %lld usecs\n",
347 i, frame_ts, d_variation);*/
348 if (d_variation
> 0) {
349 if (min_variation
== 0)
350 min_variation
= d_variation
;
352 min_variation
= ((min_variation
<= d_variation
) ?
353 min_variation
: d_variation
);
354 max_variation
= ((max_variation
>= d_variation
) ?
355 max_variation
: d_variation
);
356 avg_variation
+= d_variation
;
361 prev_recv
= cur_recv
;
362 prev_frame_ts
= frame_ts
;
364 /* Compute the time differenc */
365 usecs
= time_diff(&before
, &after
);
367 printf("<LOG> : Frame %d received after %lld usecs\n", i
, usecs
);
369 if (i
!= ignore_count
)
370 avg_variation
= avg_variation
/ (i
- ignore_count
);
374 printf("<LOG> : Received frames: %u\n", i
);
375 printf("<LOG> : Ignored frames: %u\n", ignore_count
);
376 printf("<LOG> : Minimum delay variation: %llu usecs\n", min_variation
);
377 printf("<LOG> : Maximum delay variation: %llu usecs\n", max_variation
);
378 printf("<LOG> : Average delay variation: %llu usecs\n", avg_variation
);
379 ShowStastics(DiffsBuf
, num_frames
);
384 udpServer(int frame_size
, int num_frames
, char *buf
, int64_t *DiffsBuf
) {
385 int rc
= 0, i
= 0, ignore_count
= 0;
386 uint32_t dst_len
= 0;
388 struct timeval before
, after
;
390 /* New change from Padama */
391 uint64_t prev_frame_ts
= 0, prev_recv
= 0, frame_ts
= 0, cur_recv
= 0;
392 uint64_t min_variation
= 0, max_variation
= 0, avg_variation
= 0;
394 printf("<LOG> : UDP Server\n");
395 so
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
397 perror("failed to create socket");
400 bzero(&laddr
,sizeof(laddr
));
401 laddr
.sin_family
= AF_INET
;
402 laddr
.sin_addr
.s_addr
=htonl(INADDR_ANY
);
403 laddr
.sin_port
=htons(srv_port
);
404 rc
= bind(so
, (struct sockaddr
*)&laddr
,sizeof(laddr
));
406 perror("failed to bind");
410 if ( i
== num_frames
) {
411 printf("<LOG> : Completed\n");
414 printf("<LOG> : Waiting for receiving\n");
415 bzero(&before
, sizeof(before
));
416 bzero(&after
, sizeof(after
));
417 rc
= gettimeofday(&before
, NULL
);
419 perror("gettimeofday failed");
422 bytes
= recvfrom(so
, buf
, frame_size
, 0, (struct sockaddr
*)&dst_addr
, &dst_len
);
424 perror("recv failed");
427 else if (bytes
> 0 && bytes
!= frame_size
) {
428 printf("Client exited\n");
429 printf("Didn't recv the complete frame, bytes %ld\n",
433 else if (bytes
== 0) {
436 rc
= gettimeofday(&after
, NULL
);
438 perror("gettimeofday failed");
441 cur_recv
= after
.tv_sec
* 1000 * 1000 + after
.tv_usec
;
442 memcpy((void *)&frame_ts
, buf
, sizeof(frame_ts
));
443 if (prev_frame_ts
> 0) {
444 int64_t d_variation
= 0;
446 d_variation
= (int64_t)((cur_recv
- prev_recv
) -
447 (frame_ts
- prev_frame_ts
));
448 /* printf("Frame %u ts %llu d_variation %lld usecs\n",
449 i, frame_ts, d_variation);*/
450 if (d_variation
> 0) {
451 if (min_variation
== 0)
452 min_variation
= d_variation
;
454 min_variation
= ((min_variation
<= d_variation
) ?
455 min_variation
: d_variation
);
456 max_variation
= ((max_variation
>= d_variation
) ?
457 max_variation
: d_variation
);
458 avg_variation
+= d_variation
;
463 prev_recv
= cur_recv
;
464 prev_frame_ts
= frame_ts
;
466 /* Compute the time differenc */
467 usecs
= time_diff(&before
, &after
);
469 printf("<LOG> : Frame %d received after %lld usecs\n", i
, usecs
);
471 if (i
!= ignore_count
)
472 avg_variation
= avg_variation
/ (i
- ignore_count
);
475 printf("<LOG> : Received frames: %u\n", i
);
476 printf("<LOG> : Ignored frames: %u\n", ignore_count
);
477 printf("<LOG> : Minimum delay variation: %llu usecs\n", min_variation
);
478 printf("<LOG> : Maximum delay variation: %llu usecs\n", max_variation
);
479 printf("<LOG> : Average delay variation: %llu usecs\n", avg_variation
);
480 ShowStastics(DiffsBuf
, num_frames
);
485 tcpClient(int num_frames
, int frame_size
,
486 const char *buf
, struct timespec sleep_time
){
490 printf("<LOG> : TCP Client\n");
491 so
= socket(PF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
494 perror("creating socket failed");
497 srv_addr
.sin_port
= htons(srv_port
);
498 srv_addr
.sin_len
= sizeof(srv_addr
);
499 srv_addr
.sin_family
= AF_INET
;
500 rc
= connect(so
, (const struct sockaddr
*)&srv_addr
,
503 perror("connect failed");
507 rc
= setsockopt(so
, SOL_SOCKET
, SO_TRAFFIC_CLASS
, &tc
,
510 perror("failed to set traffic class");
514 for (i
= 0; i
< num_frames
; ++i
) {
517 /* Add a timestamp to the frame */
518 rc
= gettimeofday(&fts
, NULL
);
520 perror("faile to get time of day");
523 frame_ts
= fts
.tv_sec
* 1000 * 1000 + fts
.tv_usec
;
524 memcpy((void *)buf
, (const void *)&frame_ts
, sizeof(frame_ts
));
525 bytes
= send(so
, buf
, frame_size
, 0);
527 perror("send failed \n");
530 if (bytes
!= frame_size
) {
531 printf("failed to send all bytes, sent %ld\n", bytes
);
534 rc
= nanosleep(&sleep_time
, NULL
);
536 perror("sleep failed");
539 printf("<LOG> : Sent %u frames as a whole\n", (i
+ 1));
544 udpClient(int num_frames
, int frame_size
,
545 const char *buf
, struct timespec sleep_time
){
549 printf("<LOG> : UDP Client\n");
550 so
= socket(PF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
552 perror("creating socket failed");
555 srv_addr
.sin_port
= htons(srv_port
);
556 srv_addr
.sin_len
= sizeof(srv_addr
);
557 srv_addr
.sin_family
= AF_INET
;
559 rc
= setsockopt(so
, SOL_SOCKET
, SO_TRAFFIC_CLASS
, &tc
,
562 perror("failed to set traffic class");
566 for (i
= 0; i
< num_frames
; ++i
) {
569 /* Add a timestamp to the frame */
570 rc
= gettimeofday(&fts
, NULL
);
572 perror("faile to get time of day");
575 frame_ts
= fts
.tv_sec
* 1000 * 1000 + fts
.tv_usec
;
576 memcpy((void *)buf
, (const void *)&frame_ts
, sizeof(frame_ts
));
577 bytes
= sendto(so
, buf
, frame_size
, 0, (struct sockaddr
*)&srv_addr
, sizeof(srv_addr
));
579 perror("send failed \n");
582 if (bytes
!= frame_size
) {
583 printf("failed to send all bytes, sent %ld\n", bytes
);
586 rc
= nanosleep(&sleep_time
, NULL
);
588 perror("sleep failed");
591 printf("<LOG> : Sent %u frames as a whole\n", (i
+ 1));