]> rtime.felk.cvut.cz Git - frescor/fwp.git/blob - wme_test/wclient.c
Merge branch 'master' of molnam1@rtime.felk.cvut.cz:/var/git/frescor
[frescor/fwp.git] / wme_test / wclient.c
1 #include <errno.h>
2 #include <sys/types.h>
3 #include <sys/socket.h>
4 #include <netinet/in.h>
5 #include <arpa/inet.h>
6 #include <netdb.h>
7 #include <signal.h>
8 #include <sys/wait.h>
9 #include <stdio.h>
10 #include <unistd.h>
11 #include <fcntl.h>
12 #include <time.h>
13 #include <string.h>
14 #include <pthread.h>
15 #include <string.h>
16 #include <stdlib.h>
17 #include <stdbool.h>
18
19 /*#define AC_VO 0
20 #define AC_VI 1
21 #define AC_BE 2
22 #define AC_BK 3
23 */
24
25 #define PARAM_SERVERADDR 1
26 #define BASE_PORT        5100
27 #define AC_QUEUES        4
28 #define MAX_SENDENDPOINTS  10
29 #define MTU              800 
30
31
32 enum {  AC_VO = 0,
33         AC_VI = 1,
34         AC_BE = 2,
35         AC_BK = 3
36 };
37
38 const int prio_to_ac[8] = {2,3,3,2,1,1,0,0};
39 const unsigned int ac_to_tos[4] = {224,160,96,64};
40
41 int ac_sockfd[AC_QUEUES];
42 FILE* logfd;
43 char* server_addr; 
44
45 const char logfname[] = "delay_stats.dat";
46
47 struct msg_t {
48         unsigned int tos;
49         struct timespec send_timestamp;
50         unsigned long int seqn;
51         unsigned char padding[MTU];
52 };
53
54 /* maximal traffic delay in ms */
55 #define MAX_DELAY_US 10000000
56 #define GRANULARITY 100
57
58 unsigned delay_stats[AC_QUEUES][MAX_DELAY_US/GRANULARITY];
59
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; 
65 };*/
66
67 struct send_endpoint {
68         int ac;
69         long period_nsec;
70         int bandwidth_bps;      /* bits per second */
71 };
72
73 #define MSEC (1000*1000)
74 #define Mbit (1000*1000)
75 #define Kbit 1000
76
77
78 /*
79 struct send_endpoint sepoint[] = {
80         { .ac = AC_VO, .period_nsec=200*MSEC, .bandwidth_bps = 34*Kbit },
81         { .ac = AC_VI, .period_nsec=25*MSEC, .bandwidth_bps =  480*Kbit },
82         { .ac = AC_BE, .period_nsec=40*MSEC, .bandwidth_bps =  300*Kbit },
83         { .ac = AC_BK, .period_nsec=40*MSEC, .bandwidth_bps =  300*Kbit },
84 //      { .ac = AC_VI, .period_nsec=17*MSEC, .bandwidth_bps =  675*Kbit },
85 };
86 */
87
88 struct send_endpoint sepoint[] = {
89         { .ac = AC_VO, .period_nsec=40*MSEC, .bandwidth_bps = 300*Kbit },
90         { .ac = AC_VI, .period_nsec=40*MSEC, .bandwidth_bps =  300*Kbit },
91         { .ac = AC_BE, .period_nsec=60*MSEC, .bandwidth_bps =  200*Kbit },
92         { .ac = AC_BK, .period_nsec=60*MSEC, .bandwidth_bps =  200*Kbit },
93 };
94
95 unsigned int nr_sepoints = sizeof(sepoint)/sizeof(*sepoint);
96
97 void stopper()
98 {
99         int ac, i, maxi;
100         bool allzeros;
101         unsigned sum[AC_QUEUES];
102
103         printf("Writing data to log file...\n");
104
105         allzeros = true;
106         for (maxi = MAX_DELAY_US/GRANULARITY - 1; maxi >= 0; maxi--) {
107                 for (ac = 0; ac < AC_QUEUES; ac++) {
108                         if (delay_stats[ac][maxi] != 0) allzeros = false;
109                 }
110                 if (!allzeros) break;
111         }
112         if (maxi < 10000/GRANULARITY) maxi = 10000/GRANULARITY;
113
114         for (ac = 0; ac < AC_QUEUES; ac++) { 
115                 sum[ac] = 0;
116                 for ( i = 0 ; i < maxi; i++) 
117                         sum[ac]+=delay_stats[ac][i];
118                 if (sum[ac] == 0)
119                         fprintf(stderr, "No response in AC %d\n", ac);
120         }
121
122         for (ac = 0; ac < AC_QUEUES; ac++) { 
123                 for ( i = 0 ; i < maxi; i++) {
124                         double val;
125                         val = (double)delay_stats[ac][i]*100.0 / sum[ac];
126                         fprintf(logfd,"%f %lf\n", i*GRANULARITY/1000.0, val);
127                 }
128                 
129                 fprintf(logfd, "\n\n");
130         }
131         
132         printf("Finished.\n");
133         fclose(logfd);
134
135         exit(0);
136 }
137
138 static inline 
139 void timespec_add (struct timespec *sum, const struct timespec *left,
140               const struct timespec *right)
141 {
142         sum->tv_sec = left->tv_sec + right->tv_sec;
143         sum->tv_nsec = left->tv_nsec + right->tv_nsec;
144
145         if (sum->tv_nsec >= 1000000000){
146                 ++sum->tv_sec;
147                 sum->tv_nsec -= 1000000000;
148         }
149 }
150
151 static inline 
152 void timespec_sub (struct timespec *diff, const struct timespec *left,
153               const struct timespec *right)
154 {
155         diff->tv_sec = left->tv_sec - right->tv_sec;
156         diff->tv_nsec = left->tv_nsec - right->tv_nsec;
157
158         if (diff->tv_nsec < 0){
159                   --diff->tv_sec;
160                   diff->tv_nsec += 1000000000;
161         }
162 }
163
164 int create_ac_socket(unsigned int ac) 
165 {
166         int sockfd;
167         unsigned int yes=1, tos;
168
169
170         if ((sockfd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
171         {
172                 perror("Unable to open socket");
173                 return -1;
174         }
175         
176         if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) {
177                 perror("Unable to set socket");
178                 return -1;
179         }
180
181         
182         //tos = ((AC_QUEUES - ac) *2 - 1)*32;
183         tos = ac_to_tos[ac];
184         if (setsockopt(sockfd, SOL_IP, IP_TOS, &tos, sizeof(tos))) {
185                 perror("Unable to set TOS");
186                 close(sockfd);
187                 return -1;
188         }
189
190         return sockfd;
191 }
192
193
194 void* receiver(void* queue)
195 {
196         struct msg_t    msg;
197         struct  sockaddr_in rem_addr;
198         int     mlen;
199         unsigned int ac, rem_addr_length; 
200         unsigned long int trans_time_usec;
201         unsigned long int min_trans_time;
202         struct timespec   send_timestamp,recv_timestamp, trans_time; 
203         
204         min_trans_time = ~0;
205         
206         ac = (int)queue;
207         rem_addr_length = sizeof(rem_addr);
208         while (1) {
209                 while ((mlen = recvfrom(ac_sockfd[ac], &msg, sizeof(msg), 0,\
210                         (struct sockaddr*)&rem_addr, &rem_addr_length)) < 0) {
211                             if (errno == EINTR) continue;
212                             perror("Chyba pri prijimani pozadavku");
213                             return NULL;
214                 }       
215                 clock_gettime(CLOCK_MONOTONIC,&recv_timestamp);
216                 send_timestamp = msg.send_timestamp;
217                 
218                 timespec_sub(&trans_time,&recv_timestamp ,&send_timestamp);
219                 trans_time_usec = (trans_time.tv_sec * 1000000 + \
220                                          trans_time.tv_nsec / 1000) /2;
221           
222                 if (trans_time_usec < MAX_DELAY_US)
223                         delay_stats[ac][trans_time_usec/GRANULARITY]++;
224         
225                 /*if (trans_time_nsec < min_trans_time) 
226                         min_trans_time = trans_time_nsec;*/
227                 /*printf("seqn= %lu tos= %d start= %lu(s).%lu(ns)"\
228                          "stop= %lu(s).%lu(ns)\n trans_time = %lums\n",\
229                          msg.seqn, msg.tos, send_timestamp.tv_sec,\
230                          send_timestamp.tv_nsec,recv_timestamp.tv_sec,\
231                          recv_timestamp.tv_nsec, trans_time_msec); */
232         }
233 }
234
235 void* sender(void* endpoint)
236 {
237         struct sockaddr_in rem_addr;
238         struct msg_t msg;
239         unsigned long int seqn;
240         struct timespec time_to_wait, current_time, period, interval;
241         struct hostent* ph;
242         struct send_endpoint* spoint = (struct send_endpoint*) endpoint;
243         int ac = spoint->ac;
244         
245         memset(&rem_addr,0, sizeof(rem_addr));
246         //-------------------------------------------------------------------
247         // TODO: not functioning - check it
248                 
249         if ((rem_addr.sin_addr.s_addr = inet_addr(server_addr)) == INADDR_NONE){
250            ph = gethostbyname(server_addr);
251            if (ph) 
252                    rem_addr.sin_addr = *((struct in_addr *)ph->h_addr);
253            else {
254                    perror("Unknown server"); 
255            }
256         }
257         
258         //------------------------------------------------------------------
259  
260         rem_addr.sin_family = AF_INET;
261         rem_addr.sin_addr.s_addr =  inet_addr(server_addr);
262         rem_addr.sin_port = htons(BASE_PORT + ac);
263         seqn = 0;
264         
265         period.tv_nsec = spoint->period_nsec;
266         period.tv_sec = 0;
267
268         while (1) {
269
270                 msg.seqn = seqn;
271                 msg.tos = ac_to_tos[ac];
272                 
273                 clock_gettime(CLOCK_MONOTONIC,&msg.send_timestamp);
274                 
275                 while (sendto(ac_sockfd[ac], &msg, sizeof(msg), 0,\
276                                 (struct sockaddr*)&rem_addr, sizeof(rem_addr)) < 0) {
277                                 if (errno == EINTR) continue;
278                                 perror("Error while sending.");
279                                 return NULL;
280                 }
281                 printf("%d", ac);
282                 fflush(stdout);
283
284                 seqn++;
285                 
286                 timespec_add(&time_to_wait,&msg.send_timestamp,&period);
287                 clock_gettime(CLOCK_MONOTONIC,&current_time);
288                 timespec_sub(&interval,&time_to_wait,&current_time);
289                 nanosleep(&interval,NULL);
290         }       
291 }
292
293 int main(int argc, char *argv[])
294 {
295         int ac, i, rc;
296         pthread_attr_t attr;
297         pthread_t thread;
298         int use_stdin = 0;
299         char opt;
300
301
302         while ((opt = getopt(argc, argv, "hs")) != -1) {
303                 switch (opt) {
304                         case 's':
305                                 use_stdin = 1;
306                                 break;
307                         default:
308                                 fprintf(stderr, "Usage: %s [ options ] server_addr\n", argv[0]);
309                                 fprintf(stderr, "options:  -s  read streams from stdin\n");
310                                 exit(1);
311                 }
312         }
313         if (optind < argc) {
314                 server_addr = argv[optind];
315         } else {
316                 fprintf(stderr, "Expected server address argument\n");
317                 exit(1);
318         }
319
320
321                 
322         memset(delay_stats,0, sizeof(delay_stats));     
323         pthread_attr_init(&attr);
324
325         if ((logfd = fopen(logfname,"w+")) == NULL) {
326                 fprintf(stderr,"Can not open %s\n", logfname);
327                 exit(1);
328         }
329                 
330
331         if (signal(SIGTERM, stopper) == SIG_ERR) {
332                 perror("Error in signal registration");
333                 exit(1);
334         }
335                 
336         if (signal(SIGINT, stopper) == SIG_ERR) {
337                 perror("Signal handler registration error");
338                 exit(1);
339         }
340         
341         /* create four receivers each per AC */
342         for (ac = AC_QUEUES - 1; ac >= 0; ac--) {
343                 ac_sockfd[ac] = create_ac_socket(ac);
344                 rc = pthread_create(&thread, &attr, receiver, (void*) ac);
345                 if (rc) {
346                         printf("Error while creating receiver %d\n",rc);
347                         return 1;
348                 }
349         }               
350                         
351         /* create sendpoints */
352         for (i = 0; i < nr_sepoints; i++) {
353                 rc = pthread_create(&thread, &attr, sender, (void*) &sepoint[i]);
354                 if (rc) {
355                         printf("Error while creating sender %d\n",rc);
356                         return 1;
357                 }
358         }
359         
360         while (1) {
361                 sleep(100000);
362         }
363         
364         return 0;
365 }