8 #include <sys/socket.h>
9 #include <netinet/in.h>
11 #include <arpa/inet.h>
12 #include <linux/can.h>
19 * [ ] consider can timestamp
22 #define BENCH_FLAG_N 1
23 #define BENCH_FLAG_SRC 2
24 #define BENCH_FLAG_DST 4
33 int can_sock_create( int ifindex );
34 int udp_sock_create( struct in_addr ip, unsigned int port );
41 struct cegw_if ceif[2]; /* 0 -> src, 1 -> dst */
45 pthread_barrier_t barrier;
46 struct timespec* tx_time, * rx_time;
48 void* thr_recv( void* arg )
54 if( d.ceif[1].type == IF_CAN )
55 sock = can_sock_create( d.ceif[1].can.ifindex );
57 sock = udp_sock_create( d.ceif[1].eth.ip, d.ceif[1].eth.port );
61 pthread_barrier_wait( &barrier );
64 for( i=0; i<d.n; i++ )
66 recvfrom( sock, &cf, sizeof(cf), 0, NULL, 0 );
67 clock_gettime( CLOCK_REALTIME, &rx_time[cf.data[0]] );
68 printf( "recv: (id=%d)%u\n", cf.can_id, cf.data[0] );
69 if( d.mode == BENCH_MODE_ONEATTIME )
71 pthread_barrier_wait( &barrier );
79 int timespec_subtract( struct timespec *result, struct timespec *x, struct timespec *yy )
81 struct timespec ylocal = *yy, *y = &ylocal;
82 /* Perform the carry for the later subtraction by updating Y. */
83 if( x->tv_nsec < y->tv_nsec )
85 int nsec = (y->tv_nsec - x->tv_nsec) / 1000000000 + 1;
86 y->tv_nsec -= 1000000000 * nsec;
89 if (x->tv_nsec - y->tv_nsec > 1000000000)
91 int nsec = (x->tv_nsec - y->tv_nsec) / 1000000000;
92 y->tv_nsec += 1000000000 * nsec;
96 /* Compute the time remaining to wait.
97 * `tv_nsec' is certainly positive. */
98 result->tv_sec = x->tv_sec - y->tv_sec;
99 result->tv_nsec = x->tv_nsec - y->tv_nsec;
100 /* Return 1 if result is negative. */
101 return x->tv_sec < y->tv_sec;
104 int udp_sock_create( struct in_addr ip, unsigned int port )
106 struct sockaddr_in addr_udp;
109 addr_udp.sin_family = AF_INET;
110 addr_udp.sin_port = htons( port );
111 addr_udp.sin_addr.s_addr = INADDR_ANY;
113 udp_sock = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP );
116 fprintf( stderr, "error: udp socket creation failed\n" );
120 if( bind(udp_sock, (struct sockaddr*)&addr_udp, sizeof(addr_udp)) != 0 )
122 fprintf( stderr, "error: udp socket binding failed\n" );
131 * @return can socket fd, or -1 on failure
133 int can_sock_create( int ifindex )
136 struct sockaddr_can addr_can;
138 addr_can.can_family = AF_CAN;
139 addr_can.can_ifindex = ifindex;
141 can_sock = socket( PF_CAN, SOCK_RAW, CAN_RAW );
144 fprintf( stderr, "error: can socket creation failed\n" );
148 if( bind(can_sock, (struct sockaddr*)&addr_can, sizeof(addr_can)) != 0 )
150 fprintf( stderr, "error: can socket binding failed\n" );
157 int read_mode( char* in )
159 if( strcmp( in, "asap" ) == 0 )
160 return BENCH_MODE_ASAP;
161 if( strcmp( in, "oneattime") == 0 )
162 return BENCH_MODE_ONEATTIME;
163 if( strcmp( in, "period" ) == 0 )
164 return BENCH_MODE_PERIOD;
166 return BENCH_MODE_UNDEF;
169 int main( int argc, char* argv[] )
182 d.mode = BENCH_MODE_ASAP;
184 struct option longopt[] =
186 { "mode", 0, NULL, 'm' },
192 opt = getopt( argc, argv, "s:d:m:n:" );
198 d.optflag |= BENCH_FLAG_SRC;
199 if( read_if( optarg, &d.ceif[0] ) != 0 )
206 d.optflag |= BENCH_FLAG_DST;
207 if( read_if( optarg, &d.ceif[1] ) )
214 tmp = read_mode( optarg );
215 if( tmp == BENCH_MODE_UNDEF )
217 perr( "benchmarking mode unknown" );
223 d.optflag |= BENCH_FLAG_N;
224 d.n = atoi( optarg );
233 /* '-n' option is mandatory and its value is >0 */
234 if( d.optflag & BENCH_FLAG_N )
238 perr( "'-n' should be at least 1." );
242 perr( "'-n' is mandatory." );
246 /* '-s' and '-d' should be defined and different iftype */
247 if( (d.optflag & BENCH_FLAG_SRC) && (d.optflag & BENCH_FLAG_DST) )
249 if( !(d.ceif[0].type == IF_CAN && d.ceif[1].type == IF_ETH_UDP) &&
250 !(d.ceif[0].type == IF_ETH_UDP && d.ceif[1].type == IF_CAN ) )
252 perr( "'-s' and '-d' should be different interface type." );
257 perr( "'-s' and '-d' should be defined." );
261 tx_time = malloc( d.n*sizeof(struct timespec) );
262 rx_time = malloc( d.n*sizeof(struct timespec) );
264 pthread_barrier_init( &barrier, NULL, 2 );
265 pthread_create( &thr, NULL, thr_recv, NULL );
268 struct sockaddr* addr;
269 struct sockaddr_can addr_can;
270 struct sockaddr_in addr_udp;
273 if( d.ceif[0].type == IF_CAN )
275 sock = socket( PF_CAN, SOCK_RAW, CAN_RAW );
276 addr_can.can_family = AF_CAN;
277 addr_can.can_ifindex = d.ceif[0].can.ifindex;
278 addr = (struct sockaddr*)&addr_can;
279 addr_size = sizeof( addr_can );
283 sock = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP );
284 addr_udp.sin_family = AF_INET;
285 addr_udp.sin_addr = d.ceif[0].eth.ip;
286 addr_udp.sin_port = htons( d.ceif[0].eth.port );
287 addr = (struct sockaddr*)&addr_udp;
288 addr_size = sizeof( addr_udp );
290 if( sock < 0 ) /* ToDo: ? */
293 pthread_barrier_wait( &barrier );
296 for( i=0; i<d.n; i++ )
302 clock_gettime( CLOCK_REALTIME, &tx_time[cf.data[0]] );
303 ret = sendto( sock, &cf, sizeof(cf), 0, addr, addr_size );
304 printf( "sending(%d)\n", ret );
305 if( d.mode == BENCH_MODE_ONEATTIME )
307 pthread_barrier_wait( &barrier );
311 close( sock ); /* ToDo: shutdown? */
312 pthread_join( thr, NULL );
316 for( i=0; i<d.n; i++ )
318 if( timespec_subtract( &res, &rx_time[i], &tx_time[i] ) == 0 )
320 time = res.tv_sec*1000000000.0f + (float)res.tv_nsec;
323 printf( "transfer time:%fns\n", time );
326 printf( "transfer time: irrelevant\n" );
329 mean /= tn; /* ToDo: did they arrive all? */
330 printf( "average: %fns\n", mean );
332 pthread_barrier_destroy( &barrier );