]> rtime.felk.cvut.cz Git - can-eth-gw.git/blob - ppc/user/canethgw.c
PowerPC benchmark
[can-eth-gw.git] / ppc / user / canethgw.c
1 #include <stdio.h>
2 #include <stdbool.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <unistd.h>
6 #include <netinet/in.h>
7 #include <signal.h>
8 #include <getopt.h>
9 #include <sys/ioctl.h>
10 #include <sys/types.h>
11 #include <sys/socket.h>
12 #include <arpa/inet.h>
13 #include <net/if.h>
14 #include <linux/can.h>
15 #include <linux/can/raw.h>
16 #include <poll.h>
17 #include "readif.h"
18 #include "cegwerr.h"
19
20 /**
21  * ToDo:
22  * [ ] print usage
23  */
24 //#define GW_DEBUG
25
26 /* powerpc encore */
27 #define AF_CAN 29
28 #define PF_CAN AF_CAN
29
30 #ifdef GW_DEBUG
31 #define printdbg(x) printf(x)
32 #else
33 #define printdbg(x)
34 #endif
35
36 #define GW_POLL_ETH 0
37 #define GW_POLL_CAN 1
38
39 #define GW_FLAG_SRC 1
40 #define GW_FLAG_DST 2
41 #define GW_FLAG_LISTEN 4
42 #define GW_FLAG_FILTER 8
43
44 unsigned int opt_flag = 0;
45 int sock_udp;
46 int sock_can;
47 struct can_filter flt;
48 struct sockaddr_in udp_dest;
49
50 /**
51  * filter_check
52  * @return true if frame should be dropped
53  */
54 bool filter_check( struct can_frame* cf )
55 {
56         if( !(opt_flag & GW_FLAG_FILTER) )
57                 return false;
58
59         return ( (cf->can_id & flt.can_mask) == (flt.can_id & flt.can_mask) );
60 }
61
62 void send_to_can()
63 {
64         struct can_frame cf;
65
66         read( sock_udp, &cf, sizeof(cf) );
67
68         if( filter_check( &cf ) )
69         {
70                 printdbg( "filter: drop\n" );
71                 return;
72         }
73         
74         write( sock_can, &cf, sizeof(cf) );
75         
76         printdbg( "eth -> can\n" );
77 }
78
79 void send_to_eth()
80 {
81         struct can_frame cf;
82
83         read( sock_can, &cf, sizeof(cf) );
84
85         if( filter_check( &cf ) )
86         {
87                 printdbg( "filter: drop\n" );
88                 return;
89         }
90
91         sendto( sock_udp, &cf, sizeof(cf), 0, (struct sockaddr*) &udp_dest, sizeof(udp_dest) );
92
93         printdbg( "can -> eth\n" );
94 }
95
96 void signal_exit( int sig )
97 {
98         close( sock_udp );
99         close( sock_can );
100         printf( "exiting\n" );
101
102         exit( 0 );
103 }
104
105 int main( int argc, char* argv[] )
106 {
107         struct sockaddr_in udp_addr;
108         struct sockaddr_can can_addr;
109         struct pollfd pfd[2];
110         int polret;
111         int opt;
112         struct cegw_if ceif[2], iflisten;
113         struct cegw_if* ifcan,* ifeth;
114
115         flt.can_id = 0;
116         flt.can_mask = 0;
117
118         struct option longopt[] =
119         {
120                 {"listen", 1, NULL, 'l'},
121                 { 0, 0, 0, 0 }
122         };
123
124         while( (opt = getopt_long( argc, argv, "s:d:l:f:i:", longopt, NULL )) != -1 )
125         {
126                 switch( opt )
127                 {
128                         case 's':
129                                 if( read_if(optarg, &ceif[0]) != 0 )
130                                 {
131                                         perr( "'-s'" );
132                                         return -1;
133                                 }
134                                 opt_flag |= GW_FLAG_SRC;
135                                 break;
136                         case 'd':
137                                 if( read_if(optarg, &ceif[1]) != 0 )
138                                 {
139                                         perr( "'-d'" );
140                                         return -1;
141                                 }
142                                 opt_flag |= GW_FLAG_DST;
143                                 break;
144                         case 'l':
145                                 if( read_if(optarg, &iflisten) != 0 )
146                                 {                               
147                                         perr( "'-l'" );
148                                         return -1;
149                                 }
150                                 if( iflisten.type != IF_ETH_UDP )
151                                 {
152                                         perr( "'-l' udp interface expected" );
153                                         return -1;
154                                 }
155                                 opt_flag |= GW_FLAG_LISTEN;
156                                 break;
157                         case 'f':
158                                 if( sscanf( optarg, "%x:%x", &flt.can_id,
159                                    &flt.can_mask ) != 2 ) 
160                                 {
161                                         perr( "bad filter format");
162                                         return -1;
163                                 }
164                                 opt_flag |= GW_FLAG_FILTER;
165                                 break;
166                         case '?':
167                                 return -1;
168                                 break;
169                 }
170         }
171
172         if( !((opt_flag & GW_FLAG_SRC) && (opt_flag & GW_FLAG_DST) 
173                 && (opt_flag & GW_FLAG_LISTEN)) )
174         {
175                 perr( "'s', 'd' and 'l' are mandatory" ); 
176                 /* ToDo: usage? */
177                 return -1;
178         }
179
180         if( !(ceif[0].type == IF_CAN     && ceif[1].type == IF_ETH_UDP) &&
181             !(ceif[0].type == IF_ETH_UDP && ceif[1].type == IF_CAN    )    )
182         {
183                 perr( "'-s' and '-d' should be different interface type" );
184                 return -1;
185         }
186
187         if( ceif[0].type == IF_CAN )
188         {
189                 ifcan = &ceif[0];
190                 ifeth = &ceif[1];
191         } else
192         {
193                 ifcan = &ceif[1];
194                 ifeth = &ceif[0];
195         }
196
197         signal( SIGINT, signal_exit );
198
199         /* prepare udp destination */
200         udp_dest.sin_family = AF_INET;
201         udp_dest.sin_port = htons(ifeth->eth.port);
202         udp_dest.sin_addr = ifeth->eth.ip;
203
204         /* udp socket */
205         sock_udp = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP );
206         if( sock_udp < 0 )
207         {
208                 perr( "udp socket creation failed" );
209                 return -1;
210         }
211
212         udp_addr.sin_family = AF_INET;
213         udp_addr.sin_port = htons(iflisten.eth.port);
214         udp_addr.sin_addr = iflisten.eth.ip;
215
216         if( bind( sock_udp, (struct sockaddr*) &udp_addr, sizeof(udp_addr) ) < 0 )
217         {
218                 perr( "udp socket binding failed" );
219                 close( sock_udp );
220                 return -1;
221         }
222
223         /* can socket */
224         sock_can = socket( PF_CAN, SOCK_RAW, CAN_RAW );
225         if( sock_can < 0 )
226         {
227                 perr( "can socket creation failed");
228                 close( sock_can );
229                 return -1;
230         }
231
232         can_addr.can_family = AF_CAN;
233         can_addr.can_ifindex = ifcan->can.ifindex;
234
235         if( bind( sock_can, (struct sockaddr*) &can_addr, sizeof(can_addr) ) < 0 )
236         {
237                 perr( "can socket binding failed" );
238                 return -1;
239         }
240
241         /* poll */
242         pfd[GW_POLL_ETH].fd = sock_udp;
243         pfd[GW_POLL_ETH].events = POLLIN | POLLPRI;
244         pfd[GW_POLL_ETH].revents = 0;
245
246         pfd[GW_POLL_CAN].fd = sock_can;
247         pfd[GW_POLL_CAN].events = POLLIN | POLLPRI;
248         pfd[GW_POLL_CAN].revents = 0;
249
250         printf( "canethgw is running\n" );
251
252         while( 1 )
253         {
254                 printdbg( "polling\n" );
255                 polret = poll( pfd, 2, -1 );
256                 if( polret < 0 )
257                 {
258                         perr( "poll(..) failed" );
259                         close( sock_udp );
260                         close( sock_can );
261                         return -1;
262                 }
263
264                 if( pfd[GW_POLL_ETH].revents != 0 )
265                 {
266                         send_to_can();
267                 }
268                 if( pfd[GW_POLL_CAN].revents != 0 )
269                 {
270                         send_to_eth();
271                 }
272
273                 pfd[GW_POLL_ETH].revents = 0;
274                 pfd[GW_POLL_CAN].revents = 0;
275         }
276
277         return 0;
278 }
279