3 #include <sys/socket.h>
4 #include <netinet/in.h>
19 #include <semaphore.h>
23 #define PARAM_SERVERADDR 1
24 #define MAX_SENDENDPOINTS 10
26 unsigned opt_packet_size = 800;
27 unsigned opt_period_usec = 10*MSEC;
28 unsigned opt_jitter = 0;
29 char *opt_output = "delay_stats";
30 unsigned opt_count_sec = 0;
32 int ac_sockfd[AC_QUEUES];
36 unsigned received, last_received;
37 } receivers[AC_QUEUES];
45 struct timespec send_timestamp;
46 unsigned long int seqn;
51 char nonsense[BUFFSIZE];
54 /* maximal traffic delay in ms - 10 s*/
55 #define MAX_DELAY_US 10000000
56 #define GRANULARITY 100
58 unsigned delay_stats[AC_QUEUES][MAX_DELAY_US/GRANULARITY];
60 /*struct ac_stats[AC_QUEUES] {
61 unsigned long int min_trans_time;
62 unsigned long int sum_trans_time;
63 struct timespec recv_timestamp;
64 struct timespec send_timestamp;
67 struct send_endpoint {
69 long period_usec; /* all time units are in microseconds */
70 int bandwidth_bps; /* bits per second */
74 struct send_endpoint sepoint[] = {
75 { .ac = AC_VO, .period_usec=200*MSEC, .bandwidth_bps = 34*Kbit },
76 { .ac = AC_VI, .period_usec=25*MSEC, .bandwidth_bps = 480*Kbit },
77 { .ac = AC_BE, .period_usec=40*MSEC, .bandwidth_bps = 300*Kbit },
78 { .ac = AC_BK, .period_usec=40*MSEC, .bandwidth_bps = 300*Kbit },
79 // { .ac = AC_VI, .period_usec=17*MSEC, .bandwidth_bps = 675*Kbit },
83 struct send_endpoint sepoint[] = {
84 { .ac = AC_VO, .period_usec=10*MSEC, .bandwidth_bps = 300*Kbit },
85 { .ac = AC_VI, .period_usec=10*MSEC, .bandwidth_bps = 300*Kbit },
86 { .ac = AC_BE, .period_usec=10*MSEC, .bandwidth_bps = 300*Kbit },
87 { .ac = AC_BK, .period_usec=10*MSEC, .bandwidth_bps = 300*Kbit },
90 unsigned int nr_sepoints = sizeof(sepoint)/sizeof(*sepoint);
92 sem_t sem_thread_finished;
94 bool exit_flag = false;
101 /* Interrupt all receivers */
102 for (i=0; i<AC_QUEUES; i++) {
103 pthread_kill(receivers[i].thread, SIGUSR1);
111 unsigned sum[AC_QUEUES];
113 fprintf(stderr, "\nWriting data to %s...\n", logfname);
116 for (maxi = MAX_DELAY_US/GRANULARITY - 1; maxi >= 0; maxi--) {
117 for (ac = 0; ac < AC_QUEUES; ac++) {
118 if (delay_stats[ac][maxi] != 0) allzeros = false;
120 if (!allzeros) break;
122 if (maxi < 3000/GRANULARITY) maxi = 3000/GRANULARITY;
124 for (ac = 0; ac < AC_QUEUES; ac++) {
126 for ( i = 0 ; i < maxi; i++)
127 sum[ac]+=delay_stats[ac][i];
129 fprintf(stderr, "No response in AC %d\n", ac);
132 for ( i = 0 ; i < maxi; i++) {
133 fprintf(logfd,"\n%f", i*GRANULARITY/1000.0);
134 for (ac = 0; ac < AC_QUEUES; ac++) {
136 val = (double)delay_stats[ac][i]*100.0 / sum[ac];
137 fprintf(logfd," %lf", val);
141 fprintf(stderr, "Finished.\n");
148 void timespec_add (struct timespec *sum, const struct timespec *left,
149 const struct timespec *right)
151 sum->tv_sec = left->tv_sec + right->tv_sec;
152 sum->tv_nsec = left->tv_nsec + right->tv_nsec;
154 if (sum->tv_nsec >= 1000000000){
156 sum->tv_nsec -= 1000000000;
161 void timespec_sub (struct timespec *diff, const struct timespec *left,
162 const struct timespec *right)
164 diff->tv_sec = left->tv_sec - right->tv_sec;
165 diff->tv_nsec = left->tv_nsec - right->tv_nsec;
167 if (diff->tv_nsec < 0){
169 diff->tv_nsec += 1000000000;
173 int create_ac_socket(unsigned int ac)
176 unsigned int yes=1, tos;
179 if ((sockfd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
181 perror("Unable to open socket");
185 if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) {
186 perror("Unable to set socket");
191 //tos = ((AC_QUEUES - ac) *2 - 1)*32;
193 if (setsockopt(sockfd, SOL_IP, IP_TOS, &tos, sizeof(tos))) {
194 perror("Unable to set TOS");
206 void* receiver(void* queue)
209 struct sockaddr_in rem_addr;
211 unsigned int ac, rem_addr_length;
212 unsigned long int trans_time_usec;
213 unsigned long int min_trans_time;
214 struct timespec send_timestamp,recv_timestamp, trans_time;
222 rem_addr_length = sizeof(rem_addr);
224 mlen = recvfrom(ac_sockfd[ac], &msg, sizeof(msg), 0, \
225 (struct sockaddr*)&rem_addr, &rem_addr_length);
227 if (errno == EINTR) continue;
228 perror("Chyba pri prijimani pozadavku");
231 clock_gettime(CLOCK_MONOTONIC,&recv_timestamp);
232 send_timestamp = msg.send_timestamp;
234 timespec_sub(&trans_time,&recv_timestamp ,&send_timestamp);
235 trans_time_usec = (trans_time.tv_sec * 1000000 + \
236 trans_time.tv_nsec / 1000) /2;
238 if (trans_time_usec < MAX_DELAY_US)
239 delay_stats[ac][trans_time_usec/GRANULARITY]++;
241 receivers[ac].received++;
243 /*if (trans_time_nsec < min_trans_time)
244 min_trans_time = trans_time_nsec;*/
245 /*printf("seqn= %lu tos= %d start= %lu(s).%lu(ns)"\
246 "stop= %lu(s).%lu(ns)\n trans_time = %lums\n",\
247 msg.seqn, msg.tos, send_timestamp.tv_sec,\
248 send_timestamp.tv_nsec,recv_timestamp.tv_sec,\
249 recv_timestamp.tv_nsec, trans_time_msec); */
252 sem_post(&sem_thread_finished);
256 void* sender(void* endpoint)
258 struct sockaddr_in rem_addr;
260 unsigned long int seqn;
261 struct timespec time_to_wait, current_time, period, interval;
263 struct send_endpoint* spoint = (struct send_endpoint*) endpoint;
264 char buf1[12], buf2[12], buf3[12];
267 unsigned period_usec;
268 char stream_desc[100];
270 if (opt_packet_size) {
271 packet_size = opt_packet_size;
272 period_usec = 1000000LL*packet_size*8/spoint->bandwidth_bps;
274 period_usec = spoint->period_usec;
275 packet_size = (long long)spoint->bandwidth_bps/8 * period_usec/1000000;
277 snprintf(stream_desc, sizeof(stream_desc), "%d: %s %s (%d bytes per %s +-%s, %d packets/s)\n",
278 spoint-sepoint, ac_to_text[ac], bandwidth_to_text(buf1, spoint->bandwidth_bps),
279 packet_size, usec_to_text(buf2, period_usec),
280 usec_to_text(buf3, opt_jitter*period_usec/100), 1000000/period_usec);
281 printf("%s", stream_desc);
282 fprintf(logfd, "# Stream %s", stream_desc);
284 if (packet_size < sizeof(struct msg_t)) {
285 fprintf(stderr, "Pakcet size too small (min %d)\n", sizeof(struct msg_t));
290 memset(&rem_addr,0, sizeof(rem_addr));
292 rem_addr.sin_family = AF_INET;
293 ph = gethostbyname(server_addr);
295 rem_addr.sin_addr = *((struct in_addr *)ph->h_addr);
297 perror("Unknown server");
300 rem_addr.sin_port = htons(BASE_PORT + ac);
308 buff.msg.seqn = seqn;
309 buff.msg.tos = ac_to_tos[ac];
311 clock_gettime(CLOCK_MONOTONIC,&buff.msg.send_timestamp);
313 while (sendto(ac_sockfd[ac], &buff, packet_size, 0,\
314 (struct sockaddr*)&rem_addr, sizeof(rem_addr)) < 0) {
315 if (errno == EINTR) continue;
316 perror("Error while sending");
326 /* |~~~+~~~| jitter interval (width = 2*opt_jitter percentage from period)*/
327 /* |-------------| nominal period*/
329 period.tv_nsec = 1000LL*(period_usec*(100-opt_jitter)/100
330 + rand() % (2*period_usec*opt_jitter/100));
332 period.tv_nsec = 1000LL*(period_usec);
336 timespec_add(&time_to_wait,&buff.msg.send_timestamp,&period);
337 clock_gettime(CLOCK_MONOTONIC,¤t_time);
338 timespec_sub(&interval,&time_to_wait,¤t_time);
339 nanosleep(&interval,NULL);
342 sem_post(&sem_thread_finished);
346 int main(int argc, char *argv[])
354 while ((opt = getopt(argc, argv, "c:j:o:s:")) != -1) {
357 opt_count_sec = atoi(optarg);
360 opt_jitter = atoi(optarg);
366 opt_packet_size = atoi(optarg);
369 fprintf(stderr, "Usage: %s [ options ] server_addr\n\n", argv[0]);
370 fprintf(stderr, "Options:\n");
371 fprintf(stderr, " -c count (number of seconds to run)");
372 fprintf(stderr, " -j send jitter (0-100) [%%]\n");
373 fprintf(stderr, " -o output filename (.dat will be appended)");
374 fprintf(stderr, " -s size of data payload in packets [bytes]\n");
379 server_addr = argv[optind];
381 fprintf(stderr, "Expected server address argument\n");
387 memset(delay_stats,0, sizeof(delay_stats));
388 pthread_attr_init(&attr);
390 snprintf(logfname, sizeof(logfname), "%s.dat", opt_output);
392 if ((logfd = fopen(logfname,"w+")) == NULL) {
393 fprintf(stderr,"Can not open %s\n", logfname);
396 fprintf(logfd, "# Invoked as: ");
397 for (i=0; i<argc; i++) fprintf(logfd, "%s ", argv[i]);
398 fprintf(logfd, "\n");
400 if (signal(SIGTERM, stopper) == SIG_ERR) {
401 perror("Error in signal registration");
405 if (signal(SIGINT, stopper) == SIG_ERR) {
406 perror("Signal handler registration error");
411 sa.sa_handler = empty_handler;
412 sa.sa_flags = 0; /* don't restart syscalls */
414 if (sigaction(SIGUSR1, &sa, NULL) < 0) {
415 perror("sigaction error");
419 sem_init(&sem_thread_finished, 0, 0);
421 /* create four receivers each per AC */
422 for (ac = AC_QUEUES - 1; ac >= 0; ac--) {
423 ac_sockfd[ac] = create_ac_socket(ac);
424 rc = pthread_create(&receivers[ac].thread, &attr, receiver, (void*) ac);
426 fprintf(stderr, "Error while creating receiver %d\n",rc);
431 /* create sendpoints */
432 for (i = 0; i < nr_sepoints; i++) {
433 rc = pthread_create(&thread, &attr, sender, (void*) &sepoint[i]);
435 fprintf(stderr, "Error while creating sender %d\n",rc);
442 fprintf(stderr, "\r");
443 for (ac = 0; ac<AC_QUEUES; ac++) {
444 int delta = receivers[ac].received - receivers[ac].last_received;
445 receivers[ac].last_received = receivers[ac].received;
446 fprintf(stderr, "%s: %5d (+%4d) ", ac_to_text[ac], receivers[ac].received, delta);
451 if (i == opt_count_sec) exit_flag = 1;
454 fprintf(stderr, "\nWaiting for threads to finish\n");
455 /* Wait for all threads to finish */
456 for (i=0; i < nr_sepoints + AC_QUEUES; i++) {
457 sem_wait(&sem_thread_finished);