1 /* Copyright 2005 Renzo Davoli VDE-2
2 * Licensed under the GPL
3 * --pidfile/-p and cleanup management by Mattia Belletti.
4 * some code remains from uml_switch Copyright 2001, 2002 Jeff Dike and others
5 * Modified by Ludovico Gardenghi 2005
17 #include <sys/types.h>
25 #include <vdecommon.h>
27 #include "../vde_switch/switch.h"
37 static struct swmodule
*swmh
;
40 unsigned char switchmac
[ETH_ALEN
];
41 unsigned int priority
=DEFAULT_PRIORITY
;
43 /* static int hash_size=INIT_HASH_SIZE; */
44 /* static int numports=INIT_NUMPORTS; */
47 static void recaddswm(struct swmodule
**p
,struct swmodule
*new)
49 struct swmodule
*this=*p
;
53 recaddswm(&(this->next
),new);
56 void add_swm(struct swmodule
*new)
58 static int lastlwmtag
;
59 new->swmtag
= ++lastlwmtag
;
60 if (new != NULL
&& new->swmtag
!= 0) {
66 static void recdelswm(struct swmodule
**p
,struct swmodule
*old
)
68 struct swmodule
*this=*p
;
73 recdelswm(&(this->next
),old
);
77 void del_swm(struct swmodule
*old
)
93 static struct pollfd
*fds
= NULL
;
94 static struct pollplus
**fdpp
= NULL
;
96 static int maxfds
= 0;
98 static struct swmodule
**fdtypes
;
102 #define PRIOFLAG 0x80
103 #define TYPEMASK 0x7f
104 #define ISPRIO(X) ((X) & PRIOFLAG)
106 #define TYPE2MGR(X) (fdtypes[((X) & TYPEMASK)])
108 unsigned char add_type(struct swmodule
*mgr
,int prio
)
111 if(ntypes
==maxtypes
) {
112 maxtypes
= maxtypes
? 2 * maxtypes
: 8;
113 if (maxtypes
> PRIOFLAG
) {
114 printlog(LOG_ERR
,"too many file types");
117 if((fdtypes
= realloc(fdtypes
, maxtypes
* sizeof(struct swmodule
*))) == NULL
){
118 printlog(LOG_ERR
,"realloc fdtypes %s",strerror(errno
));
121 memset(fdtypes
+ntypes
,0,sizeof(struct swmodule
*) * maxtypes
-ntypes
);
124 for(i
=0; fdtypes
[i
] != NULL
; i
++)
128 return i
| ((prio
!= 0)?PRIOFLAG
:0);
131 void del_type(unsigned char type
)
139 void add_fd(int fd
,unsigned char type
,int arg
)
143 /* enlarge fds and g_fdsdata array if needed */
145 maxfds
= maxfds
? 2 * maxfds
: 8;
146 if((fds
= realloc(fds
, maxfds
* sizeof(struct pollfd
))) == NULL
){
147 printlog(LOG_ERR
,"realloc fds %s",strerror(errno
));
150 if((fdpp
= realloc(fdpp
, maxfds
* sizeof(struct pollplus
*))) == NULL
){
151 printlog(LOG_ERR
,"realloc pollplus %s",strerror(errno
));
156 fds
[nfds
]=fds
[nprio
];
157 fdpp
[nfds
]=fdpp
[nprio
];
162 if((fdpp
[index
]=malloc(sizeof(struct pollplus
))) == NULL
) {
163 printlog(LOG_ERR
,"realloc pollplus elem %s",strerror(errno
));
168 p
->events
= POLLIN
| POLLHUP
;
169 fdpp
[index
]->type
=type
;
170 fdpp
[index
]->arg
=arg
;
174 static void file_cleanup(void)
177 for(i
= 0; i
< nfds
; i
++)
178 TYPE2MGR(fdpp
[i
]->type
)->cleanup(fdpp
[i
]->type
,fds
[i
].fd
,fdpp
[i
]->arg
);
181 void remove_fd(int fd
)
185 for(i
= 0; i
< nfds
; i
++){
186 if(fds
[i
].fd
== fd
) break;
189 printlog(LOG_WARNING
,"remove_fd : Couldn't find descriptor %d", fd
);
191 struct pollplus
*old
=fdpp
[i
];
192 TYPE2MGR(fdpp
[i
]->type
)->cleanup(fdpp
[i
]->type
,fds
[i
].fd
,fdpp
[i
]->arg
);
193 if (ISPRIO(fdpp
[i
]->type
)) nprio
--;
194 memmove(&fds
[i
], &fds
[i
+ 1], (maxfds
- i
- 1) * sizeof(struct pollfd
));
195 memmove(&fdpp
[i
], &fdpp
[i
+ 1], (maxfds
- i
- 1) * sizeof(struct pollplus
*));
201 static void main_loop()
207 n
=poll(fds
,nfds
,packetq_timeout
);
214 printlog(LOG_WARNING
,"poll %s",strerror(errno
));
216 for(i
= 0; /*i < nfds &&*/ n
>0; i
++){
217 if(fds
[i
].revents
!= 0) {
218 register int prenfds
=nfds
;
220 fdpp
[i
]->timestamp
=now
;
221 TYPE2MGR(fdpp
[i
]->type
)->handle_input(fdpp
[i
]->type
,fds
[i
].fd
,fds
[i
].revents
,&(fdpp
[i
]->arg
));
222 if (nfds
!=prenfds
) /* the current fd has been deleted */
223 break; /* PERFORMANCE it is faster returning to poll */
225 /* optimization: most used descriptors migrate to the head of the poll array */
229 if (i
< nfds
&& i
> 0 && i
!= nprio
) {
230 register int i_1
=i
-1;
231 if (fdpp
[i
]->timestamp
> fdpp
[i_1
]->timestamp
) {
233 struct pollplus
*tfdpp
;
234 tfds
=fds
[i
];fds
[i
]=fds
[i_1
];fds
[i_1
]=tfds
;
235 tfdpp
=fdpp
[i
];fdpp
[i
]=fdpp
[i_1
];fdpp
[i_1
]=tfdpp
;
242 if (packetq_timeout
> 0)
249 /* starting/ending routines, main_loop, main*/
250 #define HASH_TABLE_SIZE_ARG 0x100
251 #define MACADDR_ARG 0x101
252 #define PRIORITY_ARG 0x102
254 static void Usage(void) {
257 "Usage: vde_switch [OPTIONS]\n"
258 "Runs a VDE switch.\n"
260 " -h, --help Display this help and exit\n"
261 " -v, --version Display informations on version and exit\n"
263 for(p
=swmh
;p
!= NULL
;p
=p
->next
)
264 if (p
->usage
!= NULL
)
268 "Report bugs to "PACKAGE_BUGREPORT
"\n"
273 static void version(void)
276 "VDE " PACKAGE_VERSION
"\n"
277 "Copyright 2003,2004,2005,2006,2007,2008 Renzo Davoli\n"
278 "VDE comes with NO WARRANTY, to the extent permitted by law.\n"
279 "You may redistribute copies of VDE under the terms of the\n"
280 "GNU General Public License v2.\n"
281 "For more information about these matters, see the files\n"
283 exit(check_kernel_support());
286 static struct option
*optcpy(struct option
*tgt
, struct option
*src
, int n
, int tag
)
289 memcpy(tgt
,src
,sizeof(struct option
) * n
);
291 tgt
[i
].val
=(tgt
[i
].val
& 0xffff) | tag
<< 16;
296 static int parse_globopt(int c
, char *optarg
)
312 static void parse_args(int argc
, char **argv
)
314 struct swmodule
*swmp
;
315 struct option
*long_options
;
317 static struct option global_options
[] = {
319 {"version", 0, 0, 'v'},
321 static struct option optail
= {0,0,0,0};
322 #define N_global_options (sizeof(global_options)/sizeof(struct option))
324 int totopts
=N_global_options
+1;
326 for(swmp
=swmh
;swmp
!= NULL
;swmp
=swmp
->next
)
327 totopts
+= swmp
->swmnopts
;
328 long_options
=malloc(totopts
* sizeof(struct option
));
329 optstring
=malloc(2 * totopts
* sizeof(char));
330 if (long_options
== NULL
|| optstring
==NULL
)
332 { /* fill-in the long_options fields */
336 struct option
*opp
=long_options
;
337 opp
=optcpy(opp
,global_options
,N_global_options
,0);
338 for(swmp
=swmh
;swmp
!= NULL
;swmp
=swmp
->next
)
339 opp
=optcpy(opp
,swmp
->swmopts
,swmp
->swmnopts
,swmp
->swmtag
);
340 optcpy(opp
,&optail
,1,0);
341 for (i
=0;i
<totopts
-1;i
++)
343 int val
=long_options
[i
].val
& 0xffff;
344 if(val
> ' ' && val
<= '~' && val
!= last
)
347 if(long_options
[i
].has_arg
) *os
++=':';
354 int option_index
= 0;
357 c
= GETOPT_LONG (argc
, argv
, optstring
,
358 long_options
, &option_index
);
361 c
=parse_globopt(c
,optarg
);
362 for(swmp
=swmh
;swmp
!= NULL
&& c
!=0;swmp
=swmp
->next
) {
363 if (swmp
->parseopt
!= NULL
) {
365 c
=swmp
->parseopt(c
,optarg
);
366 else if ((c
>> 16) == swmp
->swmtag
)
367 swmp
->parseopt(c
& 0xffff,optarg
),c
=0;
378 static void init_mods(void)
380 struct swmodule
*swmp
;
382 /* Keep track of the initial cwd */
383 int cwfd
= open(".", O_RDONLY
);
385 for(swmp
=swmh
;swmp
!= NULL
;swmp
=swmp
->next
)
386 if (swmp
->init
!= NULL
)
390 /* Restore cwd so each module will be initialized with the
391 * original cwd also if the previous one changed it. */
392 if(fchdir(cwfd
) < 0) {
393 printlog(LOG_WARNING
,"Error restoring original working dir");
399 static void cleanup(void)
401 struct swmodule
*swmp
;
403 for(swmp
=swmh
;swmp
!= NULL
;swmp
=swmp
->next
)
404 if (swmp
->cleanup
!= NULL
)
405 swmp
->cleanup(0,-1,-1);
408 static void sig_handler(int sig
)
410 printlog(LOG_ERR
,"Caught signal %d, cleaning up and exiting", sig
);
412 signal(sig
, SIG_DFL
);
419 static void setsighandlers()
421 /* setting signal handlers.
422 * sets clean termination for SIGHUP, SIGINT and SIGTERM, and simply
423 * ignores all the others signals which could cause termination. */
424 struct { int sig
; const char *name
; int ignore
; } signals
[] = {
425 { SIGHUP
, "SIGHUP", 0 },
426 { SIGINT
, "SIGINT", 0 },
427 { SIGPIPE
, "SIGPIPE", 1 },
428 { SIGALRM
, "SIGALRM", 1 },
429 { SIGTERM
, "SIGTERM", 0 },
430 { SIGUSR1
, "SIGUSR1", 1 },
431 { SIGUSR2
, "SIGUSR2", 1 },
432 { SIGPROF
, "SIGPROF", 1 },
433 { SIGVTALRM
, "SIGVTALRM", 1 },
435 { SIGPOLL
, "SIGPOLL", 1 },
437 { SIGSTKFLT
, "SIGSTKFLT", 1 },
439 { SIGIO
, "SIGIO", 1 },
440 { SIGPWR
, "SIGPWR", 1 },
442 { SIGUNUSED
, "SIGUNUSED", 1 },
446 { SIGXCPU
, "SIGXCPU", 1 },
447 { SIGXFSZ
, "SIGXFSZ", 1 },
453 for(i
= 0; signals
[i
].sig
!= 0; i
++)
454 if(signal(signals
[i
].sig
,
455 signals
[i
].ignore
? SIG_IGN
: sig_handler
) < 0)
456 printlog(LOG_ERR
,"Setting handler for %s: %s", signals
[i
].name
,
460 static void start_modules(void);
462 int main(int argc
, char **argv
)
464 starting_time
=time(NULL
);
466 parse_args(argc
,argv
);
475 /* modules: module references are only here! */
476 static void start_modules(void)
478 void start_datasock(void);
479 void start_consmgmt(void);