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"
32 static struct swmodule
*swmh
;
35 unsigned char switchmac
[ETH_ALEN
];
36 unsigned int priority
=DEFAULT_PRIORITY
;
38 /* static int hash_size=INIT_HASH_SIZE; */
39 /* static int numports=INIT_NUMPORTS; */
42 static void recaddswm(struct swmodule
**p
,struct swmodule
*new)
44 struct swmodule
*this=*p
;
48 recaddswm(&(this->next
),new);
51 void add_swm(struct swmodule
*new)
53 static int lastlwmtag
;
54 new->swmtag
= ++lastlwmtag
;
55 if (new != NULL
&& new->swmtag
!= 0) {
61 static void recdelswm(struct swmodule
**p
,struct swmodule
*old
)
63 struct swmodule
*this=*p
;
68 recdelswm(&(this->next
),old
);
72 void del_swm(struct swmodule
*old
)
88 static struct pollfd
*fds
= NULL
;
89 static struct pollplus
**fdpp
= NULL
;
91 static int maxfds
= 0;
93 static struct swmodule
**fdtypes
;
99 #define ISPRIO(X) ((X) & PRIOFLAG)
101 #define TYPE2MGR(X) (fdtypes[((X) & TYPEMASK)])
103 unsigned char add_type(struct swmodule
*mgr
,int prio
)
106 if(ntypes
==maxtypes
) {
107 maxtypes
= maxtypes
? 2 * maxtypes
: 8;
108 if (maxtypes
> PRIOFLAG
) {
109 printlog(LOG_ERR
,"too many file types");
112 if((fdtypes
= realloc(fdtypes
, maxtypes
* sizeof(struct swmodule
*))) == NULL
){
113 printlog(LOG_ERR
,"realloc fdtypes %s",strerror(errno
));
116 memset(fdtypes
+ntypes
,0,sizeof(struct swmodule
*) * maxtypes
-ntypes
);
119 for(i
=0; fdtypes
[i
] != NULL
; i
++)
123 return i
| ((prio
!= 0)?PRIOFLAG
:0);
126 void del_type(unsigned char type
)
134 void add_fd(int fd
,unsigned char type
,void *private_data
)
138 /* enlarge fds and g_fdsdata array if needed */
140 maxfds
= maxfds
? 2 * maxfds
: 8;
141 if((fds
= realloc(fds
, maxfds
* sizeof(struct pollfd
))) == NULL
){
142 printlog(LOG_ERR
,"realloc fds %s",strerror(errno
));
145 if((fdpp
= realloc(fdpp
, maxfds
* sizeof(struct pollplus
*))) == NULL
){
146 printlog(LOG_ERR
,"realloc pollplus %s",strerror(errno
));
151 fds
[nfds
]=fds
[nprio
];
152 fdpp
[nfds
]=fdpp
[nprio
];
157 if((fdpp
[index
]=malloc(sizeof(struct pollplus
))) == NULL
) {
158 printlog(LOG_ERR
,"realloc pollplus elem %s",strerror(errno
));
163 p
->events
= POLLIN
| POLLHUP
;
164 fdpp
[index
]->type
=type
;
165 fdpp
[index
]->private_data
=private_data
;
169 static void file_cleanup(void)
172 for(i
= 0; i
< nfds
; i
++)
173 TYPE2MGR(fdpp
[i
]->type
)->cleanup(fdpp
[i
]->type
,fds
[i
].fd
,fdpp
[i
]->private_data
);
176 void remove_fd(int fd
)
180 for(i
= 0; i
< nfds
; i
++){
181 if(fds
[i
].fd
== fd
) break;
184 printlog(LOG_WARNING
,"remove_fd : Couldn't find descriptor %d", fd
);
186 struct pollplus
*old
=fdpp
[i
];
187 TYPE2MGR(fdpp
[i
]->type
)->cleanup(fdpp
[i
]->type
,fds
[i
].fd
,fdpp
[i
]->private_data
);
188 if (ISPRIO(fdpp
[i
]->type
)) nprio
--;
189 memmove(&fds
[i
], &fds
[i
+ 1], (maxfds
- i
- 1) * sizeof(struct pollfd
));
190 memmove(&fdpp
[i
], &fdpp
[i
+ 1], (maxfds
- i
- 1) * sizeof(struct pollplus
*));
196 static void main_loop()
205 printlog(LOG_WARNING
,"poll %s",strerror(errno
));
207 for(i
= 0; /*i < nfds &&*/ n
>0; i
++){
208 if(fds
[i
].revents
!= 0) {
211 fdpp
[i
]->timestamp
=now
;
212 TYPE2MGR(fdpp
[i
]->type
)->handle_io(fdpp
[i
]->type
,fds
[i
].fd
,fds
[i
].revents
,fdpp
[i
]->private_data
);
213 if (nfds
!=prenfds
) /* the current fd has been deleted */
214 break; /* PERFORMANCE it is faster returning to poll */
216 /* optimization: most used descriptors migrate to the head of the poll array */
222 /* starting/ending routines, main_loop, main*/
223 #define HASH_TABLE_SIZE_ARG 0x100
224 #define MACADDR_ARG 0x101
225 #define PRIORITY_ARG 0x102
227 static void Usage(void) {
230 "Usage: vde_switch [OPTIONS]\n"
231 "Runs a VDE switch.\n"
233 " -h, --help Display this help and exit\n"
234 " -v, --version Display informations on version and exit\n"
236 for(p
=swmh
;p
!= NULL
;p
=p
->next
)
237 if (p
->usage
!= NULL
)
241 "Report bugs to "PACKAGE_BUGREPORT
"\n"
246 static void version(void)
249 "VDE " PACKAGE_VERSION
"\n"
250 "Copyright 2003,2004,2005,2006,2007,2008 Renzo Davoli\n"
251 "VDE comes with NO WARRANTY, to the extent permitted by law.\n"
252 "You may redistribute copies of VDE under the terms of the\n"
253 "GNU General Public License v2.\n"
254 "For more information about these matters, see the files\n"
256 exit(check_kernel_support());
259 static struct option
*optcpy(struct option
*tgt
, struct option
*src
, int n
, int tag
)
262 memcpy(tgt
,src
,sizeof(struct option
) * n
);
264 tgt
[i
].val
=(tgt
[i
].val
& 0xffff) | tag
<< 16;
269 static int parse_globopt(int c
, char *optarg
)
285 static void parse_args(int argc
, char **argv
)
287 struct swmodule
*swmp
;
288 struct option
*long_options
;
290 static struct option global_options
[] = {
292 {"version", 0, 0, 'v'},
294 static struct option optail
= {0,0,0,0};
295 #define N_global_options (sizeof(global_options)/sizeof(struct option))
297 int totopts
=N_global_options
+1;
299 for(swmp
=swmh
;swmp
!= NULL
;swmp
=swmp
->next
)
300 totopts
+= swmp
->swmnopts
;
301 long_options
=malloc(totopts
* sizeof(struct option
));
302 optstring
=malloc(2 * totopts
* sizeof(char));
303 if (long_options
== NULL
|| optstring
==NULL
)
305 { /* fill-in the long_options fields */
309 struct option
*opp
=long_options
;
310 opp
=optcpy(opp
,global_options
,N_global_options
,0);
311 for(swmp
=swmh
;swmp
!= NULL
;swmp
=swmp
->next
)
312 opp
=optcpy(opp
,swmp
->swmopts
,swmp
->swmnopts
,swmp
->swmtag
);
313 optcpy(opp
,&optail
,1,0);
314 for (i
=0;i
<totopts
-1;i
++)
316 int val
=long_options
[i
].val
& 0xffff;
317 if(val
> ' ' && val
<= '~' && val
!= last
)
320 if(long_options
[i
].has_arg
) *os
++=':';
327 int option_index
= 0;
330 c
= GETOPT_LONG (argc
, argv
, optstring
,
331 long_options
, &option_index
);
334 c
=parse_globopt(c
,optarg
);
335 for(swmp
=swmh
;swmp
!= NULL
&& c
!=0;swmp
=swmp
->next
) {
336 if (swmp
->parseopt
!= NULL
) {
338 c
=swmp
->parseopt(c
,optarg
);
339 else if ((c
>> 16) == swmp
->swmtag
)
340 swmp
->parseopt(c
& 0xffff,optarg
),c
=0;
351 static void init_mods(void)
353 struct swmodule
*swmp
;
355 /* Keep track of the initial cwd */
356 int cwfd
= open(".", O_RDONLY
);
358 for(swmp
=swmh
;swmp
!= NULL
;swmp
=swmp
->next
)
359 if (swmp
->init
!= NULL
)
363 /* Restore cwd so each module will be initialized with the
364 * original cwd also if the previous one changed it. */
365 if(fchdir(cwfd
) < 0) {
366 printlog(LOG_WARNING
,"Error restoring original working dir");
372 static void cleanup(void)
374 struct swmodule
*swmp
;
376 for(swmp
=swmh
;swmp
!= NULL
;swmp
=swmp
->next
)
377 if (swmp
->cleanup
!= NULL
)
378 swmp
->cleanup(0,-1,NULL
);
381 static void sig_handler(int sig
)
383 printlog(LOG_ERR
,"Caught signal %d, cleaning up and exiting", sig
);
385 signal(sig
, SIG_DFL
);
392 static void setsighandlers()
394 /* setting signal handlers.
395 * sets clean termination for SIGHUP, SIGINT and SIGTERM, and simply
396 * ignores all the others signals which could cause termination. */
397 struct { int sig
; const char *name
; int ignore
; } signals
[] = {
398 { SIGHUP
, "SIGHUP", 0 },
399 { SIGINT
, "SIGINT", 0 },
400 { SIGPIPE
, "SIGPIPE", 1 },
401 { SIGALRM
, "SIGALRM", 1 },
402 { SIGTERM
, "SIGTERM", 0 },
403 { SIGUSR1
, "SIGUSR1", 1 },
404 { SIGUSR2
, "SIGUSR2", 1 },
405 { SIGPROF
, "SIGPROF", 1 },
406 { SIGVTALRM
, "SIGVTALRM", 1 },
408 { SIGPOLL
, "SIGPOLL", 1 },
410 { SIGSTKFLT
, "SIGSTKFLT", 1 },
412 { SIGIO
, "SIGIO", 1 },
413 { SIGPWR
, "SIGPWR", 1 },
415 { SIGUNUSED
, "SIGUNUSED", 1 },
419 { SIGXCPU
, "SIGXCPU", 1 },
420 { SIGXFSZ
, "SIGXFSZ", 1 },
426 for(i
= 0; signals
[i
].sig
!= 0; i
++)
427 if(signal(signals
[i
].sig
,
428 signals
[i
].ignore
? SIG_IGN
: sig_handler
) < 0)
429 printlog(LOG_ERR
,"Setting handler for %s: %s", signals
[i
].name
,
433 static void start_modules(void);
435 int main(int argc
, char **argv
)
437 starting_time
=time(NULL
);
439 parse_args(argc
,argv
);
448 /* modules: module references are only here! */
449 static void start_modules(void)
451 void start_datasock(void);
452 void start_consmgmt(void);