3 #include <sys/socket.h>
4 #include <netinet/in.h>
25 #define PARAM_SERVERADDR 1
26 #define BASE_PORT 5100
28 #define MAX_SENDENDPOINTS 10
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};
41 int ac_sockfd[AC_QUEUES];
45 const char logfname[] = "delay_stats.dat";
49 struct timespec send_timestamp;
50 unsigned long int seqn;
51 unsigned char padding[MTU];
54 /* maximal traffic delay in ms */
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 {
70 int bandwidth_bps; /* bits per second */
73 #define MSEC (1000*1000)
74 #define Mbit (1000*1000)
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 },
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 },
95 unsigned int nr_sepoints = sizeof(sepoint)/sizeof(*sepoint);
101 unsigned sum[AC_QUEUES];
103 printf("Writing data to log file...\n");
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;
110 if (!allzeros) break;
112 if (maxi < 10000/GRANULARITY) maxi = 10000/GRANULARITY;
114 for (ac = 0; ac < AC_QUEUES; ac++) {
116 for ( i = 0 ; i < maxi; i++)
117 sum[ac]+=delay_stats[ac][i];
119 fprintf(stderr, "No response in AC %d\n", ac);
122 for (ac = 0; ac < AC_QUEUES; ac++) {
123 for ( i = 0 ; i < maxi; i++) {
125 val = (double)delay_stats[ac][i]*100.0 / sum[ac];
126 fprintf(logfd,"%f %lf\n", i*GRANULARITY/1000.0, val);
129 fprintf(logfd, "\n\n");
132 printf("Finished.\n");
139 void timespec_add (struct timespec *sum, const struct timespec *left,
140 const struct timespec *right)
142 sum->tv_sec = left->tv_sec + right->tv_sec;
143 sum->tv_nsec = left->tv_nsec + right->tv_nsec;
145 if (sum->tv_nsec >= 1000000000){
147 sum->tv_nsec -= 1000000000;
152 void timespec_sub (struct timespec *diff, const struct timespec *left,
153 const struct timespec *right)
155 diff->tv_sec = left->tv_sec - right->tv_sec;
156 diff->tv_nsec = left->tv_nsec - right->tv_nsec;
158 if (diff->tv_nsec < 0){
160 diff->tv_nsec += 1000000000;
164 int create_ac_socket(unsigned int ac)
167 unsigned int yes=1, tos;
170 if ((sockfd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
172 perror("Unable to open socket");
176 if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) {
177 perror("Unable to set socket");
182 //tos = ((AC_QUEUES - ac) *2 - 1)*32;
184 if (setsockopt(sockfd, SOL_IP, IP_TOS, &tos, sizeof(tos))) {
185 perror("Unable to set TOS");
194 void* receiver(void* queue)
197 struct sockaddr_in rem_addr;
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;
207 rem_addr_length = sizeof(rem_addr);
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");
215 clock_gettime(CLOCK_MONOTONIC,&recv_timestamp);
216 send_timestamp = msg.send_timestamp;
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;
222 if (trans_time_usec < MAX_DELAY_US)
223 delay_stats[ac][trans_time_usec/GRANULARITY]++;
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); */
235 void* sender(void* endpoint)
237 struct sockaddr_in rem_addr;
239 unsigned long int seqn;
240 struct timespec time_to_wait, current_time, period, interval;
242 struct send_endpoint* spoint = (struct send_endpoint*) endpoint;
245 memset(&rem_addr,0, sizeof(rem_addr));
246 //-------------------------------------------------------------------
247 // TODO: not functioning - check it
249 if ((rem_addr.sin_addr.s_addr = inet_addr(server_addr)) == INADDR_NONE){
250 ph = gethostbyname(server_addr);
252 rem_addr.sin_addr = *((struct in_addr *)ph->h_addr);
254 perror("Unknown server");
258 //------------------------------------------------------------------
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);
265 period.tv_nsec = spoint->period_nsec;
271 msg.tos = ac_to_tos[ac];
273 clock_gettime(CLOCK_MONOTONIC,&msg.send_timestamp);
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.");
286 timespec_add(&time_to_wait,&msg.send_timestamp,&period);
287 clock_gettime(CLOCK_MONOTONIC,¤t_time);
288 timespec_sub(&interval,&time_to_wait,¤t_time);
289 nanosleep(&interval,NULL);
293 int main(int argc, char *argv[])
302 while ((opt = getopt(argc, argv, "hs")) != -1) {
308 fprintf(stderr, "Usage: %s [ options ] server_addr\n", argv[0]);
309 fprintf(stderr, "options: -s read streams from stdin\n");
314 server_addr = argv[optind];
316 fprintf(stderr, "Expected server address argument\n");
322 memset(delay_stats,0, sizeof(delay_stats));
323 pthread_attr_init(&attr);
325 if ((logfd = fopen(logfname,"w+")) == NULL) {
326 fprintf(stderr,"Can not open %s\n", logfname);
331 if (signal(SIGTERM, stopper) == SIG_ERR) {
332 perror("Error in signal registration");
336 if (signal(SIGINT, stopper) == SIG_ERR) {
337 perror("Signal handler registration error");
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);
346 printf("Error while creating receiver %d\n",rc);
351 /* create sendpoints */
352 for (i = 0; i < nr_sepoints; i++) {
353 rc = pthread_create(&thread, &attr, sender, (void*) &sepoint[i]);
355 printf("Error while creating sender %d\n",rc);