]> rtime.felk.cvut.cz Git - can-eth-gw.git/blob - utils/cegwbench/cegwbench.c
dba10dda015b5dc206a27959dd5a8b1b34a4cb9a
[can-eth-gw.git] / utils / cegwbench / cegwbench.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <time.h>
6 #include <math.h>
7 #include <sys/socket.h>
8 #include <netinet/in.h>
9 #include <net/if.h>
10 #include <arpa/inet.h>
11 #include <linux/can.h>
12 #include <pthread.h>
13
14 /**
15  * ToDo:
16  * [ ] consider can timestamp
17  */
18
19 struct optdata
20 {
21         int n;
22 };
23
24 struct optdata d;
25 pthread_barrier_t barrier;
26 struct timespec* tx_time, * rx_time;
27
28 void* udp_recv( void* arg )
29 {
30         struct sockaddr_in sa_udp;
31         int udp_sock;
32         struct can_frame cf;
33         int i;
34
35         sa_udp.sin_family = AF_INET;
36         sa_udp.sin_port = htons( 10502 );
37         inet_aton( "127.0.0.1", &sa_udp.sin_addr );
38
39         udp_sock = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP );
40         if( udp_sock < 0 )
41         {
42                 fprintf( stderr, "error: udp socket creation failed\n" );
43                 return NULL;
44         }
45
46         if( bind(udp_sock, (struct sockaddr*)&sa_udp, sizeof(sa_udp)) != 0 )
47         {
48                 fprintf( stderr, "error: udp socket binding failed\n" );
49                 return NULL;
50         }
51
52         pthread_barrier_wait( &barrier );
53
54         /* recv */
55         for( i=0; i<d.n; i++ )
56         {
57                 recvfrom( udp_sock, &cf, sizeof(cf), 0, NULL, 0 );
58                 clock_gettime( CLOCK_REALTIME, &rx_time[cf.data[0]] );
59                 printf( "recv: (id=%d)%u\n", cf.can_id, cf.data[0] );
60         }
61
62         close( udp_sock );
63         return NULL;
64 }
65
66 int timespec_subtract( struct timespec *result, struct timespec *x, struct timespec *yy )
67 {
68         struct timespec ylocal = *yy, *y = &ylocal;
69         /* Perform the carry for the later subtraction by updating Y. */
70         if( x->tv_nsec < y->tv_nsec )
71         {
72                 int nsec = (y->tv_nsec - x->tv_nsec) / 1000000000 + 1;
73                 y->tv_nsec -= 1000000000 * nsec;
74                 y->tv_sec += nsec;
75                 }
76         if (x->tv_nsec - y->tv_nsec > 1000000000) {
77                 int nsec = (x->tv_nsec - y->tv_nsec) / 1000000000;
78                 y->tv_nsec += 1000000000 * nsec;
79                 y->tv_sec -= nsec;
80         }
81
82         /* Compute the time remaining to wait.
83          *         `tv_nsec' is certainly positive. */
84         result->tv_sec = x->tv_sec - y->tv_sec;
85         result->tv_nsec = x->tv_nsec - y->tv_nsec;
86         /* Return 1 if result is negative. */
87         return x->tv_sec < y->tv_sec;
88 }
89
90 int main( int argc, char* argv[] )
91 {
92         char opt;
93         struct sockaddr_can sa_can;
94         struct can_frame cf;
95         int can_sock;
96         pthread_t thr;
97         float mean = 0;
98         float time;
99         struct timespec res;
100         int i;
101
102         while( 1 )
103         {
104                 opt = getopt( argc, argv, "n:" );
105                 if( opt == -1 )
106                         break;
107                 switch( opt )
108                 {
109                         case 'n':
110                                 d.n = atoi( optarg );
111                                 break;
112                         case '?':
113                                 return -1;
114                                 break;
115                 }
116         }
117
118         tx_time = malloc( d.n*sizeof(struct timespec) );
119         rx_time = malloc( d.n*sizeof(struct timespec) );
120
121         pthread_barrier_init( &barrier, NULL, 2 );
122         pthread_create( &thr, NULL, udp_recv, NULL  );
123
124         sa_can.can_family = AF_CAN;
125         sa_can.can_ifindex = if_nametoindex( "vcan0" );
126         
127         can_sock = socket( PF_CAN, SOCK_RAW, CAN_RAW );
128         if( can_sock < 0 )
129         {
130                 fprintf( stderr, "error: can socket creation failed\n" );
131                 return -1;
132         }
133
134         if( bind(can_sock, (struct sockaddr*)&sa_can, sizeof(sa_can)) != 0 )
135         {
136                 fprintf( stderr, "error: can socket binding failed\n" );
137                 return -1;
138         }
139
140         pthread_barrier_wait( &barrier );
141
142         /* send  */
143         for( i=0; i<d.n; i++ )
144         {
145                 //memset( &cf, 0, sizeof(cf) );
146                 cf.can_id = i;
147                 cf.can_dlc = 8;
148                 cf.data[0] = i;
149                 int ret = sendto( can_sock, &cf, sizeof(cf), 0, (struct sockaddr*)&sa_can, sizeof(sa_can) );
150                 clock_gettime( CLOCK_REALTIME, &tx_time[cf.data[0]] );
151                 printf( "sending(%d)\n", ret );
152         }
153
154         close( can_sock ); /* shutdown? */
155         pthread_join( thr, NULL );
156
157         /* results */
158         for( i=0; i<d.n; i++ )
159         {
160                 if( timespec_subtract( &res, &rx_time[i], &tx_time[i] ) == 0 )
161                 {
162                         time = res.tv_sec*1000000000.0f + (float)res.tv_nsec;
163                         mean += time;
164                         printf( "transfer time:%fns\n", time );
165                 } else
166                 {
167                         printf( "transfer time: irrelevant\n" );
168                 }
169         }
170         mean /= ++i;
171         printf( "average: %fns\n", mean );
172
173         free( tx_time );
174         free( rx_time );
175 //      clock_gettime( CLOCK_REALTIME, &tx_time );
176
177         return 0;
178 }
179