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 "compat/poll.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
,int arg
)
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
]->arg
=arg
;
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
]->arg
);
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
]->arg
);
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()
202 n
=poll(fds
,nfds
,packetq_timeout
);
209 printlog(LOG_WARNING
,"poll %s",strerror(errno
));
211 for(i
= 0; /*i < nfds &&*/ n
>0; i
++){
212 if(fds
[i
].revents
!= 0) {
213 register int prenfds
=nfds
;
215 fdpp
[i
]->timestamp
=now
;
216 TYPE2MGR(fdpp
[i
]->type
)->handle_input(fdpp
[i
]->type
,fds
[i
].fd
,fds
[i
].revents
,&(fdpp
[i
]->arg
));
217 if (nfds
!=prenfds
) /* the current fd has been deleted */
218 break; /* PERFORMANCE it is faster returning to poll */
220 /* optimization: most used descriptors migrate to the head of the poll array */
224 if (i
< nfds
&& i
> 0 && i
!= nprio
) {
225 register int i_1
=i
-1;
226 if (fdpp
[i
]->timestamp
> fdpp
[i_1
]->timestamp
) {
228 struct pollplus
*tfdpp
;
229 tfds
=fds
[i
];fds
[i
]=fds
[i_1
];fds
[i_1
]=tfds
;
230 tfdpp
=fdpp
[i
];fdpp
[i
]=fdpp
[i_1
];fdpp
[i_1
]=tfdpp
;
237 if (packetq_timeout
> 0)
244 /* starting/ending routines, main_loop, main*/
245 #define HASH_TABLE_SIZE_ARG 0x100
246 #define MACADDR_ARG 0x101
247 #define PRIORITY_ARG 0x102
249 static void Usage(void) {
252 "Usage: vde_switch [OPTIONS]\n"
253 "Runs a VDE switch.\n"
255 " -h, --help Display this help and exit\n"
256 " -v, --version Display informations on version and exit\n"
258 for(p
=swmh
;p
!= NULL
;p
=p
->next
)
259 if (p
->usage
!= NULL
)
263 "Report bugs to "PACKAGE_BUGREPORT
"\n"
268 static void version(void)
271 "VDE " PACKAGE_VERSION
"\n"
272 "Copyright 2003,2004,2005,2006,2007,2008 Renzo Davoli\n"
273 "VDE comes with NO WARRANTY, to the extent permitted by law.\n"
274 "You may redistribute copies of VDE under the terms of the\n"
275 "GNU General Public License v2.\n"
276 "For more information about these matters, see the files\n"
281 static struct option
*optcpy(struct option
*tgt
, struct option
*src
, int n
, int tag
)
284 memcpy(tgt
,src
,sizeof(struct option
) * n
);
286 tgt
[i
].val
=(tgt
[i
].val
& 0xffff) | tag
<< 16;
291 static int parse_globopt(int c
, char *optarg
)
307 static void parse_args(int argc
, char **argv
)
309 struct swmodule
*swmp
;
310 struct option
*long_options
;
312 static struct option global_options
[] = {
314 {"version", 0, 0, 'v'},
316 static struct option optail
= {0,0,0,0};
317 #define N_global_options (sizeof(global_options)/sizeof(struct option))
319 int totopts
=N_global_options
+1;
321 for(swmp
=swmh
;swmp
!= NULL
;swmp
=swmp
->next
)
322 totopts
+= swmp
->swmnopts
;
323 long_options
=malloc(totopts
* sizeof(struct option
));
324 optstring
=malloc(2 * totopts
* sizeof(char));
325 if (long_options
== NULL
|| optstring
==NULL
)
327 { /* fill-in the long_options fields */
331 struct option
*opp
=long_options
;
332 opp
=optcpy(opp
,global_options
,N_global_options
,0);
333 for(swmp
=swmh
;swmp
!= NULL
;swmp
=swmp
->next
)
334 opp
=optcpy(opp
,swmp
->swmopts
,swmp
->swmnopts
,swmp
->swmtag
);
335 optcpy(opp
,&optail
,1,0);
336 for (i
=0;i
<totopts
-1;i
++)
338 int val
=long_options
[i
].val
& 0xffff;
339 if(val
> ' ' && val
<= '~' && val
!= last
)
342 if(long_options
[i
].has_arg
) *os
++=':';
349 int option_index
= 0;
352 c
= GETOPT_LONG (argc
, argv
, optstring
,
353 long_options
, &option_index
);
356 c
=parse_globopt(c
,optarg
);
357 for(swmp
=swmh
;swmp
!= NULL
&& c
!=0;swmp
=swmp
->next
) {
358 if (swmp
->parseopt
!= NULL
) {
360 c
=swmp
->parseopt(c
,optarg
);
361 else if ((c
>> 16) == swmp
->swmtag
)
362 swmp
->parseopt(c
& 0xffff,optarg
),c
=0;
373 static void init_mods(void)
375 struct swmodule
*swmp
;
376 for(swmp
=swmh
;swmp
!= NULL
;swmp
=swmp
->next
)
377 if (swmp
->init
!= NULL
)
381 static void cleanup(void)
383 struct swmodule
*swmp
;
385 for(swmp
=swmh
;swmp
!= NULL
;swmp
=swmp
->next
)
386 if (swmp
->cleanup
!= NULL
)
387 swmp
->cleanup(0,-1,-1);
390 static void sig_handler(int sig
)
392 printlog(LOG_ERR
,"Caught signal %d, cleaning up and exiting", sig
);
394 signal(sig
, SIG_DFL
);
398 static void setsighandlers()
400 /* setting signal handlers.
401 * sets clean termination for SIGHUP, SIGINT and SIGTERM, and simply
402 * ignores all the others signals which could cause termination. */
403 struct { int sig
; const char *name
; int ignore
; } signals
[] = {
404 { SIGHUP
, "SIGHUP", 0 },
405 { SIGINT
, "SIGINT", 0 },
406 { SIGPIPE
, "SIGPIPE", 1 },
407 { SIGALRM
, "SIGALRM", 1 },
408 { SIGTERM
, "SIGTERM", 0 },
409 { SIGUSR1
, "SIGUSR1", 1 },
410 { SIGUSR2
, "SIGUSR2", 1 },
411 { SIGPROF
, "SIGPROF", 1 },
412 { SIGVTALRM
, "SIGVTALRM", 1 },
414 { SIGPOLL
, "SIGPOLL", 1 },
416 { SIGSTKFLT
, "SIGSTKFLT", 1 },
418 { SIGIO
, "SIGIO", 1 },
419 { SIGPWR
, "SIGPWR", 1 },
421 { SIGUNUSED
, "SIGUNUSED", 1 },
425 { SIGXCPU
, "SIGXCPU", 1 },
426 { SIGXFSZ
, "SIGXFSZ", 1 },
432 for(i
= 0; signals
[i
].sig
!= 0; i
++)
433 if(signal(signals
[i
].sig
,
434 signals
[i
].ignore
? SIG_IGN
: sig_handler
) < 0)
435 printlog(LOG_ERR
,"Setting handler for %s: %s", signals
[i
].name
,
439 static void start_modules(void);
441 int main(int argc
, char **argv
)
443 starting_time
=time(NULL
);
445 parse_args(argc
,argv
);
454 /* modules: module references are only here! */
455 static void start_modules(void)
457 void start_datasock(void);
458 void start_consmgmt(void);