3 #include <sys/socket.h>
4 #include <netinet/in.h>
19 #include <semaphore.h>
27 #define PARAM_SERVERADDR 1
28 #define MAX_SENDENDPOINTS 10
30 int ac_sockfd[AC_QUEUES];
34 } receivers[AC_QUEUES];
39 const char logfname[] = "delay_stats.dat";
43 struct timespec send_timestamp;
44 unsigned long int seqn;
45 unsigned char padding[MTU];
48 /* maximal traffic delay in ms - 10 s*/
49 #define MAX_DELAY_US 10000000
50 #define GRANULARITY 100
52 unsigned delay_stats[AC_QUEUES][MAX_DELAY_US/GRANULARITY];
54 /*struct ac_stats[AC_QUEUES] {
55 unsigned long int min_trans_time;
56 unsigned long int sum_trans_time;
57 struct timespec recv_timestamp;
58 struct timespec send_timestamp;
61 struct send_endpoint {
64 int bandwidth_bps; /* bits per second */
67 #define MSEC (1000*1000)
68 #define Mbit (1024*1024)
73 struct send_endpoint sepoint[] = {
74 { .ac = AC_VO, .period_nsec=200*MSEC, .bandwidth_bps = 34*Kbit },
75 { .ac = AC_VI, .period_nsec=25*MSEC, .bandwidth_bps = 480*Kbit },
76 { .ac = AC_BE, .period_nsec=40*MSEC, .bandwidth_bps = 300*Kbit },
77 { .ac = AC_BK, .period_nsec=40*MSEC, .bandwidth_bps = 300*Kbit },
78 // { .ac = AC_VI, .period_nsec=17*MSEC, .bandwidth_bps = 675*Kbit },
82 struct send_endpoint sepoint[] = {
83 { .ac = AC_VO, .period_nsec=40*MSEC, .bandwidth_bps = 300*Kbit },
84 { .ac = AC_VI, .period_nsec=40*MSEC, .bandwidth_bps = 300*Kbit },
85 { .ac = AC_BE, .period_nsec=60*MSEC, .bandwidth_bps = 200*Kbit },
86 { .ac = AC_BK, .period_nsec=60*MSEC, .bandwidth_bps = 200*Kbit },
89 unsigned int nr_sepoints = sizeof(sepoint)/sizeof(*sepoint);
91 sem_t sem_thread_finished;
93 bool exit_flag = false;
100 /* Interrupt all receivers */
101 for (i=0; i<AC_QUEUES; i++) {
102 pthread_kill(receivers[i].thread, SIGUSR1);
110 unsigned sum[AC_QUEUES];
112 printf("\nWriting data to log file...\n");
115 for (maxi = MAX_DELAY_US/GRANULARITY - 1; maxi >= 0; maxi--) {
116 for (ac = 0; ac < AC_QUEUES; ac++) {
117 if (delay_stats[ac][maxi] != 0) allzeros = false;
119 if (!allzeros) break;
121 if (maxi < 3000/GRANULARITY) maxi = 3000/GRANULARITY;
123 for (ac = 0; ac < AC_QUEUES; ac++) {
125 for ( i = 0 ; i < maxi; i++)
126 sum[ac]+=delay_stats[ac][i];
128 fprintf(stderr, "No response in AC %d\n", ac);
131 for (ac = 0; ac < AC_QUEUES; ac++) {
132 for ( i = 0 ; i < maxi; i++) {
134 val = (double)delay_stats[ac][i]*100.0 / sum[ac];
135 fprintf(logfd,"%f %lf\n", i*GRANULARITY/1000.0, val);
138 fprintf(logfd, "\n\n");
141 printf("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 /*if (trans_time_nsec < min_trans_time)
242 min_trans_time = trans_time_nsec;*/
243 /*printf("seqn= %lu tos= %d start= %lu(s).%lu(ns)"\
244 "stop= %lu(s).%lu(ns)\n trans_time = %lums\n",\
245 msg.seqn, msg.tos, send_timestamp.tv_sec,\
246 send_timestamp.tv_nsec,recv_timestamp.tv_sec,\
247 recv_timestamp.tv_nsec, trans_time_msec); */
250 sem_post(&sem_thread_finished);
254 void* sender(void* endpoint)
256 struct sockaddr_in rem_addr;
258 unsigned long int seqn;
259 struct timespec time_to_wait, current_time, period, interval;
261 struct send_endpoint* spoint = (struct send_endpoint*) endpoint;
264 memset(&rem_addr,0, sizeof(rem_addr));
265 //-------------------------------------------------------------------
266 // TODO: not functioning - check it
268 if ((rem_addr.sin_addr.s_addr = inet_addr(server_addr)) == INADDR_NONE){
269 ph = gethostbyname(server_addr);
271 rem_addr.sin_addr = *((struct in_addr *)ph->h_addr);
273 perror("Unknown server");
277 //------------------------------------------------------------------
279 rem_addr.sin_family = AF_INET;
280 rem_addr.sin_addr.s_addr = inet_addr(server_addr);
281 rem_addr.sin_port = htons(BASE_PORT + ac);
284 period.tv_nsec = spoint->period_nsec;
293 msg.tos = ac_to_tos[ac];
295 clock_gettime(CLOCK_MONOTONIC,&msg.send_timestamp);
297 while (sendto(ac_sockfd[ac], &msg, sizeof(msg), 0,\
298 (struct sockaddr*)&rem_addr, sizeof(rem_addr)) < 0) {
299 if (errno == EINTR) continue;
300 perror("Error while sending");
310 timespec_add(&time_to_wait,&msg.send_timestamp,&period);
311 clock_gettime(CLOCK_MONOTONIC,¤t_time);
312 timespec_sub(&interval,&time_to_wait,¤t_time);
313 nanosleep(&interval,NULL);
316 sem_post(&sem_thread_finished);
320 int main(int argc, char *argv[])
329 while ((opt = getopt(argc, argv, "hs")) != -1) {
335 fprintf(stderr, "Usage: %s [ options ] server_addr\n", argv[0]);
336 fprintf(stderr, "options: -s read streams from stdin\n");
341 server_addr = argv[optind];
343 fprintf(stderr, "Expected server address argument\n");
349 memset(delay_stats,0, sizeof(delay_stats));
350 pthread_attr_init(&attr);
352 if ((logfd = fopen(logfname,"w+")) == NULL) {
353 fprintf(stderr,"Can not open %s\n", logfname);
358 if (signal(SIGTERM, stopper) == SIG_ERR) {
359 perror("Error in signal registration");
363 if (signal(SIGINT, stopper) == SIG_ERR) {
364 perror("Signal handler registration error");
369 sa.sa_handler = empty_handler;
370 sa.sa_flags = 0; /* don't restart syscalls */
372 if (sigaction(SIGUSR1, &sa, NULL) < 0) {
373 perror("sigaction error");
377 sem_init(&sem_thread_finished, 0, 0);
379 /* create four receivers each per AC */
380 for (ac = AC_QUEUES - 1; ac >= 0; ac--) {
381 ac_sockfd[ac] = create_ac_socket(ac);
382 rc = pthread_create(&receivers[ac].thread, &attr, receiver, (void*) ac);
384 printf("Error while creating receiver %d\n",rc);
389 /* create sendpoints */
390 for (i = 0; i < nr_sepoints; i++) {
391 rc = pthread_create(&thread, &attr, sender, (void*) &sepoint[i]);
393 printf("Error while creating sender %d\n",rc);
402 printf("Waiting for threads to finish\n");
403 /* Wait for all threads to finish */
404 for (i=0; i < nr_sepoints + AC_QUEUES; i++) {
405 sem_wait(&sem_thread_finished);