/[dynamips]/upstream/dynamips-0.2.6-RC1/hypervisor.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /upstream/dynamips-0.2.6-RC1/hypervisor.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (hide annotations)
Sat Oct 6 16:03:58 2007 UTC (13 years, 10 months ago) by dpavlin
File MIME type: text/plain
File size: 15709 byte(s)
import dynamips-0.2.6-RC1

1 dpavlin 1 /*
2     * Cisco 7200 (Predator) simulation platform.
3     * Copyright (c) 2006 Christophe Fillot (cf@utc.fr)
4     *
5     * Hypervisor routines.
6     */
7    
8     /* By default, Cygwin supports only 64 FDs with select()! */
9     #ifdef __CYGWIN__
10     #define FD_SETSIZE 1024
11     #endif
12    
13     #include <stdio.h>
14     #include <stdlib.h>
15     #include <unistd.h>
16     #include <string.h>
17     #include <sys/types.h>
18     #include <sys/stat.h>
19     #include <sys/mman.h>
20     #include <signal.h>
21     #include <fcntl.h>
22     #include <errno.h>
23     #include <assert.h>
24     #include <stdarg.h>
25     #include <sys/ioctl.h>
26     #include <sys/types.h>
27     #include <sys/socket.h>
28     #include <arpa/inet.h>
29     #include <pthread.h>
30    
31     #include "utils.h"
32     #include "parser.h"
33     #include "net.h"
34     #include "registry.h"
35     #include "mips64.h"
36     #include "dynamips.h"
37     #include "dev_c7200.h"
38     #include "dev_c3600.h"
39     #include "hypervisor.h"
40     #include "net_io.h"
41     #include "net_io_bridge.h"
42     #include "frame_relay.h"
43     #include "atm.h"
44    
45     #define DEBUG_TOKEN 0
46    
47     /* Hypervisor modules */
48     static hypervisor_module_t *module_list = NULL;
49     static volatile int hypervisor_running = 0;
50    
51     /* Hypervisor connection list */
52     static hypervisor_conn_t *hypervisor_conn_list = NULL;
53    
54     /* Show hypervisor version */
55     static int cmd_version(hypervisor_conn_t *conn,int argc,char *argv[])
56     {
57     hypervisor_send_reply(conn,HSC_INFO_OK,1,"%s",sw_version);
58     return(0);
59     }
60    
61 dpavlin 2 /* Parser test */
62     static int cmd_parser_test(hypervisor_conn_t *conn,int argc,char *argv[])
63     {
64     int i;
65    
66     for(i=0;i<argc;i++)
67     hypervisor_send_reply(conn,HSC_INFO_MSG,0,
68     "arg %d (len %u): \"%s\"",
69     i,strlen(argv[i]),argv[i]);
70    
71     hypervisor_send_reply(conn,HSC_INFO_OK,1,"OK");
72     return(0);
73     }
74    
75 dpavlin 1 /* Show hypervisor module list */
76     static int cmd_mod_list(hypervisor_conn_t *conn,int argc,char *argv[])
77     {
78     hypervisor_module_t *m;
79    
80     for(m=module_list;m;m=m->next)
81     hypervisor_send_reply(conn,HSC_INFO_MSG,0,"%s",m->name);
82    
83     hypervisor_send_reply(conn,HSC_INFO_OK,1,"OK");
84     return(0);
85     }
86    
87     /* Show module command list */
88     static int cmd_modcmd_list(hypervisor_conn_t *conn,int argc,char *argv[])
89     {
90     hypervisor_module_t *m;
91     hypervisor_cmd_t *cmd;
92    
93     if (!(m = hypervisor_find_module(argv[0]))) {
94     hypervisor_send_reply(conn,HSC_ERR_UNK_MODULE,1,"unknown module '%s'",
95     argv[0]);
96     return(-1);
97     }
98    
99     for(cmd=m->cmd_list;cmd;cmd=cmd->next)
100     hypervisor_send_reply(conn,HSC_INFO_MSG,0,"%s (min/max args: %d/%d)",
101     cmd->name,cmd->min_param,cmd->max_param);
102    
103     hypervisor_send_reply(conn,HSC_INFO_OK,1,"OK");
104     return(0);
105     }
106    
107     /* Set working directory */
108     static int cmd_set_working_dir(hypervisor_conn_t *conn,int argc,char *argv[])
109     {
110     if (chdir(argv[0]) == -1) {
111     hypervisor_send_reply(conn,HSC_ERR_INV_PARAM,1,
112     "chdir: %s",strerror(errno));
113     } else {
114     hypervisor_send_reply(conn,HSC_INFO_OK,1,"OK");
115     }
116     return(0);
117     }
118    
119     /* Save the hypervisor configuration in the specified file */
120     static int cmd_save_config(hypervisor_conn_t *conn,int argc,char *argv[])
121     {
122     FILE *fd;
123    
124     if (!(fd = fopen(argv[0],"w"))) {
125     hypervisor_send_reply(conn,HSC_ERR_FILE,1,"fopen: %s",strerror(errno));
126     return(-1);
127     }
128    
129     /* Save configuration for all objects */
130     netio_save_config_all(fd);
131     frsw_save_config_all(fd);
132     atmsw_save_config_all(fd);
133     netio_bridge_save_config_all(fd);
134     c7200_save_config_all(fd);
135     c3600_save_config_all(fd);
136    
137     hypervisor_send_reply(conn,HSC_INFO_OK,1,"OK");
138     return(0);
139     }
140    
141     /* Reset hypervisor (delete all objects) */
142     static int cmd_reset(hypervisor_conn_t *conn,int argc,char *argv[])
143     {
144     dynamips_reset();
145     hypervisor_send_reply(conn,HSC_INFO_OK,1,"OK");
146     return(0);
147     }
148    
149     /* Close connection */
150     static int cmd_close(hypervisor_conn_t *conn,int argc,char *argv[])
151     {
152     hypervisor_send_reply(conn,HSC_INFO_OK,1,"OK");
153     conn->active = FALSE;
154     return(0);
155     }
156    
157     /* Stop hypervisor */
158     static int cmd_stop(hypervisor_conn_t *conn,int argc,char *argv[])
159     {
160     hypervisor_send_reply(conn,HSC_INFO_OK,1,"OK");
161     hypervisor_running = FALSE;
162     return(0);
163     }
164    
165     /* Hypervisor commands */
166     static hypervisor_cmd_t hypervisor_cmd_array[] = {
167     { "version", 0, 0, cmd_version, NULL },
168 dpavlin 2 { "parser_test", 0, 10, cmd_parser_test, NULL },
169 dpavlin 1 { "module_list", 0, 0, cmd_mod_list, NULL },
170     { "cmd_list", 1, 1, cmd_modcmd_list, NULL },
171     { "working_dir", 1, 1, cmd_set_working_dir, NULL },
172     { "save_config", 1, 1, cmd_save_config, NULL },
173     { "reset", 0, 0, cmd_reset, NULL },
174     { "close", 0, 0, cmd_close, NULL },
175     { "stop", 0, 0, cmd_stop, NULL },
176     { NULL, -1, -1, NULL, NULL },
177     };
178    
179     /* Send a reply */
180     int hypervisor_send_reply(hypervisor_conn_t *conn,int code,int done,
181     char *format,...)
182     {
183     va_list ap;
184     size_t n = 0;
185    
186     if (conn != NULL) {
187     va_start(ap,format);
188     n += fprintf(conn->out,"%3d%s",code,(done)?"-":" ");
189     n += vfprintf(conn->out,format,ap);
190     n += fprintf(conn->out,"\r\n");
191     fflush(conn->out);
192     va_end(ap);
193     }
194    
195     return(n);
196     }
197    
198     /* Find a module */
199     hypervisor_module_t *hypervisor_find_module(char *name)
200     {
201     hypervisor_module_t *m;
202    
203     for(m=module_list;m;m=m->next)
204     if (!strcmp(m->name,name))
205     return m;
206    
207     return NULL;
208     }
209    
210     /* Find a command in a module */
211     hypervisor_cmd_t *hypervisor_find_cmd(hypervisor_module_t *module,char *name)
212     {
213     hypervisor_cmd_t *cmd;
214    
215     for(cmd=module->cmd_list;cmd;cmd=cmd->next)
216     if (!strcmp(cmd->name,name))
217     return cmd;
218    
219     return NULL;
220     }
221    
222     /* Find an object in the registry */
223     void *hypervisor_find_object(hypervisor_conn_t *conn,char *name,int obj_type)
224     {
225     void *p;
226    
227     if (!(p = registry_find(name,obj_type))) {
228     hypervisor_send_reply(conn,HSC_ERR_UNK_OBJ,1,
229     "unable to find object '%s'",name);
230     return NULL;
231     }
232    
233     return p;
234     }
235    
236     /* Find a VM in the registry */
237     void *hypervisor_find_vm(hypervisor_conn_t *conn,char *name,int vm_type)
238     {
239     vm_instance_t *vm;
240    
241     if (!(vm = vm_acquire(name))) {
242     hypervisor_send_reply(conn,HSC_ERR_UNK_OBJ,1,
243     "unable to find VM '%s'",name);
244     return NULL;
245     }
246    
247     if (vm->type != vm_type) {
248     vm_release(vm);
249     hypervisor_send_reply(conn,HSC_ERR_BAD_OBJ,1,
250     "VM '%s' is not a VM type %d",
251     name,vm_type);
252     return NULL;
253     }
254    
255     return vm;
256     }
257    
258     /* Register a module */
259     hypervisor_module_t *hypervisor_register_module(char *name)
260     {
261     hypervisor_module_t *m;
262    
263     if (hypervisor_find_module(name) != NULL) {
264     fprintf(stderr,"Hypervisor: module '%s' already exists.\n",name);
265     return NULL;
266     }
267    
268     if (!(m = malloc(sizeof(*m)))) {
269     fprintf(stderr,"Hypervisor: unable to register new module.\n");
270     return NULL;
271     }
272    
273     m->name = name;
274     m->cmd_list = NULL;
275    
276     m->next = module_list;
277     module_list = m;
278     return m;
279     }
280    
281     /* Register a list of commands */
282     int hypervisor_register_cmd_list(hypervisor_module_t *module,
283     hypervisor_cmd_t *cmd_list)
284     {
285     hypervisor_cmd_t *cmd = cmd_list;
286    
287     while(cmd->next != NULL)
288     cmd = cmd->next;
289    
290     cmd->next = module->cmd_list;
291     module->cmd_list = cmd_list;
292     return(0);
293     }
294    
295     /* Register an array of commands */
296     int hypervisor_register_cmd_array(hypervisor_module_t *module,
297     hypervisor_cmd_t *cmd_array)
298     {
299     hypervisor_cmd_t *cmd;
300    
301     for(cmd=cmd_array;cmd->name!=NULL;cmd++) {
302     cmd->next = module->cmd_list;
303     module->cmd_list = cmd;
304     }
305    
306     return(0);
307     }
308    
309     /* Locate the module and execute command */
310     static int hypervisor_exec_cmd(hypervisor_conn_t *conn,
311     char *mod_name,char *cmd_name,
312     int argc,char *argv[])
313     {
314     hypervisor_module_t *module;
315     hypervisor_cmd_t *cmd;
316    
317     if (!(module = hypervisor_find_module(mod_name))) {
318     hypervisor_send_reply(conn,HSC_ERR_UNK_MODULE,1,"Unknown module '%s'",
319     mod_name);
320     return(-1);
321     }
322    
323     if (!(cmd = hypervisor_find_cmd(module,cmd_name))) {
324     hypervisor_send_reply(conn,HSC_ERR_UNK_CMD,1,"Unknown command '%s'",
325     cmd_name);
326     return(-1);
327     }
328    
329     if ((argc < cmd->min_param) || (argc > cmd->max_param)) {
330     hypervisor_send_reply(conn,HSC_ERR_BAD_PARAM,1,
331     "Bad number of parameters (%d with min/max=%d/%d)",
332     argc,cmd->min_param,cmd->max_param);
333     return(-1);
334     }
335    
336     return(cmd->handler(conn,argc,argv));
337     }
338    
339     /* Thread for servicing connections */
340     static void *hypervisor_thread(void *arg)
341     {
342     hypervisor_conn_t *conn = arg;
343 dpavlin 2 char buffer[512],**tokens;
344     parser_context_t ctx;
345     int res;
346 dpavlin 1
347 dpavlin 2 tokens = NULL;
348     parser_context_init(&ctx);
349    
350 dpavlin 1 while(conn->active) {
351 dpavlin 2 if (!fgets(buffer,sizeof(buffer),conn->in))
352 dpavlin 1 break;
353    
354     if (!*buffer)
355     continue;
356    
357     /* Tokenize command line */
358 dpavlin 2 res = parser_scan_buffer(&ctx,buffer,strlen(buffer));
359 dpavlin 1
360 dpavlin 2 if (res != 0) {
361     tokens = NULL;
362 dpavlin 1
363 dpavlin 2 if (ctx.error != 0) {
364     hypervisor_send_reply(conn,HSC_ERR_PARSING,1,"Parse error: %s",
365     parser_strerror(&ctx));
366     goto free_tokens;
367     }
368 dpavlin 1
369 dpavlin 2 if (ctx.tok_count < 2) {
370     hypervisor_send_reply(conn,HSC_ERR_PARSING,1,
371     "At least a module and a command "
372     "must be specified");
373     goto free_tokens;
374     }
375    
376     /* Map token list to an array */
377     tokens = parser_map_array(&ctx);
378 dpavlin 1
379 dpavlin 2 if (!tokens) {
380     hypervisor_send_reply(conn,HSC_ERR_PARSING,1,"No memory");
381     goto free_tokens;
382     }
383 dpavlin 1
384 dpavlin 2 /* Execute command */
385     //m_log("hypervisor_exec","%s\n",buffer);
386     hypervisor_exec_cmd(conn,tokens[0],tokens[1],ctx.
387     tok_count-2,&tokens[2]);
388 dpavlin 1
389 dpavlin 2 free_tokens:
390     free(tokens);
391     tokens = NULL;
392     parser_context_free(&ctx);
393     }
394 dpavlin 1 }
395    
396 dpavlin 2 free(tokens);
397     parser_context_free(&ctx);
398 dpavlin 1 return NULL;
399     }
400    
401     static void sigpipe_handler(int sig)
402     {
403     printf("SIGPIPE received.\n");
404     }
405    
406     /* Initialize hypervisor */
407     int hypervisor_init(void)
408     {
409     hypervisor_module_t *module;
410    
411     module = hypervisor_register_module("hypervisor");
412     assert(module != NULL);
413    
414     hypervisor_register_cmd_array(module,hypervisor_cmd_array);
415     return(0);
416     }
417    
418     /* Remove a connection from the list */
419     static void hypervisor_remove_conn(hypervisor_conn_t *conn)
420     {
421     if (conn->pprev != NULL) {
422     if (conn->next)
423     conn->next->pprev = conn->pprev;
424    
425     *(conn->pprev) = conn->next;
426     }
427     }
428    
429     /* Close a connection */
430     static void hypervisor_close_conn(hypervisor_conn_t *conn)
431     {
432     if (conn != NULL) {
433     conn->active = FALSE;
434     shutdown(conn->client_fd,2);
435     pthread_join(conn->tid,NULL);
436    
437     fclose(conn->in);
438     fclose(conn->out);
439    
440     shutdown(conn->client_fd,2);
441     close(conn->client_fd);
442    
443     hypervisor_remove_conn(conn);
444     free(conn);
445     }
446     }
447    
448     /* Close connections (dead or all) */
449     static void hypervisor_close_conn_list(int dead_status)
450     {
451     hypervisor_conn_t *conn,*next;
452    
453     for(conn=hypervisor_conn_list;conn;conn=next) {
454     next = conn->next;
455    
456     if (dead_status && conn->active)
457     continue;
458    
459     hypervisor_close_conn(conn);
460     }
461     }
462    
463     /* Add a new connection to the list */
464     static void hypervisor_add_conn(hypervisor_conn_t *conn)
465     {
466     conn->next = hypervisor_conn_list;
467     conn->pprev = &hypervisor_conn_list;
468    
469     if (hypervisor_conn_list != NULL)
470     hypervisor_conn_list->pprev = &conn->next;
471    
472     hypervisor_conn_list = conn;
473     }
474    
475     /* Create a new connection */
476     static hypervisor_conn_t *hypervisor_create_conn(int client_fd)
477     {
478     hypervisor_conn_t *conn;
479    
480     if (!(conn = malloc(sizeof(*conn))))
481     goto err_malloc;
482    
483     memset(conn,0,sizeof(*conn));
484     conn->active = TRUE;
485     conn->client_fd = client_fd;
486    
487     /* Open input buffered stream */
488     if (!(conn->in = fdopen(client_fd,"r"))) {
489     perror("hypervisor_create_conn: fdopen/in");
490     goto err_fd_in;
491     }
492    
493     /* Open output buffered stream */
494     if (!(conn->out = fdopen(client_fd,"w"))) {
495     perror("hypervisor_create_conn: fdopen/out");
496     goto err_fd_out;
497     }
498    
499     /* Set line buffering */
500     setlinebuf(conn->in);
501     setlinebuf(conn->out);
502    
503     /* Create the managing thread */
504     if (pthread_create(&conn->tid,NULL,hypervisor_thread,conn) != 0)
505     goto err_thread;
506    
507     /* Add it to the connection list */
508     hypervisor_add_conn(conn);
509     return conn;
510    
511     err_thread:
512     fclose(conn->out);
513     err_fd_out:
514     fclose(conn->in);
515     err_fd_in:
516     free(conn);
517     err_malloc:
518     return NULL;
519     }
520    
521     /* Stop hypervisor from sighandler */
522     int hypervisor_stopsig(void)
523     {
524     hypervisor_running = FALSE;
525     return(0);
526     }
527    
528     /* Hypervisor TCP server */
529     int hypervisor_tcp_server(int tcp_port)
530     {
531     int fd_array[HYPERVISOR_MAX_FD];
532     struct sockaddr_storage remote_addr;
533     socklen_t remote_len;
534     int i,res,clnt,fd_count,fd_max;
535     struct timeval tv;
536     fd_set fds;
537    
538     /* Initialize all hypervisor modules */
539     hypervisor_init();
540     hypervisor_nio_init();
541     hypervisor_nio_bridge_init();
542     hypervisor_frsw_init();
543     hypervisor_atmsw_init();
544     hypervisor_ethsw_init();
545     hypervisor_vm_init();
546 dpavlin 2 hypervisor_vm_debug_init();
547 dpavlin 1 hypervisor_c7200_init();
548     hypervisor_c3600_init();
549    
550     signal(SIGPIPE,sigpipe_handler);
551    
552     if (!tcp_port)
553     tcp_port = HYPERVISOR_TCP_PORT;
554    
555     fd_count = ip_listen(tcp_port,SOCK_STREAM,HYPERVISOR_MAX_FD,fd_array);
556    
557     if (fd_count <= 0) {
558     fprintf(stderr,"Hypervisor: unable to create TCP sockets.\n");
559     return(-1);
560     }
561    
562     /* Start accepting connections */
563     printf("Hypervisor TCP control server started.\n");
564     hypervisor_running = TRUE;
565    
566     while(hypervisor_running) {
567     FD_ZERO(&fds);
568     fd_max = -1;
569    
570     for(i=0;i<fd_count;i++)
571     if (fd_array[i] != -1) {
572     FD_SET(fd_array[i],&fds);
573     if (fd_array[i] > fd_max)
574     fd_max = fd_array[i];
575     }
576    
577     /* Wait for incoming connections */
578     tv.tv_sec = 0;
579     tv.tv_usec = 500 * 1000; /* 500 ms */
580     res = select(fd_max+1,&fds,NULL,NULL,&tv);
581    
582     if (res == -1) {
583     if (errno == EINTR)
584     continue;
585     else
586     perror("hypervisor_tcp_server: select");
587     }
588    
589     /* Accept connections on signaled sockets */
590     for(i=0;i<fd_count;i++) {
591     if (fd_array[i] == -1)
592     continue;
593    
594     if (!FD_ISSET(fd_array[i],&fds))
595     continue;
596    
597     remote_len = sizeof(remote_addr);
598     clnt = accept(fd_array[i],(struct sockaddr *)&remote_addr,
599     &remote_len);
600    
601     if (clnt < 0) {
602     perror("hypervisor_tcp_server: accept");
603     continue;
604     }
605    
606     /* create a new connection and start a thread to handle it */
607     if (!hypervisor_create_conn(clnt)) {
608     fprintf(stderr,"hypervisor_tcp_server: unable to create new "
609     "connection for FD %d\n",clnt);
610     close(clnt);
611     }
612     }
613    
614     /* Walk through the connection list to eliminate dead connections */
615     hypervisor_close_conn_list(TRUE);
616     }
617    
618     /* Close all control sockets */
619     printf("Hypervisor: closing control sockets.\n");
620     for(i=0;i<fd_count;i++) {
621     if (fd_array[i] != -1) {
622     shutdown(fd_array[i],2);
623     close(fd_array[i]);
624     }
625     }
626    
627     /* Close all remote client connections */
628     printf("Hypervisor: closing remote client connections.\n");
629     hypervisor_close_conn_list(FALSE);
630     return(0);
631     }

  ViewVC Help
Powered by ViewVC 1.1.26